From 32f01b2064034f9f9c2dc554fbdc58ea2f6a71d6 Mon Sep 17 00:00:00 2001 From: binarycat Date: Sat, 14 Sep 2024 12:02:37 -0400 Subject: [PATCH 001/357] don't warn about a missing change-id in CI fixes 130352 --- src/bootstrap/src/bin/main.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/bootstrap/src/bin/main.rs b/src/bootstrap/src/bin/main.rs index f03f03e2d93..ac1ff954fed 100644 --- a/src/bootstrap/src/bin/main.rs +++ b/src/bootstrap/src/bin/main.rs @@ -14,6 +14,7 @@ use bootstrap::{ find_recent_config_change_ids, human_readable_changes, t, Build, Config, Flags, Subcommand, CONFIG_CHANGE_HISTORY, }; +use build_helper::ci::CiEnv; fn main() { let args = env::args().skip(1).collect::>(); @@ -54,9 +55,12 @@ fn main() { }; } - // check_version warnings are not printed during setup - let changelog_suggestion = - if matches!(config.cmd, Subcommand::Setup { .. }) { None } else { check_version(&config) }; + // check_version warnings are not printed during setup, or during CI + let changelog_suggestion = if matches!(config.cmd, Subcommand::Setup { .. }) || CiEnv::is_ci() { + None + } else { + check_version(&config) + }; // NOTE: Since `./configure` generates a `config.toml`, distro maintainers will see the // changelog warning, not the `x.py setup` message. From 0d4259e68e5211b99dea028c1b9071362e7f3b6f Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Sun, 16 Jun 2024 20:03:17 +0300 Subject: [PATCH 002/357] Add `#[track_caller]` to allocating methods of `Vec` & `VecDeque` --- .../alloc/src/collections/vec_deque/mod.rs | 24 ++++++++++++ .../src/collections/vec_deque/spec_extend.rs | 6 +++ .../collections/vec_deque/spec_from_iter.rs | 1 + library/alloc/src/raw_vec.rs | 17 +++++++++ library/alloc/src/vec/cow.rs | 1 + library/alloc/src/vec/in_place_collect.rs | 2 + library/alloc/src/vec/mod.rs | 38 +++++++++++++++++++ library/alloc/src/vec/spec_extend.rs | 6 +++ library/alloc/src/vec/spec_from_elem.rs | 4 ++ library/alloc/src/vec/spec_from_iter.rs | 2 + .../alloc/src/vec/spec_from_iter_nested.rs | 2 + library/alloc/src/vec/splice.rs | 2 + 12 files changed, 105 insertions(+) diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index a438517b75b..5d597173a6a 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -103,6 +103,7 @@ pub struct VecDeque< #[stable(feature = "rust1", since = "1.0.0")] impl Clone for VecDeque { + #[track_caller] fn clone(&self) -> Self { let mut deq = Self::with_capacity_in(self.len(), self.allocator().clone()); deq.extend(self.iter().cloned()); @@ -113,6 +114,7 @@ impl Clone for VecDeque { /// /// This method is preferred over simply assigning `source.clone()` to `self`, /// as it avoids reallocation if possible. + #[track_caller] fn clone_from(&mut self, source: &Self) { self.clear(); self.extend(source.iter().cloned()); @@ -570,6 +572,7 @@ impl VecDeque { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[must_use] + #[track_caller] pub fn with_capacity(capacity: usize) -> VecDeque { Self::with_capacity_in(capacity, Global) } @@ -625,6 +628,7 @@ impl VecDeque { /// let deque: VecDeque = VecDeque::with_capacity(10); /// ``` #[unstable(feature = "allocator_api", issue = "32838")] + #[track_caller] pub fn with_capacity_in(capacity: usize, alloc: A) -> VecDeque { VecDeque { head: 0, len: 0, buf: RawVec::with_capacity_in(capacity, alloc) } } @@ -789,6 +793,7 @@ impl VecDeque { /// /// [`reserve`]: VecDeque::reserve #[stable(feature = "rust1", since = "1.0.0")] + #[track_caller] pub fn reserve_exact(&mut self, additional: usize) { let new_cap = self.len.checked_add(additional).expect("capacity overflow"); let old_cap = self.capacity(); @@ -818,6 +823,7 @@ impl VecDeque { /// assert!(buf.capacity() >= 11); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[track_caller] pub fn reserve(&mut self, additional: usize) { let new_cap = self.len.checked_add(additional).expect("capacity overflow"); let old_cap = self.capacity(); @@ -949,6 +955,7 @@ impl VecDeque { /// assert!(buf.capacity() >= 4); /// ``` #[stable(feature = "deque_extras_15", since = "1.5.0")] + #[track_caller] pub fn shrink_to_fit(&mut self) { self.shrink_to(0); } @@ -974,6 +981,7 @@ impl VecDeque { /// assert!(buf.capacity() >= 4); /// ``` #[stable(feature = "shrink_to", since = "1.56.0")] + #[track_caller] pub fn shrink_to(&mut self, min_capacity: usize) { let target_cap = min_capacity.max(self.len); @@ -1740,6 +1748,7 @@ impl VecDeque { /// assert_eq!(d.front(), Some(&2)); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[track_caller] pub fn push_front(&mut self, value: T) { if self.is_full() { self.grow(); @@ -1767,6 +1776,7 @@ impl VecDeque { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_confusables("push", "put", "append")] + #[track_caller] pub fn push_back(&mut self, value: T) { if self.is_full() { self.grow(); @@ -1876,6 +1886,7 @@ impl VecDeque { /// assert_eq!(vec_deque, &['a', 'd', 'b', 'c']); /// ``` #[stable(feature = "deque_extras_15", since = "1.5.0")] + #[track_caller] pub fn insert(&mut self, index: usize, value: T) { assert!(index <= self.len(), "index out of bounds"); if self.is_full() { @@ -1979,6 +1990,7 @@ impl VecDeque { #[inline] #[must_use = "use `.truncate()` if you don't need the other half"] #[stable(feature = "split_off", since = "1.4.0")] + #[track_caller] pub fn split_off(&mut self, at: usize) -> Self where A: Clone, @@ -2045,6 +2057,7 @@ impl VecDeque { /// ``` #[inline] #[stable(feature = "append", since = "1.4.0")] + #[track_caller] pub fn append(&mut self, other: &mut Self) { if T::IS_ZST { self.len = self.len.checked_add(other.len).expect("capacity overflow"); @@ -2167,6 +2180,7 @@ impl VecDeque { // be called in cold paths. // This may panic or abort #[inline(never)] + #[track_caller] fn grow(&mut self) { // Extend or possibly remove this assertion when valid use-cases for growing the // buffer without it being full emerge @@ -2205,6 +2219,7 @@ impl VecDeque { /// assert_eq!(buf, [5, 10, 101, 102, 103]); /// ``` #[stable(feature = "vec_resize_with", since = "1.33.0")] + #[track_caller] pub fn resize_with(&mut self, new_len: usize, generator: impl FnMut() -> T) { let len = self.len; @@ -2751,6 +2766,7 @@ impl VecDeque { /// assert_eq!(buf, [5, 10, 20, 20, 20]); /// ``` #[stable(feature = "deque_extras", since = "1.16.0")] + #[track_caller] pub fn resize(&mut self, new_len: usize, value: T) { if new_len > self.len() { let extra = new_len - self.len(); @@ -2870,6 +2886,7 @@ impl IndexMut for VecDeque { #[stable(feature = "rust1", since = "1.0.0")] impl FromIterator for VecDeque { + #[track_caller] fn from_iter>(iter: I) -> VecDeque { SpecFromIter::spec_from_iter(iter.into_iter()) } @@ -2909,16 +2926,19 @@ impl<'a, T, A: Allocator> IntoIterator for &'a mut VecDeque { #[stable(feature = "rust1", since = "1.0.0")] impl Extend for VecDeque { + #[track_caller] fn extend>(&mut self, iter: I) { >::spec_extend(self, iter.into_iter()); } #[inline] + #[track_caller] fn extend_one(&mut self, elem: T) { self.push_back(elem); } #[inline] + #[track_caller] fn extend_reserve(&mut self, additional: usize) { self.reserve(additional); } @@ -2934,16 +2954,19 @@ impl Extend for VecDeque { #[stable(feature = "extend_ref", since = "1.2.0")] impl<'a, T: 'a + Copy, A: Allocator> Extend<&'a T> for VecDeque { + #[track_caller] fn extend>(&mut self, iter: I) { self.spec_extend(iter.into_iter()); } #[inline] + #[track_caller] fn extend_one(&mut self, &elem: &'a T) { self.push_back(elem); } #[inline] + #[track_caller] fn extend_reserve(&mut self, additional: usize) { self.reserve(additional); } @@ -3041,6 +3064,7 @@ impl From<[T; N]> for VecDeque { /// let deq2: VecDeque<_> = [1, 2, 3, 4].into(); /// assert_eq!(deq1, deq2); /// ``` + #[track_caller] fn from(arr: [T; N]) -> Self { let mut deq = VecDeque::with_capacity(N); let arr = ManuallyDrop::new(arr); diff --git a/library/alloc/src/collections/vec_deque/spec_extend.rs b/library/alloc/src/collections/vec_deque/spec_extend.rs index a9b0fd073b5..d246385ca84 100644 --- a/library/alloc/src/collections/vec_deque/spec_extend.rs +++ b/library/alloc/src/collections/vec_deque/spec_extend.rs @@ -7,6 +7,7 @@ use crate::vec; // Specialization trait used for VecDeque::extend pub(super) trait SpecExtend { + #[track_caller] fn spec_extend(&mut self, iter: I); } @@ -14,6 +15,7 @@ impl SpecExtend for VecDeque where I: Iterator, { + #[track_caller] default fn spec_extend(&mut self, mut iter: I) { // This function should be the moral equivalent of: // @@ -44,6 +46,7 @@ impl SpecExtend for VecDeque where I: TrustedLen, { + #[track_caller] default fn spec_extend(&mut self, iter: I) { // This is the case for a TrustedLen iterator. let (low, high) = iter.size_hint(); @@ -76,6 +79,7 @@ where } impl SpecExtend> for VecDeque { + #[track_caller] fn spec_extend(&mut self, mut iterator: vec::IntoIter) { let slice = iterator.as_slice(); self.reserve(slice.len()); @@ -93,6 +97,7 @@ where I: Iterator, T: Copy, { + #[track_caller] default fn spec_extend(&mut self, iterator: I) { self.spec_extend(iterator.copied()) } @@ -102,6 +107,7 @@ impl<'a, T: 'a, A: Allocator> SpecExtend<&'a T, slice::Iter<'a, T>> for VecDeque where T: Copy, { + #[track_caller] fn spec_extend(&mut self, iterator: slice::Iter<'a, T>) { let slice = iterator.as_slice(); self.reserve(slice.len()); diff --git a/library/alloc/src/collections/vec_deque/spec_from_iter.rs b/library/alloc/src/collections/vec_deque/spec_from_iter.rs index 2708c7fe102..1efe84d6d7d 100644 --- a/library/alloc/src/collections/vec_deque/spec_from_iter.rs +++ b/library/alloc/src/collections/vec_deque/spec_from_iter.rs @@ -9,6 +9,7 @@ impl SpecFromIter for VecDeque where I: Iterator, { + #[track_caller] default fn spec_from_iter(iterator: I) -> Self { // Since converting is O(1) now, just re-use the `Vec` logic for // anything where we can't do something extra-special for `VecDeque`, diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs index 436e0596e3d..cb2d84bec1c 100644 --- a/library/alloc/src/raw_vec.rs +++ b/library/alloc/src/raw_vec.rs @@ -20,6 +20,7 @@ mod tests; // only one location which panics rather than a bunch throughout the module. #[cfg(not(no_global_oom_handling))] #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] +#[track_caller] fn capacity_overflow() -> ! { panic!("capacity overflow"); } @@ -125,6 +126,7 @@ impl RawVec { #[cfg(not(any(no_global_oom_handling, test)))] #[must_use] #[inline] + #[track_caller] pub fn with_capacity(capacity: usize) -> Self { Self { inner: RawVecInner::with_capacity(capacity, T::LAYOUT), _marker: PhantomData } } @@ -133,6 +135,7 @@ impl RawVec { #[cfg(not(any(no_global_oom_handling, test)))] #[must_use] #[inline] + #[track_caller] pub fn with_capacity_zeroed(capacity: usize) -> Self { Self { inner: RawVecInner::with_capacity_zeroed_in(capacity, Global, T::LAYOUT), @@ -145,6 +148,7 @@ impl RawVecInner { #[cfg(not(any(no_global_oom_handling, test)))] #[must_use] #[inline] + #[track_caller] fn with_capacity(capacity: usize, elem_layout: Layout) -> Self { match Self::try_allocate_in(capacity, AllocInit::Uninitialized, Global, elem_layout) { Ok(res) => res, @@ -184,6 +188,7 @@ impl RawVec { /// allocator for the returned `RawVec`. #[cfg(not(no_global_oom_handling))] #[inline] + #[track_caller] pub fn with_capacity_in(capacity: usize, alloc: A) -> Self { Self { inner: RawVecInner::with_capacity_in(capacity, alloc, T::LAYOUT), @@ -205,6 +210,7 @@ impl RawVec { /// of allocator for the returned `RawVec`. #[cfg(not(no_global_oom_handling))] #[inline] + #[track_caller] pub fn with_capacity_zeroed_in(capacity: usize, alloc: A) -> Self { Self { inner: RawVecInner::with_capacity_zeroed_in(capacity, alloc, T::LAYOUT), @@ -324,6 +330,7 @@ impl RawVec { /// Aborts on OOM. #[cfg(not(no_global_oom_handling))] #[inline] + #[track_caller] pub fn reserve(&mut self, len: usize, additional: usize) { self.inner.reserve(len, additional, T::LAYOUT) } @@ -332,6 +339,7 @@ impl RawVec { /// caller to ensure `len == self.capacity()`. #[cfg(not(no_global_oom_handling))] #[inline(never)] + #[track_caller] pub fn grow_one(&mut self) { self.inner.grow_one(T::LAYOUT) } @@ -359,6 +367,7 @@ impl RawVec { /// /// Aborts on OOM. #[cfg(not(no_global_oom_handling))] + #[track_caller] pub fn reserve_exact(&mut self, len: usize, additional: usize) { self.inner.reserve_exact(len, additional, T::LAYOUT) } @@ -383,6 +392,7 @@ impl RawVec { /// /// Aborts on OOM. #[cfg(not(no_global_oom_handling))] + #[track_caller] #[inline] pub fn shrink_to_fit(&mut self, cap: usize) { self.inner.shrink_to_fit(cap, T::LAYOUT) @@ -408,6 +418,7 @@ impl RawVecInner { #[cfg(not(no_global_oom_handling))] #[inline] + #[track_caller] fn with_capacity_in(capacity: usize, alloc: A, elem_layout: Layout) -> Self { match Self::try_allocate_in(capacity, AllocInit::Uninitialized, alloc, elem_layout) { Ok(this) => { @@ -432,6 +443,7 @@ impl RawVecInner { #[cfg(not(no_global_oom_handling))] #[inline] + #[track_caller] fn with_capacity_zeroed_in(capacity: usize, alloc: A, elem_layout: Layout) -> Self { match Self::try_allocate_in(capacity, AllocInit::Zeroed, alloc, elem_layout) { Ok(res) => res, @@ -526,6 +538,7 @@ impl RawVecInner { #[cfg(not(no_global_oom_handling))] #[inline] + #[track_caller] fn reserve(&mut self, len: usize, additional: usize, elem_layout: Layout) { // Callers expect this function to be very cheap when there is already sufficient capacity. // Therefore, we move all the resizing and error-handling logic from grow_amortized and @@ -550,6 +563,7 @@ impl RawVecInner { #[cfg(not(no_global_oom_handling))] #[inline] + #[track_caller] fn grow_one(&mut self, elem_layout: Layout) { if let Err(err) = self.grow_amortized(self.cap.0, 1, elem_layout) { handle_error(err); @@ -573,6 +587,7 @@ impl RawVecInner { } #[cfg(not(no_global_oom_handling))] + #[track_caller] fn reserve_exact(&mut self, len: usize, additional: usize, elem_layout: Layout) { if let Err(err) = self.try_reserve_exact(len, additional, elem_layout) { handle_error(err); @@ -597,6 +612,7 @@ impl RawVecInner { #[cfg(not(no_global_oom_handling))] #[inline] + #[track_caller] fn shrink_to_fit(&mut self, cap: usize, elem_layout: Layout) { if let Err(err) = self.shrink(cap, elem_layout) { handle_error(err); @@ -770,6 +786,7 @@ where #[cfg(not(no_global_oom_handling))] #[cold] #[optimize(size)] +#[track_caller] fn handle_error(e: TryReserveError) -> ! { match e.kind() { CapacityOverflow => capacity_overflow(), diff --git a/library/alloc/src/vec/cow.rs b/library/alloc/src/vec/cow.rs index c18091705a6..4deb35efffc 100644 --- a/library/alloc/src/vec/cow.rs +++ b/library/alloc/src/vec/cow.rs @@ -58,6 +58,7 @@ impl<'a, T> FromIterator for Cow<'a, [T]> where T: Clone, { + #[track_caller] fn from_iter>(it: I) -> Cow<'a, [T]> { Cow::Owned(FromIterator::from_iter(it)) } diff --git a/library/alloc/src/vec/in_place_collect.rs b/library/alloc/src/vec/in_place_collect.rs index 23dbc3b63f9..1897364af59 100644 --- a/library/alloc/src/vec/in_place_collect.rs +++ b/library/alloc/src/vec/in_place_collect.rs @@ -229,6 +229,7 @@ where I: Iterator + InPlaceCollect, ::Source: AsVecIntoIter, { + #[track_caller] default fn from_iter(iterator: I) -> Self { // Select the implementation in const eval to avoid codegen of the dead branch to improve compile times. let fun: fn(I) -> Vec = const { @@ -246,6 +247,7 @@ where } } +#[track_caller] fn from_iter_in_place(mut iterator: I) -> Vec where I: Iterator + InPlaceCollect, diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 13b06584223..1f418a94f32 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -478,6 +478,7 @@ impl Vec { #[stable(feature = "rust1", since = "1.0.0")] #[must_use] #[cfg_attr(not(test), rustc_diagnostic_item = "vec_with_capacity")] + #[track_caller] pub fn with_capacity(capacity: usize) -> Self { Self::with_capacity_in(capacity, Global) } @@ -797,6 +798,7 @@ impl Vec { #[cfg(not(no_global_oom_handling))] #[inline] #[unstable(feature = "allocator_api", issue = "32838")] + #[track_caller] pub fn with_capacity_in(capacity: usize, alloc: A) -> Self { Vec { buf: RawVec::with_capacity_in(capacity, alloc), len: 0 } } @@ -1263,6 +1265,7 @@ impl Vec { /// ``` #[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] + #[track_caller] pub fn reserve(&mut self, additional: usize) { self.buf.reserve(self.len, additional); } @@ -1293,6 +1296,7 @@ impl Vec { /// ``` #[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] + #[track_caller] pub fn reserve_exact(&mut self, additional: usize) { self.buf.reserve_exact(self.len, additional); } @@ -1396,6 +1400,7 @@ impl Vec { /// ``` #[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] + #[track_caller] #[inline] pub fn shrink_to_fit(&mut self) { // The capacity is never less than the length, and there's nothing to do when @@ -1426,6 +1431,7 @@ impl Vec { /// ``` #[cfg(not(no_global_oom_handling))] #[stable(feature = "shrink_to", since = "1.56.0")] + #[track_caller] pub fn shrink_to(&mut self, min_capacity: usize) { if self.capacity() > min_capacity { self.buf.shrink_to_fit(cmp::max(self.len, min_capacity)); @@ -1459,6 +1465,7 @@ impl Vec { /// ``` #[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] + #[track_caller] pub fn into_boxed_slice(mut self) -> Box<[T], A> { unsafe { self.shrink_to_fit(); @@ -1860,6 +1867,7 @@ impl Vec { /// the insertion index is 0. #[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] + #[track_caller] pub fn insert(&mut self, index: usize, element: T) { #[cold] #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] @@ -2299,6 +2307,7 @@ impl Vec { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_confusables("push_back", "put", "append")] + #[track_caller] pub fn push(&mut self, value: T) { // Inform codegen that the length does not change across grow_one(). let len = self.len; @@ -2440,6 +2449,7 @@ impl Vec { #[cfg(not(no_global_oom_handling))] #[inline] #[stable(feature = "append", since = "1.4.0")] + #[track_caller] pub fn append(&mut self, other: &mut Self) { unsafe { self.append_elements(other.as_slice() as _); @@ -2450,6 +2460,7 @@ impl Vec { /// Appends elements to `self` from other buffer. #[cfg(not(no_global_oom_handling))] #[inline] + #[track_caller] unsafe fn append_elements(&mut self, other: *const [T]) { let count = unsafe { (*other).len() }; self.reserve(count); @@ -2611,6 +2622,7 @@ impl Vec { #[inline] #[must_use = "use `.truncate()` if you don't need the other half"] #[stable(feature = "split_off", since = "1.4.0")] + #[track_caller] pub fn split_off(&mut self, at: usize) -> Self where A: Clone, @@ -2668,6 +2680,7 @@ impl Vec { /// ``` #[cfg(not(no_global_oom_handling))] #[stable(feature = "vec_resize_with", since = "1.33.0")] + #[track_caller] pub fn resize_with(&mut self, new_len: usize, f: F) where F: FnMut() -> T, @@ -2873,6 +2886,7 @@ impl Vec { /// ``` #[cfg(not(no_global_oom_handling))] #[stable(feature = "vec_resize", since = "1.5.0")] + #[track_caller] pub fn resize(&mut self, new_len: usize, value: T) { let len = self.len(); @@ -2904,6 +2918,7 @@ impl Vec { /// [`extend`]: Vec::extend #[cfg(not(no_global_oom_handling))] #[stable(feature = "vec_extend_from_slice", since = "1.6.0")] + #[track_caller] pub fn extend_from_slice(&mut self, other: &[T]) { self.spec_extend(other.iter()) } @@ -2931,6 +2946,7 @@ impl Vec { /// ``` #[cfg(not(no_global_oom_handling))] #[stable(feature = "vec_extend_from_within", since = "1.53.0")] + #[track_caller] pub fn extend_from_within(&mut self, src: R) where R: RangeBounds, @@ -2991,6 +3007,7 @@ impl Vec<[T; N], A> { impl Vec { #[cfg(not(no_global_oom_handling))] + #[track_caller] /// Extend the vector by `n` clones of value. fn extend_with(&mut self, n: usize, value: T) { self.reserve(n); @@ -3051,6 +3068,7 @@ impl Vec { #[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "vec_from_elem")] +#[track_caller] pub fn from_elem(elem: T, n: usize) -> Vec { ::from_elem(elem, n, Global) } @@ -3058,6 +3076,7 @@ pub fn from_elem(elem: T, n: usize) -> Vec { #[doc(hidden)] #[cfg(not(no_global_oom_handling))] #[unstable(feature = "allocator_api", issue = "32838")] +#[track_caller] pub fn from_elem_in(elem: T, n: usize, alloc: A) -> Vec { ::from_elem(elem, n, alloc) } @@ -3149,6 +3168,7 @@ unsafe impl ops::DerefPure for Vec {} #[stable(feature = "rust1", since = "1.0.0")] impl Clone for Vec { #[cfg(not(test))] + #[track_caller] fn clone(&self) -> Self { let alloc = self.allocator().clone(); <[T]>::to_vec_in(&**self, alloc) @@ -3186,6 +3206,7 @@ impl Clone for Vec { /// // And no reallocation occurred /// assert_eq!(yp, y.as_ptr()); /// ``` + #[track_caller] fn clone_from(&mut self, source: &Self) { crate::slice::SpecCloneIntoVec::clone_into(source.as_slice(), self); } @@ -3284,6 +3305,7 @@ impl, A: Allocator> IndexMut for Vec { #[stable(feature = "rust1", since = "1.0.0")] impl FromIterator for Vec { #[inline] + #[track_caller] fn from_iter>(iter: I) -> Vec { >::from_iter(iter.into_iter()) } @@ -3352,16 +3374,19 @@ impl<'a, T, A: Allocator> IntoIterator for &'a mut Vec { #[stable(feature = "rust1", since = "1.0.0")] impl Extend for Vec { #[inline] + #[track_caller] fn extend>(&mut self, iter: I) { >::spec_extend(self, iter.into_iter()) } #[inline] + #[track_caller] fn extend_one(&mut self, item: T) { self.push(item); } #[inline] + #[track_caller] fn extend_reserve(&mut self, additional: usize) { self.reserve(additional); } @@ -3381,6 +3406,7 @@ impl Vec { // leaf method to which various SpecFrom/SpecExtend implementations delegate when // they have no further optimizations to apply #[cfg(not(no_global_oom_handling))] + #[track_caller] fn extend_desugared>(&mut self, mut iterator: I) { // This is the case for a general iterator. // @@ -3408,6 +3434,7 @@ impl Vec { // specific extend for `TrustedLen` iterators, called both by the specializations // and internal places where resolving specialization makes compilation slower #[cfg(not(no_global_oom_handling))] + #[track_caller] fn extend_trusted(&mut self, iterator: impl iter::TrustedLen) { let (low, high) = iterator.size_hint(); if let Some(additional) = high { @@ -3558,16 +3585,19 @@ impl Vec { #[cfg(not(no_global_oom_handling))] #[stable(feature = "extend_ref", since = "1.2.0")] impl<'a, T: Copy + 'a, A: Allocator> Extend<&'a T> for Vec { + #[track_caller] fn extend>(&mut self, iter: I) { self.spec_extend(iter.into_iter()) } #[inline] + #[track_caller] fn extend_one(&mut self, &item: &'a T) { self.push(item); } #[inline] + #[track_caller] fn extend_reserve(&mut self, additional: usize) { self.reserve(additional); } @@ -3678,6 +3708,7 @@ impl From<&[T]> for Vec { /// assert_eq!(Vec::from(&[1, 2, 3][..]), vec![1, 2, 3]); /// ``` #[cfg(not(test))] + #[track_caller] fn from(s: &[T]) -> Vec { s.to_vec() } @@ -3698,6 +3729,7 @@ impl From<&mut [T]> for Vec { /// assert_eq!(Vec::from(&mut [1, 2, 3][..]), vec![1, 2, 3]); /// ``` #[cfg(not(test))] + #[track_caller] fn from(s: &mut [T]) -> Vec { s.to_vec() } @@ -3717,6 +3749,7 @@ impl From<&[T; N]> for Vec { /// ``` /// assert_eq!(Vec::from(&[1, 2, 3]), vec![1, 2, 3]); /// ``` + #[track_caller] fn from(s: &[T; N]) -> Vec { Self::from(s.as_slice()) } @@ -3732,6 +3765,7 @@ impl From<&mut [T; N]> for Vec { /// ``` /// assert_eq!(Vec::from(&mut [1, 2, 3]), vec![1, 2, 3]); /// ``` + #[track_caller] fn from(s: &mut [T; N]) -> Vec { Self::from(s.as_mut_slice()) } @@ -3748,6 +3782,7 @@ impl From<[T; N]> for Vec { /// assert_eq!(Vec::from([1, 2, 3]), vec![1, 2, 3]); /// ``` #[cfg(not(test))] + #[track_caller] fn from(s: [T; N]) -> Vec { <[T]>::into_vec(Box::new(s)) } @@ -3777,6 +3812,7 @@ where /// let b: Cow<'_, [i32]> = Cow::Borrowed(&[1, 2, 3]); /// assert_eq!(Vec::from(o), Vec::from(b)); /// ``` + #[track_caller] fn from(s: Cow<'a, [T]>) -> Vec { s.into_owned() } @@ -3825,6 +3861,7 @@ impl From> for Box<[T], A> { /// /// assert_eq!(Box::from(vec), vec![1, 2, 3].into_boxed_slice()); /// ``` + #[track_caller] fn from(v: Vec) -> Self { v.into_boxed_slice() } @@ -3840,6 +3877,7 @@ impl From<&str> for Vec { /// ``` /// assert_eq!(Vec::from("123"), vec![b'1', b'2', b'3']); /// ``` + #[track_caller] fn from(s: &str) -> Vec { From::from(s.as_bytes()) } diff --git a/library/alloc/src/vec/spec_extend.rs b/library/alloc/src/vec/spec_extend.rs index 7085bceef5b..b98db669059 100644 --- a/library/alloc/src/vec/spec_extend.rs +++ b/library/alloc/src/vec/spec_extend.rs @@ -6,6 +6,7 @@ use crate::alloc::Allocator; // Specialization trait used for Vec::extend pub(super) trait SpecExtend { + #[track_caller] fn spec_extend(&mut self, iter: I); } @@ -13,6 +14,7 @@ impl SpecExtend for Vec where I: Iterator, { + #[track_caller] default fn spec_extend(&mut self, iter: I) { self.extend_desugared(iter) } @@ -22,12 +24,14 @@ impl SpecExtend for Vec where I: TrustedLen, { + #[track_caller] default fn spec_extend(&mut self, iterator: I) { self.extend_trusted(iterator) } } impl SpecExtend> for Vec { + #[track_caller] fn spec_extend(&mut self, mut iterator: IntoIter) { unsafe { self.append_elements(iterator.as_slice() as _); @@ -41,6 +45,7 @@ where I: Iterator, T: Clone, { + #[track_caller] default fn spec_extend(&mut self, iterator: I) { self.spec_extend(iterator.cloned()) } @@ -50,6 +55,7 @@ impl<'a, T: 'a, A: Allocator> SpecExtend<&'a T, slice::Iter<'a, T>> for Vec) { let slice = iterator.as_slice(); unsafe { self.append_elements(slice) }; diff --git a/library/alloc/src/vec/spec_from_elem.rs b/library/alloc/src/vec/spec_from_elem.rs index 96d701e15d4..6c7b4d89f2d 100644 --- a/library/alloc/src/vec/spec_from_elem.rs +++ b/library/alloc/src/vec/spec_from_elem.rs @@ -10,6 +10,7 @@ pub(super) trait SpecFromElem: Sized { } impl SpecFromElem for T { + #[track_caller] default fn from_elem(elem: Self, n: usize, alloc: A) -> Vec { let mut v = Vec::with_capacity_in(n, alloc); v.extend_with(n, elem); @@ -19,6 +20,7 @@ impl SpecFromElem for T { impl SpecFromElem for T { #[inline] + #[track_caller] default fn from_elem(elem: T, n: usize, alloc: A) -> Vec { if elem.is_zero() { return Vec { buf: RawVec::with_capacity_zeroed_in(n, alloc), len: n }; @@ -31,6 +33,7 @@ impl SpecFromElem for T { impl SpecFromElem for i8 { #[inline] + #[track_caller] fn from_elem(elem: i8, n: usize, alloc: A) -> Vec { if elem == 0 { return Vec { buf: RawVec::with_capacity_zeroed_in(n, alloc), len: n }; @@ -46,6 +49,7 @@ impl SpecFromElem for i8 { impl SpecFromElem for u8 { #[inline] + #[track_caller] fn from_elem(elem: u8, n: usize, alloc: A) -> Vec { if elem == 0 { return Vec { buf: RawVec::with_capacity_zeroed_in(n, alloc), len: n }; diff --git a/library/alloc/src/vec/spec_from_iter.rs b/library/alloc/src/vec/spec_from_iter.rs index e1f0b639bdf..ad7688e1c59 100644 --- a/library/alloc/src/vec/spec_from_iter.rs +++ b/library/alloc/src/vec/spec_from_iter.rs @@ -29,12 +29,14 @@ impl SpecFromIter for Vec where I: Iterator, { + #[track_caller] default fn from_iter(iterator: I) -> Self { SpecFromIterNested::from_iter(iterator) } } impl SpecFromIter> for Vec { + #[track_caller] fn from_iter(iterator: IntoIter) -> Self { // A common case is passing a vector into a function which immediately // re-collects into a vector. We can short circuit this if the IntoIter diff --git a/library/alloc/src/vec/spec_from_iter_nested.rs b/library/alloc/src/vec/spec_from_iter_nested.rs index 77f7761d22f..22eed238798 100644 --- a/library/alloc/src/vec/spec_from_iter_nested.rs +++ b/library/alloc/src/vec/spec_from_iter_nested.rs @@ -15,6 +15,7 @@ impl SpecFromIterNested for Vec where I: Iterator, { + #[track_caller] default fn from_iter(mut iterator: I) -> Self { // Unroll the first iteration, as the vector is going to be // expanded on this iteration in every case when the iterable is not @@ -47,6 +48,7 @@ impl SpecFromIterNested for Vec where I: TrustedLen, { + #[track_caller] fn from_iter(iterator: I) -> Self { let mut vector = match iterator.size_hint() { (_, Some(upper)) => Vec::with_capacity(upper), diff --git a/library/alloc/src/vec/splice.rs b/library/alloc/src/vec/splice.rs index 9e36377c148..ca5cb17f8bf 100644 --- a/library/alloc/src/vec/splice.rs +++ b/library/alloc/src/vec/splice.rs @@ -52,6 +52,7 @@ impl ExactSizeIterator for Splice<'_, I, A> {} #[stable(feature = "vec_splice", since = "1.21.0")] impl Drop for Splice<'_, I, A> { + #[track_caller] fn drop(&mut self) { self.drain.by_ref().for_each(drop); // At this point draining is done and the only remaining tasks are splicing @@ -123,6 +124,7 @@ impl Drain<'_, T, A> { } /// Makes room for inserting more elements before the tail. + #[track_caller] unsafe fn move_tail(&mut self, additional: usize) { let vec = unsafe { self.vec.as_mut() }; let len = self.tail_start + self.tail_len; From 683ef6002b28091607bd33f8d9d76ab7dc5b42cc Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Sun, 18 Aug 2024 21:00:40 +0300 Subject: [PATCH 003/357] Bless a test for #70963 --- tests/ui/hygiene/panic-location.rs | 3 +-- tests/ui/hygiene/panic-location.run.stderr | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/ui/hygiene/panic-location.rs b/tests/ui/hygiene/panic-location.rs index 7b20f1683a9..580a8bcff05 100644 --- a/tests/ui/hygiene/panic-location.rs +++ b/tests/ui/hygiene/panic-location.rs @@ -4,8 +4,7 @@ //@ normalize-stderr-test: ".rs:\d+:\d+" -> ".rs:LL:CC" // // Regression test for issue #70963 -// The captured stderr from this test reports a location -// inside `VecDeque::with_capacity`, instead of `<::core::macros::panic macros>` +// The reported panic location should not be `<::core::macros::panic macros>`. fn main() { std::collections::VecDeque::::with_capacity(!0); } diff --git a/tests/ui/hygiene/panic-location.run.stderr b/tests/ui/hygiene/panic-location.run.stderr index bfed4cd6650..b9086ecef81 100644 --- a/tests/ui/hygiene/panic-location.run.stderr +++ b/tests/ui/hygiene/panic-location.run.stderr @@ -1,3 +1,3 @@ -thread 'main' panicked at alloc/src/raw_vec.rs:LL:CC: +thread 'main' panicked at $DIR/panic-location.rs:LL:CC: capacity overflow note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace From 2f6b0618b2076a9445480fbde4f1fb98986c826d Mon Sep 17 00:00:00 2001 From: Giang Dao Date: Fri, 20 Sep 2024 21:49:37 +0800 Subject: [PATCH 004/357] dont regenerate new links for rexports --- compiler/rustc_hir/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs index c1a4a4497c7..381062b1429 100644 --- a/compiler/rustc_hir/src/lib.rs +++ b/compiler/rustc_hir/src/lib.rs @@ -33,6 +33,7 @@ pub mod weak_lang_items; #[cfg(test)] mod tests; +#[doc(no_inline)] pub use hir::*; pub use hir_id::*; pub use lang_items::{LangItem, LanguageItems}; From ff86fa50fbb71073ec828e82fbfa431a3bdac2b1 Mon Sep 17 00:00:00 2001 From: Giang Dao Date: Fri, 20 Sep 2024 23:30:31 +0800 Subject: [PATCH 005/357] no_inline for index vec --- compiler/rustc_index/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_index/src/lib.rs b/compiler/rustc_index/src/lib.rs index 52f354b8eca..cae55230b06 100644 --- a/compiler/rustc_index/src/lib.rs +++ b/compiler/rustc_index/src/lib.rs @@ -17,6 +17,7 @@ mod vec; pub use idx::Idx; pub use rustc_index_macros::newtype_index; pub use slice::IndexSlice; +#[doc(no_inline)] pub use vec::IndexVec; /// Type size assertion. The first argument is a type and the second argument is its expected size. From b7a490ab33942806e3783c829ad497c982bd6f1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Wed, 14 Aug 2024 08:40:30 +0200 Subject: [PATCH 006/357] Create _imp__ symbols also when doing ThinLTO --- compiler/rustc_codegen_ssa/src/back/write.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index c170cd41ec4..a23365025bc 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -2165,8 +2165,14 @@ fn msvc_imps_needed(tcx: TyCtxt<'_>) -> bool { && tcx.sess.opts.cg.prefer_dynamic) ); + // We need to generate _imp__ symbol if we are generating an rlib or we include one + // indirectly from ThinLTO. In theory these are not needed as ThinLTO could resolve + // these, but it currently does not do so. + let can_have_static_objects = + tcx.sess.lto() == Lto::Thin || tcx.crate_types().iter().any(|ct| *ct == CrateType::Rlib); + tcx.sess.target.is_like_windows && - tcx.crate_types().iter().any(|ct| *ct == CrateType::Rlib) && + can_have_static_objects && // ThinLTO can't handle this workaround in all cases, so we don't // emit the `__imp_` symbols. Instead we make them unnecessary by disallowing // dynamic linking when linker plugin LTO is enabled. From 562c0d1299443f223b8526876701936ded463cad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Wed, 14 Aug 2024 20:50:53 +0200 Subject: [PATCH 007/357] add non-regression test for issue 81408 --- .../issue_81408.rs | 13 ++++++++ .../msvc-lld-thinlto-imp-symbols/main.rs | 5 +++ .../msvc-lld-thinlto-imp-symbols/rmake.rs | 33 +++++++++++++++++++ 3 files changed, 51 insertions(+) create mode 100644 tests/run-make/msvc-lld-thinlto-imp-symbols/issue_81408.rs create mode 100644 tests/run-make/msvc-lld-thinlto-imp-symbols/main.rs create mode 100644 tests/run-make/msvc-lld-thinlto-imp-symbols/rmake.rs diff --git a/tests/run-make/msvc-lld-thinlto-imp-symbols/issue_81408.rs b/tests/run-make/msvc-lld-thinlto-imp-symbols/issue_81408.rs new file mode 100644 index 00000000000..afb0dc42f44 --- /dev/null +++ b/tests/run-make/msvc-lld-thinlto-imp-symbols/issue_81408.rs @@ -0,0 +1,13 @@ +use std::sync::atomic::{AtomicPtr, Ordering}; + +#[inline(always)] +pub fn memrchr() { + fn detect() {} + + static CROSS_CRATE_STATIC_ITEM: AtomicPtr<()> = AtomicPtr::new(detect as *mut ()); + + unsafe { + let fun = CROSS_CRATE_STATIC_ITEM.load(Ordering::SeqCst); + std::mem::transmute::<*mut (), fn()>(fun)() + } +} diff --git a/tests/run-make/msvc-lld-thinlto-imp-symbols/main.rs b/tests/run-make/msvc-lld-thinlto-imp-symbols/main.rs new file mode 100644 index 00000000000..2d2d2e68125 --- /dev/null +++ b/tests/run-make/msvc-lld-thinlto-imp-symbols/main.rs @@ -0,0 +1,5 @@ +extern crate issue_81408; + +fn main() { + issue_81408::memrchr(); +} diff --git a/tests/run-make/msvc-lld-thinlto-imp-symbols/rmake.rs b/tests/run-make/msvc-lld-thinlto-imp-symbols/rmake.rs new file mode 100644 index 00000000000..3db1ae3452d --- /dev/null +++ b/tests/run-make/msvc-lld-thinlto-imp-symbols/rmake.rs @@ -0,0 +1,33 @@ +// This is a non-regression test for issue #81408 involving an lld bug and ThinLTO, on windows. +// MSVC's link.exe doesn't need any workarounds in rustc, but lld does, so we'll check that the +// binary runs successfully instead of using a codegen test. + +//@ only-x86_64-pc-windows-msvc +//@ needs-rust-lld +//@ ignore-cross-compile: the built binary is executed + +use run_make_support::{run, rustc}; + +fn test_with_linker(linker: &str) { + rustc().input("issue_81408.rs").crate_name("issue_81408").crate_type("lib").opt().run(); + rustc() + .input("main.rs") + .crate_type("bin") + .arg("-Clto=thin") + .opt() + .arg(&format!("-Clinker={linker}")) + .extern_("issue_81408", "libissue_81408.rlib") + .run(); + + // To make possible failures clearer, print an intro that will only be shown if the test does + // fail when running the binary. + eprint!("Running binary linked with {linker}... "); + run("main"); + eprintln!("ok"); +} + +fn main() { + // We want the reproducer to work when linked with both linkers. + test_with_linker("link"); + test_with_linker("rust-lld"); +} From 47293c1234e615045b5bd6fbbf867ff6b757fd1f Mon Sep 17 00:00:00 2001 From: Tamme Dittrich Date: Wed, 7 Aug 2024 15:48:16 +0200 Subject: [PATCH 008/357] Check ABI target compatibility for function pointers This check was previously only performed on functions not function pointers. Co-authored-by: Folkert --- .../rustc_hir_analysis/src/check/check.rs | 24 +-- compiler/rustc_hir_analysis/src/check/mod.rs | 2 +- .../src/hir_ty_lowering/cmse.rs | 19 ++- .../src/hir_ty_lowering/mod.rs | 7 + compiler/rustc_lint_defs/src/builtin.rs | 45 ++++++ tests/debuginfo/type-names.rs | 4 +- tests/ui/abi/unsupported.aarch64.stderr | 153 ++++++++++++++++-- tests/ui/abi/unsupported.arm.stderr | 136 ++++++++++++++-- tests/ui/abi/unsupported.i686.stderr | 97 ++++++++++- tests/ui/abi/unsupported.riscv32.stderr | 136 ++++++++++++++-- tests/ui/abi/unsupported.riscv64.stderr | 136 ++++++++++++++-- tests/ui/abi/unsupported.rs | 134 ++++++++++++++- tests/ui/abi/unsupported.x64.stderr | 136 ++++++++++++++-- ...ature-gate-extended_varargs_abi_support.rs | 2 + ...e-gate-extended_varargs_abi_support.stderr | 12 +- tests/ui/c-variadic/variadic-ffi-2-arm.rs | 9 ++ tests/ui/c-variadic/variadic-ffi-2.rs | 14 +- tests/ui/c-variadic/variadic-ffi-2.stderr | 2 +- .../cmse-nonsecure-call/gate_test.rs | 3 +- .../cmse-nonsecure-call/gate_test.stderr | 2 +- 20 files changed, 991 insertions(+), 82 deletions(-) create mode 100644 tests/ui/c-variadic/variadic-ffi-2-arm.rs diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index d725772a5b3..4c53414226b 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -8,7 +8,9 @@ use rustc_hir::Node; use rustc_hir::def::{CtorKind, DefKind}; use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt}; use rustc_infer::traits::Obligation; -use rustc_lint_defs::builtin::REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS; +use rustc_lint_defs::builtin::{ + REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS, UNSUPPORTED_FN_PTR_CALLING_CONVENTIONS, +}; use rustc_middle::middle::resolve_bound_vars::ResolvedArg; use rustc_middle::middle::stability::EvalResult; use rustc_middle::span_bug; @@ -52,16 +54,18 @@ pub fn check_abi(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: Abi) { }); } } +} - // This ABI is only allowed on function pointers - if abi == Abi::CCmseNonSecureCall { - struct_span_code_err!( - tcx.dcx(), - span, - E0781, - "the `\"C-cmse-nonsecure-call\"` ABI is only allowed on function pointers" - ) - .emit(); +pub fn check_abi_fn_ptr(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: Abi) { + match tcx.sess.target.is_abi_supported(abi) { + Some(true) => (), + Some(false) | None => { + tcx.node_span_lint(UNSUPPORTED_FN_PTR_CALLING_CONVENTIONS, hir_id, span, |lint| { + lint.primary_message( + "use of calling convention not supported on this target on function pointer", + ); + }); + } } } diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index d3d88919d87..004540b2643 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -73,7 +73,7 @@ pub mod wfcheck; use std::num::NonZero; -pub use check::check_abi; +pub use check::{check_abi, check_abi_fn_ptr}; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_errors::{Diag, ErrorGuaranteed, pluralize, struct_span_code_err}; use rustc_hir::def_id::{DefId, LocalDefId}; diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs index 5150db7f51b..a562759da11 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs @@ -1,6 +1,5 @@ -use rustc_errors::DiagCtxtHandle; -use rustc_hir as hir; -use rustc_hir::HirId; +use rustc_errors::{DiagCtxtHandle, E0781, struct_span_code_err}; +use rustc_hir::{self as hir, HirId}; use rustc_middle::ty::layout::LayoutError; use rustc_middle::ty::{self, ParamEnv, TyCtxt}; use rustc_span::Span; @@ -26,7 +25,19 @@ pub(crate) fn validate_cmse_abi<'tcx>( .. }) = hir_node else { - // might happen when this ABI is used incorrectly. That will be handled elsewhere + let span = match tcx.parent_hir_node(hir_id) { + hir::Node::Item(hir::Item { + kind: hir::ItemKind::ForeignMod { .. }, span, .. + }) => *span, + _ => tcx.hir().span(hir_id), + }; + struct_span_code_err!( + tcx.dcx(), + span, + E0781, + "the `\"C-cmse-nonsecure-call\"` ABI is only allowed on function pointers" + ) + .emit(); return; }; diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index e95b5142559..b6562c97247 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -53,6 +53,7 @@ use rustc_trait_selection::traits::{self, ObligationCtxt}; use tracing::{debug, debug_span, instrument}; use crate::bounds::Bounds; +use crate::check::check_abi_fn_ptr; use crate::errors::{AmbiguousLifetimeBound, BadReturnTypeNotation, WildPatTy}; use crate::hir_ty_lowering::errors::{GenericsArgsErrExtend, prohibit_assoc_item_constraint}; use crate::hir_ty_lowering::generics::{check_generic_arg_count, lower_generic_args}; @@ -2324,6 +2325,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let fn_ty = tcx.mk_fn_sig(input_tys, output_ty, decl.c_variadic, safety, abi); let bare_fn_ty = ty::Binder::bind_with_vars(fn_ty, bound_vars); + if let hir::Node::Ty(hir::Ty { kind: hir::TyKind::BareFn(bare_fn_ty), span, .. }) = + tcx.hir_node(hir_id) + { + check_abi_fn_ptr(tcx, hir_id, *span, bare_fn_ty.abi); + } + // reject function types that violate cmse ABI requirements cmse::validate_cmse_abi(self.tcx(), self.dcx(), hir_id, abi, bare_fn_ty); diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 549dc64a562..5366064856c 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -123,6 +123,7 @@ declare_lint_pass! { UNSTABLE_NAME_COLLISIONS, UNSTABLE_SYNTAX_PRE_EXPANSION, UNSUPPORTED_CALLING_CONVENTIONS, + UNSUPPORTED_FN_PTR_CALLING_CONVENTIONS, UNUSED_ASSIGNMENTS, UNUSED_ASSOCIATED_TYPE_BOUNDS, UNUSED_ATTRIBUTES, @@ -3874,6 +3875,50 @@ declare_lint! { }; } +declare_lint! { + /// The `unsupported_fn_ptr_calling_conventions` lint is output whenever there is a use of + /// a target dependent calling convention on a target that does not support this calling + /// convention on a function pointer. + /// + /// For example `stdcall` does not make much sense for a x86_64 or, more apparently, powerpc + /// code, because this calling convention was never specified for those targets. + /// + /// ### Example + /// + /// ```rust,ignore (needs specific targets) + /// fn stdcall_ptr(f: extern "stdcall" fn ()) { + /// f() + /// } + /// ``` + /// + /// This will produce: + /// + /// ```text + /// warning: use of calling convention not supported on this target on function pointer + /// --> $DIR/unsupported.rs:34:15 + /// | + /// LL | fn stdcall_ptr(f: extern "stdcall" fn()) { + /// | ^^^^^^^^^^^^^^^^^^^^^^^^ + /// | + /// = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + /// = note: for more information, see issue #130260 + /// = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default + /// ``` + /// + /// ### Explanation + /// + /// On most of the targets the behaviour of `stdcall` and similar calling conventions is not + /// defined at all, but was previously accepted due to a bug in the implementation of the + /// compiler. + pub UNSUPPORTED_FN_PTR_CALLING_CONVENTIONS, + Warn, + "use of unsupported calling convention for function pointer", + @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps, + reference: "issue #130260 ", + }; +} + declare_lint! { /// The `break_with_label_and_loop` lint detects labeled `break` expressions with /// an unlabeled loop as their value expression. diff --git a/tests/debuginfo/type-names.rs b/tests/debuginfo/type-names.rs index 6831786c228..4caaf3fc97f 100644 --- a/tests/debuginfo/type-names.rs +++ b/tests/debuginfo/type-names.rs @@ -17,7 +17,7 @@ // gdb-check:type = type_names::GenericStruct // gdb-command:whatis generic_struct2 -// gdb-check:type = type_names::GenericStruct usize> +// gdb-check:type = type_names::GenericStruct usize> // gdb-command:whatis mod_struct // gdb-check:type = type_names::mod1::Struct2 @@ -372,7 +372,7 @@ fn main() { let simple_struct = Struct1; let generic_struct1: GenericStruct = GenericStruct(PhantomData); - let generic_struct2: GenericStruct usize> = + let generic_struct2: GenericStruct usize> = GenericStruct(PhantomData); let mod_struct = mod1::Struct2; diff --git a/tests/ui/abi/unsupported.aarch64.stderr b/tests/ui/abi/unsupported.aarch64.stderr index 123e7663257..67db139ac64 100644 --- a/tests/ui/abi/unsupported.aarch64.stderr +++ b/tests/ui/abi/unsupported.aarch64.stderr @@ -1,55 +1,188 @@ +warning: use of calling convention not supported on this target on function pointer + --> $DIR/unsupported.rs:34:15 + | +LL | fn ptx_ptr(f: extern "ptx-kernel" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #130260 + = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default + error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:28:1 + --> $DIR/unsupported.rs:39:1 + | +LL | extern "ptx-kernel" {} + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of calling convention not supported on this target on function pointer + --> $DIR/unsupported.rs:48:17 + | +LL | fn aapcs_ptr(f: extern "aapcs" fn()) { + | ^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #130260 + +error[E0570]: `"aapcs"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:61:1 + | +LL | extern "aapcs" {} + | ^^^^^^^^^^^^^^^^^ + +warning: use of calling convention not supported on this target on function pointer + --> $DIR/unsupported.rs:70:18 + | +LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #130260 + +error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:75:1 + | +LL | extern "msp430-interrupt" {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of calling convention not supported on this target on function pointer + --> $DIR/unsupported.rs:80:15 + | +LL | fn avr_ptr(f: extern "avr-interrupt" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #130260 + +error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:85:1 + | +LL | extern "avr-interrupt" {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of calling convention not supported on this target on function pointer + --> $DIR/unsupported.rs:93:17 + | +LL | fn riscv_ptr(f: extern "riscv-interrupt-m" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #130260 + +error[E0570]: `"riscv-interrupt-m"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:104:1 + | +LL | extern "riscv-interrupt-m" {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of calling convention not supported on this target on function pointer + --> $DIR/unsupported.rs:115:15 + | +LL | fn x86_ptr(f: extern "x86-interrupt" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #130260 + +error[E0570]: `"x86-interrupt"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:126:1 + | +LL | extern "x86-interrupt" {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of calling convention not supported on this target on function pointer + --> $DIR/unsupported.rs:138:20 + | +LL | fn thiscall_ptr(f: extern "thiscall" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #130260 + +error[E0570]: `"thiscall"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:151:1 + | +LL | extern "thiscall" {} + | ^^^^^^^^^^^^^^^^^^^^ + +warning: use of calling convention not supported on this target on function pointer + --> $DIR/unsupported.rs:169:19 + | +LL | fn stdcall_ptr(f: extern "stdcall" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #130260 + +warning: use of calling convention not supported on this target + --> $DIR/unsupported.rs:182:1 + | +LL | extern "stdcall" {} + | ^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #87678 + = note: `#[warn(unsupported_calling_conventions)]` on by default + +warning: use of calling convention not supported on this target on function pointer + --> $DIR/unsupported.rs:194:16 + | +LL | fn cmse_ptr(f: extern "C-cmse-nonsecure-call" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #130260 + +error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:32:1 | LL | extern "ptx-kernel" fn ptx() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"aapcs"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:30:1 + --> $DIR/unsupported.rs:42:1 | LL | extern "aapcs" fn aapcs() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:36:1 + --> $DIR/unsupported.rs:68:1 | LL | extern "msp430-interrupt" fn msp430() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:38:1 + --> $DIR/unsupported.rs:78:1 | LL | extern "avr-interrupt" fn avr() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"riscv-interrupt-m"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:40:1 + --> $DIR/unsupported.rs:88:1 | LL | extern "riscv-interrupt-m" fn riscv() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"x86-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:45:1 + --> $DIR/unsupported.rs:110:1 | LL | extern "x86-interrupt" fn x86() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"thiscall"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:50:1 + --> $DIR/unsupported.rs:132:1 | LL | extern "thiscall" fn thiscall() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of calling convention not supported on this target - --> $DIR/unsupported.rs:56:1 + --> $DIR/unsupported.rs:158:1 | LL | extern "stdcall" fn stdcall() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #87678 - = note: `#[warn(unsupported_calling_conventions)]` on by default -error: aborting due to 7 previous errors; 1 warning emitted +error: aborting due to 14 previous errors; 11 warnings emitted For more information about this error, try `rustc --explain E0570`. diff --git a/tests/ui/abi/unsupported.arm.stderr b/tests/ui/abi/unsupported.arm.stderr index 7376bb17d6b..90f0cf709f2 100644 --- a/tests/ui/abi/unsupported.arm.stderr +++ b/tests/ui/abi/unsupported.arm.stderr @@ -1,49 +1,167 @@ +warning: use of calling convention not supported on this target on function pointer + --> $DIR/unsupported.rs:34:15 + | +LL | fn ptx_ptr(f: extern "ptx-kernel" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #130260 + = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default + error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:28:1 + --> $DIR/unsupported.rs:39:1 + | +LL | extern "ptx-kernel" {} + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of calling convention not supported on this target on function pointer + --> $DIR/unsupported.rs:70:18 + | +LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #130260 + +error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:75:1 + | +LL | extern "msp430-interrupt" {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of calling convention not supported on this target on function pointer + --> $DIR/unsupported.rs:80:15 + | +LL | fn avr_ptr(f: extern "avr-interrupt" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #130260 + +error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:85:1 + | +LL | extern "avr-interrupt" {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of calling convention not supported on this target on function pointer + --> $DIR/unsupported.rs:93:17 + | +LL | fn riscv_ptr(f: extern "riscv-interrupt-m" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #130260 + +error[E0570]: `"riscv-interrupt-m"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:104:1 + | +LL | extern "riscv-interrupt-m" {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of calling convention not supported on this target on function pointer + --> $DIR/unsupported.rs:115:15 + | +LL | fn x86_ptr(f: extern "x86-interrupt" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #130260 + +error[E0570]: `"x86-interrupt"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:126:1 + | +LL | extern "x86-interrupt" {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of calling convention not supported on this target on function pointer + --> $DIR/unsupported.rs:138:20 + | +LL | fn thiscall_ptr(f: extern "thiscall" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #130260 + +error[E0570]: `"thiscall"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:151:1 + | +LL | extern "thiscall" {} + | ^^^^^^^^^^^^^^^^^^^^ + +warning: use of calling convention not supported on this target on function pointer + --> $DIR/unsupported.rs:169:19 + | +LL | fn stdcall_ptr(f: extern "stdcall" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #130260 + +warning: use of calling convention not supported on this target + --> $DIR/unsupported.rs:182:1 + | +LL | extern "stdcall" {} + | ^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #87678 + = note: `#[warn(unsupported_calling_conventions)]` on by default + +warning: use of calling convention not supported on this target on function pointer + --> $DIR/unsupported.rs:194:16 + | +LL | fn cmse_ptr(f: extern "C-cmse-nonsecure-call" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #130260 + +error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:32:1 | LL | extern "ptx-kernel" fn ptx() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:36:1 + --> $DIR/unsupported.rs:68:1 | LL | extern "msp430-interrupt" fn msp430() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:38:1 + --> $DIR/unsupported.rs:78:1 | LL | extern "avr-interrupt" fn avr() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"riscv-interrupt-m"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:40:1 + --> $DIR/unsupported.rs:88:1 | LL | extern "riscv-interrupt-m" fn riscv() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"x86-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:45:1 + --> $DIR/unsupported.rs:110:1 | LL | extern "x86-interrupt" fn x86() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"thiscall"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:50:1 + --> $DIR/unsupported.rs:132:1 | LL | extern "thiscall" fn thiscall() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of calling convention not supported on this target - --> $DIR/unsupported.rs:56:1 + --> $DIR/unsupported.rs:158:1 | LL | extern "stdcall" fn stdcall() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #87678 - = note: `#[warn(unsupported_calling_conventions)]` on by default -error: aborting due to 6 previous errors; 1 warning emitted +error: aborting due to 12 previous errors; 10 warnings emitted For more information about this error, try `rustc --explain E0570`. diff --git a/tests/ui/abi/unsupported.i686.stderr b/tests/ui/abi/unsupported.i686.stderr index 23b0e581887..67e3100d419 100644 --- a/tests/ui/abi/unsupported.i686.stderr +++ b/tests/ui/abi/unsupported.i686.stderr @@ -1,33 +1,118 @@ +warning: use of calling convention not supported on this target on function pointer + --> $DIR/unsupported.rs:34:15 + | +LL | fn ptx_ptr(f: extern "ptx-kernel" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #130260 + = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default + error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:28:1 + --> $DIR/unsupported.rs:39:1 + | +LL | extern "ptx-kernel" {} + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of calling convention not supported on this target on function pointer + --> $DIR/unsupported.rs:48:17 + | +LL | fn aapcs_ptr(f: extern "aapcs" fn()) { + | ^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #130260 + +error[E0570]: `"aapcs"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:61:1 + | +LL | extern "aapcs" {} + | ^^^^^^^^^^^^^^^^^ + +warning: use of calling convention not supported on this target on function pointer + --> $DIR/unsupported.rs:70:18 + | +LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #130260 + +error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:75:1 + | +LL | extern "msp430-interrupt" {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of calling convention not supported on this target on function pointer + --> $DIR/unsupported.rs:80:15 + | +LL | fn avr_ptr(f: extern "avr-interrupt" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #130260 + +error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:85:1 + | +LL | extern "avr-interrupt" {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of calling convention not supported on this target on function pointer + --> $DIR/unsupported.rs:93:17 + | +LL | fn riscv_ptr(f: extern "riscv-interrupt-m" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #130260 + +error[E0570]: `"riscv-interrupt-m"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:104:1 + | +LL | extern "riscv-interrupt-m" {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of calling convention not supported on this target on function pointer + --> $DIR/unsupported.rs:194:16 + | +LL | fn cmse_ptr(f: extern "C-cmse-nonsecure-call" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #130260 + +error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:32:1 | LL | extern "ptx-kernel" fn ptx() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"aapcs"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:30:1 + --> $DIR/unsupported.rs:42:1 | LL | extern "aapcs" fn aapcs() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:36:1 + --> $DIR/unsupported.rs:68:1 | LL | extern "msp430-interrupt" fn msp430() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:38:1 + --> $DIR/unsupported.rs:78:1 | LL | extern "avr-interrupt" fn avr() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"riscv-interrupt-m"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:40:1 + --> $DIR/unsupported.rs:88:1 | LL | extern "riscv-interrupt-m" fn riscv() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 5 previous errors +error: aborting due to 10 previous errors; 6 warnings emitted For more information about this error, try `rustc --explain E0570`. diff --git a/tests/ui/abi/unsupported.riscv32.stderr b/tests/ui/abi/unsupported.riscv32.stderr index 708fd2c92a9..683c343eeef 100644 --- a/tests/ui/abi/unsupported.riscv32.stderr +++ b/tests/ui/abi/unsupported.riscv32.stderr @@ -1,49 +1,167 @@ +warning: use of calling convention not supported on this target on function pointer + --> $DIR/unsupported.rs:34:15 + | +LL | fn ptx_ptr(f: extern "ptx-kernel" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #130260 + = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default + error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:28:1 + --> $DIR/unsupported.rs:39:1 + | +LL | extern "ptx-kernel" {} + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of calling convention not supported on this target on function pointer + --> $DIR/unsupported.rs:48:17 + | +LL | fn aapcs_ptr(f: extern "aapcs" fn()) { + | ^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #130260 + +error[E0570]: `"aapcs"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:61:1 + | +LL | extern "aapcs" {} + | ^^^^^^^^^^^^^^^^^ + +warning: use of calling convention not supported on this target on function pointer + --> $DIR/unsupported.rs:70:18 + | +LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #130260 + +error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:75:1 + | +LL | extern "msp430-interrupt" {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of calling convention not supported on this target on function pointer + --> $DIR/unsupported.rs:80:15 + | +LL | fn avr_ptr(f: extern "avr-interrupt" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #130260 + +error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:85:1 + | +LL | extern "avr-interrupt" {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of calling convention not supported on this target on function pointer + --> $DIR/unsupported.rs:115:15 + | +LL | fn x86_ptr(f: extern "x86-interrupt" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #130260 + +error[E0570]: `"x86-interrupt"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:126:1 + | +LL | extern "x86-interrupt" {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of calling convention not supported on this target on function pointer + --> $DIR/unsupported.rs:138:20 + | +LL | fn thiscall_ptr(f: extern "thiscall" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #130260 + +error[E0570]: `"thiscall"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:151:1 + | +LL | extern "thiscall" {} + | ^^^^^^^^^^^^^^^^^^^^ + +warning: use of calling convention not supported on this target on function pointer + --> $DIR/unsupported.rs:169:19 + | +LL | fn stdcall_ptr(f: extern "stdcall" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #130260 + +warning: use of calling convention not supported on this target + --> $DIR/unsupported.rs:182:1 + | +LL | extern "stdcall" {} + | ^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #87678 + = note: `#[warn(unsupported_calling_conventions)]` on by default + +warning: use of calling convention not supported on this target on function pointer + --> $DIR/unsupported.rs:194:16 + | +LL | fn cmse_ptr(f: extern "C-cmse-nonsecure-call" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #130260 + +error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:32:1 | LL | extern "ptx-kernel" fn ptx() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"aapcs"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:30:1 + --> $DIR/unsupported.rs:42:1 | LL | extern "aapcs" fn aapcs() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:36:1 + --> $DIR/unsupported.rs:68:1 | LL | extern "msp430-interrupt" fn msp430() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:38:1 + --> $DIR/unsupported.rs:78:1 | LL | extern "avr-interrupt" fn avr() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"x86-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:45:1 + --> $DIR/unsupported.rs:110:1 | LL | extern "x86-interrupt" fn x86() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"thiscall"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:50:1 + --> $DIR/unsupported.rs:132:1 | LL | extern "thiscall" fn thiscall() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of calling convention not supported on this target - --> $DIR/unsupported.rs:56:1 + --> $DIR/unsupported.rs:158:1 | LL | extern "stdcall" fn stdcall() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #87678 - = note: `#[warn(unsupported_calling_conventions)]` on by default -error: aborting due to 6 previous errors; 1 warning emitted +error: aborting due to 12 previous errors; 10 warnings emitted For more information about this error, try `rustc --explain E0570`. diff --git a/tests/ui/abi/unsupported.riscv64.stderr b/tests/ui/abi/unsupported.riscv64.stderr index 708fd2c92a9..683c343eeef 100644 --- a/tests/ui/abi/unsupported.riscv64.stderr +++ b/tests/ui/abi/unsupported.riscv64.stderr @@ -1,49 +1,167 @@ +warning: use of calling convention not supported on this target on function pointer + --> $DIR/unsupported.rs:34:15 + | +LL | fn ptx_ptr(f: extern "ptx-kernel" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #130260 + = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default + error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:28:1 + --> $DIR/unsupported.rs:39:1 + | +LL | extern "ptx-kernel" {} + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of calling convention not supported on this target on function pointer + --> $DIR/unsupported.rs:48:17 + | +LL | fn aapcs_ptr(f: extern "aapcs" fn()) { + | ^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #130260 + +error[E0570]: `"aapcs"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:61:1 + | +LL | extern "aapcs" {} + | ^^^^^^^^^^^^^^^^^ + +warning: use of calling convention not supported on this target on function pointer + --> $DIR/unsupported.rs:70:18 + | +LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #130260 + +error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:75:1 + | +LL | extern "msp430-interrupt" {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of calling convention not supported on this target on function pointer + --> $DIR/unsupported.rs:80:15 + | +LL | fn avr_ptr(f: extern "avr-interrupt" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #130260 + +error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:85:1 + | +LL | extern "avr-interrupt" {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of calling convention not supported on this target on function pointer + --> $DIR/unsupported.rs:115:15 + | +LL | fn x86_ptr(f: extern "x86-interrupt" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #130260 + +error[E0570]: `"x86-interrupt"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:126:1 + | +LL | extern "x86-interrupt" {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of calling convention not supported on this target on function pointer + --> $DIR/unsupported.rs:138:20 + | +LL | fn thiscall_ptr(f: extern "thiscall" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #130260 + +error[E0570]: `"thiscall"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:151:1 + | +LL | extern "thiscall" {} + | ^^^^^^^^^^^^^^^^^^^^ + +warning: use of calling convention not supported on this target on function pointer + --> $DIR/unsupported.rs:169:19 + | +LL | fn stdcall_ptr(f: extern "stdcall" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #130260 + +warning: use of calling convention not supported on this target + --> $DIR/unsupported.rs:182:1 + | +LL | extern "stdcall" {} + | ^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #87678 + = note: `#[warn(unsupported_calling_conventions)]` on by default + +warning: use of calling convention not supported on this target on function pointer + --> $DIR/unsupported.rs:194:16 + | +LL | fn cmse_ptr(f: extern "C-cmse-nonsecure-call" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #130260 + +error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:32:1 | LL | extern "ptx-kernel" fn ptx() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"aapcs"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:30:1 + --> $DIR/unsupported.rs:42:1 | LL | extern "aapcs" fn aapcs() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:36:1 + --> $DIR/unsupported.rs:68:1 | LL | extern "msp430-interrupt" fn msp430() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:38:1 + --> $DIR/unsupported.rs:78:1 | LL | extern "avr-interrupt" fn avr() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"x86-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:45:1 + --> $DIR/unsupported.rs:110:1 | LL | extern "x86-interrupt" fn x86() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"thiscall"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:50:1 + --> $DIR/unsupported.rs:132:1 | LL | extern "thiscall" fn thiscall() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of calling convention not supported on this target - --> $DIR/unsupported.rs:56:1 + --> $DIR/unsupported.rs:158:1 | LL | extern "stdcall" fn stdcall() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #87678 - = note: `#[warn(unsupported_calling_conventions)]` on by default -error: aborting due to 6 previous errors; 1 warning emitted +error: aborting due to 12 previous errors; 10 warnings emitted For more information about this error, try `rustc --explain E0570`. diff --git a/tests/ui/abi/unsupported.rs b/tests/ui/abi/unsupported.rs index c12883e3fce..cf0db9a78e3 100644 --- a/tests/ui/abi/unsupported.rs +++ b/tests/ui/abi/unsupported.rs @@ -20,39 +20,141 @@ abi_msp430_interrupt, abi_avr_interrupt, abi_x86_interrupt, - abi_riscv_interrupt + abi_riscv_interrupt, + abi_c_cmse_nonsecure_call )] #[lang = "sized"] trait Sized {} +#[lang = "copy"] +trait Copy {} + extern "ptx-kernel" fn ptx() {} //~^ ERROR is not a supported ABI +fn ptx_ptr(f: extern "ptx-kernel" fn()) { + //~^ WARN unsupported_fn_ptr_calling_conventions + //~^^ WARN this was previously accepted + f() +} +extern "ptx-kernel" {} +//~^ ERROR is not a supported ABI + extern "aapcs" fn aapcs() {} //[x64]~^ ERROR is not a supported ABI //[i686]~^^ ERROR is not a supported ABI //[aarch64]~^^^ ERROR is not a supported ABI //[riscv32]~^^^^ ERROR is not a supported ABI //[riscv64]~^^^^^ ERROR is not a supported ABI +fn aapcs_ptr(f: extern "aapcs" fn()) { + //[x64]~^ WARN unsupported_fn_ptr_calling_conventions + //[x64]~^^ WARN this was previously accepted + //[i686]~^^^ WARN unsupported_fn_ptr_calling_conventions + //[i686]~^^^^ WARN this was previously accepted + //[aarch64]~^^^^^ WARN unsupported_fn_ptr_calling_conventions + //[aarch64]~^^^^^^ WARN this was previously accepted + //[riscv32]~^^^^^^^ WARN unsupported_fn_ptr_calling_conventions + //[riscv32]~^^^^^^^^ WARN this was previously accepted + //[riscv64]~^^^^^^^^^ WARN unsupported_fn_ptr_calling_conventions + //[riscv64]~^^^^^^^^^^ WARN this was previously accepted + f() +} +extern "aapcs" {} +//[x64]~^ ERROR is not a supported ABI +//[i686]~^^ ERROR is not a supported ABI +//[aarch64]~^^^ ERROR is not a supported ABI +//[riscv32]~^^^^ ERROR is not a supported ABI +//[riscv64]~^^^^^ ERROR is not a supported ABI + extern "msp430-interrupt" fn msp430() {} //~^ ERROR is not a supported ABI +fn msp430_ptr(f: extern "msp430-interrupt" fn()) { + //~^ WARN unsupported_fn_ptr_calling_conventions + //~^^ WARN this was previously accepted + f() +} +extern "msp430-interrupt" {} +//~^ ERROR is not a supported ABI + extern "avr-interrupt" fn avr() {} //~^ ERROR is not a supported ABI +fn avr_ptr(f: extern "avr-interrupt" fn()) { + //~^ WARN unsupported_fn_ptr_calling_conventions + //~^^ WARN this was previously accepted + f() +} +extern "avr-interrupt" {} +//~^ ERROR is not a supported ABI + extern "riscv-interrupt-m" fn riscv() {} //[arm]~^ ERROR is not a supported ABI //[x64]~^^ ERROR is not a supported ABI //[i686]~^^^ ERROR is not a supported ABI //[aarch64]~^^^^ ERROR is not a supported ABI +fn riscv_ptr(f: extern "riscv-interrupt-m" fn()) { + //[arm]~^ WARN unsupported_fn_ptr_calling_conventions + //[arm]~^^ WARN this was previously accepted + //[x64]~^^^ WARN unsupported_fn_ptr_calling_conventions + //[x64]~^^^^ WARN this was previously accepted + //[i686]~^^^^^ WARN unsupported_fn_ptr_calling_conventions + //[i686]~^^^^^^ WARN this was previously accepted + //[aarch64]~^^^^^^^ WARN unsupported_fn_ptr_calling_conventions + //[aarch64]~^^^^^^^^ WARN this was previously accepted + f() +} +extern "riscv-interrupt-m" {} +//[arm]~^ ERROR is not a supported ABI +//[x64]~^^ ERROR is not a supported ABI +//[i686]~^^^ ERROR is not a supported ABI +//[aarch64]~^^^^ ERROR is not a supported ABI + extern "x86-interrupt" fn x86() {} //[aarch64]~^ ERROR is not a supported ABI //[arm]~^^ ERROR is not a supported ABI //[riscv32]~^^^ ERROR is not a supported ABI //[riscv64]~^^^^ ERROR is not a supported ABI +fn x86_ptr(f: extern "x86-interrupt" fn()) { + //[aarch64]~^ WARN unsupported_fn_ptr_calling_conventions + //[aarch64]~^^ WARN this was previously accepted + //[arm]~^^^ WARN unsupported_fn_ptr_calling_conventions + //[arm]~^^^^ WARN this was previously accepted + //[riscv32]~^^^^^ WARN unsupported_fn_ptr_calling_conventions + //[riscv32]~^^^^^^ WARN this was previously accepted + //[riscv64]~^^^^^^^ WARN unsupported_fn_ptr_calling_conventions + //[riscv64]~^^^^^^^^ WARN this was previously accepted + f() +} +extern "x86-interrupt" {} +//[aarch64]~^ ERROR is not a supported ABI +//[arm]~^^ ERROR is not a supported ABI +//[riscv32]~^^^ ERROR is not a supported ABI +//[riscv64]~^^^^ ERROR is not a supported ABI + extern "thiscall" fn thiscall() {} //[x64]~^ ERROR is not a supported ABI //[arm]~^^ ERROR is not a supported ABI //[aarch64]~^^^ ERROR is not a supported ABI //[riscv32]~^^^^ ERROR is not a supported ABI //[riscv64]~^^^^^ ERROR is not a supported ABI +fn thiscall_ptr(f: extern "thiscall" fn()) { + //[x64]~^ WARN unsupported_fn_ptr_calling_conventions + //[x64]~^^ WARN this was previously accepted + //[arm]~^^^ WARN unsupported_fn_ptr_calling_conventions + //[arm]~^^^^ WARN this was previously accepted + //[aarch64]~^^^^^ WARN unsupported_fn_ptr_calling_conventions + //[aarch64]~^^^^^^ WARN this was previously accepted + //[riscv32]~^^^^^^^ WARN unsupported_fn_ptr_calling_conventions + //[riscv32]~^^^^^^^^ WARN this was previously accepted + //[riscv64]~^^^^^^^^^ WARN unsupported_fn_ptr_calling_conventions + //[riscv64]~^^^^^^^^^^ WARN this was previously accepted + f() +} +extern "thiscall" {} +//[x64]~^ ERROR is not a supported ABI +//[arm]~^^ ERROR is not a supported ABI +//[aarch64]~^^^ ERROR is not a supported ABI +//[riscv32]~^^^^ ERROR is not a supported ABI +//[riscv64]~^^^^^ ERROR is not a supported ABI + extern "stdcall" fn stdcall() {} //[x64]~^ WARN use of calling convention not supported //[x64]~^^ WARN this was previously accepted @@ -64,3 +166,33 @@ extern "stdcall" fn stdcall() {} //[riscv32]~^^^^^^^^ WARN this was previously accepted //[riscv64]~^^^^^^^^^ WARN use of calling convention not supported //[riscv64]~^^^^^^^^^^ WARN this was previously accepted +fn stdcall_ptr(f: extern "stdcall" fn()) { + //[x64]~^ WARN unsupported_fn_ptr_calling_conventions + //[x64]~^^ WARN this was previously accepted + //[arm]~^^^ WARN unsupported_fn_ptr_calling_conventions + //[arm]~^^^^ WARN this was previously accepted + //[aarch64]~^^^^^ WARN unsupported_fn_ptr_calling_conventions + //[aarch64]~^^^^^^ WARN this was previously accepted + //[riscv32]~^^^^^^^ WARN unsupported_fn_ptr_calling_conventions + //[riscv32]~^^^^^^^^ WARN this was previously accepted + //[riscv64]~^^^^^^^^^ WARN unsupported_fn_ptr_calling_conventions + //[riscv64]~^^^^^^^^^^ WARN this was previously accepted + f() +} +extern "stdcall" {} +//[x64]~^ WARN use of calling convention not supported +//[x64]~^^ WARN this was previously accepted +//[arm]~^^^ WARN use of calling convention not supported +//[arm]~^^^^ WARN this was previously accepted +//[aarch64]~^^^^^ WARN use of calling convention not supported +//[aarch64]~^^^^^^ WARN this was previously accepted +//[riscv32]~^^^^^^^ WARN use of calling convention not supported +//[riscv32]~^^^^^^^^ WARN this was previously accepted +//[riscv64]~^^^^^^^^^ WARN use of calling convention not supported +//[riscv64]~^^^^^^^^^^ WARN this was previously accepted + +fn cmse_ptr(f: extern "C-cmse-nonsecure-call" fn()) { + //~^ WARN unsupported_fn_ptr_calling_conventions + //~^^ WARN this was previously accepted + f() +} diff --git a/tests/ui/abi/unsupported.x64.stderr b/tests/ui/abi/unsupported.x64.stderr index 7b918a948d3..6f8c56fdfb1 100644 --- a/tests/ui/abi/unsupported.x64.stderr +++ b/tests/ui/abi/unsupported.x64.stderr @@ -1,49 +1,167 @@ +warning: use of calling convention not supported on this target on function pointer + --> $DIR/unsupported.rs:34:15 + | +LL | fn ptx_ptr(f: extern "ptx-kernel" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #130260 + = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default + error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:28:1 + --> $DIR/unsupported.rs:39:1 + | +LL | extern "ptx-kernel" {} + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of calling convention not supported on this target on function pointer + --> $DIR/unsupported.rs:48:17 + | +LL | fn aapcs_ptr(f: extern "aapcs" fn()) { + | ^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #130260 + +error[E0570]: `"aapcs"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:61:1 + | +LL | extern "aapcs" {} + | ^^^^^^^^^^^^^^^^^ + +warning: use of calling convention not supported on this target on function pointer + --> $DIR/unsupported.rs:70:18 + | +LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #130260 + +error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:75:1 + | +LL | extern "msp430-interrupt" {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of calling convention not supported on this target on function pointer + --> $DIR/unsupported.rs:80:15 + | +LL | fn avr_ptr(f: extern "avr-interrupt" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #130260 + +error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:85:1 + | +LL | extern "avr-interrupt" {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of calling convention not supported on this target on function pointer + --> $DIR/unsupported.rs:93:17 + | +LL | fn riscv_ptr(f: extern "riscv-interrupt-m" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #130260 + +error[E0570]: `"riscv-interrupt-m"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:104:1 + | +LL | extern "riscv-interrupt-m" {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of calling convention not supported on this target on function pointer + --> $DIR/unsupported.rs:138:20 + | +LL | fn thiscall_ptr(f: extern "thiscall" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #130260 + +error[E0570]: `"thiscall"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:151:1 + | +LL | extern "thiscall" {} + | ^^^^^^^^^^^^^^^^^^^^ + +warning: use of calling convention not supported on this target on function pointer + --> $DIR/unsupported.rs:169:19 + | +LL | fn stdcall_ptr(f: extern "stdcall" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #130260 + +warning: use of calling convention not supported on this target + --> $DIR/unsupported.rs:182:1 + | +LL | extern "stdcall" {} + | ^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #87678 + = note: `#[warn(unsupported_calling_conventions)]` on by default + +warning: use of calling convention not supported on this target on function pointer + --> $DIR/unsupported.rs:194:16 + | +LL | fn cmse_ptr(f: extern "C-cmse-nonsecure-call" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #130260 + +error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:32:1 | LL | extern "ptx-kernel" fn ptx() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"aapcs"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:30:1 + --> $DIR/unsupported.rs:42:1 | LL | extern "aapcs" fn aapcs() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:36:1 + --> $DIR/unsupported.rs:68:1 | LL | extern "msp430-interrupt" fn msp430() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:38:1 + --> $DIR/unsupported.rs:78:1 | LL | extern "avr-interrupt" fn avr() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"riscv-interrupt-m"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:40:1 + --> $DIR/unsupported.rs:88:1 | LL | extern "riscv-interrupt-m" fn riscv() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"thiscall"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:50:1 + --> $DIR/unsupported.rs:132:1 | LL | extern "thiscall" fn thiscall() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of calling convention not supported on this target - --> $DIR/unsupported.rs:56:1 + --> $DIR/unsupported.rs:158:1 | LL | extern "stdcall" fn stdcall() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #87678 - = note: `#[warn(unsupported_calling_conventions)]` on by default -error: aborting due to 6 previous errors; 1 warning emitted +error: aborting due to 12 previous errors; 10 warnings emitted For more information about this error, try `rustc --explain E0570`. diff --git a/tests/ui/c-variadic/feature-gate-extended_varargs_abi_support.rs b/tests/ui/c-variadic/feature-gate-extended_varargs_abi_support.rs index fce6210b2f4..d47a8e085fd 100644 --- a/tests/ui/c-variadic/feature-gate-extended_varargs_abi_support.rs +++ b/tests/ui/c-variadic/feature-gate-extended_varargs_abi_support.rs @@ -1,3 +1,5 @@ +//@ only-x86_64 + fn efiapi(f: extern "efiapi" fn(usize, ...)) { //~^ ERROR: C-variadic function must have a compatible calling convention, like `C` or `cdecl` //~^^ ERROR: using calling conventions other than `C` or `cdecl` for varargs functions is unstable diff --git a/tests/ui/c-variadic/feature-gate-extended_varargs_abi_support.stderr b/tests/ui/c-variadic/feature-gate-extended_varargs_abi_support.stderr index 94e9628f0f0..41be3784245 100644 --- a/tests/ui/c-variadic/feature-gate-extended_varargs_abi_support.stderr +++ b/tests/ui/c-variadic/feature-gate-extended_varargs_abi_support.stderr @@ -1,5 +1,5 @@ error[E0658]: using calling conventions other than `C` or `cdecl` for varargs functions is unstable - --> $DIR/feature-gate-extended_varargs_abi_support.rs:1:14 + --> $DIR/feature-gate-extended_varargs_abi_support.rs:3:14 | LL | fn efiapi(f: extern "efiapi" fn(usize, ...)) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -9,13 +9,13 @@ LL | fn efiapi(f: extern "efiapi" fn(usize, ...)) { = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0045]: C-variadic function must have a compatible calling convention, like `C` or `cdecl` - --> $DIR/feature-gate-extended_varargs_abi_support.rs:1:14 + --> $DIR/feature-gate-extended_varargs_abi_support.rs:3:14 | LL | fn efiapi(f: extern "efiapi" fn(usize, ...)) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C-variadic function must have a compatible calling convention error[E0658]: using calling conventions other than `C` or `cdecl` for varargs functions is unstable - --> $DIR/feature-gate-extended_varargs_abi_support.rs:6:12 + --> $DIR/feature-gate-extended_varargs_abi_support.rs:8:12 | LL | fn sysv(f: extern "sysv64" fn(usize, ...)) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -25,13 +25,13 @@ LL | fn sysv(f: extern "sysv64" fn(usize, ...)) { = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0045]: C-variadic function must have a compatible calling convention, like `C` or `cdecl` - --> $DIR/feature-gate-extended_varargs_abi_support.rs:6:12 + --> $DIR/feature-gate-extended_varargs_abi_support.rs:8:12 | LL | fn sysv(f: extern "sysv64" fn(usize, ...)) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C-variadic function must have a compatible calling convention error[E0658]: using calling conventions other than `C` or `cdecl` for varargs functions is unstable - --> $DIR/feature-gate-extended_varargs_abi_support.rs:11:11 + --> $DIR/feature-gate-extended_varargs_abi_support.rs:13:11 | LL | fn win(f: extern "win64" fn(usize, ...)) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -41,7 +41,7 @@ LL | fn win(f: extern "win64" fn(usize, ...)) { = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0045]: C-variadic function must have a compatible calling convention, like `C` or `cdecl` - --> $DIR/feature-gate-extended_varargs_abi_support.rs:11:11 + --> $DIR/feature-gate-extended_varargs_abi_support.rs:13:11 | LL | fn win(f: extern "win64" fn(usize, ...)) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C-variadic function must have a compatible calling convention diff --git a/tests/ui/c-variadic/variadic-ffi-2-arm.rs b/tests/ui/c-variadic/variadic-ffi-2-arm.rs new file mode 100644 index 00000000000..3b0a71007a0 --- /dev/null +++ b/tests/ui/c-variadic/variadic-ffi-2-arm.rs @@ -0,0 +1,9 @@ +//@ only-arm +//@ build-pass +#![feature(extended_varargs_abi_support)] + +fn aapcs(f: extern "aapcs" fn(usize, ...)) { + f(22, 44); +} + +fn main() {} diff --git a/tests/ui/c-variadic/variadic-ffi-2.rs b/tests/ui/c-variadic/variadic-ffi-2.rs index a7261ebe936..bafb7e2b20c 100644 --- a/tests/ui/c-variadic/variadic-ffi-2.rs +++ b/tests/ui/c-variadic/variadic-ffi-2.rs @@ -1,6 +1,7 @@ //@ ignore-arm stdcall isn't supported #![feature(extended_varargs_abi_support)] +#[allow(unsupported_fn_ptr_calling_conventions)] fn baz(f: extern "stdcall" fn(usize, ...)) { //~^ ERROR: C-variadic function must have a compatible calling convention, // like C, cdecl, system, aapcs, win64, sysv64 or efiapi @@ -10,15 +11,22 @@ fn baz(f: extern "stdcall" fn(usize, ...)) { fn system(f: extern "system" fn(usize, ...)) { f(22, 44); } -fn aapcs(f: extern "aapcs" fn(usize, ...)) { - f(22, 44); -} +#[cfg(target_arch = "x86_64")] fn sysv(f: extern "sysv64" fn(usize, ...)) { f(22, 44); } +#[cfg(target_arch = "x86_64")] fn win(f: extern "win64" fn(usize, ...)) { f(22, 44); } +#[cfg(any( + target_arch = "arm", + target_arch = "aarch64", + target_arch = "riscv32", + target_arch = "riscv64", + target_arch = "x86", + target_arch = "x86_64" +))] fn efiapi(f: extern "efiapi" fn(usize, ...)) { f(22, 44); } diff --git a/tests/ui/c-variadic/variadic-ffi-2.stderr b/tests/ui/c-variadic/variadic-ffi-2.stderr index fbf273b1f1d..e52de93a926 100644 --- a/tests/ui/c-variadic/variadic-ffi-2.stderr +++ b/tests/ui/c-variadic/variadic-ffi-2.stderr @@ -1,5 +1,5 @@ error[E0045]: C-variadic function must have a compatible calling convention, like `C`, `cdecl`, `system`, `aapcs`, `win64`, `sysv64` or `efiapi` - --> $DIR/variadic-ffi-2.rs:4:11 + --> $DIR/variadic-ffi-2.rs:5:11 | LL | fn baz(f: extern "stdcall" fn(usize, ...)) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C-variadic function must have a compatible calling convention diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/gate_test.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/gate_test.rs index e05dbf3bbc4..2d0ed5d2a30 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/gate_test.rs +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/gate_test.rs @@ -1,8 +1,9 @@ // gate-test-abi_c_cmse_nonsecure_call +#[allow(unsupported_fn_ptr_calling_conventions)] fn main() { let non_secure_function = unsafe { core::mem::transmute:: i32>( - //~^ ERROR [E0658] + //~^ ERROR [E0658] 0x10000004, ) }; diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/gate_test.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/gate_test.stderr index 64e9b7cc639..120d5cc5293 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/gate_test.stderr +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/gate_test.stderr @@ -1,5 +1,5 @@ error[E0658]: C-cmse-nonsecure-call ABI is experimental and subject to change - --> $DIR/gate_test.rs:4:46 + --> $DIR/gate_test.rs:5:46 | LL | core::mem::transmute:: i32>( | ^^^^^^^^^^^^^^^^^^^^^^^ From 867e776fa6220b17963c34b572fb3c8aa0ace2a3 Mon Sep 17 00:00:00 2001 From: Tamme Dittrich Date: Mon, 23 Sep 2024 14:15:20 +0200 Subject: [PATCH 009/357] Also cover the new `extern "C-cmse-nonsecure-entry"` in tests --- tests/ui/abi/unsupported.aarch64.stderr | 77 ++++++++++++++++--------- tests/ui/abi/unsupported.arm.stderr | 71 +++++++++++++++-------- tests/ui/abi/unsupported.i686.stderr | 59 +++++++++++++------ tests/ui/abi/unsupported.riscv32.stderr | 71 +++++++++++++++-------- tests/ui/abi/unsupported.riscv64.stderr | 71 +++++++++++++++-------- tests/ui/abi/unsupported.rs | 15 ++++- tests/ui/abi/unsupported.x64.stderr | 71 +++++++++++++++-------- 7 files changed, 286 insertions(+), 149 deletions(-) diff --git a/tests/ui/abi/unsupported.aarch64.stderr b/tests/ui/abi/unsupported.aarch64.stderr index 67db139ac64..00a5b4b2ee1 100644 --- a/tests/ui/abi/unsupported.aarch64.stderr +++ b/tests/ui/abi/unsupported.aarch64.stderr @@ -1,5 +1,5 @@ warning: use of calling convention not supported on this target on function pointer - --> $DIR/unsupported.rs:34:15 + --> $DIR/unsupported.rs:35:15 | LL | fn ptx_ptr(f: extern "ptx-kernel" fn()) { | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -9,13 +9,13 @@ LL | fn ptx_ptr(f: extern "ptx-kernel" fn()) { = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:39:1 + --> $DIR/unsupported.rs:40:1 | LL | extern "ptx-kernel" {} | ^^^^^^^^^^^^^^^^^^^^^^ warning: use of calling convention not supported on this target on function pointer - --> $DIR/unsupported.rs:48:17 + --> $DIR/unsupported.rs:49:17 | LL | fn aapcs_ptr(f: extern "aapcs" fn()) { | ^^^^^^^^^^^^^^^^^^^ @@ -24,13 +24,13 @@ LL | fn aapcs_ptr(f: extern "aapcs" fn()) { = note: for more information, see issue #130260 error[E0570]: `"aapcs"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:61:1 + --> $DIR/unsupported.rs:62:1 | LL | extern "aapcs" {} | ^^^^^^^^^^^^^^^^^ warning: use of calling convention not supported on this target on function pointer - --> $DIR/unsupported.rs:70:18 + --> $DIR/unsupported.rs:71:18 | LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -39,13 +39,13 @@ LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) { = note: for more information, see issue #130260 error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:75:1 + --> $DIR/unsupported.rs:76:1 | LL | extern "msp430-interrupt" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of calling convention not supported on this target on function pointer - --> $DIR/unsupported.rs:80:15 + --> $DIR/unsupported.rs:81:15 | LL | fn avr_ptr(f: extern "avr-interrupt" fn()) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -54,13 +54,13 @@ LL | fn avr_ptr(f: extern "avr-interrupt" fn()) { = note: for more information, see issue #130260 error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:85:1 + --> $DIR/unsupported.rs:86:1 | LL | extern "avr-interrupt" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of calling convention not supported on this target on function pointer - --> $DIR/unsupported.rs:93:17 + --> $DIR/unsupported.rs:94:17 | LL | fn riscv_ptr(f: extern "riscv-interrupt-m" fn()) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -69,13 +69,13 @@ LL | fn riscv_ptr(f: extern "riscv-interrupt-m" fn()) { = note: for more information, see issue #130260 error[E0570]: `"riscv-interrupt-m"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:104:1 + --> $DIR/unsupported.rs:105:1 | LL | extern "riscv-interrupt-m" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of calling convention not supported on this target on function pointer - --> $DIR/unsupported.rs:115:15 + --> $DIR/unsupported.rs:116:15 | LL | fn x86_ptr(f: extern "x86-interrupt" fn()) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -84,13 +84,13 @@ LL | fn x86_ptr(f: extern "x86-interrupt" fn()) { = note: for more information, see issue #130260 error[E0570]: `"x86-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:126:1 + --> $DIR/unsupported.rs:127:1 | LL | extern "x86-interrupt" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of calling convention not supported on this target on function pointer - --> $DIR/unsupported.rs:138:20 + --> $DIR/unsupported.rs:139:20 | LL | fn thiscall_ptr(f: extern "thiscall" fn()) { | ^^^^^^^^^^^^^^^^^^^^^^ @@ -99,13 +99,13 @@ LL | fn thiscall_ptr(f: extern "thiscall" fn()) { = note: for more information, see issue #130260 error[E0570]: `"thiscall"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:151:1 + --> $DIR/unsupported.rs:152:1 | LL | extern "thiscall" {} | ^^^^^^^^^^^^^^^^^^^^ warning: use of calling convention not supported on this target on function pointer - --> $DIR/unsupported.rs:169:19 + --> $DIR/unsupported.rs:170:19 | LL | fn stdcall_ptr(f: extern "stdcall" fn()) { | ^^^^^^^^^^^^^^^^^^^^^ @@ -114,7 +114,7 @@ LL | fn stdcall_ptr(f: extern "stdcall" fn()) { = note: for more information, see issue #130260 warning: use of calling convention not supported on this target - --> $DIR/unsupported.rs:182:1 + --> $DIR/unsupported.rs:183:1 | LL | extern "stdcall" {} | ^^^^^^^^^^^^^^^^^^^ @@ -124,58 +124,73 @@ LL | extern "stdcall" {} = note: `#[warn(unsupported_calling_conventions)]` on by default warning: use of calling convention not supported on this target on function pointer - --> $DIR/unsupported.rs:194:16 + --> $DIR/unsupported.rs:195:21 | -LL | fn cmse_ptr(f: extern "C-cmse-nonsecure-call" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn cmse_call_ptr(f: extern "C-cmse-nonsecure-call" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #130260 +warning: use of calling convention not supported on this target on function pointer + --> $DIR/unsupported.rs:203:22 + | +LL | fn cmse_entry_ptr(f: extern "C-cmse-nonsecure-entry" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #130260 + +error[E0570]: `"C-cmse-nonsecure-entry"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:208:1 + | +LL | extern "C-cmse-nonsecure-entry" {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:32:1 + --> $DIR/unsupported.rs:33:1 | LL | extern "ptx-kernel" fn ptx() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"aapcs"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:42:1 + --> $DIR/unsupported.rs:43:1 | LL | extern "aapcs" fn aapcs() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:68:1 + --> $DIR/unsupported.rs:69:1 | LL | extern "msp430-interrupt" fn msp430() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:78:1 + --> $DIR/unsupported.rs:79:1 | LL | extern "avr-interrupt" fn avr() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"riscv-interrupt-m"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:88:1 + --> $DIR/unsupported.rs:89:1 | LL | extern "riscv-interrupt-m" fn riscv() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"x86-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:110:1 + --> $DIR/unsupported.rs:111:1 | LL | extern "x86-interrupt" fn x86() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"thiscall"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:132:1 + --> $DIR/unsupported.rs:133:1 | LL | extern "thiscall" fn thiscall() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of calling convention not supported on this target - --> $DIR/unsupported.rs:158:1 + --> $DIR/unsupported.rs:159:1 | LL | extern "stdcall" fn stdcall() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -183,6 +198,12 @@ LL | extern "stdcall" fn stdcall() {} = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #87678 -error: aborting due to 14 previous errors; 11 warnings emitted +error[E0570]: `"C-cmse-nonsecure-entry"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:201:1 + | +LL | extern "C-cmse-nonsecure-entry" fn cmse_entry() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 16 previous errors; 12 warnings emitted For more information about this error, try `rustc --explain E0570`. diff --git a/tests/ui/abi/unsupported.arm.stderr b/tests/ui/abi/unsupported.arm.stderr index 90f0cf709f2..dfb5ceb0c33 100644 --- a/tests/ui/abi/unsupported.arm.stderr +++ b/tests/ui/abi/unsupported.arm.stderr @@ -1,5 +1,5 @@ warning: use of calling convention not supported on this target on function pointer - --> $DIR/unsupported.rs:34:15 + --> $DIR/unsupported.rs:35:15 | LL | fn ptx_ptr(f: extern "ptx-kernel" fn()) { | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -9,13 +9,13 @@ LL | fn ptx_ptr(f: extern "ptx-kernel" fn()) { = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:39:1 + --> $DIR/unsupported.rs:40:1 | LL | extern "ptx-kernel" {} | ^^^^^^^^^^^^^^^^^^^^^^ warning: use of calling convention not supported on this target on function pointer - --> $DIR/unsupported.rs:70:18 + --> $DIR/unsupported.rs:71:18 | LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -24,13 +24,13 @@ LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) { = note: for more information, see issue #130260 error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:75:1 + --> $DIR/unsupported.rs:76:1 | LL | extern "msp430-interrupt" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of calling convention not supported on this target on function pointer - --> $DIR/unsupported.rs:80:15 + --> $DIR/unsupported.rs:81:15 | LL | fn avr_ptr(f: extern "avr-interrupt" fn()) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -39,13 +39,13 @@ LL | fn avr_ptr(f: extern "avr-interrupt" fn()) { = note: for more information, see issue #130260 error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:85:1 + --> $DIR/unsupported.rs:86:1 | LL | extern "avr-interrupt" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of calling convention not supported on this target on function pointer - --> $DIR/unsupported.rs:93:17 + --> $DIR/unsupported.rs:94:17 | LL | fn riscv_ptr(f: extern "riscv-interrupt-m" fn()) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -54,13 +54,13 @@ LL | fn riscv_ptr(f: extern "riscv-interrupt-m" fn()) { = note: for more information, see issue #130260 error[E0570]: `"riscv-interrupt-m"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:104:1 + --> $DIR/unsupported.rs:105:1 | LL | extern "riscv-interrupt-m" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of calling convention not supported on this target on function pointer - --> $DIR/unsupported.rs:115:15 + --> $DIR/unsupported.rs:116:15 | LL | fn x86_ptr(f: extern "x86-interrupt" fn()) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -69,13 +69,13 @@ LL | fn x86_ptr(f: extern "x86-interrupt" fn()) { = note: for more information, see issue #130260 error[E0570]: `"x86-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:126:1 + --> $DIR/unsupported.rs:127:1 | LL | extern "x86-interrupt" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of calling convention not supported on this target on function pointer - --> $DIR/unsupported.rs:138:20 + --> $DIR/unsupported.rs:139:20 | LL | fn thiscall_ptr(f: extern "thiscall" fn()) { | ^^^^^^^^^^^^^^^^^^^^^^ @@ -84,13 +84,13 @@ LL | fn thiscall_ptr(f: extern "thiscall" fn()) { = note: for more information, see issue #130260 error[E0570]: `"thiscall"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:151:1 + --> $DIR/unsupported.rs:152:1 | LL | extern "thiscall" {} | ^^^^^^^^^^^^^^^^^^^^ warning: use of calling convention not supported on this target on function pointer - --> $DIR/unsupported.rs:169:19 + --> $DIR/unsupported.rs:170:19 | LL | fn stdcall_ptr(f: extern "stdcall" fn()) { | ^^^^^^^^^^^^^^^^^^^^^ @@ -99,7 +99,7 @@ LL | fn stdcall_ptr(f: extern "stdcall" fn()) { = note: for more information, see issue #130260 warning: use of calling convention not supported on this target - --> $DIR/unsupported.rs:182:1 + --> $DIR/unsupported.rs:183:1 | LL | extern "stdcall" {} | ^^^^^^^^^^^^^^^^^^^ @@ -109,52 +109,67 @@ LL | extern "stdcall" {} = note: `#[warn(unsupported_calling_conventions)]` on by default warning: use of calling convention not supported on this target on function pointer - --> $DIR/unsupported.rs:194:16 + --> $DIR/unsupported.rs:195:21 | -LL | fn cmse_ptr(f: extern "C-cmse-nonsecure-call" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn cmse_call_ptr(f: extern "C-cmse-nonsecure-call" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #130260 +warning: use of calling convention not supported on this target on function pointer + --> $DIR/unsupported.rs:203:22 + | +LL | fn cmse_entry_ptr(f: extern "C-cmse-nonsecure-entry" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #130260 + +error[E0570]: `"C-cmse-nonsecure-entry"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:208:1 + | +LL | extern "C-cmse-nonsecure-entry" {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:32:1 + --> $DIR/unsupported.rs:33:1 | LL | extern "ptx-kernel" fn ptx() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:68:1 + --> $DIR/unsupported.rs:69:1 | LL | extern "msp430-interrupt" fn msp430() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:78:1 + --> $DIR/unsupported.rs:79:1 | LL | extern "avr-interrupt" fn avr() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"riscv-interrupt-m"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:88:1 + --> $DIR/unsupported.rs:89:1 | LL | extern "riscv-interrupt-m" fn riscv() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"x86-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:110:1 + --> $DIR/unsupported.rs:111:1 | LL | extern "x86-interrupt" fn x86() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"thiscall"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:132:1 + --> $DIR/unsupported.rs:133:1 | LL | extern "thiscall" fn thiscall() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of calling convention not supported on this target - --> $DIR/unsupported.rs:158:1 + --> $DIR/unsupported.rs:159:1 | LL | extern "stdcall" fn stdcall() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -162,6 +177,12 @@ LL | extern "stdcall" fn stdcall() {} = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #87678 -error: aborting due to 12 previous errors; 10 warnings emitted +error[E0570]: `"C-cmse-nonsecure-entry"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:201:1 + | +LL | extern "C-cmse-nonsecure-entry" fn cmse_entry() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 14 previous errors; 11 warnings emitted For more information about this error, try `rustc --explain E0570`. diff --git a/tests/ui/abi/unsupported.i686.stderr b/tests/ui/abi/unsupported.i686.stderr index 67e3100d419..6537ce66057 100644 --- a/tests/ui/abi/unsupported.i686.stderr +++ b/tests/ui/abi/unsupported.i686.stderr @@ -1,5 +1,5 @@ warning: use of calling convention not supported on this target on function pointer - --> $DIR/unsupported.rs:34:15 + --> $DIR/unsupported.rs:35:15 | LL | fn ptx_ptr(f: extern "ptx-kernel" fn()) { | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -9,13 +9,13 @@ LL | fn ptx_ptr(f: extern "ptx-kernel" fn()) { = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:39:1 + --> $DIR/unsupported.rs:40:1 | LL | extern "ptx-kernel" {} | ^^^^^^^^^^^^^^^^^^^^^^ warning: use of calling convention not supported on this target on function pointer - --> $DIR/unsupported.rs:48:17 + --> $DIR/unsupported.rs:49:17 | LL | fn aapcs_ptr(f: extern "aapcs" fn()) { | ^^^^^^^^^^^^^^^^^^^ @@ -24,13 +24,13 @@ LL | fn aapcs_ptr(f: extern "aapcs" fn()) { = note: for more information, see issue #130260 error[E0570]: `"aapcs"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:61:1 + --> $DIR/unsupported.rs:62:1 | LL | extern "aapcs" {} | ^^^^^^^^^^^^^^^^^ warning: use of calling convention not supported on this target on function pointer - --> $DIR/unsupported.rs:70:18 + --> $DIR/unsupported.rs:71:18 | LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -39,13 +39,13 @@ LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) { = note: for more information, see issue #130260 error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:75:1 + --> $DIR/unsupported.rs:76:1 | LL | extern "msp430-interrupt" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of calling convention not supported on this target on function pointer - --> $DIR/unsupported.rs:80:15 + --> $DIR/unsupported.rs:81:15 | LL | fn avr_ptr(f: extern "avr-interrupt" fn()) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -54,13 +54,13 @@ LL | fn avr_ptr(f: extern "avr-interrupt" fn()) { = note: for more information, see issue #130260 error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:85:1 + --> $DIR/unsupported.rs:86:1 | LL | extern "avr-interrupt" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of calling convention not supported on this target on function pointer - --> $DIR/unsupported.rs:93:17 + --> $DIR/unsupported.rs:94:17 | LL | fn riscv_ptr(f: extern "riscv-interrupt-m" fn()) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -69,50 +69,71 @@ LL | fn riscv_ptr(f: extern "riscv-interrupt-m" fn()) { = note: for more information, see issue #130260 error[E0570]: `"riscv-interrupt-m"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:104:1 + --> $DIR/unsupported.rs:105:1 | LL | extern "riscv-interrupt-m" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of calling convention not supported on this target on function pointer - --> $DIR/unsupported.rs:194:16 + --> $DIR/unsupported.rs:195:21 | -LL | fn cmse_ptr(f: extern "C-cmse-nonsecure-call" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn cmse_call_ptr(f: extern "C-cmse-nonsecure-call" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #130260 +warning: use of calling convention not supported on this target on function pointer + --> $DIR/unsupported.rs:203:22 + | +LL | fn cmse_entry_ptr(f: extern "C-cmse-nonsecure-entry" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #130260 + +error[E0570]: `"C-cmse-nonsecure-entry"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:208:1 + | +LL | extern "C-cmse-nonsecure-entry" {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:32:1 + --> $DIR/unsupported.rs:33:1 | LL | extern "ptx-kernel" fn ptx() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"aapcs"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:42:1 + --> $DIR/unsupported.rs:43:1 | LL | extern "aapcs" fn aapcs() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:68:1 + --> $DIR/unsupported.rs:69:1 | LL | extern "msp430-interrupt" fn msp430() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:78:1 + --> $DIR/unsupported.rs:79:1 | LL | extern "avr-interrupt" fn avr() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"riscv-interrupt-m"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:88:1 + --> $DIR/unsupported.rs:89:1 | LL | extern "riscv-interrupt-m" fn riscv() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 10 previous errors; 6 warnings emitted +error[E0570]: `"C-cmse-nonsecure-entry"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:201:1 + | +LL | extern "C-cmse-nonsecure-entry" fn cmse_entry() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 12 previous errors; 7 warnings emitted For more information about this error, try `rustc --explain E0570`. diff --git a/tests/ui/abi/unsupported.riscv32.stderr b/tests/ui/abi/unsupported.riscv32.stderr index 683c343eeef..a53f85f28bc 100644 --- a/tests/ui/abi/unsupported.riscv32.stderr +++ b/tests/ui/abi/unsupported.riscv32.stderr @@ -1,5 +1,5 @@ warning: use of calling convention not supported on this target on function pointer - --> $DIR/unsupported.rs:34:15 + --> $DIR/unsupported.rs:35:15 | LL | fn ptx_ptr(f: extern "ptx-kernel" fn()) { | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -9,13 +9,13 @@ LL | fn ptx_ptr(f: extern "ptx-kernel" fn()) { = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:39:1 + --> $DIR/unsupported.rs:40:1 | LL | extern "ptx-kernel" {} | ^^^^^^^^^^^^^^^^^^^^^^ warning: use of calling convention not supported on this target on function pointer - --> $DIR/unsupported.rs:48:17 + --> $DIR/unsupported.rs:49:17 | LL | fn aapcs_ptr(f: extern "aapcs" fn()) { | ^^^^^^^^^^^^^^^^^^^ @@ -24,13 +24,13 @@ LL | fn aapcs_ptr(f: extern "aapcs" fn()) { = note: for more information, see issue #130260 error[E0570]: `"aapcs"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:61:1 + --> $DIR/unsupported.rs:62:1 | LL | extern "aapcs" {} | ^^^^^^^^^^^^^^^^^ warning: use of calling convention not supported on this target on function pointer - --> $DIR/unsupported.rs:70:18 + --> $DIR/unsupported.rs:71:18 | LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -39,13 +39,13 @@ LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) { = note: for more information, see issue #130260 error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:75:1 + --> $DIR/unsupported.rs:76:1 | LL | extern "msp430-interrupt" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of calling convention not supported on this target on function pointer - --> $DIR/unsupported.rs:80:15 + --> $DIR/unsupported.rs:81:15 | LL | fn avr_ptr(f: extern "avr-interrupt" fn()) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -54,13 +54,13 @@ LL | fn avr_ptr(f: extern "avr-interrupt" fn()) { = note: for more information, see issue #130260 error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:85:1 + --> $DIR/unsupported.rs:86:1 | LL | extern "avr-interrupt" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of calling convention not supported on this target on function pointer - --> $DIR/unsupported.rs:115:15 + --> $DIR/unsupported.rs:116:15 | LL | fn x86_ptr(f: extern "x86-interrupt" fn()) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -69,13 +69,13 @@ LL | fn x86_ptr(f: extern "x86-interrupt" fn()) { = note: for more information, see issue #130260 error[E0570]: `"x86-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:126:1 + --> $DIR/unsupported.rs:127:1 | LL | extern "x86-interrupt" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of calling convention not supported on this target on function pointer - --> $DIR/unsupported.rs:138:20 + --> $DIR/unsupported.rs:139:20 | LL | fn thiscall_ptr(f: extern "thiscall" fn()) { | ^^^^^^^^^^^^^^^^^^^^^^ @@ -84,13 +84,13 @@ LL | fn thiscall_ptr(f: extern "thiscall" fn()) { = note: for more information, see issue #130260 error[E0570]: `"thiscall"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:151:1 + --> $DIR/unsupported.rs:152:1 | LL | extern "thiscall" {} | ^^^^^^^^^^^^^^^^^^^^ warning: use of calling convention not supported on this target on function pointer - --> $DIR/unsupported.rs:169:19 + --> $DIR/unsupported.rs:170:19 | LL | fn stdcall_ptr(f: extern "stdcall" fn()) { | ^^^^^^^^^^^^^^^^^^^^^ @@ -99,7 +99,7 @@ LL | fn stdcall_ptr(f: extern "stdcall" fn()) { = note: for more information, see issue #130260 warning: use of calling convention not supported on this target - --> $DIR/unsupported.rs:182:1 + --> $DIR/unsupported.rs:183:1 | LL | extern "stdcall" {} | ^^^^^^^^^^^^^^^^^^^ @@ -109,52 +109,67 @@ LL | extern "stdcall" {} = note: `#[warn(unsupported_calling_conventions)]` on by default warning: use of calling convention not supported on this target on function pointer - --> $DIR/unsupported.rs:194:16 + --> $DIR/unsupported.rs:195:21 | -LL | fn cmse_ptr(f: extern "C-cmse-nonsecure-call" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn cmse_call_ptr(f: extern "C-cmse-nonsecure-call" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #130260 +warning: use of calling convention not supported on this target on function pointer + --> $DIR/unsupported.rs:203:22 + | +LL | fn cmse_entry_ptr(f: extern "C-cmse-nonsecure-entry" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #130260 + +error[E0570]: `"C-cmse-nonsecure-entry"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:208:1 + | +LL | extern "C-cmse-nonsecure-entry" {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:32:1 + --> $DIR/unsupported.rs:33:1 | LL | extern "ptx-kernel" fn ptx() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"aapcs"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:42:1 + --> $DIR/unsupported.rs:43:1 | LL | extern "aapcs" fn aapcs() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:68:1 + --> $DIR/unsupported.rs:69:1 | LL | extern "msp430-interrupt" fn msp430() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:78:1 + --> $DIR/unsupported.rs:79:1 | LL | extern "avr-interrupt" fn avr() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"x86-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:110:1 + --> $DIR/unsupported.rs:111:1 | LL | extern "x86-interrupt" fn x86() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"thiscall"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:132:1 + --> $DIR/unsupported.rs:133:1 | LL | extern "thiscall" fn thiscall() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of calling convention not supported on this target - --> $DIR/unsupported.rs:158:1 + --> $DIR/unsupported.rs:159:1 | LL | extern "stdcall" fn stdcall() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -162,6 +177,12 @@ LL | extern "stdcall" fn stdcall() {} = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #87678 -error: aborting due to 12 previous errors; 10 warnings emitted +error[E0570]: `"C-cmse-nonsecure-entry"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:201:1 + | +LL | extern "C-cmse-nonsecure-entry" fn cmse_entry() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 14 previous errors; 11 warnings emitted For more information about this error, try `rustc --explain E0570`. diff --git a/tests/ui/abi/unsupported.riscv64.stderr b/tests/ui/abi/unsupported.riscv64.stderr index 683c343eeef..a53f85f28bc 100644 --- a/tests/ui/abi/unsupported.riscv64.stderr +++ b/tests/ui/abi/unsupported.riscv64.stderr @@ -1,5 +1,5 @@ warning: use of calling convention not supported on this target on function pointer - --> $DIR/unsupported.rs:34:15 + --> $DIR/unsupported.rs:35:15 | LL | fn ptx_ptr(f: extern "ptx-kernel" fn()) { | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -9,13 +9,13 @@ LL | fn ptx_ptr(f: extern "ptx-kernel" fn()) { = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:39:1 + --> $DIR/unsupported.rs:40:1 | LL | extern "ptx-kernel" {} | ^^^^^^^^^^^^^^^^^^^^^^ warning: use of calling convention not supported on this target on function pointer - --> $DIR/unsupported.rs:48:17 + --> $DIR/unsupported.rs:49:17 | LL | fn aapcs_ptr(f: extern "aapcs" fn()) { | ^^^^^^^^^^^^^^^^^^^ @@ -24,13 +24,13 @@ LL | fn aapcs_ptr(f: extern "aapcs" fn()) { = note: for more information, see issue #130260 error[E0570]: `"aapcs"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:61:1 + --> $DIR/unsupported.rs:62:1 | LL | extern "aapcs" {} | ^^^^^^^^^^^^^^^^^ warning: use of calling convention not supported on this target on function pointer - --> $DIR/unsupported.rs:70:18 + --> $DIR/unsupported.rs:71:18 | LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -39,13 +39,13 @@ LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) { = note: for more information, see issue #130260 error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:75:1 + --> $DIR/unsupported.rs:76:1 | LL | extern "msp430-interrupt" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of calling convention not supported on this target on function pointer - --> $DIR/unsupported.rs:80:15 + --> $DIR/unsupported.rs:81:15 | LL | fn avr_ptr(f: extern "avr-interrupt" fn()) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -54,13 +54,13 @@ LL | fn avr_ptr(f: extern "avr-interrupt" fn()) { = note: for more information, see issue #130260 error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:85:1 + --> $DIR/unsupported.rs:86:1 | LL | extern "avr-interrupt" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of calling convention not supported on this target on function pointer - --> $DIR/unsupported.rs:115:15 + --> $DIR/unsupported.rs:116:15 | LL | fn x86_ptr(f: extern "x86-interrupt" fn()) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -69,13 +69,13 @@ LL | fn x86_ptr(f: extern "x86-interrupt" fn()) { = note: for more information, see issue #130260 error[E0570]: `"x86-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:126:1 + --> $DIR/unsupported.rs:127:1 | LL | extern "x86-interrupt" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of calling convention not supported on this target on function pointer - --> $DIR/unsupported.rs:138:20 + --> $DIR/unsupported.rs:139:20 | LL | fn thiscall_ptr(f: extern "thiscall" fn()) { | ^^^^^^^^^^^^^^^^^^^^^^ @@ -84,13 +84,13 @@ LL | fn thiscall_ptr(f: extern "thiscall" fn()) { = note: for more information, see issue #130260 error[E0570]: `"thiscall"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:151:1 + --> $DIR/unsupported.rs:152:1 | LL | extern "thiscall" {} | ^^^^^^^^^^^^^^^^^^^^ warning: use of calling convention not supported on this target on function pointer - --> $DIR/unsupported.rs:169:19 + --> $DIR/unsupported.rs:170:19 | LL | fn stdcall_ptr(f: extern "stdcall" fn()) { | ^^^^^^^^^^^^^^^^^^^^^ @@ -99,7 +99,7 @@ LL | fn stdcall_ptr(f: extern "stdcall" fn()) { = note: for more information, see issue #130260 warning: use of calling convention not supported on this target - --> $DIR/unsupported.rs:182:1 + --> $DIR/unsupported.rs:183:1 | LL | extern "stdcall" {} | ^^^^^^^^^^^^^^^^^^^ @@ -109,52 +109,67 @@ LL | extern "stdcall" {} = note: `#[warn(unsupported_calling_conventions)]` on by default warning: use of calling convention not supported on this target on function pointer - --> $DIR/unsupported.rs:194:16 + --> $DIR/unsupported.rs:195:21 | -LL | fn cmse_ptr(f: extern "C-cmse-nonsecure-call" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn cmse_call_ptr(f: extern "C-cmse-nonsecure-call" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #130260 +warning: use of calling convention not supported on this target on function pointer + --> $DIR/unsupported.rs:203:22 + | +LL | fn cmse_entry_ptr(f: extern "C-cmse-nonsecure-entry" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #130260 + +error[E0570]: `"C-cmse-nonsecure-entry"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:208:1 + | +LL | extern "C-cmse-nonsecure-entry" {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:32:1 + --> $DIR/unsupported.rs:33:1 | LL | extern "ptx-kernel" fn ptx() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"aapcs"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:42:1 + --> $DIR/unsupported.rs:43:1 | LL | extern "aapcs" fn aapcs() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:68:1 + --> $DIR/unsupported.rs:69:1 | LL | extern "msp430-interrupt" fn msp430() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:78:1 + --> $DIR/unsupported.rs:79:1 | LL | extern "avr-interrupt" fn avr() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"x86-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:110:1 + --> $DIR/unsupported.rs:111:1 | LL | extern "x86-interrupt" fn x86() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"thiscall"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:132:1 + --> $DIR/unsupported.rs:133:1 | LL | extern "thiscall" fn thiscall() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of calling convention not supported on this target - --> $DIR/unsupported.rs:158:1 + --> $DIR/unsupported.rs:159:1 | LL | extern "stdcall" fn stdcall() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -162,6 +177,12 @@ LL | extern "stdcall" fn stdcall() {} = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #87678 -error: aborting due to 12 previous errors; 10 warnings emitted +error[E0570]: `"C-cmse-nonsecure-entry"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:201:1 + | +LL | extern "C-cmse-nonsecure-entry" fn cmse_entry() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 14 previous errors; 11 warnings emitted For more information about this error, try `rustc --explain E0570`. diff --git a/tests/ui/abi/unsupported.rs b/tests/ui/abi/unsupported.rs index cf0db9a78e3..0eb039269a3 100644 --- a/tests/ui/abi/unsupported.rs +++ b/tests/ui/abi/unsupported.rs @@ -21,7 +21,8 @@ abi_avr_interrupt, abi_x86_interrupt, abi_riscv_interrupt, - abi_c_cmse_nonsecure_call + abi_c_cmse_nonsecure_call, + cmse_nonsecure_entry )] #[lang = "sized"] trait Sized {} @@ -191,8 +192,18 @@ extern "stdcall" {} //[riscv64]~^^^^^^^^^ WARN use of calling convention not supported //[riscv64]~^^^^^^^^^^ WARN this was previously accepted -fn cmse_ptr(f: extern "C-cmse-nonsecure-call" fn()) { +fn cmse_call_ptr(f: extern "C-cmse-nonsecure-call" fn()) { //~^ WARN unsupported_fn_ptr_calling_conventions //~^^ WARN this was previously accepted f() } + +extern "C-cmse-nonsecure-entry" fn cmse_entry() {} +//~^ ERROR is not a supported ABI +fn cmse_entry_ptr(f: extern "C-cmse-nonsecure-entry" fn()) { + //~^ WARN unsupported_fn_ptr_calling_conventions + //~^^ WARN this was previously accepted + f() +} +extern "C-cmse-nonsecure-entry" {} +//~^ ERROR is not a supported ABI diff --git a/tests/ui/abi/unsupported.x64.stderr b/tests/ui/abi/unsupported.x64.stderr index 6f8c56fdfb1..45ba9a6649c 100644 --- a/tests/ui/abi/unsupported.x64.stderr +++ b/tests/ui/abi/unsupported.x64.stderr @@ -1,5 +1,5 @@ warning: use of calling convention not supported on this target on function pointer - --> $DIR/unsupported.rs:34:15 + --> $DIR/unsupported.rs:35:15 | LL | fn ptx_ptr(f: extern "ptx-kernel" fn()) { | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -9,13 +9,13 @@ LL | fn ptx_ptr(f: extern "ptx-kernel" fn()) { = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:39:1 + --> $DIR/unsupported.rs:40:1 | LL | extern "ptx-kernel" {} | ^^^^^^^^^^^^^^^^^^^^^^ warning: use of calling convention not supported on this target on function pointer - --> $DIR/unsupported.rs:48:17 + --> $DIR/unsupported.rs:49:17 | LL | fn aapcs_ptr(f: extern "aapcs" fn()) { | ^^^^^^^^^^^^^^^^^^^ @@ -24,13 +24,13 @@ LL | fn aapcs_ptr(f: extern "aapcs" fn()) { = note: for more information, see issue #130260 error[E0570]: `"aapcs"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:61:1 + --> $DIR/unsupported.rs:62:1 | LL | extern "aapcs" {} | ^^^^^^^^^^^^^^^^^ warning: use of calling convention not supported on this target on function pointer - --> $DIR/unsupported.rs:70:18 + --> $DIR/unsupported.rs:71:18 | LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -39,13 +39,13 @@ LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) { = note: for more information, see issue #130260 error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:75:1 + --> $DIR/unsupported.rs:76:1 | LL | extern "msp430-interrupt" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of calling convention not supported on this target on function pointer - --> $DIR/unsupported.rs:80:15 + --> $DIR/unsupported.rs:81:15 | LL | fn avr_ptr(f: extern "avr-interrupt" fn()) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -54,13 +54,13 @@ LL | fn avr_ptr(f: extern "avr-interrupt" fn()) { = note: for more information, see issue #130260 error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:85:1 + --> $DIR/unsupported.rs:86:1 | LL | extern "avr-interrupt" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of calling convention not supported on this target on function pointer - --> $DIR/unsupported.rs:93:17 + --> $DIR/unsupported.rs:94:17 | LL | fn riscv_ptr(f: extern "riscv-interrupt-m" fn()) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -69,13 +69,13 @@ LL | fn riscv_ptr(f: extern "riscv-interrupt-m" fn()) { = note: for more information, see issue #130260 error[E0570]: `"riscv-interrupt-m"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:104:1 + --> $DIR/unsupported.rs:105:1 | LL | extern "riscv-interrupt-m" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of calling convention not supported on this target on function pointer - --> $DIR/unsupported.rs:138:20 + --> $DIR/unsupported.rs:139:20 | LL | fn thiscall_ptr(f: extern "thiscall" fn()) { | ^^^^^^^^^^^^^^^^^^^^^^ @@ -84,13 +84,13 @@ LL | fn thiscall_ptr(f: extern "thiscall" fn()) { = note: for more information, see issue #130260 error[E0570]: `"thiscall"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:151:1 + --> $DIR/unsupported.rs:152:1 | LL | extern "thiscall" {} | ^^^^^^^^^^^^^^^^^^^^ warning: use of calling convention not supported on this target on function pointer - --> $DIR/unsupported.rs:169:19 + --> $DIR/unsupported.rs:170:19 | LL | fn stdcall_ptr(f: extern "stdcall" fn()) { | ^^^^^^^^^^^^^^^^^^^^^ @@ -99,7 +99,7 @@ LL | fn stdcall_ptr(f: extern "stdcall" fn()) { = note: for more information, see issue #130260 warning: use of calling convention not supported on this target - --> $DIR/unsupported.rs:182:1 + --> $DIR/unsupported.rs:183:1 | LL | extern "stdcall" {} | ^^^^^^^^^^^^^^^^^^^ @@ -109,52 +109,67 @@ LL | extern "stdcall" {} = note: `#[warn(unsupported_calling_conventions)]` on by default warning: use of calling convention not supported on this target on function pointer - --> $DIR/unsupported.rs:194:16 + --> $DIR/unsupported.rs:195:21 | -LL | fn cmse_ptr(f: extern "C-cmse-nonsecure-call" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn cmse_call_ptr(f: extern "C-cmse-nonsecure-call" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #130260 +warning: use of calling convention not supported on this target on function pointer + --> $DIR/unsupported.rs:203:22 + | +LL | fn cmse_entry_ptr(f: extern "C-cmse-nonsecure-entry" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #130260 + +error[E0570]: `"C-cmse-nonsecure-entry"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:208:1 + | +LL | extern "C-cmse-nonsecure-entry" {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:32:1 + --> $DIR/unsupported.rs:33:1 | LL | extern "ptx-kernel" fn ptx() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"aapcs"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:42:1 + --> $DIR/unsupported.rs:43:1 | LL | extern "aapcs" fn aapcs() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:68:1 + --> $DIR/unsupported.rs:69:1 | LL | extern "msp430-interrupt" fn msp430() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:78:1 + --> $DIR/unsupported.rs:79:1 | LL | extern "avr-interrupt" fn avr() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"riscv-interrupt-m"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:88:1 + --> $DIR/unsupported.rs:89:1 | LL | extern "riscv-interrupt-m" fn riscv() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"thiscall"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:132:1 + --> $DIR/unsupported.rs:133:1 | LL | extern "thiscall" fn thiscall() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of calling convention not supported on this target - --> $DIR/unsupported.rs:158:1 + --> $DIR/unsupported.rs:159:1 | LL | extern "stdcall" fn stdcall() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -162,6 +177,12 @@ LL | extern "stdcall" fn stdcall() {} = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #87678 -error: aborting due to 12 previous errors; 10 warnings emitted +error[E0570]: `"C-cmse-nonsecure-entry"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:201:1 + | +LL | extern "C-cmse-nonsecure-entry" fn cmse_entry() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 14 previous errors; 11 warnings emitted For more information about this error, try `rustc --explain E0570`. From b8615aa3f5cde84aa7277e549c2a30fa5e4ac5d5 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Tue, 24 Sep 2024 11:32:33 +0200 Subject: [PATCH 010/357] Move existing rfc3627 tests to a dedicated folder --- .../auxiliary/migration_lint_macros.rs} | 0 .../migration_lint.fixed} | 6 ++-- .../migration_lint.rs} | 6 ++-- .../migration_lint.stderr} | 30 +++++++++---------- 4 files changed, 21 insertions(+), 21 deletions(-) rename tests/ui/pattern/{auxiliary/match_ergonomics_2024_macros.rs => rfc-3627-match-ergonomics-2024/auxiliary/migration_lint_macros.rs} (100%) rename tests/ui/pattern/{match_ergonomics_2024.fixed => rfc-3627-match-ergonomics-2024/migration_lint.fixed} (91%) rename tests/ui/pattern/{match_ergonomics_2024.rs => rfc-3627-match-ergonomics-2024/migration_lint.rs} (91%) rename tests/ui/pattern/{match_ergonomics_2024.stderr => rfc-3627-match-ergonomics-2024/migration_lint.stderr} (80%) diff --git a/tests/ui/pattern/auxiliary/match_ergonomics_2024_macros.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/auxiliary/migration_lint_macros.rs similarity index 100% rename from tests/ui/pattern/auxiliary/match_ergonomics_2024_macros.rs rename to tests/ui/pattern/rfc-3627-match-ergonomics-2024/auxiliary/migration_lint_macros.rs diff --git a/tests/ui/pattern/match_ergonomics_2024.fixed b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.fixed similarity index 91% rename from tests/ui/pattern/match_ergonomics_2024.fixed rename to tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.fixed index 1ec2b5a214b..253c9589a55 100644 --- a/tests/ui/pattern/match_ergonomics_2024.fixed +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.fixed @@ -1,12 +1,12 @@ //@ edition: 2021 //@ run-rustfix //@ rustfix-only-machine-applicable -//@ aux-build:match_ergonomics_2024_macros.rs +//@ aux-build:migration_lint_macros.rs #![feature(mut_ref, ref_pat_eat_one_layer_2024)] #![allow(incomplete_features, unused)] #![deny(rust_2024_incompatible_pat)] -extern crate match_ergonomics_2024_macros; +extern crate migration_lint_macros; struct Foo(u8); @@ -47,7 +47,7 @@ fn main() { match &(Some(0), Some(0)) { // The two patterns are the same syntactically, but because they're defined in different // editions they don't mean the same thing. - (Some(mut _x), match_ergonomics_2024_macros::mixed_edition_pat!(_y)) => { + (Some(mut _x), migration_lint_macros::mixed_edition_pat!(_y)) => { //~^ WARN: the semantics of this pattern will change in edition 2024 _x = 4; _y = &7; diff --git a/tests/ui/pattern/match_ergonomics_2024.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.rs similarity index 91% rename from tests/ui/pattern/match_ergonomics_2024.rs rename to tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.rs index c9f992c12d4..1406db779cc 100644 --- a/tests/ui/pattern/match_ergonomics_2024.rs +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.rs @@ -1,12 +1,12 @@ //@ edition: 2021 //@ run-rustfix //@ rustfix-only-machine-applicable -//@ aux-build:match_ergonomics_2024_macros.rs +//@ aux-build:migration_lint_macros.rs #![feature(mut_ref, ref_pat_eat_one_layer_2024)] #![allow(incomplete_features, unused)] #![deny(rust_2024_incompatible_pat)] -extern crate match_ergonomics_2024_macros; +extern crate migration_lint_macros; struct Foo(u8); @@ -47,7 +47,7 @@ fn main() { match &(Some(0), Some(0)) { // The two patterns are the same syntactically, but because they're defined in different // editions they don't mean the same thing. - (Some(mut _x), match_ergonomics_2024_macros::mixed_edition_pat!(_y)) => { + (Some(mut _x), migration_lint_macros::mixed_edition_pat!(_y)) => { //~^ WARN: the semantics of this pattern will change in edition 2024 _x = 4; _y = &7; diff --git a/tests/ui/pattern/match_ergonomics_2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr similarity index 80% rename from tests/ui/pattern/match_ergonomics_2024.stderr rename to tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr index 11844434ad2..4d723012024 100644 --- a/tests/ui/pattern/match_ergonomics_2024.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr @@ -1,5 +1,5 @@ error: the semantics of this pattern will change in edition 2024 - --> $DIR/match_ergonomics_2024.rs:14:9 + --> $DIR/migration_lint.rs:14:9 | LL | let Foo(mut a) = &Foo(0); | -^^^^^^^^^ @@ -7,13 +7,13 @@ LL | let Foo(mut a) = &Foo(0); | help: desugar the match ergonomics: `&` | note: the lint level is defined here - --> $DIR/match_ergonomics_2024.rs:7:9 + --> $DIR/migration_lint.rs:7:9 | LL | #![deny(rust_2024_incompatible_pat)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the semantics of this pattern will change in edition 2024 - --> $DIR/match_ergonomics_2024.rs:18:9 + --> $DIR/migration_lint.rs:18:9 | LL | let Foo(mut a) = &mut Foo(0); | -^^^^^^^^^ @@ -21,7 +21,7 @@ LL | let Foo(mut a) = &mut Foo(0); | help: desugar the match ergonomics: `&mut` error: the semantics of this pattern will change in edition 2024 - --> $DIR/match_ergonomics_2024.rs:22:12 + --> $DIR/migration_lint.rs:22:12 | LL | if let Some(&_) = &&&&&Some(&0u8) {} | -^^^^^^^ @@ -29,7 +29,7 @@ LL | if let Some(&_) = &&&&&Some(&0u8) {} | help: desugar the match ergonomics: `&&&&&` error: the semantics of this pattern will change in edition 2024 - --> $DIR/match_ergonomics_2024.rs:25:12 + --> $DIR/migration_lint.rs:25:12 | LL | if let Some(&mut _) = &&&&&Some(&mut 0u8) {} | -^^^^^^^^^^^ @@ -37,7 +37,7 @@ LL | if let Some(&mut _) = &&&&&Some(&mut 0u8) {} | help: desugar the match ergonomics: `&&&&&` error: the semantics of this pattern will change in edition 2024 - --> $DIR/match_ergonomics_2024.rs:28:12 + --> $DIR/migration_lint.rs:28:12 | LL | if let Some(&_) = &&&&&mut Some(&0u8) {} | -^^^^^^^ @@ -45,7 +45,7 @@ LL | if let Some(&_) = &&&&&mut Some(&0u8) {} | help: desugar the match ergonomics: `&&&&&mut` error: the semantics of this pattern will change in edition 2024 - --> $DIR/match_ergonomics_2024.rs:31:12 + --> $DIR/migration_lint.rs:31:12 | LL | if let Some(&mut Some(Some(_))) = &mut Some(&mut Some(&mut Some(0u8))) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -56,7 +56,7 @@ LL | if let &mut Some(&mut Some(&mut Some(_))) = &mut Some(&mut Some(&mut So | ++++ ++++ error: the semantics of this pattern will change in edition 2024 - --> $DIR/match_ergonomics_2024.rs:34:12 + --> $DIR/migration_lint.rs:34:12 | LL | if let Some(&mut Some(Some(_a))) = &mut Some(&mut Some(&mut Some(0u8))) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -67,7 +67,7 @@ LL | if let &mut Some(&mut Some(&mut Some(ref mut _a))) = &mut Some(&mut Som | ++++ ++++ +++++++ error: the semantics of this pattern will change in edition 2024 - --> $DIR/match_ergonomics_2024.rs:43:9 + --> $DIR/migration_lint.rs:43:9 | LL | let Struct { a, mut b, c } = &s; | ^^^^^^^^^^^^^^^^^^^^^^ @@ -78,20 +78,20 @@ LL | let &Struct { ref a, mut b, ref c } = &s; | + +++ +++ warning: the semantics of this pattern will change in edition 2024 - --> $DIR/match_ergonomics_2024.rs:50:9 + --> $DIR/migration_lint.rs:50:9 | -LL | (Some(mut _x), match_ergonomics_2024_macros::mixed_edition_pat!(_y)) => { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | (Some(mut _x), migration_lint_macros::mixed_edition_pat!(_y)) => { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: the lint level is defined here - --> $DIR/match_ergonomics_2024.rs:46:12 + --> $DIR/migration_lint.rs:46:12 | LL | #[warn(rust_2024_incompatible_pat)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: desugar the match ergonomics | -LL | &(Some(mut _x), match_ergonomics_2024_macros::mixed_edition_pat!(ref _y)) => { - | + +++ +LL | &(Some(mut _x), migration_lint_macros::mixed_edition_pat!(ref _y)) => { + | + +++ error: aborting due to 8 previous errors; 1 warning emitted From c22588b700a62a1d93ff7bc30fd49583efab4ad2 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Fri, 20 Sep 2024 19:47:30 +0200 Subject: [PATCH 011/357] Add `min_match_ergonomics_2024` feature gate --- compiler/rustc_feature/src/unstable.rs | 3 +++ compiler/rustc_span/src/symbol.rs | 1 + 2 files changed, 4 insertions(+) diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index fa3a7049f4a..5fff81d3e1c 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -516,6 +516,9 @@ declare_features! ( (unstable, macro_metavar_expr_concat, "1.81.0", Some(124225)), /// Allows `#[marker]` on certain traits allowing overlapping implementations. (unstable, marker_trait_attr, "1.30.0", Some(29864)), + /// A very restricted form of match ergonomics used over the 2024 edition transition to give + /// more time for T-lang to decide the final form of RFC3627. + (incomplete, min_match_ergonomics_2024, "CURRENT_RUSTC_VERSION", Some(123076)), /// A minimal, sound subset of specialization intended to be used by the /// standard library until the soundness issues with specialization /// are fixed. diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 402232a1720..81ae66ccf68 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1218,6 +1218,7 @@ symbols! { min_const_generics, min_const_unsafe_fn, min_exhaustive_patterns, + min_match_ergonomics_2024, min_specialization, min_type_alias_impl_trait, minnumf128, From 6edd86d58e5f8f35de441c3b461d1b1f5e818e1c Mon Sep 17 00:00:00 2001 From: David Wood Date: Wed, 11 Sep 2024 12:07:24 +0100 Subject: [PATCH 012/357] tests: add test for #105111 Enabling a tied feature should not enable the other feature automatically. This was fixed by something in #128796, probably #128221 or #128679. --- ...tied-features-no-implication-1.paca.stderr | 4 +++ ...tied-features-no-implication-1.pacg.stderr | 4 +++ .../tied-features-no-implication-1.rs | 20 +++++++++++++ .../tied-features-no-implication.paca.stderr | 4 +++ .../tied-features-no-implication.pacg.stderr | 14 +++++++++ .../tied-features-no-implication.rs | 29 +++++++++++++++++++ 6 files changed, 75 insertions(+) create mode 100644 tests/ui/target-feature/tied-features-no-implication-1.paca.stderr create mode 100644 tests/ui/target-feature/tied-features-no-implication-1.pacg.stderr create mode 100644 tests/ui/target-feature/tied-features-no-implication-1.rs create mode 100644 tests/ui/target-feature/tied-features-no-implication.paca.stderr create mode 100644 tests/ui/target-feature/tied-features-no-implication.pacg.stderr create mode 100644 tests/ui/target-feature/tied-features-no-implication.rs diff --git a/tests/ui/target-feature/tied-features-no-implication-1.paca.stderr b/tests/ui/target-feature/tied-features-no-implication-1.paca.stderr new file mode 100644 index 00000000000..bf211fbee2f --- /dev/null +++ b/tests/ui/target-feature/tied-features-no-implication-1.paca.stderr @@ -0,0 +1,4 @@ +error: the target features paca, pacg must all be either enabled or disabled together + +error: aborting due to 1 previous error + diff --git a/tests/ui/target-feature/tied-features-no-implication-1.pacg.stderr b/tests/ui/target-feature/tied-features-no-implication-1.pacg.stderr new file mode 100644 index 00000000000..bf211fbee2f --- /dev/null +++ b/tests/ui/target-feature/tied-features-no-implication-1.pacg.stderr @@ -0,0 +1,4 @@ +error: the target features paca, pacg must all be either enabled or disabled together + +error: aborting due to 1 previous error + diff --git a/tests/ui/target-feature/tied-features-no-implication-1.rs b/tests/ui/target-feature/tied-features-no-implication-1.rs new file mode 100644 index 00000000000..0473ca319b8 --- /dev/null +++ b/tests/ui/target-feature/tied-features-no-implication-1.rs @@ -0,0 +1,20 @@ +//@ revisions: paca pacg +//@ compile-flags: --crate-type=rlib --target=aarch64-unknown-linux-gnu +//@ needs-llvm-components: aarch64 +//@[paca] compile-flags: -Ctarget-feature=+paca +//@[paca] error-pattern: the target features paca, pacg must all be either enabled or disabled together +//@[pacg] compile-flags: -Ctarget-feature=+pacg +//@[paca] error-pattern: the target features paca, pacg must all be either enabled or disabled together +#![feature(no_core, lang_items)] +#![no_core] + +#[lang="sized"] +trait Sized {} + +// In this test, demonstrate that +paca and +pacg both result in the tied feature error if there +// isn't something causing an error. +// See tied-features-no-implication.rs + +#[cfg(target_feature = "pacg")] +pub unsafe fn foo() { +} diff --git a/tests/ui/target-feature/tied-features-no-implication.paca.stderr b/tests/ui/target-feature/tied-features-no-implication.paca.stderr new file mode 100644 index 00000000000..bf211fbee2f --- /dev/null +++ b/tests/ui/target-feature/tied-features-no-implication.paca.stderr @@ -0,0 +1,4 @@ +error: the target features paca, pacg must all be either enabled or disabled together + +error: aborting due to 1 previous error + diff --git a/tests/ui/target-feature/tied-features-no-implication.pacg.stderr b/tests/ui/target-feature/tied-features-no-implication.pacg.stderr new file mode 100644 index 00000000000..0e31dea24ea --- /dev/null +++ b/tests/ui/target-feature/tied-features-no-implication.pacg.stderr @@ -0,0 +1,14 @@ +error[E0428]: the name `foo` is defined multiple times + --> $DIR/tied-features-no-implication.rs:28:1 + | +LL | fn foo() {} + | -------- previous definition of the value `foo` here +... +LL | pub unsafe fn foo() { + | ^^^^^^^^^^^^^^^^^^^ `foo` redefined here + | + = note: `foo` must be defined only once in the value namespace of this module + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0428`. diff --git a/tests/ui/target-feature/tied-features-no-implication.rs b/tests/ui/target-feature/tied-features-no-implication.rs new file mode 100644 index 00000000000..157b50bb0d3 --- /dev/null +++ b/tests/ui/target-feature/tied-features-no-implication.rs @@ -0,0 +1,29 @@ +//@ revisions: paca pacg +//@ compile-flags: --crate-type=rlib --target=aarch64-unknown-linux-gnu +//@ needs-llvm-components: aarch64 +//@[paca] compile-flags: -Ctarget-feature=+paca +//@[paca] error-pattern: the target features paca, pacg must all be either enabled or disabled together +//@[pacg] compile-flags: -Ctarget-feature=+pacg +//@[pacg] error-pattern: the name `foo` is defined multiple times +#![feature(no_core, lang_items)] +#![no_core] + +#[lang="sized"] +trait Sized {} + +// Can't use `compile_error!` here without `core`/`std` but requiring these makes this test only +// work if you have libcore built in the sysroot for `aarch64-unknown-linux-gnu`. Can't run this +// test on any aarch64 platform because they all have different default available features - as +// written, this test depends on `aarch64-unknown-linux-gnu` having -paca,-pacg by default. +// Cause a multiple definition error instead. +fn foo() {} + +// Enabling one of the tied features does not imply the other is enabled. +// +// With +paca, this multiple definition doesn't cause an error because +paca hasn't implied +// +pacg. With +pacg, the multiple definition error is emitted (and the tied feature error would +// be). + +#[cfg(target_feature = "pacg")] +pub unsafe fn foo() { +} From 207bc77e15acc9444bf6c3e74fa46607490a8e8a Mon Sep 17 00:00:00 2001 From: David Wood Date: Wed, 11 Sep 2024 13:57:12 +0100 Subject: [PATCH 013/357] codegen_ssa: consolidate tied feature checking `rustc_codegen_llvm` and `rustc_codegen_gcc` duplicated logic for checking if tied target features were partially enabled. This commit consolidates these checks into `rustc_codegen_ssa` in the `codegen_fn_attrs` query, which also is run pre-monomorphisation for each function, which ensures that this check is run for unused functions, as would be expected. --- compiler/rustc_codegen_gcc/messages.ftl | 3 -- compiler/rustc_codegen_gcc/src/attributes.rs | 22 +-------- compiler/rustc_codegen_gcc/src/errors.rs | 36 --------------- compiler/rustc_codegen_gcc/src/gcc_util.rs | 24 ++-------- compiler/rustc_codegen_llvm/messages.ftl | 6 --- compiler/rustc_codegen_llvm/src/attributes.rs | 23 +--------- compiler/rustc_codegen_llvm/src/errors.rs | 24 ---------- compiler/rustc_codegen_llvm/src/llvm_util.rs | 26 ++--------- compiler/rustc_codegen_ssa/messages.ftl | 5 +++ .../rustc_codegen_ssa/src/codegen_attrs.rs | 45 ++++++++++++++++++- compiler/rustc_codegen_ssa/src/errors.rs | 26 ++++++++++- tests/ui/target-feature/tied-features.rs | 9 ++-- tests/ui/target-feature/tied-features.stderr | 14 ++++-- 13 files changed, 100 insertions(+), 163 deletions(-) diff --git a/compiler/rustc_codegen_gcc/messages.ftl b/compiler/rustc_codegen_gcc/messages.ftl index 0235384445e..bbae59ea7a5 100644 --- a/compiler/rustc_codegen_gcc/messages.ftl +++ b/compiler/rustc_codegen_gcc/messages.ftl @@ -8,9 +8,6 @@ codegen_gcc_invalid_minimum_alignment = codegen_gcc_lto_not_supported = LTO is not supported. You may get a linker error. -codegen_gcc_tied_target_features = the target features {$features} must all be either enabled or disabled together - .help = add the missing features in a `target_feature` attribute - codegen_gcc_unwinding_inline_asm = GCC backend does not support unwinding from inline asm diff --git a/compiler/rustc_codegen_gcc/src/attributes.rs b/compiler/rustc_codegen_gcc/src/attributes.rs index 5fdf2680aac..d20e13e15b9 100644 --- a/compiler/rustc_codegen_gcc/src/attributes.rs +++ b/compiler/rustc_codegen_gcc/src/attributes.rs @@ -7,11 +7,9 @@ use rustc_attr::InstructionSetAttr; #[cfg(feature = "master")] use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::ty; -use rustc_span::symbol::sym; use crate::context::CodegenCx; -use crate::errors::TiedTargetFeatures; -use crate::gcc_util::{check_tied_features, to_gcc_features}; +use crate::gcc_util::to_gcc_features; /// Get GCC attribute for the provided inline heuristic. #[cfg(feature = "master")] @@ -72,26 +70,10 @@ pub fn from_fn_attrs<'gcc, 'tcx>( } } - let function_features = codegen_fn_attrs + let mut function_features = codegen_fn_attrs .target_features .iter() .map(|features| features.name.as_str()) - .collect::>(); - - if let Some(features) = check_tied_features( - cx.tcx.sess, - &function_features.iter().map(|features| (*features, true)).collect(), - ) { - let span = cx - .tcx - .get_attr(instance.def_id(), sym::target_feature) - .map_or_else(|| cx.tcx.def_span(instance.def_id()), |a| a.span); - cx.tcx.dcx().create_err(TiedTargetFeatures { features: features.join(", "), span }).emit(); - return; - } - - let mut function_features = function_features - .iter() .flat_map(|feat| to_gcc_features(cx.tcx.sess, feat).into_iter()) .chain(codegen_fn_attrs.instruction_set.iter().map(|x| match *x { InstructionSetAttr::ArmA32 => "-thumb-mode", // TODO(antoyo): support removing feature. diff --git a/compiler/rustc_codegen_gcc/src/errors.rs b/compiler/rustc_codegen_gcc/src/errors.rs index 6bada3d334c..dc1895f437b 100644 --- a/compiler/rustc_codegen_gcc/src/errors.rs +++ b/compiler/rustc_codegen_gcc/src/errors.rs @@ -1,9 +1,6 @@ -use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::Span; -use crate::fluent_generated as fluent; - #[derive(Diagnostic)] #[diag(codegen_gcc_unknown_ctarget_feature_prefix)] #[note] @@ -45,15 +42,6 @@ pub(crate) struct InvalidMinimumAlignment { pub err: String, } -#[derive(Diagnostic)] -#[diag(codegen_gcc_tied_target_features)] -#[help] -pub(crate) struct TiedTargetFeatures { - #[primary_span] - pub span: Span, - pub features: String, -} - #[derive(Diagnostic)] #[diag(codegen_gcc_copy_bitcode)] pub(crate) struct CopyBitcode { @@ -78,27 +66,3 @@ pub(crate) struct LtoDylib; pub(crate) struct LtoBitcodeFromRlib { pub gcc_err: String, } - -pub(crate) struct TargetFeatureDisableOrEnable<'a> { - pub features: &'a [&'a str], - pub span: Option, - pub missing_features: Option, -} - -#[derive(Subdiagnostic)] -#[help(codegen_gcc_missing_features)] -pub(crate) struct MissingFeatures; - -impl Diagnostic<'_, G> for TargetFeatureDisableOrEnable<'_> { - fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { - let mut diag = Diag::new(dcx, level, fluent::codegen_gcc_target_feature_disable_or_enable); - if let Some(span) = self.span { - diag.span(span); - }; - if let Some(missing_features) = self.missing_features { - diag.subdiagnostic(missing_features); - } - diag.arg("features", self.features.join(", ")); - diag - } -} diff --git a/compiler/rustc_codegen_gcc/src/gcc_util.rs b/compiler/rustc_codegen_gcc/src/gcc_util.rs index 01dd1a8856a..3104088e0d5 100644 --- a/compiler/rustc_codegen_gcc/src/gcc_util.rs +++ b/compiler/rustc_codegen_gcc/src/gcc_util.rs @@ -1,15 +1,14 @@ #[cfg(feature = "master")] use gccjit::Context; +use rustc_codegen_ssa::codegen_attrs::check_tied_features; +use rustc_codegen_ssa::errors::TargetFeatureDisableOrEnable; use rustc_data_structures::fx::FxHashMap; use rustc_middle::bug; use rustc_session::Session; use rustc_target::target_features::RUSTC_SPECIFIC_FEATURES; use smallvec::{SmallVec, smallvec}; -use crate::errors::{ - PossibleFeature, TargetFeatureDisableOrEnable, UnknownCTargetFeature, - UnknownCTargetFeaturePrefix, -}; +use crate::errors::{PossibleFeature, UnknownCTargetFeature, UnknownCTargetFeaturePrefix}; /// The list of GCC features computed from CLI flags (`-Ctarget-cpu`, `-Ctarget-feature`, /// `--target` and similar). @@ -185,23 +184,6 @@ pub fn to_gcc_features<'a>(sess: &Session, s: &'a str) -> SmallVec<[&'a str; 2]> } } -// Given a map from target_features to whether they are enabled or disabled, -// ensure only valid combinations are allowed. -pub fn check_tied_features( - sess: &Session, - features: &FxHashMap<&str, bool>, -) -> Option<&'static [&'static str]> { - for tied in sess.target.tied_target_features() { - // Tied features must be set to the same value, or not set at all - let mut tied_iter = tied.iter(); - let enabled = features.get(tied_iter.next().unwrap()); - if tied_iter.any(|feature| enabled != features.get(feature)) { - return Some(tied); - } - } - None -} - fn arch_to_gcc(name: &str) -> &str { match name { "M68020" => "68020", diff --git a/compiler/rustc_codegen_llvm/messages.ftl b/compiler/rustc_codegen_llvm/messages.ftl index df2198df14b..0950e4bb26b 100644 --- a/compiler/rustc_codegen_llvm/messages.ftl +++ b/compiler/rustc_codegen_llvm/messages.ftl @@ -33,9 +33,6 @@ codegen_llvm_lto_proc_macro = lto cannot be used for `proc-macro` crate type wit codegen_llvm_mismatch_data_layout = data-layout for target `{$rustc_target}`, `{$rustc_layout}`, differs from LLVM target's `{$llvm_target}` default layout, `{$llvm_layout}` -codegen_llvm_missing_features = - add the missing features in a `target_feature` attribute - codegen_llvm_multiple_source_dicompileunit = multiple source DICompileUnits found codegen_llvm_multiple_source_dicompileunit_with_llvm_err = multiple source DICompileUnits found: {$llvm_err} @@ -63,9 +60,6 @@ codegen_llvm_serialize_module_with_llvm_err = failed to serialize module {$name} codegen_llvm_symbol_already_defined = symbol `{$symbol_name}` is already defined -codegen_llvm_target_feature_disable_or_enable = - the target features {$features} must all be either enabled or disabled together - codegen_llvm_target_machine = could not create LLVM TargetMachine for triple: {$triple} codegen_llvm_target_machine_with_llvm_err = could not create LLVM TargetMachine for triple: {$triple}: {$llvm_err} diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index 489259da856..2c5ec9dad59 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -6,12 +6,11 @@ use rustc_hir::def_id::DefId; use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, PatchableFunctionEntry}; use rustc_middle::ty::{self, TyCtxt}; use rustc_session::config::{BranchProtection, FunctionReturn, OptLevel, PAuthKey, PacRet}; -use rustc_span::symbol::sym; use rustc_target::spec::{FramePointer, SanitizerSet, StackProbeType, StackProtector}; use smallvec::SmallVec; use crate::context::CodegenCx; -use crate::errors::{MissingFeatures, SanitizerMemtagRequiresMte, TargetFeatureDisableOrEnable}; +use crate::errors::SanitizerMemtagRequiresMte; use crate::llvm::AttributePlace::Function; use crate::llvm::{self, AllocKindFlags, Attribute, AttributeKind, AttributePlace, MemoryEffects}; use crate::value::Value; @@ -502,26 +501,6 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>( let function_features = codegen_fn_attrs.target_features.iter().map(|f| f.name.as_str()).collect::>(); - if let Some(f) = llvm_util::check_tied_features( - cx.tcx.sess, - &function_features.iter().map(|f| (*f, true)).collect(), - ) { - let span = cx - .tcx - .get_attrs(instance.def_id(), sym::target_feature) - .next() - .map_or_else(|| cx.tcx.def_span(instance.def_id()), |a| a.span); - cx.tcx - .dcx() - .create_err(TargetFeatureDisableOrEnable { - features: f, - span: Some(span), - missing_features: Some(MissingFeatures), - }) - .emit(); - return; - } - let function_features = function_features .iter() // Convert to LLVMFeatures and filter out unavailable ones diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index bb481d2a308..0d436e1891e 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -80,30 +80,6 @@ impl Diagnostic<'_, G> for ParseTargetMachineConfig<'_> { } } -pub(crate) struct TargetFeatureDisableOrEnable<'a> { - pub features: &'a [&'a str], - pub span: Option, - pub missing_features: Option, -} - -#[derive(Subdiagnostic)] -#[help(codegen_llvm_missing_features)] -pub(crate) struct MissingFeatures; - -impl Diagnostic<'_, G> for TargetFeatureDisableOrEnable<'_> { - fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { - let mut diag = Diag::new(dcx, level, fluent::codegen_llvm_target_feature_disable_or_enable); - if let Some(span) = self.span { - diag.span(span); - }; - if let Some(missing_features) = self.missing_features { - diag.subdiagnostic(missing_features); - } - diag.arg("features", self.features.join(", ")); - diag - } -} - #[derive(Diagnostic)] #[diag(codegen_llvm_lto_disallowed)] pub(crate) struct LtoDisallowed; diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 71fd7afb148..79820ee0cdb 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -6,6 +6,7 @@ use std::{ptr, slice, str}; use libc::c_int; use rustc_codegen_ssa::base::wants_wasm_eh; +use rustc_codegen_ssa::codegen_attrs::check_tied_features; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::small_c_str::SmallCStr; use rustc_data_structures::unord::UnordSet; @@ -19,8 +20,8 @@ use rustc_target::target_features::{RUSTC_SPECIAL_FEATURES, RUSTC_SPECIFIC_FEATU use crate::back::write::create_informational_target_machine; use crate::errors::{ - FixedX18InvalidArch, InvalidTargetFeaturePrefix, PossibleFeature, TargetFeatureDisableOrEnable, - UnknownCTargetFeature, UnknownCTargetFeaturePrefix, UnstableCTargetFeature, + FixedX18InvalidArch, InvalidTargetFeaturePrefix, PossibleFeature, UnknownCTargetFeature, + UnknownCTargetFeaturePrefix, UnstableCTargetFeature, }; use crate::llvm; @@ -272,25 +273,6 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option, -) -> Option<&'static [&'static str]> { - if !features.is_empty() { - for tied in sess.target.tied_target_features() { - // Tied features must be set to the same value, or not set at all - let mut tied_iter = tied.iter(); - let enabled = features.get(tied_iter.next().unwrap()); - if tied_iter.any(|f| enabled != features.get(f)) { - return Some(tied); - } - } - } - None -} - /// Used to generate cfg variables and apply features /// Must express features in the way Rust understands them pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec { @@ -676,7 +658,7 @@ pub(crate) fn global_llvm_features( features.extend(feats); if diagnostics && let Some(f) = check_tied_features(sess, &featsmap) { - sess.dcx().emit_err(TargetFeatureDisableOrEnable { + sess.dcx().emit_err(rustc_codegen_ssa::errors::TargetFeatureDisableOrEnable { features: f, span: None, missing_features: None, diff --git a/compiler/rustc_codegen_ssa/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl index 9091602d75b..cce5e8b1398 100644 --- a/compiler/rustc_codegen_ssa/messages.ftl +++ b/compiler/rustc_codegen_ssa/messages.ftl @@ -183,6 +183,8 @@ codegen_ssa_metadata_object_file_write = error writing metadata object file: {$e codegen_ssa_missing_cpp_build_tool_component = or a necessary component may be missing from the "C++ build tools" workload +codegen_ssa_missing_features = add the missing features in a `target_feature` attribute + codegen_ssa_missing_memory_ordering = Atomic intrinsic missing memory ordering codegen_ssa_missing_query_depgraph = @@ -238,6 +240,9 @@ codegen_ssa_stripping_debug_info_failed = stripping debug info with `{$util}` fa codegen_ssa_symbol_file_write_failure = failed to write symbols file: {$error} +codegen_ssa_target_feature_disable_or_enable = + the target features {$features} must all be either enabled or disabled together + codegen_ssa_target_feature_safe_trait = `#[target_feature(..)]` cannot be applied to safe trait method .label = cannot be applied to safe trait method .label_def = not an `unsafe` function diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index e99c3a46271..a27f983c99a 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -1,5 +1,6 @@ use rustc_ast::{MetaItemKind, NestedMetaItem, ast, attr}; use rustc_attr::{InlineAttr, InstructionSetAttr, OptimizeAttr, list_contains_name}; +use rustc_data_structures::fx::FxHashMap; use rustc_errors::codes::*; use rustc_errors::{DiagMessage, SubdiagMessage, struct_span_code_err}; use rustc_hir as hir; @@ -13,13 +14,13 @@ use rustc_middle::middle::codegen_fn_attrs::{ use rustc_middle::mir::mono::Linkage; use rustc_middle::query::Providers; use rustc_middle::ty::{self as ty, TyCtxt}; -use rustc_session::lint; use rustc_session::parse::feature_err; +use rustc_session::{Session, lint}; use rustc_span::symbol::Ident; use rustc_span::{Span, sym}; use rustc_target::spec::{SanitizerSet, abi}; -use crate::errors; +use crate::errors::{self, MissingFeatures, TargetFeatureDisableOrEnable}; use crate::target_features::{check_target_feature_trait_unsafe, from_target_feature}; fn linkage_by_name(tcx: TyCtxt<'_>, def_id: LocalDefId, name: &str) -> Linkage { @@ -662,9 +663,49 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { } } + if let Some(features) = check_tied_features( + tcx.sess, + &codegen_fn_attrs + .target_features + .iter() + .map(|features| (features.name.as_str(), true)) + .collect(), + ) { + let span = tcx + .get_attrs(did, sym::target_feature) + .next() + .map_or_else(|| tcx.def_span(did), |a| a.span); + tcx.dcx() + .create_err(TargetFeatureDisableOrEnable { + features, + span: Some(span), + missing_features: Some(MissingFeatures), + }) + .emit(); + } + codegen_fn_attrs } +/// Given a map from target_features to whether they are enabled or disabled, ensure only valid +/// combinations are allowed. +pub fn check_tied_features( + sess: &Session, + features: &FxHashMap<&str, bool>, +) -> Option<&'static [&'static str]> { + if !features.is_empty() { + for tied in sess.target.tied_target_features() { + // Tied features must be set to the same value, or not set at all + let mut tied_iter = tied.iter(); + let enabled = features.get(tied_iter.next().unwrap()); + if tied_iter.any(|f| enabled != features.get(f)) { + return Some(tied); + } + } + } + None +} + /// Checks if the provided DefId is a method in a trait impl for a trait which has track_caller /// applied to the method prototype. fn should_inherit_track_caller(tcx: TyCtxt<'_>, def_id: DefId) -> bool { diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index 08b326e3ac3..bc80f51f31c 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -9,7 +9,7 @@ use rustc_errors::codes::*; use rustc_errors::{ Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, IntoDiagArg, Level, }; -use rustc_macros::Diagnostic; +use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_middle::ty::Ty; use rustc_middle::ty::layout::LayoutError; use rustc_span::{Span, Symbol}; @@ -1068,3 +1068,27 @@ pub(crate) struct ErrorCreatingImportLibrary<'a> { pub lib_name: &'a str, pub error: String, } + +pub struct TargetFeatureDisableOrEnable<'a> { + pub features: &'a [&'a str], + pub span: Option, + pub missing_features: Option, +} + +#[derive(Subdiagnostic)] +#[help(codegen_ssa_missing_features)] +pub struct MissingFeatures; + +impl Diagnostic<'_, G> for TargetFeatureDisableOrEnable<'_> { + fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { + let mut diag = Diag::new(dcx, level, fluent::codegen_ssa_target_feature_disable_or_enable); + if let Some(span) = self.span { + diag.span(span); + }; + if let Some(missing_features) = self.missing_features { + diag.subdiagnostic(missing_features); + } + diag.arg("features", self.features.join(", ")); + diag + } +} diff --git a/tests/ui/target-feature/tied-features.rs b/tests/ui/target-feature/tied-features.rs index e36649d8eb1..c6cdf21a3e3 100644 --- a/tests/ui/target-feature/tied-features.rs +++ b/tests/ui/target-feature/tied-features.rs @@ -1,4 +1,3 @@ -//@ build-fail //@ compile-flags: --crate-type=rlib --target=aarch64-unknown-linux-gnu //@ needs-llvm-components: aarch64 #![feature(no_core, lang_items)] @@ -7,7 +6,6 @@ #[lang="sized"] trait Sized {} -// FIXME: this should not need to be public. pub fn main() { #[target_feature(enable = "pacg")] //~^ ERROR must all be either enabled or disabled together @@ -25,10 +23,15 @@ pub fn main() { //~^ ERROR must all be either enabled or disabled together unsafe fn foo() {} - #[target_feature(enable = "paca,pacg")] unsafe fn bar() {} #[target_feature(enable = "paca")] #[target_feature(enable = "pacg")] unsafe fn baz() {} + +// Confirm that functions which do not end up collected for monomorphisation will still error. + +#[target_feature(enable = "paca")] +//~^ ERROR must all be either enabled or disabled together +unsafe fn unused() {} diff --git a/tests/ui/target-feature/tied-features.stderr b/tests/ui/target-feature/tied-features.stderr index 525c9084330..8d677735e84 100644 --- a/tests/ui/target-feature/tied-features.stderr +++ b/tests/ui/target-feature/tied-features.stderr @@ -1,5 +1,5 @@ error: the target features paca, pacg must all be either enabled or disabled together - --> $DIR/tied-features.rs:12:5 + --> $DIR/tied-features.rs:10:5 | LL | #[target_feature(enable = "pacg")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,12 +7,20 @@ LL | #[target_feature(enable = "pacg")] = help: add the missing features in a `target_feature` attribute error: the target features paca, pacg must all be either enabled or disabled together - --> $DIR/tied-features.rs:24:1 + --> $DIR/tied-features.rs:22:1 | LL | #[target_feature(enable = "paca")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: add the missing features in a `target_feature` attribute -error: aborting due to 2 previous errors +error: the target features paca, pacg must all be either enabled or disabled together + --> $DIR/tied-features.rs:35:1 + | +LL | #[target_feature(enable = "paca")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add the missing features in a `target_feature` attribute + +error: aborting due to 3 previous errors From d3ea0e4e13cfc1e0e2cddd50fd1e165ea131d57c Mon Sep 17 00:00:00 2001 From: Cameron Pickett Date: Thu, 26 Sep 2024 12:53:05 -0700 Subject: [PATCH 014/357] Do not output () on empty description --- src/bootstrap/src/lib.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index 7bf5b4e23d2..fcc7efbf8bd 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -1570,9 +1570,11 @@ Executed at: {executed_at}"#, fn rust_version(&self) -> String { let mut version = self.rust_info().version(self, &self.version); if let Some(ref s) = self.config.description { - version.push_str(" ("); - version.push_str(s); - version.push(')'); + if !s.is_empty() { + version.push_str(" ("); + version.push_str(s); + version.push(')'); + } } version } From d0165956fe070d12090896aa5546e509045471eb Mon Sep 17 00:00:00 2001 From: surechen Date: Thu, 26 Sep 2024 12:35:44 +0800 Subject: [PATCH 015/357] Add suggestion for removing invalid path separator `::` in function definition. for example: `fn invalid_path_separator::() {}` fixes: #130791 --- compiler/rustc_parse/messages.ftl | 3 +++ compiler/rustc_parse/src/errors.rs | 8 ++++++++ compiler/rustc_parse/src/parser/generics.rs | 7 +++++++ ...id-path-sep-in-fn-definition-issue-130791.fixed | 7 +++++++ ...valid-path-sep-in-fn-definition-issue-130791.rs | 7 +++++++ ...d-path-sep-in-fn-definition-issue-130791.stderr | 14 ++++++++++++++ 6 files changed, 46 insertions(+) create mode 100644 tests/ui/parser/issues/invalid-path-sep-in-fn-definition-issue-130791.fixed create mode 100644 tests/ui/parser/issues/invalid-path-sep-in-fn-definition-issue-130791.rs create mode 100644 tests/ui/parser/issues/invalid-path-sep-in-fn-definition-issue-130791.stderr diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index 6cb851eb8df..e8bff931f83 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -415,6 +415,9 @@ parse_invalid_meta_item = expected unsuffixed literal, found `{$token}` parse_invalid_offset_of = offset_of expects dot-separated field and variant names +parse_invalid_path_sep_in_fn_definition = invalid path separator in function definition + .suggestion = remove invalid path separator + parse_invalid_unicode_escape = invalid unicode character escape .label = invalid escape .help = unicode escape must {$surrogate -> diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 20bcefd4fe1..86ed38a96c5 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -1755,6 +1755,14 @@ pub(crate) struct MissingFnParams { pub span: Span, } +#[derive(Diagnostic)] +#[diag(parse_invalid_path_sep_in_fn_definition)] +pub(crate) struct InvalidPathSepInFnDefinition { + #[primary_span] + #[suggestion(code = "", applicability = "machine-applicable", style = "verbose")] + pub span: Span, +} + #[derive(Diagnostic)] #[diag(parse_missing_trait_in_trait_impl)] pub(crate) struct MissingTraitInTraitImpl { diff --git a/compiler/rustc_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs index b9256daa725..5aebe716b0a 100644 --- a/compiler/rustc_parse/src/parser/generics.rs +++ b/compiler/rustc_parse/src/parser/generics.rs @@ -269,6 +269,13 @@ impl<'a> Parser<'a> { /// | ( < lifetimes , typaramseq ( , )? > ) /// where typaramseq = ( typaram ) | ( typaram , typaramseq ) pub(super) fn parse_generics(&mut self) -> PResult<'a, ast::Generics> { + // invalid path separator `::` in function definition + // for example `fn invalid_path_separator::() {}` + if self.eat_noexpect(&token::PathSep) { + self.dcx() + .emit_err(errors::InvalidPathSepInFnDefinition { span: self.prev_token.span }); + } + let span_lo = self.token.span; let (params, span) = if self.eat_lt() { let params = self.parse_generic_params()?; diff --git a/tests/ui/parser/issues/invalid-path-sep-in-fn-definition-issue-130791.fixed b/tests/ui/parser/issues/invalid-path-sep-in-fn-definition-issue-130791.fixed new file mode 100644 index 00000000000..2c6fddccb73 --- /dev/null +++ b/tests/ui/parser/issues/invalid-path-sep-in-fn-definition-issue-130791.fixed @@ -0,0 +1,7 @@ +//@ run-rustfix + +#[allow(dead_code)] +fn invalid_path_separator() {} +//~^ ERROR invalid path separator in function definition + +fn main() {} diff --git a/tests/ui/parser/issues/invalid-path-sep-in-fn-definition-issue-130791.rs b/tests/ui/parser/issues/invalid-path-sep-in-fn-definition-issue-130791.rs new file mode 100644 index 00000000000..5f690615043 --- /dev/null +++ b/tests/ui/parser/issues/invalid-path-sep-in-fn-definition-issue-130791.rs @@ -0,0 +1,7 @@ +//@ run-rustfix + +#[allow(dead_code)] +fn invalid_path_separator::() {} +//~^ ERROR invalid path separator in function definition + +fn main() {} diff --git a/tests/ui/parser/issues/invalid-path-sep-in-fn-definition-issue-130791.stderr b/tests/ui/parser/issues/invalid-path-sep-in-fn-definition-issue-130791.stderr new file mode 100644 index 00000000000..3ad05050da0 --- /dev/null +++ b/tests/ui/parser/issues/invalid-path-sep-in-fn-definition-issue-130791.stderr @@ -0,0 +1,14 @@ +error: invalid path separator in function definition + --> $DIR/invalid-path-sep-in-fn-definition-issue-130791.rs:4:26 + | +LL | fn invalid_path_separator::() {} + | ^^ + | +help: remove invalid path separator + | +LL - fn invalid_path_separator::() {} +LL + fn invalid_path_separator() {} + | + +error: aborting due to 1 previous error + From 94ab726c7856cd7716d2a33db3e1915faed99008 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20Bj=C3=B8rnager=20Jensen?= Date: Wed, 25 Sep 2024 11:35:01 +0200 Subject: [PATCH 016/357] Add 'from_ref' and 'from_mut' constructors to 'core::ptr::NonNull'; --- library/core/src/lib.rs | 1 + library/core/src/ptr/non_null.rs | 28 ++++++++++--- ...ated_loop.PreCodegen.after.panic-abort.mir | 40 ++++++++++--------- ...ted_loop.PreCodegen.after.panic-unwind.mir | 20 +++++----- ...ward_loop.PreCodegen.after.panic-abort.mir | 16 ++++---- ...ard_loop.PreCodegen.after.panic-unwind.mir | 16 ++++---- ...erse_loop.PreCodegen.after.panic-abort.mir | 22 +++++----- ...rse_loop.PreCodegen.after.panic-unwind.mir | 22 +++++----- 8 files changed, 97 insertions(+), 68 deletions(-) diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 01cadd78cc0..53d11ebb5d6 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -174,6 +174,7 @@ #![feature(isqrt)] #![feature(lazy_get)] #![feature(link_cfg)] +#![feature(non_null_from_ref)] #![feature(offset_of_enum)] #![feature(panic_internals)] #![feature(ptr_alignment_type)] diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index daa40b3c9d2..44936d69bc9 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -230,6 +230,24 @@ impl NonNull { } } + /// Converts a reference to a `NonNull` pointer. + #[unstable(feature = "non_null_from_ref", issue = "130823")] + #[rustc_const_unstable(feature = "non_null_from_ref", issue = "130823")] + #[inline] + pub const fn from_ref(r: &T) -> Self { + // SAFETY: A reference cannot be null. + unsafe { NonNull { pointer: r as *const T } } + } + + /// Converts a mutable reference to a `NonNull` pointer. + #[unstable(feature = "non_null_from_ref", issue = "130823")] + #[rustc_const_unstable(feature = "non_null_from_ref", issue = "130823")] + #[inline] + pub const fn from_mut(r: &mut T) -> Self { + // SAFETY: A mutable reference cannot be null. + unsafe { NonNull { pointer: r as *mut T } } + } + /// Performs the same functionality as [`std::ptr::from_raw_parts`], except that a /// `NonNull` pointer is returned, as opposed to a raw `*const` pointer. /// @@ -1753,9 +1771,8 @@ impl From<&mut T> for NonNull { /// /// This conversion is safe and infallible since references cannot be null. #[inline] - fn from(reference: &mut T) -> Self { - // SAFETY: A mutable reference cannot be null. - unsafe { NonNull { pointer: reference as *mut T } } + fn from(r: &mut T) -> Self { + NonNull::from_mut(r) } } @@ -1765,8 +1782,7 @@ impl From<&T> for NonNull { /// /// This conversion is safe and infallible since references cannot be null. #[inline] - fn from(reference: &T) -> Self { - // SAFETY: A reference cannot be null. - unsafe { NonNull { pointer: reference as *const T } } + fn from(r: &T) -> Self { + NonNull::from_ref(r) } } diff --git a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir index 3aa483ed1ae..bd56ab67e00 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir @@ -19,30 +19,30 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { debug i => _22; debug x => _23; } - scope 17 (inlined > as Iterator>::next) { + scope 18 (inlined > as Iterator>::next) { let mut _14: &mut std::slice::Iter<'_, T>; let mut _15: std::option::Option<&T>; let mut _19: (usize, bool); let mut _20: (usize, &T); - scope 18 { + scope 19 { let _18: usize; - scope 23 { + scope 24 { } } - scope 19 { - scope 20 { - scope 26 (inlined as FromResidual>>::from_residual) { + scope 20 { + scope 21 { + scope 27 (inlined as FromResidual>>::from_residual) { } } } - scope 21 { - scope 22 { + scope 22 { + scope 23 { } } - scope 24 (inlined as Try>::branch) { + scope 25 (inlined as Try>::branch) { let mut _16: isize; let _17: &T; - scope 25 { + scope 26 { } } } @@ -59,29 +59,31 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { let _9: *const T; scope 7 { } - scope 11 (inlined without_provenance::) { + scope 12 (inlined without_provenance::) { } - scope 12 (inlined NonNull::::as_ptr) { + scope 13 (inlined NonNull::::as_ptr) { } - scope 13 (inlined std::ptr::mut_ptr::::add) { + scope 14 (inlined std::ptr::mut_ptr::::add) { } } scope 8 (inlined as From<&[T]>>::from) { - let mut _4: *const [T]; + scope 9 (inlined NonNull::<[T]>::from_ref) { + let mut _4: *const [T]; + } } - scope 9 (inlined NonNull::<[T]>::cast::) { + scope 10 (inlined NonNull::<[T]>::cast::) { let mut _5: *const T; - scope 10 (inlined NonNull::<[T]>::as_ptr) { + scope 11 (inlined NonNull::<[T]>::as_ptr) { } } } } } - scope 14 (inlined as Iterator>::enumerate) { - scope 15 (inlined Enumerate::>::new) { + scope 15 (inlined as Iterator>::enumerate) { + scope 16 (inlined Enumerate::>::new) { } } - scope 16 (inlined > as IntoIterator>::into_iter) { + scope 17 (inlined > as IntoIterator>::into_iter) { } bb0: { diff --git a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir index 4cc0aa0ed78..57f09a4631b 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir @@ -34,29 +34,31 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { let _9: *const T; scope 7 { } - scope 11 (inlined without_provenance::) { + scope 12 (inlined without_provenance::) { } - scope 12 (inlined NonNull::::as_ptr) { + scope 13 (inlined NonNull::::as_ptr) { } - scope 13 (inlined std::ptr::mut_ptr::::add) { + scope 14 (inlined std::ptr::mut_ptr::::add) { } } scope 8 (inlined as From<&[T]>>::from) { - let mut _4: *const [T]; + scope 9 (inlined NonNull::<[T]>::from_ref) { + let mut _4: *const [T]; + } } - scope 9 (inlined NonNull::<[T]>::cast::) { + scope 10 (inlined NonNull::<[T]>::cast::) { let mut _5: *const T; - scope 10 (inlined NonNull::<[T]>::as_ptr) { + scope 11 (inlined NonNull::<[T]>::as_ptr) { } } } } } - scope 14 (inlined as Iterator>::enumerate) { - scope 15 (inlined Enumerate::>::new) { + scope 15 (inlined as Iterator>::enumerate) { + scope 16 (inlined Enumerate::>::new) { } } - scope 16 (inlined > as IntoIterator>::into_iter) { + scope 17 (inlined > as IntoIterator>::into_iter) { } bb0: { diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir index 507afa63c68..4050304f469 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir @@ -31,25 +31,27 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { let _9: *const T; scope 7 { } - scope 11 (inlined without_provenance::) { + scope 12 (inlined without_provenance::) { } - scope 12 (inlined NonNull::::as_ptr) { + scope 13 (inlined NonNull::::as_ptr) { } - scope 13 (inlined std::ptr::mut_ptr::::add) { + scope 14 (inlined std::ptr::mut_ptr::::add) { } } scope 8 (inlined as From<&[T]>>::from) { - let mut _4: *const [T]; + scope 9 (inlined NonNull::<[T]>::from_ref) { + let mut _4: *const [T]; + } } - scope 9 (inlined NonNull::<[T]>::cast::) { + scope 10 (inlined NonNull::<[T]>::cast::) { let mut _5: *const T; - scope 10 (inlined NonNull::<[T]>::as_ptr) { + scope 11 (inlined NonNull::<[T]>::as_ptr) { } } } } } - scope 14 (inlined as IntoIterator>::into_iter) { + scope 15 (inlined as IntoIterator>::into_iter) { } bb0: { diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir index a25f12edc28..2c3d7ab1e4a 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir @@ -31,25 +31,27 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { let _9: *const T; scope 7 { } - scope 11 (inlined without_provenance::) { + scope 12 (inlined without_provenance::) { } - scope 12 (inlined NonNull::::as_ptr) { + scope 13 (inlined NonNull::::as_ptr) { } - scope 13 (inlined std::ptr::mut_ptr::::add) { + scope 14 (inlined std::ptr::mut_ptr::::add) { } } scope 8 (inlined as From<&[T]>>::from) { - let mut _4: *const [T]; + scope 9 (inlined NonNull::<[T]>::from_ref) { + let mut _4: *const [T]; + } } - scope 9 (inlined NonNull::<[T]>::cast::) { + scope 10 (inlined NonNull::<[T]>::cast::) { let mut _5: *const T; - scope 10 (inlined NonNull::<[T]>::as_ptr) { + scope 11 (inlined NonNull::<[T]>::as_ptr) { } } } } } - scope 14 (inlined as IntoIterator>::into_iter) { + scope 15 (inlined as IntoIterator>::into_iter) { } bb0: { diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir index 1b397a4e4cd..a6ccd435c40 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir @@ -18,7 +18,7 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { scope 2 { debug x => _17; } - scope 17 (inlined > as Iterator>::next) { + scope 18 (inlined > as Iterator>::next) { let mut _14: &mut std::slice::Iter<'_, T>; } } @@ -34,29 +34,31 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { let _9: *const T; scope 7 { } - scope 11 (inlined without_provenance::) { + scope 12 (inlined without_provenance::) { } - scope 12 (inlined NonNull::::as_ptr) { + scope 13 (inlined NonNull::::as_ptr) { } - scope 13 (inlined std::ptr::mut_ptr::::add) { + scope 14 (inlined std::ptr::mut_ptr::::add) { } } scope 8 (inlined as From<&[T]>>::from) { - let mut _4: *const [T]; + scope 9 (inlined NonNull::<[T]>::from_ref) { + let mut _4: *const [T]; + } } - scope 9 (inlined NonNull::<[T]>::cast::) { + scope 10 (inlined NonNull::<[T]>::cast::) { let mut _5: *const T; - scope 10 (inlined NonNull::<[T]>::as_ptr) { + scope 11 (inlined NonNull::<[T]>::as_ptr) { } } } } } - scope 14 (inlined as Iterator>::rev) { - scope 15 (inlined Rev::>::new) { + scope 15 (inlined as Iterator>::rev) { + scope 16 (inlined Rev::>::new) { } } - scope 16 (inlined > as IntoIterator>::into_iter) { + scope 17 (inlined > as IntoIterator>::into_iter) { } bb0: { diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir index 77689dd9b51..df11c8e3b49 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir @@ -18,7 +18,7 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { scope 2 { debug x => _17; } - scope 17 (inlined > as Iterator>::next) { + scope 18 (inlined > as Iterator>::next) { let mut _14: &mut std::slice::Iter<'_, T>; } } @@ -34,29 +34,31 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { let _9: *const T; scope 7 { } - scope 11 (inlined without_provenance::) { + scope 12 (inlined without_provenance::) { } - scope 12 (inlined NonNull::::as_ptr) { + scope 13 (inlined NonNull::::as_ptr) { } - scope 13 (inlined std::ptr::mut_ptr::::add) { + scope 14 (inlined std::ptr::mut_ptr::::add) { } } scope 8 (inlined as From<&[T]>>::from) { - let mut _4: *const [T]; + scope 9 (inlined NonNull::<[T]>::from_ref) { + let mut _4: *const [T]; + } } - scope 9 (inlined NonNull::<[T]>::cast::) { + scope 10 (inlined NonNull::<[T]>::cast::) { let mut _5: *const T; - scope 10 (inlined NonNull::<[T]>::as_ptr) { + scope 11 (inlined NonNull::<[T]>::as_ptr) { } } } } } - scope 14 (inlined as Iterator>::rev) { - scope 15 (inlined Rev::>::new) { + scope 15 (inlined as Iterator>::rev) { + scope 16 (inlined Rev::>::new) { } } - scope 16 (inlined > as IntoIterator>::into_iter) { + scope 17 (inlined > as IntoIterator>::into_iter) { } bb0: { From 8ef0ba22257aff64ad5e8e5b778482e6ce2bd9d2 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Sat, 28 Sep 2024 10:59:17 +0300 Subject: [PATCH 017/357] make `Step` doc-comments more clear Signed-off-by: onur-ozkan --- src/bootstrap/src/core/builder.rs | 40 +++++++++++++++++-------------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs index 47420f8fe72..0afa66feb7f 100644 --- a/src/bootstrap/src/core/builder.rs +++ b/src/bootstrap/src/core/builder.rs @@ -72,36 +72,40 @@ impl<'a> Deref for Builder<'a> { } pub trait Step: 'static + Clone + Debug + PartialEq + Eq + Hash { - /// `PathBuf` when directories are created or to return a `Compiler` once - /// it's been assembled. + /// Result type of `Step::run`. type Output: Clone; - /// Whether this step is run by default as part of its respective phase. - /// `true` here can still be overwritten by `should_run` calling `default_condition`. + /// Whether this step is run by default as part of its respective phase, as defined by the `describe` + /// macro in [`Builder::get_step_descriptions`]. + /// + /// Note: Even if set to `true`, it can still be overridden with [`ShouldRun::default_condition`] + /// by `Step::should_run`. const DEFAULT: bool = false; /// If true, then this rule should be skipped if --target was specified, but --host was not const ONLY_HOSTS: bool = false; - /// Primary function to execute this rule. Can call `builder.ensure()` - /// with other steps to run those. + /// Primary function to implement `Step` logic. /// - /// This gets called twice during a normal `./x.py` execution: first - /// with `dry_run() == true`, and then for real. + /// This function can be triggered in two ways: + /// 1. Directly from [`Builder::execute_cli`]. + /// 2. Indirectly by being called from other `Step`s using [`Builder::ensure`]. + /// + /// When called with [`Builder::execute_cli`] (as done by `Build::build`), this function executed twice: + /// - First in "dry-run" mode to validate certain things (like cyclic Step invocations, + /// directory creation, etc) super quickly. + /// - Then it's called again to run the actual, very expensive process. + /// + /// When triggered indirectly from other `Step`s, it may still run twice (as dry-run and real mode) + /// depending on the `Step::run` implementation of the caller. fn run(self, builder: &Builder<'_>) -> Self::Output; - /// When bootstrap is passed a set of paths, this controls whether this rule - /// will execute. However, it does not get called in a "default" context - /// when we are not passed any paths; in that case, `make_run` is called - /// directly. + /// Determines if this `Step` should be run when given specific paths (e.g., `x build $path`). fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_>; - /// Builds up a "root" rule, either as a default rule or from a path passed - /// to us. - /// - /// When path is `None`, we are executing in a context where no paths were - /// passed. When `./x.py build` is run, for example, this rule could get - /// called if it is in the correct list below with a path of `None`. + /// Called directly by the bootstrap `Step` handler when not triggered indirectly by other `Step`s using [`Builder::ensure`]. + /// For example, `./x.py test bootstrap` runs this for `test::Bootstrap`. Similarly, `./x.py test` runs it for every step + /// that is listed by the `describe` macro in [`Builder::get_step_descriptions`]. fn make_run(_run: RunConfig<'_>) { // It is reasonable to not have an implementation of make_run for rules // who do not want to get called from the root context. This means that From 1e30b5ae45ddf07fc7b6d233964e8eddebdc4ecd Mon Sep 17 00:00:00 2001 From: schvv31n Date: Mon, 9 Sep 2024 09:23:00 +0100 Subject: [PATCH 018/357] rustdoc-json: `Id(String)` -> `Id(u32)` --- src/librustdoc/json/conversions.rs | 596 +++++++++---------- src/librustdoc/json/mod.rs | 23 +- src/rustdoc-json-types/lib.rs | 6 +- src/tools/jsondoclint/src/validator.rs | 2 +- src/tools/jsondoclint/src/validator/tests.rs | 38 +- 5 files changed, 329 insertions(+), 336 deletions(-) diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index b411f9a1a52..b8791c9918b 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -4,20 +4,17 @@ #![allow(rustc::default_hash_types)] -use std::fmt; - use rustc_ast::ast; use rustc_attr::DeprecatedSince; use rustc_hir::def::{CtorKind, DefKind}; use rustc_hir::def_id::DefId; use rustc_metadata::rendered_const; -use rustc_middle::bug; -use rustc_middle::ty::{self, TyCtxt}; -use rustc_span::symbol::sym; -use rustc_span::{Pos, Symbol}; +use rustc_middle::{bug, ty}; +use rustc_span::{Pos, Symbol, sym}; use rustc_target::spec::abi::Abi as RustcAbi; use rustdoc_json_types::*; +use super::FullItemId; use crate::clean::{self, ItemId}; use crate::formats::FormatRenderer; use crate::formats::item_type::ItemType; @@ -40,7 +37,7 @@ impl JsonRenderer<'_> { Some(UrlFragment::UserWritten(_)) | None => *page_id, }; - (String::from(&**link), id_from_item_default(id.into(), self.tcx)) + (String::from(&**link), self.id_from_item_default(id.into())) }) .collect(); let docs = item.opt_doc_value(); @@ -48,7 +45,7 @@ impl JsonRenderer<'_> { let span = item.span(self.tcx); let visibility = item.visibility(self.tcx); let clean::Item { name, item_id, .. } = item; - let id = id_from_item(&item, self.tcx); + let id = self.id_from_item(&item); let inner = match item.kind { clean::KeywordItem => return None, clean::StrippedItem(ref inner) => { @@ -59,12 +56,12 @@ impl JsonRenderer<'_> { clean::ModuleItem(_) if self.imported_items.contains(&item_id.expect_def_id()) => { - from_clean_item(item, self.tcx) + from_clean_item(item, self) } _ => return None, } } - _ => from_clean_item(item, self.tcx), + _ => from_clean_item(item, self), }; Some(Item { id, @@ -105,37 +102,116 @@ impl JsonRenderer<'_> { Some(ty::Visibility::Public) => Visibility::Public, Some(ty::Visibility::Restricted(did)) if did.is_crate_root() => Visibility::Crate, Some(ty::Visibility::Restricted(did)) => Visibility::Restricted { - parent: id_from_item_default(did.into(), self.tcx), + parent: self.id_from_item_default(did.into()), path: self.tcx.def_path(did).to_string_no_crate_verbose(), }, } } -} -pub(crate) trait FromWithTcx { - fn from_tcx(f: T, tcx: TyCtxt<'_>) -> Self; -} + pub(crate) fn id_from_item_default(&self, item_id: ItemId) -> Id { + self.id_from_item_inner(item_id, None, None) + } -pub(crate) trait IntoWithTcx { - fn into_tcx(self, tcx: TyCtxt<'_>) -> T; -} + pub(crate) fn id_from_item_inner( + &self, + item_id: ItemId, + name: Option, + extra: Option, + ) -> Id { + let make_part = |def_id: DefId, name: Option, extra: Option| { + let name = match name { + Some(name) => Some(name), + None => { + // We need this workaround because primitive types' DefId actually refers to + // their parent module, which isn't present in the output JSON items. So + // instead, we directly get the primitive symbol + if matches!(self.tcx.def_kind(def_id), DefKind::Mod) + && let Some(prim) = self + .tcx + .get_attrs(def_id, sym::rustc_doc_primitive) + .find_map(|attr| attr.value_str()) + { + Some(prim) + } else { + self.tcx.opt_item_name(def_id) + } + } + }; -impl IntoWithTcx for T -where - U: FromWithTcx, -{ - fn into_tcx(self, tcx: TyCtxt<'_>) -> U { - U::from_tcx(self, tcx) + FullItemId { def_id, name, extra } + }; + + let key = match item_id { + ItemId::DefId(did) => (make_part(did, name, extra), None), + ItemId::Blanket { for_, impl_id } => { + (make_part(impl_id, None, None), Some(make_part(for_, name, extra))) + } + ItemId::Auto { for_, trait_ } => { + (make_part(trait_, None, None), Some(make_part(for_, name, extra))) + } + }; + + let mut interner = self.id_interner.borrow_mut(); + let len = interner.len(); + *interner + .entry(key) + .or_insert_with(|| Id(len.try_into().expect("too many items in a crate"))) + } + + pub(crate) fn id_from_item(&self, item: &clean::Item) -> Id { + match item.kind { + clean::ItemKind::ImportItem(ref import) => { + let extra = + import.source.did.map(ItemId::from).map(|i| self.id_from_item_default(i)); + self.id_from_item_inner(item.item_id, item.name, extra) + } + _ => self.id_from_item_inner(item.item_id, item.name, None), + } + } + + fn ids(&self, items: impl IntoIterator) -> Vec { + items + .into_iter() + .filter(|x| !x.is_stripped() && !x.is_keyword()) + .map(|i| self.id_from_item(&i)) + .collect() + } + + fn ids_keeping_stripped( + &self, + items: impl IntoIterator, + ) -> Vec> { + items + .into_iter() + .map(|i| (!i.is_stripped() && !i.is_keyword()).then(|| self.id_from_item(&i))) + .collect() } } -impl FromWithTcx for Vec +pub(crate) trait FromClean { + fn from_clean(f: T, renderer: &JsonRenderer<'_>) -> Self; +} + +pub(crate) trait IntoJson { + fn into_json(self, renderer: &JsonRenderer<'_>) -> T; +} + +impl IntoJson for T +where + U: FromClean, +{ + fn into_json(self, renderer: &JsonRenderer<'_>) -> U { + U::from_clean(self, renderer) + } +} + +impl FromClean for Vec where I: IntoIterator, - U: FromWithTcx, + U: FromClean, { - fn from_tcx(f: I, tcx: TyCtxt<'_>) -> Vec { - f.into_iter().map(|x| x.into_tcx(tcx)).collect() + fn from_clean(f: I, renderer: &JsonRenderer<'_>) -> Vec { + f.into_iter().map(|x| x.into_json(renderer)).collect() } } @@ -150,37 +226,38 @@ pub(crate) fn from_deprecation(deprecation: rustc_attr::Deprecation) -> Deprecat Deprecation { since, note: note.map(|s| s.to_string()) } } -impl FromWithTcx for GenericArgs { - fn from_tcx(args: clean::GenericArgs, tcx: TyCtxt<'_>) -> Self { +impl FromClean for GenericArgs { + fn from_clean(args: clean::GenericArgs, renderer: &JsonRenderer<'_>) -> Self { use clean::GenericArgs::*; match args { AngleBracketed { args, constraints } => GenericArgs::AngleBracketed { - args: args.into_vec().into_tcx(tcx), - constraints: constraints.into_tcx(tcx), + args: args.into_vec().into_json(renderer), + constraints: constraints.into_json(renderer), }, Parenthesized { inputs, output } => GenericArgs::Parenthesized { - inputs: inputs.into_vec().into_tcx(tcx), - output: output.map(|a| (*a).into_tcx(tcx)), + inputs: inputs.into_vec().into_json(renderer), + output: output.map(|a| (*a).into_json(renderer)), }, } } } -impl FromWithTcx for GenericArg { - fn from_tcx(arg: clean::GenericArg, tcx: TyCtxt<'_>) -> Self { +impl FromClean for GenericArg { + fn from_clean(arg: clean::GenericArg, renderer: &JsonRenderer<'_>) -> Self { use clean::GenericArg::*; match arg { Lifetime(l) => GenericArg::Lifetime(convert_lifetime(l)), - Type(t) => GenericArg::Type(t.into_tcx(tcx)), - Const(box c) => GenericArg::Const(c.into_tcx(tcx)), + Type(t) => GenericArg::Type(t.into_json(renderer)), + Const(box c) => GenericArg::Const(c.into_json(renderer)), Infer => GenericArg::Infer, } } } -impl FromWithTcx for Constant { +impl FromClean for Constant { // FIXME(generic_const_items): Add support for generic const items. - fn from_tcx(constant: clean::Constant, tcx: TyCtxt<'_>) -> Self { + fn from_clean(constant: clean::Constant, renderer: &JsonRenderer<'_>) -> Self { + let tcx = renderer.tcx; let expr = constant.expr(tcx); let value = constant.value(tcx); let is_literal = constant.is_literal(tcx); @@ -188,9 +265,10 @@ impl FromWithTcx for Constant { } } -impl FromWithTcx for Constant { +impl FromClean for Constant { // FIXME(generic_const_items): Add support for generic const items. - fn from_tcx(constant: clean::ConstantKind, tcx: TyCtxt<'_>) -> Self { + fn from_clean(constant: clean::ConstantKind, renderer: &JsonRenderer<'_>) -> Self { + let tcx = renderer.tcx; let expr = constant.expr(tcx); let value = constant.value(tcx); let is_literal = constant.is_literal(tcx); @@ -198,147 +276,62 @@ impl FromWithTcx for Constant { } } -impl FromWithTcx for AssocItemConstraint { - fn from_tcx(constraint: clean::AssocItemConstraint, tcx: TyCtxt<'_>) -> Self { +impl FromClean for AssocItemConstraint { + fn from_clean(constraint: clean::AssocItemConstraint, renderer: &JsonRenderer<'_>) -> Self { AssocItemConstraint { name: constraint.assoc.name.to_string(), - args: constraint.assoc.args.into_tcx(tcx), - binding: constraint.kind.into_tcx(tcx), + args: constraint.assoc.args.into_json(renderer), + binding: constraint.kind.into_json(renderer), } } } -impl FromWithTcx for AssocItemConstraintKind { - fn from_tcx(kind: clean::AssocItemConstraintKind, tcx: TyCtxt<'_>) -> Self { +impl FromClean for AssocItemConstraintKind { + fn from_clean(kind: clean::AssocItemConstraintKind, renderer: &JsonRenderer<'_>) -> Self { use clean::AssocItemConstraintKind::*; match kind { - Equality { term } => AssocItemConstraintKind::Equality(term.into_tcx(tcx)), - Bound { bounds } => AssocItemConstraintKind::Constraint(bounds.into_tcx(tcx)), + Equality { term } => AssocItemConstraintKind::Equality(term.into_json(renderer)), + Bound { bounds } => AssocItemConstraintKind::Constraint(bounds.into_json(renderer)), } } } -#[inline] -pub(crate) fn id_from_item_default(item_id: ItemId, tcx: TyCtxt<'_>) -> Id { - id_from_item_inner(item_id, tcx, None, None) -} - -/// It generates an ID as follows: -/// -/// `CRATE_ID:ITEM_ID[:NAME_ID][-EXTRA]`: -/// * If there is no `name`, `NAME_ID` is not generated. -/// * If there is no `extra`, `EXTRA` is not generated. -/// -/// * `name` is the item's name if available (it's not for impl blocks for example). -/// * `extra` is used for reexports: it contains the ID of the reexported item. It is used to allow -/// to have items with the same name but different types to both appear in the generated JSON. -pub(crate) fn id_from_item_inner( - item_id: ItemId, - tcx: TyCtxt<'_>, - name: Option, - extra: Option<&Id>, -) -> Id { - struct DisplayDefId<'a, 'b>(DefId, TyCtxt<'a>, Option<&'b Id>, Option); - - impl<'a, 'b> fmt::Display for DisplayDefId<'a, 'b> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let DisplayDefId(def_id, tcx, extra, name) = self; - // We need this workaround because primitive types' DefId actually refers to - // their parent module, which isn't present in the output JSON items. So - // instead, we directly get the primitive symbol and convert it to u32 to - // generate the ID. - let s; - let extra = if let Some(e) = extra { - s = format!("-{}", e.0); - &s - } else { - "" - }; - let name = match name { - Some(name) => format!(":{}", name.as_u32()), - None => { - // We need this workaround because primitive types' DefId actually refers to - // their parent module, which isn't present in the output JSON items. So - // instead, we directly get the primitive symbol and convert it to u32 to - // generate the ID. - if matches!(tcx.def_kind(def_id), DefKind::Mod) - && let Some(prim) = tcx - .get_attrs(*def_id, sym::rustc_doc_primitive) - .find_map(|attr| attr.value_str()) - { - format!(":{}", prim.as_u32()) - } else { - tcx.opt_item_name(*def_id) - .map(|n| format!(":{}", n.as_u32())) - .unwrap_or_default() - } - } - }; - write!(f, "{}:{}{name}{extra}", def_id.krate.as_u32(), u32::from(def_id.index)) - } - } - - match item_id { - ItemId::DefId(did) => Id(format!("{}", DisplayDefId(did, tcx, extra, name))), - ItemId::Blanket { for_, impl_id } => Id(format!( - "b:{}-{}", - DisplayDefId(impl_id, tcx, None, None), - DisplayDefId(for_, tcx, extra, name) - )), - ItemId::Auto { for_, trait_ } => Id(format!( - "a:{}-{}", - DisplayDefId(trait_, tcx, None, None), - DisplayDefId(for_, tcx, extra, name) - )), - } -} - -pub(crate) fn id_from_item(item: &clean::Item, tcx: TyCtxt<'_>) -> Id { - match item.kind { - clean::ItemKind::ImportItem(ref import) => { - let extra = - import.source.did.map(ItemId::from).map(|i| id_from_item_inner(i, tcx, None, None)); - id_from_item_inner(item.item_id, tcx, item.name, extra.as_ref()) - } - _ => id_from_item_inner(item.item_id, tcx, item.name, None), - } -} - -fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum { +fn from_clean_item(item: clean::Item, renderer: &JsonRenderer<'_>) -> ItemEnum { use clean::ItemKind::*; let name = item.name; let is_crate = item.is_crate(); - let header = item.fn_header(tcx); + let header = item.fn_header(renderer.tcx); match item.inner.kind { ModuleItem(m) => { - ItemEnum::Module(Module { is_crate, items: ids(m.items, tcx), is_stripped: false }) + ItemEnum::Module(Module { is_crate, items: renderer.ids(m.items), is_stripped: false }) } - ImportItem(i) => ItemEnum::Use(i.into_tcx(tcx)), - StructItem(s) => ItemEnum::Struct(s.into_tcx(tcx)), - UnionItem(u) => ItemEnum::Union(u.into_tcx(tcx)), - StructFieldItem(f) => ItemEnum::StructField(f.into_tcx(tcx)), - EnumItem(e) => ItemEnum::Enum(e.into_tcx(tcx)), - VariantItem(v) => ItemEnum::Variant(v.into_tcx(tcx)), - FunctionItem(f) => ItemEnum::Function(from_function(f, true, header.unwrap(), tcx)), + ImportItem(i) => ItemEnum::Use(i.into_json(renderer)), + StructItem(s) => ItemEnum::Struct(s.into_json(renderer)), + UnionItem(u) => ItemEnum::Union(u.into_json(renderer)), + StructFieldItem(f) => ItemEnum::StructField(f.into_json(renderer)), + EnumItem(e) => ItemEnum::Enum(e.into_json(renderer)), + VariantItem(v) => ItemEnum::Variant(v.into_json(renderer)), + FunctionItem(f) => ItemEnum::Function(from_function(f, true, header.unwrap(), renderer)), ForeignFunctionItem(f, _) => { - ItemEnum::Function(from_function(f, false, header.unwrap(), tcx)) + ItemEnum::Function(from_function(f, false, header.unwrap(), renderer)) } - TraitItem(t) => ItemEnum::Trait((*t).into_tcx(tcx)), - TraitAliasItem(t) => ItemEnum::TraitAlias(t.into_tcx(tcx)), - MethodItem(m, _) => ItemEnum::Function(from_function(m, true, header.unwrap(), tcx)), - TyMethodItem(m) => ItemEnum::Function(from_function(m, false, header.unwrap(), tcx)), - ImplItem(i) => ItemEnum::Impl((*i).into_tcx(tcx)), - StaticItem(s) => ItemEnum::Static(s.into_tcx(tcx)), - ForeignStaticItem(s, _) => ItemEnum::Static(s.into_tcx(tcx)), + TraitItem(t) => ItemEnum::Trait((*t).into_json(renderer)), + TraitAliasItem(t) => ItemEnum::TraitAlias(t.into_json(renderer)), + MethodItem(m, _) => ItemEnum::Function(from_function(m, true, header.unwrap(), renderer)), + TyMethodItem(m) => ItemEnum::Function(from_function(m, false, header.unwrap(), renderer)), + ImplItem(i) => ItemEnum::Impl((*i).into_json(renderer)), + StaticItem(s) => ItemEnum::Static(s.into_json(renderer)), + ForeignStaticItem(s, _) => ItemEnum::Static(s.into_json(renderer)), ForeignTypeItem => ItemEnum::ExternType, - TypeAliasItem(t) => ItemEnum::TypeAlias(t.into_tcx(tcx)), + TypeAliasItem(t) => ItemEnum::TypeAlias(t.into_json(renderer)), // FIXME(generic_const_items): Add support for generic free consts - ConstantItem(ci) => { - ItemEnum::Constant { type_: ci.type_.into_tcx(tcx), const_: ci.kind.into_tcx(tcx) } - } + ConstantItem(ci) => ItemEnum::Constant { + type_: ci.type_.into_json(renderer), + const_: ci.kind.into_json(renderer), + }, MacroItem(m) => ItemEnum::Macro(m.source), - ProcMacroItem(m) => ItemEnum::ProcMacro(m.into_tcx(tcx)), + ProcMacroItem(m) => ItemEnum::ProcMacro(m.into_json(renderer)), PrimitiveItem(p) => { ItemEnum::Primitive(Primitive { name: p.as_sym().to_string(), @@ -347,19 +340,22 @@ fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum { } // FIXME(generic_const_items): Add support for generic associated consts. TyAssocConstItem(_generics, ty) => { - ItemEnum::AssocConst { type_: (*ty).into_tcx(tcx), value: None } + ItemEnum::AssocConst { type_: (*ty).into_json(renderer), value: None } } // FIXME(generic_const_items): Add support for generic associated consts. - AssocConstItem(ci) => { - ItemEnum::AssocConst { type_: ci.type_.into_tcx(tcx), value: Some(ci.kind.expr(tcx)) } - } - TyAssocTypeItem(g, b) => { - ItemEnum::AssocType { generics: g.into_tcx(tcx), bounds: b.into_tcx(tcx), type_: None } - } + AssocConstItem(ci) => ItemEnum::AssocConst { + type_: ci.type_.into_json(renderer), + value: Some(ci.kind.expr(renderer.tcx)), + }, + TyAssocTypeItem(g, b) => ItemEnum::AssocType { + generics: g.into_json(renderer), + bounds: b.into_json(renderer), + type_: None, + }, AssocTypeItem(t, b) => ItemEnum::AssocType { - generics: t.generics.into_tcx(tcx), - bounds: b.into_tcx(tcx), - type_: Some(t.item_type.unwrap_or(t.type_).into_tcx(tcx)), + generics: t.generics.into_json(renderer), + bounds: b.into_json(renderer), + type_: Some(t.item_type.unwrap_or(t.type_).into_json(renderer)), }, // `convert_item` early returns `None` for stripped items and keywords. KeywordItem => unreachable!(), @@ -367,7 +363,7 @@ fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum { match *inner { ModuleItem(m) => ItemEnum::Module(Module { is_crate, - items: ids(m.items, tcx), + items: renderer.ids(m.items), is_stripped: true, }), // `convert_item` early returns `None` for stripped items we're not including @@ -381,36 +377,36 @@ fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum { } } -impl FromWithTcx for Struct { - fn from_tcx(struct_: clean::Struct, tcx: TyCtxt<'_>) -> Self { +impl FromClean for Struct { + fn from_clean(struct_: clean::Struct, renderer: &JsonRenderer<'_>) -> Self { let has_stripped_fields = struct_.has_stripped_entries(); let clean::Struct { ctor_kind, generics, fields } = struct_; let kind = match ctor_kind { - Some(CtorKind::Fn) => StructKind::Tuple(ids_keeping_stripped(fields, tcx)), + Some(CtorKind::Fn) => StructKind::Tuple(renderer.ids_keeping_stripped(fields)), Some(CtorKind::Const) => { assert!(fields.is_empty()); StructKind::Unit } - None => StructKind::Plain { fields: ids(fields, tcx), has_stripped_fields }, + None => StructKind::Plain { fields: renderer.ids(fields), has_stripped_fields }, }; Struct { kind, - generics: generics.into_tcx(tcx), + generics: generics.into_json(renderer), impls: Vec::new(), // Added in JsonRenderer::item } } } -impl FromWithTcx for Union { - fn from_tcx(union_: clean::Union, tcx: TyCtxt<'_>) -> Self { +impl FromClean for Union { + fn from_clean(union_: clean::Union, renderer: &JsonRenderer<'_>) -> Self { let has_stripped_fields = union_.has_stripped_entries(); let clean::Union { generics, fields } = union_; Union { - generics: generics.into_tcx(tcx), + generics: generics.into_json(renderer), has_stripped_fields, - fields: ids(fields, tcx), + fields: renderer.ids(fields), impls: Vec::new(), // Added in JsonRenderer::item } } @@ -444,51 +440,51 @@ fn convert_lifetime(l: clean::Lifetime) -> String { l.0.to_string() } -impl FromWithTcx for Generics { - fn from_tcx(generics: clean::Generics, tcx: TyCtxt<'_>) -> Self { +impl FromClean for Generics { + fn from_clean(generics: clean::Generics, renderer: &JsonRenderer<'_>) -> Self { Generics { - params: generics.params.into_tcx(tcx), - where_predicates: generics.where_predicates.into_tcx(tcx), + params: generics.params.into_json(renderer), + where_predicates: generics.where_predicates.into_json(renderer), } } } -impl FromWithTcx for GenericParamDef { - fn from_tcx(generic_param: clean::GenericParamDef, tcx: TyCtxt<'_>) -> Self { +impl FromClean for GenericParamDef { + fn from_clean(generic_param: clean::GenericParamDef, renderer: &JsonRenderer<'_>) -> Self { GenericParamDef { name: generic_param.name.to_string(), - kind: generic_param.kind.into_tcx(tcx), + kind: generic_param.kind.into_json(renderer), } } } -impl FromWithTcx for GenericParamDefKind { - fn from_tcx(kind: clean::GenericParamDefKind, tcx: TyCtxt<'_>) -> Self { +impl FromClean for GenericParamDefKind { + fn from_clean(kind: clean::GenericParamDefKind, renderer: &JsonRenderer<'_>) -> Self { use clean::GenericParamDefKind::*; match kind { Lifetime { outlives } => GenericParamDefKind::Lifetime { outlives: outlives.into_iter().map(convert_lifetime).collect(), }, Type { bounds, default, synthetic } => GenericParamDefKind::Type { - bounds: bounds.into_tcx(tcx), - default: default.map(|x| (*x).into_tcx(tcx)), + bounds: bounds.into_json(renderer), + default: default.map(|x| (*x).into_json(renderer)), is_synthetic: synthetic, }, Const { ty, default, synthetic: _ } => GenericParamDefKind::Const { - type_: (*ty).into_tcx(tcx), + type_: (*ty).into_json(renderer), default: default.map(|x| *x), }, } } } -impl FromWithTcx for WherePredicate { - fn from_tcx(predicate: clean::WherePredicate, tcx: TyCtxt<'_>) -> Self { +impl FromClean for WherePredicate { + fn from_clean(predicate: clean::WherePredicate, renderer: &JsonRenderer<'_>) -> Self { use clean::WherePredicate::*; match predicate { BoundPredicate { ty, bounds, bound_params } => WherePredicate::BoundPredicate { - type_: ty.into_tcx(tcx), - bounds: bounds.into_tcx(tcx), + type_: ty.into_json(renderer), + bounds: bounds.into_json(renderer), generic_params: bound_params .into_iter() .map(|x| { @@ -503,15 +499,15 @@ impl FromWithTcx for WherePredicate { GenericParamDefKind::Type { bounds: bounds .into_iter() - .map(|bound| bound.into_tcx(tcx)) + .map(|bound| bound.into_json(renderer)) .collect(), - default: default.map(|ty| (*ty).into_tcx(tcx)), + default: default.map(|ty| (*ty).into_json(renderer)), is_synthetic: synthetic, } } clean::GenericParamDefKind::Const { ty, default, synthetic: _ } => { GenericParamDefKind::Const { - type_: (*ty).into_tcx(tcx), + type_: (*ty).into_json(renderer), default: default.map(|d| *d), } } @@ -530,21 +526,22 @@ impl FromWithTcx for WherePredicate { }) .collect(), }, - EqPredicate { lhs, rhs } => { - WherePredicate::EqPredicate { lhs: lhs.into_tcx(tcx), rhs: rhs.into_tcx(tcx) } - } + EqPredicate { lhs, rhs } => WherePredicate::EqPredicate { + lhs: lhs.into_json(renderer), + rhs: rhs.into_json(renderer), + }, } } } -impl FromWithTcx for GenericBound { - fn from_tcx(bound: clean::GenericBound, tcx: TyCtxt<'_>) -> Self { +impl FromClean for GenericBound { + fn from_clean(bound: clean::GenericBound, renderer: &JsonRenderer<'_>) -> Self { use clean::GenericBound::*; match bound { TraitBound(clean::PolyTrait { trait_, generic_params }, modifier) => { GenericBound::TraitBound { - trait_: trait_.into_tcx(tcx), - generic_params: generic_params.into_tcx(tcx), + trait_: trait_.into_json(renderer), + generic_params: generic_params.into_json(renderer), modifier: from_trait_bound_modifier(modifier), } } @@ -572,73 +569,75 @@ pub(crate) fn from_trait_bound_modifier( } } -impl FromWithTcx for Type { - fn from_tcx(ty: clean::Type, tcx: TyCtxt<'_>) -> Self { +impl FromClean for Type { + fn from_clean(ty: clean::Type, renderer: &JsonRenderer<'_>) -> Self { use clean::Type::{ Array, BareFunction, BorrowedRef, Generic, ImplTrait, Infer, Primitive, QPath, RawPointer, SelfTy, Slice, Tuple, }; match ty { - clean::Type::Path { path } => Type::ResolvedPath(path.into_tcx(tcx)), + clean::Type::Path { path } => Type::ResolvedPath(path.into_json(renderer)), clean::Type::DynTrait(bounds, lt) => Type::DynTrait(DynTrait { lifetime: lt.map(convert_lifetime), - traits: bounds.into_tcx(tcx), + traits: bounds.into_json(renderer), }), Generic(s) => Type::Generic(s.to_string()), // FIXME: add dedicated variant to json Type? SelfTy => Type::Generic("Self".to_owned()), Primitive(p) => Type::Primitive(p.as_sym().to_string()), - BareFunction(f) => Type::FunctionPointer(Box::new((*f).into_tcx(tcx))), - Tuple(t) => Type::Tuple(t.into_tcx(tcx)), - Slice(t) => Type::Slice(Box::new((*t).into_tcx(tcx))), - Array(t, s) => Type::Array { type_: Box::new((*t).into_tcx(tcx)), len: s.to_string() }, + BareFunction(f) => Type::FunctionPointer(Box::new((*f).into_json(renderer))), + Tuple(t) => Type::Tuple(t.into_json(renderer)), + Slice(t) => Type::Slice(Box::new((*t).into_json(renderer))), + Array(t, s) => { + Type::Array { type_: Box::new((*t).into_json(renderer)), len: s.to_string() } + } clean::Type::Pat(t, p) => Type::Pat { - type_: Box::new((*t).into_tcx(tcx)), + type_: Box::new((*t).into_json(renderer)), __pat_unstable_do_not_use: p.to_string(), }, - ImplTrait(g) => Type::ImplTrait(g.into_tcx(tcx)), + ImplTrait(g) => Type::ImplTrait(g.into_json(renderer)), Infer => Type::Infer, RawPointer(mutability, type_) => Type::RawPointer { is_mutable: mutability == ast::Mutability::Mut, - type_: Box::new((*type_).into_tcx(tcx)), + type_: Box::new((*type_).into_json(renderer)), }, BorrowedRef { lifetime, mutability, type_ } => Type::BorrowedRef { lifetime: lifetime.map(convert_lifetime), is_mutable: mutability == ast::Mutability::Mut, - type_: Box::new((*type_).into_tcx(tcx)), + type_: Box::new((*type_).into_json(renderer)), }, QPath(box clean::QPathData { assoc, self_type, trait_, .. }) => Type::QualifiedPath { name: assoc.name.to_string(), - args: Box::new(assoc.args.into_tcx(tcx)), - self_type: Box::new(self_type.into_tcx(tcx)), - trait_: trait_.map(|trait_| trait_.into_tcx(tcx)), + args: Box::new(assoc.args.into_json(renderer)), + self_type: Box::new(self_type.into_json(renderer)), + trait_: trait_.map(|trait_| trait_.into_json(renderer)), }, } } } -impl FromWithTcx for Path { - fn from_tcx(path: clean::Path, tcx: TyCtxt<'_>) -> Path { +impl FromClean for Path { + fn from_clean(path: clean::Path, renderer: &JsonRenderer<'_>) -> Path { Path { name: path.whole_name(), - id: id_from_item_default(path.def_id().into(), tcx), - args: path.segments.last().map(|args| Box::new(args.clone().args.into_tcx(tcx))), + id: renderer.id_from_item_default(path.def_id().into()), + args: path.segments.last().map(|args| Box::new(args.clone().args.into_json(renderer))), } } } -impl FromWithTcx for Term { - fn from_tcx(term: clean::Term, tcx: TyCtxt<'_>) -> Term { +impl FromClean for Term { + fn from_clean(term: clean::Term, renderer: &JsonRenderer<'_>) -> Term { match term { - clean::Term::Type(ty) => Term::Type(FromWithTcx::from_tcx(ty, tcx)), - clean::Term::Constant(c) => Term::Constant(FromWithTcx::from_tcx(c, tcx)), + clean::Term::Type(ty) => Term::Type(ty.into_json(renderer)), + clean::Term::Constant(c) => Term::Constant(c.into_json(renderer)), } } } -impl FromWithTcx for FunctionPointer { - fn from_tcx(bare_decl: clean::BareFunctionDecl, tcx: TyCtxt<'_>) -> Self { +impl FromClean for FunctionPointer { + fn from_clean(bare_decl: clean::BareFunctionDecl, renderer: &JsonRenderer<'_>) -> Self { let clean::BareFunctionDecl { safety, generic_params, decl, abi } = bare_decl; FunctionPointer { header: FunctionHeader { @@ -647,29 +646,30 @@ impl FromWithTcx for FunctionPointer { is_async: false, abi: convert_abi(abi), }, - generic_params: generic_params.into_tcx(tcx), - sig: decl.into_tcx(tcx), + generic_params: generic_params.into_json(renderer), + sig: decl.into_json(renderer), } } } -impl FromWithTcx for FunctionSignature { - fn from_tcx(decl: clean::FnDecl, tcx: TyCtxt<'_>) -> Self { +impl FromClean for FunctionSignature { + fn from_clean(decl: clean::FnDecl, renderer: &JsonRenderer<'_>) -> Self { let clean::FnDecl { inputs, output, c_variadic } = decl; FunctionSignature { inputs: inputs .values .into_iter() - .map(|arg| (arg.name.to_string(), arg.type_.into_tcx(tcx))) + .map(|arg| (arg.name.to_string(), arg.type_.into_json(renderer))) .collect(), - output: if output.is_unit() { None } else { Some(output.into_tcx(tcx)) }, + output: if output.is_unit() { None } else { Some(output.into_json(renderer)) }, is_c_variadic: c_variadic, } } } -impl FromWithTcx for Trait { - fn from_tcx(trait_: clean::Trait, tcx: TyCtxt<'_>) -> Self { +impl FromClean for Trait { + fn from_clean(trait_: clean::Trait, renderer: &JsonRenderer<'_>) -> Self { + let tcx = renderer.tcx; let is_auto = trait_.is_auto(tcx); let is_unsafe = trait_.safety(tcx) == rustc_hir::Safety::Unsafe; let is_object_safe = trait_.is_object_safe(tcx); @@ -678,26 +678,29 @@ impl FromWithTcx for Trait { is_auto, is_unsafe, is_object_safe, - items: ids(items, tcx), - generics: generics.into_tcx(tcx), - bounds: bounds.into_tcx(tcx), + items: renderer.ids(items), + generics: generics.into_json(renderer), + bounds: bounds.into_json(renderer), implementations: Vec::new(), // Added in JsonRenderer::item } } } -impl FromWithTcx for PolyTrait { - fn from_tcx( +impl FromClean for PolyTrait { + fn from_clean( clean::PolyTrait { trait_, generic_params }: clean::PolyTrait, - tcx: TyCtxt<'_>, + renderer: &JsonRenderer<'_>, ) -> Self { - PolyTrait { trait_: trait_.into_tcx(tcx), generic_params: generic_params.into_tcx(tcx) } + PolyTrait { + trait_: trait_.into_json(renderer), + generic_params: generic_params.into_json(renderer), + } } } -impl FromWithTcx for Impl { - fn from_tcx(impl_: clean::Impl, tcx: TyCtxt<'_>) -> Self { - let provided_trait_methods = impl_.provided_trait_methods(tcx); +impl FromClean for Impl { + fn from_clean(impl_: clean::Impl, renderer: &JsonRenderer<'_>) -> Self { + let provided_trait_methods = impl_.provided_trait_methods(renderer.tcx); let clean::Impl { safety, generics, trait_, for_, items, polarity, kind } = impl_; // FIXME: use something like ImplKind in JSON? let (is_synthetic, blanket_impl) = match kind { @@ -711,17 +714,17 @@ impl FromWithTcx for Impl { }; Impl { is_unsafe: safety == rustc_hir::Safety::Unsafe, - generics: generics.into_tcx(tcx), + generics: generics.into_json(renderer), provided_trait_methods: provided_trait_methods .into_iter() .map(|x| x.to_string()) .collect(), - trait_: trait_.map(|path| path.into_tcx(tcx)), - for_: for_.into_tcx(tcx), - items: ids(items, tcx), + trait_: trait_.map(|path| path.into_json(renderer)), + for_: for_.into_json(renderer), + items: renderer.ids(items), is_negative, is_synthetic, - blanket_impl: blanket_impl.map(|x| x.into_tcx(tcx)), + blanket_impl: blanket_impl.map(|x| x.into_json(renderer)), } } } @@ -730,42 +733,42 @@ pub(crate) fn from_function( function: Box, has_body: bool, header: rustc_hir::FnHeader, - tcx: TyCtxt<'_>, + renderer: &JsonRenderer<'_>, ) -> Function { let clean::Function { decl, generics } = *function; Function { - sig: decl.into_tcx(tcx), - generics: generics.into_tcx(tcx), + sig: decl.into_json(renderer), + generics: generics.into_json(renderer), header: from_fn_header(&header), has_body, } } -impl FromWithTcx for Enum { - fn from_tcx(enum_: clean::Enum, tcx: TyCtxt<'_>) -> Self { +impl FromClean for Enum { + fn from_clean(enum_: clean::Enum, renderer: &JsonRenderer<'_>) -> Self { let has_stripped_variants = enum_.has_stripped_entries(); let clean::Enum { variants, generics } = enum_; Enum { - generics: generics.into_tcx(tcx), + generics: generics.into_json(renderer), has_stripped_variants, - variants: ids(variants, tcx), + variants: renderer.ids(variants), impls: Vec::new(), // Added in JsonRenderer::item } } } -impl FromWithTcx for Variant { - fn from_tcx(variant: clean::Variant, tcx: TyCtxt<'_>) -> Self { +impl FromClean for Variant { + fn from_clean(variant: clean::Variant, renderer: &JsonRenderer<'_>) -> Self { use clean::VariantKind::*; - let discriminant = variant.discriminant.map(|d| d.into_tcx(tcx)); + let discriminant = variant.discriminant.map(|d| d.into_json(renderer)); let kind = match variant.kind { CLike => VariantKind::Plain, - Tuple(fields) => VariantKind::Tuple(ids_keeping_stripped(fields, tcx)), + Tuple(fields) => VariantKind::Tuple(renderer.ids_keeping_stripped(fields)), Struct(s) => VariantKind::Struct { has_stripped_fields: s.has_stripped_entries(), - fields: ids(s.fields, tcx), + fields: renderer.ids(s.fields), }, }; @@ -773,8 +776,9 @@ impl FromWithTcx for Variant { } } -impl FromWithTcx for Discriminant { - fn from_tcx(disr: clean::Discriminant, tcx: TyCtxt<'_>) -> Self { +impl FromClean for Discriminant { + fn from_clean(disr: clean::Discriminant, renderer: &JsonRenderer<'_>) -> Self { + let tcx = renderer.tcx; Discriminant { // expr is only none if going through the inlining path, which gets // `rustc_middle` types, not `rustc_hir`, but because JSON never inlines @@ -785,8 +789,8 @@ impl FromWithTcx for Discriminant { } } -impl FromWithTcx for Use { - fn from_tcx(import: clean::Import, tcx: TyCtxt<'_>) -> Self { +impl FromClean for Use { + fn from_clean(import: clean::Import, renderer: &JsonRenderer<'_>) -> Self { use clean::ImportKind::*; let (name, is_glob) = match import.kind { Simple(s) => (s.to_string(), false), @@ -798,14 +802,14 @@ impl FromWithTcx for Use { Use { source: import.source.path.whole_name(), name, - id: import.source.did.map(ItemId::from).map(|i| id_from_item_default(i, tcx)), + id: import.source.did.map(ItemId::from).map(|i| renderer.id_from_item_default(i)), is_glob, } } } -impl FromWithTcx for ProcMacro { - fn from_tcx(mac: clean::ProcMacro, _tcx: TyCtxt<'_>) -> Self { +impl FromClean for ProcMacro { + fn from_clean(mac: clean::ProcMacro, _renderer: &JsonRenderer<'_>) -> Self { ProcMacro { kind: from_macro_kind(mac.kind), helpers: mac.helpers.iter().map(|x| x.to_string()).collect(), @@ -822,17 +826,18 @@ pub(crate) fn from_macro_kind(kind: rustc_span::hygiene::MacroKind) -> MacroKind } } -impl FromWithTcx> for TypeAlias { - fn from_tcx(type_alias: Box, tcx: TyCtxt<'_>) -> Self { +impl FromClean> for TypeAlias { + fn from_clean(type_alias: Box, renderer: &JsonRenderer<'_>) -> Self { let clean::TypeAlias { type_, generics, item_type: _, inner_type: _ } = *type_alias; - TypeAlias { type_: type_.into_tcx(tcx), generics: generics.into_tcx(tcx) } + TypeAlias { type_: type_.into_json(renderer), generics: generics.into_json(renderer) } } } -impl FromWithTcx for Static { - fn from_tcx(stat: clean::Static, tcx: TyCtxt<'_>) -> Self { +impl FromClean for Static { + fn from_clean(stat: clean::Static, renderer: &JsonRenderer<'_>) -> Self { + let tcx = renderer.tcx; Static { - type_: (*stat.type_).into_tcx(tcx), + type_: (*stat.type_).into_json(renderer), is_mutable: stat.mutability == ast::Mutability::Mut, expr: stat .expr @@ -842,14 +847,17 @@ impl FromWithTcx for Static { } } -impl FromWithTcx for TraitAlias { - fn from_tcx(alias: clean::TraitAlias, tcx: TyCtxt<'_>) -> Self { - TraitAlias { generics: alias.generics.into_tcx(tcx), params: alias.bounds.into_tcx(tcx) } +impl FromClean for TraitAlias { + fn from_clean(alias: clean::TraitAlias, renderer: &JsonRenderer<'_>) -> Self { + TraitAlias { + generics: alias.generics.into_json(renderer), + params: alias.bounds.into_json(renderer), + } } } -impl FromWithTcx for ItemKind { - fn from_tcx(kind: ItemType, _tcx: TyCtxt<'_>) -> Self { +impl FromClean for ItemKind { + fn from_clean(kind: ItemType, _renderer: &JsonRenderer<'_>) -> Self { use ItemType::*; match kind { Module => ItemKind::Module, @@ -878,25 +886,3 @@ impl FromWithTcx for ItemKind { } } } - -fn ids(items: impl IntoIterator, tcx: TyCtxt<'_>) -> Vec { - items - .into_iter() - .filter(|x| !x.is_stripped() && !x.is_keyword()) - .map(|i| id_from_item(&i, tcx)) - .collect() -} - -fn ids_keeping_stripped( - items: impl IntoIterator, - tcx: TyCtxt<'_>, -) -> Vec> { - items - .into_iter() - .map( - |i| { - if !i.is_stripped() && !i.is_keyword() { Some(id_from_item(&i, tcx)) } else { None } - }, - ) - .collect() -} diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs index b7a683eed1c..df97c5ea263 100644 --- a/src/librustdoc/json/mod.rs +++ b/src/librustdoc/json/mod.rs @@ -16,6 +16,7 @@ use std::rc::Rc; use rustc_hir::def_id::{DefId, DefIdSet}; use rustc_middle::ty::TyCtxt; use rustc_session::Session; +use rustc_span::Symbol; use rustc_span::def_id::LOCAL_CRATE; use rustdoc_json_types as types; // It's important to use the FxHashMap from rustdoc_json_types here, instead of @@ -31,9 +32,17 @@ use crate::docfs::PathError; use crate::error::Error; use crate::formats::FormatRenderer; use crate::formats::cache::Cache; -use crate::json::conversions::{IntoWithTcx, id_from_item, id_from_item_default}; +use crate::json::conversions::IntoJson; use crate::{clean, try_err}; +#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)] +struct FullItemId { + def_id: DefId, + name: Option, + /// Used to distinguish imports of different items with the same name + extra: Option, +} + #[derive(Clone)] pub(crate) struct JsonRenderer<'tcx> { tcx: TyCtxt<'tcx>, @@ -46,6 +55,7 @@ pub(crate) struct JsonRenderer<'tcx> { out_dir: Option, cache: Rc, imported_items: DefIdSet, + id_interner: Rc), types::Id>>>, } impl<'tcx> JsonRenderer<'tcx> { @@ -63,7 +73,7 @@ impl<'tcx> JsonRenderer<'tcx> { .map(|i| { let item = &i.impl_item; self.item(item.clone()).unwrap(); - id_from_item(&item, self.tcx) + self.id_from_item(&item) }) .collect() }) @@ -94,7 +104,7 @@ impl<'tcx> JsonRenderer<'tcx> { if item.item_id.is_local() || is_primitive_impl { self.item(item.clone()).unwrap(); - Some(id_from_item(&item, self.tcx)) + Some(self.id_from_item(&item)) } else { None } @@ -145,6 +155,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { out_dir: if options.output_to_stdout { None } else { Some(options.output) }, cache: Rc::new(cache), imported_items, + id_interner: Default::default(), }, krate, )) @@ -243,7 +254,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { debug!("Constructing Output"); let output_crate = types::Crate { - root: types::Id(format!("0:0:{}", e.name(self.tcx).as_u32())), + root: self.id_from_item_default(e.def_id().into()), crate_version: self.cache.crate_version.clone(), includes_private: self.cache.document_private, index, @@ -253,10 +264,10 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { .iter() .chain(&self.cache.external_paths) .map(|(&k, &(ref path, kind))| { - (id_from_item_default(k.into(), self.tcx), types::ItemSummary { + (self.id_from_item_default(k.into()), types::ItemSummary { crate_id: k.krate.as_u32(), path: path.iter().map(|s| s.to_string()).collect(), - kind: kind.into_tcx(self.tcx), + kind: kind.into_json(self), }) }) .collect(), diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs index b3707cf6157..c94efafd5b7 100644 --- a/src/rustdoc-json-types/lib.rs +++ b/src/rustdoc-json-types/lib.rs @@ -13,7 +13,7 @@ use serde::{Deserialize, Serialize}; /// This integer is incremented with every breaking change to the API, /// and is returned along with the JSON blob as [`Crate::format_version`]. /// Consuming code should assert that this value matches the format version(s) that it supports. -pub const FORMAT_VERSION: u32 = 34; +pub const FORMAT_VERSION: u32 = 35; /// The root of the emitted JSON blob. /// @@ -296,9 +296,9 @@ pub enum AssocItemConstraintKind { /// Rustdoc makes no guarantees about the inner value of Id's. Applications /// should treat them as opaque keys to lookup items, and avoid attempting /// to parse them, or otherwise depend on any implementation details. -#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] // FIXME(aDotInTheVoid): Consider making this non-public in rustdoc-types. -pub struct Id(pub String); +pub struct Id(pub u32); /// The fundamental kind of an item. Unlike [`ItemEnum`], this does not carry any aditional info. /// diff --git a/src/tools/jsondoclint/src/validator.rs b/src/tools/jsondoclint/src/validator.rs index b04919bdd3e..f7c752033c5 100644 --- a/src/tools/jsondoclint/src/validator.rs +++ b/src/tools/jsondoclint/src/validator.rs @@ -418,7 +418,7 @@ impl<'a> Validator<'a> { } else if !self.missing_ids.contains(id) { self.missing_ids.insert(id); - let sels = json_find::find_selector(&self.krate_json, &Value::String(id.0.clone())); + let sels = json_find::find_selector(&self.krate_json, &Value::Number(id.0.into())); assert_ne!(sels.len(), 0); self.fail(id, ErrorKind::NotFound(sels)) diff --git a/src/tools/jsondoclint/src/validator/tests.rs b/src/tools/jsondoclint/src/validator/tests.rs index d15aa7db315..e842e1318db 100644 --- a/src/tools/jsondoclint/src/validator/tests.rs +++ b/src/tools/jsondoclint/src/validator/tests.rs @@ -15,24 +15,20 @@ fn check(krate: &Crate, errs: &[Error]) { assert_eq!(errs, &validator.errs[..]); } -fn id(s: &str) -> Id { - Id(s.to_owned()) -} - #[test] fn errors_on_missing_links() { let k = Crate { - root: id("0"), + root: Id(0), crate_version: None, includes_private: false, - index: FxHashMap::from_iter([(id("0"), Item { + index: FxHashMap::from_iter([(Id(0), Item { name: Some("root".to_owned()), - id: id(""), + id: Id(0), crate_id: 0, span: None, visibility: Visibility::Public, docs: None, - links: FxHashMap::from_iter([("Not Found".to_owned(), id("1"))]), + links: FxHashMap::from_iter([("Not Found".to_owned(), Id(1))]), attrs: vec![], deprecation: None, inner: ItemEnum::Module(Module { is_crate: true, items: vec![], is_stripped: false }), @@ -49,7 +45,7 @@ fn errors_on_missing_links() { SelectorPart::Field("links".to_owned()), SelectorPart::Field("Not Found".to_owned()), ]]), - id: id("1"), + id: Id(1), }]); } @@ -58,28 +54,28 @@ fn errors_on_missing_links() { #[test] fn errors_on_local_in_paths_and_not_index() { let krate = Crate { - root: id("0:0:1572"), + root: Id(0), crate_version: None, includes_private: false, index: FxHashMap::from_iter([ - (id("0:0:1572"), Item { - id: id("0:0:1572"), + (Id(0), Item { + id: Id(0), crate_id: 0, name: Some("microcore".to_owned()), span: None, visibility: Visibility::Public, docs: None, - links: FxHashMap::from_iter([(("prim@i32".to_owned(), id("0:1:1571")))]), + links: FxHashMap::from_iter([(("prim@i32".to_owned(), Id(2)))]), attrs: Vec::new(), deprecation: None, inner: ItemEnum::Module(Module { is_crate: true, - items: vec![id("0:1:717")], + items: vec![Id(1)], is_stripped: false, }), }), - (id("0:1:717"), Item { - id: id("0:1:717"), + (Id(1), Item { + id: Id(1), crate_id: 0, name: Some("i32".to_owned()), span: None, @@ -91,7 +87,7 @@ fn errors_on_local_in_paths_and_not_index() { inner: ItemEnum::Primitive(Primitive { name: "i32".to_owned(), impls: vec![] }), }), ]), - paths: FxHashMap::from_iter([(id("0:1:1571"), ItemSummary { + paths: FxHashMap::from_iter([(Id(2), ItemSummary { crate_id: 0, path: vec!["microcore".to_owned(), "i32".to_owned()], kind: ItemKind::Primitive, @@ -101,7 +97,7 @@ fn errors_on_local_in_paths_and_not_index() { }; check(&krate, &[Error { - id: id("0:1:1571"), + id: Id(2), kind: ErrorKind::Custom("Id for local item in `paths` but not in `index`".to_owned()), }]); } @@ -110,11 +106,11 @@ fn errors_on_local_in_paths_and_not_index() { #[should_panic = "LOCAL_CRATE_ID is wrong"] fn checks_local_crate_id_is_correct() { let krate = Crate { - root: id("root"), + root: Id(0), crate_version: None, includes_private: false, - index: FxHashMap::from_iter([(id("root"), Item { - id: id("root"), + index: FxHashMap::from_iter([(Id(0), Item { + id: Id(0), crate_id: LOCAL_CRATE_ID.wrapping_add(1), name: Some("irrelavent".to_owned()), span: None, From 71bb0e72ce837d8669b8662ffe6b07de395983f5 Mon Sep 17 00:00:00 2001 From: Lukas Bergdoll Date: Mon, 30 Sep 2024 10:54:23 +0200 Subject: [PATCH 019/357] Port sort-research-rs test suite Rust stdlib tests This commit is a followup to https://github.com/rust-lang/rust/pull/124032. It replaces the tests that test the various sort functions in the standard library with a test-suite developed as part of https://github.com/Voultapher/sort-research-rs. The current tests suffer a couple of problems: - They don't cover important real world patterns that the implementations take advantage of and execute special code for. - The input lengths tested miss out on code paths. For example, important safety property tests never reach the quicksort part of the implementation. - The miri side is often limited to `len <= 20` which means it very thoroughly tests the insertion sort, which accounts for 19 out of 1.5k LoC. - They are split into to core and alloc, causing code duplication and uneven coverage. - The randomness is not repeatable, as it relies on `std::hash::RandomState::new().build_hasher()`. Most of these issues existed before https://github.com/rust-lang/rust/pull/124032, but they are intensified by it. One thing that is new and requires additional testing, is that the new sort implementations specialize based on type properties. For example `Freeze` and non `Freeze` execute different code paths. Effectively there are three dimensions that matter: - Input type - Input length - Input pattern The ported test-suite tests various properties along all three dimensions, greatly improving test coverage. It side-steps the miri issue by preferring sampled approaches. For example the test that checks if after a panic the set of elements is still the original one, doesn't do so for every single possible panic opportunity but rather it picks one at random, and performs this test across a range of input length, which varies the panic point across them. This allows regular execution to easily test inputs of length 10k, and miri execution up to 100 which covers significantly more code. The randomness used is tied to a fixed - but random per process execution - seed. This allows for fully repeatable tests and fuzzer like exploration across multiple runs. Structure wise, the tests are previously found in the core integration tests for `sort_unstable` and alloc unit tests for `sort`. The new test-suite was developed to be a purely black-box approach, which makes integration testing the better place, because it can't accidentally rely on internal access. Because unwinding support is required the tests can't be in core, even if the implementation is, so they are now part of the alloc integration tests. Are there architectures that can only build and test core and not alloc? If so, do such platforms require sort testing? For what it's worth the current implementation state passes miri `--target mips64-unknown-linux-gnuabi64` which is big endian. The test-suite also contains tests for properties that were and are given by the current and previous implementations, and likely relied upon by users but weren't tested. For example `self_cmp` tests that the two parameters `a` and `b` passed into the comparison function are never references to the same object, which if the user is sorting for example a `&mut [Mutex]` could lead to a deadlock. Instead of using the hashed caller location as rand seed, it uses seconds since unix epoch / 10, which given timestamps in the CI should be reasonably easy to reproduce, but also allows fuzzer like space exploration. --- library/alloc/src/slice.rs | 24 +- library/alloc/src/slice/tests.rs | 369 ----- library/alloc/tests/lib.rs | 2 + library/alloc/tests/sort/ffi_types.rs | 82 ++ .../tests/sort/known_good_stable_sort.rs | 192 +++ library/alloc/tests/sort/mod.rs | 17 + library/alloc/tests/sort/patterns.rs | 211 +++ library/alloc/tests/sort/tests.rs | 1233 +++++++++++++++++ library/alloc/tests/sort/zipf.rs | 208 +++ library/core/tests/slice.rs | 51 - 10 files changed, 1955 insertions(+), 434 deletions(-) delete mode 100644 library/alloc/src/slice/tests.rs create mode 100644 library/alloc/tests/sort/ffi_types.rs create mode 100644 library/alloc/tests/sort/known_good_stable_sort.rs create mode 100644 library/alloc/tests/sort/mod.rs create mode 100644 library/alloc/tests/sort/patterns.rs create mode 100644 library/alloc/tests/sort/tests.rs create mode 100644 library/alloc/tests/sort/zipf.rs diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs index a92d22b1c30..e3c7835f1d1 100644 --- a/library/alloc/src/slice.rs +++ b/library/alloc/src/slice.rs @@ -19,20 +19,6 @@ use core::cmp::Ordering::{self, Less}; use core::mem::{self, MaybeUninit}; #[cfg(not(no_global_oom_handling))] use core::ptr; -#[cfg(not(no_global_oom_handling))] -use core::slice::sort; - -use crate::alloc::Allocator; -#[cfg(not(no_global_oom_handling))] -use crate::alloc::Global; -#[cfg(not(no_global_oom_handling))] -use crate::borrow::ToOwned; -use crate::boxed::Box; -use crate::vec::Vec; - -#[cfg(test)] -mod tests; - #[unstable(feature = "array_chunks", issue = "74985")] pub use core::slice::ArrayChunks; #[unstable(feature = "array_chunks", issue = "74985")] @@ -43,6 +29,8 @@ pub use core::slice::ArrayWindows; pub use core::slice::EscapeAscii; #[stable(feature = "slice_get_slice", since = "1.28.0")] pub use core::slice::SliceIndex; +#[cfg(not(no_global_oom_handling))] +use core::slice::sort; #[stable(feature = "slice_group_by", since = "1.77.0")] pub use core::slice::{ChunkBy, ChunkByMut}; #[stable(feature = "rust1", since = "1.0.0")] @@ -83,6 +71,14 @@ pub use hack::into_vec; #[cfg(test)] pub use hack::to_vec; +use crate::alloc::Allocator; +#[cfg(not(no_global_oom_handling))] +use crate::alloc::Global; +#[cfg(not(no_global_oom_handling))] +use crate::borrow::ToOwned; +use crate::boxed::Box; +use crate::vec::Vec; + // HACK(japaric): With cfg(test) `impl [T]` is not available, these three // functions are actually methods that are in `impl [T]` but not in // `core::slice::SliceExt` - we need to supply these functions for the diff --git a/library/alloc/src/slice/tests.rs b/library/alloc/src/slice/tests.rs deleted file mode 100644 index 786704caeb0..00000000000 --- a/library/alloc/src/slice/tests.rs +++ /dev/null @@ -1,369 +0,0 @@ -use core::cell::Cell; -use core::cmp::Ordering::{self, Equal, Greater, Less}; -use core::convert::identity; -use core::sync::atomic::AtomicUsize; -use core::sync::atomic::Ordering::Relaxed; -use core::{fmt, mem}; -use std::panic; - -use rand::distributions::Standard; -use rand::prelude::*; -use rand::{Rng, RngCore}; - -use crate::borrow::ToOwned; -use crate::rc::Rc; -use crate::string::ToString; -use crate::test_helpers::test_rng; -use crate::vec::Vec; - -macro_rules! do_test { - ($input:ident, $func:ident) => { - let len = $input.len(); - - // Work out the total number of comparisons required to sort - // this array... - let mut count = 0usize; - $input.to_owned().$func(|a, b| { - count += 1; - a.cmp(b) - }); - - // ... and then panic on each and every single one. - for panic_countdown in 0..count { - // Refresh the counters. - VERSIONS.store(0, Relaxed); - for i in 0..len { - DROP_COUNTS[i].store(0, Relaxed); - } - - let v = $input.to_owned(); - let _ = panic::catch_unwind(move || { - let mut v = v; - let mut panic_countdown = panic_countdown; - v.$func(|a, b| { - if panic_countdown == 0 { - SILENCE_PANIC.with(|s| s.set(true)); - panic!(); - } - panic_countdown -= 1; - a.cmp(b) - }) - }); - - // Check that the number of things dropped is exactly - // what we expect (i.e., the contents of `v`). - for (i, c) in DROP_COUNTS.iter().enumerate().take(len) { - let count = c.load(Relaxed); - assert!(count == 1, "found drop count == {} for i == {}, len == {}", count, i, len); - } - - // Check that the most recent versions of values were dropped. - assert_eq!(VERSIONS.load(Relaxed), 0); - } - }; -} - -const MAX_LEN: usize = 80; - -static DROP_COUNTS: [AtomicUsize; MAX_LEN] = [ - // FIXME(RFC 1109): AtomicUsize is not Copy. - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), -]; - -static VERSIONS: AtomicUsize = AtomicUsize::new(0); - -#[derive(Clone, Eq)] -struct DropCounter { - x: u32, - id: usize, - version: Cell, -} - -impl PartialEq for DropCounter { - fn eq(&self, other: &Self) -> bool { - self.partial_cmp(other) == Some(Ordering::Equal) - } -} - -impl PartialOrd for DropCounter { - fn partial_cmp(&self, other: &Self) -> Option { - self.version.set(self.version.get() + 1); - other.version.set(other.version.get() + 1); - VERSIONS.fetch_add(2, Relaxed); - self.x.partial_cmp(&other.x) - } -} - -impl Ord for DropCounter { - fn cmp(&self, other: &Self) -> Ordering { - self.partial_cmp(other).unwrap() - } -} - -impl Drop for DropCounter { - fn drop(&mut self) { - DROP_COUNTS[self.id].fetch_add(1, Relaxed); - VERSIONS.fetch_sub(self.version.get(), Relaxed); - } -} - -std::thread_local!(static SILENCE_PANIC: Cell = Cell::new(false)); - -#[test] -#[cfg_attr(target_os = "emscripten", ignore)] // no threads -#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] -fn panic_safe() { - panic::update_hook(move |prev, info| { - if !SILENCE_PANIC.with(|s| s.get()) { - prev(info); - } - }); - - let mut rng = test_rng(); - - // Miri is too slow (but still need to `chain` to make the types match) - let lens = if cfg!(miri) { (1..10).chain(0..0) } else { (1..20).chain(70..MAX_LEN) }; - let moduli: &[u32] = if cfg!(miri) { &[5] } else { &[5, 20, 50] }; - - for len in lens { - for &modulus in moduli { - for &has_runs in &[false, true] { - let mut input = (0..len) - .map(|id| DropCounter { - x: rng.next_u32() % modulus, - id: id, - version: Cell::new(0), - }) - .collect::>(); - - if has_runs { - for c in &mut input { - c.x = c.id as u32; - } - - for _ in 0..5 { - let a = rng.gen::() % len; - let b = rng.gen::() % len; - if a < b { - input[a..b].reverse(); - } else { - input.swap(a, b); - } - } - } - - do_test!(input, sort_by); - do_test!(input, sort_unstable_by); - } - } - } - - // Set default panic hook again. - drop(panic::take_hook()); -} - -#[test] -#[cfg_attr(miri, ignore)] // Miri is too slow -#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] -fn test_sort() { - let mut rng = test_rng(); - - for len in (2..25).chain(500..510) { - for &modulus in &[5, 10, 100, 1000] { - for _ in 0..10 { - let orig: Vec<_> = (&mut rng) - .sample_iter::(&Standard) - .map(|x| x % modulus) - .take(len) - .collect(); - - // Sort in default order. - let mut v = orig.clone(); - v.sort(); - assert!(v.windows(2).all(|w| w[0] <= w[1])); - - // Sort in ascending order. - let mut v = orig.clone(); - v.sort_by(|a, b| a.cmp(b)); - assert!(v.windows(2).all(|w| w[0] <= w[1])); - - // Sort in descending order. - let mut v = orig.clone(); - v.sort_by(|a, b| b.cmp(a)); - assert!(v.windows(2).all(|w| w[0] >= w[1])); - - // Sort in lexicographic order. - let mut v1 = orig.clone(); - let mut v2 = orig.clone(); - v1.sort_by_key(|x| x.to_string()); - v2.sort_by_cached_key(|x| x.to_string()); - assert!(v1.windows(2).all(|w| w[0].to_string() <= w[1].to_string())); - assert!(v1 == v2); - - // Sort with many pre-sorted runs. - let mut v = orig.clone(); - v.sort(); - v.reverse(); - for _ in 0..5 { - let a = rng.gen::() % len; - let b = rng.gen::() % len; - if a < b { - v[a..b].reverse(); - } else { - v.swap(a, b); - } - } - v.sort(); - assert!(v.windows(2).all(|w| w[0] <= w[1])); - } - } - } - - const ORD_VIOLATION_MAX_LEN: usize = 500; - let mut v = [0; ORD_VIOLATION_MAX_LEN]; - for i in 0..ORD_VIOLATION_MAX_LEN { - v[i] = i as i32; - } - - // Sort using a completely random comparison function. This will reorder the elements *somehow*, - // it may panic but the original elements must still be present. - let _ = panic::catch_unwind(move || { - v.sort_by(|_, _| *[Less, Equal, Greater].choose(&mut rng).unwrap()); - }); - - v.sort(); - for i in 0..ORD_VIOLATION_MAX_LEN { - assert_eq!(v[i], i as i32); - } - - // Should not panic. - [0i32; 0].sort(); - [(); 10].sort(); - [(); 100].sort(); - - let mut v = [0xDEADBEEFu64]; - v.sort(); - assert!(v == [0xDEADBEEF]); -} - -#[test] -fn test_sort_stability() { - // Miri is too slow - let large_range = if cfg!(miri) { 0..0 } else { 500..510 }; - let rounds = if cfg!(miri) { 1 } else { 10 }; - - let mut rng = test_rng(); - for len in (2..25).chain(large_range) { - for _ in 0..rounds { - let mut counts = [0; 10]; - - // create a vector like [(6, 1), (5, 1), (6, 2), ...], - // where the first item of each tuple is random, but - // the second item represents which occurrence of that - // number this element is, i.e., the second elements - // will occur in sorted order. - let orig: Vec<_> = (0..len) - .map(|_| { - let n = rng.gen::() % 10; - counts[n] += 1; - (n, counts[n]) - }) - .collect(); - - let mut v = orig.clone(); - // Only sort on the first element, so an unstable sort - // may mix up the counts. - v.sort_by(|&(a, _), &(b, _)| a.cmp(&b)); - - // This comparison includes the count (the second item - // of the tuple), so elements with equal first items - // will need to be ordered with increasing - // counts... i.e., exactly asserting that this sort is - // stable. - assert!(v.windows(2).all(|w| w[0] <= w[1])); - - let mut v = orig.clone(); - v.sort_by_cached_key(|&(x, _)| x); - assert!(v.windows(2).all(|w| w[0] <= w[1])); - } - } -} diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs index 1d07a7690da..23efd605ff9 100644 --- a/library/alloc/tests/lib.rs +++ b/library/alloc/tests/lib.rs @@ -41,6 +41,7 @@ #![feature(local_waker)] #![feature(vec_pop_if)] #![feature(unique_rc_arc)] +#![feature(macro_metavar_expr_concat)] #![allow(internal_features)] #![deny(fuzzy_provenance_casts)] #![deny(unsafe_op_in_unsafe_fn)] @@ -60,6 +61,7 @@ mod heap; mod linked_list; mod rc; mod slice; +mod sort; mod str; mod string; mod task; diff --git a/library/alloc/tests/sort/ffi_types.rs b/library/alloc/tests/sort/ffi_types.rs new file mode 100644 index 00000000000..11515ea4769 --- /dev/null +++ b/library/alloc/tests/sort/ffi_types.rs @@ -0,0 +1,82 @@ +use std::cmp::Ordering; + +// Very large stack value. +#[repr(C)] +#[derive(PartialEq, Eq, Debug, Clone)] +pub struct FFIOneKibiByte { + values: [i64; 128], +} + +impl FFIOneKibiByte { + pub fn new(val: i32) -> Self { + let mut values = [0i64; 128]; + let mut val_i64 = val as i64; + + for elem in &mut values { + *elem = val_i64; + val_i64 = std::hint::black_box(val_i64 + 1); + } + Self { values } + } + + fn as_i64(&self) -> i64 { + self.values[11] + self.values[55] + self.values[77] + } +} + +impl PartialOrd for FFIOneKibiByte { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for FFIOneKibiByte { + fn cmp(&self, other: &Self) -> Ordering { + self.as_i64().cmp(&other.as_i64()) + } +} + +// 16 byte stack value, with more expensive comparison. +#[repr(C)] +#[derive(PartialEq, Debug, Clone, Copy)] +pub struct F128 { + x: f64, + y: f64, +} + +impl F128 { + pub fn new(val: i32) -> Self { + let val_f = (val as f64) + (i32::MAX as f64) + 10.0; + + let x = val_f + 0.1; + let y = val_f.log(4.1); + + assert!(y < x); + assert!(x.is_normal() && y.is_normal()); + + Self { x, y } + } +} + +// This is kind of hacky, but we know we only have normal comparable floats in there. +impl Eq for F128 {} + +impl PartialOrd for F128 { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +// Goal is similar code-gen between Rust and C++ +// - Rust https://godbolt.org/z/3YM3xenPP +// - C++ https://godbolt.org/z/178M6j1zz +impl Ord for F128 { + fn cmp(&self, other: &Self) -> Ordering { + // Simulate expensive comparison function. + let this_div = self.x / self.y; + let other_div = other.x / other.y; + + // SAFETY: We checked in the ctor that both are normal. + unsafe { this_div.partial_cmp(&other_div).unwrap_unchecked() } + } +} diff --git a/library/alloc/tests/sort/known_good_stable_sort.rs b/library/alloc/tests/sort/known_good_stable_sort.rs new file mode 100644 index 00000000000..f8615435fc2 --- /dev/null +++ b/library/alloc/tests/sort/known_good_stable_sort.rs @@ -0,0 +1,192 @@ +// This module implements a known good stable sort implementation that helps provide better error +// messages when the correctness tests fail, we can't use the stdlib sort functions because we are +// testing them for correctness. +// +// Based on https://github.com/voultapher/tiny-sort-rs. + +use alloc::alloc::{Layout, alloc, dealloc}; +use std::{mem, ptr}; + +/// Sort `v` preserving initial order of equal elements. +/// +/// - Guaranteed O(N * log(N)) worst case perf +/// - No adaptiveness +/// - Branch miss-prediction not affected by outcome of comparison function +/// - Uses `v.len()` auxiliary memory. +/// +/// If `T: Ord` does not implement a total order the resulting order is +/// unspecified. All original elements will remain in `v` and any possible modifications via +/// interior mutability will be observable. Same is true if `T: Ord` panics. +/// +/// Panics if allocating the auxiliary memory fails. +#[inline(always)] +pub fn sort(v: &mut [T]) { + stable_sort(v, |a, b| a.lt(b)) +} + +#[inline(always)] +fn stable_sort bool>(v: &mut [T], mut is_less: F) { + if mem::size_of::() == 0 { + return; + } + + let len = v.len(); + + // Inline the check for len < 2. This happens a lot, instrumenting the Rust compiler suggests + // len < 2 accounts for 94% of its calls to `slice::sort`. + if len < 2 { + return; + } + + // SAFETY: We checked that len is > 0 and that T is not a ZST. + unsafe { + mergesort_main(v, &mut is_less); + } +} + +/// The core logic should not be inlined. +/// +/// SAFETY: The caller has to ensure that len is > 0 and that T is not a ZST. +#[inline(never)] +unsafe fn mergesort_main bool>(v: &mut [T], is_less: &mut F) { + // While it would be nice to have a merge implementation that only requires N / 2 auxiliary + // memory. Doing so would make the merge implementation significantly more complex and + + // SAFETY: See function safety description. + let buf = unsafe { BufGuard::new(v.len()) }; + + // SAFETY: `scratch` has space for `v.len()` writes. And does not alias `v`. + unsafe { + mergesort_core(v, buf.buf_ptr.as_ptr(), is_less); + } +} + +/// Tiny recursive top-down merge sort optimized for binary size. It has no adaptiveness whatsoever, +/// no run detection, etc. +/// +/// Buffer as pointed to by `scratch` must have space for `v.len()` writes. And must not alias `v`. +#[inline(always)] +unsafe fn mergesort_core bool>( + v: &mut [T], + scratch_ptr: *mut T, + is_less: &mut F, +) { + let len = v.len(); + + if len > 2 { + // SAFETY: `mid` is guaranteed in-bounds. And caller has to ensure that `scratch_ptr` can + // hold `v.len()` values. + unsafe { + let mid = len / 2; + // Sort the left half recursively. + mergesort_core(v.get_unchecked_mut(..mid), scratch_ptr, is_less); + // Sort the right half recursively. + mergesort_core(v.get_unchecked_mut(mid..), scratch_ptr, is_less); + // Combine the two halves. + merge(v, scratch_ptr, is_less, mid); + } + } else if len == 2 { + if is_less(&v[1], &v[0]) { + v.swap(0, 1); + } + } +} + +/// Branchless merge function. +/// +/// SAFETY: The caller must ensure that `scratch_ptr` is valid for `v.len()` writes. And that mid is +/// in-bounds. +#[inline(always)] +unsafe fn merge(v: &mut [T], scratch_ptr: *mut T, is_less: &mut F, mid: usize) +where + F: FnMut(&T, &T) -> bool, +{ + let len = v.len(); + debug_assert!(mid > 0 && mid < len); + + let len = v.len(); + + // Indexes to track the positions while merging. + let mut l = 0; + let mut r = mid; + + // SAFETY: No matter what the result of is_less is we check that l and r remain in-bounds and if + // is_less panics the original elements remain in `v`. + unsafe { + let arr_ptr = v.as_ptr(); + + for i in 0..len { + let left_ptr = arr_ptr.add(l); + let right_ptr = arr_ptr.add(r); + + let is_lt = !is_less(&*right_ptr, &*left_ptr); + let copy_ptr = if is_lt { left_ptr } else { right_ptr }; + ptr::copy_nonoverlapping(copy_ptr, scratch_ptr.add(i), 1); + + l += is_lt as usize; + r += !is_lt as usize; + + // As long as neither side is exhausted merge left and right elements. + if ((l == mid) as u8 + (r == len) as u8) != 0 { + break; + } + } + + // The left or right side is exhausted, drain the right side in one go. + let copy_ptr = if l == mid { arr_ptr.add(r) } else { arr_ptr.add(l) }; + let i = l + (r - mid); + ptr::copy_nonoverlapping(copy_ptr, scratch_ptr.add(i), len - i); + + // Now that scratch_ptr holds the full merged content, write it back on-top of v. + ptr::copy_nonoverlapping(scratch_ptr, v.as_mut_ptr(), len); + } +} + +// SAFETY: The caller has to ensure that Option is Some, UB otherwise. +unsafe fn unwrap_unchecked(opt_val: Option) -> T { + match opt_val { + Some(val) => val, + None => { + // SAFETY: See function safety description. + unsafe { + core::hint::unreachable_unchecked(); + } + } + } +} + +// Extremely basic versions of Vec. +// Their use is super limited and by having the code here, it allows reuse between the sort +// implementations. +struct BufGuard { + buf_ptr: ptr::NonNull, + capacity: usize, +} + +impl BufGuard { + // SAFETY: The caller has to ensure that len is not 0 and that T is not a ZST. + unsafe fn new(len: usize) -> Self { + debug_assert!(len > 0 && mem::size_of::() > 0); + + // SAFETY: See function safety description. + let layout = unsafe { unwrap_unchecked(Layout::array::(len).ok()) }; + + // SAFETY: We checked that T is not a ZST. + let buf_ptr = unsafe { alloc(layout) as *mut T }; + + if buf_ptr.is_null() { + panic!("allocation failure"); + } + + Self { buf_ptr: ptr::NonNull::new(buf_ptr).unwrap(), capacity: len } + } +} + +impl Drop for BufGuard { + fn drop(&mut self) { + // SAFETY: We checked that T is not a ZST. + unsafe { + dealloc(self.buf_ptr.as_ptr() as *mut u8, Layout::array::(self.capacity).unwrap()); + } + } +} diff --git a/library/alloc/tests/sort/mod.rs b/library/alloc/tests/sort/mod.rs new file mode 100644 index 00000000000..0e2494ca9d3 --- /dev/null +++ b/library/alloc/tests/sort/mod.rs @@ -0,0 +1,17 @@ +pub trait Sort { + fn name() -> String; + + fn sort(v: &mut [T]) + where + T: Ord; + + fn sort_by(v: &mut [T], compare: F) + where + F: FnMut(&T, &T) -> std::cmp::Ordering; +} + +mod ffi_types; +mod known_good_stable_sort; +mod patterns; +mod tests; +mod zipf; diff --git a/library/alloc/tests/sort/patterns.rs b/library/alloc/tests/sort/patterns.rs new file mode 100644 index 00000000000..e5d31d868b2 --- /dev/null +++ b/library/alloc/tests/sort/patterns.rs @@ -0,0 +1,211 @@ +use std::env; +use std::hash::Hash; +use std::str::FromStr; +use std::sync::OnceLock; + +use rand::prelude::*; +use rand_xorshift::XorShiftRng; + +use crate::sort::zipf::ZipfDistribution; + +/// Provides a set of patterns useful for testing and benchmarking sorting algorithms. +/// Currently limited to i32 values. + +// --- Public --- + +pub fn random(len: usize) -> Vec { + // . + // : . : : + // :.:::.:: + + random_vec(len) +} + +pub fn random_uniform(len: usize, range: R) -> Vec +where + R: Into> + Hash, +{ + // :.:.:.:: + + let mut rng: XorShiftRng = rand::SeedableRng::seed_from_u64(get_or_init_rand_seed()); + + // Abstracting over ranges in Rust :( + let dist: rand::distributions::Uniform = range.into(); + (0..len).map(|_| dist.sample(&mut rng)).collect() +} + +pub fn random_zipf(len: usize, exponent: f64) -> Vec { + // https://en.wikipedia.org/wiki/Zipf's_law + + let mut rng: XorShiftRng = rand::SeedableRng::seed_from_u64(get_or_init_rand_seed()); + + // Abstracting over ranges in Rust :( + let dist = ZipfDistribution::new(len, exponent).unwrap(); + (0..len).map(|_| dist.sample(&mut rng) as i32).collect() +} + +pub fn random_sorted(len: usize, sorted_percent: f64) -> Vec { + // .: + // .:::. : + // .::::::.:: + // [----][--] + // ^ ^ + // | | + // sorted | + // unsorted + + // Simulate pre-existing sorted slice, where len - sorted_percent are the new unsorted values + // and part of the overall distribution. + let mut v = random_vec(len); + let sorted_len = ((len as f64) * (sorted_percent / 100.0)).round() as usize; + + v[0..sorted_len].sort_unstable(); + + v +} + +pub fn all_equal(len: usize) -> Vec { + // ...... + // :::::: + + (0..len).map(|_| 66).collect::>() +} + +pub fn ascending(len: usize) -> Vec { + // .: + // .::: + // .::::: + + (0..len as i32).collect::>() +} + +pub fn descending(len: usize) -> Vec { + // :. + // :::. + // :::::. + + (0..len as i32).rev().collect::>() +} + +pub fn saw_mixed(len: usize, saw_count: usize) -> Vec { + // :. :. .::. .: + // :::.:::..::::::..::: + + if len == 0 { + return Vec::new(); + } + + let mut vals = random_vec(len); + let chunks_size = len / saw_count.max(1); + let saw_directions = random_uniform((len / chunks_size) + 1, 0..=1); + + for (i, chunk) in vals.chunks_mut(chunks_size).enumerate() { + if saw_directions[i] == 0 { + chunk.sort_unstable(); + } else if saw_directions[i] == 1 { + chunk.sort_unstable_by_key(|&e| std::cmp::Reverse(e)); + } else { + unreachable!(); + } + } + + vals +} + +pub fn saw_mixed_range(len: usize, range: std::ops::Range) -> Vec { + // :. + // :. :::. .::. .: + // :::.:::::..::::::..:.::: + + // ascending and descending randomly picked, with length in `range`. + + if len == 0 { + return Vec::new(); + } + + let mut vals = random_vec(len); + + let max_chunks = len / range.start; + let saw_directions = random_uniform(max_chunks + 1, 0..=1); + let chunk_sizes = random_uniform(max_chunks + 1, (range.start as i32)..(range.end as i32)); + + let mut i = 0; + let mut l = 0; + while l < len { + let chunk_size = chunk_sizes[i] as usize; + let chunk_end = std::cmp::min(l + chunk_size, len); + let chunk = &mut vals[l..chunk_end]; + + if saw_directions[i] == 0 { + chunk.sort_unstable(); + } else if saw_directions[i] == 1 { + chunk.sort_unstable_by_key(|&e| std::cmp::Reverse(e)); + } else { + unreachable!(); + } + + i += 1; + l += chunk_size; + } + + vals +} + +pub fn pipe_organ(len: usize) -> Vec { + // .:. + // .:::::. + + let mut vals = random_vec(len); + + let first_half = &mut vals[0..(len / 2)]; + first_half.sort_unstable(); + + let second_half = &mut vals[(len / 2)..len]; + second_half.sort_unstable_by_key(|&e| std::cmp::Reverse(e)); + + vals +} + +pub fn get_or_init_rand_seed() -> u64 { + *SEED_VALUE.get_or_init(|| { + env::var("OVERRIDE_SEED") + .ok() + .map(|seed| u64::from_str(&seed).unwrap()) + .unwrap_or_else(rand_root_seed) + }) +} + +// --- Private --- + +static SEED_VALUE: OnceLock = OnceLock::new(); + +#[cfg(not(miri))] +fn rand_root_seed() -> u64 { + // Other test code hashes `panic::Location::caller()` and constructs a seed from that, in these + // tests we want to have a fuzzer like exploration of the test space, if we used the same caller + // based construction we would always test the same. + // + // Instead we use the seconds since UNIX epoch / 10, given CI log output this value should be + // reasonably easy to re-construct. + + use std::time::{SystemTime, UNIX_EPOCH}; + + let epoch_seconds = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs(); + + epoch_seconds / 10 +} + +#[cfg(miri)] +fn rand_root_seed() -> u64 { + // Miri is usually run with isolation with gives us repeatability but also permutations based on + // other code that runs before. + use core::hash::{BuildHasher, Hash, Hasher}; + let mut hasher = std::hash::RandomState::new().build_hasher(); + core::panic::Location::caller().hash(&mut hasher); + hasher.finish() +} + +fn random_vec(len: usize) -> Vec { + let mut rng: XorShiftRng = rand::SeedableRng::seed_from_u64(get_or_init_rand_seed()); + (0..len).map(|_| rng.gen::()).collect() +} diff --git a/library/alloc/tests/sort/tests.rs b/library/alloc/tests/sort/tests.rs new file mode 100644 index 00000000000..14e6013f965 --- /dev/null +++ b/library/alloc/tests/sort/tests.rs @@ -0,0 +1,1233 @@ +use std::cell::Cell; +use std::cmp::Ordering; +use std::fmt::Debug; +use std::panic::{self, AssertUnwindSafe}; +use std::rc::Rc; +use std::{env, fs}; + +use crate::sort::ffi_types::{F128, FFIOneKibiByte}; +use crate::sort::{Sort, known_good_stable_sort, patterns}; + +#[cfg(miri)] +const TEST_LENGTHS: &[usize] = &[2, 3, 4, 7, 10, 15, 20, 24, 33, 50, 100, 171, 300]; + +#[cfg(not(miri))] +const TEST_LENGTHS: &[usize] = &[ + 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 16, 17, 20, 24, 30, 32, 33, 35, 50, 100, 200, 500, 1_000, + 2_048, 5_000, 10_000, 100_000, 1_100_000, +]; + +fn check_is_sorted(v: &mut [T]) { + let seed = patterns::get_or_init_rand_seed(); + + let is_small_test = v.len() <= 100; + let v_orig = v.to_vec(); + + ::sort(v); + + assert_eq!(v.len(), v_orig.len()); + + for window in v.windows(2) { + if window[0] > window[1] { + let mut known_good_sorted_vec = v_orig.clone(); + known_good_stable_sort::sort(known_good_sorted_vec.as_mut_slice()); + + if is_small_test { + eprintln!("Orginal: {:?}", v_orig); + eprintln!("Expected: {:?}", known_good_sorted_vec); + eprintln!("Got: {:?}", v); + } else { + if env::var("WRITE_LARGE_FAILURE").is_ok() { + // Large arrays output them as files. + let original_name = format!("original_{}.txt", seed); + let std_name = format!("known_good_sorted_{}.txt", seed); + let testsort_name = format!("{}_sorted_{}.txt", S::name(), seed); + + fs::write(&original_name, format!("{:?}", v_orig)).unwrap(); + fs::write(&std_name, format!("{:?}", known_good_sorted_vec)).unwrap(); + fs::write(&testsort_name, format!("{:?}", v)).unwrap(); + + eprintln!( + "Failed comparison, see files {original_name}, {std_name}, and {testsort_name}" + ); + } else { + eprintln!( + "Failed comparison, re-run with WRITE_LARGE_FAILURE env var set, to get output." + ); + } + } + + panic!("Test assertion failed!") + } + } +} + +fn test_is_sorted( + test_len: usize, + map_fn: impl Fn(i32) -> T, + pattern_fn: impl Fn(usize) -> Vec, +) { + let mut test_data: Vec = pattern_fn(test_len).into_iter().map(map_fn).collect(); + check_is_sorted::(test_data.as_mut_slice()); +} + +trait DynTrait: Debug { + fn get_val(&self) -> i32; +} + +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] +struct DynValA { + value: i32, +} + +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] +struct DynValB { + value: u64, +} + +impl DynTrait for DynValA { + fn get_val(&self) -> i32 { + self.value + } +} +impl DynTrait for DynValB { + fn get_val(&self) -> i32 { + let bytes = self.value.to_ne_bytes(); + i32::from_ne_bytes([bytes[0], bytes[1], bytes[6], bytes[7]]) + } +} + +impl PartialOrd for dyn DynTrait { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for dyn DynTrait { + fn cmp(&self, other: &Self) -> Ordering { + self.get_val().cmp(&other.get_val()) + } +} + +impl PartialEq for dyn DynTrait { + fn eq(&self, other: &Self) -> bool { + self.get_val() == other.get_val() + } +} + +impl Eq for dyn DynTrait {} + +fn shift_i32_to_u32(val: i32) -> u32 { + (val as i64 + (i32::MAX as i64 + 1)) as u32 +} + +fn reverse_shift_i32_to_u32(val: u32) -> i32 { + (val as i64 - (i32::MAX as i64 + 1)) as i32 +} + +fn extend_i32_to_u64(val: i32) -> u64 { + // Extends the value into the 64 bit range, + // while preserving input order. + (shift_i32_to_u32(val) as u64) * i32::MAX as u64 +} + +fn extend_i32_to_u128(val: i32) -> u128 { + // Extends the value into the 64 bit range, + // while preserving input order. + (shift_i32_to_u32(val) as u128) * i64::MAX as u128 +} + +fn dyn_trait_from_i32(val: i32) -> Rc { + if val % 2 == 0 { + Rc::new(DynValA { value: val }) + } else { + Rc::new(DynValB { value: extend_i32_to_u64(val) }) + } +} + +fn i32_from_i32(val: i32) -> i32 { + val +} + +fn i32_from_i32_ref(val: &i32) -> i32 { + *val +} + +fn string_from_i32(val: i32) -> String { + format!("{:010}", shift_i32_to_u32(val)) +} + +fn i32_from_string(val: &String) -> i32 { + reverse_shift_i32_to_u32(val.parse::().unwrap()) +} + +fn cell_i32_from_i32(val: i32) -> Cell { + Cell::new(val) +} + +fn i32_from_cell_i32(val: &Cell) -> i32 { + val.get() +} + +fn calc_comps_required(v: &mut [T], mut cmp_fn: impl FnMut(&T, &T) -> Ordering) -> u32 { + let mut comp_counter = 0u32; + + ::sort_by(v, |a, b| { + comp_counter += 1; + + cmp_fn(a, b) + }); + + comp_counter +} + +#[derive(PartialEq, Eq, Debug, Clone)] +#[repr(C)] +struct CompCount { + val: i32, + comp_count: Cell, +} + +impl CompCount { + fn new(val: i32) -> Self { + Self { val, comp_count: Cell::new(0) } + } +} + +/// Generates $base_name_pattern_name_impl functions calling the test_fns for all test_len. +macro_rules! gen_sort_test_fns { + ( + $base_name:ident, + $test_fn:expr, + $test_lengths:expr, + [$(($pattern_name:ident, $pattern_fn:expr)),* $(,)?] $(,)? + ) => { + $(fn ${concat($base_name, _, $pattern_name, _impl)}() { + for test_len in $test_lengths { + $test_fn(*test_len, $pattern_fn); + } + })* + }; +} + +/// Generates $base_name_pattern_name_impl functions calling the test_fns for all test_len, +/// with a default set of patterns that can be extended by the caller. +macro_rules! gen_sort_test_fns_with_default_patterns { + ( + $base_name:ident, + $test_fn:expr, + $test_lengths:expr, + [$(($pattern_name:ident, $pattern_fn:expr)),* $(,)?] $(,)? + ) => { + gen_sort_test_fns!( + $base_name, + $test_fn, + $test_lengths, + [ + (random, patterns::random), + (random_z1, |len| patterns::random_zipf(len, 1.0)), + (random_d2, |len| patterns::random_uniform(len, 0..2)), + (random_d20, |len| patterns::random_uniform(len, 0..16)), + (random_s95, |len| patterns::random_sorted(len, 95.0)), + (ascending, patterns::ascending), + (descending, patterns::descending), + (saw_mixed, |len| patterns::saw_mixed( + len, + ((len as f64).log2().round()) as usize + )), + $(($pattern_name, $pattern_fn),)* + ] + ); + }; +} + +/// Generates $base_name_type_pattern_name_impl functions calling the test_fns for all test_len for +/// three types that cover the core specialization differences in the sort implementations, with a +/// default set of patterns that can be extended by the caller. +macro_rules! gen_sort_test_fns_with_default_patterns_3_ty { + ( + $base_name:ident, + $test_fn:ident, + [$(($pattern_name:ident, $pattern_fn:expr)),* $(,)?] $(,)? + ) => { + gen_sort_test_fns_with_default_patterns!( + ${concat($base_name, _i32)}, + |len, pattern_fn| $test_fn::(len, i32_from_i32, i32_from_i32_ref, pattern_fn), + &TEST_LENGTHS[..TEST_LENGTHS.len() - 2], + [$(($pattern_name, $pattern_fn),)*], + ); + + gen_sort_test_fns_with_default_patterns!( + ${concat($base_name, _cell_i32)}, + |len, pattern_fn| $test_fn::, S>(len, cell_i32_from_i32, i32_from_cell_i32, pattern_fn), + &TEST_LENGTHS[..TEST_LENGTHS.len() - 3], + [$(($pattern_name, $pattern_fn),)*], + ); + + gen_sort_test_fns_with_default_patterns!( + ${concat($base_name, _string)}, + |len, pattern_fn| $test_fn::(len, string_from_i32, i32_from_string, pattern_fn), + &TEST_LENGTHS[..TEST_LENGTHS.len() - 3], + [$(($pattern_name, $pattern_fn),)*], + ); + }; +} + +// --- TESTS --- + +pub fn basic_impl() { + check_is_sorted::(&mut []); + check_is_sorted::<(), S>(&mut []); + check_is_sorted::<(), S>(&mut [()]); + check_is_sorted::<(), S>(&mut [(), ()]); + check_is_sorted::<(), S>(&mut [(), (), ()]); + check_is_sorted::(&mut []); + check_is_sorted::(&mut [77]); + check_is_sorted::(&mut [2, 3]); + check_is_sorted::(&mut [2, 3, 6]); + check_is_sorted::(&mut [2, 3, 99, 6]); + check_is_sorted::(&mut [2, 7709, 400, 90932]); + check_is_sorted::(&mut [15, -1, 3, -1, -3, -1, 7]); +} + +fn fixed_seed_impl() { + let fixed_seed_a = patterns::get_or_init_rand_seed(); + let fixed_seed_b = patterns::get_or_init_rand_seed(); + + assert_eq!(fixed_seed_a, fixed_seed_b); +} + +fn fixed_seed_rand_vec_prefix_impl() { + let vec_rand_len_5 = patterns::random(5); + let vec_rand_len_7 = patterns::random(7); + + assert_eq!(vec_rand_len_5, vec_rand_len_7[..5]); +} + +fn int_edge_impl() { + // Ensure that the sort can handle integer edge cases. + check_is_sorted::(&mut [i32::MIN, i32::MAX]); + check_is_sorted::(&mut [i32::MAX, i32::MIN]); + check_is_sorted::(&mut [i32::MIN, 3]); + check_is_sorted::(&mut [i32::MIN, -3]); + check_is_sorted::(&mut [i32::MIN, -3, i32::MAX]); + check_is_sorted::(&mut [i32::MIN, -3, i32::MAX, i32::MIN, 5]); + check_is_sorted::(&mut [i32::MAX, 3, i32::MIN, 5, i32::MIN, -3, 60, 200, 50, 7, 10]); + + check_is_sorted::(&mut [u64::MIN, u64::MAX]); + check_is_sorted::(&mut [u64::MAX, u64::MIN]); + check_is_sorted::(&mut [u64::MIN, 3]); + check_is_sorted::(&mut [u64::MIN, u64::MAX - 3]); + check_is_sorted::(&mut [u64::MIN, u64::MAX - 3, u64::MAX]); + check_is_sorted::(&mut [u64::MIN, u64::MAX - 3, u64::MAX, u64::MIN, 5]); + check_is_sorted::(&mut [ + u64::MAX, + 3, + u64::MIN, + 5, + u64::MIN, + u64::MAX - 3, + 60, + 200, + 50, + 7, + 10, + ]); + + let mut large = patterns::random(TEST_LENGTHS[TEST_LENGTHS.len() - 2]); + large.push(i32::MAX); + large.push(i32::MIN); + large.push(i32::MAX); + check_is_sorted::(&mut large); +} + +fn sort_vs_sort_by_impl() { + // Ensure that sort and sort_by produce the same result. + let mut input_normal = [800, 3, -801, 5, -801, -3, 60, 200, 50, 7, 10]; + let expected = [-801, -801, -3, 3, 5, 7, 10, 50, 60, 200, 800]; + + let mut input_sort_by = input_normal.to_vec(); + + ::sort(&mut input_normal); + ::sort_by(&mut input_sort_by, |a, b| a.cmp(b)); + + assert_eq!(input_normal, expected); + assert_eq!(input_sort_by, expected); +} + +gen_sort_test_fns_with_default_patterns!( + correct_i32, + |len, pattern_fn| test_is_sorted::(len, |val| val, pattern_fn), + TEST_LENGTHS, + [ + (random_d4, |len| patterns::random_uniform(len, 0..4)), + (random_d8, |len| patterns::random_uniform(len, 0..8)), + (random_d311, |len| patterns::random_uniform(len, 0..311)), + (random_d1024, |len| patterns::random_uniform(len, 0..1024)), + (random_z1_03, |len| patterns::random_zipf(len, 1.03)), + (random_z2, |len| patterns::random_zipf(len, 2.0)), + (random_s50, |len| patterns::random_sorted(len, 50.0)), + (narrow, |len| patterns::random_uniform( + len, + 0..=(((len as f64).log2().round()) as i32) * 100 + )), + (all_equal, patterns::all_equal), + (saw_mixed_range, |len| patterns::saw_mixed_range(len, 20..50)), + (pipe_organ, patterns::pipe_organ), + ] +); + +gen_sort_test_fns_with_default_patterns!( + correct_u64, + |len, pattern_fn| test_is_sorted::(len, extend_i32_to_u64, pattern_fn), + TEST_LENGTHS, + [] +); + +gen_sort_test_fns_with_default_patterns!( + correct_u128, + |len, pattern_fn| test_is_sorted::(len, extend_i32_to_u128, pattern_fn), + &TEST_LENGTHS[..TEST_LENGTHS.len() - 2], + [] +); + +gen_sort_test_fns_with_default_patterns!( + correct_cell_i32, + |len, pattern_fn| test_is_sorted::, S>(len, Cell::new, pattern_fn), + &TEST_LENGTHS[..TEST_LENGTHS.len() - 2], + [] +); + +gen_sort_test_fns_with_default_patterns!( + correct_string, + |len, pattern_fn| test_is_sorted::( + len, + |val| format!("{:010}", shift_i32_to_u32(val)), + pattern_fn + ), + &TEST_LENGTHS[..TEST_LENGTHS.len() - 2], + [] +); + +gen_sort_test_fns_with_default_patterns!( + correct_f128, + |len, pattern_fn| test_is_sorted::(len, F128::new, pattern_fn), + &TEST_LENGTHS[..TEST_LENGTHS.len() - 2], + [] +); + +gen_sort_test_fns_with_default_patterns!( + correct_1k, + |len, pattern_fn| test_is_sorted::(len, FFIOneKibiByte::new, pattern_fn), + &TEST_LENGTHS[..TEST_LENGTHS.len() - 2], + [] +); + +// Dyn values are fat pointers, something the implementation might have overlooked. +gen_sort_test_fns_with_default_patterns!( + correct_dyn_val, + |len, pattern_fn| test_is_sorted::, S>(len, dyn_trait_from_i32, pattern_fn), + &TEST_LENGTHS[..TEST_LENGTHS.len() - 2], + [] +); + +fn stability_legacy_impl() { + // This non pattern variant has proven to catch some bugs the pattern version of this function + // doesn't catch, so it remains in conjunction with the other one. + + if ::name().contains("unstable") { + // It would be great to mark the test as skipped, but that isn't possible as of now. + return; + } + + let large_range = if cfg!(miri) { 100..110 } else { 3000..3010 }; + let rounds = if cfg!(miri) { 1 } else { 10 }; + + let rand_vals = patterns::random_uniform(5_000, 0..=9); + let mut rand_idx = 0; + + for len in (2..55).chain(large_range) { + for _ in 0..rounds { + let mut counts = [0; 10]; + + // create a vector like [(6, 1), (5, 1), (6, 2), ...], + // where the first item of each tuple is random, but + // the second item represents which occurrence of that + // number this element is, i.e., the second elements + // will occur in sorted order. + let orig: Vec<_> = (0..len) + .map(|_| { + let n = rand_vals[rand_idx]; + rand_idx += 1; + if rand_idx >= rand_vals.len() { + rand_idx = 0; + } + + counts[n as usize] += 1; + i32_tup_as_u64((n, counts[n as usize])) + }) + .collect(); + + let mut v = orig.clone(); + // Only sort on the first element, so an unstable sort + // may mix up the counts. + ::sort_by(&mut v, |a_packed, b_packed| { + let a = i32_tup_from_u64(*a_packed).0; + let b = i32_tup_from_u64(*b_packed).0; + + a.cmp(&b) + }); + + // This comparison includes the count (the second item + // of the tuple), so elements with equal first items + // will need to be ordered with increasing + // counts... i.e., exactly asserting that this sort is + // stable. + assert!(v.windows(2).all(|w| i32_tup_from_u64(w[0]) <= i32_tup_from_u64(w[1]))); + } + } + + // For cpp_sorts that only support u64 we can pack the two i32 inside a u64. + fn i32_tup_as_u64(val: (i32, i32)) -> u64 { + let a_bytes = val.0.to_le_bytes(); + let b_bytes = val.1.to_le_bytes(); + + u64::from_le_bytes([a_bytes, b_bytes].concat().try_into().unwrap()) + } + + fn i32_tup_from_u64(val: u64) -> (i32, i32) { + let bytes = val.to_le_bytes(); + + let a = i32::from_le_bytes(bytes[0..4].try_into().unwrap()); + let b = i32::from_le_bytes(bytes[4..8].try_into().unwrap()); + + (a, b) + } +} + +fn stability_with_patterns( + len: usize, + type_into_fn: impl Fn(i32) -> T, + _type_from_fn: impl Fn(&T) -> i32, + pattern_fn: fn(usize) -> Vec, +) { + if ::name().contains("unstable") { + // It would be great to mark the test as skipped, but that isn't possible as of now. + return; + } + + let pattern = pattern_fn(len); + + let mut counts = [0i32; 128]; + + // create a vector like [(6, 1), (5, 1), (6, 2), ...], + // where the first item of each tuple is random, but + // the second item represents which occurrence of that + // number this element is, i.e., the second elements + // will occur in sorted order. + let orig: Vec<_> = pattern + .iter() + .map(|val| { + let n = val.saturating_abs() % counts.len() as i32; + counts[n as usize] += 1; + (type_into_fn(n), counts[n as usize]) + }) + .collect(); + + let mut v = orig.clone(); + // Only sort on the first element, so an unstable sort + // may mix up the counts. + ::sort(&mut v); + + // This comparison includes the count (the second item + // of the tuple), so elements with equal first items + // will need to be ordered with increasing + // counts... i.e., exactly asserting that this sort is + // stable. + assert!(v.windows(2).all(|w| w[0] <= w[1])); +} + +gen_sort_test_fns_with_default_patterns_3_ty!(stability, stability_with_patterns, []); + +fn observable_is_less(len: usize, pattern_fn: fn(usize) -> Vec) { + // This test, tests that every is_less is actually observable. Ie. this can go wrong if a hole + // is created using temporary memory and, the whole is used as comparison but not copied back. + // + // If this is not upheld a custom type + comparison function could yield UB in otherwise safe + // code. Eg T == Mutex>> which replaces the pointer with none in the comparison + // function, which would not be observed in the original slice and would lead to a double free. + + let pattern = pattern_fn(len); + let mut test_input = pattern.into_iter().map(|val| CompCount::new(val)).collect::>(); + + let mut comp_count_global = 0; + + ::sort_by(&mut test_input, |a, b| { + a.comp_count.replace(a.comp_count.get() + 1); + b.comp_count.replace(b.comp_count.get() + 1); + comp_count_global += 1; + + a.val.cmp(&b.val) + }); + + let total_inner: u64 = test_input.iter().map(|c| c.comp_count.get() as u64).sum(); + + assert_eq!(total_inner, comp_count_global * 2); +} + +gen_sort_test_fns_with_default_patterns!( + observable_is_less, + observable_is_less::, + &TEST_LENGTHS[..TEST_LENGTHS.len() - 2], + [] +); + +fn panic_retain_orig_set( + len: usize, + type_into_fn: impl Fn(i32) -> T + Copy, + type_from_fn: impl Fn(&T) -> i32, + pattern_fn: fn(usize) -> Vec, +) { + let mut test_data: Vec = pattern_fn(len).into_iter().map(type_into_fn).collect(); + + let sum_before: i64 = test_data.iter().map(|x| type_from_fn(x) as i64).sum(); + + // Calculate a specific comparison that should panic. + // Ensure that it can be any of the possible comparisons and that it always panics. + let required_comps = calc_comps_required::(&mut test_data.clone(), |a, b| a.cmp(b)); + let panic_threshold = patterns::random_uniform(1, 1..=required_comps as i32)[0] as usize - 1; + + let mut comp_counter = 0; + + let res = panic::catch_unwind(AssertUnwindSafe(|| { + ::sort_by(&mut test_data, |a, b| { + if comp_counter == panic_threshold { + // Make the panic dependent on the test len and some random factor. We want to + // make sure that panicking may also happen when comparing elements a second + // time. + panic!(); + } + comp_counter += 1; + + a.cmp(b) + }); + })); + + assert!(res.is_err()); + + // If the sum before and after don't match, it means the set of elements hasn't remained the + // same. + let sum_after: i64 = test_data.iter().map(|x| type_from_fn(x) as i64).sum(); + assert_eq!(sum_before, sum_after); +} + +gen_sort_test_fns_with_default_patterns_3_ty!(panic_retain_orig_set, panic_retain_orig_set, []); + +fn panic_observable_is_less(len: usize, pattern_fn: fn(usize) -> Vec) { + // This test, tests that every is_less is actually observable. Ie. this can go wrong if a hole + // is created using temporary memory and, the whole is used as comparison but not copied back. + // This property must also hold if the user provided comparison panics. + // + // If this is not upheld a custom type + comparison function could yield UB in otherwise safe + // code. Eg T == Mutex>> which replaces the pointer with none in the comparison + // function, which would not be observed in the original slice and would lead to a double free. + + let mut test_input = + pattern_fn(len).into_iter().map(|val| CompCount::new(val)).collect::>(); + + let sum_before: i64 = test_input.iter().map(|x| x.val as i64).sum(); + + // Calculate a specific comparison that should panic. + // Ensure that it can be any of the possible comparisons and that it always panics. + let required_comps = + calc_comps_required::(&mut test_input.clone(), |a, b| a.val.cmp(&b.val)); + + let panic_threshold = patterns::random_uniform(1, 1..=required_comps as i32)[0] as u64 - 1; + + let mut comp_count_global = 0; + + let res = panic::catch_unwind(AssertUnwindSafe(|| { + ::sort_by(&mut test_input, |a, b| { + if comp_count_global == panic_threshold { + // Make the panic dependent on the test len and some random factor. We want to + // make sure that panicking may also happen when comparing elements a second + // time. + panic!(); + } + + a.comp_count.replace(a.comp_count.get() + 1); + b.comp_count.replace(b.comp_count.get() + 1); + comp_count_global += 1; + + a.val.cmp(&b.val) + }); + })); + + assert!(res.is_err()); + + let total_inner: u64 = test_input.iter().map(|c| c.comp_count.get() as u64).sum(); + + assert_eq!(total_inner, comp_count_global * 2); + + // If the sum before and after don't match, it means the set of elements hasn't remained the + // same. + let sum_after: i64 = test_input.iter().map(|x| x.val as i64).sum(); + assert_eq!(sum_before, sum_after); +} + +gen_sort_test_fns_with_default_patterns!( + panic_observable_is_less, + panic_observable_is_less::, + &TEST_LENGTHS[..TEST_LENGTHS.len() - 2], + [] +); + +fn deterministic( + len: usize, + type_into_fn: impl Fn(i32) -> T + Copy, + type_from_fn: impl Fn(&T) -> i32, + pattern_fn: fn(usize) -> Vec, +) { + // A property similar to stability is deterministic output order. If the entire value is used as + // the comparison key a lack of determinism has no effect. But if only a part of the value is + // used as comparison key, a lack of determinism can manifest itself in the order of values + // considered equal by the comparison predicate. + // + // This test only tests that results are deterministic across runs, it does not test determinism + // on different platforms and with different toolchains. + + let mut test_input = + pattern_fn(len).into_iter().map(|val| type_into_fn(val)).collect::>(); + + let mut test_input_clone = test_input.clone(); + + let comparison_fn = |a: &T, b: &T| { + let a_i32 = type_from_fn(a); + let b_i32 = type_from_fn(b); + + let a_i32_key_space_reduced = a_i32 % 10_000; + let b_i32_key_space_reduced = b_i32 % 10_000; + + a_i32_key_space_reduced.cmp(&b_i32_key_space_reduced) + }; + + ::sort_by(&mut test_input, comparison_fn); + ::sort_by(&mut test_input_clone, comparison_fn); + + assert_eq!(test_input, test_input_clone); +} + +gen_sort_test_fns_with_default_patterns_3_ty!(deterministic, deterministic, []); + +fn self_cmp( + len: usize, + type_into_fn: impl Fn(i32) -> T + Copy, + _type_from_fn: impl Fn(&T) -> i32, + pattern_fn: fn(usize) -> Vec, +) { + // It's possible for comparisons to run into problems if the values of `a` and `b` passed into + // the comparison function are the same reference. So this tests that they never are. + + let mut test_input = + pattern_fn(len).into_iter().map(|val| type_into_fn(val)).collect::>(); + + let comparison_fn = |a: &T, b: &T| { + assert_ne!(a as *const T as usize, b as *const T as usize); + a.cmp(b) + }; + + ::sort_by(&mut test_input, comparison_fn); + + // Check that the output is actually sorted and wasn't stopped by the assert. + for window in test_input.windows(2) { + assert!(window[0] <= window[1]); + } +} + +gen_sort_test_fns_with_default_patterns_3_ty!(self_cmp, self_cmp, []); + +fn violate_ord_retain_orig_set( + len: usize, + type_into_fn: impl Fn(i32) -> T + Copy, + type_from_fn: impl Fn(&T) -> i32, + pattern_fn: fn(usize) -> Vec, +) { + // A user may implement Ord incorrectly for a type or violate it by calling sort_by with a + // comparison function that violates Ord with the orderings it returns. Even under such + // circumstances the input must retain its original set of elements. + + // Ord implies a strict total order see https://en.wikipedia.org/wiki/Total_order. + + // Generating random numbers with miri is quite expensive. + let random_orderings_len = if cfg!(miri) { 200 } else { 10_000 }; + + // Make sure we get a good distribution of random orderings, that are repeatable with the seed. + // Just using random_uniform with the same len and range will always yield the same value. + let random_orderings = patterns::random_uniform(random_orderings_len, 0..2); + + let get_random_0_1_or_2 = |random_idx: &mut usize| { + let ridx = *random_idx; + *random_idx += 1; + if ridx + 1 == random_orderings.len() { + *random_idx = 0; + } + + random_orderings[ridx] as usize + }; + + let mut random_idx_a = 0; + let mut random_idx_b = 0; + let mut random_idx_c = 0; + + let mut last_element_a = -1; + let mut last_element_b = -1; + + let mut rand_counter_b = 0; + let mut rand_counter_c = 0; + + let mut streak_counter_a = 0; + let mut streak_counter_b = 0; + + // Examples, a = 3, b = 5, c = 9. + // Correct Ord -> 10010 | is_less(a, b) is_less(a, a) is_less(b, a) is_less(a, c) is_less(c, a) + let mut invalid_ord_comp_functions: Vec Ordering>> = vec![ + Box::new(|_a, _b| -> Ordering { + // random + // Eg. is_less(3, 5) == true, is_less(3, 5) == false + + let idx = get_random_0_1_or_2(&mut random_idx_a); + [Ordering::Less, Ordering::Equal, Ordering::Greater][idx] + }), + Box::new(|_a, _b| -> Ordering { + // everything is less -> 11111 + Ordering::Less + }), + Box::new(|_a, _b| -> Ordering { + // everything is equal -> 00000 + Ordering::Equal + }), + Box::new(|_a, _b| -> Ordering { + // everything is greater -> 00000 + // Eg. is_less(3, 5) == false, is_less(5, 3) == false, is_less(3, 3) == false + Ordering::Greater + }), + Box::new(|a, b| -> Ordering { + // equal means less else greater -> 01000 + if a == b { Ordering::Less } else { Ordering::Greater } + }), + Box::new(|a, b| -> Ordering { + // Transitive breaker. remember last element -> 10001 + let lea = last_element_a; + let leb = last_element_b; + + let a_as_i32 = type_from_fn(a); + let b_as_i32 = type_from_fn(b); + + last_element_a = a_as_i32; + last_element_b = b_as_i32; + + if a_as_i32 == lea && b_as_i32 != leb { b.cmp(a) } else { a.cmp(b) } + }), + Box::new(|a, b| -> Ordering { + // Sampled random 1% of comparisons are reversed. + rand_counter_b += get_random_0_1_or_2(&mut random_idx_b); + if rand_counter_b >= 100 { + rand_counter_b = 0; + b.cmp(a) + } else { + a.cmp(b) + } + }), + Box::new(|a, b| -> Ordering { + // Sampled random 33% of comparisons are reversed. + rand_counter_c += get_random_0_1_or_2(&mut random_idx_c); + if rand_counter_c >= 3 { + rand_counter_c = 0; + b.cmp(a) + } else { + a.cmp(b) + } + }), + Box::new(|a, b| -> Ordering { + // STREAK_LEN comparisons yield a.cmp(b) then STREAK_LEN comparisons less. This can + // discover bugs that neither, random Ord, or just Less or Greater can find. Because it + // can push a pointer further than expected. Random Ord will average out how far a + // comparison based pointer travels. Just Less or Greater will be caught by pattern + // analysis and never enter interesting code. + const STREAK_LEN: usize = 50; + + streak_counter_a += 1; + if streak_counter_a <= STREAK_LEN { + a.cmp(b) + } else { + if streak_counter_a == STREAK_LEN * 2 { + streak_counter_a = 0; + } + Ordering::Less + } + }), + Box::new(|a, b| -> Ordering { + // See above. + const STREAK_LEN: usize = 50; + + streak_counter_b += 1; + if streak_counter_b <= STREAK_LEN { + a.cmp(b) + } else { + if streak_counter_b == STREAK_LEN * 2 { + streak_counter_b = 0; + } + Ordering::Greater + } + }), + ]; + + for comp_func in &mut invalid_ord_comp_functions { + let mut test_data: Vec = pattern_fn(len).into_iter().map(type_into_fn).collect(); + let sum_before: i64 = test_data.iter().map(|x| type_from_fn(x) as i64).sum(); + + // It's ok to panic on Ord violation or to complete. + // In both cases the original elements must still be present. + let _ = panic::catch_unwind(AssertUnwindSafe(|| { + ::sort_by(&mut test_data, &mut *comp_func); + })); + + // If the sum before and after don't match, it means the set of elements hasn't remained the + // same. + let sum_after: i64 = test_data.iter().map(|x| type_from_fn(x) as i64).sum(); + assert_eq!(sum_before, sum_after); + + if cfg!(miri) { + // This test is prohibitively expensive in miri, so only run one of the comparison + // functions. This test is not expected to yield direct UB, but rather surface potential + // UB by showing that the sum is different now. + break; + } + } +} + +gen_sort_test_fns_with_default_patterns_3_ty!( + violate_ord_retain_orig_set, + violate_ord_retain_orig_set, + [] +); + +macro_rules! instantiate_sort_test_inner { + ($sort_impl:ty, miri_yes, $test_fn_name:ident) => { + #[test] + fn $test_fn_name() { + $crate::sort::tests::$test_fn_name::<$sort_impl>(); + } + }; + ($sort_impl:ty, miri_no, $test_fn_name:ident) => { + #[test] + #[cfg_attr(miri, ignore)] + fn $test_fn_name() { + $crate::sort::tests::$test_fn_name::<$sort_impl>(); + } + }; +} + +// Using this construct allows us to get warnings for unused test functions. +macro_rules! define_instantiate_sort_tests { + ($([$miri_use:ident, $test_fn_name:ident]),*,) => { + $(pub fn $test_fn_name() { + ${concat($test_fn_name, _impl)}::(); + })* + + + macro_rules! instantiate_sort_tests_gen { + ($sort_impl:ty) => { + $( + instantiate_sort_test_inner!( + $sort_impl, + $miri_use, + $test_fn_name + ); + )* + } + } + }; +} + +// Some tests are not tested with miri to avoid prohibitively long test times. This leaves coverage +// holes, but the way they are selected should make for relatively small holes. Many properties that +// can lead to UB are tested directly, for example that the original set of elements is retained +// even when a panic occurs or Ord is implemented incorrectly. +define_instantiate_sort_tests!( + [miri_yes, basic], + [miri_yes, fixed_seed], + [miri_yes, fixed_seed_rand_vec_prefix], + [miri_yes, int_edge], + [miri_yes, sort_vs_sort_by], + [miri_yes, correct_i32_random], + [miri_yes, correct_i32_random_z1], + [miri_yes, correct_i32_random_d2], + [miri_yes, correct_i32_random_d20], + [miri_yes, correct_i32_random_s95], + [miri_yes, correct_i32_ascending], + [miri_yes, correct_i32_descending], + [miri_yes, correct_i32_saw_mixed], + [miri_no, correct_i32_random_d4], + [miri_no, correct_i32_random_d8], + [miri_no, correct_i32_random_d311], + [miri_no, correct_i32_random_d1024], + [miri_no, correct_i32_random_z1_03], + [miri_no, correct_i32_random_z2], + [miri_no, correct_i32_random_s50], + [miri_no, correct_i32_narrow], + [miri_no, correct_i32_all_equal], + [miri_no, correct_i32_saw_mixed_range], + [miri_yes, correct_i32_pipe_organ], + [miri_no, correct_u64_random], + [miri_yes, correct_u64_random_z1], + [miri_no, correct_u64_random_d2], + [miri_no, correct_u64_random_d20], + [miri_no, correct_u64_random_s95], + [miri_no, correct_u64_ascending], + [miri_no, correct_u64_descending], + [miri_no, correct_u64_saw_mixed], + [miri_no, correct_u128_random], + [miri_yes, correct_u128_random_z1], + [miri_no, correct_u128_random_d2], + [miri_no, correct_u128_random_d20], + [miri_no, correct_u128_random_s95], + [miri_no, correct_u128_ascending], + [miri_no, correct_u128_descending], + [miri_no, correct_u128_saw_mixed], + [miri_no, correct_cell_i32_random], + [miri_yes, correct_cell_i32_random_z1], + [miri_no, correct_cell_i32_random_d2], + [miri_no, correct_cell_i32_random_d20], + [miri_no, correct_cell_i32_random_s95], + [miri_no, correct_cell_i32_ascending], + [miri_no, correct_cell_i32_descending], + [miri_no, correct_cell_i32_saw_mixed], + [miri_no, correct_string_random], + [miri_yes, correct_string_random_z1], + [miri_no, correct_string_random_d2], + [miri_no, correct_string_random_d20], + [miri_no, correct_string_random_s95], + [miri_no, correct_string_ascending], + [miri_no, correct_string_descending], + [miri_no, correct_string_saw_mixed], + [miri_no, correct_f128_random], + [miri_yes, correct_f128_random_z1], + [miri_no, correct_f128_random_d2], + [miri_no, correct_f128_random_d20], + [miri_no, correct_f128_random_s95], + [miri_no, correct_f128_ascending], + [miri_no, correct_f128_descending], + [miri_no, correct_f128_saw_mixed], + [miri_no, correct_1k_random], + [miri_yes, correct_1k_random_z1], + [miri_no, correct_1k_random_d2], + [miri_no, correct_1k_random_d20], + [miri_no, correct_1k_random_s95], + [miri_no, correct_1k_ascending], + [miri_no, correct_1k_descending], + [miri_no, correct_1k_saw_mixed], + [miri_no, correct_dyn_val_random], + [miri_yes, correct_dyn_val_random_z1], + [miri_no, correct_dyn_val_random_d2], + [miri_no, correct_dyn_val_random_d20], + [miri_no, correct_dyn_val_random_s95], + [miri_no, correct_dyn_val_ascending], + [miri_no, correct_dyn_val_descending], + [miri_no, correct_dyn_val_saw_mixed], + [miri_no, stability_legacy], + [miri_no, stability_i32_random], + [miri_yes, stability_i32_random_z1], + [miri_no, stability_i32_random_d2], + [miri_no, stability_i32_random_d20], + [miri_no, stability_i32_random_s95], + [miri_no, stability_i32_ascending], + [miri_no, stability_i32_descending], + [miri_no, stability_i32_saw_mixed], + [miri_no, stability_cell_i32_random], + [miri_yes, stability_cell_i32_random_z1], + [miri_no, stability_cell_i32_random_d2], + [miri_no, stability_cell_i32_random_d20], + [miri_no, stability_cell_i32_random_s95], + [miri_no, stability_cell_i32_ascending], + [miri_no, stability_cell_i32_descending], + [miri_no, stability_cell_i32_saw_mixed], + [miri_no, stability_string_random], + [miri_yes, stability_string_random_z1], + [miri_no, stability_string_random_d2], + [miri_no, stability_string_random_d20], + [miri_no, stability_string_random_s95], + [miri_no, stability_string_ascending], + [miri_no, stability_string_descending], + [miri_no, stability_string_saw_mixed], + [miri_no, observable_is_less_random], + [miri_yes, observable_is_less_random_z1], + [miri_no, observable_is_less_random_d2], + [miri_no, observable_is_less_random_d20], + [miri_no, observable_is_less_random_s95], + [miri_no, observable_is_less_ascending], + [miri_no, observable_is_less_descending], + [miri_no, observable_is_less_saw_mixed], + [miri_no, panic_retain_orig_set_i32_random], + [miri_yes, panic_retain_orig_set_i32_random_z1], + [miri_no, panic_retain_orig_set_i32_random_d2], + [miri_no, panic_retain_orig_set_i32_random_d20], + [miri_no, panic_retain_orig_set_i32_random_s95], + [miri_no, panic_retain_orig_set_i32_ascending], + [miri_no, panic_retain_orig_set_i32_descending], + [miri_no, panic_retain_orig_set_i32_saw_mixed], + [miri_no, panic_retain_orig_set_cell_i32_random], + [miri_yes, panic_retain_orig_set_cell_i32_random_z1], + [miri_no, panic_retain_orig_set_cell_i32_random_d2], + [miri_no, panic_retain_orig_set_cell_i32_random_d20], + [miri_no, panic_retain_orig_set_cell_i32_random_s95], + [miri_no, panic_retain_orig_set_cell_i32_ascending], + [miri_no, panic_retain_orig_set_cell_i32_descending], + [miri_no, panic_retain_orig_set_cell_i32_saw_mixed], + [miri_no, panic_retain_orig_set_string_random], + [miri_yes, panic_retain_orig_set_string_random_z1], + [miri_no, panic_retain_orig_set_string_random_d2], + [miri_no, panic_retain_orig_set_string_random_d20], + [miri_no, panic_retain_orig_set_string_random_s95], + [miri_no, panic_retain_orig_set_string_ascending], + [miri_no, panic_retain_orig_set_string_descending], + [miri_no, panic_retain_orig_set_string_saw_mixed], + [miri_no, panic_observable_is_less_random], + [miri_yes, panic_observable_is_less_random_z1], + [miri_no, panic_observable_is_less_random_d2], + [miri_no, panic_observable_is_less_random_d20], + [miri_no, panic_observable_is_less_random_s95], + [miri_no, panic_observable_is_less_ascending], + [miri_no, panic_observable_is_less_descending], + [miri_no, panic_observable_is_less_saw_mixed], + [miri_no, deterministic_i32_random], + [miri_yes, deterministic_i32_random_z1], + [miri_no, deterministic_i32_random_d2], + [miri_no, deterministic_i32_random_d20], + [miri_no, deterministic_i32_random_s95], + [miri_no, deterministic_i32_ascending], + [miri_no, deterministic_i32_descending], + [miri_no, deterministic_i32_saw_mixed], + [miri_no, deterministic_cell_i32_random], + [miri_yes, deterministic_cell_i32_random_z1], + [miri_no, deterministic_cell_i32_random_d2], + [miri_no, deterministic_cell_i32_random_d20], + [miri_no, deterministic_cell_i32_random_s95], + [miri_no, deterministic_cell_i32_ascending], + [miri_no, deterministic_cell_i32_descending], + [miri_no, deterministic_cell_i32_saw_mixed], + [miri_no, deterministic_string_random], + [miri_yes, deterministic_string_random_z1], + [miri_no, deterministic_string_random_d2], + [miri_no, deterministic_string_random_d20], + [miri_no, deterministic_string_random_s95], + [miri_no, deterministic_string_ascending], + [miri_no, deterministic_string_descending], + [miri_no, deterministic_string_saw_mixed], + [miri_no, self_cmp_i32_random], + [miri_yes, self_cmp_i32_random_z1], + [miri_no, self_cmp_i32_random_d2], + [miri_no, self_cmp_i32_random_d20], + [miri_no, self_cmp_i32_random_s95], + [miri_no, self_cmp_i32_ascending], + [miri_no, self_cmp_i32_descending], + [miri_no, self_cmp_i32_saw_mixed], + [miri_no, self_cmp_cell_i32_random], + [miri_yes, self_cmp_cell_i32_random_z1], + [miri_no, self_cmp_cell_i32_random_d2], + [miri_no, self_cmp_cell_i32_random_d20], + [miri_no, self_cmp_cell_i32_random_s95], + [miri_no, self_cmp_cell_i32_ascending], + [miri_no, self_cmp_cell_i32_descending], + [miri_no, self_cmp_cell_i32_saw_mixed], + [miri_no, self_cmp_string_random], + [miri_yes, self_cmp_string_random_z1], + [miri_no, self_cmp_string_random_d2], + [miri_no, self_cmp_string_random_d20], + [miri_no, self_cmp_string_random_s95], + [miri_no, self_cmp_string_ascending], + [miri_no, self_cmp_string_descending], + [miri_no, self_cmp_string_saw_mixed], + [miri_no, violate_ord_retain_orig_set_i32_random], + [miri_yes, violate_ord_retain_orig_set_i32_random_z1], + [miri_no, violate_ord_retain_orig_set_i32_random_d2], + [miri_no, violate_ord_retain_orig_set_i32_random_d20], + [miri_no, violate_ord_retain_orig_set_i32_random_s95], + [miri_no, violate_ord_retain_orig_set_i32_ascending], + [miri_no, violate_ord_retain_orig_set_i32_descending], + [miri_no, violate_ord_retain_orig_set_i32_saw_mixed], + [miri_no, violate_ord_retain_orig_set_cell_i32_random], + [miri_yes, violate_ord_retain_orig_set_cell_i32_random_z1], + [miri_no, violate_ord_retain_orig_set_cell_i32_random_d2], + [miri_no, violate_ord_retain_orig_set_cell_i32_random_d20], + [miri_no, violate_ord_retain_orig_set_cell_i32_random_s95], + [miri_no, violate_ord_retain_orig_set_cell_i32_ascending], + [miri_no, violate_ord_retain_orig_set_cell_i32_descending], + [miri_no, violate_ord_retain_orig_set_cell_i32_saw_mixed], + [miri_no, violate_ord_retain_orig_set_string_random], + [miri_yes, violate_ord_retain_orig_set_string_random_z1], + [miri_no, violate_ord_retain_orig_set_string_random_d2], + [miri_no, violate_ord_retain_orig_set_string_random_d20], + [miri_no, violate_ord_retain_orig_set_string_random_s95], + [miri_no, violate_ord_retain_orig_set_string_ascending], + [miri_no, violate_ord_retain_orig_set_string_descending], + [miri_no, violate_ord_retain_orig_set_string_saw_mixed], +); + +macro_rules! instantiate_sort_tests { + ($sort_impl:ty) => { + instantiate_sort_tests_gen!($sort_impl); + }; +} + +mod unstable { + struct SortImpl {} + + impl crate::sort::Sort for SortImpl { + fn name() -> String { + "rust_std_unstable".into() + } + + fn sort(v: &mut [T]) + where + T: Ord, + { + v.sort_unstable(); + } + + fn sort_by(v: &mut [T], mut compare: F) + where + F: FnMut(&T, &T) -> std::cmp::Ordering, + { + v.sort_unstable_by(|a, b| compare(a, b)); + } + } + + instantiate_sort_tests!(SortImpl); +} + +mod stable { + struct SortImpl {} + + impl crate::sort::Sort for SortImpl { + fn name() -> String { + "rust_std_stable".into() + } + + fn sort(v: &mut [T]) + where + T: Ord, + { + v.sort(); + } + + fn sort_by(v: &mut [T], mut compare: F) + where + F: FnMut(&T, &T) -> std::cmp::Ordering, + { + v.sort_by(|a, b| compare(a, b)); + } + } + + instantiate_sort_tests!(SortImpl); +} diff --git a/library/alloc/tests/sort/zipf.rs b/library/alloc/tests/sort/zipf.rs new file mode 100644 index 00000000000..cc774ee5c43 --- /dev/null +++ b/library/alloc/tests/sort/zipf.rs @@ -0,0 +1,208 @@ +// This module implements a Zipfian distribution generator. +// +// Based on https://github.com/jonhoo/rust-zipf. + +use rand::Rng; + +/// Random number generator that generates Zipf-distributed random numbers using rejection +/// inversion. +#[derive(Clone, Copy)] +pub struct ZipfDistribution { + /// Number of elements + num_elements: f64, + /// Exponent parameter of the distribution + exponent: f64, + /// `hIntegral(1.5) - 1}` + h_integral_x1: f64, + /// `hIntegral(num_elements + 0.5)}` + h_integral_num_elements: f64, + /// `2 - hIntegralInverse(hIntegral(2.5) - h(2)}` + s: f64, +} + +impl ZipfDistribution { + /// Creates a new [Zipf-distributed](https://en.wikipedia.org/wiki/Zipf's_law) + /// random number generator. + /// + /// Note that both the number of elements and the exponent must be greater than 0. + pub fn new(num_elements: usize, exponent: f64) -> Result { + if num_elements == 0 { + return Err(()); + } + if exponent <= 0f64 { + return Err(()); + } + + let z = ZipfDistribution { + num_elements: num_elements as f64, + exponent, + h_integral_x1: ZipfDistribution::h_integral(1.5, exponent) - 1f64, + h_integral_num_elements: ZipfDistribution::h_integral( + num_elements as f64 + 0.5, + exponent, + ), + s: 2f64 + - ZipfDistribution::h_integral_inv( + ZipfDistribution::h_integral(2.5, exponent) + - ZipfDistribution::h(2f64, exponent), + exponent, + ), + }; + + // populate cache + + Ok(z) + } +} + +impl ZipfDistribution { + fn next(&self, rng: &mut R) -> usize { + // The paper describes an algorithm for exponents larger than 1 (Algorithm ZRI). + // + // The original method uses + // H(x) = (v + x)^(1 - q) / (1 - q) + // as the integral of the hat function. + // + // This function is undefined for q = 1, which is the reason for the limitation of the + // exponent. + // + // If instead the integral function + // H(x) = ((v + x)^(1 - q) - 1) / (1 - q) + // is used, for which a meaningful limit exists for q = 1, the method works for all + // positive exponents. + // + // The following implementation uses v = 0 and generates integral number in the range [1, + // num_elements]. This is different to the original method where v is defined to + // be positive and numbers are taken from [0, i_max]. This explains why the implementation + // looks slightly different. + + let hnum = self.h_integral_num_elements; + + loop { + use std::cmp; + let u: f64 = hnum + rng.gen::() * (self.h_integral_x1 - hnum); + // u is uniformly distributed in (h_integral_x1, h_integral_num_elements] + + let x: f64 = ZipfDistribution::h_integral_inv(u, self.exponent); + + // Limit k to the range [1, num_elements] if it would be outside + // due to numerical inaccuracies. + let k64 = x.max(1.0).min(self.num_elements); + // float -> integer rounds towards zero, so we add 0.5 + // to prevent bias towards k == 1 + let k = cmp::max(1, (k64 + 0.5) as usize); + + // Here, the distribution of k is given by: + // + // P(k = 1) = C * (hIntegral(1.5) - h_integral_x1) = C + // P(k = m) = C * (hIntegral(m + 1/2) - hIntegral(m - 1/2)) for m >= 2 + // + // where C = 1 / (h_integral_num_elements - h_integral_x1) + if k64 - x <= self.s + || u >= ZipfDistribution::h_integral(k64 + 0.5, self.exponent) + - ZipfDistribution::h(k64, self.exponent) + { + // Case k = 1: + // + // The right inequality is always true, because replacing k by 1 gives + // u >= hIntegral(1.5) - h(1) = h_integral_x1 and u is taken from + // (h_integral_x1, h_integral_num_elements]. + // + // Therefore, the acceptance rate for k = 1 is P(accepted | k = 1) = 1 + // and the probability that 1 is returned as random value is + // P(k = 1 and accepted) = P(accepted | k = 1) * P(k = 1) = C = C / 1^exponent + // + // Case k >= 2: + // + // The left inequality (k - x <= s) is just a short cut + // to avoid the more expensive evaluation of the right inequality + // (u >= hIntegral(k + 0.5) - h(k)) in many cases. + // + // If the left inequality is true, the right inequality is also true: + // Theorem 2 in the paper is valid for all positive exponents, because + // the requirements h'(x) = -exponent/x^(exponent + 1) < 0 and + // (-1/hInverse'(x))'' = (1+1/exponent) * x^(1/exponent-1) >= 0 + // are both fulfilled. + // Therefore, f(x) = x - hIntegralInverse(hIntegral(x + 0.5) - h(x)) + // is a non-decreasing function. If k - x <= s holds, + // k - x <= s + f(k) - f(2) is obviously also true which is equivalent to + // -x <= -hIntegralInverse(hIntegral(k + 0.5) - h(k)), + // -hIntegralInverse(u) <= -hIntegralInverse(hIntegral(k + 0.5) - h(k)), + // and finally u >= hIntegral(k + 0.5) - h(k). + // + // Hence, the right inequality determines the acceptance rate: + // P(accepted | k = m) = h(m) / (hIntegrated(m+1/2) - hIntegrated(m-1/2)) + // The probability that m is returned is given by + // P(k = m and accepted) = P(accepted | k = m) * P(k = m) + // = C * h(m) = C / m^exponent. + // + // In both cases the probabilities are proportional to the probability mass + // function of the Zipf distribution. + + return k; + } + } + } +} + +impl rand::distributions::Distribution for ZipfDistribution { + fn sample(&self, rng: &mut R) -> usize { + self.next(rng) + } +} + +use std::fmt; +impl fmt::Debug for ZipfDistribution { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + f.debug_struct("ZipfDistribution") + .field("e", &self.exponent) + .field("n", &self.num_elements) + .finish() + } +} + +impl ZipfDistribution { + /// Computes `H(x)`, defined as + /// + /// - `(x^(1 - exponent) - 1) / (1 - exponent)`, if `exponent != 1` + /// - `log(x)`, if `exponent == 1` + /// + /// `H(x)` is an integral function of `h(x)`, the derivative of `H(x)` is `h(x)`. + fn h_integral(x: f64, exponent: f64) -> f64 { + let log_x = x.ln(); + helper2((1f64 - exponent) * log_x) * log_x + } + + /// Computes `h(x) = 1 / x^exponent` + fn h(x: f64, exponent: f64) -> f64 { + (-exponent * x.ln()).exp() + } + + /// The inverse function of `H(x)`. + /// Returns the `y` for which `H(y) = x`. + fn h_integral_inv(x: f64, exponent: f64) -> f64 { + let mut t: f64 = x * (1f64 - exponent); + if t < -1f64 { + // Limit value to the range [-1, +inf). + // t could be smaller than -1 in some rare cases due to numerical errors. + t = -1f64; + } + (helper1(t) * x).exp() + } +} + +/// Helper function that calculates `log(1 + x) / x`. +/// A Taylor series expansion is used, if x is close to 0. +fn helper1(x: f64) -> f64 { + if x.abs() > 1e-8 { x.ln_1p() / x } else { 1f64 - x * (0.5 - x * (1.0 / 3.0 - 0.25 * x)) } +} + +/// Helper function to calculate `(exp(x) - 1) / x`. +/// A Taylor series expansion is used, if x is close to 0. +fn helper2(x: f64) -> f64 { + if x.abs() > 1e-8 { + x.exp_m1() / x + } else { + 1f64 + x * 0.5 * (1f64 + x * 1.0 / 3.0 * (1f64 + 0.25 * x)) + } +} diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs index 7197f3812e5..9ae2bcc8526 100644 --- a/library/core/tests/slice.rs +++ b/library/core/tests/slice.rs @@ -1800,57 +1800,6 @@ fn brute_force_rotate_test_1() { } } -#[test] -#[cfg(not(target_arch = "wasm32"))] -fn sort_unstable() { - use rand::Rng; - - // Miri is too slow (but still need to `chain` to make the types match) - let lens = if cfg!(miri) { (2..20).chain(0..0) } else { (2..25).chain(500..510) }; - let rounds = if cfg!(miri) { 1 } else { 100 }; - - let mut v = [0; 600]; - let mut tmp = [0; 600]; - let mut rng = crate::test_rng(); - - for len in lens { - let v = &mut v[0..len]; - let tmp = &mut tmp[0..len]; - - for &modulus in &[5, 10, 100, 1000] { - for _ in 0..rounds { - for i in 0..len { - v[i] = rng.gen::() % modulus; - } - - // Sort in default order. - tmp.copy_from_slice(v); - tmp.sort_unstable(); - assert!(tmp.windows(2).all(|w| w[0] <= w[1])); - - // Sort in ascending order. - tmp.copy_from_slice(v); - tmp.sort_unstable_by(|a, b| a.cmp(b)); - assert!(tmp.windows(2).all(|w| w[0] <= w[1])); - - // Sort in descending order. - tmp.copy_from_slice(v); - tmp.sort_unstable_by(|a, b| b.cmp(a)); - assert!(tmp.windows(2).all(|w| w[0] >= w[1])); - } - } - } - - // Should not panic. - [0i32; 0].sort_unstable(); - [(); 10].sort_unstable(); - [(); 100].sort_unstable(); - - let mut v = [0xDEADBEEFu64]; - v.sort_unstable(); - assert!(v == [0xDEADBEEF]); -} - #[test] #[cfg(not(target_arch = "wasm32"))] #[cfg_attr(miri, ignore)] // Miri is too slow From cb0e1505cec1a70bc60f6aa9075384fcdf4759a3 Mon Sep 17 00:00:00 2001 From: Binlogo Date: Mon, 30 Sep 2024 22:45:26 +0800 Subject: [PATCH 020/357] Update doc.rs --- src/bootstrap/src/core/build_steps/doc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs index 3d504c3771f..1df76c23634 100644 --- a/src/bootstrap/src/core/build_steps/doc.rs +++ b/src/bootstrap/src/core/build_steps/doc.rs @@ -82,7 +82,7 @@ book!( EditionGuide, "src/doc/edition-guide", "edition-guide", &[], submodule; EmbeddedBook, "src/doc/embedded-book", "embedded-book", &[], submodule; Nomicon, "src/doc/nomicon", "nomicon", &[], submodule; - RustByExample, "src/doc/rust-by-example", "rust-by-example", &["ja"], submodule; + RustByExample, "src/doc/rust-by-example", "rust-by-example", &["ja", "zh"], submodule; RustdocBook, "src/doc/rustdoc", "rustdoc", &[]; StyleGuide, "src/doc/style-guide", "style-guide", &[]; ); From 48df1ff50536969b1ed14d0125b443fa54b57c44 Mon Sep 17 00:00:00 2001 From: ismailarilik Date: Mon, 30 Sep 2024 18:00:28 +0300 Subject: [PATCH 021/357] Fix std_detect links Fixes #96506 --- src/bootstrap/src/core/build_steps/doc.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs index 3d504c3771f..5e402378cc2 100644 --- a/src/bootstrap/src/core/build_steps/doc.rs +++ b/src/bootstrap/src/core/build_steps/doc.rs @@ -718,6 +718,10 @@ fn doc_std( .arg("--target-dir") .arg(&*target_dir.to_string_lossy()) .arg("-Zskip-rustdoc-fingerprint") + .arg("-Zrustdoc-map") + .rustdocflag("--extern-html-root-url") + .rustdocflag("std_detect=https://docs.rs/std_detect/latest/") + .rustdocflag("--extern-html-root-takes-precedence") .rustdocflag("--resource-suffix") .rustdocflag(&builder.version); for arg in extra_args { From e9047612313496f0cad1b0feb200072e0fd78027 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 1 Oct 2024 16:23:04 +0200 Subject: [PATCH 022/357] Use environment variables instead of command line arguments for merged doctests --- src/librustdoc/doctest.rs | 3 +-- src/librustdoc/doctest/runner.rs | 42 ++++++++++++-------------------- 2 files changed, 17 insertions(+), 28 deletions(-) diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index 3ee6b24ac92..e8bd36dffc7 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -644,8 +644,7 @@ fn run_test( } else { cmd = Command::new(&output_file); if doctest.is_multiple_tests { - cmd.arg("*doctest-bin-path"); - cmd.arg(&output_file); + cmd.env("RUSTDOC_DOCTEST_BIN_PATH", &output_file); } } if let Some(run_directory) = &rustdoc_options.test_run_directory { diff --git a/src/librustdoc/doctest/runner.rs b/src/librustdoc/doctest/runner.rs index 326ca4ee1e6..176008ae7a2 100644 --- a/src/librustdoc/doctest/runner.rs +++ b/src/librustdoc/doctest/runner.rs @@ -112,8 +112,7 @@ mod __doctest_mod {{ use std::path::PathBuf; pub static BINARY_PATH: OnceLock = OnceLock::new(); - pub const RUN_OPTION: &str = \"*doctest-inner-test\"; - pub const BIN_OPTION: &str = \"*doctest-bin-path\"; + pub const RUN_OPTION: &str = \"RUSTDOC_DOCTEST_RUN_NB_TEST\"; #[allow(unused)] pub fn doctest_path() -> Option<&'static PathBuf> {{ @@ -123,8 +122,8 @@ mod __doctest_mod {{ #[allow(unused)] pub fn doctest_runner(bin: &std::path::Path, test_nb: usize) -> Result<(), String> {{ let out = std::process::Command::new(bin) - .arg(self::RUN_OPTION) - .arg(test_nb.to_string()) + .env(self::RUN_OPTION, test_nb.to_string()) + .args(std::env::args().skip(1).collect::>()) .output() .expect(\"failed to run command\"); if !out.status.success() {{ @@ -138,36 +137,27 @@ mod __doctest_mod {{ #[rustc_main] fn main() -> std::process::ExitCode {{ const TESTS: [test::TestDescAndFn; {nb_tests}] = [{ids}]; -let bin_marker = std::ffi::OsStr::new(__doctest_mod::BIN_OPTION); let test_marker = std::ffi::OsStr::new(__doctest_mod::RUN_OPTION); let test_args = &[{test_args}]; +const ENV_BIN: &'static str = \"RUSTDOC_DOCTEST_BIN_PATH\"; -let mut args = std::env::args_os().skip(1); -while let Some(arg) = args.next() {{ - if arg == bin_marker {{ - let Some(binary) = args.next() else {{ - panic!(\"missing argument after `{{}}`\", __doctest_mod::BIN_OPTION); - }}; - if crate::__doctest_mod::BINARY_PATH.set(binary.into()).is_err() {{ - panic!(\"`{{}}` option was used more than once\", bin_marker.to_string_lossy()); - }} - return std::process::Termination::report(test::test_main(test_args, Vec::from(TESTS), None)); - }} else if arg == test_marker {{ - let Some(nb_test) = args.next() else {{ - panic!(\"missing argument after `{{}}`\", __doctest_mod::RUN_OPTION); - }}; - if let Some(nb_test) = nb_test.to_str().and_then(|nb| nb.parse::().ok()) {{ - if let Some(test) = TESTS.get(nb_test) {{ - if let test::StaticTestFn(f) = test.testfn {{ - return std::process::Termination::report(f()); - }} +if let Ok(binary) = std::env::var(ENV_BIN) {{ + let _ = crate::__doctest_mod::BINARY_PATH.set(binary.into()); + unsafe {{ std::env::remove_var(ENV_BIN); }} + return std::process::Termination::report(test::test_main(test_args, Vec::from(TESTS), None)); +}} else if let Ok(nb_test) = std::env::var(__doctest_mod::RUN_OPTION) {{ + if let Ok(nb_test) = nb_test.parse::() {{ + if let Some(test) = TESTS.get(nb_test) {{ + if let test::StaticTestFn(f) = test.testfn {{ + return std::process::Termination::report(f()); }} }} - panic!(\"Unexpected value after `{{}}`\", __doctest_mod::RUN_OPTION); }} + panic!(\"Unexpected value for `{{}}`\", __doctest_mod::RUN_OPTION); }} -eprintln!(\"WARNING: No argument provided so doctests will be run in the same process\"); +eprintln!(\"WARNING: No rustdoc doctest environment variable provided so doctests will be run in \ +the same process\"); std::process::Termination::report(test::test_main(test_args, Vec::from(TESTS), None)) }}", nb_tests = self.nb_tests, From e3a0da18633a8cfb5263bb975747352690b01fcf Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 29 Sep 2024 22:10:16 -0400 Subject: [PATCH 023/357] Remove unnamed field feature --- compiler/rustc_ast_passes/messages.ftl | 8 - .../rustc_ast_passes/src/ast_validation.rs | 26 - compiler/rustc_ast_passes/src/errors.rs | 18 - compiler/rustc_ast_passes/src/feature_gate.rs | 1 - compiler/rustc_feature/src/removed.rs | 2 + compiler/rustc_feature/src/unstable.rs | 2 - compiler/rustc_hir_analysis/messages.ftl | 15 - .../rustc_hir_analysis/src/check/check.rs | 56 - compiler/rustc_hir_analysis/src/collect.rs | 104 +- compiler/rustc_hir_analysis/src/errors.rs | 42 - compiler/rustc_hir_typeck/src/expr.rs | 63 +- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 10 +- compiler/rustc_hir_typeck/src/pat.rs | 3 +- compiler/rustc_hir_typeck/src/writeback.rs | 5 - compiler/rustc_metadata/src/rmeta/decoder.rs | 3 - compiler/rustc_middle/src/ty/adt.rs | 9 +- compiler/rustc_middle/src/ty/context.rs | 10 +- compiler/rustc_middle/src/ty/mod.rs | 22 +- .../rustc_middle/src/ty/typeck_results.rs | 19 - compiler/rustc_mir_build/src/thir/cx/expr.rs | 20 +- compiler/rustc_parse/src/parser/item.rs | 4 +- .../feature-gate-unnamed_fields.rs | 29 - .../feature-gate-unnamed_fields.stderr | 63 - .../anon-struct-in-enum-issue-121446.rs | 11 - .../anon-struct-in-enum-issue-121446.stderr | 16 - .../ui/union/unnamed-fields/auxiliary/dep.rs | 18 - .../unnamed-fields/field_uniqueness_check.rs | 337 ---- .../field_uniqueness_check.stderr | 1734 ----------------- tests/ui/union/unnamed-fields/repr_check.rs | 69 - .../ui/union/unnamed-fields/repr_check.stderr | 152 -- .../restrict_anonymous_structs.rs | 32 - .../restrict_anonymous_structs.stderr | 48 - .../restrict_anonymous_unions.rs | 32 - .../restrict_anonymous_unions.stderr | 48 - .../union/unnamed-fields/restrict_type_hir.rs | 44 - .../unnamed-fields/restrict_type_hir.stderr | 62 - .../unnamed-enum-field-issue-121757.rs | 25 - .../unnamed-enum-field-issue-121757.stderr | 45 - tests/ui/unpretty/expanded-exhaustive.rs | 14 - tests/ui/unpretty/expanded-exhaustive.stdout | 18 - 40 files changed, 30 insertions(+), 3209 deletions(-) delete mode 100644 tests/ui/feature-gates/feature-gate-unnamed_fields.rs delete mode 100644 tests/ui/feature-gates/feature-gate-unnamed_fields.stderr delete mode 100644 tests/ui/union/unnamed-fields/anon-struct-in-enum-issue-121446.rs delete mode 100644 tests/ui/union/unnamed-fields/anon-struct-in-enum-issue-121446.stderr delete mode 100644 tests/ui/union/unnamed-fields/auxiliary/dep.rs delete mode 100644 tests/ui/union/unnamed-fields/field_uniqueness_check.rs delete mode 100644 tests/ui/union/unnamed-fields/field_uniqueness_check.stderr delete mode 100644 tests/ui/union/unnamed-fields/repr_check.rs delete mode 100644 tests/ui/union/unnamed-fields/repr_check.stderr delete mode 100644 tests/ui/union/unnamed-fields/restrict_anonymous_structs.rs delete mode 100644 tests/ui/union/unnamed-fields/restrict_anonymous_structs.stderr delete mode 100644 tests/ui/union/unnamed-fields/restrict_anonymous_unions.rs delete mode 100644 tests/ui/union/unnamed-fields/restrict_anonymous_unions.stderr delete mode 100644 tests/ui/union/unnamed-fields/restrict_type_hir.rs delete mode 100644 tests/ui/union/unnamed-fields/restrict_type_hir.stderr delete mode 100644 tests/ui/union/unnamed-fields/unnamed-enum-field-issue-121757.rs delete mode 100644 tests/ui/union/unnamed-fields/unnamed-enum-field-issue-121757.stderr diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl index c361c35b723..0146a8d9082 100644 --- a/compiler/rustc_ast_passes/messages.ftl +++ b/compiler/rustc_ast_passes/messages.ftl @@ -160,14 +160,6 @@ ast_passes_inherent_cannot_be = inherent impls cannot be {$annotation} .type = inherent impl for this type .only_trait = only trait implementations may be annotated with {$annotation} -ast_passes_invalid_unnamed_field = - unnamed fields are not allowed outside of structs or unions - .label = unnamed field declared here - -ast_passes_invalid_unnamed_field_ty = - unnamed fields can only have struct or union types - .label = not a struct or union - ast_passes_item_invalid_safety = items outside of `unsafe extern {"{ }"}` cannot be declared with `safe` safety qualifier .suggestion = remove safe from this item diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 229d04f8de2..b3d91d881c4 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -255,7 +255,6 @@ impl<'a> AstValidator<'a> { if let Some(ident) = field.ident && ident.name == kw::Underscore { - self.check_unnamed_field_ty(&field.ty, ident.span); self.visit_vis(&field.vis); self.visit_ident(ident); self.visit_ty_common(&field.ty); @@ -294,21 +293,6 @@ impl<'a> AstValidator<'a> { } } - fn check_unnamed_field_ty(&self, ty: &Ty, span: Span) { - if matches!( - &ty.kind, - // We already checked for `kw::Underscore` before calling this function, - // so skip the check - TyKind::AnonStruct(..) | TyKind::AnonUnion(..) - // If the anonymous field contains a Path as type, we can't determine - // if the path is a valid struct or union, so skip the check - | TyKind::Path(..) - ) { - return; - } - self.dcx().emit_err(errors::InvalidUnnamedFieldTy { span, ty_span: ty.span }); - } - fn deny_anon_struct_or_union(&self, ty: &Ty) { let struct_or_union = match &ty.kind { TyKind::AnonStruct(..) => "struct", @@ -318,15 +302,6 @@ impl<'a> AstValidator<'a> { self.dcx().emit_err(errors::AnonStructOrUnionNotAllowed { struct_or_union, span: ty.span }); } - fn deny_unnamed_field(&self, field: &FieldDef) { - if let Some(ident) = field.ident - && ident.name == kw::Underscore - { - self.dcx() - .emit_err(errors::InvalidUnnamedField { span: field.span, ident_span: ident.span }); - } - } - fn check_trait_fn_not_const(&self, constness: Const, parent: &TraitOrTraitImpl) { let Const::Yes(span) = constness else { return; @@ -895,7 +870,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } fn visit_field_def(&mut self, field: &'a FieldDef) { - self.deny_unnamed_field(field); visit::walk_field_def(self, field) } diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index 5cce47ce7bd..07515897c69 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -814,24 +814,6 @@ pub(crate) struct NegativeBoundWithParentheticalNotation { pub span: Span, } -#[derive(Diagnostic)] -#[diag(ast_passes_invalid_unnamed_field_ty)] -pub(crate) struct InvalidUnnamedFieldTy { - #[primary_span] - pub span: Span, - #[label] - pub ty_span: Span, -} - -#[derive(Diagnostic)] -#[diag(ast_passes_invalid_unnamed_field)] -pub(crate) struct InvalidUnnamedField { - #[primary_span] - pub span: Span, - #[label] - pub ident_span: Span, -} - #[derive(Diagnostic)] #[diag(ast_passes_anon_struct_or_union_not_allowed)] pub(crate) struct AnonStructOrUnionNotAllowed { diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 83931a8c1a9..e47f5d43128 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -541,7 +541,6 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { gate_all!(builtin_syntax, "`builtin #` syntax is unstable"); gate_all!(explicit_tail_calls, "`become` expression is experimental"); gate_all!(generic_const_items, "generic const items are experimental"); - gate_all!(unnamed_fields, "unnamed fields are not yet fully implemented"); gate_all!(fn_delegation, "functions delegation is not yet fully implemented"); gate_all!(postfix_match, "postfix match is experimental"); gate_all!(mut_ref, "mutable by-reference bindings are experimental"); diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs index 0cd0963d4e3..276814dd0d9 100644 --- a/compiler/rustc_feature/src/removed.rs +++ b/compiler/rustc_feature/src/removed.rs @@ -216,6 +216,8 @@ declare_features! ( (removed, test_removed_feature, "1.0.0", None, None), /// Allows using items which are missing stability attributes (removed, unmarked_api, "1.0.0", None, None), + /// Allows unnamed fields of struct and union type + (removed, unnamed_fields, "1.74.0", Some(49804)), (removed, unsafe_no_drop_flag, "1.0.0", None, None), /// Allows `union` fields that don't implement `Copy` as long as they don't have any drop glue. (removed, untagged_unions, "1.13.0", Some(55149), diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index c5530097e96..843610a18a1 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -618,8 +618,6 @@ declare_features! ( /// Allows creation of instances of a struct by moving fields that have /// not changed from prior instances of the same struct (RFC #2528) (unstable, type_changing_struct_update, "1.58.0", Some(86555)), - /// Allows unnamed fields of struct and union type - (incomplete, unnamed_fields, "1.74.0", Some(49804)), /// Allows const generic parameters to be defined with types that /// are not `Sized`, e.g. `fn foo() {`. (incomplete, unsized_const_params, "1.82.0", Some(95174)), diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index c73826c489f..b64a400f75e 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -248,8 +248,6 @@ hir_analysis_invalid_union_field = hir_analysis_invalid_union_field_sugg = wrap the field type in `ManuallyDrop<...>` -hir_analysis_invalid_unnamed_field_ty = unnamed fields can only have struct or union types - hir_analysis_late_bound_const_in_apit = `impl Trait` can only mention const parameters from an fn or impl .label = const parameter declared here @@ -535,19 +533,6 @@ hir_analysis_unconstrained_generic_parameter = the {$param_def_kind} `{$param_na hir_analysis_unconstrained_opaque_type = unconstrained opaque type .note = `{$name}` must be used in combination with a concrete type within the same {$what} -hir_analysis_unnamed_fields_repr_field_defined = unnamed field defined here - -hir_analysis_unnamed_fields_repr_field_missing_repr_c = - named type of unnamed field must have `#[repr(C)]` representation - .label = unnamed field defined here - .field_ty_label = `{$field_ty}` defined here - .suggestion = add `#[repr(C)]` to this {$field_adt_kind} - -hir_analysis_unnamed_fields_repr_missing_repr_c = - {$adt_kind} with unnamed fields must have `#[repr(C)]` representation - .label = {$adt_kind} `{$adt_name}` defined here - .suggestion = add `#[repr(C)]` to this {$adt_kind} - hir_analysis_unrecognized_atomic_operation = unrecognized atomic operation function: `{$op}` .label = unrecognized atomic operation diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index d725772a5b3..b9111a5cd39 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -76,7 +76,6 @@ fn check_struct(tcx: TyCtxt<'_>, def_id: LocalDefId) { check_transparent(tcx, def); check_packed(tcx, span, def); - check_unnamed_fields(tcx, def); } fn check_union(tcx: TyCtxt<'_>, def_id: LocalDefId) { @@ -86,61 +85,6 @@ fn check_union(tcx: TyCtxt<'_>, def_id: LocalDefId) { check_transparent(tcx, def); check_union_fields(tcx, span, def_id); check_packed(tcx, span, def); - check_unnamed_fields(tcx, def); -} - -/// Check the representation of adts with unnamed fields. -fn check_unnamed_fields(tcx: TyCtxt<'_>, def: ty::AdtDef<'_>) { - if def.is_enum() { - return; - } - let variant = def.non_enum_variant(); - if !variant.has_unnamed_fields() { - return; - } - if !def.is_anonymous() { - let adt_kind = def.descr(); - let span = tcx.def_span(def.did()); - let unnamed_fields = variant - .fields - .iter() - .filter(|f| f.is_unnamed()) - .map(|f| { - let span = tcx.def_span(f.did); - errors::UnnamedFieldsReprFieldDefined { span } - }) - .collect::>(); - debug_assert_ne!(unnamed_fields.len(), 0, "expect unnamed fields in this adt"); - let adt_name = tcx.item_name(def.did()); - if !def.repr().c() { - tcx.dcx().emit_err(errors::UnnamedFieldsRepr::MissingReprC { - span, - adt_kind, - adt_name, - unnamed_fields, - sugg_span: span.shrink_to_lo(), - }); - } - } - for field in variant.fields.iter().filter(|f| f.is_unnamed()) { - let field_ty = tcx.type_of(field.did).instantiate_identity(); - if let Some(adt) = field_ty.ty_adt_def() - && !adt.is_enum() - { - if !adt.is_anonymous() && !adt.repr().c() { - let field_ty_span = tcx.def_span(adt.did()); - tcx.dcx().emit_err(errors::UnnamedFieldsRepr::FieldMissingReprC { - span: tcx.def_span(field.did), - field_ty_span, - field_ty, - field_adt_kind: adt.descr(), - sugg_span: field_ty_span.shrink_to_lo(), - }); - } - } else { - tcx.dcx().emit_err(errors::InvalidUnnamedFieldTy { span: tcx.def_span(field.did) }); - } - } } /// Check that the fields of the `union` do not need dropping. diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 93b021be245..cfa148d925d 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1007,79 +1007,6 @@ impl<'tcx> FieldUniquenessCheckContext<'tcx> { } } } - - /// Check the uniqueness of fields across adt where there are - /// nested fields imported from an unnamed field. - fn check_field_in_nested_adt(&mut self, adt_def: ty::AdtDef<'_>, unnamed_field_span: Span) { - for field in adt_def.all_fields() { - if field.is_unnamed() { - // Here we don't care about the generic parameters, so `instantiate_identity` is enough. - match self.tcx.type_of(field.did).instantiate_identity().kind() { - ty::Adt(adt_def, _) => { - self.check_field_in_nested_adt(*adt_def, unnamed_field_span); - } - ty_kind => span_bug!( - self.tcx.def_span(field.did), - "Unexpected TyKind in FieldUniquenessCheckContext::check_field_in_nested_adt(): {ty_kind:?}" - ), - } - } else { - self.check_field_decl( - field.ident(self.tcx), - NestedSpan { - span: unnamed_field_span, - nested_field_span: self.tcx.def_span(field.did), - } - .into(), - ); - } - } - } - - /// Check the uniqueness of fields in a struct variant, and recursively - /// check the nested fields if it is an unnamed field with type of an - /// anonymous adt. - fn check_field(&mut self, field: &hir::FieldDef<'_>) { - if field.ident.name != kw::Underscore { - self.check_field_decl(field.ident, field.span.into()); - return; - } - match &field.ty.kind { - hir::TyKind::AnonAdt(item_id) => { - match &self.tcx.hir_node(item_id.hir_id()).expect_item().kind { - hir::ItemKind::Struct(variant_data, ..) - | hir::ItemKind::Union(variant_data, ..) => { - variant_data.fields().iter().for_each(|f| self.check_field(f)); - } - item_kind => span_bug!( - field.ty.span, - "Unexpected ItemKind in FieldUniquenessCheckContext::check_field(): {item_kind:?}" - ), - } - } - hir::TyKind::Path(hir::QPath::Resolved(_, hir::Path { res, .. })) => { - // If this is a direct path to an ADT, we can check it - // If this is a type alias or non-ADT, `check_unnamed_fields` should verify it - if let Some(def_id) = res.opt_def_id() - && let Some(local) = def_id.as_local() - && let Node::Item(item) = self.tcx.hir_node_by_def_id(local) - && item.is_adt() - { - self.check_field_in_nested_adt(self.tcx.adt_def(def_id), field.span); - } - } - // Abort due to errors (there must be an error if an unnamed field - // has any type kind other than an anonymous adt or a named adt) - ty_kind => { - self.tcx.dcx().span_delayed_bug( - field.ty.span, - format!("Unexpected TyKind in FieldUniquenessCheckContext::check_field(): {ty_kind:?}"), - ); - // FIXME: errors during AST validation should abort the compilation before reaching here. - self.tcx.dcx().abort_if_errors(); - } - } - } } fn lower_variant( @@ -1090,20 +1017,13 @@ fn lower_variant( def: &hir::VariantData<'_>, adt_kind: ty::AdtKind, parent_did: LocalDefId, - is_anonymous: bool, ) -> ty::VariantDef { - let mut has_unnamed_fields = false; let mut field_uniqueness_check_ctx = FieldUniquenessCheckContext::new(tcx); let fields = def .fields() .iter() - .inspect(|f| { - has_unnamed_fields |= f.ident.name == kw::Underscore; - // We only check named ADT here because anonymous ADTs are checked inside - // the named ADT in which they are defined. - if !is_anonymous { - field_uniqueness_check_ctx.check_field(f); - } + .inspect(|field| { + field_uniqueness_check_ctx.check_field_decl(field.ident, field.span.into()); }) .map(|f| ty::FieldDef { did: f.def_id.to_def_id(), @@ -1127,7 +1047,6 @@ fn lower_variant( adt_kind == AdtKind::Struct && tcx.has_attr(parent_did, sym::non_exhaustive) || variant_did .is_some_and(|variant_did| tcx.has_attr(variant_did, sym::non_exhaustive)), - has_unnamed_fields, ) } @@ -1138,20 +1057,7 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> { bug!("expected ADT to be an item"); }; - let is_anonymous = item.ident.name == kw::Empty; - let repr = if is_anonymous { - let parent = tcx.local_parent(def_id); - if let Node::Item(item) = tcx.hir_node_by_def_id(parent) - && item.is_struct_or_union() - { - tcx.adt_def(parent).repr() - } else { - tcx.dcx().span_delayed_bug(item.span, "anonymous field inside non struct/union"); - ty::ReprOptions::default() - } - } else { - tcx.repr_options_of_def(def_id) - }; + let repr = tcx.repr_options_of_def(def_id); let (kind, variants) = match &item.kind { ItemKind::Enum(def, _) => { let mut distance_from_explicit = 0; @@ -1175,7 +1081,6 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> { &v.data, AdtKind::Enum, def_id, - is_anonymous, ) }) .collect(); @@ -1195,7 +1100,6 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> { def, adt_kind, def_id, - is_anonymous, )) .collect(); @@ -1203,7 +1107,7 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> { } _ => bug!("{:?} is not an ADT", item.owner_id.def_id), }; - tcx.mk_adt_def(def_id.to_def_id(), kind, variants, repr, is_anonymous) + tcx.mk_adt_def(def_id.to_def_id(), kind, variants, repr) } fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef { diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 4edb68e6199..9099703e812 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -734,13 +734,6 @@ pub(crate) struct InvalidUnionField { pub note: (), } -#[derive(Diagnostic)] -#[diag(hir_analysis_invalid_unnamed_field_ty)] -pub(crate) struct InvalidUnnamedFieldTy { - #[primary_span] - pub span: Span, -} - #[derive(Diagnostic)] #[diag(hir_analysis_return_type_notation_on_non_rpitit)] pub(crate) struct ReturnTypeNotationOnNonRpitit<'tcx> { @@ -1598,41 +1591,6 @@ pub(crate) struct UnconstrainedGenericParameter { pub const_param_note2: bool, } -#[derive(Diagnostic)] -pub(crate) enum UnnamedFieldsRepr<'a> { - #[diag(hir_analysis_unnamed_fields_repr_missing_repr_c)] - MissingReprC { - #[primary_span] - #[label] - span: Span, - adt_kind: &'static str, - adt_name: Symbol, - #[subdiagnostic] - unnamed_fields: Vec, - #[suggestion(code = "#[repr(C)]\n")] - sugg_span: Span, - }, - #[diag(hir_analysis_unnamed_fields_repr_field_missing_repr_c)] - FieldMissingReprC { - #[primary_span] - #[label] - span: Span, - #[label(hir_analysis_field_ty_label)] - field_ty_span: Span, - field_ty: Ty<'a>, - field_adt_kind: &'static str, - #[suggestion(code = "#[repr(C)]\n")] - sugg_span: Span, - }, -} - -#[derive(Subdiagnostic)] -#[note(hir_analysis_unnamed_fields_repr_field_defined)] -pub(crate) struct UnnamedFieldsReprFieldDefined { - #[primary_span] - pub span: Span, -} - #[derive(Diagnostic)] #[diag(hir_analysis_opaque_captures_higher_ranked_lifetime, code = E0657)] pub(crate) struct OpaqueCapturesHigherRankedLifetime { diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index b34ed4640db..ed7be72551b 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -33,7 +33,6 @@ use rustc_span::symbol::{Ident, Symbol, kw, sym}; use rustc_target::abi::{FIRST_VARIANT, FieldIdx}; use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::{self, ObligationCauseCode, ObligationCtxt}; -use smallvec::SmallVec; use tracing::{debug, instrument, trace}; use {rustc_ast as ast, rustc_hir as hir}; @@ -1722,8 +1721,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let ident = tcx.adjust_ident(field.ident, variant.def_id); let field_type = if let Some((i, v_field)) = remaining_fields.remove(&ident) { seen_fields.insert(ident, field.span); - // FIXME: handle nested fields - self.write_field_index(field.hir_id, i, Vec::new()); + self.write_field_index(field.hir_id, i); // We don't look at stability attributes on // struct-like enums (yet...), but it's definitely not @@ -2367,35 +2365,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, base_def: ty::AdtDef<'tcx>, ident: Ident, - nested_fields: &mut SmallVec<[(FieldIdx, &'tcx ty::FieldDef); 1]>, - ) -> bool { + ) -> Option<(FieldIdx, &'tcx ty::FieldDef)> { // No way to find a field in an enum. if base_def.is_enum() { - return false; + return None; } for (field_idx, field) in base_def.non_enum_variant().fields.iter_enumerated() { - if field.is_unnamed() { - // We have an unnamed field, recurse into the nested ADT to find `ident`. - // If we find it there, return immediately, and `nested_fields` will contain the - // correct path. - nested_fields.push((field_idx, field)); - - let field_ty = self.tcx.type_of(field.did).instantiate_identity(); - let adt_def = field_ty.ty_adt_def().expect("expect Adt for unnamed field"); - if self.find_adt_field(adt_def, ident, &mut *nested_fields) { - return true; - } - - nested_fields.pop(); - } else if field.ident(self.tcx).normalize_to_macros_2_0() == ident { + if field.ident(self.tcx).normalize_to_macros_2_0() == ident { // We found the field we wanted. - nested_fields.push((field_idx, field)); - return true; + return Some((field_idx, field)); } } - false + None } // Check field access expressions @@ -2425,34 +2408,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return Ty::new_error(self.tcx(), guar); } - let mut field_path = SmallVec::new(); - if self.find_adt_field(*base_def, ident, &mut field_path) { - let (first_idx, _) = field_path[0]; - let (_, last_field) = field_path.last().unwrap(); - - // Save the index of all fields regardless of their visibility in case - // of error recovery. - let nested_fields = field_path[..] - .array_windows() - .map(|[(_, outer), (inner_idx, _)]| { - let outer_ty = self.field_ty(expr.span, outer, args); - (outer_ty, *inner_idx) - }) - .collect(); - self.write_field_index(expr.hir_id, first_idx, nested_fields); + if let Some((idx, field)) = self.find_adt_field(*base_def, ident) { + self.write_field_index(expr.hir_id, idx); let adjustments = self.adjust_steps(&autoderef); - if last_field.vis.is_accessible_from(def_scope, self.tcx) { + if field.vis.is_accessible_from(def_scope, self.tcx) { self.apply_adjustments(base, adjustments); self.register_predicates(autoderef.into_obligations()); - self.tcx.check_stability( - last_field.did, - Some(expr.hir_id), - expr.span, - None, - ); - return self.field_ty(expr.span, last_field, args); + self.tcx.check_stability(field.did, Some(expr.hir_id), expr.span, None); + return self.field_ty(expr.span, field, args); } // The field is not accessible, fall through to error reporting. @@ -2467,11 +2432,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.apply_adjustments(base, adjustments); self.register_predicates(autoderef.into_obligations()); - self.write_field_index( - expr.hir_id, - FieldIdx::from_usize(index), - Vec::new(), - ); + self.write_field_index(expr.hir_id, FieldIdx::from_usize(index)); return field_ty; } } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 62107877283..cd4c5de2a66 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -165,16 +165,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - pub(crate) fn write_field_index( - &self, - hir_id: HirId, - index: FieldIdx, - nested_fields: Vec<(Ty<'tcx>, FieldIdx)>, - ) { + pub(crate) fn write_field_index(&self, hir_id: HirId, index: FieldIdx) { self.typeck_results.borrow_mut().field_indices_mut().insert(hir_id, index); - if !nested_fields.is_empty() { - self.typeck_results.borrow_mut().nested_fields_mut().insert(hir_id, nested_fields); - } } #[instrument(level = "debug", skip(self))] diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 49c5a7d8a65..fb78da0a86c 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -1513,8 +1513,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { field_map .get(&ident) .map(|(i, f)| { - // FIXME: handle nested fields - self.write_field_index(field.hir_id, *i, Vec::new()); + self.write_field_index(field.hir_id, *i); self.tcx.check_stability(f.did, Some(pat.hir_id), span, None); self.field_ty(span, f, args) }) diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index 3254dddaee9..b193b81f6de 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -588,11 +588,6 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { { self.typeck_results.field_indices_mut().insert(hir_id, index); } - if let Some(nested_fields) = - self.fcx.typeck_results.borrow_mut().nested_fields_mut().remove(hir_id) - { - self.typeck_results.nested_fields_mut().insert(hir_id, nested_fields); - } } #[instrument(skip(self, span), level = "debug")] diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 2157324d5cc..600a9b75097 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1107,8 +1107,6 @@ impl<'a> CrateMetadataRef<'a> { parent_did, None, data.is_non_exhaustive, - // FIXME: unnamed fields in crate metadata is unimplemented yet. - false, ), ) } @@ -1151,7 +1149,6 @@ impl<'a> CrateMetadataRef<'a> { adt_kind, variants.into_iter().map(|(_, variant)| variant).collect(), repr, - false, ) } diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs index 8f89f5c25af..3322a2643d7 100644 --- a/compiler/rustc_middle/src/ty/adt.rs +++ b/compiler/rustc_middle/src/ty/adt.rs @@ -259,12 +259,8 @@ impl AdtDefData { kind: AdtKind, variants: IndexVec, repr: ReprOptions, - is_anonymous: bool, ) -> Self { - debug!( - "AdtDef::new({:?}, {:?}, {:?}, {:?}, {:?})", - did, kind, variants, repr, is_anonymous - ); + debug!("AdtDef::new({:?}, {:?}, {:?}, {:?})", did, kind, variants, repr); let mut flags = AdtFlags::NO_ADT_FLAGS; if kind == AdtKind::Enum && tcx.has_attr(did, sym::non_exhaustive) { @@ -297,9 +293,6 @@ impl AdtDefData { if tcx.is_lang_item(did, LangItem::UnsafeCell) { flags |= AdtFlags::IS_UNSAFE_CELL; } - if is_anonymous { - flags |= AdtFlags::IS_ANONYMOUS; - } AdtDefData { did, variants, flags, repr } } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 2ffb273cb6f..4eaba540e33 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1419,16 +1419,8 @@ impl<'tcx> TyCtxt<'tcx> { kind: AdtKind, variants: IndexVec, repr: ReprOptions, - is_anonymous: bool, ) -> ty::AdtDef<'tcx> { - self.mk_adt_def_from_data(ty::AdtDefData::new( - self, - did, - kind, - variants, - repr, - is_anonymous, - )) + self.mk_adt_def_from_data(ty::AdtDefData::new(self, did, kind, variants, repr)) } /// Allocates a read-only byte or string literal for `mir::interpret`. diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 2b1212a5eb5..33bb5fa5739 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1155,8 +1155,6 @@ bitflags::bitflags! { const NO_VARIANT_FLAGS = 0; /// Indicates whether the field list of this variant is `#[non_exhaustive]`. const IS_FIELD_LIST_NON_EXHAUSTIVE = 1 << 0; - /// Indicates whether this variant has unnamed fields. - const HAS_UNNAMED_FIELDS = 1 << 1; } } rustc_data_structures::external_bitflags_debug! { VariantFlags } @@ -1209,12 +1207,11 @@ impl VariantDef { parent_did: DefId, recover_tainted: Option, is_field_list_non_exhaustive: bool, - has_unnamed_fields: bool, ) -> Self { debug!( "VariantDef::new(name = {:?}, variant_did = {:?}, ctor = {:?}, discr = {:?}, - fields = {:?}, adt_kind = {:?}, parent_did = {:?}, has_unnamed_fields = {:?})", - name, variant_did, ctor, discr, fields, adt_kind, parent_did, has_unnamed_fields, + fields = {:?}, adt_kind = {:?}, parent_did = {:?})", + name, variant_did, ctor, discr, fields, adt_kind, parent_did, ); let mut flags = VariantFlags::NO_VARIANT_FLAGS; @@ -1222,10 +1219,6 @@ impl VariantDef { flags |= VariantFlags::IS_FIELD_LIST_NON_EXHAUSTIVE; } - if has_unnamed_fields { - flags |= VariantFlags::HAS_UNNAMED_FIELDS; - } - VariantDef { def_id: variant_did.unwrap_or(parent_did), ctor, @@ -1243,12 +1236,6 @@ impl VariantDef { self.flags.intersects(VariantFlags::IS_FIELD_LIST_NON_EXHAUSTIVE) } - /// Does this variant contains unnamed fields - #[inline] - pub fn has_unnamed_fields(&self) -> bool { - self.flags.intersects(VariantFlags::HAS_UNNAMED_FIELDS) - } - /// Computes the `Ident` of this variant by looking up the `Span` pub fn ident(&self, tcx: TyCtxt<'_>) -> Ident { Ident::new(self.name, tcx.def_ident_span(self.def_id).unwrap()) @@ -1434,11 +1421,6 @@ impl<'tcx> FieldDef { pub fn ident(&self, tcx: TyCtxt<'_>) -> Ident { Ident::new(self.name, tcx.def_ident_span(self.did).unwrap()) } - - /// Returns whether the field is unnamed - pub fn is_unnamed(&self) -> bool { - self.name == rustc_span::symbol::kw::Underscore - } } #[derive(Debug, PartialEq, Eq)] diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs index 17280c3d047..c01d2120111 100644 --- a/compiler/rustc_middle/src/ty/typeck_results.rs +++ b/compiler/rustc_middle/src/ty/typeck_results.rs @@ -42,12 +42,6 @@ pub struct TypeckResults<'tcx> { /// belongs, but it may not exist if it's a tuple field (`tuple.0`). field_indices: ItemLocalMap, - /// Resolved types and indices for the nested fields' accesses of `obj.field` (expanded - /// to `obj._(1)._(2).field` in THIR). This map only stores the intermediate type - /// of `obj._(1)` and index of `_(1)._(2)`, and the type of `_(1)._(2)`, and the index of - /// `_(2).field`. - nested_fields: ItemLocalMap, FieldIdx)>>, - /// Stores the types for various nodes in the AST. Note that this table /// is not guaranteed to be populated outside inference. See /// typeck::check::fn_ctxt for details. @@ -225,7 +219,6 @@ impl<'tcx> TypeckResults<'tcx> { hir_owner, type_dependent_defs: Default::default(), field_indices: Default::default(), - nested_fields: Default::default(), user_provided_types: Default::default(), user_provided_sigs: Default::default(), node_types: Default::default(), @@ -299,18 +292,6 @@ impl<'tcx> TypeckResults<'tcx> { self.field_indices().get(id).cloned() } - pub fn nested_fields(&self) -> LocalTableInContext<'_, Vec<(Ty<'tcx>, FieldIdx)>> { - LocalTableInContext { hir_owner: self.hir_owner, data: &self.nested_fields } - } - - pub fn nested_fields_mut(&mut self) -> LocalTableInContextMut<'_, Vec<(Ty<'tcx>, FieldIdx)>> { - LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.nested_fields } - } - - pub fn nested_field_tys_and_indices(&self, id: HirId) -> &[(Ty<'tcx>, FieldIdx)] { - self.nested_fields().get(id).map_or(&[], Vec::as_slice) - } - pub fn user_provided_types(&self) -> LocalTableInContext<'_, CanonicalUserType<'tcx>> { LocalTableInContext { hir_owner: self.hir_owner, data: &self.user_provided_types } } diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 2ffad0b4834..044d8045a27 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -807,21 +807,11 @@ impl<'tcx> Cx<'tcx> { }); ExprKind::Loop { body } } - hir::ExprKind::Field(source, ..) => { - let mut kind = ExprKind::Field { - lhs: self.mirror_expr(source), - variant_index: FIRST_VARIANT, - name: self.typeck_results.field_index(expr.hir_id), - }; - let nested_field_tys_and_indices = - self.typeck_results.nested_field_tys_and_indices(expr.hir_id); - for &(ty, idx) in nested_field_tys_and_indices { - let expr = Expr { temp_lifetime, ty, span: source.span, kind }; - let lhs = self.thir.exprs.push(expr); - kind = ExprKind::Field { lhs, variant_index: FIRST_VARIANT, name: idx }; - } - kind - } + hir::ExprKind::Field(source, ..) => ExprKind::Field { + lhs: self.mirror_expr(source), + variant_index: FIRST_VARIANT, + name: self.typeck_results.field_index(expr.hir_id), + }, hir::ExprKind::Cast(source, cast_ty) => { // Check for a user-given type annotation on this `cast` let user_provided_types = self.typeck_results.user_provided_types(); diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 9fc82d84225..13681c00f8e 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -2009,9 +2009,7 @@ impl<'a> Parser<'a> { /// for better diagnostics and suggestions. fn parse_field_ident(&mut self, adt_ty: &str, lo: Span) -> PResult<'a, Ident> { let (ident, is_raw) = self.ident_or_err(true)?; - if ident.name == kw::Underscore { - self.psess.gated_spans.gate(sym::unnamed_fields, lo); - } else if matches!(is_raw, IdentIsRaw::No) && ident.is_reserved() { + if matches!(is_raw, IdentIsRaw::No) && ident.is_reserved() { let snapshot = self.create_snapshot_for_diagnostic(); let err = if self.check_fn_front_matter(false, Case::Sensitive) { let inherited_vis = diff --git a/tests/ui/feature-gates/feature-gate-unnamed_fields.rs b/tests/ui/feature-gates/feature-gate-unnamed_fields.rs deleted file mode 100644 index 302a9bbeb45..00000000000 --- a/tests/ui/feature-gates/feature-gate-unnamed_fields.rs +++ /dev/null @@ -1,29 +0,0 @@ -#[repr(C)] -struct Foo { - foo: u8, - _: union { //~ ERROR unnamed fields are not yet fully implemented [E0658] - //~^ ERROR unnamed fields are not yet fully implemented [E0658] - bar: u8, - baz: u16 - } -} - -#[repr(C)] -union Bar { - foobar: u8, - _: struct { //~ ERROR unnamed fields are not yet fully implemented [E0658] - //~^ ERROR unnamed fields are not yet fully implemented [E0658] - foobaz: u8, - barbaz: u16 - } -} - -#[repr(C)] -struct S; - -#[repr(C)] -struct Baz { - _: S //~ ERROR unnamed fields are not yet fully implemented [E0658] -} - -fn main(){} diff --git a/tests/ui/feature-gates/feature-gate-unnamed_fields.stderr b/tests/ui/feature-gates/feature-gate-unnamed_fields.stderr deleted file mode 100644 index bc9e95bab98..00000000000 --- a/tests/ui/feature-gates/feature-gate-unnamed_fields.stderr +++ /dev/null @@ -1,63 +0,0 @@ -error[E0658]: unnamed fields are not yet fully implemented - --> $DIR/feature-gate-unnamed_fields.rs:4:5 - | -LL | _: union { - | ^ - | - = note: see issue #49804 for more information - = help: add `#![feature(unnamed_fields)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: unnamed fields are not yet fully implemented - --> $DIR/feature-gate-unnamed_fields.rs:4:8 - | -LL | _: union { - | ________^ -LL | | -LL | | bar: u8, -LL | | baz: u16 -LL | | } - | |_____^ - | - = note: see issue #49804 for more information - = help: add `#![feature(unnamed_fields)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: unnamed fields are not yet fully implemented - --> $DIR/feature-gate-unnamed_fields.rs:14:5 - | -LL | _: struct { - | ^ - | - = note: see issue #49804 for more information - = help: add `#![feature(unnamed_fields)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: unnamed fields are not yet fully implemented - --> $DIR/feature-gate-unnamed_fields.rs:14:8 - | -LL | _: struct { - | ________^ -LL | | -LL | | foobaz: u8, -LL | | barbaz: u16 -LL | | } - | |_____^ - | - = note: see issue #49804 for more information - = help: add `#![feature(unnamed_fields)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: unnamed fields are not yet fully implemented - --> $DIR/feature-gate-unnamed_fields.rs:26:5 - | -LL | _: S - | ^ - | - = note: see issue #49804 for more information - = help: add `#![feature(unnamed_fields)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: aborting due to 5 previous errors - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/union/unnamed-fields/anon-struct-in-enum-issue-121446.rs b/tests/ui/union/unnamed-fields/anon-struct-in-enum-issue-121446.rs deleted file mode 100644 index 00f9bfd5cdf..00000000000 --- a/tests/ui/union/unnamed-fields/anon-struct-in-enum-issue-121446.rs +++ /dev/null @@ -1,11 +0,0 @@ -#![crate_type = "lib"] -#![feature(unnamed_fields)] -#![allow(unused, incomplete_features)] - -enum K { - M { - _ : struct { field: u8 }, - //~^ error: unnamed fields are not allowed outside of structs or unions - //~| error: anonymous structs are not allowed outside of unnamed struct or union fields - } -} diff --git a/tests/ui/union/unnamed-fields/anon-struct-in-enum-issue-121446.stderr b/tests/ui/union/unnamed-fields/anon-struct-in-enum-issue-121446.stderr deleted file mode 100644 index 43843141e2e..00000000000 --- a/tests/ui/union/unnamed-fields/anon-struct-in-enum-issue-121446.stderr +++ /dev/null @@ -1,16 +0,0 @@ -error: unnamed fields are not allowed outside of structs or unions - --> $DIR/anon-struct-in-enum-issue-121446.rs:7:9 - | -LL | _ : struct { field: u8 }, - | -^^^^^^^^^^^^^^^^^^^^^^^ - | | - | unnamed field declared here - -error: anonymous structs are not allowed outside of unnamed struct or union fields - --> $DIR/anon-struct-in-enum-issue-121446.rs:7:13 - | -LL | _ : struct { field: u8 }, - | ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here - -error: aborting due to 2 previous errors - diff --git a/tests/ui/union/unnamed-fields/auxiliary/dep.rs b/tests/ui/union/unnamed-fields/auxiliary/dep.rs deleted file mode 100644 index a11f3e18f52..00000000000 --- a/tests/ui/union/unnamed-fields/auxiliary/dep.rs +++ /dev/null @@ -1,18 +0,0 @@ -#[repr(C)] -pub struct GoodStruct(()); - -pub struct BadStruct(()); - -pub enum BadEnum { - A, - B, -} - -#[repr(C)] -pub enum BadEnum2 { - A, - B, -} - -pub type GoodAlias = GoodStruct; -pub type BadAlias = i32; diff --git a/tests/ui/union/unnamed-fields/field_uniqueness_check.rs b/tests/ui/union/unnamed-fields/field_uniqueness_check.rs deleted file mode 100644 index ddb951aa06c..00000000000 --- a/tests/ui/union/unnamed-fields/field_uniqueness_check.rs +++ /dev/null @@ -1,337 +0,0 @@ -#![allow(incomplete_features)] -#![feature(unnamed_fields)] - -#[derive(Clone, Copy)] -#[repr(C)] -struct Foo { - a: u8, -} - -#[derive(Clone, Copy)] -#[repr(C)] -struct Bar { - _: union { - a: u8, - }, -} - - -// duplicated with a normal field -#[derive(Clone, Copy)] -#[repr(C)] -union A { - // referent field - a: u8, - - // normal field - a: u8, //~ ERROR field `a` is already declared [E0124] - // nested field - _: struct { - a: u8, //~ ERROR field `a` is already declared [E0124] - a: u8, //~ ERROR field `a` is already declared [E0124] - }, - // more nested field - _: union { - _: struct { - a: u8, //~ ERROR field `a` is already declared [E0124] - }, - }, - // nested field in a named adt - _: Foo, //~ ERROR field `a` is already declared - _: Bar, //~ ERROR field `a` is already declared - // nested field in a named adt in an anoymous adt - _: struct { - _: Foo, //~ ERROR field `a` is already declared - _: Bar, //~ ERROR field `a` is already declared - }, -} - -// duplicated with a nested field -#[derive(Clone, Copy)] -#[repr(C)] -struct B { - _: union { - // referent field - a: u8, - - // normal field (within the same anonymous adt) - a: u8, //~ ERROR field `a` is already declared [E0124] - // nested field (within the same anonymous adt) - _: struct { - a: u8, //~ ERROR field `a` is already declared [E0124] - }, - // more nested field (within the same anonymous adt) - _: union { - _: struct { - a: u8, //~ ERROR field `a` is already declared [E0124] - }, - }, - // nested field in a named adt (within the same anonymous adt) - _: Foo, //~ ERROR field `a` is already declared - _: Bar, //~ ERROR field `a` is already declared - // nested field in a named adt in an anoymous adt (within the same anonymous adt) - _: struct { - _: Foo, //~ ERROR field `a` is already declared - _: Bar, //~ ERROR field `a` is already declared - }, - }, - - // normal field - a: u8, //~ ERROR field `a` is already declared [E0124] - // nested field - _: struct { - a: u8, //~ ERROR field `a` is already declared [E0124] - }, - // more nested field - _: union { - _: struct { - a: u8, //~ ERROR field `a` is already declared [E0124] - }, - }, - // nested field in a named adt - _: Foo, //~ ERROR field `a` is already declared - _: Bar, //~ ERROR field `a` is already declared - // nested field in a named adt in an anoymous adt - _: struct { - _: Foo, //~ ERROR field `a` is already declared - _: Bar, //~ ERROR field `a` is already declared - }, -} - -// duplicated with a more nested field -#[derive(Clone, Copy)] -#[repr(C)] -union C { - _: struct { - _: union { - // referent field - a: u8, - - // normal field (within the same anonymous adt) - a: u8, //~ ERROR field `a` is already declared [E0124] - // nested field (within the same anonymous adt) - _: struct { - a: u8, //~ ERROR field `a` is already declared [E0124] - }, - // more nested field (within the same anonymous adt) - _: union { - _: struct { - a: u8, //~ ERROR field `a` is already declared [E0124] - }, - }, - // nested field in a named adt (within the same anonymous adt) - _: Foo, //~ ERROR field `a` is already declared - _: Bar, //~ ERROR field `a` is already declared - // nested field in a named adt in an anoymous adt (within the same anonymous adt) - _: struct { - _: Foo, //~ ERROR field `a` is already declared - _: Bar, //~ ERROR field `a` is already declared - }, - }, - - // normal field (within the direct outer anonymous adt) - a: u8, //~ ERROR field `a` is already declared [E0124] - // nested field (within the direct outer anonymous adt) - _: struct { - a: u8, //~ ERROR field `a` is already declared [E0124] - }, - // more nested field (within the direct outer anonymous adt) - _: union { - _: struct { - a: u8, //~ ERROR field `a` is already declared [E0124] - }, - }, - // nested field in a named adt (within the direct outer anonymous adt) - _: Foo, //~ ERROR field `a` is already declared - _: Bar, //~ ERROR field `a` is already declared - // nested field in a named adt in an anoymous adt (within the direct outer anonymous adt) - _: struct { - _: Foo, //~ ERROR field `a` is already declared - _: Bar, //~ ERROR field `a` is already declared - }, - }, - // normal field - a: u8, //~ ERROR field `a` is already declared [E0124] - // nested field - _: union { - a: u8, //~ ERROR field `a` is already declared [E0124] - }, - // more nested field - _: struct { - _: union { - a: u8, //~ ERROR field `a` is already declared [E0124] - }, - }, - // nested field in a named adt - _: Foo, //~ ERROR field `a` is already declared - _: Bar, //~ ERROR field `a` is already declared - // nested field in a named adt in an anoymous adt - _: union { - _: Foo, //~ ERROR field `a` is already declared - _: Bar, //~ ERROR field `a` is already declared - }, -} - -// duplicated with a nested field in a named adt -#[derive(Clone, Copy)] -#[repr(C)] -struct D { - // referent field `a` - _: Foo, - - // normal field - a: u8, //~ ERROR field `a` is already declared - // nested field - _: union { - a: u8, //~ ERROR field `a` is already declared - }, - // more nested field - _: struct { - _: union { - a: u8, //~ ERROR field `a` is already declared - }, - }, - // nested field in another named adt - _: Foo, //~ ERROR field `a` is already declared - _: Bar, //~ ERROR field `a` is already declared - // nested field in a named adt in an anoymous adt - _: union { - _: Foo, //~ ERROR field `a` is already declared - _: Bar, //~ ERROR field `a` is already declared - }, -} - -// duplicated with a nested field in a nested field of a named adt -#[derive(Clone, Copy)] -#[repr(C)] -union D2 { - // referent field `a` - _: Bar, - - // normal field - a: u8, //~ ERROR field `a` is already declared - // nested field - _: union { - a: u8, //~ ERROR field `a` is already declared - }, - // more nested field - _: struct { - _: union { - a: u8, //~ ERROR field `a` is already declared - }, - }, - // nested field in another named adt - _: Foo, //~ ERROR field `a` is already declared - _: Bar, //~ ERROR field `a` is already declared - // nested field in a named adt in an anoymous adt - _: union { - _: Foo, //~ ERROR field `a` is already declared - _: Bar, //~ ERROR field `a` is already declared - }, -} - -// duplicated with a nested field in a named adt in an anonymous adt -#[derive(Clone, Copy)] -#[repr(C)] -struct E { - _: struct { - // referent field `a` - _: Foo, - - // normal field (within the same anonymous adt) - a: u8, //~ ERROR field `a` is already declared - // nested field (within the same anonymous adt) - _: struct { - a: u8, //~ ERROR field `a` is already declared - }, - // more nested field (within the same anonymous adt) - _: union { - _: struct { - a: u8, //~ ERROR field `a` is already declared - }, - }, - // nested field in a named adt (within the same anonymous adt) - _: Foo, //~ ERROR field `a` is already declared - _: Bar, //~ ERROR field `a` is already declared - // nested field in a named adt in an anoymous adt (within the same anonymous adt) - _: struct { - _: Foo, //~ ERROR field `a` is already declared - _: Bar, //~ ERROR field `a` is already declared - }, - }, - - // normal field - a: u8, //~ ERROR field `a` is already declared - // nested field - _: union { - a: u8, //~ ERROR field `a` is already declared - }, - // more nested field - _: struct { - _: union { - a: u8, //~ ERROR field `a` is already declared - }, - }, - // nested field in another named adt - _: Foo, //~ ERROR field `a` is already declared - _: Bar, //~ ERROR field `a` is already declared - // nested field in a named adt in an anoymous adt - _: union { - _: Foo, //~ ERROR field `a` is already declared - _: Bar, //~ ERROR field `a` is already declared - }, -} - -// duplicated with a nested field in a named adt in an anonymous adt -#[repr(C)] -#[derive(Clone, Copy)] -union E2 { - _: struct { - // referent field `a` - _: Bar, - - // normal field (within the same anonymous adt) - a: u8, //~ ERROR field `a` is already declared - // nested field (within the same anonymous adt) - _: struct { - a: u8, //~ ERROR field `a` is already declared - }, - // more nested field (within the same anonymous adt) - _: union { - _: struct { - a: u8, //~ ERROR field `a` is already declared - }, - }, - // nested field in a named adt (within the same anonymous adt) - _: Foo, //~ ERROR field `a` is already declared - _: Bar, //~ ERROR field `a` is already declared - // nested field in a named adt in an anoymous adt (within the same anonymous adt) - _: struct { - _: Foo, //~ ERROR field `a` is already declared - _: Bar, //~ ERROR field `a` is already declared - }, - }, - - // normal field - a: u8, //~ ERROR field `a` is already declared - // nested field - _: union { - a: u8, //~ ERROR field `a` is already declared - }, - // more nested field - _: struct { - _: union { - a: u8, //~ ERROR field `a` is already declared - }, - }, - // nested field in another named adt - _: Foo, //~ ERROR field `a` is already declared - _: Bar, //~ ERROR field `a` is already declared - // nested field in a named adt in an anoymous adt - _: union { - _: Foo, //~ ERROR field `a` is already declared - _: Bar, //~ ERROR field `a` is already declared - }, -} - -fn main() {} diff --git a/tests/ui/union/unnamed-fields/field_uniqueness_check.stderr b/tests/ui/union/unnamed-fields/field_uniqueness_check.stderr deleted file mode 100644 index 11978386843..00000000000 --- a/tests/ui/union/unnamed-fields/field_uniqueness_check.stderr +++ /dev/null @@ -1,1734 +0,0 @@ -error[E0124]: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:27:5 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | a: u8, - | ^^^^^ field already declared - -error[E0124]: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:30:9 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | a: u8, - | ^^^^^ field already declared - -error[E0124]: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:31:9 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | a: u8, - | ^^^^^ field already declared - -error[E0124]: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:36:13 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | a: u8, - | ^^^^^ field already declared - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:40:5 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | _: Foo, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:40:5 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:41:5 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | _: Bar, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:41:5 - | -LL | _: Bar, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:44:9 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | _: Foo, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:44:9 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:45:9 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | _: Bar, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:45:9 - | -LL | _: Bar, - | ^^^^^^ - -error[E0124]: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:58:9 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | a: u8, - | ^^^^^ field already declared - -error[E0124]: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:61:13 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | a: u8, - | ^^^^^ field already declared - -error[E0124]: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:66:17 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | a: u8, - | ^^^^^ field already declared - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:70:9 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | _: Foo, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:70:9 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:71:9 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | _: Bar, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:71:9 - | -LL | _: Bar, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:74:13 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | _: Foo, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:74:13 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:75:13 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | _: Bar, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:75:13 - | -LL | _: Bar, - | ^^^^^^ - -error[E0124]: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:80:5 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | a: u8, - | ^^^^^ field already declared - -error[E0124]: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:83:9 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | a: u8, - | ^^^^^ field already declared - -error[E0124]: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:88:13 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | a: u8, - | ^^^^^ field already declared - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:92:5 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | _: Foo, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:92:5 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:93:5 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | _: Bar, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:93:5 - | -LL | _: Bar, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:96:9 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | _: Foo, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:96:9 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:97:9 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | _: Bar, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:97:9 - | -LL | _: Bar, - | ^^^^^^ - -error[E0124]: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:111:13 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | a: u8, - | ^^^^^ field already declared - -error[E0124]: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:114:17 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | a: u8, - | ^^^^^ field already declared - -error[E0124]: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:119:21 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | a: u8, - | ^^^^^ field already declared - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:123:13 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | _: Foo, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:123:13 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:124:13 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | _: Bar, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:124:13 - | -LL | _: Bar, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:127:17 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | _: Foo, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:127:17 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:128:17 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | _: Bar, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:128:17 - | -LL | _: Bar, - | ^^^^^^ - -error[E0124]: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:133:9 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | a: u8, - | ^^^^^ field already declared - -error[E0124]: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:136:13 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | a: u8, - | ^^^^^ field already declared - -error[E0124]: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:141:17 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | a: u8, - | ^^^^^ field already declared - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:145:9 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | _: Foo, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:145:9 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:146:9 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | _: Bar, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:146:9 - | -LL | _: Bar, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:149:13 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | _: Foo, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:149:13 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:150:13 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | _: Bar, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:150:13 - | -LL | _: Bar, - | ^^^^^^ - -error[E0124]: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:154:5 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | a: u8, - | ^^^^^ field already declared - -error[E0124]: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:157:9 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | a: u8, - | ^^^^^ field already declared - -error[E0124]: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:162:13 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | a: u8, - | ^^^^^ field already declared - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:166:5 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | _: Foo, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:166:5 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:167:5 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | _: Bar, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:167:5 - | -LL | _: Bar, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:170:9 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | _: Foo, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:170:9 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:171:9 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | _: Bar, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:171:9 - | -LL | _: Bar, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:183:5 - | -LL | _: Foo, - | ------ `a` first declared here in this unnamed field -... -LL | a: u8, - | ^^^^^ field already declared - | -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:180:5 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:186:9 - | -LL | _: Foo, - | ------ `a` first declared here in this unnamed field -... -LL | a: u8, - | ^^^^^ field already declared - | -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:180:5 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:191:13 - | -LL | _: Foo, - | ------ `a` first declared here in this unnamed field -... -LL | a: u8, - | ^^^^^ field already declared - | -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:180:5 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:195:5 - | -LL | _: Foo, - | ------ `a` first declared here in this unnamed field -... -LL | _: Foo, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:195:5 - | -LL | _: Foo, - | ^^^^^^ -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:180:5 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:196:5 - | -LL | _: Foo, - | ------ `a` first declared here in this unnamed field -... -LL | _: Bar, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:196:5 - | -LL | _: Bar, - | ^^^^^^ -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:180:5 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:199:9 - | -LL | _: Foo, - | ------ `a` first declared here in this unnamed field -... -LL | _: Foo, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:199:9 - | -LL | _: Foo, - | ^^^^^^ -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:180:5 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:200:9 - | -LL | _: Foo, - | ------ `a` first declared here in this unnamed field -... -LL | _: Bar, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:200:9 - | -LL | _: Bar, - | ^^^^^^ -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:180:5 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:212:5 - | -LL | _: Bar, - | ------ `a` first declared here in this unnamed field -... -LL | a: u8, - | ^^^^^ field already declared - | -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:209:5 - | -LL | _: Bar, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:215:9 - | -LL | _: Bar, - | ------ `a` first declared here in this unnamed field -... -LL | a: u8, - | ^^^^^ field already declared - | -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:209:5 - | -LL | _: Bar, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:220:13 - | -LL | _: Bar, - | ------ `a` first declared here in this unnamed field -... -LL | a: u8, - | ^^^^^ field already declared - | -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:209:5 - | -LL | _: Bar, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:224:5 - | -LL | _: Bar, - | ------ `a` first declared here in this unnamed field -... -LL | _: Foo, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:224:5 - | -LL | _: Foo, - | ^^^^^^ -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:209:5 - | -LL | _: Bar, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:225:5 - | -LL | _: Bar, - | ------ `a` first declared here in this unnamed field -... -LL | _: Bar, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:225:5 - | -LL | _: Bar, - | ^^^^^^ -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:209:5 - | -LL | _: Bar, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:228:9 - | -LL | _: Bar, - | ------ `a` first declared here in this unnamed field -... -LL | _: Foo, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:228:9 - | -LL | _: Foo, - | ^^^^^^ -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:209:5 - | -LL | _: Bar, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:229:9 - | -LL | _: Bar, - | ------ `a` first declared here in this unnamed field -... -LL | _: Bar, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:229:9 - | -LL | _: Bar, - | ^^^^^^ -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:209:5 - | -LL | _: Bar, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:242:9 - | -LL | _: Foo, - | ------ `a` first declared here in this unnamed field -... -LL | a: u8, - | ^^^^^ field already declared - | -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:239:9 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:245:13 - | -LL | _: Foo, - | ------ `a` first declared here in this unnamed field -... -LL | a: u8, - | ^^^^^ field already declared - | -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:239:9 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:250:17 - | -LL | _: Foo, - | ------ `a` first declared here in this unnamed field -... -LL | a: u8, - | ^^^^^ field already declared - | -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:239:9 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:254:9 - | -LL | _: Foo, - | ------ `a` first declared here in this unnamed field -... -LL | _: Foo, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:254:9 - | -LL | _: Foo, - | ^^^^^^ -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:239:9 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:255:9 - | -LL | _: Foo, - | ------ `a` first declared here in this unnamed field -... -LL | _: Bar, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:255:9 - | -LL | _: Bar, - | ^^^^^^ -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:239:9 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:258:13 - | -LL | _: Foo, - | ------ `a` first declared here in this unnamed field -... -LL | _: Foo, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:258:13 - | -LL | _: Foo, - | ^^^^^^ -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:239:9 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:259:13 - | -LL | _: Foo, - | ------ `a` first declared here in this unnamed field -... -LL | _: Bar, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:259:13 - | -LL | _: Bar, - | ^^^^^^ -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:239:9 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:264:5 - | -LL | _: Foo, - | ------ `a` first declared here in this unnamed field -... -LL | a: u8, - | ^^^^^ field already declared - | -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:239:9 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:267:9 - | -LL | _: Foo, - | ------ `a` first declared here in this unnamed field -... -LL | a: u8, - | ^^^^^ field already declared - | -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:239:9 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:272:13 - | -LL | _: Foo, - | ------ `a` first declared here in this unnamed field -... -LL | a: u8, - | ^^^^^ field already declared - | -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:239:9 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:276:5 - | -LL | _: Foo, - | ------ `a` first declared here in this unnamed field -... -LL | _: Foo, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:276:5 - | -LL | _: Foo, - | ^^^^^^ -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:239:9 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:277:5 - | -LL | _: Foo, - | ------ `a` first declared here in this unnamed field -... -LL | _: Bar, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:277:5 - | -LL | _: Bar, - | ^^^^^^ -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:239:9 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:280:9 - | -LL | _: Foo, - | ------ `a` first declared here in this unnamed field -... -LL | _: Foo, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:280:9 - | -LL | _: Foo, - | ^^^^^^ -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:239:9 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:281:9 - | -LL | _: Foo, - | ------ `a` first declared here in this unnamed field -... -LL | _: Bar, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:281:9 - | -LL | _: Bar, - | ^^^^^^ -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:239:9 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:294:9 - | -LL | _: Bar, - | ------ `a` first declared here in this unnamed field -... -LL | a: u8, - | ^^^^^ field already declared - | -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:291:9 - | -LL | _: Bar, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:297:13 - | -LL | _: Bar, - | ------ `a` first declared here in this unnamed field -... -LL | a: u8, - | ^^^^^ field already declared - | -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:291:9 - | -LL | _: Bar, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:302:17 - | -LL | _: Bar, - | ------ `a` first declared here in this unnamed field -... -LL | a: u8, - | ^^^^^ field already declared - | -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:291:9 - | -LL | _: Bar, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:306:9 - | -LL | _: Bar, - | ------ `a` first declared here in this unnamed field -... -LL | _: Foo, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:306:9 - | -LL | _: Foo, - | ^^^^^^ -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:291:9 - | -LL | _: Bar, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:307:9 - | -LL | _: Bar, - | ------ `a` first declared here in this unnamed field -... -LL | _: Bar, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:307:9 - | -LL | _: Bar, - | ^^^^^^ -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:291:9 - | -LL | _: Bar, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:310:13 - | -LL | _: Bar, - | ------ `a` first declared here in this unnamed field -... -LL | _: Foo, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:310:13 - | -LL | _: Foo, - | ^^^^^^ -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:291:9 - | -LL | _: Bar, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:311:13 - | -LL | _: Bar, - | ------ `a` first declared here in this unnamed field -... -LL | _: Bar, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:311:13 - | -LL | _: Bar, - | ^^^^^^ -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:291:9 - | -LL | _: Bar, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:316:5 - | -LL | _: Bar, - | ------ `a` first declared here in this unnamed field -... -LL | a: u8, - | ^^^^^ field already declared - | -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:291:9 - | -LL | _: Bar, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:319:9 - | -LL | _: Bar, - | ------ `a` first declared here in this unnamed field -... -LL | a: u8, - | ^^^^^ field already declared - | -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:291:9 - | -LL | _: Bar, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:324:13 - | -LL | _: Bar, - | ------ `a` first declared here in this unnamed field -... -LL | a: u8, - | ^^^^^ field already declared - | -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:291:9 - | -LL | _: Bar, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:328:5 - | -LL | _: Bar, - | ------ `a` first declared here in this unnamed field -... -LL | _: Foo, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:328:5 - | -LL | _: Foo, - | ^^^^^^ -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:291:9 - | -LL | _: Bar, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:329:5 - | -LL | _: Bar, - | ------ `a` first declared here in this unnamed field -... -LL | _: Bar, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:329:5 - | -LL | _: Bar, - | ^^^^^^ -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:291:9 - | -LL | _: Bar, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:332:9 - | -LL | _: Bar, - | ------ `a` first declared here in this unnamed field -... -LL | _: Foo, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:332:9 - | -LL | _: Foo, - | ^^^^^^ -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:291:9 - | -LL | _: Bar, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:333:9 - | -LL | _: Bar, - | ------ `a` first declared here in this unnamed field -... -LL | _: Bar, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:333:9 - | -LL | _: Bar, - | ^^^^^^ -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:291:9 - | -LL | _: Bar, - | ^^^^^^ - -error: aborting due to 85 previous errors - -For more information about this error, try `rustc --explain E0124`. diff --git a/tests/ui/union/unnamed-fields/repr_check.rs b/tests/ui/union/unnamed-fields/repr_check.rs deleted file mode 100644 index b50b54b20af..00000000000 --- a/tests/ui/union/unnamed-fields/repr_check.rs +++ /dev/null @@ -1,69 +0,0 @@ -#![allow(incomplete_features)] -#![feature(unnamed_fields)] - -struct A { //~ ERROR struct with unnamed fields must have `#[repr(C)]` representation - //~^ NOTE struct `A` defined here - _: struct { //~ NOTE unnamed field defined here - a: i32, - }, - _: struct { //~ NOTE unnamed field defined here - _: struct { - b: i32, - }, - }, -} - -union B { //~ ERROR union with unnamed fields must have `#[repr(C)]` representation - //~^ NOTE union `B` defined here - _: union { //~ NOTE unnamed field defined here - a: i32, - }, - _: union { //~ NOTE unnamed field defined here - _: union { - b: i32, - }, - }, -} - -#[derive(Clone, Copy)] -#[repr(C)] -struct Foo {} - -#[derive(Clone, Copy)] -struct Bar {} -//~^ `Bar` defined here -//~| `Bar` defined here -//~| `Bar` defined here -//~| `Bar` defined here - -struct C { //~ ERROR struct with unnamed fields must have `#[repr(C)]` representation - //~^ NOTE struct `C` defined here - _: Foo, //~ NOTE unnamed field defined here -} - -union D { //~ ERROR union with unnamed fields must have `#[repr(C)]` representation - //~^ NOTE union `D` defined here - _: Foo, //~ NOTE unnamed field defined here -} - -#[repr(C)] -struct E { - _: Bar, //~ ERROR named type of unnamed field must have `#[repr(C)]` representation - //~^ NOTE unnamed field defined here - _: struct { - _: Bar, //~ ERROR named type of unnamed field must have `#[repr(C)]` representation - //~^ NOTE unnamed field defined here - }, -} - -#[repr(C)] -union F { - _: Bar, //~ ERROR named type of unnamed field must have `#[repr(C)]` representation - //~^ NOTE unnamed field defined here - _: union { - _: Bar, //~ ERROR named type of unnamed field must have `#[repr(C)]` representation - //~^ NOTE unnamed field defined here - }, -} - -fn main() {} diff --git a/tests/ui/union/unnamed-fields/repr_check.stderr b/tests/ui/union/unnamed-fields/repr_check.stderr deleted file mode 100644 index 324968b1264..00000000000 --- a/tests/ui/union/unnamed-fields/repr_check.stderr +++ /dev/null @@ -1,152 +0,0 @@ -error: struct with unnamed fields must have `#[repr(C)]` representation - --> $DIR/repr_check.rs:4:1 - | -LL | struct A { - | ^^^^^^^^ struct `A` defined here - | -note: unnamed field defined here - --> $DIR/repr_check.rs:6:5 - | -LL | / _: struct { -LL | | a: i32, -LL | | }, - | |_____^ -note: unnamed field defined here - --> $DIR/repr_check.rs:9:5 - | -LL | / _: struct { -LL | | _: struct { -LL | | b: i32, -LL | | }, -LL | | }, - | |_____^ -help: add `#[repr(C)]` to this struct - | -LL + #[repr(C)] -LL | struct A { - | - -error: union with unnamed fields must have `#[repr(C)]` representation - --> $DIR/repr_check.rs:16:1 - | -LL | union B { - | ^^^^^^^ union `B` defined here - | -note: unnamed field defined here - --> $DIR/repr_check.rs:18:5 - | -LL | / _: union { -LL | | a: i32, -LL | | }, - | |_____^ -note: unnamed field defined here - --> $DIR/repr_check.rs:21:5 - | -LL | / _: union { -LL | | _: union { -LL | | b: i32, -LL | | }, -LL | | }, - | |_____^ -help: add `#[repr(C)]` to this union - | -LL + #[repr(C)] -LL | union B { - | - -error: struct with unnamed fields must have `#[repr(C)]` representation - --> $DIR/repr_check.rs:39:1 - | -LL | struct C { - | ^^^^^^^^ struct `C` defined here - | -note: unnamed field defined here - --> $DIR/repr_check.rs:41:5 - | -LL | _: Foo, - | ^^^^^^ -help: add `#[repr(C)]` to this struct - | -LL + #[repr(C)] -LL | struct C { - | - -error: union with unnamed fields must have `#[repr(C)]` representation - --> $DIR/repr_check.rs:44:1 - | -LL | union D { - | ^^^^^^^ union `D` defined here - | -note: unnamed field defined here - --> $DIR/repr_check.rs:46:5 - | -LL | _: Foo, - | ^^^^^^ -help: add `#[repr(C)]` to this union - | -LL + #[repr(C)] -LL | union D { - | - -error: named type of unnamed field must have `#[repr(C)]` representation - --> $DIR/repr_check.rs:51:5 - | -LL | struct Bar {} - | ---------- `Bar` defined here -... -LL | _: Bar, - | ^^^^^^ unnamed field defined here - | -help: add `#[repr(C)]` to this struct - | -LL + #[repr(C)] -LL | struct Bar {} - | - -error: named type of unnamed field must have `#[repr(C)]` representation - --> $DIR/repr_check.rs:54:9 - | -LL | struct Bar {} - | ---------- `Bar` defined here -... -LL | _: Bar, - | ^^^^^^ unnamed field defined here - | -help: add `#[repr(C)]` to this struct - | -LL + #[repr(C)] -LL | struct Bar {} - | - -error: named type of unnamed field must have `#[repr(C)]` representation - --> $DIR/repr_check.rs:61:5 - | -LL | struct Bar {} - | ---------- `Bar` defined here -... -LL | _: Bar, - | ^^^^^^ unnamed field defined here - | -help: add `#[repr(C)]` to this struct - | -LL + #[repr(C)] -LL | struct Bar {} - | - -error: named type of unnamed field must have `#[repr(C)]` representation - --> $DIR/repr_check.rs:64:9 - | -LL | struct Bar {} - | ---------- `Bar` defined here -... -LL | _: Bar, - | ^^^^^^ unnamed field defined here - | -help: add `#[repr(C)]` to this struct - | -LL + #[repr(C)] -LL | struct Bar {} - | - -error: aborting due to 8 previous errors - diff --git a/tests/ui/union/unnamed-fields/restrict_anonymous_structs.rs b/tests/ui/union/unnamed-fields/restrict_anonymous_structs.rs deleted file mode 100644 index 03545ed7b18..00000000000 --- a/tests/ui/union/unnamed-fields/restrict_anonymous_structs.rs +++ /dev/null @@ -1,32 +0,0 @@ -#![allow(incomplete_features)] -#![feature(unnamed_fields)] - -struct F { - field1: struct { field2: u8 }, //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields - _: struct { field3: u8 }, -} - -struct G { - _: (u8, u8), //~ ERROR unnamed fields can only have struct or union types -} - -union H { - field1: struct { field2: u8 }, //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields - _: struct { field3: u8 }, -} - -union I { - _: (u8, u8), //~ ERROR unnamed fields can only have struct or union types -} - -enum K { - M { - _ : struct { field: u8 }, //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields - //~^ ERROR unnamed fields are not allowed outside of structs or unions - }, - N { - _ : u8, //~ ERROR unnamed fields are not allowed outside of structs or unions - } -} - -fn main() {} diff --git a/tests/ui/union/unnamed-fields/restrict_anonymous_structs.stderr b/tests/ui/union/unnamed-fields/restrict_anonymous_structs.stderr deleted file mode 100644 index 3b3890af771..00000000000 --- a/tests/ui/union/unnamed-fields/restrict_anonymous_structs.stderr +++ /dev/null @@ -1,48 +0,0 @@ -error: anonymous structs are not allowed outside of unnamed struct or union fields - --> $DIR/restrict_anonymous_structs.rs:5:13 - | -LL | field1: struct { field2: u8 }, - | ^^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here - -error: unnamed fields can only have struct or union types - --> $DIR/restrict_anonymous_structs.rs:10:5 - | -LL | _: (u8, u8), - | ^ -------- not a struct or union - -error: anonymous structs are not allowed outside of unnamed struct or union fields - --> $DIR/restrict_anonymous_structs.rs:14:13 - | -LL | field1: struct { field2: u8 }, - | ^^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here - -error: unnamed fields can only have struct or union types - --> $DIR/restrict_anonymous_structs.rs:19:5 - | -LL | _: (u8, u8), - | ^ -------- not a struct or union - -error: unnamed fields are not allowed outside of structs or unions - --> $DIR/restrict_anonymous_structs.rs:24:9 - | -LL | _ : struct { field: u8 }, - | -^^^^^^^^^^^^^^^^^^^^^^^ - | | - | unnamed field declared here - -error: anonymous structs are not allowed outside of unnamed struct or union fields - --> $DIR/restrict_anonymous_structs.rs:24:13 - | -LL | _ : struct { field: u8 }, - | ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here - -error: unnamed fields are not allowed outside of structs or unions - --> $DIR/restrict_anonymous_structs.rs:28:9 - | -LL | _ : u8, - | -^^^^^ - | | - | unnamed field declared here - -error: aborting due to 7 previous errors - diff --git a/tests/ui/union/unnamed-fields/restrict_anonymous_unions.rs b/tests/ui/union/unnamed-fields/restrict_anonymous_unions.rs deleted file mode 100644 index 9ffe71b28c2..00000000000 --- a/tests/ui/union/unnamed-fields/restrict_anonymous_unions.rs +++ /dev/null @@ -1,32 +0,0 @@ -#![allow(incomplete_features)] -#![feature(unnamed_fields)] - -struct F { - field1: union { field2: u8 }, //~ ERROR anonymous unions are not allowed outside of unnamed struct or union fields - _: union { field3: u8 }, -} - -struct G { - _: (u8, u8), //~ ERROR unnamed fields can only have struct or union types -} - -union H { - field1: union { field2: u8 }, //~ ERROR anonymous unions are not allowed outside of unnamed struct or union fields - _: union { field3: u8 }, -} - -union I { - _: (u8, u8), //~ ERROR unnamed fields can only have struct or union types -} - -enum K { - M { - _ : union { field: u8 }, //~ ERROR anonymous unions are not allowed outside of unnamed struct or union fields - //~^ ERROR unnamed fields are not allowed outside of structs or unions - }, - N { - _ : u8, //~ ERROR unnamed fields are not allowed outside of structs or unions - } -} - -fn main() {} diff --git a/tests/ui/union/unnamed-fields/restrict_anonymous_unions.stderr b/tests/ui/union/unnamed-fields/restrict_anonymous_unions.stderr deleted file mode 100644 index f8679aad2d7..00000000000 --- a/tests/ui/union/unnamed-fields/restrict_anonymous_unions.stderr +++ /dev/null @@ -1,48 +0,0 @@ -error: anonymous unions are not allowed outside of unnamed struct or union fields - --> $DIR/restrict_anonymous_unions.rs:5:13 - | -LL | field1: union { field2: u8 }, - | ^^^^^^^^^^^^^^^^^^^^ anonymous union declared here - -error: unnamed fields can only have struct or union types - --> $DIR/restrict_anonymous_unions.rs:10:5 - | -LL | _: (u8, u8), - | ^ -------- not a struct or union - -error: anonymous unions are not allowed outside of unnamed struct or union fields - --> $DIR/restrict_anonymous_unions.rs:14:13 - | -LL | field1: union { field2: u8 }, - | ^^^^^^^^^^^^^^^^^^^^ anonymous union declared here - -error: unnamed fields can only have struct or union types - --> $DIR/restrict_anonymous_unions.rs:19:5 - | -LL | _: (u8, u8), - | ^ -------- not a struct or union - -error: unnamed fields are not allowed outside of structs or unions - --> $DIR/restrict_anonymous_unions.rs:24:9 - | -LL | _ : union { field: u8 }, - | -^^^^^^^^^^^^^^^^^^^^^^ - | | - | unnamed field declared here - -error: anonymous unions are not allowed outside of unnamed struct or union fields - --> $DIR/restrict_anonymous_unions.rs:24:13 - | -LL | _ : union { field: u8 }, - | ^^^^^^^^^^^^^^^^^^^ anonymous union declared here - -error: unnamed fields are not allowed outside of structs or unions - --> $DIR/restrict_anonymous_unions.rs:28:9 - | -LL | _ : u8, - | -^^^^^ - | | - | unnamed field declared here - -error: aborting due to 7 previous errors - diff --git a/tests/ui/union/unnamed-fields/restrict_type_hir.rs b/tests/ui/union/unnamed-fields/restrict_type_hir.rs deleted file mode 100644 index 80e4608be82..00000000000 --- a/tests/ui/union/unnamed-fields/restrict_type_hir.rs +++ /dev/null @@ -1,44 +0,0 @@ -//@ aux-build:dep.rs - -// test for #121151 - -#![allow(incomplete_features)] -#![feature(unnamed_fields)] - -extern crate dep; - -#[repr(C)] -struct A { - a: u8, -} - -enum BadEnum { - A, - B, -} - -#[repr(C)] -enum BadEnum2 { - A, - B, -} - -type MyStruct = A; -type MyI32 = i32; - -#[repr(C)] -struct L { - _: i32, //~ ERROR unnamed fields can only have struct or union types - _: MyI32, //~ ERROR unnamed fields can only have struct or union types - _: BadEnum, //~ ERROR unnamed fields can only have struct or union types - _: BadEnum2, //~ ERROR unnamed fields can only have struct or union types - _: MyStruct, - _: dep::BadStruct, //~ ERROR named type of unnamed field must have `#[repr(C)]` representation - _: dep::BadEnum, //~ ERROR unnamed fields can only have struct or union types - _: dep::BadEnum2, //~ ERROR unnamed fields can only have struct or union types - _: dep::BadAlias, //~ ERROR unnamed fields can only have struct or union types - _: dep::GoodAlias, - _: dep::GoodStruct, -} - -fn main() {} diff --git a/tests/ui/union/unnamed-fields/restrict_type_hir.stderr b/tests/ui/union/unnamed-fields/restrict_type_hir.stderr deleted file mode 100644 index 3e80d7fbf5c..00000000000 --- a/tests/ui/union/unnamed-fields/restrict_type_hir.stderr +++ /dev/null @@ -1,62 +0,0 @@ -error: unnamed fields can only have struct or union types - --> $DIR/restrict_type_hir.rs:31:5 - | -LL | _: i32, - | ^^^^^^ - -error: unnamed fields can only have struct or union types - --> $DIR/restrict_type_hir.rs:32:5 - | -LL | _: MyI32, - | ^^^^^^^^ - -error: unnamed fields can only have struct or union types - --> $DIR/restrict_type_hir.rs:33:5 - | -LL | _: BadEnum, - | ^^^^^^^^^^ - -error: unnamed fields can only have struct or union types - --> $DIR/restrict_type_hir.rs:34:5 - | -LL | _: BadEnum2, - | ^^^^^^^^^^^ - -error: named type of unnamed field must have `#[repr(C)]` representation - --> $DIR/restrict_type_hir.rs:36:5 - | -LL | _: dep::BadStruct, - | ^^^^^^^^^^^^^^^^^ unnamed field defined here - | - ::: $DIR/auxiliary/dep.rs:4:1 - | -LL | pub struct BadStruct(()); - | -------------------- `BadStruct` defined here - | -help: add `#[repr(C)]` to this struct - --> $DIR/auxiliary/dep.rs:4:1 - | -LL + #[repr(C)] -LL | pub struct BadStruct(()); - | - -error: unnamed fields can only have struct or union types - --> $DIR/restrict_type_hir.rs:37:5 - | -LL | _: dep::BadEnum, - | ^^^^^^^^^^^^^^^ - -error: unnamed fields can only have struct or union types - --> $DIR/restrict_type_hir.rs:38:5 - | -LL | _: dep::BadEnum2, - | ^^^^^^^^^^^^^^^^ - -error: unnamed fields can only have struct or union types - --> $DIR/restrict_type_hir.rs:39:5 - | -LL | _: dep::BadAlias, - | ^^^^^^^^^^^^^^^^ - -error: aborting due to 8 previous errors - diff --git a/tests/ui/union/unnamed-fields/unnamed-enum-field-issue-121757.rs b/tests/ui/union/unnamed-fields/unnamed-enum-field-issue-121757.rs deleted file mode 100644 index 5d15ec4cffd..00000000000 --- a/tests/ui/union/unnamed-fields/unnamed-enum-field-issue-121757.rs +++ /dev/null @@ -1,25 +0,0 @@ -type NodeId = u32; -struct Type<'a>(std::marker::PhantomData::<&'a ()>); - -type Ast<'ast> = &'ast AstStructure<'ast>; - -struct AstStructure<'ast> { -//~^ ERROR struct with unnamed fields must have `#[repr(C)]` representation - id: NodeId, - _: AstKind<'ast> -//~^ ERROR unnamed fields are not yet fully implemented [E0658] -//~^^ ERROR unnamed fields can only have struct or union types -} - -enum AstKind<'ast> { - ExprInt, - ExprLambda(Ast<'ast>), -} - -fn compute_types<'tcx,'ast>(ast: Ast<'ast>) -> Type<'tcx> -{ - match ast.kind {} -//~^ ERROR no field `kind` on type `&'ast AstStructure<'ast>` [E0609] -} - -fn main() {} diff --git a/tests/ui/union/unnamed-fields/unnamed-enum-field-issue-121757.stderr b/tests/ui/union/unnamed-fields/unnamed-enum-field-issue-121757.stderr deleted file mode 100644 index 4ea910202de..00000000000 --- a/tests/ui/union/unnamed-fields/unnamed-enum-field-issue-121757.stderr +++ /dev/null @@ -1,45 +0,0 @@ -error[E0658]: unnamed fields are not yet fully implemented - --> $DIR/unnamed-enum-field-issue-121757.rs:9:5 - | -LL | _: AstKind<'ast> - | ^ - | - = note: see issue #49804 for more information - = help: add `#![feature(unnamed_fields)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: struct with unnamed fields must have `#[repr(C)]` representation - --> $DIR/unnamed-enum-field-issue-121757.rs:6:1 - | -LL | struct AstStructure<'ast> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^ struct `AstStructure` defined here - | -note: unnamed field defined here - --> $DIR/unnamed-enum-field-issue-121757.rs:9:5 - | -LL | _: AstKind<'ast> - | ^^^^^^^^^^^^^^^^ -help: add `#[repr(C)]` to this struct - | -LL + #[repr(C)] -LL | struct AstStructure<'ast> { - | - -error: unnamed fields can only have struct or union types - --> $DIR/unnamed-enum-field-issue-121757.rs:9:5 - | -LL | _: AstKind<'ast> - | ^^^^^^^^^^^^^^^^ - -error[E0609]: no field `kind` on type `&'ast AstStructure<'ast>` - --> $DIR/unnamed-enum-field-issue-121757.rs:21:15 - | -LL | match ast.kind {} - | ^^^^ unknown field - | - = note: available fields are: `id`, `_` - -error: aborting due to 4 previous errors - -Some errors have detailed explanations: E0609, E0658. -For more information about an error, try `rustc --explain E0609`. diff --git a/tests/ui/unpretty/expanded-exhaustive.rs b/tests/ui/unpretty/expanded-exhaustive.rs index 279d723a26c..b287e48e476 100644 --- a/tests/ui/unpretty/expanded-exhaustive.rs +++ b/tests/ui/unpretty/expanded-exhaustive.rs @@ -786,20 +786,6 @@ mod types { let _: (T, T); } - /// TyKind::AnonStruct - fn ty_anon_struct() { - struct Struct { - _: struct { t: T }, - } - } - - /// TyKind::AnonUnion - fn ty_anon_union() { - struct Struct { - _: union { t: T }, - } - } - /// TyKind::Path fn ty_path() { let _: T; diff --git a/tests/ui/unpretty/expanded-exhaustive.stdout b/tests/ui/unpretty/expanded-exhaustive.stdout index 149659693ae..f8d09650d92 100644 --- a/tests/ui/unpretty/expanded-exhaustive.stdout +++ b/tests/ui/unpretty/expanded-exhaustive.stdout @@ -361,8 +361,6 @@ mod expressions { - - @@ -636,22 +634,6 @@ mod types { fn ty_never() { let _: !; } /// TyKind::Tup fn ty_tup() { let _: (); let _: (T,); let _: (T, T); } - /// TyKind::AnonStruct - fn ty_anon_struct() { - struct Struct { - _: struct { - t: T, - }, - } - } - /// TyKind::AnonUnion - fn ty_anon_union() { - struct Struct { - _: union { - t: T, - }, - } - } /// TyKind::Path fn ty_path() { let _: T; From 40465d2449f3d9a36c86b94885f58ed3ee2a99f0 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 29 Sep 2024 22:17:30 -0400 Subject: [PATCH 024/357] Remove anon struct and union types --- compiler/rustc_ast/src/ast.rs | 8 ---- compiler/rustc_ast/src/mut_visit.rs | 4 -- compiler/rustc_ast/src/util/classify.rs | 6 --- compiler/rustc_ast/src/visit.rs | 3 -- compiler/rustc_ast_lowering/src/lib.rs | 40 ---------------- compiler/rustc_ast_passes/messages.ftl | 4 -- .../rustc_ast_passes/src/ast_validation.rs | 17 ------- compiler/rustc_ast_passes/src/errors.rs | 9 ---- compiler/rustc_ast_pretty/src/pprust/state.rs | 8 ---- .../src/deriving/clone.rs | 2 +- .../rustc_builtin_macros/src/deriving/mod.rs | 2 - compiler/rustc_feature/src/removed.rs | 2 +- compiler/rustc_parse/src/parser/item.rs | 2 +- compiler/rustc_parse/src/parser/ty.rs | 47 ------------------- compiler/rustc_passes/src/hir_stats.rs | 2 - .../rustc_resolve/src/build_reduced_graph.rs | 23 --------- compiler/rustc_resolve/src/def_collector.rs | 18 ------- src/tools/rustfmt/src/types.rs | 2 - .../rustfmt/tests/target/anonymous-types.rs | 31 ------------ 19 files changed, 3 insertions(+), 227 deletions(-) delete mode 100644 src/tools/rustfmt/tests/target/anonymous-types.rs diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 37f429cce44..4a92cc881fa 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2167,10 +2167,6 @@ pub enum TyKind { Never, /// A tuple (`(A, B, C, D,...)`). Tup(ThinVec>), - /// An anonymous struct type i.e. `struct { foo: Type }`. - AnonStruct(NodeId, ThinVec), - /// An anonymous union type i.e. `union { bar: Type }`. - AnonUnion(NodeId, ThinVec), /// A path (`module::module::...::Type`), optionally /// "qualified", e.g., ` as SomeTrait>::SomeType`. /// @@ -2227,10 +2223,6 @@ impl TyKind { None } } - - pub fn is_anon_adt(&self) -> bool { - matches!(self, TyKind::AnonStruct(..) | TyKind::AnonUnion(..)) - } } /// Syntax used to declare a trait object. diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 104f84f26e0..a59eed4125c 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -519,10 +519,6 @@ pub fn walk_ty(vis: &mut T, ty: &mut P) { visit_vec(bounds, |bound| vis.visit_param_bound(bound, BoundKind::Impl)); } TyKind::MacCall(mac) => vis.visit_mac_call(mac), - TyKind::AnonStruct(id, fields) | TyKind::AnonUnion(id, fields) => { - vis.visit_id(id); - fields.flat_map_in_place(|field| vis.flat_map_field_def(field)); - } } visit_lazy_tts(vis, tokens); vis.visit_span(span); diff --git a/compiler/rustc_ast/src/util/classify.rs b/compiler/rustc_ast/src/util/classify.rs index 1a80a9ccdbf..a517f17c82c 100644 --- a/compiler/rustc_ast/src/util/classify.rs +++ b/compiler/rustc_ast/src/util/classify.rs @@ -287,12 +287,6 @@ fn type_trailing_braced_mac_call(mut ty: &ast::Ty) -> Option<&ast::MacCall> { | ast::TyKind::Pat(..) | ast::TyKind::Dummy | ast::TyKind::Err(..) => break None, - - // These end in brace, but cannot occur in a let-else statement. - // They are only parsed as fields of a data structure. For the - // purpose of denying trailing braces in the expression of a - // let-else, we can disregard these. - ast::TyKind::AnonStruct(..) | ast::TyKind::AnonUnion(..) => break None, } } } diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 9f9c3d8c392..4dcadb8517e 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -535,9 +535,6 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) -> V::Result { TyKind::Err(_guar) => {} TyKind::MacCall(mac) => try_visit!(visitor.visit_mac_call(mac)), TyKind::Never | TyKind::CVarArgs => {} - TyKind::AnonStruct(_id, ref fields) | TyKind::AnonUnion(_id, ref fields) => { - walk_list!(visitor, visit_field_def, fields); - } } V::Result::output() } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index c6cb7aa7dd5..e38374281f7 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1264,46 +1264,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let kind = match &t.kind { TyKind::Infer => hir::TyKind::Infer, TyKind::Err(guar) => hir::TyKind::Err(*guar), - // Lower the anonymous structs or unions in a nested lowering context. - // - // ``` - // struct Foo { - // _: union { - // // ^__________________ <-- within the nested lowering context, - // /* fields */ // | we lower all fields defined into an - // } // | owner node of struct or union item - // // ^_____________________| - // } - // ``` - TyKind::AnonStruct(node_id, fields) | TyKind::AnonUnion(node_id, fields) => { - // Here its `def_id` is created in `build_reduced_graph`. - let def_id = self.local_def_id(*node_id); - debug!(?def_id); - let owner_id = hir::OwnerId { def_id }; - self.with_hir_id_owner(*node_id, |this| { - let fields = this.arena.alloc_from_iter( - fields.iter().enumerate().map(|f| this.lower_field_def(f)), - ); - let span = t.span; - let variant_data = - hir::VariantData::Struct { fields, recovered: ast::Recovered::No }; - // FIXME: capture the generics from the outer adt. - let generics = hir::Generics::empty(); - let kind = match t.kind { - TyKind::AnonStruct(..) => hir::ItemKind::Struct(variant_data, generics), - TyKind::AnonUnion(..) => hir::ItemKind::Union(variant_data, generics), - _ => unreachable!(), - }; - hir::OwnerNode::Item(this.arena.alloc(hir::Item { - ident: Ident::new(kw::Empty, span), - owner_id, - kind, - span: this.lower_span(span), - vis_span: this.lower_span(span.shrink_to_lo()), - })) - }); - hir::TyKind::AnonAdt(hir::ItemId { owner_id }) - } TyKind::Slice(ty) => hir::TyKind::Slice(self.lower_ty(ty, itctx)), TyKind::Ptr(mt) => hir::TyKind::Ptr(self.lower_mt(mt, itctx)), TyKind::Ref(region, mt) => { diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl index 0146a8d9082..7cfbd6c6c6c 100644 --- a/compiler/rustc_ast_passes/messages.ftl +++ b/compiler/rustc_ast_passes/messages.ftl @@ -1,7 +1,3 @@ -ast_passes_anon_struct_or_union_not_allowed = - anonymous {$struct_or_union}s are not allowed outside of unnamed struct or union fields - .label = anonymous {$struct_or_union} declared here - ast_passes_assoc_const_without_body = associated constant in `impl` without body .suggestion = provide a definition for the constant diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index b3d91d881c4..f99654a9a65 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -244,9 +244,6 @@ impl<'a> AstValidator<'a> { } } } - TyKind::AnonStruct(_, ref fields) | TyKind::AnonUnion(_, ref fields) => { - walk_list!(self, visit_struct_field_def, fields) - } _ => visit::walk_ty(self, t), } } @@ -293,15 +290,6 @@ impl<'a> AstValidator<'a> { } } - fn deny_anon_struct_or_union(&self, ty: &Ty) { - let struct_or_union = match &ty.kind { - TyKind::AnonStruct(..) => "struct", - TyKind::AnonUnion(..) => "union", - _ => return, - }; - self.dcx().emit_err(errors::AnonStructOrUnionNotAllowed { struct_or_union, span: ty.span }); - } - fn check_trait_fn_not_const(&self, constness: Const, parent: &TraitOrTraitImpl) { let Const::Yes(span) = constness else { return; @@ -865,14 +853,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> { fn visit_ty(&mut self, ty: &'a Ty) { self.visit_ty_common(ty); - self.deny_anon_struct_or_union(ty); self.walk_ty(ty) } - fn visit_field_def(&mut self, field: &'a FieldDef) { - visit::walk_field_def(self, field) - } - fn visit_item(&mut self, item: &'a Item) { if item.attrs.iter().any(|attr| attr.is_proc_macro_attr()) { self.has_proc_macro_decls = true; diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index 07515897c69..c60925b3049 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -814,15 +814,6 @@ pub(crate) struct NegativeBoundWithParentheticalNotation { pub span: Span, } -#[derive(Diagnostic)] -#[diag(ast_passes_anon_struct_or_union_not_allowed)] -pub(crate) struct AnonStructOrUnionNotAllowed { - #[primary_span] - #[label] - pub span: Span, - pub struct_or_union: &'static str, -} - #[derive(Diagnostic)] #[diag(ast_passes_match_arm_with_no_body)] pub(crate) struct MatchArmWithNoBody { diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index 7e07ccf28a0..01713a9beca 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -1174,14 +1174,6 @@ impl<'a> State<'a> { } self.pclose(); } - ast::TyKind::AnonStruct(_, fields) => { - self.head("struct"); - self.print_record_struct_body(fields, ty.span); - } - ast::TyKind::AnonUnion(_, fields) => { - self.head("union"); - self.print_record_struct_body(fields, ty.span); - } ast::TyKind::Paren(typ) => { self.popen(); self.print_type(typ); diff --git a/compiler/rustc_builtin_macros/src/deriving/clone.rs b/compiler/rustc_builtin_macros/src/deriving/clone.rs index dde696fca61..f79227d52a8 100644 --- a/compiler/rustc_builtin_macros/src/deriving/clone.rs +++ b/compiler/rustc_builtin_macros/src/deriving/clone.rs @@ -113,7 +113,7 @@ fn cs_clone_simple( // Already produced an assertion for this type. // Anonymous structs or unions must be eliminated as they cannot be // type parameters. - } else if !field.ty.kind.is_anon_adt() { + } else { // let _: AssertParamIsClone; super::assert_ty_bounds(cx, &mut stmts, field.ty.clone(), field.span, &[ sym::clone, diff --git a/compiler/rustc_builtin_macros/src/deriving/mod.rs b/compiler/rustc_builtin_macros/src/deriving/mod.rs index d5ee5e430d5..e884c0ec718 100644 --- a/compiler/rustc_builtin_macros/src/deriving/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/mod.rs @@ -124,8 +124,6 @@ fn assert_ty_bounds( span: Span, assert_path: &[Symbol], ) { - // Deny anonymous structs or unions to avoid weird errors. - assert!(!ty.kind.is_anon_adt(), "Anonymous structs or unions cannot be type parameters"); // Generate statement `let _: assert_path;`. let span = cx.with_def_site_ctxt(span); let assert_path = cx.path_all(span, true, cx.std_path(assert_path), vec![GenericArg::Type(ty)]); diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs index 276814dd0d9..85bc1460b3e 100644 --- a/compiler/rustc_feature/src/removed.rs +++ b/compiler/rustc_feature/src/removed.rs @@ -217,7 +217,7 @@ declare_features! ( /// Allows using items which are missing stability attributes (removed, unmarked_api, "1.0.0", None, None), /// Allows unnamed fields of struct and union type - (removed, unnamed_fields, "1.74.0", Some(49804)), + (removed, unnamed_fields, "CURRENT_RUSTC_VERSION", Some(49804), Some("feature needs redesign")), (removed, unsafe_no_drop_flag, "1.0.0", None, None), /// Allows `union` fields that don't implement `Copy` as long as they don't have any drop glue. (removed, untagged_unions, "1.13.0", Some(55149), diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 13681c00f8e..36733726564 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1984,7 +1984,7 @@ impl<'a> Parser<'a> { } } self.expect_field_ty_separator()?; - let ty = self.parse_ty_for_field_def()?; + let ty = self.parse_ty()?; if self.token == token::Colon && self.look_ahead(1, |t| *t != token::Colon) { self.dcx().emit_err(errors::SingleColonStructType { span: self.token.span }); } diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index a8ed8b5df9c..625a4cabdf2 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -128,17 +128,6 @@ impl<'a> Parser<'a> { ) } - /// Parse a type suitable for a field definition. - /// The difference from `parse_ty` is that this version - /// allows anonymous structs and unions. - pub(super) fn parse_ty_for_field_def(&mut self) -> PResult<'a, P> { - if self.can_begin_anon_struct_or_union() { - self.parse_anon_struct_or_union() - } else { - self.parse_ty() - } - } - /// Parse a type suitable for a function or function pointer parameter. /// The difference from `parse_ty` is that this version allows `...` /// (`CVarArgs`) at the top level of the type. @@ -382,37 +371,6 @@ impl<'a> Parser<'a> { if allow_qpath_recovery { self.maybe_recover_from_bad_qpath(ty) } else { Ok(ty) } } - /// Parse an anonymous struct or union (only for field definitions): - /// ```ignore (feature-not-ready) - /// #[repr(C)] - /// struct Foo { - /// _: struct { // anonymous struct - /// x: u32, - /// y: f64, - /// } - /// _: union { // anonymous union - /// z: u32, - /// w: f64, - /// } - /// } - /// ``` - fn parse_anon_struct_or_union(&mut self) -> PResult<'a, P> { - assert!(self.token.is_keyword(kw::Union) || self.token.is_keyword(kw::Struct)); - let is_union = self.token.is_keyword(kw::Union); - - let lo = self.token.span; - self.bump(); - - let (fields, _recovered) = - self.parse_record_struct_body(if is_union { "union" } else { "struct" }, lo, false)?; - let span = lo.to(self.prev_token.span); - self.psess.gated_spans.gate(sym::unnamed_fields, span); - let id = ast::DUMMY_NODE_ID; - let kind = - if is_union { TyKind::AnonUnion(id, fields) } else { TyKind::AnonStruct(id, fields) }; - Ok(self.mk_ty(span, kind)) - } - /// Parses either: /// - `(TYPE)`, a parenthesized type. /// - `(TYPE,)`, a tuple with a single field of type TYPE. @@ -813,11 +771,6 @@ impl<'a> Parser<'a> { Ok(bounds) } - pub(super) fn can_begin_anon_struct_or_union(&mut self) -> bool { - (self.token.is_keyword(kw::Struct) || self.token.is_keyword(kw::Union)) - && self.look_ahead(1, |t| t == &token::OpenDelim(Delimiter::Brace)) - } - /// Can the current token begin a bound? fn can_begin_bound(&mut self) -> bool { self.check_path() diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs index 903fb114744..e89838b22ab 100644 --- a/compiler/rustc_passes/src/hir_stats.rs +++ b/compiler/rustc_passes/src/hir_stats.rs @@ -583,8 +583,6 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { BareFn, Never, Tup, - AnonStruct, - AnonUnion, Path, Pat, TraitObject, diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index a9ea268e51a..ae7389342ec 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -724,29 +724,6 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { // Record field names for error reporting. self.insert_field_idents(def_id, fields); self.insert_field_visibilities_local(def_id.to_def_id(), fields); - - for field in fields { - match &field.ty.kind { - ast::TyKind::AnonStruct(id, nested_fields) - | ast::TyKind::AnonUnion(id, nested_fields) => { - let feed = self.r.feed(*id); - let local_def_id = feed.key(); - let def_id = local_def_id.to_def_id(); - let def_kind = self.r.tcx.def_kind(local_def_id); - let res = Res::Def(def_kind, def_id); - self.build_reduced_graph_for_struct_variant( - &nested_fields, - Ident::empty(), - feed, - res, - // Anonymous adts inherit visibility from their parent adts. - adt_vis, - field.ty.span, - ); - } - _ => {} - } - } } /// Constructs the reduced graph for one item. diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index 98662385434..0047f2c4b51 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -105,22 +105,6 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> { let name = field.ident.map_or_else(|| sym::integer(index(self)), |ident| ident.name); let def = self.create_def(field.id, name, DefKind::Field, field.span); self.with_parent(def, |this| visit::walk_field_def(this, field)); - self.visit_anon_adt(&field.ty); - } - } - - fn visit_anon_adt(&mut self, ty: &'a Ty) { - let def_kind = match &ty.kind { - TyKind::AnonStruct(..) => DefKind::Struct, - TyKind::AnonUnion(..) => DefKind::Union, - _ => return, - }; - match &ty.kind { - TyKind::AnonStruct(node_id, _) | TyKind::AnonUnion(node_id, _) => { - let def_id = self.create_def(*node_id, kw::Empty, def_kind, ty.span); - self.with_parent(def_id, |this| visit::walk_ty(this, ty)); - } - _ => {} } } @@ -476,8 +460,6 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { fn visit_ty(&mut self, ty: &'a Ty) { match &ty.kind { TyKind::MacCall(..) => self.visit_macro_invoc(ty.id), - // Anonymous structs or unions are visited later after defined. - TyKind::AnonStruct(..) | TyKind::AnonUnion(..) => {} TyKind::ImplTrait(id, _) => { // HACK: pprust breaks strings with newlines when the type // gets too long. We don't want these to show up in compiler diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs index 07b483b2b37..f75c4f0fad7 100644 --- a/src/tools/rustfmt/src/types.rs +++ b/src/tools/rustfmt/src/types.rs @@ -951,8 +951,6 @@ impl Rewrite for ast::Ty { ast::TyKind::Tup(ref items) => { rewrite_tuple(context, items.iter(), self.span, shape, items.len() == 1) } - ast::TyKind::AnonStruct(..) => Ok(context.snippet(self.span).to_owned()), - ast::TyKind::AnonUnion(..) => Ok(context.snippet(self.span).to_owned()), ast::TyKind::Path(ref q_self, ref path) => { rewrite_path(context, PathContext::Type, q_self, path, shape) } diff --git a/src/tools/rustfmt/tests/target/anonymous-types.rs b/src/tools/rustfmt/tests/target/anonymous-types.rs deleted file mode 100644 index e8c2d83878c..00000000000 --- a/src/tools/rustfmt/tests/target/anonymous-types.rs +++ /dev/null @@ -1,31 +0,0 @@ -// Test for issue 85480 -// Pretty print anonymous struct and union types - -// pp-exact -// pretty-compare-only - -struct Foo { - _: union { - _: struct { - a: u8, - b: u16, - }, - c: u32, - }, - d: u64, - e: f32, -} - -// Test for https://github.com/rust-lang/rust/issues/117942 -struct Foo { - _: union { - #[rustfmt::skip] - f: String, - }, - #[rustfmt::skip] - _: struct { - g: i32, - }, -} - -fn main() {} From 6628bba06083d8b182d1f526f53a4ed6f8203042 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 29 Sep 2024 22:23:44 -0400 Subject: [PATCH 025/357] Remove crashes and fix tests --- .../clippy/tests/ui/crashes/ice-12284.rs | 10 --- tests/crashes/117942.rs | 7 -- tests/crashes/121161.rs | 12 --- tests/crashes/121263-2.rs | 6 -- tests/crashes/121263.rs | 9 --- tests/crashes/121299.rs | 6 -- tests/crashes/121722.rs | 10 --- tests/crashes/121799.rs | 11 --- tests/crashes/126969.rs | 9 --- ...d_access.bar.SimplifyCfg-initial.after.mir | 59 --------------- ...d_access.foo.SimplifyCfg-initial.after.mir | 59 --------------- tests/mir-opt/unnamed-fields/field_access.rs | 73 ------------------- tests/ui/unpretty/expanded-exhaustive.rs | 1 - tests/ui/unpretty/expanded-exhaustive.stdout | 1 - 14 files changed, 273 deletions(-) delete mode 100644 src/tools/clippy/tests/ui/crashes/ice-12284.rs delete mode 100644 tests/crashes/117942.rs delete mode 100644 tests/crashes/121161.rs delete mode 100644 tests/crashes/121263-2.rs delete mode 100644 tests/crashes/121263.rs delete mode 100644 tests/crashes/121299.rs delete mode 100644 tests/crashes/121722.rs delete mode 100644 tests/crashes/121799.rs delete mode 100644 tests/crashes/126969.rs delete mode 100644 tests/mir-opt/unnamed-fields/field_access.bar.SimplifyCfg-initial.after.mir delete mode 100644 tests/mir-opt/unnamed-fields/field_access.foo.SimplifyCfg-initial.after.mir delete mode 100644 tests/mir-opt/unnamed-fields/field_access.rs diff --git a/src/tools/clippy/tests/ui/crashes/ice-12284.rs b/src/tools/clippy/tests/ui/crashes/ice-12284.rs deleted file mode 100644 index 8d1dbface8e..00000000000 --- a/src/tools/clippy/tests/ui/crashes/ice-12284.rs +++ /dev/null @@ -1,10 +0,0 @@ -#![allow(incomplete_features)] -#![feature(unnamed_fields)] - -#[repr(C)] -struct Foo { - _: struct { - }, -} - -fn main() {} diff --git a/tests/crashes/117942.rs b/tests/crashes/117942.rs deleted file mode 100644 index 6fdfc689250..00000000000 --- a/tests/crashes/117942.rs +++ /dev/null @@ -1,7 +0,0 @@ -//@ known-bug: #117942 -struct Foo { - _: union { - #[rustfmt::skip] - f: String - }, -} diff --git a/tests/crashes/121161.rs b/tests/crashes/121161.rs deleted file mode 100644 index 6da6426a86d..00000000000 --- a/tests/crashes/121161.rs +++ /dev/null @@ -1,12 +0,0 @@ -//@ known-bug: #121161 -#![allow(incomplete_features)] -#![feature(unnamed_fields)] - - -#[derive(Eq)] -#[repr(C)] -struct Bar { - _: union { - a: u8, - }, -} diff --git a/tests/crashes/121263-2.rs b/tests/crashes/121263-2.rs deleted file mode 100644 index 2c6327a8808..00000000000 --- a/tests/crashes/121263-2.rs +++ /dev/null @@ -1,6 +0,0 @@ -//@ known-bug: #121263 -#[repr(C)] -#[derive(Debug)] -struct L { - _: MyI32, -} diff --git a/tests/crashes/121263.rs b/tests/crashes/121263.rs deleted file mode 100644 index cd7583a7faf..00000000000 --- a/tests/crashes/121263.rs +++ /dev/null @@ -1,9 +0,0 @@ -//@ known-bug: #121263 -#[repr(C)] -#[repr(C)] -#[derive(Debug)] -struct L { - _: i32, - _: MyI32, - _: BadEnum, -} diff --git a/tests/crashes/121299.rs b/tests/crashes/121299.rs deleted file mode 100644 index be5e0c0df57..00000000000 --- a/tests/crashes/121299.rs +++ /dev/null @@ -1,6 +0,0 @@ -//@ known-bug: #121299 -#[derive(Eq)] -struct D { - _: union { - }, -} diff --git a/tests/crashes/121722.rs b/tests/crashes/121722.rs deleted file mode 100644 index d1b8c447bf7..00000000000 --- a/tests/crashes/121722.rs +++ /dev/null @@ -1,10 +0,0 @@ -//@ known-bug: #121722 -#[repr(C)] -struct Foo { - _: u8, -} - -#[repr(C)] -struct D { - _: Foo, -} diff --git a/tests/crashes/121799.rs b/tests/crashes/121799.rs deleted file mode 100644 index 6035c9d9b15..00000000000 --- a/tests/crashes/121799.rs +++ /dev/null @@ -1,11 +0,0 @@ -//@ known-bug: #121799 -struct S { - _: str -} - -fn func(a: S) -{ - let _x = a.f; -} - -fn main() {} diff --git a/tests/crashes/126969.rs b/tests/crashes/126969.rs deleted file mode 100644 index 676563d059c..00000000000 --- a/tests/crashes/126969.rs +++ /dev/null @@ -1,9 +0,0 @@ -//@ known-bug: rust-lang/rust#126969 - -struct S { - _: union { t: T }, -} - -fn f(S::<&i8> { .. }: S<&i8>) {} - -fn main() {} diff --git a/tests/mir-opt/unnamed-fields/field_access.bar.SimplifyCfg-initial.after.mir b/tests/mir-opt/unnamed-fields/field_access.bar.SimplifyCfg-initial.after.mir deleted file mode 100644 index f1904e5d0f4..00000000000 --- a/tests/mir-opt/unnamed-fields/field_access.bar.SimplifyCfg-initial.after.mir +++ /dev/null @@ -1,59 +0,0 @@ -// MIR for `bar` after SimplifyCfg-initial - -fn bar(_1: Bar) -> () { - debug bar => _1; - let mut _0: (); - let _2: (); - let mut _3: u8; - let _4: (); - let mut _5: i8; - let _6: (); - let mut _7: bool; - let _8: (); - let mut _9: [u8; 1]; - - bb0: { - StorageLive(_2); - StorageLive(_3); - _3 = copy (_1.0: u8); - _2 = access::(move _3) -> [return: bb1, unwind: bb5]; - } - - bb1: { - StorageDead(_3); - StorageDead(_2); - StorageLive(_4); - StorageLive(_5); - _5 = copy ((_1.1: Bar::{anon_adt#0}).0: i8); - _4 = access::(move _5) -> [return: bb2, unwind: bb5]; - } - - bb2: { - StorageDead(_5); - StorageDead(_4); - StorageLive(_6); - StorageLive(_7); - _7 = copy ((_1.1: Bar::{anon_adt#0}).1: bool); - _6 = access::(move _7) -> [return: bb3, unwind: bb5]; - } - - bb3: { - StorageDead(_7); - StorageDead(_6); - StorageLive(_8); - StorageLive(_9); - _9 = copy (((_1.2: Bar::{anon_adt#1}).0: Bar::{anon_adt#1}::{anon_adt#0}).0: [u8; 1]); - _8 = access::<[u8; 1]>(move _9) -> [return: bb4, unwind: bb5]; - } - - bb4: { - StorageDead(_9); - StorageDead(_8); - _0 = const (); - return; - } - - bb5 (cleanup): { - resume; - } -} diff --git a/tests/mir-opt/unnamed-fields/field_access.foo.SimplifyCfg-initial.after.mir b/tests/mir-opt/unnamed-fields/field_access.foo.SimplifyCfg-initial.after.mir deleted file mode 100644 index c279f590012..00000000000 --- a/tests/mir-opt/unnamed-fields/field_access.foo.SimplifyCfg-initial.after.mir +++ /dev/null @@ -1,59 +0,0 @@ -// MIR for `foo` after SimplifyCfg-initial - -fn foo(_1: Foo) -> () { - debug foo => _1; - let mut _0: (); - let _2: (); - let mut _3: u8; - let _4: (); - let mut _5: i8; - let _6: (); - let mut _7: bool; - let _8: (); - let mut _9: [u8; 1]; - - bb0: { - StorageLive(_2); - StorageLive(_3); - _3 = copy (_1.0: u8); - _2 = access::(move _3) -> [return: bb1, unwind: bb5]; - } - - bb1: { - StorageDead(_3); - StorageDead(_2); - StorageLive(_4); - StorageLive(_5); - _5 = copy ((_1.1: Foo::{anon_adt#0}).0: i8); - _4 = access::(move _5) -> [return: bb2, unwind: bb5]; - } - - bb2: { - StorageDead(_5); - StorageDead(_4); - StorageLive(_6); - StorageLive(_7); - _7 = copy ((_1.1: Foo::{anon_adt#0}).1: bool); - _6 = access::(move _7) -> [return: bb3, unwind: bb5]; - } - - bb3: { - StorageDead(_7); - StorageDead(_6); - StorageLive(_8); - StorageLive(_9); - _9 = copy (((_1.2: Foo::{anon_adt#1}).0: Foo::{anon_adt#1}::{anon_adt#0}).0: [u8; 1]); - _8 = access::<[u8; 1]>(move _9) -> [return: bb4, unwind: bb5]; - } - - bb4: { - StorageDead(_9); - StorageDead(_8); - _0 = const (); - return; - } - - bb5 (cleanup): { - resume; - } -} diff --git a/tests/mir-opt/unnamed-fields/field_access.rs b/tests/mir-opt/unnamed-fields/field_access.rs deleted file mode 100644 index cc0ac9a3427..00000000000 --- a/tests/mir-opt/unnamed-fields/field_access.rs +++ /dev/null @@ -1,73 +0,0 @@ -// Tests the correct handling of unnamed fields within structs and unions marked with #[repr(C)]. - -// EMIT_MIR field_access.foo.SimplifyCfg-initial.after.mir -// EMIT_MIR field_access.bar.SimplifyCfg-initial.after.mir - -#![allow(incomplete_features)] -#![feature(unnamed_fields)] - -#[repr(C)] -struct Foo { - a: u8, - _: struct { - b: i8, - c: bool, - }, - _: struct { - _: struct { - d: [u8; 1], - } - }, -} - -#[repr(C)] -union Bar { - a: u8, - _: union { - b: i8, - c: bool, - }, - _: union { - _: union { - d: [u8; 1], - } - }, -} - -fn access(_: T) {} - -// CHECK-LABEL: fn foo( -fn foo(foo: Foo) { - // CHECK [[a:_.*]] = (_1.0: u8); - // CHECK _.* = access::(move [[a]]) -> [return: bb1, unwind: bb5]; - access(foo.a); - // CHECK [[b:_.*]] = ((_1.1: Foo::{anon_adt#0}).0: i8); - // CHECK _.* = access::(move [[b]]) -> [return: bb2, unwind: bb5]; - access(foo.b); - // CHECK [[c:_.*]] = ((_1.1: Foo::{anon_adt#0}).1: bool); - // CHECK _.* = access::(move [[c]]) -> [return: bb3, unwind: bb5]; - access(foo.c); - // CHECK [[d:_.*]] = (((_1.2: Foo::{anon_adt#1}).0: Foo::{anon_adt#1}::{anon_adt#0}).0: [u8; 1]); - // CHECK _.* = access::<[u8; 1]>(move [[d]]) -> [return: bb4, unwind: bb5]; - access(foo.d); -} - -// CHECK-LABEL: fn bar( -fn bar(bar: Bar) { - unsafe { - // CHECK [[a:_.*]] = (_1.0: u8); - // CHECK _.* = access::(move [[a]]) -> [return: bb1, unwind: bb5]; - access(bar.a); - // CHECK [[b:_.*]] = ((_1.1: Bar::{anon_adt#0}).0: i8); - // CHECK _.* = access::(move [[b]]) -> [return: bb2, unwind: bb5]; - access(bar.b); - // CHECK [[c:_.*]] = ((_1.1: Bar::{anon_adt#0}).1: bool); - // CHECK _.* = access::(move [[c]]) -> [return: bb3, unwind: bb5]; - access(bar.c); - // CHECK [[d:_.*]] = (((_1.2: Bar::{anon_adt#1}).0: Bar::{anon_adt#1}::{anon_adt#0}).0: [u8; 1]); - // CHECK _.* = access::<[u8; 1]>(move [[d]]) -> [return: bb4, unwind: bb5]; - access(bar.d); - } -} - -fn main() {} diff --git a/tests/ui/unpretty/expanded-exhaustive.rs b/tests/ui/unpretty/expanded-exhaustive.rs index b287e48e476..799e8071d02 100644 --- a/tests/ui/unpretty/expanded-exhaustive.rs +++ b/tests/ui/unpretty/expanded-exhaustive.rs @@ -23,7 +23,6 @@ #![feature(trace_macros)] #![feature(trait_alias)] #![feature(try_blocks)] -#![feature(unnamed_fields)] #![feature(yeet_expr)] #![allow(incomplete_features)] diff --git a/tests/ui/unpretty/expanded-exhaustive.stdout b/tests/ui/unpretty/expanded-exhaustive.stdout index f8d09650d92..d8384951e12 100644 --- a/tests/ui/unpretty/expanded-exhaustive.stdout +++ b/tests/ui/unpretty/expanded-exhaustive.stdout @@ -24,7 +24,6 @@ #![feature(trace_macros)] #![feature(trait_alias)] #![feature(try_blocks)] -#![feature(unnamed_fields)] #![feature(yeet_expr)] #![allow(incomplete_features)] #[prelude_import] From 2bc2304e30f9b35cd41e15a483f1dfcb727050e7 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Tue, 1 Oct 2024 14:40:45 -0400 Subject: [PATCH 026/357] Stabilize `debug_more_non_exhaustive` Fixes: https://github.com/rust-lang/rust/issues/127942 --- library/core/src/fmt/builders.rs | 16 ++++------------ library/core/tests/lib.rs | 1 - 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/library/core/src/fmt/builders.rs b/library/core/src/fmt/builders.rs index c7c462a4df1..3d0c9f7c964 100644 --- a/library/core/src/fmt/builders.rs +++ b/library/core/src/fmt/builders.rs @@ -366,8 +366,6 @@ impl<'a, 'b: 'a> DebugTuple<'a, 'b> { /// # Examples /// /// ``` - /// #![feature(debug_more_non_exhaustive)] - /// /// use std::fmt; /// /// struct Foo(i32, String); @@ -385,7 +383,7 @@ impl<'a, 'b: 'a> DebugTuple<'a, 'b> { /// "Foo(10, ..)", /// ); /// ``` - #[unstable(feature = "debug_more_non_exhaustive", issue = "127942")] + #[stable(feature = "debug_more_non_exhaustive", since = "CURRENT_RUSTC_VERSION")] pub fn finish_non_exhaustive(&mut self) -> fmt::Result { self.result = self.result.and_then(|_| { if self.fields > 0 { @@ -606,8 +604,6 @@ impl<'a, 'b: 'a> DebugSet<'a, 'b> { /// # Examples /// /// ``` - /// #![feature(debug_more_non_exhaustive)] - /// /// use std::fmt; /// /// struct Foo(Vec); @@ -630,7 +626,7 @@ impl<'a, 'b: 'a> DebugSet<'a, 'b> { /// "{1, 2, ..}", /// ); /// ``` - #[unstable(feature = "debug_more_non_exhaustive", issue = "127942")] + #[stable(feature = "debug_more_non_exhaustive", since = "CURRENT_RUSTC_VERSION")] pub fn finish_non_exhaustive(&mut self) -> fmt::Result { self.inner.result = self.inner.result.and_then(|_| { if self.inner.has_fields { @@ -800,8 +796,6 @@ impl<'a, 'b: 'a> DebugList<'a, 'b> { /// # Examples /// /// ``` - /// #![feature(debug_more_non_exhaustive)] - /// /// use std::fmt; /// /// struct Foo(Vec); @@ -824,7 +818,7 @@ impl<'a, 'b: 'a> DebugList<'a, 'b> { /// "[1, 2, ..]", /// ); /// ``` - #[unstable(feature = "debug_more_non_exhaustive", issue = "127942")] + #[stable(feature = "debug_more_non_exhaustive", since = "CURRENT_RUSTC_VERSION")] pub fn finish_non_exhaustive(&mut self) -> fmt::Result { self.inner.result.and_then(|_| { if self.inner.has_fields { @@ -1126,8 +1120,6 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { /// # Examples /// /// ``` - /// #![feature(debug_more_non_exhaustive)] - /// /// use std::fmt; /// /// struct Foo(Vec<(String, i32)>); @@ -1154,7 +1146,7 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { /// r#"{"A": 10, "B": 11, ..}"#, /// ); /// ``` - #[unstable(feature = "debug_more_non_exhaustive", issue = "127942")] + #[stable(feature = "debug_more_non_exhaustive", since = "CURRENT_RUSTC_VERSION")] pub fn finish_non_exhaustive(&mut self) -> fmt::Result { self.result = self.result.and_then(|_| { assert!(!self.has_key, "attempted to finish a map with a partial entry"); diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 4f2190f78bf..91632c28e00 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -39,7 +39,6 @@ #![feature(core_io_borrowed_buf)] #![feature(core_private_bignum)] #![feature(core_private_diy_float)] -#![feature(debug_more_non_exhaustive)] #![feature(dec2flt)] #![feature(duration_constants)] #![feature(duration_constructors)] From 302551388b1942bb4216bb5a15d9d55cee3643a8 Mon Sep 17 00:00:00 2001 From: Yoh Deadfall Date: Fri, 20 Sep 2024 12:27:51 +0300 Subject: [PATCH 027/357] Implemented FromStr for CString and TryFrom for String --- library/alloc/src/ffi/c_str.rs | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/library/alloc/src/ffi/c_str.rs b/library/alloc/src/ffi/c_str.rs index e32676a6543..15b0506023d 100644 --- a/library/alloc/src/ffi/c_str.rs +++ b/library/alloc/src/ffi/c_str.rs @@ -7,7 +7,7 @@ use core::borrow::Borrow; use core::ffi::{c_char, CStr}; use core::num::NonZero; use core::slice::memchr; -use core::str::{self, Utf8Error}; +use core::str::{self, FromStr, Utf8Error}; use core::{fmt, mem, ops, ptr, slice}; use crate::borrow::{Cow, ToOwned}; @@ -815,6 +815,30 @@ impl From>> for CString { } } +impl FromStr for CString { + type Err = NulError; + + /// Converts a string `s` into a [`CString`]. + /// + /// This method is equivalent to [`CString::new`]. + #[inline] + fn from_str(s: &str) -> Result { + Self::new(s) + } +} + +impl TryFrom for String { + type Error = IntoStringError; + + /// Converts a [`CString`] into a [`String`] if it contains valid UTF-8 data. + /// + /// This method is equivalent to [`CString::into_string`]. + #[inline] + fn try_from(value: CString) -> Result { + value.into_string() + } +} + #[cfg(not(test))] #[stable(feature = "more_box_slice_clone", since = "1.29.0")] impl Clone for Box { From 5fef4621c3fd3a2b460dbacd35fbef52537d8889 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Tue, 1 Oct 2024 21:04:22 -0700 Subject: [PATCH 028/357] Add 1.82 release notes --- RELEASES.md | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) diff --git a/RELEASES.md b/RELEASES.md index b49470c3075..b9d58d6b757 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,100 @@ +Version 1.82.0 (2024-10-17) +========================== + + + +Language +-------- +- [Don't make statement nonterminals match pattern nonterminals](https://github.com/rust-lang/rust/pull/120221/) +- [Implement lint against ambiguous negative literals](https://github.com/rust-lang/rust/pull/121364/) +- [Patterns matching empty types can now be omitted in common cases](https://github.com/rust-lang/rust/pull/122792) +- [size_of_val_raw: for length 0 this is safe to call](https://github.com/rust-lang/rust/pull/126152/) +- [Reorder trait bound modifiers *after* `for<...>` binder in trait bounds](https://github.com/rust-lang/rust/pull/127054/) +- [Stabilize opaque type precise capturing (RFC 3617)](https://github.com/rust-lang/rust/pull/127672) +- [Stabilize explicit opt-in to unsafe attributes](https://github.com/rust-lang/rust/pull/128771) + + + + +Compiler +-------- +- [Promote riscv64gc-unknown-linux-musl to tier 2](https://github.com/rust-lang/rust/pull/122049) +- [Improved diagnostics to explain why a pattern is unreachable](https://github.com/rust-lang/rust/pull/128034) +- [The compiler now triggers the unreachable code warning properly for async functions that don't return/are `-> !`](https://github.com/rust-lang/rust/pull/128443) +- [Promote `wasm32-wasip2` to Tier 2.](https://github.com/rust-lang/rust/pull/126967/) + + + + +Libraries +--------- +- [Implement DoubleEnded and ExactSize for Take and Take](https://github.com/rust-lang/rust/pull/106943/) +- [Stabilize Wasm relaxed SIMD](https://github.com/rust-lang/rust/pull/117468/) +- [Stabilize const `{integer}::from_str_radix` i.e. `const_int_from_str`](https://github.com/rust-lang/rust/pull/124941/) +- [CommandExt::before_exec: deprecate safety in edition 2024](https://github.com/rust-lang/rust/pull/125970/) +- [CloneToUninit impls](https://github.com/rust-lang/rust/pull/126877/) +- [impl `Default` for collection iterators that don't already have it](https://github.com/rust-lang/rust/pull/128261/) + + + + +Stabilized APIs +--------------- + + + +Cargo +----- +- [feat: Add `info` cargo subcommand](https://github.com/rust-lang/cargo/pull/14141/) + + + +Compatibility Notes +------------------- +- [`addr_of(_mut)!` macros and the newly stabilized `&raw (const|mut)` are now safe to use with all static items](https://github.com/rust-lang/rust/pull/125834) + - We now [disallow setting some built-in cfgs via the command-line](https://github.com/rust-lang/rust/pull/126158) with the newly added [`explicit_builtin_cfgs_in_flags`](https://doc.rust-lang.org/rustc/lints/listing/deny-by-default.html#explicit-builtin-cfgs-in-flags) lint in order to prevent incoherent state, eg. `windows` cfg active but target is Linux based. The appropriate [`rustc` flag](https://doc.rust-lang.org/rustc/command-line-arguments.html) should be used instead. +- [Stabilize `&raw const` and `&raw mut` operators (RFC 2582)](https://github.com/rust-lang/rust/pull/127679) +- [Stabilize unsafe extern blocks (RFC 3484)](https://github.com/rust-lang/rust/pull/127921) +- The standard library has a new implementation of `binary_search` which is significantly improves performance (#128254). However when a sorted slice has multiple values which compare equal, the new implementation may select a different value among the equal ones than the old implementation. +- [illumos/Solaris now sets `MSG_NOSIGNAL` when writing to sockets](https://github.com/rust-lang/rust/pull/128259). This avoids killing the process with SIGPIPE when writing to a closed socket, which matches the existing behavior on other UNIX targets. +- [Stabilize offset_of_nested](https://github.com/rust-lang/rust/pull/128284) +- [Removes a problematic hack that always passed the --whole-archive linker flag for tests, which may cause linker errors for code accidentally relying on it.](https://github.com/rust-lang/rust/pull/128400) +- The WebAssembly target features `multivalue` and `reference-types` are now + both enabled by default. These two features both have subtle changes implied + for generated WebAssembly binaries. For the `multivalue` feature, WebAssembly + target support has changed when upgrading to LLVM 19. Support for generating + functions with multiple returns no longer works and + `-Ctarget-feature=+multivalue` has a different meaning than it did in LLVM 18 + and prior. There is no longer any supported means to generate a module that has + a function with multiple returns in WebAssembly from Rust source code. For the + `reference-types` feature the encoding of immediates in the `call_indirect`, a + commonly used instruction by the WebAssembly backend, has changed. Validators + and parsers which don't understand the `reference-types` proposal will no + longer accept modules produced by LLVM due to this change in encoding of + immediates. Additionally these features being enabled are encoded in the + `target_features` custom section and may affect downstream tooling such as + `wasm-opt` consuming the module. Generating a WebAssembly module that disables + default features requires `-Zbuild-std` support from Cargo and more information + can be found at + [rust-lang/rust#128511](https://github.com/rust-lang/rust/pull/128511). +- [Stabilize `const` arguments to inline asm](https://github.com/rust-lang/rust/pull/128570) +- [Promote aarch64-apple-darwin to Tier 1](https://github.com/rust-lang/rust/pull/128592) +- [stabilize floating-point arithmetic in `const fn`](https://github.com/rust-lang/rust/pull/128596) +- [float types: document NaN bit pattern guarantees](https://github.com/rust-lang/rust/pull/129559) +- [Rust now raises unsafety errors for union patterns in parameter-position](https://github.com/rust-lang/rust/pull/130531) + + + + +Internal Changes +---------------- + +These changes do not affect any public interfaces of Rust, but they represent +significant improvements to the performance or internals of rustc and related +tools. + +- [Update to LLVM 19](https://github.com/rust-lang/rust/pull/127513) + Version 1.81.0 (2024-09-05) ========================== From 7d27ceb9543244867e8c75c513ecf3e5173a3ea1 Mon Sep 17 00:00:00 2001 From: Henry Jiang Date: Thu, 3 Oct 2024 11:37:41 -0400 Subject: [PATCH 029/357] Add AIX Calling Convention --- compiler/rustc_target/src/abi/call/powerpc64.rs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_target/src/abi/call/powerpc64.rs b/compiler/rustc_target/src/abi/call/powerpc64.rs index b9767bf906b..d08a30cb3d1 100644 --- a/compiler/rustc_target/src/abi/call/powerpc64.rs +++ b/compiler/rustc_target/src/abi/call/powerpc64.rs @@ -10,6 +10,7 @@ use crate::spec::HasTargetSpec; enum ABI { ELFv1, // original ABI used for powerpc64 (big-endian) ELFv2, // newer ABI used for powerpc64le and musl (both endians) + AIX, // used by AIX OS, big-endian only } use ABI::*; @@ -23,9 +24,9 @@ where C: HasDataLayout, { arg.layout.homogeneous_aggregate(cx).ok().and_then(|ha| ha.unit()).and_then(|unit| { - // ELFv1 only passes one-member aggregates transparently. + // ELFv1 and AIX only passes one-member aggregates transparently. // ELFv2 passes up to eight uniquely addressable members. - if (abi == ELFv1 && arg.layout.size > unit.size) + if ((abi == ELFv1 || abi == AIX) && arg.layout.size > unit.size) || arg.layout.size > unit.size.checked_mul(8, cx).unwrap() { return None; @@ -55,8 +56,14 @@ where return; } + // See https://github.com/llvm/llvm-project/blob/main/clang/lib/CodeGen/Targets/PPC.cpp. + if !is_ret && abi == AIX { + arg.make_indirect_byval(None); + return; + } + // The ELFv1 ABI doesn't return aggregates in registers - if is_ret && abi == ELFv1 { + if is_ret && (abi == ELFv1 || abi == AIX) { arg.make_indirect(); return; } @@ -93,6 +100,8 @@ where { let abi = if cx.target_spec().env == "musl" { ELFv2 + } else if cx.target_spec().os == "aix" { + AIX } else { match cx.data_layout().endian { Endian::Big => ELFv1, From d09e27d54ace664f90583e12e4be6089a13be7e6 Mon Sep 17 00:00:00 2001 From: Henry Jiang Date: Thu, 3 Oct 2024 12:36:36 -0400 Subject: [PATCH 030/357] update call --- compiler/rustc_target/src/abi/call/powerpc64.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_target/src/abi/call/powerpc64.rs b/compiler/rustc_target/src/abi/call/powerpc64.rs index d08a30cb3d1..71e533b8cc5 100644 --- a/compiler/rustc_target/src/abi/call/powerpc64.rs +++ b/compiler/rustc_target/src/abi/call/powerpc64.rs @@ -56,9 +56,10 @@ where return; } + // The AIX ABI expect byval for aggregates // See https://github.com/llvm/llvm-project/blob/main/clang/lib/CodeGen/Targets/PPC.cpp. if !is_ret && abi == AIX { - arg.make_indirect_byval(None); + arg.pass_by_stack_offset(None); return; } From 82b4d0d8aa9e1da2c9df3701bc970cb46b00778e Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sun, 11 Aug 2024 12:53:48 +0100 Subject: [PATCH 031/357] std::fs::get_path freebsd update. what matters is we re doing the right things as doing sizeof, rather than KINFO_FILE_SIZE (only defined on intel architectures), the kernel making sure it matches the expectation in its side. --- library/std/src/sys/pal/unix/fs.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/std/src/sys/pal/unix/fs.rs b/library/std/src/sys/pal/unix/fs.rs index 39aabf0b2d6..1d962fbc0c2 100644 --- a/library/std/src/sys/pal/unix/fs.rs +++ b/library/std/src/sys/pal/unix/fs.rs @@ -1538,7 +1538,7 @@ impl fmt::Debug for File { Some(PathBuf::from(OsString::from_vec(buf))) } - #[cfg(all(target_os = "freebsd", target_arch = "x86_64"))] + #[cfg(target_os = "freebsd")] fn get_path(fd: c_int) -> Option { let info = Box::::new_zeroed(); let mut info = unsafe { info.assume_init() }; @@ -1566,7 +1566,7 @@ impl fmt::Debug for File { #[cfg(not(any( target_os = "linux", target_os = "vxworks", - all(target_os = "freebsd", target_arch = "x86_64"), + target_os = "freebsd", target_os = "netbsd", target_os = "illumos", target_os = "solaris", From 65532e71131869fac507e5791b7e49cb5d4cfe93 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Thu, 3 Oct 2024 22:44:14 +0100 Subject: [PATCH 032/357] update libc version --- library/std/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index 63c65b8ef39..aed3ca80d26 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -39,7 +39,7 @@ miniz_oxide = { version = "0.7.0", optional = true, default-features = false } addr2line = { version = "0.22.0", optional = true, default-features = false } [target.'cfg(not(all(windows, target_env = "msvc")))'.dependencies] -libc = { version = "0.2.156", default-features = false, features = [ +libc = { version = "0.2.159", default-features = false, features = [ 'rustc-dep-of-std', ], public = true } From 925e7e6baf435e68b463f9e31911d28118de318e Mon Sep 17 00:00:00 2001 From: ismailarilik Date: Sat, 5 Oct 2024 07:34:14 +0300 Subject: [PATCH 033/357] Handle `clippy` cases of `rustc::potential_query_instability` lint --- compiler/rustc_data_structures/src/unhash.rs | 1 + compiler/rustc_session/src/parse.rs | 2 +- .../clippy/clippy_lints/src/index_refutable_slice.rs | 4 ++-- src/tools/clippy/clippy_lints/src/lib.rs | 2 -- src/tools/clippy/clippy_lints/src/lifetimes.rs | 8 ++++---- .../clippy_lints/src/loops/needless_range_loop.rs | 6 +++--- .../src/matches/significant_drop_in_scrutinee.rs | 7 ++++--- .../clippy_lints/src/missing_asserts_for_indexing.rs | 10 +++++----- src/tools/clippy/clippy_lints/src/module_style.rs | 6 +++--- .../clippy_lints/src/needless_pass_by_ref_mut.rs | 10 +++++----- src/tools/clippy/clippy_lints/src/swap.rs | 4 ++-- src/tools/clippy/clippy_lints/src/trait_bounds.rs | 9 ++++----- 12 files changed, 34 insertions(+), 35 deletions(-) diff --git a/compiler/rustc_data_structures/src/unhash.rs b/compiler/rustc_data_structures/src/unhash.rs index 48e21a9dab1..0617ef83aad 100644 --- a/compiler/rustc_data_structures/src/unhash.rs +++ b/compiler/rustc_data_structures/src/unhash.rs @@ -3,6 +3,7 @@ use std::hash::{BuildHasherDefault, Hasher}; pub type UnhashMap = HashMap>; pub type UnhashSet = HashSet>; +pub type UnindexMap = indexmap::IndexMap>; /// This no-op hasher expects only a single `write_u64` call. It's intended for /// map keys that already have hash-like quality, like `Fingerprint`. diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index 9781c746520..3d44810e7dd 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -66,7 +66,7 @@ impl GatedSpans { #[derive(Default)] pub struct SymbolGallery { /// All symbols occurred and their first occurrence span. - pub symbols: Lock>, + pub symbols: Lock>, } impl SymbolGallery { diff --git a/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs b/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs index 73ebe6aec15..96550c4d1cb 100644 --- a/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs +++ b/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs @@ -5,7 +5,7 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::higher::IfLet; use clippy_utils::ty::is_copy; use clippy_utils::{is_expn_of, is_lint_allowed, path_to_local}; -use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; +use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::HirId; @@ -133,7 +133,7 @@ fn lint_slice(cx: &LateContext<'_>, slice: &SliceLintInformation) { .index_use .iter() .map(|(index, _)| *index) - .collect::>(); + .collect::>(); let value_name = |index| format!("{}_{index}", slice.ident.name); diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs index 2eb6d99b761..1a6d646e0df 100644 --- a/src/tools/clippy/clippy_lints/src/lib.rs +++ b/src/tools/clippy/clippy_lints/src/lib.rs @@ -27,8 +27,6 @@ unused_qualifications, rustc::internal )] -// Disable this rustc lint for now, as it was also done in rustc -#![allow(rustc::potential_query_instability)] // FIXME: switch to something more ergonomic here, once available. // (Currently there is no way to opt into sysroot crates without `extern crate`.) diff --git a/src/tools/clippy/clippy_lints/src/lifetimes.rs b/src/tools/clippy/clippy_lints/src/lifetimes.rs index 5c37e735445..0d151e299b2 100644 --- a/src/tools/clippy/clippy_lints/src/lifetimes.rs +++ b/src/tools/clippy/clippy_lints/src/lifetimes.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_then}; use clippy_utils::trait_ref_of_method; use itertools::Itertools; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_errors::Applicability; use rustc_hir::FnRetTy::Return; use rustc_hir::intravisit::nested_filter::{self as hir_nested_filter, NestedFilter}; @@ -311,7 +311,7 @@ fn could_use_elision<'tcx>( Some((elidable_lts, usages)) } -fn allowed_lts_from(named_generics: &[GenericParam<'_>]) -> FxHashSet { +fn allowed_lts_from(named_generics: &[GenericParam<'_>]) -> FxIndexSet { named_generics .iter() .filter_map(|par| { @@ -499,7 +499,7 @@ struct Usage { struct LifetimeChecker<'cx, 'tcx, F> { cx: &'cx LateContext<'tcx>, - map: FxHashMap>, + map: FxIndexMap>, where_predicate_depth: usize, generic_args_depth: usize, phantom: std::marker::PhantomData, @@ -621,7 +621,7 @@ fn report_extra_impl_lifetimes<'tcx>(cx: &LateContext<'tcx>, impl_: &'tcx Impl<' fn report_elidable_impl_lifetimes<'tcx>( cx: &LateContext<'tcx>, impl_: &'tcx Impl<'_>, - map: &FxHashMap>, + map: &FxIndexMap>, ) { let single_usages = map .iter() diff --git a/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs b/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs index 745f070a577..214b8b0f379 100644 --- a/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs @@ -5,7 +5,7 @@ use clippy_utils::ty::has_iter_method; use clippy_utils::visitors::is_local_used; use clippy_utils::{SpanlessEq, contains_name, higher, is_integer_const, sugg}; use rustc_ast::ast; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::{Visitor, walk_expr}; @@ -39,7 +39,7 @@ pub(super) fn check<'tcx>( var: canonical_id, indexed_mut: FxHashSet::default(), indexed_indirectly: FxHashMap::default(), - indexed_directly: FxHashMap::default(), + indexed_directly: FxIndexMap::default(), referenced: FxHashSet::default(), nonindex: false, prefer_mutable: false, @@ -229,7 +229,7 @@ struct VarVisitor<'a, 'tcx> { indexed_indirectly: FxHashMap>, /// subset of `indexed` of vars that are indexed directly: `v[i]` /// this will not contain cases like `v[calc_index(i)]` or `v[(i + 4) % N]` - indexed_directly: FxHashMap, Ty<'tcx>)>, + indexed_directly: FxIndexMap, Ty<'tcx>)>, /// Any names that are used outside an index operation. /// Used to detect things like `&mut vec` used together with `vec[i]` referenced: FxHashSet, diff --git a/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs b/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs index 7372f52e1e5..2ce6a8a85a5 100644 --- a/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs +++ b/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs @@ -7,6 +7,7 @@ use clippy_utils::ty::{for_each_top_level_late_bound_region, is_copy}; use clippy_utils::{get_attr, is_lint_allowed}; use itertools::Itertools; use rustc_ast::Mutability; +use rustc_data_structures::fx::FxIndexSet; use rustc_errors::{Applicability, Diag}; use rustc_hir::intravisit::{Visitor, walk_expr}; use rustc_hir::{Arm, Expr, ExprKind, MatchSource}; @@ -475,19 +476,19 @@ impl<'tcx> Visitor<'tcx> for SigDropHelper<'_, 'tcx> { struct ArmSigDropHelper<'a, 'tcx> { sig_drop_checker: SigDropChecker<'a, 'tcx>, - found_sig_drop_spans: FxHashSet, + found_sig_drop_spans: FxIndexSet, } impl<'a, 'tcx> ArmSigDropHelper<'a, 'tcx> { fn new(cx: &'a LateContext<'tcx>) -> ArmSigDropHelper<'a, 'tcx> { ArmSigDropHelper { sig_drop_checker: SigDropChecker::new(cx), - found_sig_drop_spans: FxHashSet::::default(), + found_sig_drop_spans: FxIndexSet::::default(), } } } -fn has_significant_drop_in_arms<'tcx>(cx: &LateContext<'tcx>, arms: &[&'tcx Expr<'_>]) -> FxHashSet { +fn has_significant_drop_in_arms<'tcx>(cx: &LateContext<'tcx>, arms: &[&'tcx Expr<'_>]) -> FxIndexSet { let mut helper = ArmSigDropHelper::new(cx); for arm in arms { helper.visit_expr(arm); diff --git a/src/tools/clippy/clippy_lints/src/missing_asserts_for_indexing.rs b/src/tools/clippy/clippy_lints/src/missing_asserts_for_indexing.rs index b40d7eba15e..c56a4014b34 100644 --- a/src/tools/clippy/clippy_lints/src/missing_asserts_for_indexing.rs +++ b/src/tools/clippy/clippy_lints/src/missing_asserts_for_indexing.rs @@ -8,7 +8,7 @@ use clippy_utils::visitors::for_each_expr_without_closures; use clippy_utils::{eq_expr_value, hash_expr, higher}; use rustc_ast::{LitKind, RangeLimits}; use rustc_data_structures::packed::Pu128; -use rustc_data_structures::unhash::UnhashMap; +use rustc_data_structures::unhash::UnindexMap; use rustc_errors::{Applicability, Diag}; use rustc_hir::{BinOp, Block, Body, Expr, ExprKind, UnOp}; use rustc_lint::{LateContext, LateLintPass}; @@ -226,7 +226,7 @@ fn upper_index_expr(expr: &Expr<'_>) -> Option { } /// Checks if the expression is an index into a slice and adds it to `indexes` -fn check_index<'hir>(cx: &LateContext<'_>, expr: &'hir Expr<'hir>, map: &mut UnhashMap>>) { +fn check_index<'hir>(cx: &LateContext<'_>, expr: &'hir Expr<'hir>, map: &mut UnindexMap>>) { if let ExprKind::Index(slice, index_lit, _) = expr.kind && cx.typeck_results().expr_ty_adjusted(slice).peel_refs().is_slice() && let Some(index) = upper_index_expr(index_lit) @@ -274,7 +274,7 @@ fn check_index<'hir>(cx: &LateContext<'_>, expr: &'hir Expr<'hir>, map: &mut Unh } /// Checks if the expression is an `assert!` expression and adds it to `asserts` -fn check_assert<'hir>(cx: &LateContext<'_>, expr: &'hir Expr<'hir>, map: &mut UnhashMap>>) { +fn check_assert<'hir>(cx: &LateContext<'_>, expr: &'hir Expr<'hir>, map: &mut UnindexMap>>) { if let Some((comparison, asserted_len, slice)) = assert_len_expr(cx, expr) { let hash = hash_expr(cx, slice); let indexes = map.entry(hash).or_default(); @@ -311,7 +311,7 @@ fn check_assert<'hir>(cx: &LateContext<'_>, expr: &'hir Expr<'hir>, map: &mut Un /// Inspects indexes and reports lints. /// /// Called at the end of this lint after all indexing and `assert!` expressions have been collected. -fn report_indexes(cx: &LateContext<'_>, map: &UnhashMap>>) { +fn report_indexes(cx: &LateContext<'_>, map: &UnindexMap>>) { for bucket in map.values() { for entry in bucket { let Some(full_span) = entry @@ -403,7 +403,7 @@ fn report_indexes(cx: &LateContext<'_>, map: &UnhashMap> impl LateLintPass<'_> for MissingAssertsForIndexing { fn check_body(&mut self, cx: &LateContext<'_>, body: &Body<'_>) { - let mut map = UnhashMap::default(); + let mut map = UnindexMap::default(); for_each_expr_without_closures(body.value, |expr| { check_index(cx, expr, &mut map); diff --git a/src/tools/clippy/clippy_lints/src/module_style.rs b/src/tools/clippy/clippy_lints/src/module_style.rs index e9c5f64a255..676d608eb31 100644 --- a/src/tools/clippy/clippy_lints/src/module_style.rs +++ b/src/tools/clippy/clippy_lints/src/module_style.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_then; use rustc_ast::ast; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; use rustc_lint::{EarlyContext, EarlyLintPass, Level, LintContext}; use rustc_session::impl_lint_pass; use rustc_span::def_id::LOCAL_CRATE; @@ -87,7 +87,7 @@ impl EarlyLintPass for ModStyle { // `folder_segments` is all unique folder path segments `path/to/foo.rs` gives // `[path, to]` but not foo - let mut folder_segments = FxHashSet::default(); + let mut folder_segments = FxIndexSet::default(); // `mod_folders` is all the unique folder names that contain a mod.rs file let mut mod_folders = FxHashSet::default(); // `file_map` maps file names to the full path including the file name @@ -144,7 +144,7 @@ impl EarlyLintPass for ModStyle { /// is `mod.rs` we add it's parent folder to `mod_folders`. fn process_paths_for_mod_files<'a>( path: &'a Path, - folder_segments: &mut FxHashSet<&'a OsStr>, + folder_segments: &mut FxIndexSet<&'a OsStr>, mod_folders: &mut FxHashSet<&'a OsStr>, ) { let mut comp = path.components().rev().peekable(); diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs index c2facb2fcf6..5c631a176c4 100644 --- a/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs +++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs @@ -5,7 +5,7 @@ use clippy_utils::source::snippet; use clippy_utils::visitors::for_each_expr; use clippy_utils::{inherits_cfg, is_from_proc_macro, is_self}; use core::ops::ControlFlow; -use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; +use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_errors::Applicability; use rustc_hir::intravisit::FnKind; use rustc_hir::{ @@ -101,7 +101,7 @@ fn check_closures<'tcx>( ctx: &mut MutablyUsedVariablesCtxt<'tcx>, cx: &LateContext<'tcx>, checked_closures: &mut FxHashSet, - closures: FxHashSet, + closures: FxIndexSet, ) { let hir = cx.tcx.hir(); for closure in closures { @@ -196,7 +196,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByRefMut<'tcx> { prev_bind: None, prev_move_to_closure: HirIdSet::default(), aliases: HirIdMap::default(), - async_closures: FxHashSet::default(), + async_closures: FxIndexSet::default(), tcx: cx.tcx, }; euv::ExprUseVisitor::for_clippy(cx, fn_def_id, &mut ctx) @@ -207,7 +207,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByRefMut<'tcx> { // We retrieve all the closures declared in the function because they will not be found // by `euv::Delegate`. - let mut closures: FxHashSet = FxHashSet::default(); + let mut closures: FxIndexSet = FxIndexSet::default(); for_each_expr(cx, body, |expr| { if let ExprKind::Closure(closure) = expr.kind { closures.insert(closure.def_id); @@ -307,7 +307,7 @@ struct MutablyUsedVariablesCtxt<'tcx> { /// use of a variable. prev_move_to_closure: HirIdSet, aliases: HirIdMap, - async_closures: FxHashSet, + async_closures: FxIndexSet, tcx: TyCtxt<'tcx>, } diff --git a/src/tools/clippy/clippy_lints/src/swap.rs b/src/tools/clippy/clippy_lints/src/swap.rs index a3145c4647c..6cba560393d 100644 --- a/src/tools/clippy/clippy_lints/src/swap.rs +++ b/src/tools/clippy/clippy_lints/src/swap.rs @@ -6,9 +6,9 @@ use clippy_utils::ty::is_type_diagnostic_item; use clippy_utils::{can_mut_borrow_both, eq_expr_value, is_in_const_context, std_or_core}; use itertools::Itertools; +use rustc_data_structures::fx::FxIndexSet; use rustc_hir::intravisit::{Visitor, walk_expr}; -use crate::FxHashSet; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Block, Expr, ExprKind, LetStmt, PatKind, QPath, Stmt, StmtKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; @@ -334,7 +334,7 @@ struct IndexBinding<'a, 'tcx> { impl<'tcx> IndexBinding<'_, 'tcx> { fn snippet_index_bindings(&mut self, exprs: &[&'tcx Expr<'tcx>]) -> String { - let mut bindings = FxHashSet::default(); + let mut bindings = FxIndexSet::default(); for expr in exprs { bindings.insert(self.snippet_index_binding(expr)); } diff --git a/src/tools/clippy/clippy_lints/src/trait_bounds.rs b/src/tools/clippy/clippy_lints/src/trait_bounds.rs index 00277593622..3c3973857e7 100644 --- a/src/tools/clippy/clippy_lints/src/trait_bounds.rs +++ b/src/tools/clippy/clippy_lints/src/trait_bounds.rs @@ -5,7 +5,7 @@ use clippy_utils::source::{SpanRangeExt, snippet, snippet_with_applicability}; use clippy_utils::{SpanlessEq, SpanlessHash, is_from_proc_macro}; use core::hash::{Hash, Hasher}; use itertools::Itertools; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, IndexEntry}; use rustc_data_structures::unhash::UnhashMap; use rustc_errors::Applicability; use rustc_hir::def::Res; @@ -16,7 +16,6 @@ use rustc_hir::{ use rustc_lint::{LateContext, LateLintPass}; use rustc_session::impl_lint_pass; use rustc_span::{BytePos, Span}; -use std::collections::hash_map::Entry; declare_clippy_lint! { /// ### What it does @@ -427,7 +426,7 @@ fn rollup_traits( bounds: &[GenericBound<'_>], msg: &'static str, ) -> Vec<(ComparableTraitRef, Span)> { - let mut map = FxHashMap::default(); + let mut map = FxIndexMap::default(); let mut repeated_res = false; let only_comparable_trait_refs = |bound: &GenericBound<'_>| { @@ -442,8 +441,8 @@ fn rollup_traits( for bound in bounds.iter().filter_map(only_comparable_trait_refs) { let (comparable_bound, span_direct) = bound; match map.entry(comparable_bound) { - Entry::Occupied(_) => repeated_res = true, - Entry::Vacant(e) => { + IndexEntry::Occupied(_) => repeated_res = true, + IndexEntry::Vacant(e) => { e.insert((span_direct, i)); i += 1; }, From 885ec88f936c39769486776ab002627f6559ff03 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 5 Oct 2024 17:21:08 +0200 Subject: [PATCH 034/357] avoid pthread_attr_t in tests --- .../concurrency/libc_pthread_create_main_terminate.rs | 7 ++++--- .../concurrency/libc_pthread_create_too_few_args.rs | 7 ++++--- .../concurrency/libc_pthread_create_too_many_args.rs | 7 ++++--- .../fail-dep/concurrency/libc_pthread_join_detached.rs | 7 ++++--- .../tests/fail-dep/concurrency/libc_pthread_join_joined.rs | 7 ++++--- .../fail-dep/concurrency/libc_pthread_join_multiple.rs | 7 ++++--- 6 files changed, 24 insertions(+), 18 deletions(-) diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_main_terminate.rs b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_main_terminate.rs index d4a9f076bfd..818a27fe66f 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_main_terminate.rs +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_main_terminate.rs @@ -12,8 +12,9 @@ extern "C" fn thread_start(_null: *mut libc::c_void) -> *mut libc::c_void { fn main() { unsafe { let mut native: libc::pthread_t = mem::zeroed(); - let attr: libc::pthread_attr_t = mem::zeroed(); - // assert_eq!(libc::pthread_attr_init(&mut attr), 0); FIXME: this function is not yet implemented. - assert_eq!(libc::pthread_create(&mut native, &attr, thread_start, ptr::null_mut()), 0); + assert_eq!( + libc::pthread_create(&mut native, ptr::null(), thread_start, ptr::null_mut()), + 0 + ); } } diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_too_few_args.rs b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_too_few_args.rs index d4accdba5d7..520bc9572f8 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_too_few_args.rs +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_too_few_args.rs @@ -12,12 +12,13 @@ extern "C" fn thread_start() -> *mut libc::c_void { fn main() { unsafe { let mut native: libc::pthread_t = mem::zeroed(); - let attr: libc::pthread_attr_t = mem::zeroed(); - // assert_eq!(libc::pthread_attr_init(&mut attr), 0); FIXME: this function is not yet implemented. let thread_start: extern "C" fn() -> *mut libc::c_void = thread_start; let thread_start: extern "C" fn(*mut libc::c_void) -> *mut libc::c_void = mem::transmute(thread_start); - assert_eq!(libc::pthread_create(&mut native, &attr, thread_start, ptr::null_mut()), 0); + assert_eq!( + libc::pthread_create(&mut native, ptr::null(), thread_start, ptr::null_mut()), + 0 + ); assert_eq!(libc::pthread_join(native, ptr::null_mut()), 0); } } diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_too_many_args.rs b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_too_many_args.rs index 0af3600854d..92d8a765e51 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_too_many_args.rs +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_too_many_args.rs @@ -12,12 +12,13 @@ extern "C" fn thread_start(_null: *mut libc::c_void, _x: i32) -> *mut libc::c_vo fn main() { unsafe { let mut native: libc::pthread_t = mem::zeroed(); - let attr: libc::pthread_attr_t = mem::zeroed(); - // assert_eq!(libc::pthread_attr_init(&mut attr), 0); FIXME: this function is not yet implemented. let thread_start: extern "C" fn(*mut libc::c_void, i32) -> *mut libc::c_void = thread_start; let thread_start: extern "C" fn(*mut libc::c_void) -> *mut libc::c_void = mem::transmute(thread_start); - assert_eq!(libc::pthread_create(&mut native, &attr, thread_start, ptr::null_mut()), 0); + assert_eq!( + libc::pthread_create(&mut native, ptr::null(), thread_start, ptr::null_mut()), + 0 + ); assert_eq!(libc::pthread_join(native, ptr::null_mut()), 0); } } diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_join_detached.rs b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_join_detached.rs index 472d07f617e..1c6bd629635 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_join_detached.rs +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_join_detached.rs @@ -11,9 +11,10 @@ extern "C" fn thread_start(_null: *mut libc::c_void) -> *mut libc::c_void { fn main() { unsafe { let mut native: libc::pthread_t = mem::zeroed(); - let attr: libc::pthread_attr_t = mem::zeroed(); - // assert_eq!(libc::pthread_attr_init(&mut attr), 0); FIXME: this function is not yet implemented. - assert_eq!(libc::pthread_create(&mut native, &attr, thread_start, ptr::null_mut()), 0); + assert_eq!( + libc::pthread_create(&mut native, ptr::null(), thread_start, ptr::null_mut()), + 0 + ); assert_eq!(libc::pthread_detach(native), 0); assert_eq!(libc::pthread_join(native, ptr::null_mut()), 0); //~ ERROR: Undefined Behavior: trying to join a detached thread } diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_join_joined.rs b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_join_joined.rs index 988c33868a6..b81214b217e 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_join_joined.rs +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_join_joined.rs @@ -11,9 +11,10 @@ extern "C" fn thread_start(_null: *mut libc::c_void) -> *mut libc::c_void { fn main() { unsafe { let mut native: libc::pthread_t = mem::zeroed(); - let attr: libc::pthread_attr_t = mem::zeroed(); - // assert_eq!(libc::pthread_attr_init(&mut attr), 0); FIXME: this function is not yet implemented. - assert_eq!(libc::pthread_create(&mut native, &attr, thread_start, ptr::null_mut()), 0); + assert_eq!( + libc::pthread_create(&mut native, ptr::null(), thread_start, ptr::null_mut()), + 0 + ); assert_eq!(libc::pthread_join(native, ptr::null_mut()), 0); assert_eq!(libc::pthread_join(native, ptr::null_mut()), 0); //~ ERROR: Undefined Behavior: trying to join an already joined thread } diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_join_multiple.rs b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_join_multiple.rs index b2a398e0a19..2f29731c6b3 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_join_multiple.rs +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_join_multiple.rs @@ -14,9 +14,10 @@ extern "C" fn thread_start(_null: *mut libc::c_void) -> *mut libc::c_void { fn main() { unsafe { let mut native: libc::pthread_t = mem::zeroed(); - let attr: libc::pthread_attr_t = mem::zeroed(); - // assert_eq!(libc::pthread_attr_init(&mut attr), 0); FIXME: this function is not yet implemented. - assert_eq!(libc::pthread_create(&mut native, &attr, thread_start, ptr::null_mut()), 0); + assert_eq!( + libc::pthread_create(&mut native, ptr::null(), thread_start, ptr::null_mut()), + 0 + ); let mut native_copy: libc::pthread_t = mem::zeroed(); ptr::copy_nonoverlapping(&native, &mut native_copy, 1); let handle = thread::spawn(move || { From 35eb2da229a6698c799febf9792fb52911d864cd Mon Sep 17 00:00:00 2001 From: Yoh Deadfall Date: Thu, 3 Oct 2024 22:27:17 +0300 Subject: [PATCH 035/357] Added rust-analyzer instructions for Helix --- src/tools/miri/CONTRIBUTING.md | 68 +++++++++----------- src/tools/miri/etc/rust_analyzer_helix.toml | 32 +++++++++ src/tools/miri/etc/rust_analyzer_vscode.json | 27 ++++++++ 3 files changed, 90 insertions(+), 37 deletions(-) create mode 100644 src/tools/miri/etc/rust_analyzer_helix.toml create mode 100644 src/tools/miri/etc/rust_analyzer_vscode.json diff --git a/src/tools/miri/CONTRIBUTING.md b/src/tools/miri/CONTRIBUTING.md index ca03a9b16e3..362924d89d3 100644 --- a/src/tools/miri/CONTRIBUTING.md +++ b/src/tools/miri/CONTRIBUTING.md @@ -195,48 +195,42 @@ installed (`cargo install hyperfine`). ## Configuring `rust-analyzer` -To configure `rust-analyzer` and VS Code for working on Miri, save the following -to `.vscode/settings.json` in your local Miri clone: +To configure `rust-analyzer` and the IDE for working on Miri, use one of the provided +configuration files according to the instructions below. -```json -{ - "rust-analyzer.rustc.source": "discover", - "rust-analyzer.linkedProjects": [ - "Cargo.toml", - "cargo-miri/Cargo.toml", - "miri-script/Cargo.toml", - ], - "rust-analyzer.check.invocationLocation": "root", - "rust-analyzer.check.invocationStrategy": "once", - "rust-analyzer.check.overrideCommand": [ - "env", - "MIRI_AUTO_OPS=no", - "./miri", - "clippy", // make this `check` when working with a locally built rustc - "--message-format=json", - ], - // Contrary to what the name suggests, this also affects proc macros. - "rust-analyzer.cargo.buildScripts.invocationLocation": "root", - "rust-analyzer.cargo.buildScripts.invocationStrategy": "once", - "rust-analyzer.cargo.buildScripts.overrideCommand": [ - "env", - "MIRI_AUTO_OPS=no", - "./miri", - "check", - "--message-format=json", - ], -} -``` -> #### Note +### Visual Studio Code + +Copy [`etc/rust_analyzer_vscode.json`] to `.vscode/settings.json` in the project root directory. + +> #### Hint > -> If you are [building Miri with a locally built rustc][], set -> `rust-analyzer.rustcSource` to the relative path from your Miri clone to the -> root `Cargo.toml` of the locally built rustc. For example, the path might look -> like `../rust/Cargo.toml`. +> To keep the `rust-analyzer` configuration up-to-date, make a symbolic link to one +> of the provided files depending on the IDE you use. + +[`etc/rust_analyzer_vscode.json`]: https://github.com/rust-lang/miri/blob/master/etc/rust_analyzer_vscode.json + +### Helix + +Copy [`etc/rust_analyzer_helix.toml`] to `.helix/languages.toml` in the project root directory. + +Since working on Miri requires a custom toolchain, and Helix requires the language server +to be installed with the toolchain, you have to run `./miri toolchain -c rust-analyzer` +when installing the Miri toolchain. Alternatively, set the `RUSTUP_TOOLCHAIN` environment variable according to +[the documentation](https://rust-analyzer.github.io/manual.html#toolchain). + +[`etc/rust_analyzer_helix.toml`]: https://github.com/rust-lang/miri/blob/master/etc/rust_analyzer_helix.toml + +### Advanced configuration + +If you are building Miri with a locally built rustc, set +`rust-analyzer.rustcSource` to the relative path from your Miri clone to the +root `Cargo.toml` of the locally built rustc. For example, the path might look +like `../rust/Cargo.toml`. In addition to that, replace `clippy` by `check` +in the `rust-analyzer.check.overrideCommand` setting. See the rustc-dev-guide's docs on ["Configuring `rust-analyzer` for `rustc`"][rdg-r-a] -for more information about configuring VS Code and `rust-analyzer`. +for more information about configuring the IDE and `rust-analyzer`. [rdg-r-a]: https://rustc-dev-guide.rust-lang.org/building/suggested.html#configuring-rust-analyzer-for-rustc diff --git a/src/tools/miri/etc/rust_analyzer_helix.toml b/src/tools/miri/etc/rust_analyzer_helix.toml new file mode 100644 index 00000000000..62db463a191 --- /dev/null +++ b/src/tools/miri/etc/rust_analyzer_helix.toml @@ -0,0 +1,32 @@ +[language-server.rust-analyzer.config.rustc] +source = "discover" + +[language-server.rust-analyzer.config] +linkedProjects = [ + "Cargo.toml", + "cargo-miri/Cargo.toml", + "miri-script/Cargo.toml", +] + +[language-server.rust-analyzer.config.check] +invocationLocation = "root" +invocationStrategy = "once" +overrideCommand = [ + "env", + "MIRI_AUTO_OPS=no", + "./miri", + "clippy", # make this `check` when working with a locally built rustc + "--message-format=json", +] + +# Contrary to what the name suggests, this also affects proc macros. +[language-server.rust-analyzer.config.buildScripts] +invocationLocation = "root" +invocationStrategy = "once" +overrideCommand = [ + "env", + "MIRI_AUTO_OPS=no", + "./miri", + "check", + "--message-format=json", +] diff --git a/src/tools/miri/etc/rust_analyzer_vscode.json b/src/tools/miri/etc/rust_analyzer_vscode.json new file mode 100644 index 00000000000..5e51c3e8880 --- /dev/null +++ b/src/tools/miri/etc/rust_analyzer_vscode.json @@ -0,0 +1,27 @@ +{ + "rust-analyzer.rustc.source": "discover", + "rust-analyzer.linkedProjects": [ + "Cargo.toml", + "cargo-miri/Cargo.toml", + "miri-script/Cargo.toml", + ], + "rust-analyzer.check.invocationLocation": "root", + "rust-analyzer.check.invocationStrategy": "once", + "rust-analyzer.check.overrideCommand": [ + "env", + "MIRI_AUTO_OPS=no", + "./miri", + "clippy", // make this `check` when working with a locally built rustc + "--message-format=json", + ], + // Contrary to what the name suggests, this also affects proc macros. + "rust-analyzer.cargo.buildScripts.invocationLocation": "root", + "rust-analyzer.cargo.buildScripts.invocationStrategy": "once", + "rust-analyzer.cargo.buildScripts.overrideCommand": [ + "env", + "MIRI_AUTO_OPS=no", + "./miri", + "check", + "--message-format=json", + ], +} From 0b00a54976cfa70b47dbb897db6066cb9557813c Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Fri, 4 Oct 2024 18:22:54 -0700 Subject: [PATCH 036/357] library: Stabilize const `MaybeUninit::assume_init_mut` Co-authored-by: Ralf Jung --- library/core/src/lib.rs | 1 - library/core/src/mem/maybe_uninit.rs | 9 +++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 65721800ea8..4b161ce132a 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -131,7 +131,6 @@ #![feature(const_ipv6)] #![feature(const_likely)] #![feature(const_make_ascii)] -#![feature(const_maybe_uninit_assume_init)] #![feature(const_nonnull_new)] #![feature(const_num_midpoint)] #![feature(const_option)] diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index c67796ad3db..f992785c43b 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -913,7 +913,11 @@ impl MaybeUninit { /// }; /// ``` #[stable(feature = "maybe_uninit_ref", since = "1.55.0")] - #[rustc_const_unstable(feature = "const_maybe_uninit_assume_init", issue = "none")] + #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] + #[rustc_const_stable( + feature = "const_maybe_uninit_assume_init", + since = "CURRENT_RUSTC_VERSION" + )] #[inline(always)] pub const unsafe fn assume_init_mut(&mut self) -> &mut T { // SAFETY: the caller must guarantee that `self` is initialized. @@ -999,7 +1003,8 @@ impl MaybeUninit { /// /// [`assume_init_mut`]: MaybeUninit::assume_init_mut #[unstable(feature = "maybe_uninit_slice", issue = "63569")] - #[rustc_const_unstable(feature = "const_maybe_uninit_assume_init", issue = "none")] + #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] + #[rustc_const_unstable(feature = "maybe_uninit_slice", issue = "63569")] #[inline(always)] pub const unsafe fn slice_assume_init_mut(slice: &mut [Self]) -> &mut [T] { // SAFETY: similar to safety notes for `slice_get_ref`, but we have a From 3743618c13d9f4afb06c9778b05b75e879b6919c Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Sun, 6 Oct 2024 08:14:44 +0900 Subject: [PATCH 037/357] Support clobber_abi in MSP430 inline assembly --- compiler/rustc_target/src/asm/mod.rs | 10 ++++++++ tests/codegen/asm-msp430-clobbers.rs | 36 ++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 tests/codegen/asm-msp430-clobbers.rs diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs index df13d24cb9e..73ae1ae96ae 100644 --- a/compiler/rustc_target/src/asm/mod.rs +++ b/compiler/rustc_target/src/asm/mod.rs @@ -893,6 +893,7 @@ pub enum InlineAsmClobberAbi { RiscV, LoongArch, S390x, + Msp430, } impl InlineAsmClobberAbi { @@ -946,6 +947,10 @@ impl InlineAsmClobberAbi { "C" | "system" => Ok(InlineAsmClobberAbi::S390x), _ => Err(&["C", "system"]), }, + InlineAsmArch::Msp430 => match name { + "C" | "system" => Ok(InlineAsmClobberAbi::Msp430), + _ => Err(&["C", "system"]), + }, _ => Err(&[]), } } @@ -1125,6 +1130,11 @@ impl InlineAsmClobberAbi { a8, a9, a10, a11, a12, a13, a14, a15, } }, + InlineAsmClobberAbi::Msp430 => clobbered_regs! { + Msp430 Msp430InlineAsmReg { + r11, r12, r13, r14, r15, + } + }, } } } diff --git a/tests/codegen/asm-msp430-clobbers.rs b/tests/codegen/asm-msp430-clobbers.rs new file mode 100644 index 00000000000..c00c04f3088 --- /dev/null +++ b/tests/codegen/asm-msp430-clobbers.rs @@ -0,0 +1,36 @@ +//@ assembly-output: emit-asm +//@ compile-flags: --target msp430-none-elf +//@ needs-llvm-components: msp430 + +#![crate_type = "rlib"] +#![feature(no_core, rustc_attrs, lang_items, asm_experimental_arch)] +#![no_core] + +#[lang = "sized"] +trait Sized {} + +#[rustc_builtin_macro] +macro_rules! asm { + () => {}; +} + +// CHECK-LABEL: @sr_clobber +// CHECK: call void asm sideeffect "", "~{sr}"() +#[no_mangle] +pub unsafe fn sr_clobber() { + asm!("", options(nostack, nomem)); +} + +// CHECK-LABEL: @no_clobber +// CHECK: call void asm sideeffect "", ""() +#[no_mangle] +pub unsafe fn no_clobber() { + asm!("", options(nostack, nomem, preserves_flags)); +} + +// CHECK-LABEL: @clobber_abi +// CHECK: asm sideeffect "", "={r11},={r12},={r13},={r14},={r15}"() +#[no_mangle] +pub unsafe fn clobber_abi() { + asm!("", clobber_abi("C"), options(nostack, nomem, preserves_flags)); +} From 8a5e03bf438ddc990ab311bc63d7c15b2f21f5a8 Mon Sep 17 00:00:00 2001 From: WANG Rui Date: Fri, 13 Sep 2024 14:30:22 +0800 Subject: [PATCH 038/357] Enable sanitizers for loongarch64-unknown-* --- .../src/spec/targets/loongarch64_unknown_linux_gnu.rs | 7 ++++++- .../src/spec/targets/loongarch64_unknown_linux_musl.rs | 7 ++++++- .../src/spec/targets/loongarch64_unknown_linux_ohos.rs | 7 ++++++- src/bootstrap/src/core/build_steps/llvm.rs | 3 +++ .../docker/host-x86_64/dist-loongarch64-linux/Dockerfile | 1 + src/ci/docker/host-x86_64/dist-loongarch64-musl/Dockerfile | 1 + 6 files changed, 23 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_gnu.rs index de8d99977b4..e869314d4d8 100644 --- a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_gnu.rs @@ -1,4 +1,4 @@ -use crate::spec::{CodeModel, Target, TargetOptions, base}; +use crate::spec::{CodeModel, SanitizerSet, Target, TargetOptions, base}; pub(crate) fn target() -> Target { Target { @@ -18,6 +18,11 @@ pub(crate) fn target() -> Target { features: "+f,+d".into(), llvm_abiname: "lp64d".into(), max_atomic_width: Some(64), + supported_sanitizers: SanitizerSet::ADDRESS + | SanitizerSet::CFI + | SanitizerSet::LEAK + | SanitizerSet::MEMORY + | SanitizerSet::THREAD, direct_access_external_data: Some(false), ..base::linux_gnu::opts() }, diff --git a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_musl.rs index a5088bcd5c2..70e8bf633a9 100644 --- a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_musl.rs @@ -1,4 +1,4 @@ -use crate::spec::{CodeModel, Target, TargetOptions, base}; +use crate::spec::{CodeModel, SanitizerSet, Target, TargetOptions, base}; pub(crate) fn target() -> Target { Target { @@ -19,6 +19,11 @@ pub(crate) fn target() -> Target { llvm_abiname: "lp64d".into(), max_atomic_width: Some(64), crt_static_default: false, + supported_sanitizers: SanitizerSet::ADDRESS + | SanitizerSet::CFI + | SanitizerSet::LEAK + | SanitizerSet::MEMORY + | SanitizerSet::THREAD, ..base::linux_musl::opts() }, } diff --git a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_ohos.rs b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_ohos.rs index 32a856be669..90bcd9a45cf 100644 --- a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_ohos.rs +++ b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_ohos.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions, base}; +use crate::spec::{SanitizerSet, Target, TargetOptions, base}; pub(crate) fn target() -> Target { Target { @@ -17,6 +17,11 @@ pub(crate) fn target() -> Target { features: "+f,+d".into(), llvm_abiname: "lp64d".into(), max_atomic_width: Some(64), + supported_sanitizers: SanitizerSet::ADDRESS + | SanitizerSet::CFI + | SanitizerSet::LEAK + | SanitizerSet::MEMORY + | SanitizerSet::THREAD, ..base::linux_ohos::opts() }, } diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index 30213584157..c64ca730698 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -1215,6 +1215,9 @@ fn supported_sanitizers( "aarch64-unknown-linux-ohos" => { common_libs("linux", "aarch64", &["asan", "lsan", "msan", "tsan", "hwasan"]) } + "loongarch64-unknown-linux-gnu" | "loongarch64-unknown-linux-musl" => { + common_libs("linux", "loongarch64", &["asan", "lsan", "msan", "tsan"]) + } "x86_64-apple-darwin" => darwin_libs("osx", &["asan", "lsan", "tsan"]), "x86_64-unknown-fuchsia" => common_libs("fuchsia", "x86_64", &["asan"]), "x86_64-apple-ios" => darwin_libs("iossim", &["asan", "tsan"]), diff --git a/src/ci/docker/host-x86_64/dist-loongarch64-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-loongarch64-linux/Dockerfile index 865a9e32fa9..71eb72686b0 100644 --- a/src/ci/docker/host-x86_64/dist-loongarch64-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-loongarch64-linux/Dockerfile @@ -47,6 +47,7 @@ ENV RUST_CONFIGURE_ARGS \ --enable-extended \ --enable-full-tools \ --enable-profiler \ + --enable-sanitizers \ --disable-docs ENV SCRIPT python3 ../x.py dist --host $HOSTS --target $TARGETS diff --git a/src/ci/docker/host-x86_64/dist-loongarch64-musl/Dockerfile b/src/ci/docker/host-x86_64/dist-loongarch64-musl/Dockerfile index 62dbfaaa673..5081f25e567 100644 --- a/src/ci/docker/host-x86_64/dist-loongarch64-musl/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-loongarch64-musl/Dockerfile @@ -29,6 +29,7 @@ ENV RUST_CONFIGURE_ARGS \ --enable-extended \ --enable-full-tools \ --enable-profiler \ + --enable-sanitizers \ --disable-docs \ --set target.loongarch64-unknown-linux-musl.crt-static=false \ --musl-root-loongarch64=/x-tools/loongarch64-unknown-linux-musl/loongarch64-unknown-linux-musl/sysroot/usr From 6f84740b54c73de94c61a8975f916715d063c905 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 6 Oct 2024 08:27:13 +0200 Subject: [PATCH 039/357] tweak the hint --- src/tools/miri/CONTRIBUTING.md | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/tools/miri/CONTRIBUTING.md b/src/tools/miri/CONTRIBUTING.md index 362924d89d3..7a32962886c 100644 --- a/src/tools/miri/CONTRIBUTING.md +++ b/src/tools/miri/CONTRIBUTING.md @@ -195,19 +195,14 @@ installed (`cargo install hyperfine`). ## Configuring `rust-analyzer` -To configure `rust-analyzer` and the IDE for working on Miri, use one of the provided -configuration files according to the instructions below. - +To configure `rust-analyzer` and the IDE for working on Miri, copy one of the provided +configuration files according to the instructions below. You can also set up a symbolic +link to keep the configuration in sync with our recommendations. ### Visual Studio Code Copy [`etc/rust_analyzer_vscode.json`] to `.vscode/settings.json` in the project root directory. -> #### Hint -> -> To keep the `rust-analyzer` configuration up-to-date, make a symbolic link to one -> of the provided files depending on the IDE you use. - [`etc/rust_analyzer_vscode.json`]: https://github.com/rust-lang/miri/blob/master/etc/rust_analyzer_vscode.json ### Helix From a0e687f0348af5d269c8ba0ac9bbb52308850c6a Mon Sep 17 00:00:00 2001 From: ismailarilik Date: Sun, 6 Oct 2024 15:57:23 +0300 Subject: [PATCH 040/357] Remove unnecessary sorts in `rustc_hir_analysis`. This is an attempt to gain the performance loss after the PR #131140. Here the related objects are `IndexSet` so do not require a sort to stay stable. --- compiler/rustc_hir_analysis/src/check/wfcheck.rs | 5 +---- .../src/coherence/inherent_impls_overlap.rs | 4 +--- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 3a9d2640eee..3079fd71b0c 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -531,7 +531,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, trait_def_id: LocalDefId) { debug!(?required_bounds); let param_env = tcx.param_env(gat_def_id); - let mut unsatisfied_bounds: Vec<_> = required_bounds + let unsatisfied_bounds: Vec<_> = required_bounds .into_iter() .filter(|clause| match clause.kind().skip_binder() { ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(a, b)) => { @@ -552,9 +552,6 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, trait_def_id: LocalDefId) { .map(|clause| clause.to_string()) .collect(); - // We sort so that order is predictable - unsatisfied_bounds.sort(); - if !unsatisfied_bounds.is_empty() { let plural = pluralize!(unsatisfied_bounds.len()); let suggestion = format!( diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs index d1c888a185e..5127e73d978 100644 --- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs +++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs @@ -319,9 +319,7 @@ impl<'tcx> InherentOverlapChecker<'tcx> { // List of connected regions is built. Now, run the overlap check // for each pair of impl blocks in the same connected region. for region in connected_regions.into_iter().flatten() { - let mut impl_blocks = - region.impl_blocks.into_iter().collect::>(); - impl_blocks.sort_unstable(); + let impl_blocks = region.impl_blocks.into_iter().collect::>(); for (i, &impl1_items_idx) in impl_blocks.iter().enumerate() { let &(&impl1_def_id, impl_items1) = &impls_items[impl1_items_idx]; res = res.and(self.check_for_duplicate_items_in_impl(impl1_def_id)); From 2bd0d070ed7733a827ef46d3e4a2430a7a5aaed3 Mon Sep 17 00:00:00 2001 From: Andreas Molzer Date: Sun, 6 Oct 2024 21:32:04 +0200 Subject: [PATCH 041/357] Expand set_ptr_value / with_metadata_of docs Rewrite these blobs to explicitly mention the case of a sized operand. The previous made that seem wrong instead of emphasizing it is nothing but a simple cast. Instead, the explanation now emphasizes that the address portion of the argument, together with its provenance, is discarded which previously had to be inferred by the reader. Then an example demonstrates a simple line of incorrect usage based on this idea of provenance. --- library/core/src/ptr/const_ptr.rs | 41 +++++++++++++++++++++++-------- library/core/src/ptr/mut_ptr.rs | 40 ++++++++++++++++++++++-------- 2 files changed, 61 insertions(+), 20 deletions(-) diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 332c5e904d7..7b91b1bcb3b 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -63,21 +63,22 @@ impl *const T { self as _ } - /// Uses the pointer value in a new pointer of another type. + /// Uses the address value in a new pointer of another type. /// - /// In case `meta` is a (fat) pointer to an unsized type, this operation - /// will ignore the pointer part, whereas for (thin) pointers to sized - /// types, this has the same effect as a simple cast. + /// This operation will ignore the address part of its `meta` operand and discard existing + /// metadata of `self`. For pointers to a sized types (thin pointers), this has the same effect + /// as a simple cast. For pointers to an unsized type (fat pointers) this recombines the address + /// with new metadata such as slice lengths or `dyn`-vtable. /// - /// The resulting pointer will have provenance of `self`, i.e., for a fat - /// pointer, this operation is semantically the same as creating a new - /// fat pointer with the data pointer value of `self` but the metadata of - /// `meta`. + /// The resulting pointer will have provenance of `self`. This operation is semantically the + /// same as creating a new pointer with the data pointer value of `self` but the metadata of + /// `meta`, being fat or thing depending on the `meta` operand. /// /// # Examples /// - /// This function is primarily useful for allowing byte-wise pointer - /// arithmetic on potentially fat pointers: + /// This function is primarily useful for enabling pointer arithmetic on potentially fat + /// pointers. The pointer is cast to a sized pointee to utilize offset operations and then + /// recombined with its own original metadata. /// /// ``` /// #![feature(set_ptr_value)] @@ -91,6 +92,26 @@ impl *const T { /// println!("{:?}", &*ptr); // will print "3" /// } /// ``` + /// + /// # *Incorrect* usage + /// + /// The provenance from pointers is *not* combined. The result must only be used to refer to the + /// address allowed by `self`. + /// + /// ```rust,no_run + /// #![feature(set_ptr_value)] + /// let x = 0u32; + /// let y = 1u32; + /// + /// let x = (&x) as *const u32; + /// let y = (&y) as *const u32; + /// + /// let offset = (x as usize - y as usize) / 4; + /// let bad = x.wrapping_add(offset).with_metadata_of(y); + /// + /// // This dereference is UB. The pointer only has provenance for `x` but points to `y`. + /// println!("{:?}", unsafe { &*bad }); + /// ``` #[unstable(feature = "set_ptr_value", issue = "75091")] #[rustc_const_stable(feature = "ptr_metadata_const", since = "CURRENT_RUSTC_VERSION")] #[must_use = "returns a new pointer rather than modifying its argument"] diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 287073497f8..e1a181158af 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -45,21 +45,22 @@ impl *mut T { self as _ } - /// Uses the pointer value in a new pointer of another type. + /// Uses the address value in a new pointer of another type. /// - /// In case `meta` is a (fat) pointer to an unsized type, this operation - /// will ignore the pointer part, whereas for (thin) pointers to sized - /// types, this has the same effect as a simple cast. + /// This operation will ignore the address part of its `meta` operand and discard existing + /// metadata of `self`. For pointers to a sized types (thin pointers), this has the same effect + /// as a simple cast. For pointers to an unsized type (fat pointers) this recombines the address + /// with new metadata such as slice lengths or `dyn`-vtable. /// - /// The resulting pointer will have provenance of `self`, i.e., for a fat - /// pointer, this operation is semantically the same as creating a new - /// fat pointer with the data pointer value of `self` but the metadata of - /// `meta`. + /// The resulting pointer will have provenance of `self`. This operation is semantically the + /// same as creating a new pointer with the data pointer value of `self` but the metadata of + /// `meta`, being fat or thing depending on the `meta` operand. /// /// # Examples /// - /// This function is primarily useful for allowing byte-wise pointer - /// arithmetic on potentially fat pointers: + /// This function is primarily useful for enabling pointer arithmetic on potentially fat + /// pointers. The pointer is cast to a sized pointee to utilize offset operations and then + /// recombined with its own original metadata. /// /// ``` /// #![feature(set_ptr_value)] @@ -73,6 +74,25 @@ impl *mut T { /// println!("{:?}", &*ptr); // will print "3" /// } /// ``` + /// + /// # *Incorrect* usage + /// + /// The provenance from pointers is *not* combined. The result must only be used to refer to the + /// address allowed by `self`. + /// + /// ```rust,no_run + /// #![feature(set_ptr_value)] + /// let mut x = 0u32; + /// let mut y = 1u32; + /// + /// let x = (&mut x) as *mut u32; + /// let y = (&mut y) as *mut u32; + /// + /// let offset = (x as usize - y as usize) / 4; + /// let bad = x.wrapping_add(offset).with_metadata_of(y); + /// + /// // This dereference is UB. The pointer only has provenance for `x` but points to `y`. + /// println!("{:?}", unsafe { &*bad }); #[unstable(feature = "set_ptr_value", issue = "75091")] #[rustc_const_stable(feature = "ptr_metadata_const", since = "CURRENT_RUSTC_VERSION")] #[must_use = "returns a new pointer rather than modifying its argument"] From 126cb9bb78854f10310129869a583536a947517c Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 7 Oct 2024 18:41:32 +0200 Subject: [PATCH 042/357] Remove dead code --- src/librustdoc/html/markdown.rs | 49 +------------- .../passes/collect_intra_doc_links.rs | 67 ------------------- 2 files changed, 1 insertion(+), 115 deletions(-) diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index b18d621478c..b86fbf77e59 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -35,8 +35,7 @@ use std::str::{self, CharIndices}; use std::sync::OnceLock; use pulldown_cmark::{ - BrokenLink, BrokenLinkCallback, CodeBlockKind, CowStr, Event, LinkType, OffsetIter, Options, - Parser, Tag, TagEnd, html, + BrokenLink, CodeBlockKind, CowStr, Event, LinkType, Options, Parser, Tag, TagEnd, html, }; use rustc_data_structures::fx::FxHashMap; use rustc_errors::{Diag, DiagMessage}; @@ -1683,7 +1682,6 @@ pub(crate) fn html_text_from_events<'a>( pub(crate) struct MarkdownLink { pub kind: LinkType, pub link: String, - pub display_text: Option, pub range: MarkdownLinkRange, } @@ -1845,23 +1843,9 @@ pub(crate) fn markdown_links<'md, R>( LinkType::Autolink | LinkType::Email => unreachable!(), }; - let display_text = if matches!( - link_type, - LinkType::Inline - | LinkType::ReferenceUnknown - | LinkType::Reference - | LinkType::Shortcut - | LinkType::ShortcutUnknown - ) { - collect_link_data(&mut event_iter) - } else { - None - }; - if let Some(link) = preprocess_link(MarkdownLink { kind: link_type, link: dest_url.into_string(), - display_text, range, }) { links.push(link); @@ -1874,37 +1858,6 @@ pub(crate) fn markdown_links<'md, R>( links } -/// Collects additional data of link. -fn collect_link_data<'input, F: BrokenLinkCallback<'input>>( - event_iter: &mut OffsetIter<'input, F>, -) -> Option { - let mut display_text: Option = None; - let mut append_text = |text: CowStr<'_>| { - if let Some(display_text) = &mut display_text { - display_text.push_str(&text); - } else { - display_text = Some(text.to_string()); - } - }; - - while let Some((event, _span)) = event_iter.next() { - match event { - Event::Text(text) => { - append_text(text); - } - Event::Code(code) => { - append_text(code); - } - Event::End(_) => { - break; - } - _ => {} - } - } - - display_text -} - #[derive(Debug)] pub(crate) struct RustCodeBlock { /// The range in the markdown that the code block occupies. Note that this includes the fences diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index e95e8762b1d..2656612a13e 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -1028,21 +1028,6 @@ impl LinkCollector<'_, '_> { false, )?; - if ori_link.display_text.is_some() { - self.resolve_display_text( - path_str, - ResolutionInfo { - item_id, - module_id, - dis: disambiguator, - path_str: ori_link.display_text.clone()?.into_boxed_str(), - extra_fragment: extra_fragment.clone(), - }, - &ori_link, - &diag_info, - ); - } - // Check for a primitive which might conflict with a module // Report the ambiguity and require that the user specify which one they meant. // FIXME: could there ever be a primitive not in the type namespace? @@ -1385,58 +1370,6 @@ impl LinkCollector<'_, '_> { } } } - - /// Resolve display text if the provided link has separated parts of links. - /// - /// For example: - /// Inline link `[display_text](dest_link)` and reference link `[display_text][reference_link]` has - /// separated parts of links. - fn resolve_display_text( - &mut self, - explicit_link: &Box, - display_res_info: ResolutionInfo, - ori_link: &MarkdownLink, - diag_info: &DiagnosticInfo<'_>, - ) { - // Check if explicit resolution's path is same as resolution of original link's display text path, see - // tests/rustdoc-ui/lint/redundant_explicit_links.rs for more cases. - // - // To avoid disambiguator from panicking, we check if display text path is possible to be disambiguated - // into explicit path. - if !matches!( - ori_link.kind, - LinkType::Inline | LinkType::Reference | LinkType::ReferenceUnknown - ) { - return; - } - - // Algorithm to check if display text could possibly be the explicit link: - // - // Consider 2 links which are display text and explicit link, pick the shorter - // one as symbol and longer one as full qualified path, and tries to match symbol - // to the full qualified path's last symbol. - // - // Otherwise, check if 2 links are same, if so, skip the resolve process. - // - // Notice that this algorithm is passive, might possibly miss actual redundant cases. - let explicit_link = explicit_link.to_string(); - let display_text = ori_link.display_text.as_ref().unwrap(); - - if display_text.len() == explicit_link.len() { - // Whether they are same or not, skip the resolve process. - return; - } - - if explicit_link.ends_with(&display_text[..]) || display_text.ends_with(&explicit_link[..]) - { - self.resolve_with_disambiguator_cached( - display_res_info, - diag_info.clone(), // this struct should really be Copy, but Range is not :( - false, - true, - ); - } - } } /// Get the section of a link between the backticks, From bf2d46dedb7f4e390e345970dfbd111d780750ad Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 7 Oct 2024 19:57:40 +0200 Subject: [PATCH 043/357] bump rustc_tools_util version --- src/tools/miri/cargo-miri/Cargo.lock | 6 +++--- src/tools/miri/cargo-miri/Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/tools/miri/cargo-miri/Cargo.lock b/src/tools/miri/cargo-miri/Cargo.lock index a873472fd5d..b8e08d39a86 100644 --- a/src/tools/miri/cargo-miri/Cargo.lock +++ b/src/tools/miri/cargo-miri/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "anyhow" @@ -202,9 +202,9 @@ dependencies = [ [[package]] name = "rustc_tools_util" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ba09476327c4b70ccefb6180f046ef588c26a24cf5d269a9feba316eb4f029f" +checksum = "3316159ab19e19d1065ecc49278e87f767a9dae9fae80348d2b4d4fa4ae02d4d" [[package]] name = "rustc_version" diff --git a/src/tools/miri/cargo-miri/Cargo.toml b/src/tools/miri/cargo-miri/Cargo.toml index ee2004278b4..de0988d6d1c 100644 --- a/src/tools/miri/cargo-miri/Cargo.toml +++ b/src/tools/miri/cargo-miri/Cargo.toml @@ -26,4 +26,4 @@ rustc-build-sysroot = "0.5.4" serde = { version = "1.0.185", features = ["derive"] } [build-dependencies] -rustc_tools_util = "0.3" +rustc_tools_util = "0.4" From ae698f819935aae8623f41aa3837cc0a07903c1a Mon Sep 17 00:00:00 2001 From: Eric Holk Date: Fri, 20 Sep 2024 12:09:18 -0700 Subject: [PATCH 044/357] Add sugar for &pin (const|mut) types --- compiler/rustc_ast/src/ast.rs | 11 +++- compiler/rustc_ast/src/mut_visit.rs | 2 +- compiler/rustc_ast/src/util/classify.rs | 4 +- compiler/rustc_ast/src/visit.rs | 3 +- compiler/rustc_ast_ir/src/lib.rs | 7 +++ compiler/rustc_ast_lowering/src/expr.rs | 5 +- compiler/rustc_ast_lowering/src/lib.rs | 51 ++++++++++++++++--- .../src/lifetime_collector.rs | 2 +- compiler/rustc_ast_passes/src/feature_gate.rs | 1 + compiler/rustc_ast_pretty/src/pprust/state.rs | 6 +++ compiler/rustc_hir/src/hir.rs | 5 +- compiler/rustc_parse/src/parser/ty.rs | 39 ++++++++++++-- compiler/rustc_passes/src/hir_stats.rs | 50 +++++++++--------- compiler/rustc_resolve/src/late.rs | 4 +- .../rustc_resolve/src/late/diagnostics.rs | 2 +- .../clippy/clippy_utils/src/ast_utils.rs | 3 ++ src/tools/rustfmt/src/types.rs | 5 +- tests/ui/async-await/pin-sugar-ambiguity.rs | 15 ++++++ tests/ui/async-await/pin-sugar-no-const.rs | 8 +++ .../ui/async-await/pin-sugar-no-const.stderr | 15 ++++++ tests/ui/async-await/pin-sugar.rs | 51 +++++++++++++++++++ .../feature-gate-pin_ergonomics.rs | 11 ++-- .../feature-gate-pin_ergonomics.stderr | 47 ++++++++++++++--- 23 files changed, 284 insertions(+), 63 deletions(-) create mode 100644 tests/ui/async-await/pin-sugar-ambiguity.rs create mode 100644 tests/ui/async-await/pin-sugar-no-const.rs create mode 100644 tests/ui/async-await/pin-sugar-no-const.stderr create mode 100644 tests/ui/async-await/pin-sugar.rs diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index f2b52eea12f..88db97b66e4 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -23,7 +23,7 @@ use std::{cmp, fmt, mem}; pub use GenericArgs::*; pub use UnsafeSource::*; -pub use rustc_ast_ir::{Movability, Mutability}; +pub use rustc_ast_ir::{Movability, Mutability, Pinnedness}; use rustc_data_structures::packed::Pu128; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::stack::ensure_sufficient_stack; @@ -2161,6 +2161,10 @@ pub enum TyKind { Ptr(MutTy), /// A reference (`&'a T` or `&'a mut T`). Ref(Option, MutTy), + /// A pinned reference (`&'a pin const T` or `&'a pin mut T`). + /// + /// Desugars into `Pin<&'a T>` or `Pin<&'a mut T>`. + PinnedRef(Option, MutTy), /// A bare function (e.g., `fn(usize) -> bool`). BareFn(P), /// The never type (`!`). @@ -2509,7 +2513,10 @@ impl Param { if ident.name == kw::SelfLower { return match self.ty.kind { TyKind::ImplicitSelf => Some(respan(self.pat.span, SelfKind::Value(mutbl))), - TyKind::Ref(lt, MutTy { ref ty, mutbl }) if ty.kind.is_implicit_self() => { + TyKind::Ref(lt, MutTy { ref ty, mutbl }) + | TyKind::PinnedRef(lt, MutTy { ref ty, mutbl }) + if ty.kind.is_implicit_self() => + { Some(respan(self.pat.span, SelfKind::Region(lt, mutbl))) } _ => Some(respan( diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 6ce23a1479d..1c57dd948fc 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -485,7 +485,7 @@ pub fn walk_ty(vis: &mut T, ty: &mut P) { } TyKind::Slice(ty) => vis.visit_ty(ty), TyKind::Ptr(mt) => vis.visit_mt(mt), - TyKind::Ref(lt, mt) => { + TyKind::Ref(lt, mt) | TyKind::PinnedRef(lt, mt) => { visit_opt(lt, |lt| vis.visit_lifetime(lt)); vis.visit_mt(mt); } diff --git a/compiler/rustc_ast/src/util/classify.rs b/compiler/rustc_ast/src/util/classify.rs index 1a80a9ccdbf..8fdaf995850 100644 --- a/compiler/rustc_ast/src/util/classify.rs +++ b/compiler/rustc_ast/src/util/classify.rs @@ -247,7 +247,9 @@ fn type_trailing_braced_mac_call(mut ty: &ast::Ty) -> Option<&ast::MacCall> { break (mac.args.delim == Delimiter::Brace).then_some(mac); } - ast::TyKind::Ptr(mut_ty) | ast::TyKind::Ref(_, mut_ty) => { + ast::TyKind::Ptr(mut_ty) + | ast::TyKind::Ref(_, mut_ty) + | ast::TyKind::PinnedRef(_, mut_ty) => { ty = &mut_ty.ty; } diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 9f9c3d8c392..1ab88e8c02e 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -499,7 +499,8 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) -> V::Result { match kind { TyKind::Slice(ty) | TyKind::Paren(ty) => try_visit!(visitor.visit_ty(ty)), TyKind::Ptr(MutTy { ty, mutbl: _ }) => try_visit!(visitor.visit_ty(ty)), - TyKind::Ref(opt_lifetime, MutTy { ty, mutbl: _ }) => { + TyKind::Ref(opt_lifetime, MutTy { ty, mutbl: _ }) + | TyKind::PinnedRef(opt_lifetime, MutTy { ty, mutbl: _ }) => { visit_opt!(visitor, visit_lifetime, opt_lifetime, LifetimeCtxt::Ref); try_visit!(visitor.visit_ty(ty)); } diff --git a/compiler/rustc_ast_ir/src/lib.rs b/compiler/rustc_ast_ir/src/lib.rs index eeed5d36151..ff9d940ce9f 100644 --- a/compiler/rustc_ast_ir/src/lib.rs +++ b/compiler/rustc_ast_ir/src/lib.rs @@ -79,3 +79,10 @@ impl Mutability { matches!(self, Self::Not) } } + +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)] +#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_NoContext))] +pub enum Pinnedness { + Not, + Pinned, +} diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 52372bbf991..ae1e1b3f8a2 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -640,7 +640,8 @@ impl<'hir> LoweringContext<'_, 'hir> { self.lower_span(span), Some(self.allow_gen_future.clone()), ); - let resume_ty = self.make_lang_item_qpath(hir::LangItem::ResumeTy, unstable_span); + let resume_ty = + self.make_lang_item_qpath(hir::LangItem::ResumeTy, unstable_span, None); let input_ty = hir::Ty { hir_id: self.next_id(), kind: hir::TyKind::Path(resume_ty), @@ -2065,7 +2066,7 @@ impl<'hir> LoweringContext<'_, 'hir> { lang_item: hir::LangItem, name: Symbol, ) -> hir::Expr<'hir> { - let qpath = self.make_lang_item_qpath(lang_item, self.lower_span(span)); + let qpath = self.make_lang_item_qpath(lang_item, self.lower_span(span), None); let path = hir::ExprKind::Path(hir::QPath::TypeRelative( self.arena.alloc(self.ty(span, hir::TyKind::Path(qpath))), self.arena.alloc(hir::PathSegment::new( diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index b26797f4203..bd20a70f325 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -55,8 +55,8 @@ use rustc_errors::{DiagArgFromDisplay, DiagCtxtHandle, StashKey}; use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res}; use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId, LocalDefIdMap}; use rustc_hir::{ - self as hir, ConstArg, GenericArg, HirId, ItemLocalMap, MissingLifetimeKind, ParamName, - TraitCandidate, + self as hir, ConstArg, GenericArg, HirId, ItemLocalMap, LangItem, MissingLifetimeKind, + ParamName, TraitCandidate, }; use rustc_index::{Idx, IndexSlice, IndexVec}; use rustc_macros::extension; @@ -765,8 +765,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { res } - fn make_lang_item_qpath(&mut self, lang_item: hir::LangItem, span: Span) -> hir::QPath<'hir> { - hir::QPath::Resolved(None, self.make_lang_item_path(lang_item, span, None)) + fn make_lang_item_qpath( + &mut self, + lang_item: hir::LangItem, + span: Span, + args: Option<&'hir hir::GenericArgs<'hir>>, + ) -> hir::QPath<'hir> { + hir::QPath::Resolved(None, self.make_lang_item_path(lang_item, span, args)) } fn make_lang_item_path( @@ -1317,6 +1322,32 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let lifetime = self.lower_lifetime(®ion); hir::TyKind::Ref(lifetime, self.lower_mt(mt, itctx)) } + TyKind::PinnedRef(region, mt) => { + let region = region.unwrap_or_else(|| { + let id = if let Some(LifetimeRes::ElidedAnchor { start, end }) = + self.resolver.get_lifetime_res(t.id) + { + debug_assert_eq!(start.plus(1), end); + start + } else { + self.next_node_id() + }; + let span = self.tcx.sess.source_map().start_point(t.span).shrink_to_hi(); + Lifetime { ident: Ident::new(kw::UnderscoreLifetime, span), id } + }); + let lifetime = self.lower_lifetime(®ion); + let kind = hir::TyKind::Ref(lifetime, self.lower_mt(mt, itctx)); + let span = self.lower_span(t.span); + let arg = hir::Ty { kind, span, hir_id: self.next_id() }; + let args = self.arena.alloc(hir::GenericArgs { + args: self.arena.alloc([hir::GenericArg::Type(self.arena.alloc(arg))]), + constraints: &[], + parenthesized: hir::GenericArgsParentheses::No, + span_ext: span, + }); + let path = self.make_lang_item_qpath(LangItem::Pin, span, Some(args)); + hir::TyKind::Path(path) + } TyKind::BareFn(f) => { let generic_params = self.lower_lifetime_binder(t.id, &f.generic_params); hir::TyKind::BareFn(self.arena.alloc(hir::BareFnTy { @@ -1882,10 +1913,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Given we are only considering `ImplicitSelf` types, we needn't consider // the case where we have a mutable pattern to a reference as that would // no longer be an `ImplicitSelf`. - TyKind::Ref(_, mt) if mt.ty.kind.is_implicit_self() => match mt.mutbl { - hir::Mutability::Not => hir::ImplicitSelfKind::RefImm, - hir::Mutability::Mut => hir::ImplicitSelfKind::RefMut, - }, + TyKind::Ref(_, mt) | TyKind::PinnedRef(_, mt) + if mt.ty.kind.is_implicit_self() => + { + match mt.mutbl { + hir::Mutability::Not => hir::ImplicitSelfKind::RefImm, + hir::Mutability::Mut => hir::ImplicitSelfKind::RefMut, + } + } _ => hir::ImplicitSelfKind::None, } }), diff --git a/compiler/rustc_ast_lowering/src/lifetime_collector.rs b/compiler/rustc_ast_lowering/src/lifetime_collector.rs index 1e82ba5db8a..fe64160fb4d 100644 --- a/compiler/rustc_ast_lowering/src/lifetime_collector.rs +++ b/compiler/rustc_ast_lowering/src/lifetime_collector.rs @@ -95,7 +95,7 @@ impl<'ast> Visitor<'ast> for LifetimeCollectVisitor<'ast> { visit::walk_ty(self, t); self.current_binders.pop(); } - TyKind::Ref(None, _) => { + TyKind::Ref(None, _) | TyKind::PinnedRef(None, _) => { self.record_elided_anchor(t.id, t.span); visit::walk_ty(self, t); } diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 42d1ef5c558..5daaa840e13 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -547,6 +547,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { gate_all!(mut_ref, "mutable by-reference bindings are experimental"); gate_all!(global_registration, "global registration is experimental"); gate_all!(return_type_notation, "return type notation is experimental"); + gate_all!(pin_ergonomics, "pinned reference syntax is experimental"); if !visitor.features.never_patterns { if let Some(spans) = spans.get(&sym::never_patterns) { diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index 884cc413bd5..8b3653ab097 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -1163,6 +1163,12 @@ impl<'a> State<'a> { self.print_opt_lifetime(lifetime); self.print_mt(mt, false); } + ast::TyKind::PinnedRef(lifetime, mt) => { + self.word("&"); + self.print_opt_lifetime(lifetime); + self.word("pin "); + self.print_mt(mt, true); + } ast::TyKind::Never => { self.word("!"); } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 2ef6fa53f4e..bc5ed249559 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1,10 +1,9 @@ use std::fmt; -use rustc_ast as ast; use rustc_ast::util::parser::ExprPrecedence; use rustc_ast::{ - Attribute, FloatTy, InlineAsmOptions, InlineAsmTemplatePiece, IntTy, Label, LitKind, - TraitObjectSyntax, UintTy, + self as ast, Attribute, FloatTy, InlineAsmOptions, InlineAsmTemplatePiece, IntTy, Label, + LitKind, TraitObjectSyntax, UintTy, }; pub use rustc_ast::{ BinOp, BinOpKind, BindingMode, BorrowKind, ByRef, CaptureBy, ImplPolarity, IsAuto, Movability, diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index a8ed8b5df9c..ccd6dfda797 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -2,9 +2,7 @@ use rustc_ast::ptr::P; use rustc_ast::token::{self, BinOpToken, Delimiter, IdentIsRaw, Token, TokenKind}; use rustc_ast::util::case::Case; use rustc_ast::{ - self as ast, BareFnTy, BoundAsyncness, BoundConstness, BoundPolarity, DUMMY_NODE_ID, FnRetTy, - GenericBound, GenericBounds, GenericParam, Generics, Lifetime, MacCall, MutTy, Mutability, - PolyTraitRef, PreciseCapturingArg, TraitBoundModifiers, TraitObjectSyntax, Ty, TyKind, + self as ast, BareFnTy, BoundAsyncness, BoundConstness, BoundPolarity, FnRetTy, GenericBound, GenericBounds, GenericParam, Generics, Lifetime, MacCall, MutTy, Mutability, Pinnedness, PolyTraitRef, PreciseCapturingArg, TraitBoundModifiers, TraitObjectSyntax, Ty, TyKind, DUMMY_NODE_ID }; use rustc_errors::{Applicability, PResult}; use rustc_span::symbol::{Ident, kw, sym}; @@ -529,7 +527,10 @@ impl<'a> Parser<'a> { fn parse_borrowed_pointee(&mut self) -> PResult<'a, TyKind> { let and_span = self.prev_token.span; let mut opt_lifetime = self.check_lifetime().then(|| self.expect_lifetime()); - let mut mutbl = self.parse_mutability(); + let (pinned, mut mutbl) = match self.parse_pin_and_mut() { + Some(pin_mut) => pin_mut, + None => (Pinnedness::Not, self.parse_mutability()), + }; if self.token.is_lifetime() && mutbl == Mutability::Mut && opt_lifetime.is_none() { // A lifetime is invalid here: it would be part of a bare trait bound, which requires // it to be followed by a plus, but we disallow plus in the pointee type. @@ -565,7 +566,35 @@ impl<'a> Parser<'a> { self.bump_with((dyn_tok, dyn_tok_sp)); } let ty = self.parse_ty_no_plus()?; - Ok(TyKind::Ref(opt_lifetime, MutTy { ty, mutbl })) + Ok(match pinned { + Pinnedness::Not => TyKind::Ref(opt_lifetime, MutTy { ty, mutbl }), + Pinnedness::Pinned => TyKind::PinnedRef(opt_lifetime, MutTy { ty, mutbl }), + }) + } + + /// Parses `pin` and `mut` annotations on references. + /// + /// It must be either `pin const` or `pin mut`. + pub(crate) fn parse_pin_and_mut(&mut self) -> Option<(Pinnedness, Mutability)> { + if self.token.is_ident_named(sym::pin) { + let result = self.look_ahead(1, |token| { + if token.is_keyword(kw::Const) { + Some((Pinnedness::Pinned, Mutability::Not)) + } else if token.is_keyword(kw::Mut) { + Some((Pinnedness::Pinned, Mutability::Mut)) + } else { + None + } + }); + if result.is_some() { + self.psess.gated_spans.gate(sym::pin_ergonomics, self.token.span); + self.bump(); + self.bump(); + } + result + } else { + None + } } // Parses the `typeof(EXPR)`. diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs index 8ad14b6eb74..fc9d548d1fb 100644 --- a/compiler/rustc_passes/src/hir_stats.rs +++ b/compiler/rustc_passes/src/hir_stats.rs @@ -574,29 +574,33 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { } fn visit_ty(&mut self, t: &'v ast::Ty) { - record_variants!((self, t, t.kind, Id::None, ast, Ty, TyKind), [ - Slice, - Array, - Ptr, - Ref, - BareFn, - Never, - Tup, - AnonStruct, - AnonUnion, - Path, - Pat, - TraitObject, - ImplTrait, - Paren, - Typeof, - Infer, - ImplicitSelf, - MacCall, - CVarArgs, - Dummy, - Err - ]); + record_variants!( + (self, t, t.kind, Id::None, ast, Ty, TyKind), + [ + Slice, + Array, + Ptr, + Ref, + PinnedRef, + BareFn, + Never, + Tup, + AnonStruct, + AnonUnion, + Path, + Pat, + TraitObject, + ImplTrait, + Paren, + Typeof, + Infer, + ImplicitSelf, + MacCall, + CVarArgs, + Dummy, + Err + ] + ); ast_visit::walk_ty(self, t) } diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 66c1ff93ce1..b84cbf9c629 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -779,7 +779,7 @@ impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'r let prev = self.diag_metadata.current_trait_object; let prev_ty = self.diag_metadata.current_type_path; match &ty.kind { - TyKind::Ref(None, _) => { + TyKind::Ref(None, _) | TyKind::PinnedRef(None, _) => { // Elided lifetime in reference: we resolve as if there was some lifetime `'_` with // NodeId `ty.id`. // This span will be used in case of elision failure. @@ -2326,7 +2326,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { impl<'ra> Visitor<'ra> for FindReferenceVisitor<'_, '_, '_> { fn visit_ty(&mut self, ty: &'ra Ty) { trace!("FindReferenceVisitor considering ty={:?}", ty); - if let TyKind::Ref(lt, _) = ty.kind { + if let TyKind::Ref(lt, _) | TyKind::PinnedRef(lt, _) = ty.kind { // See if anything inside the &thing contains Self let mut visitor = SelfVisitor { r: self.r, impl_self: self.impl_self, self_found: false }; diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index fce5ec36c66..aced05ca351 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -3482,7 +3482,7 @@ struct LifetimeFinder<'ast> { impl<'ast> Visitor<'ast> for LifetimeFinder<'ast> { fn visit_ty(&mut self, t: &'ast Ty) { - if let TyKind::Ref(_, mut_ty) = &t.kind { + if let TyKind::Ref(_, mut_ty) | TyKind::PinnedRef(_, mut_ty) = &t.kind { self.seen.push(t); if t.span.lo() == self.lifetime.lo() { self.found = Some(&mut_ty.ty); diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs index 68f74e52ed7..187f7fb4417 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs @@ -753,6 +753,9 @@ pub fn eq_ty(l: &Ty, r: &Ty) -> bool { (Ref(ll, l), Ref(rl, r)) => { both(ll.as_ref(), rl.as_ref(), |l, r| eq_id(l.ident, r.ident)) && l.mutbl == r.mutbl && eq_ty(&l.ty, &r.ty) }, + (PinnedRef(ll, l), PinnedRef(rl, r)) => { + both(ll.as_ref(), rl.as_ref(), |l, r| eq_id(l.ident, r.ident)) && l.mutbl == r.mutbl && eq_ty(&l.ty, &r.ty) + }, (BareFn(l), BareFn(r)) => { l.safety == r.safety && eq_ext(&l.ext, &r.ext) diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs index 07b483b2b37..b64e069e096 100644 --- a/src/tools/rustfmt/src/types.rs +++ b/src/tools/rustfmt/src/types.rs @@ -827,7 +827,8 @@ impl Rewrite for ast::Ty { rewrite_unary_prefix(context, prefix, &*mt.ty, shape) } - ast::TyKind::Ref(ref lifetime, ref mt) => { + ast::TyKind::Ref(ref lifetime, _pinned, ref mt) => { + // FIXME: format pinnedness let mut_str = format_mutability(mt.mutbl); let mut_len = mut_str.len(); let mut result = String::with_capacity(128); @@ -1262,7 +1263,7 @@ pub(crate) fn can_be_overflowed_type( ) -> bool { match ty.kind { ast::TyKind::Tup(..) => context.use_block_indent() && len == 1, - ast::TyKind::Ref(_, ref mutty) | ast::TyKind::Ptr(ref mutty) => { + ast::TyKind::Ref(_, _, ref mutty) | ast::TyKind::Ptr(ref mutty) => { can_be_overflowed_type(context, &*mutty.ty, len) } _ => false, diff --git a/tests/ui/async-await/pin-sugar-ambiguity.rs b/tests/ui/async-await/pin-sugar-ambiguity.rs new file mode 100644 index 00000000000..d183000931e --- /dev/null +++ b/tests/ui/async-await/pin-sugar-ambiguity.rs @@ -0,0 +1,15 @@ +//@ check-pass +#![feature(pin_ergonomics)] +#![allow(dead_code, incomplete_features)] + +// Handle the case where there's ambiguity between pin as a contextual keyword and pin as a path. + +struct Foo; + +mod pin { + pub struct Foo; +} + +fn main() { + let _x: &pin ::Foo = &pin::Foo; +} diff --git a/tests/ui/async-await/pin-sugar-no-const.rs b/tests/ui/async-await/pin-sugar-no-const.rs new file mode 100644 index 00000000000..dd6456b6034 --- /dev/null +++ b/tests/ui/async-await/pin-sugar-no-const.rs @@ -0,0 +1,8 @@ +#![feature(pin_ergonomics)] +#![allow(incomplete_features)] + +// Makes sure we don't accidentally accept `&pin Foo` without the `const` keyword. + +fn main() { + let _x: &pin i32 = todo!(); //~ ERROR found `i32` +} diff --git a/tests/ui/async-await/pin-sugar-no-const.stderr b/tests/ui/async-await/pin-sugar-no-const.stderr new file mode 100644 index 00000000000..5f01156c1f0 --- /dev/null +++ b/tests/ui/async-await/pin-sugar-no-const.stderr @@ -0,0 +1,15 @@ +error: expected one of `!`, `(`, `::`, `;`, `<`, or `=`, found `i32` + --> $DIR/pin-sugar-no-const.rs:7:18 + | +LL | let _x: &pin i32 = todo!(); + | - ^^^ expected one of `!`, `(`, `::`, `;`, `<`, or `=` + | | + | while parsing the type for `_x` + | +help: there is a keyword `in` with a similar name + | +LL | let _x: &in i32 = todo!(); + | ~~ + +error: aborting due to 1 previous error + diff --git a/tests/ui/async-await/pin-sugar.rs b/tests/ui/async-await/pin-sugar.rs new file mode 100644 index 00000000000..8dbdec418b1 --- /dev/null +++ b/tests/ui/async-await/pin-sugar.rs @@ -0,0 +1,51 @@ +//@ check-pass + +#![feature(pin_ergonomics)] +#![allow(dead_code, incomplete_features)] + +// Makes sure we can handle `&pin mut T` and `&pin const T` as sugar for `Pin<&mut T>` and +// `Pin<&T>`. + +use std::pin::Pin; + +struct Foo; + +impl Foo { + fn baz(self: &pin mut Self) { + } + + fn baz_const(self: &pin const Self) { + } + + fn baz_lt<'a>(self: &'a pin mut Self) { + } + + fn baz_const_lt(self: &'_ pin const Self) { + } +} + +fn foo(_: &pin mut Foo) { +} + +fn foo_const(x: &pin const Foo) { +} + +fn bar(x: &pin mut Foo) { + foo(x); + foo(x); // for this to work we need to automatically reborrow, + // as if the user had written `foo(x.as_mut())`. + + Foo::baz(x); + Foo::baz(x); + + // make sure we can reborrow &mut as &. + foo_const(x); + Foo::baz_const(x); + + let x: &pin const _ = Pin::new(&Foo); + + foo_const(x); // make sure reborrowing from & to & works. + foo_const(x); +} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-pin_ergonomics.rs b/tests/ui/feature-gates/feature-gate-pin_ergonomics.rs index 3382504af9d..4624faf1e53 100644 --- a/tests/ui/feature-gates/feature-gate-pin_ergonomics.rs +++ b/tests/ui/feature-gates/feature-gate-pin_ergonomics.rs @@ -1,4 +1,4 @@ -#![allow(dead_code, incomplete_features)] +#![allow(dead_code)] use std::pin::Pin; @@ -9,10 +9,13 @@ impl Foo { } } -fn foo(_: Pin<&mut Foo>) { +fn foo(x: Pin<&mut Foo>) { + let _y: &pin mut Foo = x; //~ ERROR pinned reference syntax is experimental } -fn bar(mut x: Pin<&mut Foo>) { +fn foo_sugar(_: &pin mut Foo) {} //~ ERROR pinned reference syntax is experimental + +fn bar(x: Pin<&mut Foo>) { foo(x); foo(x); //~ ERROR use of moved value: `x` } @@ -22,4 +25,6 @@ fn baz(mut x: Pin<&mut Foo>) { x.foo(); //~ ERROR use of moved value: `x` } +fn baz_sugar(_: &pin const Foo) {} //~ ERROR pinned reference syntax is experimental + fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-pin_ergonomics.stderr b/tests/ui/feature-gates/feature-gate-pin_ergonomics.stderr index 430b7866241..dd93a7be1ad 100644 --- a/tests/ui/feature-gates/feature-gate-pin_ergonomics.stderr +++ b/tests/ui/feature-gates/feature-gate-pin_ergonomics.stderr @@ -1,8 +1,38 @@ -error[E0382]: use of moved value: `x` - --> $DIR/feature-gate-pin_ergonomics.rs:17:9 +error[E0658]: pinned reference syntax is experimental + --> $DIR/feature-gate-pin_ergonomics.rs:13:14 | -LL | fn bar(mut x: Pin<&mut Foo>) { - | ----- move occurs because `x` has type `Pin<&mut Foo>`, which does not implement the `Copy` trait +LL | let _y: &pin mut Foo = x; + | ^^^ + | + = note: see issue #130494 for more information + = help: add `#![feature(pin_ergonomics)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: pinned reference syntax is experimental + --> $DIR/feature-gate-pin_ergonomics.rs:16:18 + | +LL | fn foo_sugar(_: &pin mut Foo) {} + | ^^^ + | + = note: see issue #130494 for more information + = help: add `#![feature(pin_ergonomics)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: pinned reference syntax is experimental + --> $DIR/feature-gate-pin_ergonomics.rs:28:18 + | +LL | fn baz_sugar(_: &pin const Foo) {} + | ^^^ + | + = note: see issue #130494 for more information + = help: add `#![feature(pin_ergonomics)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0382]: use of moved value: `x` + --> $DIR/feature-gate-pin_ergonomics.rs:20:9 + | +LL | fn bar(x: Pin<&mut Foo>) { + | - move occurs because `x` has type `Pin<&mut Foo>`, which does not implement the `Copy` trait LL | foo(x); | - value moved here LL | foo(x); @@ -11,13 +41,13 @@ LL | foo(x); note: consider changing this parameter type in function `foo` to borrow instead if owning the value isn't necessary --> $DIR/feature-gate-pin_ergonomics.rs:12:11 | -LL | fn foo(_: Pin<&mut Foo>) { +LL | fn foo(x: Pin<&mut Foo>) { | --- ^^^^^^^^^^^^^ this parameter takes ownership of the value | | | in this function error[E0382]: use of moved value: `x` - --> $DIR/feature-gate-pin_ergonomics.rs:22:5 + --> $DIR/feature-gate-pin_ergonomics.rs:25:5 | LL | fn baz(mut x: Pin<&mut Foo>) { | ----- move occurs because `x` has type `Pin<&mut Foo>`, which does not implement the `Copy` trait @@ -36,6 +66,7 @@ help: consider reborrowing the `Pin` instead of moving it LL | x.as_mut().foo(); | +++++++++ -error: aborting due to 2 previous errors +error: aborting due to 5 previous errors -For more information about this error, try `rustc --explain E0382`. +Some errors have detailed explanations: E0382, E0658. +For more information about an error, try `rustc --explain E0382`. From b490bf56b7da3a689f0ea7a46f56d7cd2339efb0 Mon Sep 17 00:00:00 2001 From: Eric Holk Date: Fri, 20 Sep 2024 15:44:43 -0700 Subject: [PATCH 045/357] Fix clippy and rustfmt compilation --- compiler/rustc_parse/src/parser/ty.rs | 5 ++- compiler/rustc_passes/src/hir_stats.rs | 51 ++++++++++++-------------- src/tools/rustfmt/src/types.rs | 11 +++--- 3 files changed, 34 insertions(+), 33 deletions(-) diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index ccd6dfda797..b0ff033cf80 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -2,7 +2,10 @@ use rustc_ast::ptr::P; use rustc_ast::token::{self, BinOpToken, Delimiter, IdentIsRaw, Token, TokenKind}; use rustc_ast::util::case::Case; use rustc_ast::{ - self as ast, BareFnTy, BoundAsyncness, BoundConstness, BoundPolarity, FnRetTy, GenericBound, GenericBounds, GenericParam, Generics, Lifetime, MacCall, MutTy, Mutability, Pinnedness, PolyTraitRef, PreciseCapturingArg, TraitBoundModifiers, TraitObjectSyntax, Ty, TyKind, DUMMY_NODE_ID + self as ast, BareFnTy, BoundAsyncness, BoundConstness, BoundPolarity, DUMMY_NODE_ID, FnRetTy, + GenericBound, GenericBounds, GenericParam, Generics, Lifetime, MacCall, MutTy, Mutability, + Pinnedness, PolyTraitRef, PreciseCapturingArg, TraitBoundModifiers, TraitObjectSyntax, Ty, + TyKind, }; use rustc_errors::{Applicability, PResult}; use rustc_span::symbol::{Ident, kw, sym}; diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs index fc9d548d1fb..daf1bd8b19d 100644 --- a/compiler/rustc_passes/src/hir_stats.rs +++ b/compiler/rustc_passes/src/hir_stats.rs @@ -574,33 +574,30 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { } fn visit_ty(&mut self, t: &'v ast::Ty) { - record_variants!( - (self, t, t.kind, Id::None, ast, Ty, TyKind), - [ - Slice, - Array, - Ptr, - Ref, - PinnedRef, - BareFn, - Never, - Tup, - AnonStruct, - AnonUnion, - Path, - Pat, - TraitObject, - ImplTrait, - Paren, - Typeof, - Infer, - ImplicitSelf, - MacCall, - CVarArgs, - Dummy, - Err - ] - ); + record_variants!((self, t, t.kind, Id::None, ast, Ty, TyKind), [ + Slice, + Array, + Ptr, + Ref, + PinnedRef, + BareFn, + Never, + Tup, + AnonStruct, + AnonUnion, + Path, + Pat, + TraitObject, + ImplTrait, + Paren, + Typeof, + Infer, + ImplicitSelf, + MacCall, + CVarArgs, + Dummy, + Err + ]); ast_visit::walk_ty(self, t) } diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs index b64e069e096..999deb5dd4a 100644 --- a/src/tools/rustfmt/src/types.rs +++ b/src/tools/rustfmt/src/types.rs @@ -827,8 +827,9 @@ impl Rewrite for ast::Ty { rewrite_unary_prefix(context, prefix, &*mt.ty, shape) } - ast::TyKind::Ref(ref lifetime, _pinned, ref mt) => { - // FIXME: format pinnedness + ast::TyKind::Ref(ref lifetime, ref mt) + | ast::TyKind::PinnedRef(ref lifetime, ref mt) => { + // FIXME(pin_ergonomics): correctly format pinned reference syntax let mut_str = format_mutability(mt.mutbl); let mut_len = mut_str.len(); let mut result = String::with_capacity(128); @@ -1263,9 +1264,9 @@ pub(crate) fn can_be_overflowed_type( ) -> bool { match ty.kind { ast::TyKind::Tup(..) => context.use_block_indent() && len == 1, - ast::TyKind::Ref(_, _, ref mutty) | ast::TyKind::Ptr(ref mutty) => { - can_be_overflowed_type(context, &*mutty.ty, len) - } + ast::TyKind::Ref(_, ref mutty) + | ast::TyKind::PinnedRef(_, ref mutty) + | ast::TyKind::Ptr(ref mutty) => can_be_overflowed_type(context, &*mutty.ty, len), _ => false, } } From 3aabe1e4a3518f943a20b692a0db90189fc5898c Mon Sep 17 00:00:00 2001 From: Eric Holk Date: Mon, 23 Sep 2024 16:07:31 -0700 Subject: [PATCH 046/357] Add basic pin sugar support to rustfmt --- src/tools/rustfmt/src/types.rs | 8 +++++++- src/tools/rustfmt/tests/source/pin_sugar.rs | 10 ++++++++++ src/tools/rustfmt/tests/target/pin_sugar.rs | 9 +++++++++ 3 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 src/tools/rustfmt/tests/source/pin_sugar.rs create mode 100644 src/tools/rustfmt/tests/target/pin_sugar.rs diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs index 999deb5dd4a..f7177c7f854 100644 --- a/src/tools/rustfmt/src/types.rs +++ b/src/tools/rustfmt/src/types.rs @@ -829,7 +829,6 @@ impl Rewrite for ast::Ty { } ast::TyKind::Ref(ref lifetime, ref mt) | ast::TyKind::PinnedRef(ref lifetime, ref mt) => { - // FIXME(pin_ergonomics): correctly format pinned reference syntax let mut_str = format_mutability(mt.mutbl); let mut_len = mut_str.len(); let mut result = String::with_capacity(128); @@ -863,6 +862,13 @@ impl Rewrite for ast::Ty { cmnt_lo = lifetime.ident.span.hi(); } + if let ast::TyKind::PinnedRef(..) = self.kind { + result.push_str("pin "); + if ast::Mutability::Not == mt.mutbl { + result.push_str("const "); + } + } + if ast::Mutability::Mut == mt.mutbl { let mut_hi = context.snippet_provider.span_after(self.span(), "mut"); let before_mut_span = mk_sp(cmnt_lo, mut_hi - BytePos::from_usize(3)); diff --git a/src/tools/rustfmt/tests/source/pin_sugar.rs b/src/tools/rustfmt/tests/source/pin_sugar.rs new file mode 100644 index 00000000000..0eb3c0770c4 --- /dev/null +++ b/src/tools/rustfmt/tests/source/pin_sugar.rs @@ -0,0 +1,10 @@ +// See #130494 + +#![feature(pin_ergonomics)] +#![allow(incomplete_features)] + +fn f(x: &pin const i32) {} +fn g<'a>(x: & 'a pin const i32) {} +fn h<'a>(x: & 'a pin +mut i32) {} +fn i(x: &pin mut i32) {} diff --git a/src/tools/rustfmt/tests/target/pin_sugar.rs b/src/tools/rustfmt/tests/target/pin_sugar.rs new file mode 100644 index 00000000000..c9fa883e238 --- /dev/null +++ b/src/tools/rustfmt/tests/target/pin_sugar.rs @@ -0,0 +1,9 @@ +// See #130494 + +#![feature(pin_ergonomics)] +#![allow(incomplete_features)] + +fn f(x: &pin const i32) {} +fn g<'a>(x: &'a pin const i32) {} +fn h<'a>(x: &'a pin mut i32) {} +fn i(x: &pin mut i32) {} From 005a6298f75b309cb0ab07f36d2888961ffa602f Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Mon, 7 Oct 2024 14:20:27 -0400 Subject: [PATCH 047/357] re-sync with latest tracking issue changes --- RELEASES.md | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/RELEASES.md b/RELEASES.md index b9d58d6b757..4bdee5f66ed 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -6,12 +6,19 @@ Version 1.82.0 (2024-10-17) Language -------- - [Don't make statement nonterminals match pattern nonterminals](https://github.com/rust-lang/rust/pull/120221/) -- [Implement lint against ambiguous negative literals](https://github.com/rust-lang/rust/pull/121364/) - [Patterns matching empty types can now be omitted in common cases](https://github.com/rust-lang/rust/pull/122792) +- [`addr_of(_mut)!` macros and the newly stabilized `&raw (const|mut)` are now safe to use with all static items](https://github.com/rust-lang/rust/pull/125834) - [size_of_val_raw: for length 0 this is safe to call](https://github.com/rust-lang/rust/pull/126152/) - [Reorder trait bound modifiers *after* `for<...>` binder in trait bounds](https://github.com/rust-lang/rust/pull/127054/) - [Stabilize opaque type precise capturing (RFC 3617)](https://github.com/rust-lang/rust/pull/127672) +- [Stabilize `&raw const` and `&raw mut` operators (RFC 2582)](https://github.com/rust-lang/rust/pull/127679) +- [Stabilize unsafe extern blocks (RFC 3484)](https://github.com/rust-lang/rust/pull/127921) +- [Stabilize nested field access in `offset_of!`](https://github.com/rust-lang/rust/pull/128284) +- [Do not require `T` to be live when dropping `[T; 0]`](https://github.com/rust-lang/rust/pull/128438) +- [Stabilize `const` operands in inline assembly](https://github.com/rust-lang/rust/pull/128570) +- [Stabilize floating-point arithmetic in `const fn`](https://github.com/rust-lang/rust/pull/128596) - [Stabilize explicit opt-in to unsafe attributes](https://github.com/rust-lang/rust/pull/128771) +- [Document NaN bit patterns guarantees](https://github.com/rust-lang/rust/pull/129559) @@ -19,8 +26,11 @@ Language Compiler -------- - [Promote riscv64gc-unknown-linux-musl to tier 2](https://github.com/rust-lang/rust/pull/122049) +- [Promote Mac Catalyst targets `aarch64-apple-ios-macabi` and `x86_64-apple-ios-macabi` to Tier 2, and ship them with rustup](https://github.com/rust-lang/rust/pull/126450) - [Improved diagnostics to explain why a pattern is unreachable](https://github.com/rust-lang/rust/pull/128034) - [The compiler now triggers the unreachable code warning properly for async functions that don't return/are `-> !`](https://github.com/rust-lang/rust/pull/128443) +- [Promote `aarch64-apple-darwin` to Tier 1](https://github.com/rust-lang/rust/pull/128592) +- [Add Trusty OS target `aarch64-unknown-trusty` and `armv7-unknown-trusty` as tier 3 targets](https://github.com/rust-lang/rust/pull/129490) - [Promote `wasm32-wasip2` to Tier 2.](https://github.com/rust-lang/rust/pull/126967/) @@ -31,7 +41,6 @@ Libraries - [Implement DoubleEnded and ExactSize for Take and Take](https://github.com/rust-lang/rust/pull/106943/) - [Stabilize Wasm relaxed SIMD](https://github.com/rust-lang/rust/pull/117468/) - [Stabilize const `{integer}::from_str_radix` i.e. `const_int_from_str`](https://github.com/rust-lang/rust/pull/124941/) -- [CommandExt::before_exec: deprecate safety in edition 2024](https://github.com/rust-lang/rust/pull/125970/) - [CloneToUninit impls](https://github.com/rust-lang/rust/pull/126877/) - [impl `Default` for collection iterators that don't already have it](https://github.com/rust-lang/rust/pull/128261/) @@ -51,13 +60,9 @@ Cargo Compatibility Notes ------------------- -- [`addr_of(_mut)!` macros and the newly stabilized `&raw (const|mut)` are now safe to use with all static items](https://github.com/rust-lang/rust/pull/125834) - We now [disallow setting some built-in cfgs via the command-line](https://github.com/rust-lang/rust/pull/126158) with the newly added [`explicit_builtin_cfgs_in_flags`](https://doc.rust-lang.org/rustc/lints/listing/deny-by-default.html#explicit-builtin-cfgs-in-flags) lint in order to prevent incoherent state, eg. `windows` cfg active but target is Linux based. The appropriate [`rustc` flag](https://doc.rust-lang.org/rustc/command-line-arguments.html) should be used instead. -- [Stabilize `&raw const` and `&raw mut` operators (RFC 2582)](https://github.com/rust-lang/rust/pull/127679) -- [Stabilize unsafe extern blocks (RFC 3484)](https://github.com/rust-lang/rust/pull/127921) - The standard library has a new implementation of `binary_search` which is significantly improves performance (#128254). However when a sorted slice has multiple values which compare equal, the new implementation may select a different value among the equal ones than the old implementation. - [illumos/Solaris now sets `MSG_NOSIGNAL` when writing to sockets](https://github.com/rust-lang/rust/pull/128259). This avoids killing the process with SIGPIPE when writing to a closed socket, which matches the existing behavior on other UNIX targets. -- [Stabilize offset_of_nested](https://github.com/rust-lang/rust/pull/128284) - [Removes a problematic hack that always passed the --whole-archive linker flag for tests, which may cause linker errors for code accidentally relying on it.](https://github.com/rust-lang/rust/pull/128400) - The WebAssembly target features `multivalue` and `reference-types` are now both enabled by default. These two features both have subtle changes implied @@ -77,10 +82,6 @@ Compatibility Notes default features requires `-Zbuild-std` support from Cargo and more information can be found at [rust-lang/rust#128511](https://github.com/rust-lang/rust/pull/128511). -- [Stabilize `const` arguments to inline asm](https://github.com/rust-lang/rust/pull/128570) -- [Promote aarch64-apple-darwin to Tier 1](https://github.com/rust-lang/rust/pull/128592) -- [stabilize floating-point arithmetic in `const fn`](https://github.com/rust-lang/rust/pull/128596) -- [float types: document NaN bit pattern guarantees](https://github.com/rust-lang/rust/pull/129559) - [Rust now raises unsafety errors for union patterns in parameter-position](https://github.com/rust-lang/rust/pull/130531) From 0130edd3026384ae831d19349aff8921a7eb93ca Mon Sep 17 00:00:00 2001 From: Jake Date: Mon, 7 Oct 2024 13:06:23 -0700 Subject: [PATCH 048/357] Fix spelling in README --- src/tools/miri/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/miri/README.md b/src/tools/miri/README.md index f6349f45f43..9a50079bc94 100644 --- a/src/tools/miri/README.md +++ b/src/tools/miri/README.md @@ -290,7 +290,7 @@ environment variable. We first document the most relevant and most commonly used * `-Zmiri-compare-exchange-weak-failure-rate=` changes the failure rate of `compare_exchange_weak` operations. The default is `0.8` (so 4 out of 5 weak ops will fail). You can change it to any value between `0.0` and `1.0`, where `1.0` means it - will always fail and `0.0` means it will never fail. Note than setting it to + will always fail and `0.0` means it will never fail. Note that setting it to `1.0` will likely cause hangs, since it means programs using `compare_exchange_weak` cannot make progress. * `-Zmiri-disable-isolation` disables host isolation. As a consequence, @@ -392,7 +392,7 @@ to Miri failing to detect cases of undefined behavior in a program. but reports to the program that it did actually write. This is useful when you are not interested in the actual program's output, but only want to see Miri's errors and warnings. -* `-Zmiri-panic-on-unsupported` will makes some forms of unsupported functionality, +* `-Zmiri-panic-on-unsupported` will make some forms of unsupported functionality, such as FFI and unsupported syscalls, panic within the context of the emulated application instead of raising an error within the context of Miri (and halting execution). Note that code might not expect these operations to ever panic, so From 4abbdfa1c9cd3e2f3181608fb60539755f3a8068 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sun, 6 Oct 2024 20:05:27 +0200 Subject: [PATCH 049/357] Prepare tests --- .../migration_lint.fixed | 113 ++++++++++++++---- .../migration_lint.rs | 113 ++++++++++++++---- .../migration_lint.stderr | 113 ++++++++++++------ 3 files changed, 262 insertions(+), 77 deletions(-) diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.fixed b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.fixed index 253c9589a55..528d274c0ac 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.fixed +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.fixed @@ -8,49 +8,120 @@ extern crate migration_lint_macros; -struct Foo(u8); +struct Foo(T); + +// Tests type equality in a way that avoids coercing `&&T` to `&T`. +trait Eq {} +impl Eq for T {} +fn assert_type_eq>(_: T, _: U) {} fn main() { - let &Foo(mut a) = &Foo(0); - //~^ ERROR: the semantics of this pattern will change in edition 2024 - a = 42; + let Foo(x) = &Foo(0); + assert_type_eq(x, &0u8); - let &mut Foo(mut a) = &mut Foo(0); - //~^ ERROR: the semantics of this pattern will change in edition 2024 - a = 42; + let Foo(x) = &mut Foo(0); + assert_type_eq(x, &mut 0u8); - if let &&&&&Some(&_) = &&&&&Some(&0u8) {} + let &Foo(mut x) = &Foo(0); //~^ ERROR: the semantics of this pattern will change in edition 2024 + assert_type_eq(x, 0u8); - if let &&&&&Some(&mut _) = &&&&&Some(&mut 0u8) {} + let &mut Foo(mut x) = &mut Foo(0); //~^ ERROR: the semantics of this pattern will change in edition 2024 + assert_type_eq(x, 0u8); - if let &&&&&mut Some(&_) = &&&&&mut Some(&0u8) {} + let Foo(ref x) = &Foo(0); + assert_type_eq(x, &0u8); + + let Foo(ref x) = &mut Foo(0); + assert_type_eq(x, &0u8); + + let &Foo(x) = &Foo(0); + assert_type_eq(x, 0u8); + + let &mut Foo(x) = &mut Foo(0); + assert_type_eq(x, 0u8); + + let &Foo(x) = &Foo(&0); + assert_type_eq(x, &0u8); + + let &mut Foo(x) = &mut Foo(&0); + assert_type_eq(x, &0u8); + + let &Foo(&x) = &Foo(&0); //~^ ERROR: the semantics of this pattern will change in edition 2024 + assert_type_eq(x, 0u8); - if let &mut Some(&mut Some(&mut Some(_))) = &mut Some(&mut Some(&mut Some(0u8))) {} + let &Foo(&mut x) = &Foo(&mut 0); //~^ ERROR: the semantics of this pattern will change in edition 2024 + assert_type_eq(x, 0u8); - if let &mut Some(&mut Some(&mut Some(ref mut _a))) = &mut Some(&mut Some(&mut Some(0u8))) {} + let &mut Foo(&x) = &mut Foo(&0); //~^ ERROR: the semantics of this pattern will change in edition 2024 + assert_type_eq(x, 0u8); - struct Struct { - a: u32, - b: u32, - c: u32, + let &mut Foo(&mut x) = &mut Foo(&mut 0); + //~^ ERROR: the semantics of this pattern will change in edition 2024 + assert_type_eq(x, 0u8); + + if let Some(x) = &&&&&Some(&0u8) { + assert_type_eq(x, &&0u8); } - let s = Struct { a: 0, b: 0, c: 0 }; - let &Struct { ref a, mut b, ref c } = &s; + + if let &&&&&Some(&x) = &&&&&Some(&0u8) { + //~^ ERROR: the semantics of this pattern will change in edition 2024 + assert_type_eq(x, 0u8); + } + + if let &&&&&Some(&mut x) = &&&&&Some(&mut 0u8) { + //~^ ERROR: the semantics of this pattern will change in edition 2024 + assert_type_eq(x, 0u8); + } + + if let &&&&&mut Some(&x) = &&&&&mut Some(&0u8) { + //~^ ERROR: the semantics of this pattern will change in edition 2024 + assert_type_eq(x, 0u8); + } + + if let &mut Some(&mut Some(&mut Some(ref mut x))) = &mut Some(&mut Some(&mut Some(0u8))) { + //~^ ERROR: the semantics of this pattern will change in edition 2024 + assert_type_eq(x, &mut 0u8); + } + + struct Struct { + a: A, + b: B, + c: C, + } + + let &Struct { ref a, mut b, ref c } = &Struct { a: 0, b: 0, c: 0 }; //~^ ERROR: the semantics of this pattern will change in edition 2024 + assert_type_eq(a, &0u32); + assert_type_eq(b, 0u32); + + let &Struct { a: &a, ref b, ref c } = &Struct { a: &0, b: &0, c: &0 }; + //~^ ERROR: the semantics of this pattern will change in edition 2024 + assert_type_eq(a, 0u32); + assert_type_eq(b, &&0u32); + assert_type_eq(c, &&0u32); + + if let &Struct { a: &Some(a), b: &Some(&b), c: &Some(ref c) } = + //~^ ERROR: the semantics of this pattern will change in edition 2024 + &(Struct { a: &Some(&0), b: &Some(&0), c: &Some(&0) }) + { + assert_type_eq(a, &0u32); + assert_type_eq(b, 0u32); + assert_type_eq(c, &&0u32); + } #[warn(rust_2024_incompatible_pat)] match &(Some(0), Some(0)) { // The two patterns are the same syntactically, but because they're defined in different // editions they don't mean the same thing. - (Some(mut _x), migration_lint_macros::mixed_edition_pat!(_y)) => { + (Some(mut x), migration_lint_macros::mixed_edition_pat!(y)) => { //~^ WARN: the semantics of this pattern will change in edition 2024 - _x = 4; - _y = &7; + assert_type_eq(x, 0u32); + assert_type_eq(y, &0u32); } _ => {} } diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.rs index 1406db779cc..0c5be2c761d 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.rs +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.rs @@ -8,49 +8,120 @@ extern crate migration_lint_macros; -struct Foo(u8); +struct Foo(T); + +// Tests type equality in a way that avoids coercing `&&T` to `&T`. +trait Eq {} +impl Eq for T {} +fn assert_type_eq>(_: T, _: U) {} fn main() { - let Foo(mut a) = &Foo(0); - //~^ ERROR: the semantics of this pattern will change in edition 2024 - a = 42; + let Foo(x) = &Foo(0); + assert_type_eq(x, &0u8); - let Foo(mut a) = &mut Foo(0); - //~^ ERROR: the semantics of this pattern will change in edition 2024 - a = 42; + let Foo(x) = &mut Foo(0); + assert_type_eq(x, &mut 0u8); - if let Some(&_) = &&&&&Some(&0u8) {} + let Foo(mut x) = &Foo(0); //~^ ERROR: the semantics of this pattern will change in edition 2024 + assert_type_eq(x, 0u8); - if let Some(&mut _) = &&&&&Some(&mut 0u8) {} + let Foo(mut x) = &mut Foo(0); //~^ ERROR: the semantics of this pattern will change in edition 2024 + assert_type_eq(x, 0u8); - if let Some(&_) = &&&&&mut Some(&0u8) {} + let Foo(ref x) = &Foo(0); + assert_type_eq(x, &0u8); + + let Foo(ref x) = &mut Foo(0); + assert_type_eq(x, &0u8); + + let &Foo(x) = &Foo(0); + assert_type_eq(x, 0u8); + + let &mut Foo(x) = &mut Foo(0); + assert_type_eq(x, 0u8); + + let &Foo(x) = &Foo(&0); + assert_type_eq(x, &0u8); + + let &mut Foo(x) = &mut Foo(&0); + assert_type_eq(x, &0u8); + + let Foo(&x) = &Foo(&0); //~^ ERROR: the semantics of this pattern will change in edition 2024 + assert_type_eq(x, 0u8); - if let Some(&mut Some(Some(_))) = &mut Some(&mut Some(&mut Some(0u8))) {} + let Foo(&mut x) = &Foo(&mut 0); //~^ ERROR: the semantics of this pattern will change in edition 2024 + assert_type_eq(x, 0u8); - if let Some(&mut Some(Some(_a))) = &mut Some(&mut Some(&mut Some(0u8))) {} + let Foo(&x) = &mut Foo(&0); //~^ ERROR: the semantics of this pattern will change in edition 2024 + assert_type_eq(x, 0u8); - struct Struct { - a: u32, - b: u32, - c: u32, + let Foo(&mut x) = &mut Foo(&mut 0); + //~^ ERROR: the semantics of this pattern will change in edition 2024 + assert_type_eq(x, 0u8); + + if let Some(x) = &&&&&Some(&0u8) { + assert_type_eq(x, &&0u8); } - let s = Struct { a: 0, b: 0, c: 0 }; - let Struct { a, mut b, c } = &s; + + if let Some(&x) = &&&&&Some(&0u8) { + //~^ ERROR: the semantics of this pattern will change in edition 2024 + assert_type_eq(x, 0u8); + } + + if let Some(&mut x) = &&&&&Some(&mut 0u8) { + //~^ ERROR: the semantics of this pattern will change in edition 2024 + assert_type_eq(x, 0u8); + } + + if let Some(&x) = &&&&&mut Some(&0u8) { + //~^ ERROR: the semantics of this pattern will change in edition 2024 + assert_type_eq(x, 0u8); + } + + if let Some(&mut Some(Some(x))) = &mut Some(&mut Some(&mut Some(0u8))) { + //~^ ERROR: the semantics of this pattern will change in edition 2024 + assert_type_eq(x, &mut 0u8); + } + + struct Struct { + a: A, + b: B, + c: C, + } + + let Struct { a, mut b, c } = &Struct { a: 0, b: 0, c: 0 }; //~^ ERROR: the semantics of this pattern will change in edition 2024 + assert_type_eq(a, &0u32); + assert_type_eq(b, 0u32); + + let Struct { a: &a, b, ref c } = &Struct { a: &0, b: &0, c: &0 }; + //~^ ERROR: the semantics of this pattern will change in edition 2024 + assert_type_eq(a, 0u32); + assert_type_eq(b, &&0u32); + assert_type_eq(c, &&0u32); + + if let Struct { a: &Some(a), b: Some(&b), c: Some(c) } = + //~^ ERROR: the semantics of this pattern will change in edition 2024 + &(Struct { a: &Some(&0), b: &Some(&0), c: &Some(&0) }) + { + assert_type_eq(a, &0u32); + assert_type_eq(b, 0u32); + assert_type_eq(c, &&0u32); + } #[warn(rust_2024_incompatible_pat)] match &(Some(0), Some(0)) { // The two patterns are the same syntactically, but because they're defined in different // editions they don't mean the same thing. - (Some(mut _x), migration_lint_macros::mixed_edition_pat!(_y)) => { + (Some(mut x), migration_lint_macros::mixed_edition_pat!(y)) => { //~^ WARN: the semantics of this pattern will change in edition 2024 - _x = 4; - _y = &7; + assert_type_eq(x, 0u32); + assert_type_eq(y, &0u32); } _ => {} } diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr index 4d723012024..29e9183acc3 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr @@ -1,7 +1,7 @@ error: the semantics of this pattern will change in edition 2024 - --> $DIR/migration_lint.rs:14:9 + --> $DIR/migration_lint.rs:25:9 | -LL | let Foo(mut a) = &Foo(0); +LL | let Foo(mut x) = &Foo(0); | -^^^^^^^^^ | | | help: desugar the match ergonomics: `&` @@ -13,85 +13,128 @@ LL | #![deny(rust_2024_incompatible_pat)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the semantics of this pattern will change in edition 2024 - --> $DIR/migration_lint.rs:18:9 + --> $DIR/migration_lint.rs:29:9 | -LL | let Foo(mut a) = &mut Foo(0); +LL | let Foo(mut x) = &mut Foo(0); | -^^^^^^^^^ | | | help: desugar the match ergonomics: `&mut` error: the semantics of this pattern will change in edition 2024 - --> $DIR/migration_lint.rs:22:12 + --> $DIR/migration_lint.rs:51:9 | -LL | if let Some(&_) = &&&&&Some(&0u8) {} +LL | let Foo(&x) = &Foo(&0); + | -^^^^^^ + | | + | help: desugar the match ergonomics: `&` + +error: the semantics of this pattern will change in edition 2024 + --> $DIR/migration_lint.rs:55:9 + | +LL | let Foo(&mut x) = &Foo(&mut 0); + | -^^^^^^^^^^ + | | + | help: desugar the match ergonomics: `&` + +error: the semantics of this pattern will change in edition 2024 + --> $DIR/migration_lint.rs:59:9 + | +LL | let Foo(&x) = &mut Foo(&0); + | -^^^^^^ + | | + | help: desugar the match ergonomics: `&mut` + +error: the semantics of this pattern will change in edition 2024 + --> $DIR/migration_lint.rs:63:9 + | +LL | let Foo(&mut x) = &mut Foo(&mut 0); + | -^^^^^^^^^^ + | | + | help: desugar the match ergonomics: `&mut` + +error: the semantics of this pattern will change in edition 2024 + --> $DIR/migration_lint.rs:71:12 + | +LL | if let Some(&x) = &&&&&Some(&0u8) { | -^^^^^^^ | | | help: desugar the match ergonomics: `&&&&&` error: the semantics of this pattern will change in edition 2024 - --> $DIR/migration_lint.rs:25:12 + --> $DIR/migration_lint.rs:76:12 | -LL | if let Some(&mut _) = &&&&&Some(&mut 0u8) {} +LL | if let Some(&mut x) = &&&&&Some(&mut 0u8) { | -^^^^^^^^^^^ | | | help: desugar the match ergonomics: `&&&&&` error: the semantics of this pattern will change in edition 2024 - --> $DIR/migration_lint.rs:28:12 + --> $DIR/migration_lint.rs:81:12 | -LL | if let Some(&_) = &&&&&mut Some(&0u8) {} +LL | if let Some(&x) = &&&&&mut Some(&0u8) { | -^^^^^^^ | | | help: desugar the match ergonomics: `&&&&&mut` error: the semantics of this pattern will change in edition 2024 - --> $DIR/migration_lint.rs:31:12 + --> $DIR/migration_lint.rs:86:12 | -LL | if let Some(&mut Some(Some(_))) = &mut Some(&mut Some(&mut Some(0u8))) {} +LL | if let Some(&mut Some(Some(x))) = &mut Some(&mut Some(&mut Some(0u8))) { | ^^^^^^^^^^^^^^^^^^^^^^^^ | help: desugar the match ergonomics | -LL | if let &mut Some(&mut Some(&mut Some(_))) = &mut Some(&mut Some(&mut Some(0u8))) {} - | ++++ ++++ - -error: the semantics of this pattern will change in edition 2024 - --> $DIR/migration_lint.rs:34:12 - | -LL | if let Some(&mut Some(Some(_a))) = &mut Some(&mut Some(&mut Some(0u8))) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: desugar the match ergonomics - | -LL | if let &mut Some(&mut Some(&mut Some(ref mut _a))) = &mut Some(&mut Some(&mut Some(0u8))) {} +LL | if let &mut Some(&mut Some(&mut Some(ref mut x))) = &mut Some(&mut Some(&mut Some(0u8))) { | ++++ ++++ +++++++ error: the semantics of this pattern will change in edition 2024 - --> $DIR/migration_lint.rs:43:9 + --> $DIR/migration_lint.rs:97:9 | -LL | let Struct { a, mut b, c } = &s; +LL | let Struct { a, mut b, c } = &Struct { a: 0, b: 0, c: 0 }; | ^^^^^^^^^^^^^^^^^^^^^^ | help: desugar the match ergonomics | -LL | let &Struct { ref a, mut b, ref c } = &s; +LL | let &Struct { ref a, mut b, ref c } = &Struct { a: 0, b: 0, c: 0 }; | + +++ +++ -warning: the semantics of this pattern will change in edition 2024 - --> $DIR/migration_lint.rs:50:9 +error: the semantics of this pattern will change in edition 2024 + --> $DIR/migration_lint.rs:102:9 | -LL | (Some(mut _x), migration_lint_macros::mixed_edition_pat!(_y)) => { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let Struct { a: &a, b, ref c } = &Struct { a: &0, b: &0, c: &0 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: desugar the match ergonomics + | +LL | let &Struct { a: &a, ref b, ref c } = &Struct { a: &0, b: &0, c: &0 }; + | + +++ + +error: the semantics of this pattern will change in edition 2024 + --> $DIR/migration_lint.rs:108:12 + | +LL | if let Struct { a: &Some(a), b: Some(&b), c: Some(c) } = + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: desugar the match ergonomics + | +LL | if let &Struct { a: &Some(a), b: &Some(&b), c: &Some(ref c) } = + | + + + +++ + +warning: the semantics of this pattern will change in edition 2024 + --> $DIR/migration_lint.rs:121:9 + | +LL | (Some(mut x), migration_lint_macros::mixed_edition_pat!(y)) => { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: the lint level is defined here - --> $DIR/migration_lint.rs:46:12 + --> $DIR/migration_lint.rs:117:12 | LL | #[warn(rust_2024_incompatible_pat)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: desugar the match ergonomics | -LL | &(Some(mut _x), migration_lint_macros::mixed_edition_pat!(ref _y)) => { - | + +++ +LL | &(Some(mut x), migration_lint_macros::mixed_edition_pat!(ref y)) => { + | + +++ -error: aborting due to 8 previous errors; 1 warning emitted +error: aborting due to 13 previous errors; 1 warning emitted From 5fb71c677f2fc7922147764f928bbb104e0ebe87 Mon Sep 17 00:00:00 2001 From: Miguel Ojeda Date: Mon, 7 Oct 2024 23:32:05 +0200 Subject: [PATCH 050/357] CI: rfl: move job forward to Linux v6.12-rc2 Signed-off-by: Miguel Ojeda --- src/ci/docker/scripts/rfl-build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ci/docker/scripts/rfl-build.sh b/src/ci/docker/scripts/rfl-build.sh index 8011e07e92e..27dbfc6040c 100755 --- a/src/ci/docker/scripts/rfl-build.sh +++ b/src/ci/docker/scripts/rfl-build.sh @@ -2,7 +2,7 @@ set -euo pipefail -LINUX_VERSION=4c7864e81d8bbd51036dacf92fb0a400e13aaeee +LINUX_VERSION=v6.12-rc2 # Build rustc, rustdoc, cargo, clippy-driver and rustfmt ../x.py build --stage 2 library rustdoc clippy rustfmt From 4107322766523afa7d1968acc0dfee4fd06e8ad8 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sun, 6 Oct 2024 20:47:06 +0200 Subject: [PATCH 051/357] Error on resetted binding mode in edition 2024 --- compiler/rustc_hir_typeck/src/pat.rs | 15 +- compiler/rustc_hir_typeck/src/writeback.rs | 6 +- compiler/rustc_lint_defs/src/builtin.rs | 4 +- .../rustc_middle/src/ty/typeck_results.rs | 15 +- compiler/rustc_mir_build/src/errors.rs | 2 + .../rustc_mir_build/src/thir/pattern/mod.rs | 28 +++- .../migration_lint.fixed | 9 +- .../migration_lint.rs | 7 +- .../migration_lint.stderr | 20 +-- .../min_match_ergonomics_fail.rs | 49 ++++++ .../min_match_ergonomics_fail.stderr | 144 ++++++++++++++++++ .../min_match_ergonomics_success.rs | 19 +++ 12 files changed, 270 insertions(+), 48 deletions(-) create mode 100644 tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.rs create mode 100644 tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.stderr create mode 100644 tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_success.rs diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 45a6efc7a6a..8eb3118fb8a 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -692,10 +692,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { BindingMode(def_br, Mutability::Mut) } else { // `mut` resets binding mode on edition <= 2021 - self.typeck_results + *self + .typeck_results .borrow_mut() .rust_2024_migration_desugared_pats_mut() - .insert(pat_info.top_info.hir_id); + .entry(pat_info.top_info.hir_id) + .or_default() |= pat.span.at_least_rust_2024(); BindingMode(ByRef::No, Mutability::Mut) } } @@ -2206,14 +2208,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } else { // Reset binding mode on old editions - if pat_info.binding_mode != ByRef::No { pat_info.binding_mode = ByRef::No; - - self.typeck_results + *self + .typeck_results .borrow_mut() .rust_2024_migration_desugared_pats_mut() - .insert(pat_info.top_info.hir_id); + .entry(pat_info.top_info.hir_id) + .or_default() |= pat.span.at_least_rust_2024(); } } @@ -2264,6 +2266,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (err, err) } }; + self.check_pat(inner, inner_ty, pat_info); ref_ty } diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index c2555d2bb47..8164c737752 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -640,7 +640,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { #[instrument(skip(self), level = "debug")] fn visit_rust_2024_migration_desugared_pats(&mut self, hir_id: hir::HirId) { - if self + if let Some(is_hard_error) = self .fcx .typeck_results .borrow_mut() @@ -650,7 +650,9 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { debug!( "node is a pat whose match ergonomics are desugared by the Rust 2024 migration lint" ); - self.typeck_results.rust_2024_migration_desugared_pats_mut().insert(hir_id); + self.typeck_results + .rust_2024_migration_desugared_pats_mut() + .insert(hir_id, is_hard_error); } } diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 9b6d63c2ef4..06e63bd7341 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -1650,7 +1650,7 @@ declare_lint! { /// ### Example /// /// ```rust,edition2021 - /// #![feature(ref_pat_eat_one_layer_2024)] + /// #![feature(min_match_ergonomics_2024)] /// #![warn(rust_2024_incompatible_pat)] /// /// if let Some(&a) = &Some(&0u8) { @@ -1671,7 +1671,7 @@ declare_lint! { pub RUST_2024_INCOMPATIBLE_PAT, Allow, "detects patterns whose meaning will change in Rust 2024", - @feature_gate = ref_pat_eat_one_layer_2024; + @feature_gate = min_match_ergonomics_2024; // FIXME uncomment below upon stabilization /*@future_incompatible = FutureIncompatibleInfo { reason: FutureIncompatibilityReason::EditionSemanticsChange(Edition::Edition2024), diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs index a92bdb2eae0..c13d229ebdc 100644 --- a/compiler/rustc_middle/src/ty/typeck_results.rs +++ b/compiler/rustc_middle/src/ty/typeck_results.rs @@ -79,9 +79,10 @@ pub struct TypeckResults<'tcx> { /// Stores the actual binding mode for all instances of [`BindingMode`]. pat_binding_modes: ItemLocalMap, - /// Top-level patterns whose match ergonomics need to be desugared - /// by the Rust 2021 -> 2024 migration lint. - rust_2024_migration_desugared_pats: ItemLocalSet, + /// Top-level patterns whose match ergonomics need to be desugared by the Rust 2021 -> 2024 + /// migration lint. The boolean indicates whether the emitted diagnostic should be a hard error + /// (if any of the incompatible pattern elements are in edition 2024). + rust_2024_migration_desugared_pats: ItemLocalMap, /// Stores the types which were implicitly dereferenced in pattern binding modes /// for later usage in THIR lowering. For example, @@ -437,15 +438,15 @@ impl<'tcx> TypeckResults<'tcx> { LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.pat_adjustments } } - pub fn rust_2024_migration_desugared_pats(&self) -> LocalSetInContext<'_> { - LocalSetInContext { + pub fn rust_2024_migration_desugared_pats(&self) -> LocalTableInContext<'_, bool> { + LocalTableInContext { hir_owner: self.hir_owner, data: &self.rust_2024_migration_desugared_pats, } } - pub fn rust_2024_migration_desugared_pats_mut(&mut self) -> LocalSetInContextMut<'_> { - LocalSetInContextMut { + pub fn rust_2024_migration_desugared_pats_mut(&mut self) -> LocalTableInContextMut<'_, bool> { + LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.rust_2024_migration_desugared_pats, } diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 411e9420914..7f905d5b90b 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -983,6 +983,8 @@ pub(crate) struct Rust2024IncompatiblePat { pub(crate) struct Rust2024IncompatiblePatSugg { pub(crate) suggestion: Vec<(Span, String)>, + /// Whether the incompatibility is a hard error because a relevant span is in edition 2024. + pub(crate) is_hard_error: bool, } impl Subdiagnostic for Rust2024IncompatiblePatSugg { diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index d78e1f5da09..90355d7fce6 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -48,18 +48,30 @@ pub(super) fn pat_from_hir<'a, 'tcx>( typeck_results, rust_2024_migration_suggestion: typeck_results .rust_2024_migration_desugared_pats() - .contains(pat.hir_id) - .then_some(Rust2024IncompatiblePatSugg { suggestion: Vec::new() }), + .get(pat.hir_id) + .map(|&is_hard_error| Rust2024IncompatiblePatSugg { + suggestion: Vec::new(), + is_hard_error, + }), }; let result = pcx.lower_pattern(pat); debug!("pat_from_hir({:?}) = {:?}", pat, result); if let Some(sugg) = pcx.rust_2024_migration_suggestion { - tcx.emit_node_span_lint( - lint::builtin::RUST_2024_INCOMPATIBLE_PAT, - pat.hir_id, - pat.span, - Rust2024IncompatiblePat { sugg }, - ); + if tcx.features().min_match_ergonomics_2024 && sugg.is_hard_error { + let mut err = tcx.dcx().struct_span_err( + pat.span, + "patterns are not allowed to reset the default binding mode in rust 2024", + ); + err.subdiagnostic(sugg); + err.emit(); + } else { + tcx.emit_node_span_lint( + lint::builtin::RUST_2024_INCOMPATIBLE_PAT, + pat.hir_id, + pat.span, + Rust2024IncompatiblePat { sugg }, + ); + } } result } diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.fixed b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.fixed index 528d274c0ac..63c84ae5b99 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.fixed +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.fixed @@ -2,7 +2,7 @@ //@ run-rustfix //@ rustfix-only-machine-applicable //@ aux-build:migration_lint_macros.rs -#![feature(mut_ref, ref_pat_eat_one_layer_2024)] +#![feature(mut_ref, min_match_ergonomics_2024)] #![allow(incomplete_features, unused)] #![deny(rust_2024_incompatible_pat)] @@ -114,14 +114,13 @@ fn main() { assert_type_eq(c, &&0u32); } - #[warn(rust_2024_incompatible_pat)] match &(Some(0), Some(0)) { // The two patterns are the same syntactically, but because they're defined in different // editions they don't mean the same thing. - (Some(mut x), migration_lint_macros::mixed_edition_pat!(y)) => { - //~^ WARN: the semantics of this pattern will change in edition 2024 + &(Some(mut x), migration_lint_macros::mixed_edition_pat!(y)) => { + //~^ ERROR: patterns are not allowed to reset the default binding mode assert_type_eq(x, 0u32); - assert_type_eq(y, &0u32); + assert_type_eq(y, 0u32); } _ => {} } diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.rs index 0c5be2c761d..f2a83c1266b 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.rs +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.rs @@ -2,7 +2,7 @@ //@ run-rustfix //@ rustfix-only-machine-applicable //@ aux-build:migration_lint_macros.rs -#![feature(mut_ref, ref_pat_eat_one_layer_2024)] +#![feature(mut_ref, min_match_ergonomics_2024)] #![allow(incomplete_features, unused)] #![deny(rust_2024_incompatible_pat)] @@ -114,14 +114,13 @@ fn main() { assert_type_eq(c, &&0u32); } - #[warn(rust_2024_incompatible_pat)] match &(Some(0), Some(0)) { // The two patterns are the same syntactically, but because they're defined in different // editions they don't mean the same thing. (Some(mut x), migration_lint_macros::mixed_edition_pat!(y)) => { - //~^ WARN: the semantics of this pattern will change in edition 2024 + //~^ ERROR: patterns are not allowed to reset the default binding mode assert_type_eq(x, 0u32); - assert_type_eq(y, &0u32); + assert_type_eq(y, 0u32); } _ => {} } diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr index 29e9183acc3..5e42e03d668 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr @@ -120,21 +120,13 @@ help: desugar the match ergonomics LL | if let &Struct { a: &Some(a), b: &Some(&b), c: &Some(ref c) } = | + + + +++ -warning: the semantics of this pattern will change in edition 2024 - --> $DIR/migration_lint.rs:121:9 +error: patterns are not allowed to reset the default binding mode in rust 2024 + --> $DIR/migration_lint.rs:120:9 | LL | (Some(mut x), migration_lint_macros::mixed_edition_pat!(y)) => { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: the lint level is defined here - --> $DIR/migration_lint.rs:117:12 - | -LL | #[warn(rust_2024_incompatible_pat)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: desugar the match ergonomics - | -LL | &(Some(mut x), migration_lint_macros::mixed_edition_pat!(ref y)) => { - | + +++ + | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | help: desugar the match ergonomics: `&` -error: aborting due to 13 previous errors; 1 warning emitted +error: aborting due to 14 previous errors diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.rs new file mode 100644 index 00000000000..283666fdf4c --- /dev/null +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.rs @@ -0,0 +1,49 @@ +//@ check-fail +//@ edition: 2024 +//@ compile-flags: -Zunstable-options +// gate-test-min_match_ergonomics_2024 +#![feature(min_match_ergonomics_2024)] +#![allow(incomplete_features)] +#![deny(rust_2024_incompatible_pat)] + +fn main() {} + +#[derive(Copy, Clone)] +struct T; + +struct Foo { + f: &'static (u8,), +} + +macro_rules! test_pat_on_type { + ($($tt:tt)*) => { + const _: () = { + // Define a new function to ensure all cases are tested independently. + fn foo($($tt)*) {} + }; + }; +} + +test_pat_on_type![(&x,): &(T,)]; //~ ERROR mismatched types +test_pat_on_type![(&x,): &(&T,)]; //~ ERROR patterns are not allowed to reset the default binding mode +test_pat_on_type![(&x,): &(&mut T,)]; //~ ERROR mismatched types +test_pat_on_type![(&mut x,): &(&T,)]; //~ ERROR mismatched types +test_pat_on_type![(&mut x,): &(&mut T,)]; //~ ERROR patterns are not allowed to reset the default binding mode +test_pat_on_type![(&x,): &&mut &(T,)]; //~ ERROR mismatched types +test_pat_on_type![Foo { f: (&x,) }: Foo]; //~ ERROR mismatched types +test_pat_on_type![Foo { f: (&x,) }: &mut Foo]; //~ ERROR mismatched types +test_pat_on_type![Foo { f: &(x,) }: &Foo]; //~ ERROR patterns are not allowed to reset the default binding mode +test_pat_on_type![(mut x,): &(T,)]; //~ ERROR patterns are not allowed to reset the default binding mode +test_pat_on_type![(ref x,): &(T,)]; +test_pat_on_type![(ref mut x,): &mut (T,)]; + +fn get() -> X { + unimplemented!() +} + +// Make sure this works even when the underlying type is inferred. This test passes on rust stable. +fn infer() -> X { + match &get() { + (&x,) => x, //~ ERROR patterns are not allowed to reset the default binding mode + } +} diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.stderr new file mode 100644 index 00000000000..22247847def --- /dev/null +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.stderr @@ -0,0 +1,144 @@ +error[E0308]: mismatched types + --> $DIR/min_match_ergonomics_fail.rs:27:20 + | +LL | test_pat_on_type![(&x,): &(T,)]; + | ^^ ----- expected due to this + | | + | expected `T`, found `&_` + | + = note: expected struct `T` + found reference `&_` +help: consider removing `&` from the pattern + | +LL - test_pat_on_type![(&x,): &(T,)]; +LL + test_pat_on_type![(x,): &(T,)]; + | + +error[E0308]: mismatched types + --> $DIR/min_match_ergonomics_fail.rs:29:20 + | +LL | test_pat_on_type![(&x,): &(&mut T,)]; + | ^^ ---------- expected due to this + | | + | types differ in mutability + | + = note: expected mutable reference `&mut T` + found reference `&_` +help: consider removing `&` from the pattern + | +LL - test_pat_on_type![(&x,): &(&mut T,)]; +LL + test_pat_on_type![(x,): &(&mut T,)]; + | + +error[E0308]: mismatched types + --> $DIR/min_match_ergonomics_fail.rs:30:20 + | +LL | test_pat_on_type![(&mut x,): &(&T,)]; + | ^^^^^^ ------ expected due to this + | | + | types differ in mutability + | + = note: expected reference `&T` + found mutable reference `&mut _` +note: to declare a mutable binding use: `mut x` + --> $DIR/min_match_ergonomics_fail.rs:30:20 + | +LL | test_pat_on_type![(&mut x,): &(&T,)]; + | ^^^^^^ +help: consider removing `&mut` from the pattern + | +LL - test_pat_on_type![(&mut x,): &(&T,)]; +LL + test_pat_on_type![(x,): &(&T,)]; + | + +error[E0308]: mismatched types + --> $DIR/min_match_ergonomics_fail.rs:32:20 + | +LL | test_pat_on_type![(&x,): &&mut &(T,)]; + | ^^ ----------- expected due to this + | | + | expected `T`, found `&_` + | + = note: expected struct `T` + found reference `&_` +help: consider removing `&` from the pattern + | +LL - test_pat_on_type![(&x,): &&mut &(T,)]; +LL + test_pat_on_type![(x,): &&mut &(T,)]; + | + +error[E0308]: mismatched types + --> $DIR/min_match_ergonomics_fail.rs:33:29 + | +LL | test_pat_on_type![Foo { f: (&x,) }: Foo]; + | ^^ --- expected due to this + | | + | expected `u8`, found `&_` + | + = note: expected type `u8` + found reference `&_` +help: consider removing `&` from the pattern + | +LL - test_pat_on_type![Foo { f: (&x,) }: Foo]; +LL + test_pat_on_type![Foo { f: (x,) }: Foo]; + | + +error[E0308]: mismatched types + --> $DIR/min_match_ergonomics_fail.rs:34:29 + | +LL | test_pat_on_type![Foo { f: (&x,) }: &mut Foo]; + | ^^ -------- expected due to this + | | + | expected `u8`, found `&_` + | + = note: expected type `u8` + found reference `&_` +help: consider removing `&` from the pattern + | +LL - test_pat_on_type![Foo { f: (&x,) }: &mut Foo]; +LL + test_pat_on_type![Foo { f: (x,) }: &mut Foo]; + | + +error: patterns are not allowed to reset the default binding mode in rust 2024 + --> $DIR/min_match_ergonomics_fail.rs:28:19 + | +LL | test_pat_on_type![(&x,): &(&T,)]; + | -^^^^ + | | + | help: desugar the match ergonomics: `&` + +error: patterns are not allowed to reset the default binding mode in rust 2024 + --> $DIR/min_match_ergonomics_fail.rs:31:19 + | +LL | test_pat_on_type![(&mut x,): &(&mut T,)]; + | -^^^^^^^^ + | | + | help: desugar the match ergonomics: `&` + +error: patterns are not allowed to reset the default binding mode in rust 2024 + --> $DIR/min_match_ergonomics_fail.rs:35:19 + | +LL | test_pat_on_type![Foo { f: &(x,) }: &Foo]; + | -^^^^^^^^^^^^^^^ + | | + | help: desugar the match ergonomics: `&` + +error: patterns are not allowed to reset the default binding mode in rust 2024 + --> $DIR/min_match_ergonomics_fail.rs:36:19 + | +LL | test_pat_on_type![(mut x,): &(T,)]; + | -^^^^^^^ + | | + | help: desugar the match ergonomics: `&` + +error: patterns are not allowed to reset the default binding mode in rust 2024 + --> $DIR/min_match_ergonomics_fail.rs:47:9 + | +LL | (&x,) => x, + | -^^^^ + | | + | help: desugar the match ergonomics: `&` + +error: aborting due to 11 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_success.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_success.rs new file mode 100644 index 00000000000..8dbbd7cfbb0 --- /dev/null +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_success.rs @@ -0,0 +1,19 @@ +//@ revisions: normal min_match_ergonomics +//@ check-pass +#![cfg_attr(min_match_ergonomics, feature(min_match_ergonomics_2024))] +#![allow(incomplete_features)] + +fn main() {} + +// Tests type equality in a way that avoids coercing `&&T` to `&T`. +trait Eq {} +impl Eq for T {} +fn assert_type_eq>(_: T, _: U) {} + +#[derive(Copy, Clone)] +struct T; + +fn test() { + let (x,) = &(&T,); + assert_type_eq(x, &&T); +} From 575033c50cf3f530bb054211e3dae968d373037f Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Mon, 7 Oct 2024 23:39:33 +0200 Subject: [PATCH 052/357] Also disallow `ref`/`ref mut` overriding the binding mode --- compiler/rustc_hir_typeck/src/pat.rs | 15 ++++++- .../migration_lint.fixed | 6 ++- .../migration_lint.rs | 2 + .../migration_lint.stderr | 42 +++++++++++++------ .../min_match_ergonomics_fail.rs | 4 +- .../min_match_ergonomics_fail.stderr | 18 +++++++- 6 files changed, 67 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 8eb3118fb8a..9ac5367d5d9 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -691,7 +691,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { BindingMode(def_br, Mutability::Mut) } else { - // `mut` resets binding mode on edition <= 2021 + // `mut` resets the binding mode on edition <= 2021 *self .typeck_results .borrow_mut() @@ -702,7 +702,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } BindingMode(ByRef::No, mutbl) => BindingMode(def_br, mutbl), - BindingMode(ByRef::Yes(_), _) => user_bind_annot, + BindingMode(ByRef::Yes(_), _) => { + if matches!(def_br, ByRef::Yes(_)) { + // `ref`/`ref mut` overrides the binding mode on edition <= 2021 + *self + .typeck_results + .borrow_mut() + .rust_2024_migration_desugared_pats_mut() + .entry(pat_info.top_info.hir_id) + .or_default() |= pat.span.at_least_rust_2024(); + } + user_bind_annot + } }; if bm.0 == ByRef::Yes(Mutability::Mut) diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.fixed b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.fixed index 63c84ae5b99..a0fc34826a2 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.fixed +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.fixed @@ -30,10 +30,12 @@ fn main() { //~^ ERROR: the semantics of this pattern will change in edition 2024 assert_type_eq(x, 0u8); - let Foo(ref x) = &Foo(0); + let &Foo(ref x) = &Foo(0); + //~^ ERROR: the semantics of this pattern will change in edition 2024 assert_type_eq(x, &0u8); - let Foo(ref x) = &mut Foo(0); + let &mut Foo(ref x) = &mut Foo(0); + //~^ ERROR: the semantics of this pattern will change in edition 2024 assert_type_eq(x, &0u8); let &Foo(x) = &Foo(0); diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.rs index f2a83c1266b..6fdea065dc0 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.rs +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.rs @@ -31,9 +31,11 @@ fn main() { assert_type_eq(x, 0u8); let Foo(ref x) = &Foo(0); + //~^ ERROR: the semantics of this pattern will change in edition 2024 assert_type_eq(x, &0u8); let Foo(ref x) = &mut Foo(0); + //~^ ERROR: the semantics of this pattern will change in edition 2024 assert_type_eq(x, &0u8); let &Foo(x) = &Foo(0); diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr index 5e42e03d668..f429b96010d 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr @@ -21,7 +21,23 @@ LL | let Foo(mut x) = &mut Foo(0); | help: desugar the match ergonomics: `&mut` error: the semantics of this pattern will change in edition 2024 - --> $DIR/migration_lint.rs:51:9 + --> $DIR/migration_lint.rs:33:9 + | +LL | let Foo(ref x) = &Foo(0); + | -^^^^^^^^^ + | | + | help: desugar the match ergonomics: `&` + +error: the semantics of this pattern will change in edition 2024 + --> $DIR/migration_lint.rs:37:9 + | +LL | let Foo(ref x) = &mut Foo(0); + | -^^^^^^^^^ + | | + | help: desugar the match ergonomics: `&mut` + +error: the semantics of this pattern will change in edition 2024 + --> $DIR/migration_lint.rs:53:9 | LL | let Foo(&x) = &Foo(&0); | -^^^^^^ @@ -29,7 +45,7 @@ LL | let Foo(&x) = &Foo(&0); | help: desugar the match ergonomics: `&` error: the semantics of this pattern will change in edition 2024 - --> $DIR/migration_lint.rs:55:9 + --> $DIR/migration_lint.rs:57:9 | LL | let Foo(&mut x) = &Foo(&mut 0); | -^^^^^^^^^^ @@ -37,7 +53,7 @@ LL | let Foo(&mut x) = &Foo(&mut 0); | help: desugar the match ergonomics: `&` error: the semantics of this pattern will change in edition 2024 - --> $DIR/migration_lint.rs:59:9 + --> $DIR/migration_lint.rs:61:9 | LL | let Foo(&x) = &mut Foo(&0); | -^^^^^^ @@ -45,7 +61,7 @@ LL | let Foo(&x) = &mut Foo(&0); | help: desugar the match ergonomics: `&mut` error: the semantics of this pattern will change in edition 2024 - --> $DIR/migration_lint.rs:63:9 + --> $DIR/migration_lint.rs:65:9 | LL | let Foo(&mut x) = &mut Foo(&mut 0); | -^^^^^^^^^^ @@ -53,7 +69,7 @@ LL | let Foo(&mut x) = &mut Foo(&mut 0); | help: desugar the match ergonomics: `&mut` error: the semantics of this pattern will change in edition 2024 - --> $DIR/migration_lint.rs:71:12 + --> $DIR/migration_lint.rs:73:12 | LL | if let Some(&x) = &&&&&Some(&0u8) { | -^^^^^^^ @@ -61,7 +77,7 @@ LL | if let Some(&x) = &&&&&Some(&0u8) { | help: desugar the match ergonomics: `&&&&&` error: the semantics of this pattern will change in edition 2024 - --> $DIR/migration_lint.rs:76:12 + --> $DIR/migration_lint.rs:78:12 | LL | if let Some(&mut x) = &&&&&Some(&mut 0u8) { | -^^^^^^^^^^^ @@ -69,7 +85,7 @@ LL | if let Some(&mut x) = &&&&&Some(&mut 0u8) { | help: desugar the match ergonomics: `&&&&&` error: the semantics of this pattern will change in edition 2024 - --> $DIR/migration_lint.rs:81:12 + --> $DIR/migration_lint.rs:83:12 | LL | if let Some(&x) = &&&&&mut Some(&0u8) { | -^^^^^^^ @@ -77,7 +93,7 @@ LL | if let Some(&x) = &&&&&mut Some(&0u8) { | help: desugar the match ergonomics: `&&&&&mut` error: the semantics of this pattern will change in edition 2024 - --> $DIR/migration_lint.rs:86:12 + --> $DIR/migration_lint.rs:88:12 | LL | if let Some(&mut Some(Some(x))) = &mut Some(&mut Some(&mut Some(0u8))) { | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -88,7 +104,7 @@ LL | if let &mut Some(&mut Some(&mut Some(ref mut x))) = &mut Some(&mut Some | ++++ ++++ +++++++ error: the semantics of this pattern will change in edition 2024 - --> $DIR/migration_lint.rs:97:9 + --> $DIR/migration_lint.rs:99:9 | LL | let Struct { a, mut b, c } = &Struct { a: 0, b: 0, c: 0 }; | ^^^^^^^^^^^^^^^^^^^^^^ @@ -99,7 +115,7 @@ LL | let &Struct { ref a, mut b, ref c } = &Struct { a: 0, b: 0, c: 0 }; | + +++ +++ error: the semantics of this pattern will change in edition 2024 - --> $DIR/migration_lint.rs:102:9 + --> $DIR/migration_lint.rs:104:9 | LL | let Struct { a: &a, b, ref c } = &Struct { a: &0, b: &0, c: &0 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -110,7 +126,7 @@ LL | let &Struct { a: &a, ref b, ref c } = &Struct { a: &0, b: &0, c: &0 }; | + +++ error: the semantics of this pattern will change in edition 2024 - --> $DIR/migration_lint.rs:108:12 + --> $DIR/migration_lint.rs:110:12 | LL | if let Struct { a: &Some(a), b: Some(&b), c: Some(c) } = | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -121,12 +137,12 @@ LL | if let &Struct { a: &Some(a), b: &Some(&b), c: &Some(ref c) } = | + + + +++ error: patterns are not allowed to reset the default binding mode in rust 2024 - --> $DIR/migration_lint.rs:120:9 + --> $DIR/migration_lint.rs:122:9 | LL | (Some(mut x), migration_lint_macros::mixed_edition_pat!(y)) => { | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | help: desugar the match ergonomics: `&` -error: aborting due to 14 previous errors +error: aborting due to 16 previous errors diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.rs index 283666fdf4c..c5d2199852b 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.rs +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.rs @@ -34,8 +34,8 @@ test_pat_on_type![Foo { f: (&x,) }: Foo]; //~ ERROR mismatched types test_pat_on_type![Foo { f: (&x,) }: &mut Foo]; //~ ERROR mismatched types test_pat_on_type![Foo { f: &(x,) }: &Foo]; //~ ERROR patterns are not allowed to reset the default binding mode test_pat_on_type![(mut x,): &(T,)]; //~ ERROR patterns are not allowed to reset the default binding mode -test_pat_on_type![(ref x,): &(T,)]; -test_pat_on_type![(ref mut x,): &mut (T,)]; +test_pat_on_type![(ref x,): &(T,)]; //~ ERROR patterns are not allowed to reset the default binding mode +test_pat_on_type![(ref mut x,): &mut (T,)]; //~ ERROR patterns are not allowed to reset the default binding mode fn get() -> X { unimplemented!() diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.stderr index 22247847def..8f189e1cf07 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.stderr @@ -131,6 +131,22 @@ LL | test_pat_on_type![(mut x,): &(T,)]; | | | help: desugar the match ergonomics: `&` +error: patterns are not allowed to reset the default binding mode in rust 2024 + --> $DIR/min_match_ergonomics_fail.rs:37:19 + | +LL | test_pat_on_type![(ref x,): &(T,)]; + | -^^^^^^^ + | | + | help: desugar the match ergonomics: `&` + +error: patterns are not allowed to reset the default binding mode in rust 2024 + --> $DIR/min_match_ergonomics_fail.rs:38:19 + | +LL | test_pat_on_type![(ref mut x,): &mut (T,)]; + | -^^^^^^^^^^^ + | | + | help: desugar the match ergonomics: `&mut` + error: patterns are not allowed to reset the default binding mode in rust 2024 --> $DIR/min_match_ergonomics_fail.rs:47:9 | @@ -139,6 +155,6 @@ LL | (&x,) => x, | | | help: desugar the match ergonomics: `&` -error: aborting due to 11 previous errors +error: aborting due to 13 previous errors For more information about this error, try `rustc --explain E0308`. From 4aaada42d0b59c3294908f9996277c60d9e13917 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Mon, 7 Oct 2024 23:47:21 +0200 Subject: [PATCH 053/357] Stabilize `min_match_ergonomics_2024` --- compiler/rustc_feature/src/unstable.rs | 3 - compiler/rustc_lint_defs/src/builtin.rs | 7 +- .../rustc_mir_build/src/thir/pattern/mod.rs | 2 +- compiler/rustc_span/src/symbol.rs | 1 - .../migration_lint.fixed | 17 ++++- .../migration_lint.rs | 17 ++++- .../migration_lint.stderr | 70 +++++++++++++++---- .../min_match_ergonomics_fail.rs | 3 - .../min_match_ergonomics_fail.stderr | 28 ++++---- .../min_match_ergonomics_success.rs | 2 - 10 files changed, 104 insertions(+), 46 deletions(-) diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 5fff81d3e1c..fa3a7049f4a 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -516,9 +516,6 @@ declare_features! ( (unstable, macro_metavar_expr_concat, "1.81.0", Some(124225)), /// Allows `#[marker]` on certain traits allowing overlapping implementations. (unstable, marker_trait_attr, "1.30.0", Some(29864)), - /// A very restricted form of match ergonomics used over the 2024 edition transition to give - /// more time for T-lang to decide the final form of RFC3627. - (incomplete, min_match_ergonomics_2024, "CURRENT_RUSTC_VERSION", Some(123076)), /// A minimal, sound subset of specialization intended to be used by the /// standard library until the soundness issues with specialization /// are fixed. diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 06e63bd7341..b73ceb91c40 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -1650,7 +1650,6 @@ declare_lint! { /// ### Example /// /// ```rust,edition2021 - /// #![feature(min_match_ergonomics_2024)] /// #![warn(rust_2024_incompatible_pat)] /// /// if let Some(&a) = &Some(&0u8) { @@ -1671,12 +1670,10 @@ declare_lint! { pub RUST_2024_INCOMPATIBLE_PAT, Allow, "detects patterns whose meaning will change in Rust 2024", - @feature_gate = min_match_ergonomics_2024; - // FIXME uncomment below upon stabilization - /*@future_incompatible = FutureIncompatibleInfo { + @future_incompatible = FutureIncompatibleInfo { reason: FutureIncompatibilityReason::EditionSemanticsChange(Edition::Edition2024), reference: "123076", - };*/ + }; } declare_lint! { diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 90355d7fce6..bb02ee37733 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -57,7 +57,7 @@ pub(super) fn pat_from_hir<'a, 'tcx>( let result = pcx.lower_pattern(pat); debug!("pat_from_hir({:?}) = {:?}", pat, result); if let Some(sugg) = pcx.rust_2024_migration_suggestion { - if tcx.features().min_match_ergonomics_2024 && sugg.is_hard_error { + if sugg.is_hard_error { let mut err = tcx.dcx().struct_span_err( pat.span, "patterns are not allowed to reset the default binding mode in rust 2024", diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 81ae66ccf68..402232a1720 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1218,7 +1218,6 @@ symbols! { min_const_generics, min_const_unsafe_fn, min_exhaustive_patterns, - min_match_ergonomics_2024, min_specialization, min_type_alias_impl_trait, minnumf128, diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.fixed b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.fixed index a0fc34826a2..90c35b5a697 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.fixed +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.fixed @@ -2,7 +2,7 @@ //@ run-rustfix //@ rustfix-only-machine-applicable //@ aux-build:migration_lint_macros.rs -#![feature(mut_ref, min_match_ergonomics_2024)] +#![feature(mut_ref)] #![allow(incomplete_features, unused)] #![deny(rust_2024_incompatible_pat)] @@ -24,18 +24,22 @@ fn main() { let &Foo(mut x) = &Foo(0); //~^ ERROR: the semantics of this pattern will change in edition 2024 + //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); let &mut Foo(mut x) = &mut Foo(0); //~^ ERROR: the semantics of this pattern will change in edition 2024 + //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); let &Foo(ref x) = &Foo(0); //~^ ERROR: the semantics of this pattern will change in edition 2024 + //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, &0u8); let &mut Foo(ref x) = &mut Foo(0); //~^ ERROR: the semantics of this pattern will change in edition 2024 + //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, &0u8); let &Foo(x) = &Foo(0); @@ -52,18 +56,22 @@ fn main() { let &Foo(&x) = &Foo(&0); //~^ ERROR: the semantics of this pattern will change in edition 2024 + //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); let &Foo(&mut x) = &Foo(&mut 0); //~^ ERROR: the semantics of this pattern will change in edition 2024 + //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); let &mut Foo(&x) = &mut Foo(&0); //~^ ERROR: the semantics of this pattern will change in edition 2024 + //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); let &mut Foo(&mut x) = &mut Foo(&mut 0); //~^ ERROR: the semantics of this pattern will change in edition 2024 + //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); if let Some(x) = &&&&&Some(&0u8) { @@ -72,21 +80,25 @@ fn main() { if let &&&&&Some(&x) = &&&&&Some(&0u8) { //~^ ERROR: the semantics of this pattern will change in edition 2024 + //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); } if let &&&&&Some(&mut x) = &&&&&Some(&mut 0u8) { //~^ ERROR: the semantics of this pattern will change in edition 2024 + //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); } if let &&&&&mut Some(&x) = &&&&&mut Some(&0u8) { //~^ ERROR: the semantics of this pattern will change in edition 2024 + //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); } if let &mut Some(&mut Some(&mut Some(ref mut x))) = &mut Some(&mut Some(&mut Some(0u8))) { //~^ ERROR: the semantics of this pattern will change in edition 2024 + //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, &mut 0u8); } @@ -98,17 +110,20 @@ fn main() { let &Struct { ref a, mut b, ref c } = &Struct { a: 0, b: 0, c: 0 }; //~^ ERROR: the semantics of this pattern will change in edition 2024 + //~| WARN: this changes meaning in Rust 2024 assert_type_eq(a, &0u32); assert_type_eq(b, 0u32); let &Struct { a: &a, ref b, ref c } = &Struct { a: &0, b: &0, c: &0 }; //~^ ERROR: the semantics of this pattern will change in edition 2024 + //~| WARN: this changes meaning in Rust 2024 assert_type_eq(a, 0u32); assert_type_eq(b, &&0u32); assert_type_eq(c, &&0u32); if let &Struct { a: &Some(a), b: &Some(&b), c: &Some(ref c) } = //~^ ERROR: the semantics of this pattern will change in edition 2024 + //~| WARN: this changes meaning in Rust 2024 &(Struct { a: &Some(&0), b: &Some(&0), c: &Some(&0) }) { assert_type_eq(a, &0u32); diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.rs index 6fdea065dc0..04d547f3018 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.rs +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.rs @@ -2,7 +2,7 @@ //@ run-rustfix //@ rustfix-only-machine-applicable //@ aux-build:migration_lint_macros.rs -#![feature(mut_ref, min_match_ergonomics_2024)] +#![feature(mut_ref)] #![allow(incomplete_features, unused)] #![deny(rust_2024_incompatible_pat)] @@ -24,18 +24,22 @@ fn main() { let Foo(mut x) = &Foo(0); //~^ ERROR: the semantics of this pattern will change in edition 2024 + //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); let Foo(mut x) = &mut Foo(0); //~^ ERROR: the semantics of this pattern will change in edition 2024 + //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); let Foo(ref x) = &Foo(0); //~^ ERROR: the semantics of this pattern will change in edition 2024 + //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, &0u8); let Foo(ref x) = &mut Foo(0); //~^ ERROR: the semantics of this pattern will change in edition 2024 + //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, &0u8); let &Foo(x) = &Foo(0); @@ -52,18 +56,22 @@ fn main() { let Foo(&x) = &Foo(&0); //~^ ERROR: the semantics of this pattern will change in edition 2024 + //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); let Foo(&mut x) = &Foo(&mut 0); //~^ ERROR: the semantics of this pattern will change in edition 2024 + //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); let Foo(&x) = &mut Foo(&0); //~^ ERROR: the semantics of this pattern will change in edition 2024 + //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); let Foo(&mut x) = &mut Foo(&mut 0); //~^ ERROR: the semantics of this pattern will change in edition 2024 + //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); if let Some(x) = &&&&&Some(&0u8) { @@ -72,21 +80,25 @@ fn main() { if let Some(&x) = &&&&&Some(&0u8) { //~^ ERROR: the semantics of this pattern will change in edition 2024 + //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); } if let Some(&mut x) = &&&&&Some(&mut 0u8) { //~^ ERROR: the semantics of this pattern will change in edition 2024 + //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); } if let Some(&x) = &&&&&mut Some(&0u8) { //~^ ERROR: the semantics of this pattern will change in edition 2024 + //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); } if let Some(&mut Some(Some(x))) = &mut Some(&mut Some(&mut Some(0u8))) { //~^ ERROR: the semantics of this pattern will change in edition 2024 + //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, &mut 0u8); } @@ -98,17 +110,20 @@ fn main() { let Struct { a, mut b, c } = &Struct { a: 0, b: 0, c: 0 }; //~^ ERROR: the semantics of this pattern will change in edition 2024 + //~| WARN: this changes meaning in Rust 2024 assert_type_eq(a, &0u32); assert_type_eq(b, 0u32); let Struct { a: &a, b, ref c } = &Struct { a: &0, b: &0, c: &0 }; //~^ ERROR: the semantics of this pattern will change in edition 2024 + //~| WARN: this changes meaning in Rust 2024 assert_type_eq(a, 0u32); assert_type_eq(b, &&0u32); assert_type_eq(c, &&0u32); if let Struct { a: &Some(a), b: Some(&b), c: Some(c) } = //~^ ERROR: the semantics of this pattern will change in edition 2024 + //~| WARN: this changes meaning in Rust 2024 &(Struct { a: &Some(&0), b: &Some(&0), c: &Some(&0) }) { assert_type_eq(a, &0u32); diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr index f429b96010d..4881748f71a 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr @@ -6,6 +6,8 @@ LL | let Foo(mut x) = &Foo(0); | | | help: desugar the match ergonomics: `&` | + = warning: this changes meaning in Rust 2024 + = note: for more information, see 123076 note: the lint level is defined here --> $DIR/migration_lint.rs:7:9 | @@ -13,131 +15,169 @@ LL | #![deny(rust_2024_incompatible_pat)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the semantics of this pattern will change in edition 2024 - --> $DIR/migration_lint.rs:29:9 + --> $DIR/migration_lint.rs:30:9 | LL | let Foo(mut x) = &mut Foo(0); | -^^^^^^^^^ | | | help: desugar the match ergonomics: `&mut` + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see 123076 error: the semantics of this pattern will change in edition 2024 - --> $DIR/migration_lint.rs:33:9 + --> $DIR/migration_lint.rs:35:9 | LL | let Foo(ref x) = &Foo(0); | -^^^^^^^^^ | | | help: desugar the match ergonomics: `&` + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see 123076 error: the semantics of this pattern will change in edition 2024 - --> $DIR/migration_lint.rs:37:9 + --> $DIR/migration_lint.rs:40:9 | LL | let Foo(ref x) = &mut Foo(0); | -^^^^^^^^^ | | | help: desugar the match ergonomics: `&mut` + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see 123076 error: the semantics of this pattern will change in edition 2024 - --> $DIR/migration_lint.rs:53:9 + --> $DIR/migration_lint.rs:57:9 | LL | let Foo(&x) = &Foo(&0); | -^^^^^^ | | | help: desugar the match ergonomics: `&` + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see 123076 error: the semantics of this pattern will change in edition 2024 - --> $DIR/migration_lint.rs:57:9 + --> $DIR/migration_lint.rs:62:9 | LL | let Foo(&mut x) = &Foo(&mut 0); | -^^^^^^^^^^ | | | help: desugar the match ergonomics: `&` + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see 123076 error: the semantics of this pattern will change in edition 2024 - --> $DIR/migration_lint.rs:61:9 + --> $DIR/migration_lint.rs:67:9 | LL | let Foo(&x) = &mut Foo(&0); | -^^^^^^ | | | help: desugar the match ergonomics: `&mut` + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see 123076 error: the semantics of this pattern will change in edition 2024 - --> $DIR/migration_lint.rs:65:9 + --> $DIR/migration_lint.rs:72:9 | LL | let Foo(&mut x) = &mut Foo(&mut 0); | -^^^^^^^^^^ | | | help: desugar the match ergonomics: `&mut` + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see 123076 error: the semantics of this pattern will change in edition 2024 - --> $DIR/migration_lint.rs:73:12 + --> $DIR/migration_lint.rs:81:12 | LL | if let Some(&x) = &&&&&Some(&0u8) { | -^^^^^^^ | | | help: desugar the match ergonomics: `&&&&&` + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see 123076 error: the semantics of this pattern will change in edition 2024 - --> $DIR/migration_lint.rs:78:12 + --> $DIR/migration_lint.rs:87:12 | LL | if let Some(&mut x) = &&&&&Some(&mut 0u8) { | -^^^^^^^^^^^ | | | help: desugar the match ergonomics: `&&&&&` + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see 123076 error: the semantics of this pattern will change in edition 2024 - --> $DIR/migration_lint.rs:83:12 + --> $DIR/migration_lint.rs:93:12 | LL | if let Some(&x) = &&&&&mut Some(&0u8) { | -^^^^^^^ | | | help: desugar the match ergonomics: `&&&&&mut` + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see 123076 error: the semantics of this pattern will change in edition 2024 - --> $DIR/migration_lint.rs:88:12 + --> $DIR/migration_lint.rs:99:12 | LL | if let Some(&mut Some(Some(x))) = &mut Some(&mut Some(&mut Some(0u8))) { | ^^^^^^^^^^^^^^^^^^^^^^^^ | + = warning: this changes meaning in Rust 2024 + = note: for more information, see 123076 help: desugar the match ergonomics | LL | if let &mut Some(&mut Some(&mut Some(ref mut x))) = &mut Some(&mut Some(&mut Some(0u8))) { | ++++ ++++ +++++++ error: the semantics of this pattern will change in edition 2024 - --> $DIR/migration_lint.rs:99:9 + --> $DIR/migration_lint.rs:111:9 | LL | let Struct { a, mut b, c } = &Struct { a: 0, b: 0, c: 0 }; | ^^^^^^^^^^^^^^^^^^^^^^ | + = warning: this changes meaning in Rust 2024 + = note: for more information, see 123076 help: desugar the match ergonomics | LL | let &Struct { ref a, mut b, ref c } = &Struct { a: 0, b: 0, c: 0 }; | + +++ +++ error: the semantics of this pattern will change in edition 2024 - --> $DIR/migration_lint.rs:104:9 + --> $DIR/migration_lint.rs:117:9 | LL | let Struct { a: &a, b, ref c } = &Struct { a: &0, b: &0, c: &0 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | + = warning: this changes meaning in Rust 2024 + = note: for more information, see 123076 help: desugar the match ergonomics | LL | let &Struct { a: &a, ref b, ref c } = &Struct { a: &0, b: &0, c: &0 }; | + +++ error: the semantics of this pattern will change in edition 2024 - --> $DIR/migration_lint.rs:110:12 + --> $DIR/migration_lint.rs:124:12 | LL | if let Struct { a: &Some(a), b: Some(&b), c: Some(c) } = | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | + = warning: this changes meaning in Rust 2024 + = note: for more information, see 123076 help: desugar the match ergonomics | LL | if let &Struct { a: &Some(a), b: &Some(&b), c: &Some(ref c) } = | + + + +++ error: patterns are not allowed to reset the default binding mode in rust 2024 - --> $DIR/migration_lint.rs:122:9 + --> $DIR/migration_lint.rs:137:9 | LL | (Some(mut x), migration_lint_macros::mixed_edition_pat!(y)) => { | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.rs index c5d2199852b..a822c90ab6e 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.rs +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.rs @@ -1,9 +1,6 @@ //@ check-fail //@ edition: 2024 //@ compile-flags: -Zunstable-options -// gate-test-min_match_ergonomics_2024 -#![feature(min_match_ergonomics_2024)] -#![allow(incomplete_features)] #![deny(rust_2024_incompatible_pat)] fn main() {} diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.stderr index 8f189e1cf07..ca34ad8d0ec 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/min_match_ergonomics_fail.rs:27:20 + --> $DIR/min_match_ergonomics_fail.rs:24:20 | LL | test_pat_on_type![(&x,): &(T,)]; | ^^ ----- expected due to this @@ -15,7 +15,7 @@ LL + test_pat_on_type![(x,): &(T,)]; | error[E0308]: mismatched types - --> $DIR/min_match_ergonomics_fail.rs:29:20 + --> $DIR/min_match_ergonomics_fail.rs:26:20 | LL | test_pat_on_type![(&x,): &(&mut T,)]; | ^^ ---------- expected due to this @@ -31,7 +31,7 @@ LL + test_pat_on_type![(x,): &(&mut T,)]; | error[E0308]: mismatched types - --> $DIR/min_match_ergonomics_fail.rs:30:20 + --> $DIR/min_match_ergonomics_fail.rs:27:20 | LL | test_pat_on_type![(&mut x,): &(&T,)]; | ^^^^^^ ------ expected due to this @@ -41,7 +41,7 @@ LL | test_pat_on_type![(&mut x,): &(&T,)]; = note: expected reference `&T` found mutable reference `&mut _` note: to declare a mutable binding use: `mut x` - --> $DIR/min_match_ergonomics_fail.rs:30:20 + --> $DIR/min_match_ergonomics_fail.rs:27:20 | LL | test_pat_on_type![(&mut x,): &(&T,)]; | ^^^^^^ @@ -52,7 +52,7 @@ LL + test_pat_on_type![(x,): &(&T,)]; | error[E0308]: mismatched types - --> $DIR/min_match_ergonomics_fail.rs:32:20 + --> $DIR/min_match_ergonomics_fail.rs:29:20 | LL | test_pat_on_type![(&x,): &&mut &(T,)]; | ^^ ----------- expected due to this @@ -68,7 +68,7 @@ LL + test_pat_on_type![(x,): &&mut &(T,)]; | error[E0308]: mismatched types - --> $DIR/min_match_ergonomics_fail.rs:33:29 + --> $DIR/min_match_ergonomics_fail.rs:30:29 | LL | test_pat_on_type![Foo { f: (&x,) }: Foo]; | ^^ --- expected due to this @@ -84,7 +84,7 @@ LL + test_pat_on_type![Foo { f: (x,) }: Foo]; | error[E0308]: mismatched types - --> $DIR/min_match_ergonomics_fail.rs:34:29 + --> $DIR/min_match_ergonomics_fail.rs:31:29 | LL | test_pat_on_type![Foo { f: (&x,) }: &mut Foo]; | ^^ -------- expected due to this @@ -100,7 +100,7 @@ LL + test_pat_on_type![Foo { f: (x,) }: &mut Foo]; | error: patterns are not allowed to reset the default binding mode in rust 2024 - --> $DIR/min_match_ergonomics_fail.rs:28:19 + --> $DIR/min_match_ergonomics_fail.rs:25:19 | LL | test_pat_on_type![(&x,): &(&T,)]; | -^^^^ @@ -108,7 +108,7 @@ LL | test_pat_on_type![(&x,): &(&T,)]; | help: desugar the match ergonomics: `&` error: patterns are not allowed to reset the default binding mode in rust 2024 - --> $DIR/min_match_ergonomics_fail.rs:31:19 + --> $DIR/min_match_ergonomics_fail.rs:28:19 | LL | test_pat_on_type![(&mut x,): &(&mut T,)]; | -^^^^^^^^ @@ -116,7 +116,7 @@ LL | test_pat_on_type![(&mut x,): &(&mut T,)]; | help: desugar the match ergonomics: `&` error: patterns are not allowed to reset the default binding mode in rust 2024 - --> $DIR/min_match_ergonomics_fail.rs:35:19 + --> $DIR/min_match_ergonomics_fail.rs:32:19 | LL | test_pat_on_type![Foo { f: &(x,) }: &Foo]; | -^^^^^^^^^^^^^^^ @@ -124,7 +124,7 @@ LL | test_pat_on_type![Foo { f: &(x,) }: &Foo]; | help: desugar the match ergonomics: `&` error: patterns are not allowed to reset the default binding mode in rust 2024 - --> $DIR/min_match_ergonomics_fail.rs:36:19 + --> $DIR/min_match_ergonomics_fail.rs:33:19 | LL | test_pat_on_type![(mut x,): &(T,)]; | -^^^^^^^ @@ -132,7 +132,7 @@ LL | test_pat_on_type![(mut x,): &(T,)]; | help: desugar the match ergonomics: `&` error: patterns are not allowed to reset the default binding mode in rust 2024 - --> $DIR/min_match_ergonomics_fail.rs:37:19 + --> $DIR/min_match_ergonomics_fail.rs:34:19 | LL | test_pat_on_type![(ref x,): &(T,)]; | -^^^^^^^ @@ -140,7 +140,7 @@ LL | test_pat_on_type![(ref x,): &(T,)]; | help: desugar the match ergonomics: `&` error: patterns are not allowed to reset the default binding mode in rust 2024 - --> $DIR/min_match_ergonomics_fail.rs:38:19 + --> $DIR/min_match_ergonomics_fail.rs:35:19 | LL | test_pat_on_type![(ref mut x,): &mut (T,)]; | -^^^^^^^^^^^ @@ -148,7 +148,7 @@ LL | test_pat_on_type![(ref mut x,): &mut (T,)]; | help: desugar the match ergonomics: `&mut` error: patterns are not allowed to reset the default binding mode in rust 2024 - --> $DIR/min_match_ergonomics_fail.rs:47:9 + --> $DIR/min_match_ergonomics_fail.rs:44:9 | LL | (&x,) => x, | -^^^^ diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_success.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_success.rs index 8dbbd7cfbb0..0fb448afca9 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_success.rs +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_success.rs @@ -1,6 +1,4 @@ -//@ revisions: normal min_match_ergonomics //@ check-pass -#![cfg_attr(min_match_ergonomics, feature(min_match_ergonomics_2024))] #![allow(incomplete_features)] fn main() {} From 2ef0a8fdfd5142e8a524f4dc9fff8c65d0bd7cc2 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Tue, 8 Oct 2024 00:14:35 +0200 Subject: [PATCH 054/357] Change error message --- compiler/rustc_mir_build/messages.ftl | 2 +- .../rustc_mir_build/src/thir/pattern/mod.rs | 7 ++-- .../migration_lint.fixed | 30 ++++++++--------- .../migration_lint.rs | 30 ++++++++--------- .../migration_lint.stderr | 32 +++++++++---------- .../min_match_ergonomics_fail.stderr | 14 ++++---- 6 files changed, 57 insertions(+), 58 deletions(-) diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl index 1c4e9fd11cb..55149570dbc 100644 --- a/compiler/rustc_mir_build/messages.ftl +++ b/compiler/rustc_mir_build/messages.ftl @@ -265,7 +265,7 @@ mir_build_pointer_pattern = function pointers and raw pointers not derived from mir_build_privately_uninhabited = pattern `{$witness_1}` is currently uninhabited, but this variant contains private fields which may become inhabited in the future -mir_build_rust_2024_incompatible_pat = the semantics of this pattern will change in edition 2024 +mir_build_rust_2024_incompatible_pat = patterns are not allowed to reset the default binding mode in edition 2024 mir_build_rustc_box_attribute_error = `#[rustc_box]` attribute used incorrectly .attributes = no other attributes may be applied diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index bb02ee37733..16b7cac4e4d 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -25,6 +25,7 @@ use tracing::{debug, instrument}; pub(crate) use self::check_match::check_match; use crate::errors::*; +use crate::fluent_generated as fluent; use crate::thir::util::UserAnnotatedTyHelpers; struct PatCtxt<'a, 'tcx> { @@ -58,10 +59,8 @@ pub(super) fn pat_from_hir<'a, 'tcx>( debug!("pat_from_hir({:?}) = {:?}", pat, result); if let Some(sugg) = pcx.rust_2024_migration_suggestion { if sugg.is_hard_error { - let mut err = tcx.dcx().struct_span_err( - pat.span, - "patterns are not allowed to reset the default binding mode in rust 2024", - ); + let mut err = + tcx.dcx().struct_span_err(pat.span, fluent::mir_build_rust_2024_incompatible_pat); err.subdiagnostic(sugg); err.emit(); } else { diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.fixed b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.fixed index 90c35b5a697..086671e69cb 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.fixed +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.fixed @@ -23,22 +23,22 @@ fn main() { assert_type_eq(x, &mut 0u8); let &Foo(mut x) = &Foo(0); - //~^ ERROR: the semantics of this pattern will change in edition 2024 + //~^ ERROR: patterns are not allowed to reset the default binding mode //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); let &mut Foo(mut x) = &mut Foo(0); - //~^ ERROR: the semantics of this pattern will change in edition 2024 + //~^ ERROR: patterns are not allowed to reset the default binding mode //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); let &Foo(ref x) = &Foo(0); - //~^ ERROR: the semantics of this pattern will change in edition 2024 + //~^ ERROR: patterns are not allowed to reset the default binding mode //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, &0u8); let &mut Foo(ref x) = &mut Foo(0); - //~^ ERROR: the semantics of this pattern will change in edition 2024 + //~^ ERROR: patterns are not allowed to reset the default binding mode //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, &0u8); @@ -55,22 +55,22 @@ fn main() { assert_type_eq(x, &0u8); let &Foo(&x) = &Foo(&0); - //~^ ERROR: the semantics of this pattern will change in edition 2024 + //~^ ERROR: patterns are not allowed to reset the default binding mode //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); let &Foo(&mut x) = &Foo(&mut 0); - //~^ ERROR: the semantics of this pattern will change in edition 2024 + //~^ ERROR: patterns are not allowed to reset the default binding mode //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); let &mut Foo(&x) = &mut Foo(&0); - //~^ ERROR: the semantics of this pattern will change in edition 2024 + //~^ ERROR: patterns are not allowed to reset the default binding mode //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); let &mut Foo(&mut x) = &mut Foo(&mut 0); - //~^ ERROR: the semantics of this pattern will change in edition 2024 + //~^ ERROR: patterns are not allowed to reset the default binding mode //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); @@ -79,25 +79,25 @@ fn main() { } if let &&&&&Some(&x) = &&&&&Some(&0u8) { - //~^ ERROR: the semantics of this pattern will change in edition 2024 + //~^ ERROR: patterns are not allowed to reset the default binding mode //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); } if let &&&&&Some(&mut x) = &&&&&Some(&mut 0u8) { - //~^ ERROR: the semantics of this pattern will change in edition 2024 + //~^ ERROR: patterns are not allowed to reset the default binding mode //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); } if let &&&&&mut Some(&x) = &&&&&mut Some(&0u8) { - //~^ ERROR: the semantics of this pattern will change in edition 2024 + //~^ ERROR: patterns are not allowed to reset the default binding mode //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); } if let &mut Some(&mut Some(&mut Some(ref mut x))) = &mut Some(&mut Some(&mut Some(0u8))) { - //~^ ERROR: the semantics of this pattern will change in edition 2024 + //~^ ERROR: patterns are not allowed to reset the default binding mode //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, &mut 0u8); } @@ -109,20 +109,20 @@ fn main() { } let &Struct { ref a, mut b, ref c } = &Struct { a: 0, b: 0, c: 0 }; - //~^ ERROR: the semantics of this pattern will change in edition 2024 + //~^ ERROR: patterns are not allowed to reset the default binding mode //~| WARN: this changes meaning in Rust 2024 assert_type_eq(a, &0u32); assert_type_eq(b, 0u32); let &Struct { a: &a, ref b, ref c } = &Struct { a: &0, b: &0, c: &0 }; - //~^ ERROR: the semantics of this pattern will change in edition 2024 + //~^ ERROR: patterns are not allowed to reset the default binding mode //~| WARN: this changes meaning in Rust 2024 assert_type_eq(a, 0u32); assert_type_eq(b, &&0u32); assert_type_eq(c, &&0u32); if let &Struct { a: &Some(a), b: &Some(&b), c: &Some(ref c) } = - //~^ ERROR: the semantics of this pattern will change in edition 2024 + //~^ ERROR: patterns are not allowed to reset the default binding mode //~| WARN: this changes meaning in Rust 2024 &(Struct { a: &Some(&0), b: &Some(&0), c: &Some(&0) }) { diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.rs index 04d547f3018..acceafdb7ec 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.rs +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.rs @@ -23,22 +23,22 @@ fn main() { assert_type_eq(x, &mut 0u8); let Foo(mut x) = &Foo(0); - //~^ ERROR: the semantics of this pattern will change in edition 2024 + //~^ ERROR: patterns are not allowed to reset the default binding mode //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); let Foo(mut x) = &mut Foo(0); - //~^ ERROR: the semantics of this pattern will change in edition 2024 + //~^ ERROR: patterns are not allowed to reset the default binding mode //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); let Foo(ref x) = &Foo(0); - //~^ ERROR: the semantics of this pattern will change in edition 2024 + //~^ ERROR: patterns are not allowed to reset the default binding mode //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, &0u8); let Foo(ref x) = &mut Foo(0); - //~^ ERROR: the semantics of this pattern will change in edition 2024 + //~^ ERROR: patterns are not allowed to reset the default binding mode //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, &0u8); @@ -55,22 +55,22 @@ fn main() { assert_type_eq(x, &0u8); let Foo(&x) = &Foo(&0); - //~^ ERROR: the semantics of this pattern will change in edition 2024 + //~^ ERROR: patterns are not allowed to reset the default binding mode //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); let Foo(&mut x) = &Foo(&mut 0); - //~^ ERROR: the semantics of this pattern will change in edition 2024 + //~^ ERROR: patterns are not allowed to reset the default binding mode //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); let Foo(&x) = &mut Foo(&0); - //~^ ERROR: the semantics of this pattern will change in edition 2024 + //~^ ERROR: patterns are not allowed to reset the default binding mode //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); let Foo(&mut x) = &mut Foo(&mut 0); - //~^ ERROR: the semantics of this pattern will change in edition 2024 + //~^ ERROR: patterns are not allowed to reset the default binding mode //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); @@ -79,25 +79,25 @@ fn main() { } if let Some(&x) = &&&&&Some(&0u8) { - //~^ ERROR: the semantics of this pattern will change in edition 2024 + //~^ ERROR: patterns are not allowed to reset the default binding mode //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); } if let Some(&mut x) = &&&&&Some(&mut 0u8) { - //~^ ERROR: the semantics of this pattern will change in edition 2024 + //~^ ERROR: patterns are not allowed to reset the default binding mode //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); } if let Some(&x) = &&&&&mut Some(&0u8) { - //~^ ERROR: the semantics of this pattern will change in edition 2024 + //~^ ERROR: patterns are not allowed to reset the default binding mode //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); } if let Some(&mut Some(Some(x))) = &mut Some(&mut Some(&mut Some(0u8))) { - //~^ ERROR: the semantics of this pattern will change in edition 2024 + //~^ ERROR: patterns are not allowed to reset the default binding mode //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, &mut 0u8); } @@ -109,20 +109,20 @@ fn main() { } let Struct { a, mut b, c } = &Struct { a: 0, b: 0, c: 0 }; - //~^ ERROR: the semantics of this pattern will change in edition 2024 + //~^ ERROR: patterns are not allowed to reset the default binding mode //~| WARN: this changes meaning in Rust 2024 assert_type_eq(a, &0u32); assert_type_eq(b, 0u32); let Struct { a: &a, b, ref c } = &Struct { a: &0, b: &0, c: &0 }; - //~^ ERROR: the semantics of this pattern will change in edition 2024 + //~^ ERROR: patterns are not allowed to reset the default binding mode //~| WARN: this changes meaning in Rust 2024 assert_type_eq(a, 0u32); assert_type_eq(b, &&0u32); assert_type_eq(c, &&0u32); if let Struct { a: &Some(a), b: Some(&b), c: Some(c) } = - //~^ ERROR: the semantics of this pattern will change in edition 2024 + //~^ ERROR: patterns are not allowed to reset the default binding mode //~| WARN: this changes meaning in Rust 2024 &(Struct { a: &Some(&0), b: &Some(&0), c: &Some(&0) }) { diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr index 4881748f71a..1c9a469e6ee 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr @@ -1,4 +1,4 @@ -error: the semantics of this pattern will change in edition 2024 +error: patterns are not allowed to reset the default binding mode in edition 2024 --> $DIR/migration_lint.rs:25:9 | LL | let Foo(mut x) = &Foo(0); @@ -14,7 +14,7 @@ note: the lint level is defined here LL | #![deny(rust_2024_incompatible_pat)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: the semantics of this pattern will change in edition 2024 +error: patterns are not allowed to reset the default binding mode in edition 2024 --> $DIR/migration_lint.rs:30:9 | LL | let Foo(mut x) = &mut Foo(0); @@ -25,7 +25,7 @@ LL | let Foo(mut x) = &mut Foo(0); = warning: this changes meaning in Rust 2024 = note: for more information, see 123076 -error: the semantics of this pattern will change in edition 2024 +error: patterns are not allowed to reset the default binding mode in edition 2024 --> $DIR/migration_lint.rs:35:9 | LL | let Foo(ref x) = &Foo(0); @@ -36,7 +36,7 @@ LL | let Foo(ref x) = &Foo(0); = warning: this changes meaning in Rust 2024 = note: for more information, see 123076 -error: the semantics of this pattern will change in edition 2024 +error: patterns are not allowed to reset the default binding mode in edition 2024 --> $DIR/migration_lint.rs:40:9 | LL | let Foo(ref x) = &mut Foo(0); @@ -47,7 +47,7 @@ LL | let Foo(ref x) = &mut Foo(0); = warning: this changes meaning in Rust 2024 = note: for more information, see 123076 -error: the semantics of this pattern will change in edition 2024 +error: patterns are not allowed to reset the default binding mode in edition 2024 --> $DIR/migration_lint.rs:57:9 | LL | let Foo(&x) = &Foo(&0); @@ -58,7 +58,7 @@ LL | let Foo(&x) = &Foo(&0); = warning: this changes meaning in Rust 2024 = note: for more information, see 123076 -error: the semantics of this pattern will change in edition 2024 +error: patterns are not allowed to reset the default binding mode in edition 2024 --> $DIR/migration_lint.rs:62:9 | LL | let Foo(&mut x) = &Foo(&mut 0); @@ -69,7 +69,7 @@ LL | let Foo(&mut x) = &Foo(&mut 0); = warning: this changes meaning in Rust 2024 = note: for more information, see 123076 -error: the semantics of this pattern will change in edition 2024 +error: patterns are not allowed to reset the default binding mode in edition 2024 --> $DIR/migration_lint.rs:67:9 | LL | let Foo(&x) = &mut Foo(&0); @@ -80,7 +80,7 @@ LL | let Foo(&x) = &mut Foo(&0); = warning: this changes meaning in Rust 2024 = note: for more information, see 123076 -error: the semantics of this pattern will change in edition 2024 +error: patterns are not allowed to reset the default binding mode in edition 2024 --> $DIR/migration_lint.rs:72:9 | LL | let Foo(&mut x) = &mut Foo(&mut 0); @@ -91,7 +91,7 @@ LL | let Foo(&mut x) = &mut Foo(&mut 0); = warning: this changes meaning in Rust 2024 = note: for more information, see 123076 -error: the semantics of this pattern will change in edition 2024 +error: patterns are not allowed to reset the default binding mode in edition 2024 --> $DIR/migration_lint.rs:81:12 | LL | if let Some(&x) = &&&&&Some(&0u8) { @@ -102,7 +102,7 @@ LL | if let Some(&x) = &&&&&Some(&0u8) { = warning: this changes meaning in Rust 2024 = note: for more information, see 123076 -error: the semantics of this pattern will change in edition 2024 +error: patterns are not allowed to reset the default binding mode in edition 2024 --> $DIR/migration_lint.rs:87:12 | LL | if let Some(&mut x) = &&&&&Some(&mut 0u8) { @@ -113,7 +113,7 @@ LL | if let Some(&mut x) = &&&&&Some(&mut 0u8) { = warning: this changes meaning in Rust 2024 = note: for more information, see 123076 -error: the semantics of this pattern will change in edition 2024 +error: patterns are not allowed to reset the default binding mode in edition 2024 --> $DIR/migration_lint.rs:93:12 | LL | if let Some(&x) = &&&&&mut Some(&0u8) { @@ -124,7 +124,7 @@ LL | if let Some(&x) = &&&&&mut Some(&0u8) { = warning: this changes meaning in Rust 2024 = note: for more information, see 123076 -error: the semantics of this pattern will change in edition 2024 +error: patterns are not allowed to reset the default binding mode in edition 2024 --> $DIR/migration_lint.rs:99:12 | LL | if let Some(&mut Some(Some(x))) = &mut Some(&mut Some(&mut Some(0u8))) { @@ -137,7 +137,7 @@ help: desugar the match ergonomics LL | if let &mut Some(&mut Some(&mut Some(ref mut x))) = &mut Some(&mut Some(&mut Some(0u8))) { | ++++ ++++ +++++++ -error: the semantics of this pattern will change in edition 2024 +error: patterns are not allowed to reset the default binding mode in edition 2024 --> $DIR/migration_lint.rs:111:9 | LL | let Struct { a, mut b, c } = &Struct { a: 0, b: 0, c: 0 }; @@ -150,7 +150,7 @@ help: desugar the match ergonomics LL | let &Struct { ref a, mut b, ref c } = &Struct { a: 0, b: 0, c: 0 }; | + +++ +++ -error: the semantics of this pattern will change in edition 2024 +error: patterns are not allowed to reset the default binding mode in edition 2024 --> $DIR/migration_lint.rs:117:9 | LL | let Struct { a: &a, b, ref c } = &Struct { a: &0, b: &0, c: &0 }; @@ -163,7 +163,7 @@ help: desugar the match ergonomics LL | let &Struct { a: &a, ref b, ref c } = &Struct { a: &0, b: &0, c: &0 }; | + +++ -error: the semantics of this pattern will change in edition 2024 +error: patterns are not allowed to reset the default binding mode in edition 2024 --> $DIR/migration_lint.rs:124:12 | LL | if let Struct { a: &Some(a), b: Some(&b), c: Some(c) } = @@ -176,7 +176,7 @@ help: desugar the match ergonomics LL | if let &Struct { a: &Some(a), b: &Some(&b), c: &Some(ref c) } = | + + + +++ -error: patterns are not allowed to reset the default binding mode in rust 2024 +error: patterns are not allowed to reset the default binding mode in edition 2024 --> $DIR/migration_lint.rs:137:9 | LL | (Some(mut x), migration_lint_macros::mixed_edition_pat!(y)) => { diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.stderr index ca34ad8d0ec..33e4f0021b7 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.stderr @@ -99,7 +99,7 @@ LL - test_pat_on_type![Foo { f: (&x,) }: &mut Foo]; LL + test_pat_on_type![Foo { f: (x,) }: &mut Foo]; | -error: patterns are not allowed to reset the default binding mode in rust 2024 +error: patterns are not allowed to reset the default binding mode in edition 2024 --> $DIR/min_match_ergonomics_fail.rs:25:19 | LL | test_pat_on_type![(&x,): &(&T,)]; @@ -107,7 +107,7 @@ LL | test_pat_on_type![(&x,): &(&T,)]; | | | help: desugar the match ergonomics: `&` -error: patterns are not allowed to reset the default binding mode in rust 2024 +error: patterns are not allowed to reset the default binding mode in edition 2024 --> $DIR/min_match_ergonomics_fail.rs:28:19 | LL | test_pat_on_type![(&mut x,): &(&mut T,)]; @@ -115,7 +115,7 @@ LL | test_pat_on_type![(&mut x,): &(&mut T,)]; | | | help: desugar the match ergonomics: `&` -error: patterns are not allowed to reset the default binding mode in rust 2024 +error: patterns are not allowed to reset the default binding mode in edition 2024 --> $DIR/min_match_ergonomics_fail.rs:32:19 | LL | test_pat_on_type![Foo { f: &(x,) }: &Foo]; @@ -123,7 +123,7 @@ LL | test_pat_on_type![Foo { f: &(x,) }: &Foo]; | | | help: desugar the match ergonomics: `&` -error: patterns are not allowed to reset the default binding mode in rust 2024 +error: patterns are not allowed to reset the default binding mode in edition 2024 --> $DIR/min_match_ergonomics_fail.rs:33:19 | LL | test_pat_on_type![(mut x,): &(T,)]; @@ -131,7 +131,7 @@ LL | test_pat_on_type![(mut x,): &(T,)]; | | | help: desugar the match ergonomics: `&` -error: patterns are not allowed to reset the default binding mode in rust 2024 +error: patterns are not allowed to reset the default binding mode in edition 2024 --> $DIR/min_match_ergonomics_fail.rs:34:19 | LL | test_pat_on_type![(ref x,): &(T,)]; @@ -139,7 +139,7 @@ LL | test_pat_on_type![(ref x,): &(T,)]; | | | help: desugar the match ergonomics: `&` -error: patterns are not allowed to reset the default binding mode in rust 2024 +error: patterns are not allowed to reset the default binding mode in edition 2024 --> $DIR/min_match_ergonomics_fail.rs:35:19 | LL | test_pat_on_type![(ref mut x,): &mut (T,)]; @@ -147,7 +147,7 @@ LL | test_pat_on_type![(ref mut x,): &mut (T,)]; | | | help: desugar the match ergonomics: `&mut` -error: patterns are not allowed to reset the default binding mode in rust 2024 +error: patterns are not allowed to reset the default binding mode in edition 2024 --> $DIR/min_match_ergonomics_fail.rs:44:9 | LL | (&x,) => x, From cb267b4c560715f9e5fa60010c92be4003655c67 Mon Sep 17 00:00:00 2001 From: AngelicosPhosphoros Date: Tue, 8 Oct 2024 00:23:53 +0200 Subject: [PATCH 055/357] Add docs about slicing slices at the ends Closes https://github.com/rust-lang/rust/issues/60783 --- library/core/src/primitive_docs.rs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index c25501f1200..89936dc12ac 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -862,6 +862,27 @@ mod prim_array {} /// assert_eq!(x, &[1, 7, 3]); /// ``` /// +/// It is possible to slice empty subranges of slices by using empty ranges (including `slice.len()..slice.len()`): +/// ``` +/// let x = [1, 2, 3]; +/// let empty = &x[0..0]; // subslice before the first element +/// assert_eq!(empty, &[]); +/// let empty = &x[..0]; // same as &x[0..0] +/// assert_eq!(empty, &[]); +/// let empty = &x[1..1]; // empty subslice in the middle +/// assert_eq!(empty, &[]); +/// let empty = &x[3..3]; // subslice after the last element +/// assert_eq!(empty, &[]); +/// let empty = &x[3..]; // same as &x[3..3] +/// assert_eq!(empty, &[]); +/// ``` +/// +/// It is not allowed to use subranges that start with lower bound bigger than `slice.len()`: +/// ```should_panic +/// let x = vec![1, 2, 3]; +/// let _ = &x[4..4]; +/// ``` +/// /// As slices store the length of the sequence they refer to, they have twice /// the size of pointers to [`Sized`](marker/trait.Sized.html) types. /// Also see the reference on From 03abf6756ded764648c500d39e506d34ca30868b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= Date: Thu, 3 Oct 2024 14:27:47 +0000 Subject: [PATCH 056/357] Use untracked env var to pass `-Zon-broken-pipe=kill` for tools - Don't touch rustc's `-Zon-broken-pipe=kill` env var in `compile.rs`. - Use an untracked env var to pass `-Zon-broken-pipe=kill` for tools but skip cargo still, because cargo wants `-Zon-broken-pipe=kill` unset. --- src/bootstrap/src/bin/rustc.rs | 8 ++++++ src/bootstrap/src/core/build_steps/compile.rs | 15 +++++++++-- src/bootstrap/src/core/build_steps/tool.rs | 25 ++++++++++++++++--- 3 files changed, 42 insertions(+), 6 deletions(-) diff --git a/src/bootstrap/src/bin/rustc.rs b/src/bootstrap/src/bin/rustc.rs index 780979ed981..6f7ccde5e5b 100644 --- a/src/bootstrap/src/bin/rustc.rs +++ b/src/bootstrap/src/bin/rustc.rs @@ -136,6 +136,14 @@ fn main() { cmd.args(lint_flags.split_whitespace()); } + // Conditionally pass `-Zon-broken-pipe=kill` to rustc bin shim when this shim is *not* used to + // build cargo itself, i.e. set `-Zon-broken-pipe=kill` only when building non-cargo tools. + // + // See for more context. + if env::var_os("FORCE_ON_BROKEN_PIPE_KILL").is_some() { + cmd.arg("-Z").arg("on-broken-pipe=kill"); + } + if target.is_some() { // The stage0 compiler has a special sysroot distinct from what we // actually downloaded, so we just always pass the `--sysroot` option, diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index b5be7d841dd..27bbc8bd8ff 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -1053,8 +1053,19 @@ pub fn rustc_cargo( cargo.rustdocflag("-Zcrate-attr=warn(rust_2018_idioms)"); - // If the rustc output is piped to e.g. `head -n1` we want the process to be - // killed, rather than having an error bubble up and cause a panic. + // If the rustc output is piped to e.g. `head -n1` we want the process to be killed, rather than + // having an error bubble up and cause a panic. + // + // FIXME(jieyouxu): this flag is load-bearing for rustc to not ICE on broken pipes, because + // rustc internally sometimes uses std `println!` -- but std `println!` by default will panic on + // broken pipes, and uncaught panics will manifest as an ICE. The compiler *should* handle this + // properly, but this flag is set in the meantime to paper over the I/O errors. + // + // See for details. + // + // Also see the discussion for properly handling I/O errors related to broken pipes, i.e. safe + // variants of `println!` in + // . cargo.rustflag("-Zon-broken-pipe=kill"); if builder.config.llvm_enzyme { diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs index e2fcd13efe3..a01497c2bb9 100644 --- a/src/bootstrap/src/core/build_steps/tool.rs +++ b/src/bootstrap/src/core/build_steps/tool.rs @@ -209,11 +209,28 @@ pub fn prepare_tool_cargo( // See https://github.com/rust-lang/rust/issues/116538 cargo.rustflag("-Zunstable-options"); - // `-Zon-broken-pipe=kill` breaks cargo tests + // NOTE: The root cause of needing `-Zon-broken-pipe=kill` in the first place is because `rustc` + // and `rustdoc` doesn't gracefully handle I/O errors due to usages of raw std `println!` macros + // which panics upon encountering broken pipes. `-Zon-broken-pipe=kill` just papers over that + // and stops rustc/rustdoc ICEing on e.g. `rustc --print=sysroot | false`. + // + // cargo explicitly does not want the `-Zon-broken-pipe=kill` paper because it does actually use + // variants of `println!` that handles I/O errors gracefully. It's also a breaking change for a + // spawn process not written in Rust, especially if the language default handler is not + // `SIG_IGN`. Thankfully cargo tests will break if we do set the flag. + // + // For the cargo discussion, see + // . + // + // For the rustc discussion, see + // + // for proper solutions. if !path.ends_with("cargo") { - // If the output is piped to e.g. `head -n1` we want the process to be killed, - // rather than having an error bubble up and cause a panic. - cargo.rustflag("-Zon-broken-pipe=kill"); + // Use an untracked env var `FORCE_ON_BROKEN_PIPE_KILL` here instead of `RUSTFLAGS`. + // `RUSTFLAGS` is tracked by cargo. Conditionally omitting `-Zon-broken-pipe=kill` from + // `RUSTFLAGS` causes unnecessary tool rebuilds due to cache invalidation from building e.g. + // cargo *without* `-Zon-broken-pipe=kill` but then rustdoc *with* `-Zon-broken-pipe=kill`. + cargo.env("FORCE_ON_BROKEN_PIPE_KILL", "-Zon-broken-pipe=kill"); } cargo From e502a7f13a4605503e1b73cfdfb69d64d11ea722 Mon Sep 17 00:00:00 2001 From: Henry Jiang Date: Mon, 7 Oct 2024 20:40:55 -0400 Subject: [PATCH 057/357] add aix aggregate test --- tests/assembly/powerpc64-struct-abi.rs | 43 +++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/tests/assembly/powerpc64-struct-abi.rs b/tests/assembly/powerpc64-struct-abi.rs index 9a3540d8b41..7052937acf6 100644 --- a/tests/assembly/powerpc64-struct-abi.rs +++ b/tests/assembly/powerpc64-struct-abi.rs @@ -1,4 +1,4 @@ -//@ revisions: elfv1-be elfv2-be elfv2-le +//@ revisions: elfv1-be elfv2-be elfv2-le aix //@ assembly-output: emit-asm //@ compile-flags: -O //@[elfv1-be] compile-flags: --target powerpc64-unknown-linux-gnu @@ -7,8 +7,13 @@ //@[elfv2-be] needs-llvm-components: powerpc //@[elfv2-le] compile-flags: --target powerpc64le-unknown-linux-gnu //@[elfv2-le] needs-llvm-components: powerpc +//@[aix] compile-flags: --target powerpc64-ibm-aix +//@[aix] needs-llvm-components: powerpc //@[elfv1-be] filecheck-flags: --check-prefix be //@[elfv2-be] filecheck-flags: --check-prefix be +//@[elfv1-be] filecheck-flags: --check-prefix elf +//@[elfv2-be] filecheck-flags: --check-prefix elf +//@[elfv2-le] filecheck-flags: --check-prefix elf #![feature(no_core, lang_items)] #![no_std] @@ -44,6 +49,10 @@ struct FiveU16s(u16, u16, u16, u16, u16); struct ThreeU8s(u8, u8, u8); // CHECK-LABEL: read_large +// aix: lwz [[REG1:.*]], 16(4) +// aix-NEXT: lxvd2x 0, 0, 4 +// aix-NEXT: stw [[REG1]], 16(3) +// aix-NEXT: stxvd2x 0, 0, 3 // be: lwz [[REG1:.*]], 16(4) // be-NEXT: stw [[REG1]], 16(3) // be-NEXT: ld [[REG2:.*]], 8(4) @@ -61,6 +70,10 @@ extern "C" fn read_large(x: &FiveU32s) -> FiveU32s { } // CHECK-LABEL: read_medium +// aix: lhz [[REG1:.*]], 8(4) +// aix-NEXT: ld [[REG2:.*]], 0(4) +// aix-NEXT: sth [[REG1]], 8(3) +// aix-NEXT: std [[REG2]], 0(3) // elfv1-be: lhz [[REG1:.*]], 8(4) // elfv1-be-NEXT: ld [[REG2:.*]], 0(4) // elfv1-be-NEXT: sth [[REG1]], 8(3) @@ -78,6 +91,10 @@ extern "C" fn read_medium(x: &FiveU16s) -> FiveU16s { } // CHECK-LABEL: read_small +// aix: lbz [[REG1:.*]], 2(4) +// aix-NEXT: lhz [[REG2:.*]], 0(4) +// aix-NEXT: stb [[REG1]], 2(3) +// aix-NEXT: sth [[REG2]], 0(3) // elfv1-be: lbz [[REG1:.*]], 2(4) // elfv1-be-NEXT: lhz [[REG2:.*]], 0(4) // elfv1-be-NEXT: stb [[REG1]], 2(3) @@ -95,9 +112,17 @@ extern "C" fn read_small(x: &ThreeU8s) -> ThreeU8s { } // CHECK-LABEL: write_large -// CHECK: std 3, 0(6) +// aix: std 3, 48(1) +// aix-NEXT: rldicl [[REG1:.*]], 5, 32, 32 +// aix-NEXT: std 5, 64(1) +// aix-NEXT: std 4, 56(1) +// aix-NEXT: stw [[REG1]], 16(6) +// aix-NEXT: addi [[REG2:.*]], 1, 48 +// aix-NEXT: lxvd2x 0, 0, [[REG2]] +// aix-NEXT: stxvd2x 0, 0, 6 +// elf: std 3, 0(6) // be-NEXT: rldicl [[REG1:.*]], 5, 32, 32 -// CHECK-NEXT: std 4, 8(6) +// elf-NEXT: std 4, 8(6) // be-NEXT: stw [[REG1]], 16(6) // elfv2-le-NEXT: stw 5, 16(6) // CHECK-NEXT: blr @@ -107,7 +132,12 @@ extern "C" fn write_large(x: FiveU32s, dest: &mut FiveU32s) { } // CHECK-LABEL: write_medium -// CHECK: std 3, 0(5) +// aix: std 4, 56(1) +// aix-NEXT: rldicl [[REG1:.*]], 4, 16, 48 +// aix-NEXT: std 3, 48(1) +// aix-NEXT: std 3, 0(5) +// aix-NEXT: sth [[REG1]], 8(5) +// elf: std 3, 0(5) // be-NEXT: rldicl [[REG1:.*]], 4, 16, 48 // be-NEXT: sth [[REG1]], 8(5) // elfv2-le-NEXT: sth 4, 8(5) @@ -118,6 +148,11 @@ extern "C" fn write_medium(x: FiveU16s, dest: &mut FiveU16s) { } // CHECK-LABEL: write_small +// aix: std 3, 48(1) +// aix-NEXT: rldicl [[REG1:.*]], 3, 16, 48 +// aix-NEXT: sth 3, 0(4) +// aix-NEXT: lbz 3, 50(1) +// aix-NEXT: stb [[REG1]], 2(4) // be: stb 3, 2(4) // be-NEXT: srwi [[REG1:.*]], 3, 8 // be-NEXT: sth [[REG1]], 0(4) From 5c0131641d2edfc21e4f627f94f0aadc6cfc6e47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= Date: Thu, 3 Oct 2024 16:27:11 +0000 Subject: [PATCH 058/357] Add regression test for rustc/rustdoc broken pipe ICEs --- src/bootstrap/src/bin/rustc.rs | 6 +- tests/run-make/broken-pipe-no-ice/rmake.rs | 73 ++++++++++++++++++++++ 2 files changed, 75 insertions(+), 4 deletions(-) create mode 100644 tests/run-make/broken-pipe-no-ice/rmake.rs diff --git a/src/bootstrap/src/bin/rustc.rs b/src/bootstrap/src/bin/rustc.rs index 6f7ccde5e5b..18f5a1a58db 100644 --- a/src/bootstrap/src/bin/rustc.rs +++ b/src/bootstrap/src/bin/rustc.rs @@ -136,10 +136,8 @@ fn main() { cmd.args(lint_flags.split_whitespace()); } - // Conditionally pass `-Zon-broken-pipe=kill` to rustc bin shim when this shim is *not* used to - // build cargo itself, i.e. set `-Zon-broken-pipe=kill` only when building non-cargo tools. - // - // See for more context. + // Conditionally pass `-Zon-broken-pipe=kill` to underlying rustc. Not all binaries want + // `-Zon-broken-pipe=kill`, which includes cargo itself. if env::var_os("FORCE_ON_BROKEN_PIPE_KILL").is_some() { cmd.arg("-Z").arg("on-broken-pipe=kill"); } diff --git a/tests/run-make/broken-pipe-no-ice/rmake.rs b/tests/run-make/broken-pipe-no-ice/rmake.rs new file mode 100644 index 00000000000..d1db0bc7368 --- /dev/null +++ b/tests/run-make/broken-pipe-no-ice/rmake.rs @@ -0,0 +1,73 @@ +//! Check that `rustc` and `rustdoc` does not ICE upon encountering a broken pipe due to unhandled +//! panics from raw std `println!` usages. +//! +//! Regression test for . + +//@ ignore-cross-compile (needs to run test binary) + +#![feature(anonymous_pipe)] + +use std::io::Read; +use std::process::{Command, Stdio}; + +use run_make_support::env_var; + +#[derive(Debug, PartialEq)] +enum Binary { + Rustc, + Rustdoc, +} + +fn check_broken_pipe_handled_gracefully(bin: Binary, mut cmd: Command) { + let (reader, writer) = std::pipe::pipe().unwrap(); + drop(reader); // close read-end + cmd.stdout(writer).stderr(Stdio::piped()); + + let mut child = cmd.spawn().unwrap(); + + let mut stderr = String::new(); + child.stderr.as_mut().unwrap().read_to_string(&mut stderr).unwrap(); + let status = child.wait().unwrap(); + + assert!(!status.success(), "{bin:?} unexpectedly succeeded"); + + const PANIC_ICE_EXIT_CODE: i32 = 101; + + #[cfg(not(windows))] + { + // On non-Windows, rustc/rustdoc built with `-Zon-broken-pipe=kill` shouldn't have an exit + // code of 101 because it should have an wait status that corresponds to SIGPIPE signal + // number. + assert_ne!(status.code(), Some(PANIC_ICE_EXIT_CODE), "{bin:?}"); + // And the stderr should be empty because rustc/rustdoc should've gotten killed. + assert!(stderr.is_empty(), "{bin:?} stderr:\n{}", stderr); + } + + #[cfg(windows)] + { + match bin { + // On Windows, rustc has a paper that propagates the panic exit code of 101 but converts + // broken pipe errors into fatal errors instead of ICEs. + Binary::Rustc => { + assert_eq!(status.code(), Some(PANIC_ICE_EXIT_CODE), "{bin:?}"); + // But make sure it doesn't manifest as an ICE. + assert!(!stderr.contains("internal compiler error"), "{bin:?} ICE'd"); + } + // On Windows, rustdoc seems to cleanly exit with exit code of 1. + Binary::Rustdoc => { + assert_eq!(status.code(), Some(1), "{bin:?}"); + assert!(!stderr.contains("panic"), "{bin:?} stderr contains panic"); + } + } + } +} + +fn main() { + let mut rustc = Command::new(env_var("RUSTC")); + rustc.arg("--print=sysroot"); + check_broken_pipe_handled_gracefully(Binary::Rustc, rustc); + + let mut rustdoc = Command::new(env_var("RUSTDOC")); + rustdoc.arg("--version"); + check_broken_pipe_handled_gracefully(Binary::Rustdoc, rustdoc); +} From abf212c16cbc2fdef9dc4b515165f144c716f3d3 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 2 Oct 2024 17:38:42 +1000 Subject: [PATCH 059/357] Remove `OutlivesEnvironmentBuilder`. `OutlivesEnvironment::new` can call `OutlivesEnvironment::with_bounds` with an empty `extra_bounds`. And once that's done, `OutlivesEnvironmentBuilder` has a single use and can be inlined and removed into `OutlivesEnvironment::with_bounds`. --- .../rustc_infer/src/infer/outlives/env.rs | 113 ++++++------------ 1 file changed, 39 insertions(+), 74 deletions(-) diff --git a/compiler/rustc_infer/src/infer/outlives/env.rs b/compiler/rustc_infer/src/infer/outlives/env.rs index a071b84a1a0..9300fc574dc 100644 --- a/compiler/rustc_infer/src/infer/outlives/env.rs +++ b/compiler/rustc_infer/src/infer/outlives/env.rs @@ -1,8 +1,7 @@ use rustc_data_structures::fx::FxIndexSet; use rustc_data_structures::transitive_relation::TransitiveRelationBuilder; -use rustc_middle::bug; -use rustc_middle::ty::{self, Region}; -use tracing::{debug, instrument}; +use rustc_middle::{bug, ty}; +use tracing::debug; use super::explicit_outlives_bounds; use crate::infer::GenericKind; @@ -54,37 +53,16 @@ pub struct OutlivesEnvironment<'tcx> { region_bound_pairs: RegionBoundPairs<'tcx>, } -/// Builder of OutlivesEnvironment. -#[derive(Debug)] -struct OutlivesEnvironmentBuilder<'tcx> { - param_env: ty::ParamEnv<'tcx>, - region_relation: TransitiveRelationBuilder>, - region_bound_pairs: RegionBoundPairs<'tcx>, -} - /// "Region-bound pairs" tracks outlives relations that are known to /// be true, either because of explicit where-clauses like `T: 'a` or /// because of implied bounds. pub type RegionBoundPairs<'tcx> = FxIndexSet>>; impl<'tcx> OutlivesEnvironment<'tcx> { - /// Create a builder using `ParamEnv` and add explicit outlives bounds into it. - fn builder(param_env: ty::ParamEnv<'tcx>) -> OutlivesEnvironmentBuilder<'tcx> { - let mut builder = OutlivesEnvironmentBuilder { - param_env, - region_relation: Default::default(), - region_bound_pairs: Default::default(), - }; - - builder.add_outlives_bounds(explicit_outlives_bounds(param_env)); - - builder - } - - #[inline] /// Create a new `OutlivesEnvironment` without extra outlives bounds. + #[inline] pub fn new(param_env: ty::ParamEnv<'tcx>) -> Self { - Self::builder(param_env).build() + Self::with_bounds(param_env, vec![]) } /// Create a new `OutlivesEnvironment` with extra outlives bounds. @@ -92,9 +70,41 @@ impl<'tcx> OutlivesEnvironment<'tcx> { param_env: ty::ParamEnv<'tcx>, extra_bounds: impl IntoIterator>, ) -> Self { - let mut builder = Self::builder(param_env); - builder.add_outlives_bounds(extra_bounds); - builder.build() + let mut region_relation = TransitiveRelationBuilder::default(); + let mut region_bound_pairs = RegionBoundPairs::default(); + + // Record relationships such as `T:'x` that don't go into the + // free-region-map but which we use here. + for outlives_bound in explicit_outlives_bounds(param_env).chain(extra_bounds) { + debug!("add_outlives_bounds: outlives_bound={:?}", outlives_bound); + match outlives_bound { + OutlivesBound::RegionSubParam(r_a, param_b) => { + region_bound_pairs + .insert(ty::OutlivesPredicate(GenericKind::Param(param_b), r_a)); + } + OutlivesBound::RegionSubAlias(r_a, alias_b) => { + region_bound_pairs + .insert(ty::OutlivesPredicate(GenericKind::Alias(alias_b), r_a)); + } + OutlivesBound::RegionSubRegion(r_a, r_b) => match (*r_a, *r_b) { + ( + ty::ReStatic | ty::ReEarlyParam(_) | ty::ReLateParam(_), + ty::ReStatic | ty::ReEarlyParam(_) | ty::ReLateParam(_), + ) => region_relation.add(r_a, r_b), + (ty::ReError(_), _) | (_, ty::ReError(_)) => {} + // FIXME(#109628): We shouldn't have existential variables in implied bounds. + // Panic here once the linked issue is resolved! + (ty::ReVar(_), _) | (_, ty::ReVar(_)) => {} + _ => bug!("add_outlives_bounds: unexpected regions: ({r_a:?}, {r_b:?})"), + }, + } + } + + OutlivesEnvironment { + param_env, + free_region_map: FreeRegionMap { relation: region_relation.freeze() }, + region_bound_pairs, + } } /// Borrows current value of the `free_region_map`. @@ -107,48 +117,3 @@ impl<'tcx> OutlivesEnvironment<'tcx> { &self.region_bound_pairs } } - -impl<'tcx> OutlivesEnvironmentBuilder<'tcx> { - #[inline] - #[instrument(level = "debug")] - fn build(self) -> OutlivesEnvironment<'tcx> { - OutlivesEnvironment { - param_env: self.param_env, - free_region_map: FreeRegionMap { relation: self.region_relation.freeze() }, - region_bound_pairs: self.region_bound_pairs, - } - } - - /// Processes outlives bounds that are known to hold, whether from implied or other sources. - fn add_outlives_bounds(&mut self, outlives_bounds: I) - where - I: IntoIterator>, - { - // Record relationships such as `T:'x` that don't go into the - // free-region-map but which we use here. - for outlives_bound in outlives_bounds { - debug!("add_outlives_bounds: outlives_bound={:?}", outlives_bound); - match outlives_bound { - OutlivesBound::RegionSubParam(r_a, param_b) => { - self.region_bound_pairs - .insert(ty::OutlivesPredicate(GenericKind::Param(param_b), r_a)); - } - OutlivesBound::RegionSubAlias(r_a, alias_b) => { - self.region_bound_pairs - .insert(ty::OutlivesPredicate(GenericKind::Alias(alias_b), r_a)); - } - OutlivesBound::RegionSubRegion(r_a, r_b) => match (*r_a, *r_b) { - ( - ty::ReStatic | ty::ReEarlyParam(_) | ty::ReLateParam(_), - ty::ReStatic | ty::ReEarlyParam(_) | ty::ReLateParam(_), - ) => self.region_relation.add(r_a, r_b), - (ty::ReError(_), _) | (_, ty::ReError(_)) => {} - // FIXME(#109628): We shouldn't have existential variables in implied bounds. - // Panic here once the linked issue is resolved! - (ty::ReVar(_), _) | (_, ty::ReVar(_)) => {} - _ => bug!("add_outlives_bounds: unexpected regions: ({r_a:?}, {r_b:?})"), - }, - } - } - } -} From 27dad009c61e6a21fc7cb438a08597cf0ec0b1c8 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 3 Oct 2024 09:25:41 +1000 Subject: [PATCH 060/357] Add a useful comment about `InferOk`. Prompted by #131134, which tried to remove `InferOk<'tcx, ()>` occurrences. --- compiler/rustc_infer/src/infer/mod.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index cb60d9f286b..29936fadc57 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -67,6 +67,13 @@ pub mod resolve; pub(crate) mod snapshot; mod type_variable; +/// `InferOk<'tcx, ()>` is used a lot. It may seem like a useless wrapper +/// around `Vec>`, but it has one important property: +/// because `InferOk` is marked with `#[must_use]`, if you have a method +/// `InferCtxt::f` that returns `InferResult<'tcx, ()>` and you call it with +/// `infcx.f()?;` you'll get a warning about the obligations being discarded +/// without use, which is probably unintentional and has been a source of bugs +/// in the past. #[must_use] #[derive(Debug)] pub struct InferOk<'tcx, T> { From 0293827e093b233eda3a403a5238c164200bfc98 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 2 Oct 2024 14:07:57 +1000 Subject: [PATCH 061/357] Improve formatting of some comments. I.e. fixing comments lines that are too long or too short. --- compiler/rustc_infer/src/infer/mod.rs | 12 ++-- .../rustc_infer/src/infer/opaque_types/mod.rs | 10 ++-- .../src/infer/outlives/obligations.rs | 11 ++-- .../infer/region_constraints/leak_check.rs | 11 ++-- .../src/infer/relate/generalize.rs | 6 +- compiler/rustc_infer/src/traits/project.rs | 55 ++++++++----------- 6 files changed, 51 insertions(+), 54 deletions(-) diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 29936fadc57..f2cb28fd6f6 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1011,8 +1011,8 @@ impl<'tcx> InferCtxt<'tcx> { ty::Const::new_infer(self.tcx, ty::InferConst::EffectVar(effect_vid)).into() } - /// Given a set of generics defined on a type or impl, returns the generic parameters mapping each - /// type/region parameter to a fresh inference variable. + /// Given a set of generics defined on a type or impl, returns the generic parameters mapping + /// each type/region parameter to a fresh inference variable. pub fn fresh_args_for_item(&self, span: Span, def_id: DefId) -> GenericArgsRef<'tcx> { GenericArgs::for_item(self.tcx, def_id, |param, _| self.var_for_def(span, param)) } @@ -1390,10 +1390,10 @@ impl<'tcx> InferCtxt<'tcx> { /// /// The constant can be located on a trait like `::C`, in which case the given /// generic parameters and environment are used to resolve the constant. Alternatively if the - /// constant has generic parameters in scope the instantiations are used to evaluate the value of - /// the constant. For example in `fn foo() { let _ = [0; bar::()]; }` the repeat count - /// constant `bar::()` requires a instantiation for `T`, if the instantiation for `T` is still - /// too generic for the constant to be evaluated then `Err(ErrorHandled::TooGeneric)` is + /// constant has generic parameters in scope the instantiations are used to evaluate the value + /// of the constant. For example in `fn foo() { let _ = [0; bar::()]; }` the repeat count + /// constant `bar::()` requires a instantiation for `T`, if the instantiation for `T` is + /// still too generic for the constant to be evaluated then `Err(ErrorHandled::TooGeneric)` is /// returned. /// /// This handles inferences variables within both `param_env` and `args` by diff --git a/compiler/rustc_infer/src/infer/opaque_types/mod.rs b/compiler/rustc_infer/src/infer/opaque_types/mod.rs index 5a2ffbf029e..365ddaba138 100644 --- a/compiler/rustc_infer/src/infer/opaque_types/mod.rs +++ b/compiler/rustc_infer/src/infer/opaque_types/mod.rs @@ -148,11 +148,11 @@ impl<'tcx> InferCtxt<'tcx> { } if let ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }) = *b.kind() { - // We could accept this, but there are various ways to handle this situation, and we don't - // want to make a decision on it right now. Likely this case is so super rare anyway, that - // no one encounters it in practice. - // It does occur however in `fn fut() -> impl Future { async { 42 } }`, - // where it is of no concern, so we only check for TAITs. + // We could accept this, but there are various ways to handle this situation, + // and we don't want to make a decision on it right now. Likely this case is so + // super rare anyway, that no one encounters it in practice. It does occur + // however in `fn fut() -> impl Future { async { 42 } }`, where + // it is of no concern, so we only check for TAITs. if self.can_define_opaque_ty(b_def_id) && self.tcx.is_type_alias_impl_trait(b_def_id) { diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index 634cda86bc3..e0e03a29220 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -396,11 +396,12 @@ where // 'a` in the environment but `trait Foo<'b> { type Item: 'b // }` in the trait definition. approx_env_bounds.retain(|bound_outlives| { - // OK to skip binder because we only manipulate and compare against other - // values from the same binder. e.g. if we have (e.g.) `for<'a> >::Item: 'a` - // in `bound`, the `'a` will be a `^1` (bound, debruijn index == innermost) region. - // If the declaration is `trait Trait<'b> { type Item: 'b; }`, then `projection_declared_bounds_from_trait` - // will be invoked with `['b => ^1]` and so we will get `^1` returned. + // OK to skip binder because we only manipulate and compare against other values from + // the same binder. e.g. if we have (e.g.) `for<'a> >::Item: 'a` in + // `bound`, the `'a` will be a `^1` (bound, debruijn index == innermost) region. If the + // declaration is `trait Trait<'b> { type Item: 'b; }`, then + // `projection_declared_bounds_from_trait` will be invoked with `['b => ^1]` and so we + // will get `^1` returned. let bound = bound_outlives.skip_binder(); let ty::Alias(_, alias_ty) = bound.0.kind() else { bug!("expected AliasTy") }; self.verify_bound.declared_bounds_from_definition(*alias_ty).all(|r| r != bound.1) diff --git a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs index 7913f0e340e..30eba3e8f4f 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs @@ -55,8 +55,8 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { /// * what placeholder they must outlive transitively /// * if they must also be equal to a placeholder, report an error because `P1: P2` /// * minimum universe U of all SCCs they must outlive - /// * if they must also be equal to a placeholder P, and U cannot name P, report an error, as that - /// indicates `P: R` and `R` is in an incompatible universe + /// * if they must also be equal to a placeholder P, and U cannot name P, report an error, as + /// that indicates `P: R` and `R` is in an incompatible universe /// /// To improve performance and for the old trait solver caching to be sound, this takes /// an optional snapshot in which case we only look at region constraints added in that @@ -216,8 +216,8 @@ impl<'a, 'b, 'tcx> LeakCheck<'a, 'b, 'tcx> { // Walk over each `scc2` such that `scc1: scc2` and compute: // // * `scc1_universe`: the minimum universe of `scc2` and the constituents of `scc1` - // * `succ_bound`: placeholder `P` that the successors must outlive, if any (if there are multiple, - // we pick one arbitrarily) + // * `succ_bound`: placeholder `P` that the successors must outlive, if any (if there + // are multiple, we pick one arbitrarily) let mut scc1_universe = self.scc_universes[scc1]; let mut succ_bound = None; for &scc2 in self.mini_graph.sccs.successors(scc1) { @@ -260,7 +260,8 @@ impl<'a, 'b, 'tcx> LeakCheck<'a, 'b, 'tcx> { self.scc_placeholders[scc1] = succ_bound; } - // At this point, `scc_placeholder[scc1]` stores some placeholder that `scc1` must outlive (if any). + // At this point, `scc_placeholder[scc1]` stores some placeholder that `scc1` must + // outlive (if any). } Ok(()) } diff --git a/compiler/rustc_infer/src/infer/relate/generalize.rs b/compiler/rustc_infer/src/infer/relate/generalize.rs index a6d10aa5968..726a2296d11 100644 --- a/compiler/rustc_infer/src/infer/relate/generalize.rs +++ b/compiler/rustc_infer/src/infer/relate/generalize.rs @@ -50,7 +50,8 @@ impl<'tcx> InferCtxt<'tcx> { // Then the `generalized_ty` would be `&'?2 ?3`, where `'?2` and `?3` are fresh // region/type inference variables. // - // We then relate `generalized_ty <: source_ty`,adding constraints like `'x: '?2` and `?1 <: ?3`. + // We then relate `generalized_ty <: source_ty`, adding constraints like `'x: '?2` and + // `?1 <: ?3`. let Generalization { value_may_be_infer: generalized_ty, has_unconstrained_ty_var } = self .generalize( relation.span(), @@ -104,7 +105,8 @@ impl<'tcx> InferCtxt<'tcx> { &ty::Alias(ty::Projection, data) => { // FIXME: This does not handle subtyping correctly, we could // instead create a new inference variable `?normalized_source`, emitting - // `Projection(normalized_source, ?ty_normalized)` and `?normalized_source <: generalized_ty`. + // `Projection(normalized_source, ?ty_normalized)` and + // `?normalized_source <: generalized_ty`. relation.register_predicates([ty::ProjectionPredicate { projection_term: data.into(), term: generalized_ty.into(), diff --git a/compiler/rustc_infer/src/traits/project.rs b/compiler/rustc_infer/src/traits/project.rs index fa813d0f90c..64b72de3986 100644 --- a/compiler/rustc_infer/src/traits/project.rs +++ b/compiler/rustc_infer/src/traits/project.rs @@ -92,38 +92,31 @@ pub enum ProjectionCacheEntry<'tcx> { Error, NormalizedTerm { ty: NormalizedTerm<'tcx>, - /// If we were able to successfully evaluate the - /// corresponding cache entry key during predicate - /// evaluation, then this field stores the final - /// result obtained from evaluating all of the projection - /// sub-obligations. During evaluation, we will skip - /// evaluating the cached sub-obligations in `ty` - /// if this field is set. Evaluation only - /// cares about the final result, so we don't - /// care about any region constraint side-effects - /// produced by evaluating the sub-obligations. - /// - /// Additionally, we will clear out the sub-obligations - /// entirely if we ever evaluate the cache entry (along - /// with all its sub obligations) to `EvaluatedToOk`. - /// This affects all users of the cache, not just evaluation. - /// Since a result of `EvaluatedToOk` means that there were - /// no region obligations that need to be tracked, it's - /// fine to forget about the sub-obligations - they - /// don't provide any additional information. However, - /// we do *not* discard any obligations when we see - /// `EvaluatedToOkModuloRegions` - we don't know - /// which sub-obligations may introduce region constraints, - /// so we keep them all to be safe. - /// - /// When we are not performing evaluation - /// (e.g. in `FulfillmentContext`), we ignore this field, - /// and always re-process the cached sub-obligations - /// (which may have been cleared out - see the above - /// paragraph). - /// This ensures that we do not lose any regions - /// constraints that arise from processing the + /// If we were able to successfully evaluate the corresponding cache + /// entry key during predicate evaluation, then this field stores the + /// final result obtained from evaluating all of the projection + /// sub-obligations. During evaluation, we will skip evaluating the + /// cached sub-obligations in `ty` if this field is set. Evaluation + /// only cares about the final result, so we don't care about any + /// region constraint side-effects produced by evaluating the /// sub-obligations. + /// + /// Additionally, we will clear out the sub-obligations entirely if we + /// ever evaluate the cache entry (along with all its sub obligations) + /// to `EvaluatedToOk`. This affects all users of the cache, not just + /// evaluation. Since a result of `EvaluatedToOk` means that there were + /// no region obligations that need to be tracked, it's fine to forget + /// about the sub-obligations - they don't provide any additional + /// information. However, we do *not* discard any obligations when we + /// see `EvaluatedToOkModuloRegions` - we don't know which + /// sub-obligations may introduce region constraints, so we keep them + /// all to be safe. + /// + /// When we are not performing evaluation (e.g. in + /// `FulfillmentContext`), we ignore this field, and always re-process + /// the cached sub-obligations (which may have been cleared out - see + /// the above paragraph). This ensures that we do not lose any regions + /// constraints that arise from processing the sub-obligations. complete: Option, }, } From 2b57a785a917faa8a1c44414ed3d43e13e626f63 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 3 Oct 2024 10:44:48 +1000 Subject: [PATCH 062/357] Inline and remove `RegionConstraintCollector::into_infos_and_data`. It's a weird method, and used weirdly: - It's on `RegionConstraintCollector` but operates on `RegionConstraintStorage`. So at both call sites we create a temporary `RegionConstraintCollector`, using `with_log`, to call it. - It `take`s just two of the six fields in `RegionConstraintStorage`. At one of the two call sites we unnecessarily clone the entire `RegionConstraintStorage` just to take those two fields. This commit just inlines and removes it. We no longer need to `take` the two fields, we can just use them directly. --- compiler/rustc_infer/src/infer/mod.rs | 23 ++++++++----------- .../rustc_infer/src/infer/outlives/mod.rs | 15 +++++------- .../src/infer/region_constraints/mod.rs | 12 ++-------- 3 files changed, 18 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index f2cb28fd6f6..785ef8f939e 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -18,7 +18,7 @@ pub use relate::combine::PredicateEmittingRelation; use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_data_structures::sync::Lrc; -use rustc_data_structures::undo_log::Rollback; +use rustc_data_structures::undo_log::{Rollback, UndoLogs}; use rustc_data_structures::unify as ut; use rustc_errors::{DiagCtxtHandle, ErrorGuaranteed}; use rustc_hir as hir; @@ -50,6 +50,7 @@ use snapshot::undo_log::InferCtxtUndoLogs; use tracing::{debug, instrument}; use type_variable::TypeVariableOrigin; +use crate::infer::region_constraints::UndoLog; use crate::traits::{self, ObligationCause, ObligationInspector, PredicateObligation, TraitEngine}; pub mod at; @@ -1043,18 +1044,14 @@ impl<'tcx> InferCtxt<'tcx> { /// Clone the list of variable regions. This is used only during NLL processing /// to put the set of region variables into the NLL region context. pub fn get_region_var_origins(&self) -> VarInfos { - let mut inner = self.inner.borrow_mut(); - let (var_infos, data) = inner - .region_constraint_storage - // We clone instead of taking because borrowck still wants to use - // the inference context after calling this for diagnostics - // and the new trait solver. - .clone() - .expect("regions already resolved") - .with_log(&mut inner.undo_log) - .into_infos_and_data(); - assert!(data.is_empty()); - var_infos + let inner = self.inner.borrow(); + assert!(!UndoLogs::>::in_snapshot(&inner.undo_log)); + let storage = inner.region_constraint_storage.as_ref().expect("regions already resolved"); + assert!(storage.data.is_empty()); + // We clone instead of taking because borrowck still wants to use the + // inference context after calling this for diagnostics and the new + // trait solver. + storage.var_infos.clone() } #[instrument(level = "debug", skip(self), ret)] diff --git a/compiler/rustc_infer/src/infer/outlives/mod.rs b/compiler/rustc_infer/src/infer/outlives/mod.rs index a270f9322f3..e23bb1aaa56 100644 --- a/compiler/rustc_infer/src/infer/outlives/mod.rs +++ b/compiler/rustc_infer/src/infer/outlives/mod.rs @@ -1,11 +1,12 @@ //! Various code related to computing outlives relations. +use rustc_data_structures::undo_log::UndoLogs; use rustc_middle::traits::query::{NoSolution, OutlivesBound}; use rustc_middle::ty; use tracing::instrument; use self::env::OutlivesEnvironment; -use super::region_constraints::RegionConstraintData; +use super::region_constraints::{RegionConstraintData, UndoLog}; use super::{InferCtxt, RegionResolutionError, SubregionOrigin}; use crate::infer::free_regions::RegionRelations; use crate::infer::lexical_region_resolve; @@ -63,7 +64,7 @@ impl<'tcx> InferCtxt<'tcx> { } }; - let (var_infos, data) = { + let storage = { let mut inner = self.inner.borrow_mut(); let inner = &mut *inner; assert!( @@ -71,18 +72,14 @@ impl<'tcx> InferCtxt<'tcx> { "region_obligations not empty: {:#?}", inner.region_obligations ); - inner - .region_constraint_storage - .take() - .expect("regions already resolved") - .with_log(&mut inner.undo_log) - .into_infos_and_data() + assert!(!UndoLogs::>::in_snapshot(&inner.undo_log)); + inner.region_constraint_storage.take().expect("regions already resolved") }; let region_rels = &RegionRelations::new(self.tcx, outlives_env.free_region_map()); let (lexical_region_resolutions, errors) = - lexical_region_resolve::resolve(region_rels, var_infos, data); + lexical_region_resolve::resolve(region_rels, storage.var_infos, storage.data); let old_value = self.lexical_region_resolutions.replace(Some(lexical_region_resolutions)); assert!(old_value.is_none()); diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs index 4411f8db72a..0d9249bb552 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs @@ -27,9 +27,9 @@ pub use rustc_middle::infer::MemberConstraint; #[derive(Clone, Default)] pub struct RegionConstraintStorage<'tcx> { /// For each `RegionVid`, the corresponding `RegionVariableOrigin`. - var_infos: IndexVec, + pub(super) var_infos: IndexVec, - data: RegionConstraintData<'tcx>, + pub(super) data: RegionConstraintData<'tcx>, /// For a given pair of regions (R1, R2), maps to a region R3 that /// is designated as their LUB (edges R1 <= R3 and R2 <= R3 @@ -354,14 +354,6 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { &self.data } - /// Once all the constraints have been gathered, extract out the final data. - /// - /// Not legal during a snapshot. - pub fn into_infos_and_data(self) -> (VarInfos, RegionConstraintData<'tcx>) { - assert!(!UndoLogs::>::in_snapshot(&self.undo_log)); - (mem::take(&mut self.storage.var_infos), mem::take(&mut self.storage.data)) - } - /// Takes (and clears) the current set of constraints. Note that /// the set of variables remains intact, but all relationships /// between them are reset. This is used during NLL checking to From 85507cffc32de9211f03b5e257acfad4a24fcea5 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 3 Oct 2024 12:06:34 +1000 Subject: [PATCH 063/357] Inline and remove `RegionConstraintStorage::remove_constraint_entry`. It has a single call site. --- .../src/infer/region_constraints/mod.rs | 44 +++++++++---------- 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs index 0d9249bb552..a60954ad545 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs @@ -320,29 +320,6 @@ impl<'tcx> RegionConstraintStorage<'tcx> { ) -> RegionConstraintCollector<'a, 'tcx> { RegionConstraintCollector { storage: self, undo_log } } - - fn rollback_undo_entry(&mut self, undo_entry: UndoLog<'tcx>) { - match undo_entry { - AddVar(vid) => { - self.var_infos.pop().unwrap(); - assert_eq!(self.var_infos.len(), vid.index()); - } - AddConstraint(index) => { - self.data.constraints.pop().unwrap(); - assert_eq!(self.data.constraints.len(), index); - } - AddVerify(index) => { - self.data.verifys.pop(); - assert_eq!(self.data.verifys.len(), index); - } - AddCombination(Glb, ref regions) => { - self.glbs.remove(regions); - } - AddCombination(Lub, ref regions) => { - self.lubs.remove(regions); - } - } - } } impl<'tcx> RegionConstraintCollector<'_, 'tcx> { @@ -793,6 +770,25 @@ impl<'tcx> RegionConstraintData<'tcx> { impl<'tcx> Rollback> for RegionConstraintStorage<'tcx> { fn reverse(&mut self, undo: UndoLog<'tcx>) { - self.rollback_undo_entry(undo) + match undo { + AddVar(vid) => { + self.var_infos.pop().unwrap(); + assert_eq!(self.var_infos.len(), vid.index()); + } + AddConstraint(index) => { + self.data.constraints.pop().unwrap(); + assert_eq!(self.data.constraints.len(), index); + } + AddVerify(index) => { + self.data.verifys.pop(); + assert_eq!(self.data.verifys.len(), index); + } + AddCombination(Glb, ref regions) => { + self.glbs.remove(regions); + } + AddCombination(Lub, ref regions) => { + self.lubs.remove(regions); + } + } } } From e8a0bd65498976656fbb7fff7d74fbc91cc442d1 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 3 Oct 2024 13:58:13 +1000 Subject: [PATCH 064/357] Remove unnecessary lifetime from `LeakCheck`. `LeakCheck` can own `mini_graph` and `rcc` instead of holding references to them. This requires inlining `assign_scc_value` to avoid a borrowck error, but that's fine because it has a single call site. --- .../infer/region_constraints/leak_check.rs | 54 ++++++++----------- 1 file changed, 22 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs index 30eba3e8f4f..3cfc58dea05 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs @@ -73,7 +73,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { /// * R: P1, R: P2, as above #[instrument(level = "debug", skip(self, tcx, only_consider_snapshot), ret)] pub fn leak_check( - &mut self, + self, tcx: TyCtxt<'tcx>, outer_universe: ty::UniverseIndex, max_universe: ty::UniverseIndex, @@ -83,7 +83,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { return Ok(()); } - let mini_graph = &MiniGraph::new(tcx, self, only_consider_snapshot); + let mini_graph = MiniGraph::new(tcx, &self, only_consider_snapshot); let mut leak_check = LeakCheck::new(tcx, outer_universe, max_universe, mini_graph, self); leak_check.assign_placeholder_values()?; @@ -92,11 +92,11 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { } } -struct LeakCheck<'a, 'b, 'tcx> { +struct LeakCheck<'a, 'tcx> { tcx: TyCtxt<'tcx>, outer_universe: ty::UniverseIndex, - mini_graph: &'a MiniGraph<'tcx>, - rcc: &'a mut RegionConstraintCollector<'b, 'tcx>, + mini_graph: MiniGraph<'tcx>, + rcc: RegionConstraintCollector<'a, 'tcx>, // Initially, for each SCC S, stores a placeholder `P` such that `S = P` // must hold. @@ -115,26 +115,27 @@ struct LeakCheck<'a, 'b, 'tcx> { // either the placeholder `P1` or the empty region in that same universe. // // To detect errors, we look for an SCC S where the values in - // `scc_values[S]` (if any) cannot be stored into `scc_universes[S]`. + // `scc_placeholders[S]` (if any) cannot be stored into `scc_universes[S]`. scc_universes: IndexVec>, } -impl<'a, 'b, 'tcx> LeakCheck<'a, 'b, 'tcx> { +impl<'a, 'tcx> LeakCheck<'a, 'tcx> { fn new( tcx: TyCtxt<'tcx>, outer_universe: ty::UniverseIndex, max_universe: ty::UniverseIndex, - mini_graph: &'a MiniGraph<'tcx>, - rcc: &'a mut RegionConstraintCollector<'b, 'tcx>, + mini_graph: MiniGraph<'tcx>, + rcc: RegionConstraintCollector<'a, 'tcx>, ) -> Self { let dummy_scc_universe = SccUniverse { universe: max_universe, region: None }; + let num_sccs = mini_graph.sccs.num_sccs(); Self { tcx, outer_universe, mini_graph, rcc, - scc_placeholders: IndexVec::from_elem_n(None, mini_graph.sccs.num_sccs()), - scc_universes: IndexVec::from_elem_n(dummy_scc_universe, mini_graph.sccs.num_sccs()), + scc_placeholders: IndexVec::from_elem_n(None, num_sccs), + scc_universes: IndexVec::from_elem_n(dummy_scc_universe, num_sccs), } } @@ -156,7 +157,16 @@ impl<'a, 'b, 'tcx> LeakCheck<'a, 'b, 'tcx> { // Detect those SCCs that directly contain a placeholder if let ty::RePlaceholder(placeholder) = **region { if self.outer_universe.cannot_name(placeholder.universe) { - self.assign_scc_value(scc, placeholder)?; + // Update `scc_placeholders` to account for the fact that `P: S` must hold. + match self.scc_placeholders[scc] { + Some(p) => { + assert_ne!(p, placeholder); + return Err(self.placeholder_error(p, placeholder)); + } + None => { + self.scc_placeholders[scc] = Some(placeholder); + } + } } } } @@ -164,26 +174,6 @@ impl<'a, 'b, 'tcx> LeakCheck<'a, 'b, 'tcx> { Ok(()) } - // assign_scc_value(S, P): Update `scc_values` to account for the fact that `P: S` must hold. - // This may create an error. - fn assign_scc_value( - &mut self, - scc: LeakCheckScc, - placeholder: ty::PlaceholderRegion, - ) -> RelateResult<'tcx, ()> { - match self.scc_placeholders[scc] { - Some(p) => { - assert_ne!(p, placeholder); - return Err(self.placeholder_error(p, placeholder)); - } - None => { - self.scc_placeholders[scc] = Some(placeholder); - } - }; - - Ok(()) - } - /// For each SCC S, iterate over each successor S1 where `S: S1`: /// /// * Compute From 8b05df44f96978b81df4af51f469c266b21df793 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 3 Oct 2024 14:16:55 +1000 Subject: [PATCH 065/357] Remove `Deref`/`DerefMut` impls for `RegionConstraintCollector`. `Deref`/`DerefMut` can be useful, but they can also obfuscate. I don't think they're worth it for `RegionConstraintCollector`. They're also not present on the similar types `OpaqueTypeTable` and `TypeVariableTable`. --- .../src/infer/region_constraints/mod.rs | 50 +++++++------------ 1 file changed, 18 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs index a60954ad545..c7dd65330be 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs @@ -61,21 +61,6 @@ pub struct RegionConstraintCollector<'a, 'tcx> { undo_log: &'a mut InferCtxtUndoLogs<'tcx>, } -impl<'tcx> std::ops::Deref for RegionConstraintCollector<'_, 'tcx> { - type Target = RegionConstraintStorage<'tcx>; - #[inline] - fn deref(&self) -> &RegionConstraintStorage<'tcx> { - self.storage - } -} - -impl<'tcx> std::ops::DerefMut for RegionConstraintCollector<'_, 'tcx> { - #[inline] - fn deref_mut(&mut self) -> &mut RegionConstraintStorage<'tcx> { - self.storage - } -} - pub type VarInfos = IndexVec; /// The full set of region constraints gathered up by the collector. @@ -324,11 +309,11 @@ impl<'tcx> RegionConstraintStorage<'tcx> { impl<'tcx> RegionConstraintCollector<'_, 'tcx> { pub fn num_region_vars(&self) -> usize { - self.var_infos.len() + self.storage.var_infos.len() } pub fn region_constraint_data(&self) -> &RegionConstraintData<'tcx> { - &self.data + &self.storage.data } /// Takes (and clears) the current set of constraints. Note that @@ -384,17 +369,17 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { } pub fn data(&self) -> &RegionConstraintData<'tcx> { - &self.data + &self.storage.data } pub(super) fn start_snapshot(&mut self) -> RegionSnapshot { debug!("RegionConstraintCollector: start_snapshot"); - RegionSnapshot { any_unifications: self.any_unifications } + RegionSnapshot { any_unifications: self.storage.any_unifications } } pub(super) fn rollback_to(&mut self, snapshot: RegionSnapshot) { debug!("RegionConstraintCollector: rollback_to({:?})", snapshot); - self.any_unifications = snapshot.any_unifications; + self.storage.any_unifications = snapshot.any_unifications; } pub(super) fn new_region_var( @@ -402,7 +387,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { universe: ty::UniverseIndex, origin: RegionVariableOrigin, ) -> RegionVid { - let vid = self.var_infos.push(RegionVariableInfo { origin, universe }); + let vid = self.storage.var_infos.push(RegionVariableInfo { origin, universe }); let u_vid = self.unification_table_mut().new_key(RegionVariableValue::Unknown { universe }); assert_eq!(vid, u_vid.vid); @@ -413,7 +398,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { /// Returns the origin for the given variable. pub(super) fn var_origin(&self, vid: RegionVid) -> RegionVariableOrigin { - self.var_infos[vid].origin + self.storage.var_infos[vid].origin } fn add_constraint(&mut self, constraint: Constraint<'tcx>, origin: SubregionOrigin<'tcx>) { @@ -436,8 +421,8 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { return; } - let index = self.data.verifys.len(); - self.data.verifys.push(verify); + let index = self.storage.data.verifys.len(); + self.storage.data.verifys.push(verify); self.undo_log.push(AddVerify(index)); } @@ -457,7 +442,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { (ty::ReVar(a), ty::ReVar(b)) => { debug!("make_eqregion: unifying {:?} with {:?}", a, b); if self.unification_table_mut().unify_var_var(a, b).is_ok() { - self.any_unifications = true; + self.storage.any_unifications = true; } } (ty::ReVar(vid), _) => { @@ -467,7 +452,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { .unify_var_value(vid, RegionVariableValue::Known { value: b }) .is_ok() { - self.any_unifications = true; + self.storage.any_unifications = true; }; } (_, ty::ReVar(vid)) => { @@ -477,7 +462,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { .unify_var_value(vid, RegionVariableValue::Known { value: a }) .is_ok() { - self.any_unifications = true; + self.storage.any_unifications = true; }; } (_, _) => {} @@ -499,7 +484,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { return; } - self.data.member_constraints.push(MemberConstraint { + self.storage.data.member_constraints.push(MemberConstraint { key, definition_span, hidden_ty, @@ -615,8 +600,8 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { fn combine_map(&mut self, t: CombineMapType) -> &mut CombineMap<'tcx> { match t { - Glb => &mut self.glbs, - Lub => &mut self.lubs, + Glb => &mut self.storage.glbs, + Lub => &mut self.storage.lubs, } } @@ -669,11 +654,12 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { &self, value_count: usize, ) -> (Range, Vec) { - let range = RegionVid::from(value_count)..RegionVid::from(self.unification_table.len()); + let range = + RegionVid::from(value_count)..RegionVid::from(self.storage.unification_table.len()); ( range.clone(), (range.start.index()..range.end.index()) - .map(|index| self.var_infos[ty::RegionVid::from(index)].origin) + .map(|index| self.storage.var_infos[ty::RegionVid::from(index)].origin) .collect(), ) } From 4df21f2ca0a51e0687fd7443c99ed32edb080988 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 3 Oct 2024 14:33:28 +1000 Subject: [PATCH 066/357] Downgrade a `&mut self` to `&self`. --- compiler/rustc_infer/src/infer/region_constraints/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs index c7dd65330be..6a7f30a5dcf 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs @@ -372,7 +372,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { &self.storage.data } - pub(super) fn start_snapshot(&mut self) -> RegionSnapshot { + pub(super) fn start_snapshot(&self) -> RegionSnapshot { debug!("RegionConstraintCollector: start_snapshot"); RegionSnapshot { any_unifications: self.storage.any_unifications } } From 1dac23f6fef62faf178d3bbdab15b99fc19abafa Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 3 Oct 2024 14:40:05 +1000 Subject: [PATCH 067/357] Use `Default` more in `InferCtxtInner`. --- compiler/rustc_infer/src/infer/mod.rs | 12 ++++++------ .../rustc_infer/src/infer/region_constraints/mod.rs | 4 ---- compiler/rustc_infer/src/infer/type_variable.rs | 9 +-------- 3 files changed, 7 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 785ef8f939e..21f9bf028d5 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -171,12 +171,12 @@ impl<'tcx> InferCtxtInner<'tcx> { undo_log: InferCtxtUndoLogs::default(), projection_cache: Default::default(), - type_variable_storage: type_variable::TypeVariableStorage::new(), - const_unification_storage: ut::UnificationTableStorage::new(), - int_unification_storage: ut::UnificationTableStorage::new(), - float_unification_storage: ut::UnificationTableStorage::new(), - effect_unification_storage: ut::UnificationTableStorage::new(), - region_constraint_storage: Some(RegionConstraintStorage::new()), + type_variable_storage: Default::default(), + const_unification_storage: Default::default(), + int_unification_storage: Default::default(), + float_unification_storage: Default::default(), + effect_unification_storage: Default::default(), + region_constraint_storage: Some(Default::default()), region_obligations: vec![], opaque_type_storage: Default::default(), } diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs index 6a7f30a5dcf..270217e26b7 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs @@ -294,10 +294,6 @@ pub(crate) struct RegionSnapshot { } impl<'tcx> RegionConstraintStorage<'tcx> { - pub fn new() -> Self { - Self::default() - } - #[inline] pub(crate) fn with_log<'a>( &'a mut self, diff --git a/compiler/rustc_infer/src/infer/type_variable.rs b/compiler/rustc_infer/src/infer/type_variable.rs index c50477b2922..779ce976bec 100644 --- a/compiler/rustc_infer/src/infer/type_variable.rs +++ b/compiler/rustc_infer/src/infer/type_variable.rs @@ -19,7 +19,7 @@ impl<'tcx> Rollback>>> for TypeVariabl } } -#[derive(Clone)] +#[derive(Clone, Default)] pub(crate) struct TypeVariableStorage<'tcx> { /// The origins of each type variable. values: IndexVec, @@ -74,13 +74,6 @@ impl<'tcx> TypeVariableValue<'tcx> { } impl<'tcx> TypeVariableStorage<'tcx> { - pub(crate) fn new() -> TypeVariableStorage<'tcx> { - TypeVariableStorage { - values: Default::default(), - eq_relations: ut::UnificationTableStorage::new(), - } - } - #[inline] pub(crate) fn with_log<'a>( &'a mut self, From 3b1eee775550530c51131161d3b397517ef69f10 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 7 Oct 2024 10:01:37 +1100 Subject: [PATCH 068/357] Remove unnecessary `return` keyword. --- compiler/rustc_infer/src/infer/resolve.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_infer/src/infer/resolve.rs b/compiler/rustc_infer/src/infer/resolve.rs index 025c3a629fa..64cc76f827e 100644 --- a/compiler/rustc_infer/src/infer/resolve.rs +++ b/compiler/rustc_infer/src/infer/resolve.rs @@ -38,7 +38,7 @@ impl<'a, 'tcx> TypeFolder> for OpportunisticVarResolver<'a, 'tcx> { if !t.has_non_region_infer() { t // micro-optimize -- if there is nothing in this type that this fold affects... } else if let Some(&ty) = self.cache.get(&t) { - return ty; + ty } else { let shallow = self.infcx.shallow_resolve(t); let res = shallow.super_fold_with(self); From b81a3c81998b03cab4925801edf11c3113b26184 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= Date: Tue, 8 Oct 2024 04:30:19 +0000 Subject: [PATCH 069/357] Drop compiletest legacy directive checks Sufficient time has passed (> 6 months) since we migrated from `//` to `//@`, so let's drop the legacy directive check as it causes friction due to false positives. --- src/tools/compiletest/src/header.rs | 137 +++++++----------- .../test-auxillary/known_legacy_directive.rs | 1 - src/tools/compiletest/src/header/tests.rs | 11 -- 3 files changed, 52 insertions(+), 97 deletions(-) delete mode 100644 src/tools/compiletest/src/header/test-auxillary/known_legacy_directive.rs diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 83a10c56208..a6830a6aa17 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -5,9 +5,7 @@ use std::io::BufReader; use std::io::prelude::*; use std::path::{Path, PathBuf}; use std::process::Command; -use std::sync::OnceLock; -use regex::Regex; use tracing::*; use crate::common::{Config, Debugger, FailMode, Mode, PassMode}; @@ -797,7 +795,6 @@ struct HeaderLine<'ln> { pub(crate) struct CheckDirectiveResult<'ln> { is_known_directive: bool, - directive_name: &'ln str, trailing_directive: Option<&'ln str>, } @@ -832,11 +829,7 @@ pub(crate) fn check_directive<'a>( } .then_some(trailing); - CheckDirectiveResult { - is_known_directive: is_known(&directive_name), - directive_name: directive_ln, - trailing_directive, - } + CheckDirectiveResult { is_known_directive: is_known(&directive_name), trailing_directive } } fn iter_header( @@ -851,16 +844,17 @@ fn iter_header( return; } - // Coverage tests in coverage-run mode always have these extra directives, - // without needing to specify them manually in every test file. - // (Some of the comments below have been copied over from the old - // `tests/run-make/coverage-reports/Makefile`, which no longer exists.) + // Coverage tests in coverage-run mode always have these extra directives, without needing to + // specify them manually in every test file. (Some of the comments below have been copied over + // from the old `tests/run-make/coverage-reports/Makefile`, which no longer exists.) + // + // FIXME(jieyouxu): I feel like there's a better way to do this, leaving for later. if mode == Mode::CoverageRun { let extra_directives: &[&str] = &[ "needs-profiler-support", - // FIXME(pietroalbini): this test currently does not work on cross-compiled - // targets because remote-test is not capable of sending back the *.profraw - // files generated by the LLVM instrumentation. + // FIXME(pietroalbini): this test currently does not work on cross-compiled targets + // because remote-test is not capable of sending back the *.profraw files generated by + // the LLVM instrumentation. "ignore-cross-compile", ]; // Process the extra implied directives, with a dummy line number of 0. @@ -869,17 +863,13 @@ fn iter_header( } } + // NOTE(jieyouxu): once we get rid of `Makefile`s we can unconditionally check for `//@`. let comment = if testfile.extension().is_some_and(|e| e == "rs") { "//@" } else { "#" }; let mut rdr = BufReader::with_capacity(1024, rdr); let mut ln = String::new(); let mut line_number = 0; - // Match on error annotations like `//~ERROR`. - static REVISION_MAGIC_COMMENT_RE: OnceLock = OnceLock::new(); - let revision_magic_comment_re = - REVISION_MAGIC_COMMENT_RE.get_or_init(|| Regex::new("//(\\[.*\\])?~.*").unwrap()); - loop { line_number += 1; ln.clear(); @@ -892,85 +882,62 @@ fn iter_header( // with a warm page cache. Maybe with a cold one. let original_line = &ln; let ln = ln.trim(); + + // Assume that any directives will be found before the first module or function. This + // doesn't seem to be an optimization with a warm page cache. Maybe with a cold one. + // FIXME(jieyouxu): this will cause `//@` directives in the rest of the test file to + // not be checked. if ln.starts_with("fn") || ln.starts_with("mod") { return; + } - // First try to accept `ui_test` style comments (`//@`) - } else if let Some((header_revision, non_revisioned_directive_line)) = - line_directive(comment, ln) - { - // Perform unknown directive check on Rust files. - if testfile.extension().map(|e| e == "rs").unwrap_or(false) { - let directive_ln = non_revisioned_directive_line.trim(); + let Some((header_revision, non_revisioned_directive_line)) = line_directive(comment, ln) + else { + continue; + }; - let CheckDirectiveResult { is_known_directive, trailing_directive, .. } = - check_directive(directive_ln, mode, ln); + // Perform unknown directive check on Rust files. + if testfile.extension().map(|e| e == "rs").unwrap_or(false) { + let directive_ln = non_revisioned_directive_line.trim(); - if !is_known_directive { - *poisoned = true; + let CheckDirectiveResult { is_known_directive, trailing_directive } = + check_directive(directive_ln, mode, ln); - eprintln!( - "error: detected unknown compiletest test directive `{}` in {}:{}", - directive_ln, - testfile.display(), - line_number, - ); - - return; - } - - if let Some(trailing_directive) = &trailing_directive { - *poisoned = true; - - eprintln!( - "error: detected trailing compiletest test directive `{}` in {}:{}\n \ - help: put the trailing directive in it's own line: `//@ {}`", - trailing_directive, - testfile.display(), - line_number, - trailing_directive, - ); - - return; - } - } - - it(HeaderLine { - line_number, - original_line, - header_revision, - directive: non_revisioned_directive_line, - }); - // Then we try to check for legacy-style candidates, which are not the magic ~ERROR family - // error annotations. - } else if !revision_magic_comment_re.is_match(ln) { - let Some((_, rest)) = line_directive("//", ln) else { - continue; - }; - - if rest.trim_start().starts_with(':') { - // This is likely a markdown link: - // `[link_name]: https://example.org` - continue; - } - - let rest = rest.trim_start(); - - let CheckDirectiveResult { is_known_directive, directive_name, .. } = - check_directive(rest, mode, ln); - - if is_known_directive { + if !is_known_directive { *poisoned = true; + eprintln!( - "error: detected legacy-style directive {} in compiletest test: {}:{}, please use `ui_test`-style directives `//@` instead: {:#?}", - directive_name, + "error: detected unknown compiletest test directive `{}` in {}:{}", + directive_ln, testfile.display(), line_number, - line_directive("//", ln), ); + + return; + } + + if let Some(trailing_directive) = &trailing_directive { + *poisoned = true; + + eprintln!( + "error: detected trailing compiletest test directive `{}` in {}:{}\n \ + help: put the trailing directive in it's own line: `//@ {}`", + trailing_directive, + testfile.display(), + line_number, + trailing_directive, + ); + return; } } + + it(HeaderLine { + line_number, + original_line, + header_revision, + directive: non_revisioned_directive_line, + }); } } diff --git a/src/tools/compiletest/src/header/test-auxillary/known_legacy_directive.rs b/src/tools/compiletest/src/header/test-auxillary/known_legacy_directive.rs deleted file mode 100644 index 108ca432e13..00000000000 --- a/src/tools/compiletest/src/header/test-auxillary/known_legacy_directive.rs +++ /dev/null @@ -1 +0,0 @@ -// ignore-wasm diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs index 76a8b129198..b70b4b27f40 100644 --- a/src/tools/compiletest/src/header/tests.rs +++ b/src/tools/compiletest/src/header/tests.rs @@ -618,17 +618,6 @@ fn test_unknown_directive_check() { assert!(poisoned); } -#[test] -fn test_known_legacy_directive_check() { - let mut poisoned = false; - run_path( - &mut poisoned, - Path::new("a.rs"), - include_bytes!("./test-auxillary/known_legacy_directive.rs"), - ); - assert!(poisoned); -} - #[test] fn test_known_directive_check_no_error() { let mut poisoned = false; From aeaea1b4b1a0b7bb7f3269d11d816251dc99aa00 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 8 Oct 2024 12:08:16 +0200 Subject: [PATCH 070/357] Add a mailmap entry for bjorn3 --- .mailmap | 1 + 1 file changed, 1 insertion(+) diff --git a/.mailmap b/.mailmap index 9ac7f1a9b49..0f58762e023 100644 --- a/.mailmap +++ b/.mailmap @@ -74,6 +74,7 @@ Ben Striegel Benjamin Jackman Benoît Cortier Bheesham Persaud Bheesham Persaud +bjorn3 <17426603+bjorn3@users.noreply.github.com> Björn Steinbrink blake2-ppc blyxyas Alejandra González From 27583378d317b7f7e0b8b8d87e0e9ff306641d81 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 8 Oct 2024 19:08:54 +1100 Subject: [PATCH 071/357] Simplify the directives for ignoring coverage-test modes --- src/tools/compiletest/src/command-list.rs | 4 ++-- src/tools/compiletest/src/header/cfg.rs | 9 +++------ src/tools/compiletest/src/header/tests.rs | 18 ++++++++---------- tests/coverage/color.coverage | 2 +- tests/coverage/color.rs | 2 +- tests/coverage/ignore_map.coverage | 2 +- tests/coverage/ignore_map.rs | 2 +- tests/coverage/ignore_run.rs | 2 +- 8 files changed, 18 insertions(+), 23 deletions(-) diff --git a/src/tools/compiletest/src/command-list.rs b/src/tools/compiletest/src/command-list.rs index bcdd4a69b66..b34c276ab19 100644 --- a/src/tools/compiletest/src/command-list.rs +++ b/src/tools/compiletest/src/command-list.rs @@ -42,6 +42,8 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "ignore-cdb", "ignore-compare-mode-next-solver", "ignore-compare-mode-polonius", + "ignore-coverage-map", + "ignore-coverage-run", "ignore-cross-compile", "ignore-debug", "ignore-eabi", @@ -64,8 +66,6 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "ignore-loongarch64", "ignore-macabi", "ignore-macos", - "ignore-mode-coverage-map", - "ignore-mode-coverage-run", "ignore-msp430", "ignore-msvc", "ignore-musl", diff --git a/src/tools/compiletest/src/header/cfg.rs b/src/tools/compiletest/src/header/cfg.rs index f3835637a1e..6e351aa27b9 100644 --- a/src/tools/compiletest/src/header/cfg.rs +++ b/src/tools/compiletest/src/header/cfg.rs @@ -217,13 +217,10 @@ pub(super) fn parse_cfg_name_directive<'a>( } // Coverage tests run the same test file in multiple modes. // If a particular test should not be run in one of the modes, ignore it - // with "ignore-mode-coverage-map" or "ignore-mode-coverage-run". + // with "ignore-coverage-map" or "ignore-coverage-run". condition! { - name: format!("mode-{}", config.mode.to_str()), - allowed_names: ContainsPrefixed { - prefix: "mode-", - inner: ["coverage-run", "coverage-map"], - }, + name: config.mode.to_str(), + allowed_names: ["coverage-map", "coverage-run"], message: "when the test mode is {name}", } diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs index 76a8b129198..c467b5c45ec 100644 --- a/src/tools/compiletest/src/header/tests.rs +++ b/src/tools/compiletest/src/header/tests.rs @@ -572,17 +572,15 @@ fn families() { } #[test] -fn ignore_mode() { - for mode in ["coverage-map", "coverage-run"] { - // Indicate profiler support so that "coverage-run" tests aren't skipped. - let config: Config = cfg().mode(mode).profiler_support(true).build(); - let other = if mode == "coverage-run" { "coverage-map" } else { "coverage-run" }; +fn ignore_coverage() { + // Indicate profiler support so that "coverage-run" tests aren't skipped. + let config = cfg().mode("coverage-map").profiler_support(true).build(); + assert!(check_ignore(&config, "//@ ignore-coverage-map")); + assert!(!check_ignore(&config, "//@ ignore-coverage-run")); - assert_ne!(mode, other); - - assert!(check_ignore(&config, &format!("//@ ignore-mode-{mode}"))); - assert!(!check_ignore(&config, &format!("//@ ignore-mode-{other}"))); - } + let config = cfg().mode("coverage-run").profiler_support(true).build(); + assert!(!check_ignore(&config, "//@ ignore-coverage-map")); + assert!(check_ignore(&config, "//@ ignore-coverage-run")); } #[test] diff --git a/tests/coverage/color.coverage b/tests/coverage/color.coverage index b12f20204b4..4e6ef6b60ce 100644 --- a/tests/coverage/color.coverage +++ b/tests/coverage/color.coverage @@ -1,5 +1,5 @@ LL| |//@ edition: 2021 - LL| |//@ ignore-mode-coverage-map + LL| |//@ ignore-coverage-map LL| |//@ ignore-windows LL| |//@ llvm-cov-flags: --use-color LL| | diff --git a/tests/coverage/color.rs b/tests/coverage/color.rs index 144e798ba5d..bdb81c088f5 100644 --- a/tests/coverage/color.rs +++ b/tests/coverage/color.rs @@ -1,5 +1,5 @@ //@ edition: 2021 -//@ ignore-mode-coverage-map +//@ ignore-coverage-map //@ ignore-windows //@ llvm-cov-flags: --use-color diff --git a/tests/coverage/ignore_map.coverage b/tests/coverage/ignore_map.coverage index a796a7375a7..466f9e29815 100644 --- a/tests/coverage/ignore_map.coverage +++ b/tests/coverage/ignore_map.coverage @@ -1,4 +1,4 @@ - LL| |//@ ignore-mode-coverage-map + LL| |//@ ignore-coverage-map LL| | LL| 1|fn main() {} diff --git a/tests/coverage/ignore_map.rs b/tests/coverage/ignore_map.rs index deee6e27d99..95df6cbbf0d 100644 --- a/tests/coverage/ignore_map.rs +++ b/tests/coverage/ignore_map.rs @@ -1,3 +1,3 @@ -//@ ignore-mode-coverage-map +//@ ignore-coverage-map fn main() {} diff --git a/tests/coverage/ignore_run.rs b/tests/coverage/ignore_run.rs index 0363524d369..2d67ebe6f3a 100644 --- a/tests/coverage/ignore_run.rs +++ b/tests/coverage/ignore_run.rs @@ -1,3 +1,3 @@ -//@ ignore-mode-coverage-run +//@ ignore-coverage-run fn main() {} From 287eb03838d5ff211706c8df8f5357034219472f Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 8 Oct 2024 12:25:26 +0200 Subject: [PATCH 072/357] fix/update teach_note from 'escaping mutable ref/ptr' const-check --- compiler/rustc_const_eval/messages.ftl | 51 ++++++++++--------- .../src/check_consts/check.rs | 1 + .../rustc_const_eval/src/check_consts/ops.rs | 6 +-- compiler/rustc_const_eval/src/errors.rs | 12 ++--- tests/ui/error-codes/E0010-teach.stderr | 2 +- 5 files changed, 37 insertions(+), 35 deletions(-) diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl index 73a9a1569f6..24dbe688f36 100644 --- a/compiler/rustc_const_eval/messages.ftl +++ b/compiler/rustc_const_eval/messages.ftl @@ -134,14 +134,16 @@ const_eval_incompatible_return_types = const_eval_incompatible_types = calling a function with argument of type {$callee_ty} passing data of type {$caller_ty} -const_eval_interior_mutable_data_refer = +const_eval_interior_mutable_ref_escaping = {const_eval_const_context}s cannot refer to interior mutable data .label = this borrow of an interior mutable value may end up in the final value .help = to fix this, the value can be extracted to a separate `static` item and then referenced .teach_note = - A constant containing interior mutable data behind a reference can allow you to modify that data. - This would make multiple uses of a constant to be able to see different values and allow circumventing - the `Send` and `Sync` requirements for shared mutable data, which is unsound. + References that escape into the final value of a constant or static must be immutable. + This is to avoid accidentally creating shared mutable state. + + + If you really want global mutable state, try using an interior mutable `static` or a `static mut`. const_eval_intern_kind = {$kind -> [static] static @@ -229,6 +231,24 @@ const_eval_modified_global = const_eval_mutable_ptr_in_final = encountered mutable pointer in final value of {const_eval_intern_kind} +const_eval_mutable_raw_escaping = + raw mutable pointers are not allowed in the final value of {const_eval_const_context}s + .teach_note = + Pointers that escape into the final value of a constant or static must be immutable. + This is to avoid accidentally creating shared mutable state. + + + If you really want global mutable state, try using an interior mutable `static` or a `static mut`. + +const_eval_mutable_ref_escaping = + mutable references are not allowed in the final value of {const_eval_const_context}s + .teach_note = + References that escape into the final value of a constant or static must be immutable. + This is to avoid accidentally creating shared mutable state. + + + If you really want global mutable state, try using an interior mutable `static` or a `static mut`. + const_eval_nested_static_in_thread_local = #[thread_local] does not support implicit nested statics, please create explicit static items and refer to them instead const_eval_non_const_fmt_macro_call = cannot call non-const formatting macro in {const_eval_const_context}s @@ -364,30 +384,11 @@ const_eval_unallowed_fn_pointer_call = function pointer calls are not allowed in const_eval_unallowed_heap_allocations = allocations are not allowed in {const_eval_const_context}s .label = allocation not allowed in {const_eval_const_context}s - .teach_note = The value of statics and constants must be known at compile time, and they live for the entire lifetime of a program. Creating a boxed value allocates memory on the heap at runtime, and therefore cannot be done at compile time. + .teach_note = + The runtime heap is not yet available at compile-time, so no runtime heap allocations can be created. const_eval_unallowed_inline_asm = inline assembly is not allowed in {const_eval_const_context}s -const_eval_unallowed_mutable_raw = - raw mutable pointers are not allowed in the final value of {const_eval_const_context}s - .teach_note = - References in statics and constants may only refer to immutable values. - - - Statics are shared everywhere, and if they refer to mutable data one might violate memory - safety since holding multiple mutable references to shared data is not allowed. - - - If you really want global mutable state, try using static mut or a global UnsafeCell. - -const_eval_unallowed_mutable_refs = - mutable references are not allowed in the final value of {const_eval_const_context}s - .teach_note = - Statics are shared everywhere, and if they refer to mutable data one might violate memory - safety since holding multiple mutable references to shared data is not allowed. - - - If you really want global mutable state, try using static mut or a global UnsafeCell. const_eval_unallowed_op_in_const_context = {$msg} diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs index 2cbf242fcf2..463a66d4e2e 100644 --- a/compiler/rustc_const_eval/src/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/check_consts/check.rs @@ -666,6 +666,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { } } + // This can be called on stable via the `vec!` macro. if tcx.is_lang_item(callee, LangItem::ExchangeMalloc) { self.check_op(ops::HeapAllocation); return; diff --git a/compiler/rustc_const_eval/src/check_consts/ops.rs b/compiler/rustc_const_eval/src/check_consts/ops.rs index 6eb33c29e1d..5c4a899f28a 100644 --- a/compiler/rustc_const_eval/src/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/check_consts/ops.rs @@ -402,7 +402,7 @@ impl<'tcx> NonConstOp<'tcx> for EscapingCellBorrow { DiagImportance::Secondary } fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> { - ccx.dcx().create_err(errors::InteriorMutableDataRefer { + ccx.dcx().create_err(errors::InteriorMutableRefEscaping { span, opt_help: matches!(ccx.const_kind(), hir::ConstContext::Static(_)), kind: ccx.const_kind(), @@ -430,12 +430,12 @@ impl<'tcx> NonConstOp<'tcx> for EscapingMutBorrow { fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> { match self.0 { - hir::BorrowKind::Raw => ccx.tcx.dcx().create_err(errors::UnallowedMutableRaw { + hir::BorrowKind::Raw => ccx.tcx.dcx().create_err(errors::MutableRawEscaping { span, kind: ccx.const_kind(), teach: ccx.tcx.sess.teach(E0764), }), - hir::BorrowKind::Ref => ccx.dcx().create_err(errors::UnallowedMutableRefs { + hir::BorrowKind::Ref => ccx.dcx().create_err(errors::MutableRefEscaping { span, kind: ccx.const_kind(), teach: ccx.tcx.sess.teach(E0764), diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs index c60bacb8506..c943236affc 100644 --- a/compiler/rustc_const_eval/src/errors.rs +++ b/compiler/rustc_const_eval/src/errors.rs @@ -118,8 +118,8 @@ pub(crate) struct UnstableConstFn { } #[derive(Diagnostic)] -#[diag(const_eval_unallowed_mutable_refs, code = E0764)] -pub(crate) struct UnallowedMutableRefs { +#[diag(const_eval_mutable_ref_escaping, code = E0764)] +pub(crate) struct MutableRefEscaping { #[primary_span] pub span: Span, pub kind: ConstContext, @@ -128,8 +128,8 @@ pub(crate) struct UnallowedMutableRefs { } #[derive(Diagnostic)] -#[diag(const_eval_unallowed_mutable_raw, code = E0764)] -pub(crate) struct UnallowedMutableRaw { +#[diag(const_eval_mutable_raw_escaping, code = E0764)] +pub(crate) struct MutableRawEscaping { #[primary_span] pub span: Span, pub kind: ConstContext, @@ -181,8 +181,8 @@ pub(crate) struct UnallowedInlineAsm { } #[derive(Diagnostic)] -#[diag(const_eval_interior_mutable_data_refer, code = E0492)] -pub(crate) struct InteriorMutableDataRefer { +#[diag(const_eval_interior_mutable_ref_escaping, code = E0492)] +pub(crate) struct InteriorMutableRefEscaping { #[primary_span] #[label] pub span: Span, diff --git a/tests/ui/error-codes/E0010-teach.stderr b/tests/ui/error-codes/E0010-teach.stderr index 7634970f36e..37a9892ccbf 100644 --- a/tests/ui/error-codes/E0010-teach.stderr +++ b/tests/ui/error-codes/E0010-teach.stderr @@ -4,7 +4,7 @@ error[E0010]: allocations are not allowed in constants LL | const CON: Vec = vec![1, 2, 3]; | ^^^^^^^^^^^^^ allocation not allowed in constants | - = note: The value of statics and constants must be known at compile time, and they live for the entire lifetime of a program. Creating a boxed value allocates memory on the heap at runtime, and therefore cannot be done at compile time. + = note: The runtime heap is not yet available at compile-time, so no runtime heap allocations can be created. = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0015]: cannot call non-const fn `slice::::into_vec::` in constants From 076927b7cfdcac9d740c85ebdc84025292d9caf5 Mon Sep 17 00:00:00 2001 From: ismailarilik Date: Tue, 8 Oct 2024 16:06:22 +0300 Subject: [PATCH 073/357] fix(rustdoc): add space between struct fields and their descriptions --- src/librustdoc/html/static/css/rustdoc.css | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 5f6f3c65c7f..1e3b70d6921 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -230,6 +230,9 @@ h4.code-header { padding: 0; white-space: pre-wrap; } +.structfield { + margin: 0.6em 0; +} #crate-search, h1, h2, h3, h4, h5, h6, From 4e9554d893f9910f00a7c31dda4b9a0062430471 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 8 Oct 2024 14:44:40 +0200 Subject: [PATCH 074/357] fix behavior of release_clock() --- src/tools/miri/src/alloc_addresses/mod.rs | 2 +- src/tools/miri/src/concurrency/data_race.rs | 33 ++++++++++--------- src/tools/miri/src/concurrency/init_once.rs | 6 ++-- src/tools/miri/src/concurrency/sync.rs | 16 ++++++--- src/tools/miri/src/shims/unix/linux/epoll.rs | 4 +-- .../miri/src/shims/unix/linux/eventfd.rs | 4 +-- .../miri/src/shims/unix/unnamed_socket.rs | 4 +-- .../fail-dep/libc/socketpair-data-race.rs | 31 +++++++++++++++++ .../fail-dep/libc/socketpair-data-race.stderr | 20 +++++++++++ 9 files changed, 90 insertions(+), 30 deletions(-) create mode 100644 src/tools/miri/tests/fail-dep/libc/socketpair-data-race.rs create mode 100644 src/tools/miri/tests/fail-dep/libc/socketpair-data-race.stderr diff --git a/src/tools/miri/src/alloc_addresses/mod.rs b/src/tools/miri/src/alloc_addresses/mod.rs index a13b14ca90a..50e55268248 100644 --- a/src/tools/miri/src/alloc_addresses/mod.rs +++ b/src/tools/miri/src/alloc_addresses/mod.rs @@ -453,7 +453,7 @@ impl<'tcx> MiriMachine<'tcx> { let thread = self.threads.active_thread(); global_state.reuse.add_addr(rng, addr, size, align, kind, thread, || { if let Some(data_race) = &self.data_race { - data_race.release_clock(&self.threads).clone() + data_race.release_clock(&self.threads, |clock| clock.clone()) } else { VClock::default() } diff --git a/src/tools/miri/src/concurrency/data_race.rs b/src/tools/miri/src/concurrency/data_race.rs index 82c4f6d3007..797b3191d83 100644 --- a/src/tools/miri/src/concurrency/data_race.rs +++ b/src/tools/miri/src/concurrency/data_race.rs @@ -828,15 +828,14 @@ pub trait EvalContextExt<'tcx>: MiriInterpCxExt<'tcx> { } } - /// Returns the `release` clock of the current thread. + /// Calls the callback with the "release" clock of the current thread. /// Other threads can acquire this clock in the future to establish synchronization /// with this program point. - fn release_clock<'a>(&'a self) -> Option> - where - 'tcx: 'a, - { + /// + /// The closure will only be invoked if data race handling is on. + fn release_clock(&self, callback: impl FnOnce(&VClock) -> R) -> Option { let this = self.eval_context_ref(); - Some(this.machine.data_race.as_ref()?.release_clock(&this.machine.threads)) + Some(this.machine.data_race.as_ref()?.release_clock(&this.machine.threads, callback)) } /// Acquire the given clock into the current thread, establishing synchronization with @@ -1728,7 +1727,7 @@ impl GlobalState { let current_index = self.active_thread_index(thread_mgr); // Store the terminaion clock. - let terminaion_clock = self.release_clock(thread_mgr).clone(); + let terminaion_clock = self.release_clock(thread_mgr, |clock| clock.clone()); self.thread_info.get_mut()[current_thread].termination_vector_clock = Some(terminaion_clock); @@ -1778,21 +1777,23 @@ impl GlobalState { clocks.clock.join(clock); } - /// Returns the `release` clock of the current thread. + /// Calls the given closure with the "release" clock of the current thread. /// Other threads can acquire this clock in the future to establish synchronization /// with this program point. - pub fn release_clock<'tcx>(&self, threads: &ThreadManager<'tcx>) -> Ref<'_, VClock> { + pub fn release_clock<'tcx, R>( + &self, + threads: &ThreadManager<'tcx>, + callback: impl FnOnce(&VClock) -> R, + ) -> R { let thread = threads.active_thread(); let span = threads.active_thread_ref().current_span(); - // We increment the clock each time this happens, to ensure no two releases - // can be confused with each other. let (index, mut clocks) = self.thread_state_mut(thread); + let r = callback(&clocks.clock); + // Increment the clock, so that all following events cannot be confused with anything that + // occurred before the release. Crucially, the callback is invoked on the *old* clock! clocks.increment_clock(index, span); - drop(clocks); - // To return a read-only view, we need to release the RefCell - // and borrow it again. - let (_index, clocks) = self.thread_state(thread); - Ref::map(clocks, |c| &c.clock) + + r } fn thread_index(&self, thread: ThreadId) -> VectorIdx { diff --git a/src/tools/miri/src/concurrency/init_once.rs b/src/tools/miri/src/concurrency/init_once.rs index 7a9b12bbe82..488edc91dff 100644 --- a/src/tools/miri/src/concurrency/init_once.rs +++ b/src/tools/miri/src/concurrency/init_once.rs @@ -93,7 +93,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Each complete happens-before the end of the wait if let Some(data_race) = &this.machine.data_race { - init_once.clock.clone_from(&data_race.release_clock(&this.machine.threads)); + data_race + .release_clock(&this.machine.threads, |clock| init_once.clock.clone_from(clock)); } // Wake up everyone. @@ -119,7 +120,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Each complete happens-before the end of the wait if let Some(data_race) = &this.machine.data_race { - init_once.clock.clone_from(&data_race.release_clock(&this.machine.threads)); + data_race + .release_clock(&this.machine.threads, |clock| init_once.clock.clone_from(clock)); } // Wake up one waiting thread, so they can go ahead and try to init this. diff --git a/src/tools/miri/src/concurrency/sync.rs b/src/tools/miri/src/concurrency/sync.rs index 5627ccdbbea..e1e748e7945 100644 --- a/src/tools/miri/src/concurrency/sync.rs +++ b/src/tools/miri/src/concurrency/sync.rs @@ -444,7 +444,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // The mutex is completely unlocked. Try transferring ownership // to another thread. if let Some(data_race) = &this.machine.data_race { - mutex.clock.clone_from(&data_race.release_clock(&this.machine.threads)); + data_race.release_clock(&this.machine.threads, |clock| { + mutex.clock.clone_from(clock) + }); } if let Some(thread) = this.machine.sync.mutexes[id].queue.pop_front() { this.unblock_thread(thread, BlockReason::Mutex(id))?; @@ -553,7 +555,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } if let Some(data_race) = &this.machine.data_race { // Add this to the shared-release clock of all concurrent readers. - rwlock.clock_current_readers.join(&data_race.release_clock(&this.machine.threads)); + data_race.release_clock(&this.machine.threads, |clock| { + rwlock.clock_current_readers.join(clock) + }); } // The thread was a reader. If the lock is not held any more, give it to a writer. @@ -632,7 +636,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { trace!("rwlock_writer_unlock: {:?} unlocked by {:?}", id, thread); // Record release clock for next lock holder. if let Some(data_race) = &this.machine.data_race { - rwlock.clock_unlocked.clone_from(&*data_race.release_clock(&this.machine.threads)); + data_race.release_clock(&this.machine.threads, |clock| { + rwlock.clock_unlocked.clone_from(clock) + }); } // The thread was a writer. // @@ -764,7 +770,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Each condvar signal happens-before the end of the condvar wake if let Some(data_race) = data_race { - condvar.clock.clone_from(&*data_race.release_clock(&this.machine.threads)); + data_race.release_clock(&this.machine.threads, |clock| condvar.clock.clone_from(clock)); } let Some(waiter) = condvar.waiters.pop_front() else { return interp_ok(false); @@ -837,7 +843,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Each futex-wake happens-before the end of the futex wait if let Some(data_race) = data_race { - futex.clock.clone_from(&*data_race.release_clock(&this.machine.threads)); + data_race.release_clock(&this.machine.threads, |clock| futex.clock.clone_from(clock)); } // Wake up the first thread in the queue that matches any of the bits in the bitset. diff --git a/src/tools/miri/src/shims/unix/linux/epoll.rs b/src/tools/miri/src/shims/unix/linux/epoll.rs index b57347abffa..81a6739728b 100644 --- a/src/tools/miri/src/shims/unix/linux/epoll.rs +++ b/src/tools/miri/src/shims/unix/linux/epoll.rs @@ -568,9 +568,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let epoll = epfd.downcast::().unwrap(); // Synchronize running thread to the epoll ready list. - if let Some(clock) = &this.release_clock() { + this.release_clock(|clock| { epoll.ready_list.clock.borrow_mut().join(clock); - } + }); if let Some(thread_id) = epoll.thread_id.borrow_mut().pop() { waiter.push(thread_id); diff --git a/src/tools/miri/src/shims/unix/linux/eventfd.rs b/src/tools/miri/src/shims/unix/linux/eventfd.rs index 910ab7e90f2..35bc933885c 100644 --- a/src/tools/miri/src/shims/unix/linux/eventfd.rs +++ b/src/tools/miri/src/shims/unix/linux/eventfd.rs @@ -140,9 +140,9 @@ impl FileDescription for Event { match self.counter.get().checked_add(num) { Some(new_count @ 0..=MAX_COUNTER) => { // Future `read` calls will synchronize with this write, so update the FD clock. - if let Some(clock) = &ecx.release_clock() { + ecx.release_clock(|clock| { self.clock.borrow_mut().join(clock); - } + }); self.counter.set(new_count); } None | Some(u64::MAX) => diff --git a/src/tools/miri/src/shims/unix/unnamed_socket.rs b/src/tools/miri/src/shims/unix/unnamed_socket.rs index faa54c6a75e..e83c0afb287 100644 --- a/src/tools/miri/src/shims/unix/unnamed_socket.rs +++ b/src/tools/miri/src/shims/unix/unnamed_socket.rs @@ -234,9 +234,9 @@ impl FileDescription for AnonSocket { } } // Remember this clock so `read` can synchronize with us. - if let Some(clock) = &ecx.release_clock() { + ecx.release_clock(|clock| { writebuf.clock.join(clock); - } + }); // Do full write / partial write based on the space available. let actual_write_size = len.min(available_space); let bytes = ecx.read_bytes_ptr_strip_provenance(ptr, Size::from_bytes(len))?; diff --git a/src/tools/miri/tests/fail-dep/libc/socketpair-data-race.rs b/src/tools/miri/tests/fail-dep/libc/socketpair-data-race.rs new file mode 100644 index 00000000000..f4c009456d2 --- /dev/null +++ b/src/tools/miri/tests/fail-dep/libc/socketpair-data-race.rs @@ -0,0 +1,31 @@ +//! This is a regression test for : we had some +//! faulty logic around `release_clock` that led to this code not reporting a data race. +//@ignore-target: windows # no libc socketpair on Windows +//@compile-flags: -Zmiri-preemption-rate=0 +use std::thread; + +fn main() { + static mut VAL: u8 = 0; + let mut fds = [-1, -1]; + let res = unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) }; + assert_eq!(res, 0); + let thread1 = thread::spawn(move || { + let data = "a".as_bytes().as_ptr(); + let res = unsafe { libc::write(fds[0], data as *const libc::c_void, 1) }; + assert_eq!(res, 1); + // The write to VAL is *after* the write to the socket, so there's no proper synchronization. + unsafe { VAL = 1 }; + }); + thread::yield_now(); + + let mut buf: [u8; 1] = [0; 1]; + let res: i32 = unsafe { + libc::read(fds[1], buf.as_mut_ptr().cast(), buf.len() as libc::size_t).try_into().unwrap() + }; + assert_eq!(res, 1); + assert_eq!(buf, "a".as_bytes()); + + unsafe { assert_eq!({ VAL }, 1) }; //~ERROR: Data race + + thread1.join().unwrap(); +} diff --git a/src/tools/miri/tests/fail-dep/libc/socketpair-data-race.stderr b/src/tools/miri/tests/fail-dep/libc/socketpair-data-race.stderr new file mode 100644 index 00000000000..6472c33727c --- /dev/null +++ b/src/tools/miri/tests/fail-dep/libc/socketpair-data-race.stderr @@ -0,0 +1,20 @@ +error: Undefined Behavior: Data race detected between (1) non-atomic write on thread `unnamed-ID` and (2) non-atomic read on thread `main` at ALLOC. (2) just happened here + --> tests/fail-dep/libc/socketpair-data-race.rs:LL:CC + | +LL | unsafe { assert_eq!({ VAL }, 1) }; + | ^^^ Data race detected between (1) non-atomic write on thread `unnamed-ID` and (2) non-atomic read on thread `main` at ALLOC. (2) just happened here + | +help: and (1) occurred earlier here + --> tests/fail-dep/libc/socketpair-data-race.rs:LL:CC + | +LL | unsafe { VAL = 1 }; + | ^^^^^^^ + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE (of the first span): + = note: inside `main` at tests/fail-dep/libc/socketpair-data-race.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + From c9b4d1bfb13b371a1f90be398b56a015f2ee73ba Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 8 Oct 2024 15:13:26 +0200 Subject: [PATCH 075/357] Remove unneeded argument of `LinkCollector::verify_disambiguator` --- src/librustdoc/passes/collect_intra_doc_links.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 2656612a13e..a930ffca5db 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -1061,7 +1061,7 @@ impl LinkCollector<'_, '_> { // valid omission. See https://github.com/rust-lang/rust/pull/80660#discussion_r551585677 // for discussion on the matter. let kind = self.cx.tcx.def_kind(id); - self.verify_disambiguator(path_str, kind, id, disambiguator, item, &diag_info)?; + self.verify_disambiguator(path_str, kind, id, disambiguator, &diag_info)?; } else { match disambiguator { Some(Disambiguator::Primitive | Disambiguator::Namespace(_)) | None => {} @@ -1090,7 +1090,6 @@ impl LinkCollector<'_, '_> { kind_for_dis, id_for_dis, disambiguator, - item, &diag_info, )?; @@ -1111,7 +1110,6 @@ impl LinkCollector<'_, '_> { kind: DefKind, id: DefId, disambiguator: Option, - item: &Item, diag_info: &DiagnosticInfo<'_>, ) -> Option<()> { debug!("intra-doc link to {path_str} resolved to {:?}", (kind, id)); @@ -1138,7 +1136,7 @@ impl LinkCollector<'_, '_> { // item can be non-local e.g. when using `#[rustc_doc_primitive = "pointer"]` if let Some((src_id, dst_id)) = id.as_local().and_then(|dst_id| { - item.item_id.expect_def_id().as_local().map(|src_id| (src_id, dst_id)) + diag_info.item.item_id.expect_def_id().as_local().map(|src_id| (src_id, dst_id)) }) { if self.cx.tcx.effective_visibilities(()).is_exported(src_id) && !self.cx.tcx.effective_visibilities(()).is_exported(dst_id) From 7ab466697faf64aaeda40d6407c01f6bfff83fdb Mon Sep 17 00:00:00 2001 From: Michal Piotrowski Date: Tue, 8 Oct 2024 15:17:45 +0200 Subject: [PATCH 076/357] Fix needless_lifetimes in rustc_serialize --- compiler/rustc_serialize/src/serialize.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_serialize/src/serialize.rs b/compiler/rustc_serialize/src/serialize.rs index 2d37f5bdab8..bae5f259fcc 100644 --- a/compiler/rustc_serialize/src/serialize.rs +++ b/compiler/rustc_serialize/src/serialize.rs @@ -325,7 +325,7 @@ impl Decodable for [u8; N] { } } -impl<'a, S: Encoder, T: Encodable> Encodable for Cow<'a, [T]> +impl> Encodable for Cow<'_, [T]> where [T]: ToOwned>, { @@ -345,14 +345,14 @@ where } } -impl<'a, S: Encoder> Encodable for Cow<'a, str> { +impl Encodable for Cow<'_, str> { fn encode(&self, s: &mut S) { let val: &str = self; val.encode(s) } } -impl<'a, D: Decoder> Decodable for Cow<'a, str> { +impl Decodable for Cow<'_, str> { fn decode(d: &mut D) -> Cow<'static, str> { let v: String = Decodable::decode(d); Cow::Owned(v) From 11af16c9838f0a693040c693e98a64c68c0c2da0 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Wed, 24 Apr 2024 17:06:11 +0300 Subject: [PATCH 077/357] use precompiled rustc for non-dist builders by default Signed-off-by: onur-ozkan --- src/ci/run.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/ci/run.sh b/src/ci/run.sh index c8201d9bcfd..06e3b573758 100755 --- a/src/ci/run.sh +++ b/src/ci/run.sh @@ -173,6 +173,10 @@ else # included with LLVM, since a dynamic libstdcpp may not be available. RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set llvm.static-libstdcpp" fi + + if [ "$NO_DOWNLOAD_CI_RUSTC" = "" ]; then + RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set rust.download-rustc=if-unchanged" + fi fi if [ "$ENABLE_GCC_CODEGEN" = "1" ]; then From 9826e3ece3a5a52e9cc2af5401218f4bd71a749a Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Wed, 24 Apr 2024 19:59:46 +0300 Subject: [PATCH 078/357] disable CI rustc when not using CI LLVM Signed-off-by: onur-ozkan --- src/ci/run.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ci/run.sh b/src/ci/run.sh index 06e3b573758..c33a376c2d6 100755 --- a/src/ci/run.sh +++ b/src/ci/run.sh @@ -169,6 +169,8 @@ else if [ "$NO_DOWNLOAD_CI_LLVM" = "" ]; then RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set llvm.download-ci-llvm=if-unchanged" else + # CI rustc requires CI LLVM to be enabled (see https://github.com/rust-lang/rust/issues/123586). + NO_DOWNLOAD_CI_RUSTC=1 # When building for CI we want to use the static C++ Standard library # included with LLVM, since a dynamic libstdcpp may not be available. RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set llvm.static-libstdcpp" From bfcd00190d798ce97e0e5c9b964b70c92174d46a Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Sun, 12 May 2024 09:55:26 +0300 Subject: [PATCH 079/357] add test for ci rustc's if-unchanged logic Signed-off-by: onur-ozkan --- src/bootstrap/src/core/builder/tests.rs | 49 +++++++++++++++++++++++++ src/bootstrap/src/core/config/tests.rs | 2 +- 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index bd81dc930be..363a9c82699 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -212,6 +212,55 @@ fn alias_and_path_for_library() { assert_eq!(first(cache.all::()), &[doc_std!(A => A, stage = 0)]); } +#[test] +fn ci_rustc_if_unchanged_logic() { + let config = Config::parse_inner( + Flags::parse(&[ + "build".to_owned(), + "--dry-run".to_owned(), + "--set=rust.download-rustc='if-unchanged'".to_owned(), + ]), + |&_| Ok(Default::default()), + ); + + let build = Build::new(config.clone()); + let builder = Builder::new(&build); + + if config.rust_info.is_from_tarball() { + return; + } + + if config.out.exists() { + fs::remove_dir_all(&config.out).unwrap(); + } + + builder.run_step_descriptions(&Builder::get_step_descriptions(config.cmd.kind()), &[]); + + let commit = helpers::get_closest_merge_base_commit( + Some(&builder.config.src), + &builder.config.git_config(), + &builder.config.stage0_metadata.config.git_merge_commit_email, + &[], + ) + .unwrap(); + + let compiler_path = build.src.join("compiler"); + let library_path = build.src.join("library"); + + let has_changes = helpers::git(Some(&builder.src)) + .args(["diff-index", "--quiet", &commit]) + .arg("--") + .args([compiler_path, library_path]) + .as_command_mut() + .status() + .unwrap() + .success(); + + assert!( + has_changes != config.out.join(config.build.to_string()).join("ci-rustc-sysroot").exists() + ); +} + mod defaults { use pretty_assertions::assert_eq; diff --git a/src/bootstrap/src/core/config/tests.rs b/src/bootstrap/src/core/config/tests.rs index 278becdcbc7..ed89112de90 100644 --- a/src/bootstrap/src/core/config/tests.rs +++ b/src/bootstrap/src/core/config/tests.rs @@ -12,7 +12,7 @@ use super::{ChangeIdWrapper, Config}; use crate::core::build_steps::clippy::get_clippy_rules_in_order; use crate::core::config::{LldMode, Target, TargetSelection, TomlConfig}; -fn parse(config: &str) -> Config { +pub(crate) fn parse(config: &str) -> Config { Config::parse_inner( Flags::parse(&["check".to_string(), "--config=/does/not/exist".to_string()]), |&_| toml::from_str(&config), From b21949b9623b236617746c8dd4c98f9e110cced6 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Sun, 12 May 2024 10:31:43 +0300 Subject: [PATCH 080/357] make an explicit change on compiler then run bootstrap test Signed-off-by: onur-ozkan --- src/ci/docker/host-x86_64/mingw-check/Dockerfile | 15 ++++++++++++++- src/ci/github-actions/jobs.yml | 3 +++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/ci/docker/host-x86_64/mingw-check/Dockerfile b/src/ci/docker/host-x86_64/mingw-check/Dockerfile index 571378774be..97fe56fbfcb 100644 --- a/src/ci/docker/host-x86_64/mingw-check/Dockerfile +++ b/src/ci/docker/host-x86_64/mingw-check/Dockerfile @@ -46,7 +46,20 @@ ENV RUN_CHECK_WITH_PARALLEL_QUERIES 1 # Check library crates on all tier 1 targets. # We disable optimized compiler built-ins because that requires a C toolchain for the target. # We also skip the x86_64-unknown-linux-gnu target as it is well-tested by other jobs. -ENV SCRIPT python3 ../x.py check --stage 0 --set build.optimized-compiler-builtins=false core alloc std --target=aarch64-unknown-linux-gnu,i686-pc-windows-msvc,i686-unknown-linux-gnu,x86_64-apple-darwin,x86_64-pc-windows-gnu,x86_64-pc-windows-msvc && \ +ENV SCRIPT \ + # `core::builder::tests::ci_rustc_if_unchanged_logic` bootstrap test covers the `rust.download-rustc=if-unchanged` logic. + # Here we are adding a dummy commit on compiler and running that test to ensure when there is a change on the compiler, + # we never download ci rustc with `rust.download-rustc=if-unchanged` option. + echo \"\" >> ../compiler/rustc/src/main.rs && \ + git config --global user.email \"dummy@dummy.com\" && \ + git config --global user.name \"dummy\" && \ + git add ../compiler/rustc/src/main.rs && \ + git commit -m \"test commit for rust.download-rustc=if-unchanged logic\" && \ + python3 ../x.py test bootstrap -- core::builder::tests::ci_rustc_if_unchanged_logic && \ + # Revert the dummy commit + git reset --hard HEAD~1 && \ + + python3 ../x.py check --stage 0 --set build.optimized-compiler-builtins=false core alloc std --target=aarch64-unknown-linux-gnu,i686-pc-windows-msvc,i686-unknown-linux-gnu,x86_64-apple-darwin,x86_64-pc-windows-gnu,x86_64-pc-windows-msvc && \ /scripts/check-default-config-profiles.sh && \ python3 ../x.py check --target=i686-pc-windows-gnu --host=i686-pc-windows-gnu && \ python3 ../x.py clippy bootstrap -Dwarnings && \ diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index 6379f1ade1c..e8ad4319aff 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -85,6 +85,9 @@ envs: # it in each job definition. pr: - image: mingw-check + env: + # We are adding (temporarily) a dummy commit on the compiler + READ_ONLY_SRC: "0" <<: *job-linux-4c - image: mingw-check-tidy continue_on_error: true From eb5e6239aa6524888821d2a3eac5e22e90d25832 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Sun, 26 May 2024 22:27:34 +0300 Subject: [PATCH 081/357] use if-unchanged only when ci rustc is available Signed-off-by: onur-ozkan --- src/bootstrap/src/core/config/config.rs | 26 ++++++++++------ src/bootstrap/src/core/download.rs | 40 +++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 9 deletions(-) diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 7dc3b7b081a..b0af7f29d5e 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -22,6 +22,7 @@ use crate::core::build_steps::compile::CODEGEN_BACKEND_PREFIX; use crate::core::build_steps::llvm; pub use crate::core::config::flags::Subcommand; use crate::core::config::flags::{Color, Flags, Warnings}; +use crate::core::download::is_download_ci_available; use crate::utils::cache::{INTERNER, Interned}; use crate::utils::channel::{self, GitInfo}; use crate::utils::helpers::{self, exe, output, t}; @@ -1627,9 +1628,11 @@ impl Config { config.mandir = mandir.map(PathBuf::from); } + config.llvm_assertions = + toml.llvm.as_ref().map_or(false, |llvm| llvm.assertions.unwrap_or(false)); + // Store off these values as options because if they're not provided // we'll infer default values for them later - let mut llvm_assertions = None; let mut llvm_tests = None; let mut llvm_enzyme = None; let mut llvm_plugins = None; @@ -1712,7 +1715,8 @@ impl Config { is_user_configured_rust_channel = channel.is_some(); set(&mut config.channel, channel.clone()); - config.download_rustc_commit = config.download_ci_rustc_commit(download_rustc); + config.download_rustc_commit = + config.download_ci_rustc_commit(download_rustc, config.llvm_assertions); debug = debug_toml; debug_assertions = debug_assertions_toml; @@ -1848,7 +1852,7 @@ impl Config { optimize: optimize_toml, thin_lto, release_debuginfo, - assertions, + assertions: _, tests, enzyme, plugins, @@ -1882,7 +1886,6 @@ impl Config { Some(StringOrBool::Bool(false)) | None => {} } set(&mut config.ninja_in_file, ninja); - llvm_assertions = assertions; llvm_tests = tests; llvm_enzyme = enzyme; llvm_plugins = plugins; @@ -1911,8 +1914,8 @@ impl Config { config.llvm_enable_warnings = enable_warnings.unwrap_or(false); config.llvm_build_config = build_config.clone().unwrap_or(Default::default()); - let asserts = llvm_assertions.unwrap_or(false); - config.llvm_from_ci = config.parse_download_ci_llvm(download_ci_llvm, asserts); + config.llvm_from_ci = + config.parse_download_ci_llvm(download_ci_llvm, config.llvm_assertions); if config.llvm_from_ci { let warn = |option: &str| { @@ -2080,7 +2083,6 @@ impl Config { // Now that we've reached the end of our configuration, infer the // default values for all options that we haven't otherwise stored yet. - config.llvm_assertions = llvm_assertions.unwrap_or(false); config.llvm_tests = llvm_tests.unwrap_or(false); config.llvm_enzyme = llvm_enzyme.unwrap_or(false); config.llvm_plugins = llvm_plugins.unwrap_or(false); @@ -2711,12 +2713,18 @@ impl Config { } /// Returns the commit to download, or `None` if we shouldn't download CI artifacts. - fn download_ci_rustc_commit(&self, download_rustc: Option) -> Option { + fn download_ci_rustc_commit( + &self, + download_rustc: Option, + llvm_assertions: bool, + ) -> Option { // If `download-rustc` is not set, default to rebuilding. let if_unchanged = match download_rustc { None | Some(StringOrBool::Bool(false)) => return None, Some(StringOrBool::Bool(true)) => false, - Some(StringOrBool::String(s)) if s == "if-unchanged" => true, + Some(StringOrBool::String(s)) if s == "if-unchanged" => { + is_download_ci_available(&self.build.triple, llvm_assertions) + } Some(StringOrBool::String(other)) => { panic!("unrecognized option for download-rustc: {other}") } diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs index 444b75876f2..db1f5b08338 100644 --- a/src/bootstrap/src/core/download.rs +++ b/src/bootstrap/src/core/download.rs @@ -832,3 +832,43 @@ fn path_is_dylib(path: &Path) -> bool { // The .so is not necessarily the extension, it might be libLLVM.so.18.1 path.to_str().map_or(false, |path| path.contains(".so")) } + +/// Checks whether the CI rustc is available for the given target triple. +pub(crate) fn is_download_ci_available(target_triple: &str, llvm_assertions: bool) -> bool { + // All tier 1 targets and tier 2 targets with host tools. + const SUPPORTED_PLATFORMS: &[&str] = &[ + "aarch64-apple-darwin", + "aarch64-pc-windows-msvc", + "aarch64-unknown-linux-gnu", + "aarch64-unknown-linux-musl", + "arm-unknown-linux-gnueabi", + "arm-unknown-linux-gnueabihf", + "armv7-unknown-linux-gnueabihf", + "i686-pc-windows-gnu", + "i686-pc-windows-msvc", + "i686-unknown-linux-gnu", + "loongarch64-unknown-linux-gnu", + "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", + "x86_64-pc-windows-msvc", + "x86_64-unknown-freebsd", + "x86_64-unknown-illumos", + "x86_64-unknown-linux-gnu", + "x86_64-unknown-linux-musl", + "x86_64-unknown-netbsd", + ]; + + const SUPPORTED_PLATFORMS_WITH_ASSERTIONS: &[&str] = + &["x86_64-unknown-linux-gnu", "x86_64-pc-windows-msvc"]; + + if llvm_assertions { + SUPPORTED_PLATFORMS_WITH_ASSERTIONS.contains(&target_triple) + } else { + SUPPORTED_PLATFORMS.contains(&target_triple) + } +} From 1090d8920c4a2804b1ba5d6ca45712ba1a21b29e Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Mon, 5 Aug 2024 14:25:24 +0300 Subject: [PATCH 082/357] improve ci-rustc finding logic Signed-off-by: onur-ozkan --- src/bootstrap/src/core/config/config.rs | 29 +++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index b0af7f29d5e..e3641254b19 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -13,6 +13,7 @@ use std::str::FromStr; use std::sync::OnceLock; use std::{cmp, env, fs}; +use build_helper::ci::CiEnv; use build_helper::exit; use build_helper::git::{GitConfig, get_closest_merge_commit, output_result}; use serde::{Deserialize, Deserializer}; @@ -2718,13 +2719,15 @@ impl Config { download_rustc: Option, llvm_assertions: bool, ) -> Option { + if !is_download_ci_available(&self.build.triple, llvm_assertions) { + return None; + } + // If `download-rustc` is not set, default to rebuilding. let if_unchanged = match download_rustc { None | Some(StringOrBool::Bool(false)) => return None, Some(StringOrBool::Bool(true)) => false, - Some(StringOrBool::String(s)) if s == "if-unchanged" => { - is_download_ci_available(&self.build.triple, llvm_assertions) - } + Some(StringOrBool::String(s)) if s == "if-unchanged" => true, Some(StringOrBool::String(other)) => { panic!("unrecognized option for download-rustc: {other}") } @@ -2732,7 +2735,12 @@ impl Config { // Look for a version to compare to based on the current commit. // Only commits merged by bors will have CI artifacts. - let commit = get_closest_merge_commit(Some(&self.src), &self.git_config(), &[]).unwrap(); + let commit = get_closest_merge_commit( + Some(&self.src), + &self.git_config(), + &[self.src.join("compiler"), self.src.join("library")], + ) + .unwrap(); if commit.is_empty() { println!("ERROR: could not find commit hash for downloading rustc"); println!("HELP: maybe your repository history is too shallow?"); @@ -2741,6 +2749,19 @@ impl Config { crate::exit!(1); } + if CiEnv::is_ci() && { + let head_sha = + output(helpers::git(Some(&self.src)).arg("rev-parse").arg("HEAD").as_command_mut()); + let head_sha = head_sha.trim(); + commit == head_sha + } { + eprintln!("CI rustc commit matches with HEAD and we are in CI."); + eprintln!( + "`rustc.download-ci` functionality will be skipped as artifacts are not available." + ); + return None; + } + // Warn if there were changes to the compiler or standard library since the ancestor commit. let has_changes = !t!(helpers::git(Some(&self.src)) .args(["diff-index", "--quiet", &commit]) From ee5f51af30a009d08a76e99b005e0cbe03359873 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Tue, 28 May 2024 11:56:15 +0300 Subject: [PATCH 083/357] disable read-only mode in mingw-check image for merge pipeline Signed-off-by: onur-ozkan --- src/ci/github-actions/jobs.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index e8ad4319aff..4bbebbc4697 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -210,6 +210,8 @@ auto: <<: *job-linux-8c - image: mingw-check + env: + READ_ONLY_SRC: 0 <<: *job-linux-4c - image: test-various From a3bb170e370e5711ec401fe971411b40cfc254c8 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Tue, 28 May 2024 19:17:00 +0300 Subject: [PATCH 084/357] disable download-rustc on x86_64-gnu-integration Signed-off-by: onur-ozkan --- src/ci/docker/host-x86_64/x86_64-fuchsia/Dockerfile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/ci/docker/host-x86_64/x86_64-fuchsia/Dockerfile b/src/ci/docker/host-x86_64/x86_64-fuchsia/Dockerfile index ba3e8bdb687..0cae83a85b3 100644 --- a/src/ci/docker/host-x86_64/x86_64-fuchsia/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-fuchsia/Dockerfile @@ -58,6 +58,9 @@ RUN mkdir -p $RUST_INSTALL_DIR/etc # Fuchsia only supports LLVM. ENV CODEGEN_BACKENDS llvm +# download-rustc is not allowed for `x install` +ENV NO_DOWNLOAD_CI_RUSTC 1 + ENV RUST_CONFIGURE_ARGS \ --prefix=$RUST_INSTALL_DIR \ --sysconfdir=etc \ @@ -70,6 +73,7 @@ ENV RUST_CONFIGURE_ARGS \ --set target.x86_64-unknown-fuchsia.ar=/usr/local/bin/llvm-ar \ --set target.x86_64-unknown-fuchsia.ranlib=/usr/local/bin/llvm-ranlib \ --set target.x86_64-unknown-fuchsia.linker=/usr/local/bin/ld.lld + ENV SCRIPT \ python3 ../x.py install --target $TARGETS compiler/rustc library/std clippy && \ bash ../src/ci/docker/host-x86_64/x86_64-fuchsia/build-fuchsia.sh From b0b4f4a1f3bbad98abc08c4ea9dd447d39890b74 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Wed, 29 May 2024 09:25:24 +0300 Subject: [PATCH 085/357] fail on {dist, install} subcommand if download-rustc is enabled --- src/bootstrap/src/core/builder.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs index 155c6515db8..d32830c0a96 100644 --- a/src/bootstrap/src/core/builder.rs +++ b/src/bootstrap/src/core/builder.rs @@ -414,6 +414,15 @@ impl StepDescription { .map(|desc| (desc.should_run)(ShouldRun::new(builder, desc.kind))) .collect::>(); + if builder.download_rustc() && (builder.kind == Kind::Dist || builder.kind == Kind::Install) + { + eprintln!( + "ERROR: '{}' subcommand is incompatible with `rust.download-rustc`.", + builder.kind.as_str() + ); + crate::exit!(1); + } + // sanity checks on rules for (desc, should_run) in v.iter().zip(&should_runs) { assert!( From 8a5f418f147204ca3803b986db36d4867cc1cf20 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Mon, 5 Aug 2024 15:04:39 +0300 Subject: [PATCH 086/357] handle CI rustc incompatible runners Signed-off-by: onur-ozkan --- src/ci/docker/run.sh | 1 + src/ci/run.sh | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh index fad4b5af095..28487bce482 100755 --- a/src/ci/docker/run.sh +++ b/src/ci/docker/run.sh @@ -343,6 +343,7 @@ docker \ --env PR_CI_JOB \ --env OBJDIR_ON_HOST="$objdir" \ --env CODEGEN_BACKENDS \ + --env DISABLE_CI_RUSTC_IF_INCOMPATIBLE="$DISABLE_CI_RUSTC_IF_INCOMPATIBLE" \ --init \ --rm \ rust-ci \ diff --git a/src/ci/run.sh b/src/ci/run.sh index c33a376c2d6..8a8d26f8302 100755 --- a/src/ci/run.sh +++ b/src/ci/run.sh @@ -52,6 +52,11 @@ if [ "$CI" != "" ]; then RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set change-id=99999999" fi +# If runner uses an incompatible option and `FORCE_CI_RUSTC` is not defined, switch to in-tree rustc. +if [ "$FORCE_CI_RUSTC" == "" ]; then + DISABLE_CI_RUSTC_IF_INCOMPATIBLE=1 +fi + if ! isCI || isCiBranch auto || isCiBranch beta || isCiBranch try || isCiBranch try-perf || \ isCiBranch automation/bors/try; then RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set build.print-step-timings --enable-verbose-tests" From abac4dc8889bc741d1c1880c89abb8c1ca4420f8 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Mon, 5 Aug 2024 16:26:39 +0300 Subject: [PATCH 087/357] fix `ci_rustc_if_unchanged_logic` test Signed-off-by: onur-ozkan --- src/bootstrap/src/core/builder/tests.rs | 25 +++++++++---------- src/bootstrap/src/core/config/config.rs | 5 ++-- .../docker/host-x86_64/mingw-check/Dockerfile | 2 +- src/ci/run.sh | 3 ++- 4 files changed, 18 insertions(+), 17 deletions(-) diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index 363a9c82699..3d2e3daf915 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -1,5 +1,7 @@ use std::thread; +use build_helper::git::get_closest_merge_commit; + use super::*; use crate::Flags; use crate::core::build_steps::doc::DocumentationFormat; @@ -223,31 +225,30 @@ fn ci_rustc_if_unchanged_logic() { |&_| Ok(Default::default()), ); - let build = Build::new(config.clone()); - let builder = Builder::new(&build); - if config.rust_info.is_from_tarball() { return; } + let build = Build::new(config.clone()); + let builder = Builder::new(&build); + if config.out.exists() { fs::remove_dir_all(&config.out).unwrap(); } builder.run_step_descriptions(&Builder::get_step_descriptions(config.cmd.kind()), &[]); - let commit = helpers::get_closest_merge_base_commit( + let compiler_path = build.src.join("compiler"); + let library_path = build.src.join("compiler"); + + let commit = get_closest_merge_commit( Some(&builder.config.src), &builder.config.git_config(), - &builder.config.stage0_metadata.config.git_merge_commit_email, - &[], + &[compiler_path.clone(), library_path.clone()], ) .unwrap(); - let compiler_path = build.src.join("compiler"); - let library_path = build.src.join("library"); - - let has_changes = helpers::git(Some(&builder.src)) + let has_changes = !helpers::git(Some(&builder.src)) .args(["diff-index", "--quiet", &commit]) .arg("--") .args([compiler_path, library_path]) @@ -256,9 +257,7 @@ fn ci_rustc_if_unchanged_logic() { .unwrap() .success(); - assert!( - has_changes != config.out.join(config.build.to_string()).join("ci-rustc-sysroot").exists() - ); + assert!(has_changes == config.download_rustc_commit.is_none()); } mod defaults { diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index e3641254b19..76e3343e86f 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -2422,8 +2422,9 @@ impl Config { ci_config_toml, ); - let disable_ci_rustc_if_incompatible = - env::var_os("DISABLE_CI_RUSTC_IF_INCOMPATIBLE") + // Primarily used by CI runners to avoid handling download-rustc incompatible + // options one by one on shell scripts. + let disable_ci_rustc_if_incompatible = env::var_os("DISABLE_CI_RUSTC_IF_INCOMPATIBLE") .is_some_and(|s| s == "1" || s == "true"); if disable_ci_rustc_if_incompatible && res.is_err() { diff --git a/src/ci/docker/host-x86_64/mingw-check/Dockerfile b/src/ci/docker/host-x86_64/mingw-check/Dockerfile index 97fe56fbfcb..467ca1dac67 100644 --- a/src/ci/docker/host-x86_64/mingw-check/Dockerfile +++ b/src/ci/docker/host-x86_64/mingw-check/Dockerfile @@ -55,7 +55,7 @@ ENV SCRIPT \ git config --global user.name \"dummy\" && \ git add ../compiler/rustc/src/main.rs && \ git commit -m \"test commit for rust.download-rustc=if-unchanged logic\" && \ - python3 ../x.py test bootstrap -- core::builder::tests::ci_rustc_if_unchanged_logic && \ + DISABLE_CI_RUSTC_IF_INCOMPATIBLE=0 python3 ../x.py test bootstrap -- core::builder::tests::ci_rustc_if_unchanged_logic && \ # Revert the dummy commit git reset --hard HEAD~1 && \ diff --git a/src/ci/run.sh b/src/ci/run.sh index 8a8d26f8302..457f36bdd20 100755 --- a/src/ci/run.sh +++ b/src/ci/run.sh @@ -52,7 +52,8 @@ if [ "$CI" != "" ]; then RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set change-id=99999999" fi -# If runner uses an incompatible option and `FORCE_CI_RUSTC` is not defined, switch to in-tree rustc. +# If runner uses an incompatible option and `FORCE_CI_RUSTC` is not defined, +# switch to in-tree rustc. if [ "$FORCE_CI_RUSTC" == "" ]; then DISABLE_CI_RUSTC_IF_INCOMPATIBLE=1 fi From 4082f9f77567b6b5b61f411d9c08b66853e87a95 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Fri, 16 Aug 2024 21:57:28 +0300 Subject: [PATCH 088/357] force `download-rustc=if-unchanged` for x86_64-gnu-tools runner Signed-off-by: onur-ozkan --- src/bootstrap/src/core/builder/tests.rs | 12 ++++++------ src/bootstrap/src/core/config/config.rs | 9 ++++----- .../docker/host-x86_64/x86_64-gnu-tools/Dockerfile | 1 + src/ci/run.sh | 1 + 4 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index 3d2e3daf915..4a96ecf1421 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -241,12 +241,12 @@ fn ci_rustc_if_unchanged_logic() { let compiler_path = build.src.join("compiler"); let library_path = build.src.join("compiler"); - let commit = get_closest_merge_commit( - Some(&builder.config.src), - &builder.config.git_config(), - &[compiler_path.clone(), library_path.clone()], - ) - .unwrap(); + let commit = + get_closest_merge_commit(Some(&builder.config.src), &builder.config.git_config(), &[ + compiler_path.clone(), + library_path.clone(), + ]) + .unwrap(); let has_changes = !helpers::git(Some(&builder.src)) .args(["diff-index", "--quiet", &commit]) diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 76e3343e86f..9f84b492b80 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -2736,11 +2736,10 @@ impl Config { // Look for a version to compare to based on the current commit. // Only commits merged by bors will have CI artifacts. - let commit = get_closest_merge_commit( - Some(&self.src), - &self.git_config(), - &[self.src.join("compiler"), self.src.join("library")], - ) + let commit = get_closest_merge_commit(Some(&self.src), &self.git_config(), &[ + self.src.join("compiler"), + self.src.join("library"), + ]) .unwrap(); if commit.is_empty() { println!("ERROR: could not find commit hash for downloading rustc"); diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile index 145f41f21e1..17fc1a57492 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile @@ -84,6 +84,7 @@ ENV RUST_CONFIGURE_ARGS \ --enable-new-symbol-mangling ENV HOST_TARGET x86_64-unknown-linux-gnu +ENV FORCE_CI_RUSTC 1 COPY host-x86_64/dist-x86_64-linux/shared.sh /scripts/ COPY host-x86_64/dist-x86_64-linux/build-gccjit.sh /scripts/ diff --git a/src/ci/run.sh b/src/ci/run.sh index 457f36bdd20..1ce54f9ecb3 100755 --- a/src/ci/run.sh +++ b/src/ci/run.sh @@ -55,6 +55,7 @@ fi # If runner uses an incompatible option and `FORCE_CI_RUSTC` is not defined, # switch to in-tree rustc. if [ "$FORCE_CI_RUSTC" == "" ]; then + echo "debug: `DISABLE_CI_RUSTC_IF_INCOMPATIBLE` configured." DISABLE_CI_RUSTC_IF_INCOMPATIBLE=1 fi From 5db54bee68a0328cb49cef690be53c15d56cb857 Mon Sep 17 00:00:00 2001 From: Noa Date: Thu, 22 Aug 2024 14:42:46 -0500 Subject: [PATCH 089/357] Stabilize Pin::as_deref_mut --- library/core/src/pin.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index 9c13662e08e..fac789dbd99 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -1422,7 +1422,7 @@ impl Pin { /// move in the future, and this method does not enable the pointee to move. "Malicious" /// implementations of `Ptr::DerefMut` are likewise ruled out by the contract of /// `Pin::new_unchecked`. - #[unstable(feature = "pin_deref_mut", issue = "86918")] + #[stable(feature = "pin_deref_mut", since = "CURRENT_RUSTC_VERSION")] #[must_use = "`self` will be dropped if the result is not used"] #[inline(always)] pub fn as_deref_mut(self: Pin<&mut Pin>) -> Pin<&mut Ptr::Target> { From 17eca60c2432d4b140ec0dca441cc6fde6562698 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 8 Oct 2024 16:46:00 -0400 Subject: [PATCH 090/357] Dont ICE when encountering post-mono layout cycle error --- compiler/rustc_codegen_llvm/src/context.rs | 11 ++-- tests/ui/layout/post-mono-layout-cycle-2.rs | 59 +++++++++++++++++++ .../ui/layout/post-mono-layout-cycle-2.stderr | 23 ++++++++ tests/ui/layout/post-mono-layout-cycle.rs | 25 ++++++++ tests/ui/layout/post-mono-layout-cycle.stderr | 16 +++++ 5 files changed, 129 insertions(+), 5 deletions(-) create mode 100644 tests/ui/layout/post-mono-layout-cycle-2.rs create mode 100644 tests/ui/layout/post-mono-layout-cycle-2.stderr create mode 100644 tests/ui/layout/post-mono-layout-cycle.rs create mode 100644 tests/ui/layout/post-mono-layout-cycle.stderr diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 81b82840472..0a116971e07 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -1187,10 +1187,11 @@ impl<'tcx> FnAbiOfHelpers<'tcx> for CodegenCx<'_, 'tcx> { span: Span, fn_abi_request: FnAbiRequest<'tcx>, ) -> ! { - if let FnAbiError::Layout(LayoutError::SizeOverflow(_)) = err { - self.tcx.dcx().emit_fatal(Spanned { span, node: err }) - } else { - match fn_abi_request { + match err { + FnAbiError::Layout(LayoutError::SizeOverflow(_) | LayoutError::Cycle(_)) => { + self.tcx.dcx().emit_fatal(Spanned { span, node: err }); + } + _ => match fn_abi_request { FnAbiRequest::OfFnPtr { sig, extra_args } => { span_bug!(span, "`fn_abi_of_fn_ptr({sig}, {extra_args:?})` failed: {err:?}",); } @@ -1200,7 +1201,7 @@ impl<'tcx> FnAbiOfHelpers<'tcx> for CodegenCx<'_, 'tcx> { "`fn_abi_of_instance({instance}, {extra_args:?})` failed: {err:?}", ); } - } + }, } } } diff --git a/tests/ui/layout/post-mono-layout-cycle-2.rs b/tests/ui/layout/post-mono-layout-cycle-2.rs new file mode 100644 index 00000000000..356f1e777c7 --- /dev/null +++ b/tests/ui/layout/post-mono-layout-cycle-2.rs @@ -0,0 +1,59 @@ +//@ build-fail +//@ edition: 2021 + +#![feature(async_closure, noop_waker)] + +use std::future::Future; +use std::pin::pin; +use std::task::*; + +pub fn block_on(fut: impl Future) -> T { + let mut fut = pin!(fut); + // Poll loop, just to test the future... + let ctx = &mut Context::from_waker(Waker::noop()); + + loop { + match fut.as_mut().poll(ctx) { + Poll::Pending => {} + Poll::Ready(t) => break t, + } + } +} + +trait Blah { + async fn iter(&mut self, iterator: T) + where + T: IntoIterator; +} + +impl Blah for () { + async fn iter(&mut self, iterator: T) + //~^ ERROR recursion in an async fn requires boxing + where + T: IntoIterator, + { + Blah::iter(self, iterator).await + } +} + +struct Wrap { + t: T, +} + +impl Wrap +where + T: Blah, +{ + async fn ice(&mut self) { + //~^ ERROR a cycle occurred during layout computation + let arr: [(); 0] = []; + self.t.iter(arr.into_iter()).await; + } +} + +fn main() { + block_on(async { + let mut t = Wrap { t: () }; + t.ice(); + }) +} diff --git a/tests/ui/layout/post-mono-layout-cycle-2.stderr b/tests/ui/layout/post-mono-layout-cycle-2.stderr new file mode 100644 index 00000000000..ad01c2694fa --- /dev/null +++ b/tests/ui/layout/post-mono-layout-cycle-2.stderr @@ -0,0 +1,23 @@ +error[E0733]: recursion in an async fn requires boxing + --> $DIR/post-mono-layout-cycle-2.rs:30:5 + | +LL | / async fn iter(&mut self, iterator: T) +LL | | +LL | | where +LL | | T: IntoIterator, + | |___________________________________^ +LL | { +LL | Blah::iter(self, iterator).await + | -------------------------------- recursive call here + | + = note: a recursive `async fn` call must introduce indirection such as `Box::pin` to avoid an infinitely sized future + +error: a cycle occurred during layout computation + --> $DIR/post-mono-layout-cycle-2.rs:47:5 + | +LL | async fn ice(&mut self) { + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0733`. diff --git a/tests/ui/layout/post-mono-layout-cycle.rs b/tests/ui/layout/post-mono-layout-cycle.rs new file mode 100644 index 00000000000..8d136190c00 --- /dev/null +++ b/tests/ui/layout/post-mono-layout-cycle.rs @@ -0,0 +1,25 @@ +//@ build-fail +//~^ cycle detected when computing layout of `Wrapper<()>` + +trait Trait { + type Assoc; +} + +impl Trait for () { + type Assoc = Wrapper<()>; +} + +struct Wrapper { + _x: ::Assoc, +} + +fn abi(_: Option>) {} +//~^ ERROR a cycle occurred during layout computation + +fn indirect() { + abi::(None); +} + +fn main() { + indirect::<()>(); +} diff --git a/tests/ui/layout/post-mono-layout-cycle.stderr b/tests/ui/layout/post-mono-layout-cycle.stderr new file mode 100644 index 00000000000..47f7f30b1cb --- /dev/null +++ b/tests/ui/layout/post-mono-layout-cycle.stderr @@ -0,0 +1,16 @@ +error[E0391]: cycle detected when computing layout of `Wrapper<()>` + | + = note: ...which requires computing layout of `<() as Trait>::Assoc`... + = note: ...which again requires computing layout of `Wrapper<()>`, completing the cycle + = note: cycle used when computing layout of `core::option::Option>` + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information + +error: a cycle occurred during layout computation + --> $DIR/post-mono-layout-cycle.rs:16:1 + | +LL | fn abi(_: Option>) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0391`. From 35d9bdbcdebeb95e747efa366dac2c811ceab92d Mon Sep 17 00:00:00 2001 From: Noa Date: Tue, 8 Oct 2024 15:33:50 -0500 Subject: [PATCH 091/357] Use throw intrinsic from stdarch in wasm libunwind --- library/unwind/src/lib.rs | 3 +-- library/unwind/src/wasm.rs | 24 ++++++++++-------------- 2 files changed, 11 insertions(+), 16 deletions(-) diff --git a/library/unwind/src/lib.rs b/library/unwind/src/lib.rs index 46026324d2f..5a476d5843b 100644 --- a/library/unwind/src/lib.rs +++ b/library/unwind/src/lib.rs @@ -3,11 +3,10 @@ #![feature(link_cfg)] #![feature(staged_api)] #![feature(strict_provenance)] -#![cfg_attr(target_arch = "wasm64", feature(simd_wasm64))] #![cfg_attr(not(target_env = "msvc"), feature(libc))] #![cfg_attr( all(target_family = "wasm", not(target_os = "emscripten")), - feature(link_llvm_intrinsics) + feature(simd_wasm64, wasm_exception_handling_intrinsics) )] #![allow(internal_features)] diff --git a/library/unwind/src/wasm.rs b/library/unwind/src/wasm.rs index f4ffac1ba16..2d36a8be004 100644 --- a/library/unwind/src/wasm.rs +++ b/library/unwind/src/wasm.rs @@ -40,29 +40,25 @@ pub unsafe fn _Unwind_DeleteException(exception: *mut _Unwind_Exception) { } pub unsafe fn _Unwind_RaiseException(exception: *mut _Unwind_Exception) -> _Unwind_Reason_Code { - #[cfg(panic = "unwind")] - extern "C" { - /// LLVM lowers this intrinsic to the `throw` instruction. - // FIXME(coolreader18): move to stdarch - #[link_name = "llvm.wasm.throw"] - fn wasm_throw(tag: i32, ptr: *mut u8) -> !; - } - // The wasm `throw` instruction takes a "tag", which differentiates certain // types of exceptions from others. LLVM currently just identifies these // via integers, with 0 corresponding to C++ exceptions and 1 to C setjmp()/longjmp(). // Ideally, we'd be able to choose something unique for Rust, but for now, // we pretend to be C++ and implement the Itanium exception-handling ABI. cfg_if::cfg_if! { - // for now, unless we're -Zbuild-std with panic=unwind, never codegen a throw. + // panic=abort is default for wasm targets. Because an unknown instruction is a load-time + // error on wasm, instead of a runtime error like on traditional architectures, we never + // want to codegen a `throw` instruction, as that would break users using runtimes that + // don't yet support exceptions. The only time this first branch would be selected is if + // the user explicitly opts in to wasm exceptions, via -Zbuild-std with -Cpanic=unwind. if #[cfg(panic = "unwind")] { - wasm_throw(0, exception.cast()) + // corresponds with llvm::WebAssembly::Tag::CPP_EXCEPTION + // in llvm-project/llvm/include/llvm/CodeGen/WasmEHFuncInfo.h + const CPP_EXCEPTION_TAG: i32 = 0; + core::arch::wasm::throw::(exception.cast()) } else { let _ = exception; - #[cfg(target_arch = "wasm32")] - core::arch::wasm32::unreachable(); - #[cfg(target_arch = "wasm64")] - core::arch::wasm64::unreachable(); + core::arch::wasm::unreachable() } } } From 7018a99172ea325fb5fd29d452858824517e85b4 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Tue, 8 Oct 2024 19:14:49 -0400 Subject: [PATCH 092/357] Update cargo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This also adds three license exceptions to Cargo. * arrayref — BSD-2-Clause * blake3 — CC0-1.0 OR Apache-2.0 OR Apache-2.0 WITH LLVM-exception * constant_time_eq — CC0-1.0 OR MIT-0 OR Apache-2.0 These exceptions were added to rustc in rust-lang/rust#126930, so should be fine for Cargo as well. --- src/tools/cargo | 2 +- src/tools/tidy/src/deps.rs | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/tools/cargo b/src/tools/cargo index ad074abe3a1..15fbd2f607d 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit ad074abe3a18ce8444c06f962ceecfd056acfc73 +Subproject commit 15fbd2f607d4defc87053b8b76bf5038f2483cf4 diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 1ffad06457f..5163f039a23 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -129,11 +129,14 @@ const EXCEPTIONS_STDARCH: ExceptionList = &[ const EXCEPTIONS_CARGO: ExceptionList = &[ // tidy-alphabetical-start + ("arrayref", "BSD-2-Clause"), ("bitmaps", "MPL-2.0+"), + ("blake3", "CC0-1.0 OR Apache-2.0 OR Apache-2.0 WITH LLVM-exception"), ("bytesize", "Apache-2.0"), ("ciborium", "Apache-2.0"), ("ciborium-io", "Apache-2.0"), ("ciborium-ll", "Apache-2.0"), + ("constant_time_eq", "CC0-1.0 OR MIT-0 OR Apache-2.0"), ("dunce", "CC0-1.0 OR MIT-0 OR Apache-2.0"), ("encoding_rs", "(Apache-2.0 OR MIT) AND BSD-3-Clause"), ("fiat-crypto", "MIT OR Apache-2.0 OR BSD-1-Clause"), From 321a5db7d4026cf703d6deebc413c855ba133142 Mon Sep 17 00:00:00 2001 From: Peter Jaszkowiak Date: Sun, 14 Apr 2024 17:37:45 -0600 Subject: [PATCH 093/357] Reserve guarded string literals (RFC 3593) --- compiler/rustc_lexer/src/lib.rs | 93 +++++- compiler/rustc_lint/messages.ftl | 3 + .../rustc_lint/src/context/diagnostics.rs | 3 + compiler/rustc_lint/src/lints.rs | 7 + compiler/rustc_lint_defs/src/builtin.rs | 41 +++ compiler/rustc_lint_defs/src/lib.rs | 2 + compiler/rustc_parse/messages.ftl | 4 + compiler/rustc_parse/src/errors.rs | 18 ++ compiler/rustc_parse/src/lexer/mod.rs | 84 ++++- src/librustdoc/html/highlight.rs | 1 + .../crates/parser/src/lexed_str.rs | 6 + .../reserved-guarded-strings-macro-2021.rs | 20 ++ .../reserved-guarded-strings-macro-2024.rs | 21 ++ .../reserved-guarded-strings-lexing.rs | 80 +++++ .../reserved-guarded-strings-lexing.stderr | 271 ++++++++++++++++ .../reserved-guarded-strings-migration.fixed | 99 ++++++ .../reserved-guarded-strings-migration.rs | 99 ++++++ .../reserved-guarded-strings-migration.stderr | 293 ++++++++++++++++++ .../reserved-guarded-strings-via-macro-2.rs | 18 ++ ...eserved-guarded-strings-via-macro-2.stderr | 20 ++ .../reserved-guarded-strings-via-macro.rs | 12 + .../ui/rust-2024/reserved-guarded-strings.rs | 74 +++++ .../rust-2024/reserved-guarded-strings.stderr | 254 +++++++++++++++ 23 files changed, 1514 insertions(+), 9 deletions(-) create mode 100644 tests/ui/rust-2024/auxiliary/reserved-guarded-strings-macro-2021.rs create mode 100644 tests/ui/rust-2024/auxiliary/reserved-guarded-strings-macro-2024.rs create mode 100644 tests/ui/rust-2024/reserved-guarded-strings-lexing.rs create mode 100644 tests/ui/rust-2024/reserved-guarded-strings-lexing.stderr create mode 100644 tests/ui/rust-2024/reserved-guarded-strings-migration.fixed create mode 100644 tests/ui/rust-2024/reserved-guarded-strings-migration.rs create mode 100644 tests/ui/rust-2024/reserved-guarded-strings-migration.stderr create mode 100644 tests/ui/rust-2024/reserved-guarded-strings-via-macro-2.rs create mode 100644 tests/ui/rust-2024/reserved-guarded-strings-via-macro-2.stderr create mode 100644 tests/ui/rust-2024/reserved-guarded-strings-via-macro.rs create mode 100644 tests/ui/rust-2024/reserved-guarded-strings.rs create mode 100644 tests/ui/rust-2024/reserved-guarded-strings.stderr diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs index 60aab668cba..b0ab50dd773 100644 --- a/compiler/rustc_lexer/src/lib.rs +++ b/compiler/rustc_lexer/src/lib.rs @@ -104,6 +104,12 @@ pub enum TokenKind { /// for emoji identifier recovery, as those are not meant to be ever accepted. InvalidPrefix, + /// Guarded string literal prefix: `#"` or `##`. + /// + /// Used for reserving "guarded strings" (RFC 3598) in edition 2024. + /// Split into the component tokens on older editions. + GuardedStrPrefix, + /// Examples: `12u8`, `1.0e-40`, `b"123"`. Note that `_` is an invalid /// suffix, but may be present here on string and float literals. Users of /// this type will need to check for and reject that case. @@ -191,30 +197,41 @@ pub enum DocStyle { /// `rustc_ast::ast::LitKind`). #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] pub enum LiteralKind { - /// "12_u8", "0o100", "0b120i99", "1f32". + /// `12_u8`, `0o100`, `0b120i99`, `1f32`. Int { base: Base, empty_int: bool }, - /// "12.34f32", "1e3", but not "1f32". + /// `12.34f32`, `1e3`, but not `1f32`. Float { base: Base, empty_exponent: bool }, - /// "'a'", "'\\'", "'''", "';" + /// `'a'`, `'\\'`, `'''`, `';` Char { terminated: bool }, - /// "b'a'", "b'\\'", "b'''", "b';" + /// `b'a'`, `b'\\'`, `b'''`, `b';` Byte { terminated: bool }, - /// ""abc"", ""abc" + /// `"abc"`, `"abc` Str { terminated: bool }, - /// "b"abc"", "b"abc" + /// `b"abc"`, `b"abc` ByteStr { terminated: bool }, /// `c"abc"`, `c"abc` CStr { terminated: bool }, - /// "r"abc"", "r#"abc"#", "r####"ab"###"c"####", "r#"a". `None` indicates + /// `r"abc"`, `r#"abc"#`, `r####"ab"###"c"####`, `r#"a`. `None` indicates /// an invalid literal. RawStr { n_hashes: Option }, - /// "br"abc"", "br#"abc"#", "br####"ab"###"c"####", "br#"a". `None` + /// `br"abc"`, `br#"abc"#`, `br####"ab"###"c"####`, `br#"a`. `None` /// indicates an invalid literal. RawByteStr { n_hashes: Option }, /// `cr"abc"`, "cr#"abc"#", `cr#"a`. `None` indicates an invalid literal. RawCStr { n_hashes: Option }, } +/// `#"abc"#`, `##"a"` (fewer closing), or even `#"a` (unterminated). +/// +/// Can capture fewer closing hashes than starting hashes, +/// for more efficient lexing and better backwards diagnostics. +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] +pub struct GuardedStr { + pub n_hashes: u32, + pub terminated: bool, + pub token_len: u32, +} + #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] pub enum RawStrError { /// Non `#` characters exist between `r` and `"`, e.g. `r##~"abcde"##` @@ -403,6 +420,12 @@ impl Cursor<'_> { TokenKind::Literal { kind: literal_kind, suffix_start } } + // Guarded string literal prefix: `#"` or `##` + '#' if matches!(self.first(), '"' | '#') => { + self.bump(); + TokenKind::GuardedStrPrefix + } + // One-symbol tokens. ';' => Semi, ',' => Comma, @@ -780,6 +803,60 @@ impl Cursor<'_> { false } + /// Attempt to lex for a guarded string literal. + /// + /// Used by `rustc_parse::lexer` to lex for guarded strings + /// conditionally based on edition. + /// + /// Note: this will not reset the `Cursor` when a + /// guarded string is not found. It is the caller's + /// responsibility to do so. + pub fn guarded_double_quoted_string(&mut self) -> Option { + debug_assert!(self.prev() != '#'); + + let mut n_start_hashes: u32 = 0; + while self.first() == '#' { + n_start_hashes += 1; + self.bump(); + } + + if self.first() != '"' { + return None; + } + self.bump(); + debug_assert!(self.prev() == '"'); + + // Lex the string itself as a normal string literal + // so we can recover that for older editions later. + let terminated = self.double_quoted_string(); + if !terminated { + let token_len = self.pos_within_token(); + self.reset_pos_within_token(); + + return Some(GuardedStr { n_hashes: n_start_hashes, terminated: false, token_len }); + } + + // Consume closing '#' symbols. + // Note that this will not consume extra trailing `#` characters: + // `###"abcde"####` is lexed as a `GuardedStr { n_end_hashes: 3, .. }` + // followed by a `#` token. + let mut n_end_hashes = 0; + while self.first() == '#' && n_end_hashes < n_start_hashes { + n_end_hashes += 1; + self.bump(); + } + + // Reserved syntax, always an error, so it doesn't matter if + // `n_start_hashes != n_end_hashes`. + + self.eat_literal_suffix(); + + let token_len = self.pos_within_token(); + self.reset_pos_within_token(); + + Some(GuardedStr { n_hashes: n_start_hashes, terminated: true, token_len }) + } + /// Eats the double-quoted string and returns `n_hashes` and an error if encountered. fn raw_double_quoted_string(&mut self, prefix_len: u32) -> Result { // Wrap the actual function to handle the error with too many hashes. diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index d3799594871..e733e92c7cb 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -740,6 +740,9 @@ lint_reserved_prefix = prefix `{$prefix}` is unknown .label = unknown prefix .suggestion = insert whitespace here to avoid this being parsed as a prefix in Rust 2021 +lint_reserved_string = will be parsed as a guarded string in Rust 2024 + .suggestion = insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + lint_shadowed_into_iter = this method call resolves to `<&{$target} as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to `<{$target} as IntoIterator>::into_iter` in Rust {$edition} .use_iter_suggestion = use `.iter()` instead of `.into_iter()` to avoid ambiguity diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs index b5ab56912cb..565c3c04252 100644 --- a/compiler/rustc_lint/src/context/diagnostics.rs +++ b/compiler/rustc_lint/src/context/diagnostics.rs @@ -176,6 +176,9 @@ pub(super) fn decorate_lint(sess: &Session, diagnostic: BuiltinLintDiag, diag: & lints::RawPrefix { label: label_span, suggestion: label_span.shrink_to_hi() } .decorate_lint(diag); } + BuiltinLintDiag::ReservedString(suggestion) => { + lints::ReservedString { suggestion }.decorate_lint(diag); + } BuiltinLintDiag::UnusedBuiltinAttribute { attr_name, macro_name, invoc_span } => { lints::UnusedBuiltinAttribute { invoc_span, attr_name, macro_name }.decorate_lint(diag); } diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index a861894a444..87afeca0b28 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -3053,3 +3053,10 @@ pub(crate) enum MutRefSugg { #[derive(LintDiagnostic)] #[diag(lint_unqualified_local_imports)] pub(crate) struct UnqualifiedLocalImportsDiag {} + +#[derive(LintDiagnostic)] +#[diag(lint_reserved_string)] +pub(crate) struct ReservedString { + #[suggestion(code = " ", applicability = "machine-applicable")] + pub suggestion: Span, +} diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index a123059df8f..827791c54be 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -92,6 +92,7 @@ declare_lint_pass! { RUST_2021_INCOMPATIBLE_OR_PATTERNS, RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX, RUST_2021_PRELUDE_COLLISIONS, + RUST_2024_GUARDED_STRING_INCOMPATIBLE_SYNTAX, RUST_2024_INCOMPATIBLE_PAT, RUST_2024_PRELUDE_COLLISIONS, SELF_CONSTRUCTOR_FROM_OUTER_ITEM, @@ -4996,3 +4997,43 @@ declare_lint! { Warn, "detects pointer to integer transmutes in const functions and associated constants", } + +declare_lint! { + /// The `rust_2024_guarded_string_incompatible_syntax` lint detects `#` tokens + /// that will be parsed as part of a guarded string literal in Rust 2024. + /// + /// ### Example + /// + /// ```rust,edition2021,compile_fail + /// #![deny(rust_2024_guarded_string_incompatible_syntax)] + /// + /// macro_rules! m { + /// (# $x:expr #) => (); + /// (# $x:expr) => (); + /// } + /// + /// m!(#"hey"#); + /// m!(#"hello"); + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// Prior to Rust 2024, `#"hey"#` is three tokens: the first `#` + /// followed by the string literal `"hey"` then the final `#`. + /// In Rust 2024, the whole sequence is considered a single token. + /// + /// This lint suggests to add whitespace between the leading `#` + /// and the string to keep them separated in Rust 2024. + // Allow this lint -- rustdoc doesn't yet support threading edition into this lint's parser. + #[allow(rustdoc::invalid_rust_codeblocks)] + pub RUST_2024_GUARDED_STRING_INCOMPATIBLE_SYNTAX, + Allow, + "will be parsed as a guarded string in Rust 2024", + @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::EditionError(Edition::Edition2024), + reference: "issue #123735 ", + }; + crate_level_only +} diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 386918a5c41..c01fa5c54d6 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -614,6 +614,8 @@ pub enum BuiltinLintDiag { ReservedPrefix(Span, String), /// `'r#` in edition < 2021. RawPrefix(Span), + /// `##` or `#"` is edition < 2024. + ReservedString(Span), TrailingMacro(bool, Ident), BreakWithLabelAndLoop(Span), UnicodeTextFlow(Span, String), diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index 948199fd55c..ba5e2ddf4fc 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -706,6 +706,10 @@ parse_require_colon_after_labeled_expression = labeled expression must be follow .label = the label .suggestion = add `:` after the label +parse_reserved_string = invalid string literal + .note = unprefixed guarded string literals are reserved for future use since Rust 2024 + .suggestion_whitespace = consider inserting whitespace here + parse_return_types_use_thin_arrow = return types are denoted using `->` .suggestion = use `->` instead diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index dade3912751..124975f67f1 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -2110,6 +2110,24 @@ pub(crate) enum UnknownPrefixSugg { }, } +#[derive(Diagnostic)] +#[diag(parse_reserved_string)] +#[note] +pub(crate) struct ReservedString { + #[primary_span] + pub span: Span, + #[subdiagnostic] + pub sugg: Option, +} +#[derive(Subdiagnostic)] +#[suggestion( + parse_suggestion_whitespace, + code = " ", + applicability = "maybe-incorrect", + style = "verbose" +)] +pub(crate) struct GuardedStringSugg(#[primary_span] pub Span); + #[derive(Diagnostic)] #[diag(parse_too_many_hashes)] pub(crate) struct TooManyHashes { diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index 3e46fc93fa4..d627ef3d2cb 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -10,7 +10,8 @@ use rustc_lexer::unescape::{self, EscapeError, Mode}; use rustc_lexer::{Base, Cursor, DocStyle, LiteralKind, RawStrError}; use rustc_session::lint::BuiltinLintDiag; use rustc_session::lint::builtin::{ - RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX, TEXT_DIRECTION_CODEPOINT_IN_COMMENT, + RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX, RUST_2024_GUARDED_STRING_INCOMPATIBLE_SYNTAX, + TEXT_DIRECTION_CODEPOINT_IN_COMMENT, }; use rustc_session::parse::ParseSess; use rustc_span::symbol::Symbol; @@ -251,6 +252,7 @@ impl<'psess, 'src> StringReader<'psess, 'src> { let prefix_span = self.mk_sp(start, lit_start); return (Token::new(self.ident(start), prefix_span), preceded_by_whitespace); } + rustc_lexer::TokenKind::GuardedStrPrefix => self.maybe_report_guarded_str(start, str_before), rustc_lexer::TokenKind::Literal { kind, suffix_start } => { let suffix_start = start + BytePos(suffix_start); let (kind, symbol) = self.cook_lexer_literal(start, suffix_start, kind); @@ -781,6 +783,86 @@ impl<'psess, 'src> StringReader<'psess, 'src> { } } + /// Detect guarded string literal syntax + /// + /// RFC 3598 reserved this syntax for future use. As of Rust 2024, + /// using this syntax produces an error. In earlier editions, however, it + /// only results in an (allowed by default) lint, and is treated as + /// separate tokens. + fn maybe_report_guarded_str(&mut self, start: BytePos, str_before: &'src str) -> TokenKind { + let span = self.mk_sp(start, self.pos); + let edition2024 = span.edition().at_least_rust_2024(); + + let space_pos = start + BytePos(1); + let space_span = self.mk_sp(space_pos, space_pos); + + let mut cursor = Cursor::new(str_before); + + let (span, unterminated) = match cursor.guarded_double_quoted_string() { + Some(rustc_lexer::GuardedStr { n_hashes, terminated, token_len }) => { + let end = start + BytePos(token_len); + let span = self.mk_sp(start, end); + let str_start = start + BytePos(n_hashes); + + if edition2024 { + self.cursor = cursor; + self.pos = end; + } + + let unterminated = if terminated { None } else { Some(str_start) }; + + (span, unterminated) + } + _ => { + // We should only get here in the `##+` case. + debug_assert_eq!(self.str_from_to(start, start + BytePos(2)), "##"); + + (span, None) + } + }; + if edition2024 { + if let Some(str_start) = unterminated { + // Only a fatal error if string is unterminated. + self.dcx() + .struct_span_fatal( + self.mk_sp(str_start, self.pos), + "unterminated double quote string", + ) + .with_code(E0765) + .emit() + } + + let sugg = if span.from_expansion() { + None + } else { + Some(errors::GuardedStringSugg(space_span)) + }; + + // In Edition 2024 and later, emit a hard error. + let err = self.dcx().emit_err(errors::ReservedString { span, sugg }); + + token::Literal(token::Lit { + kind: token::Err(err), + symbol: self.symbol_from_to(start, self.pos), + suffix: None, + }) + } else { + // Before Rust 2024, only emit a lint for migration. + self.psess.buffer_lint( + RUST_2024_GUARDED_STRING_INCOMPATIBLE_SYNTAX, + span, + ast::CRATE_NODE_ID, + BuiltinLintDiag::ReservedString(space_span), + ); + + // For backwards compatibility, roll back to after just the first `#` + // and return the `Pound` token. + self.pos = start + BytePos(1); + self.cursor = Cursor::new(&str_before[1..]); + token::Pound + } + } + fn report_too_many_hashes(&self, start: BytePos, num: u32) -> ! { self.dcx().emit_fatal(errors::TooManyHashes { span: self.mk_sp(start, self.pos), num }); } diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index e7ddd4b73b4..b68b7295096 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -845,6 +845,7 @@ impl<'src> Classifier<'src> { // Number literals. LiteralKind::Float { .. } | LiteralKind::Int { .. } => Class::Number, }, + TokenKind::GuardedStrPrefix => return no_highlight(sink), TokenKind::Ident | TokenKind::RawIdent if lookahead == Some(TokenKind::Bang) => { self.in_macro = true; sink(Highlight::EnterSpan { class: Class::Macro(self.new_span(before, text)) }); diff --git a/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs b/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs index dceac815e0b..7ea23b4f752 100644 --- a/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs +++ b/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs @@ -187,6 +187,12 @@ impl<'a> Converter<'a> { } rustc_lexer::TokenKind::RawIdent => IDENT, + + rustc_lexer::TokenKind::GuardedStrPrefix => { + err = "Invalid string literal (reserved syntax)"; + ERROR + }, + rustc_lexer::TokenKind::Literal { kind, .. } => { self.extend_literal(token_text.len(), kind); return; diff --git a/tests/ui/rust-2024/auxiliary/reserved-guarded-strings-macro-2021.rs b/tests/ui/rust-2024/auxiliary/reserved-guarded-strings-macro-2021.rs new file mode 100644 index 00000000000..81080fcdce3 --- /dev/null +++ b/tests/ui/rust-2024/auxiliary/reserved-guarded-strings-macro-2021.rs @@ -0,0 +1,20 @@ +//@ force-host +//@ edition:2021 +//@ no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; +use std::str::FromStr; + +#[proc_macro] +pub fn number_of_tokens_in_a_guarded_string_literal(_: TokenStream) -> TokenStream { + TokenStream::from_str("#\"abc\"#").unwrap().into_iter().count().to_string().parse().unwrap() +} + +#[proc_macro] +pub fn number_of_tokens_in_a_guarded_unterminated_string_literal(_: TokenStream) -> TokenStream { + TokenStream::from_str("#\"abc\"").unwrap().into_iter().count().to_string().parse().unwrap() +} diff --git a/tests/ui/rust-2024/auxiliary/reserved-guarded-strings-macro-2024.rs b/tests/ui/rust-2024/auxiliary/reserved-guarded-strings-macro-2024.rs new file mode 100644 index 00000000000..2c3dc30f0ae --- /dev/null +++ b/tests/ui/rust-2024/auxiliary/reserved-guarded-strings-macro-2024.rs @@ -0,0 +1,21 @@ +//@ force-host +//@ compile-flags: -Zunstable-options +//@ edition:2024 +//@ no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; +use std::str::FromStr; + +#[proc_macro] +pub fn number_of_tokens_in_a_guarded_string_literal(_: TokenStream) -> TokenStream { + TokenStream::from_str("#\"abc\"#").unwrap().into_iter().count().to_string().parse().unwrap() +} + +#[proc_macro] +pub fn number_of_tokens_in_a_guarded_unterminated_string_literal(_: TokenStream) -> TokenStream { + TokenStream::from_str("#\"abc\"").unwrap().into_iter().count().to_string().parse().unwrap() +} diff --git a/tests/ui/rust-2024/reserved-guarded-strings-lexing.rs b/tests/ui/rust-2024/reserved-guarded-strings-lexing.rs new file mode 100644 index 00000000000..83e0dcbb4be --- /dev/null +++ b/tests/ui/rust-2024/reserved-guarded-strings-lexing.rs @@ -0,0 +1,80 @@ +//@ edition:2021 +// ignore-tidy-linelength + +#![warn(rust_2024_guarded_string_incompatible_syntax)] + +macro_rules! demo2 { + ( $a:tt $b:tt ) => { println!("two tokens") }; +} + +macro_rules! demo3 { + ( $a:tt $b:tt $c:tt ) => { println!("three tokens") }; +} + +macro_rules! demo4 { + ( $a:tt $b:tt $c:tt $d:tt ) => { println!("four tokens") }; +} + +macro_rules! demo5 { + ( $a:tt $b:tt $c:tt $d:tt $e:tt ) => { println!("five tokens") }; +} + +macro_rules! demo7 { + ( $a:tt $b:tt $c:tt $d:tt $e:tt $f:tt $g:tt ) => { println!("seven tokens") }; +} + + +fn main() { + demo3!(## "foo"); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + demo4!(### "foo"); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + demo4!(## "foo"#); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + demo7!(### "foo"###); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + + demo5!(###"foo"#); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + demo5!(#"foo"###); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + demo4!("foo"###); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + + // Non-ascii identifiers + demo2!(Ñ"foo"); + //~^ ERROR prefix `Ñ` is unknown + demo4!(Ñ#""#); + //~^ ERROR prefix `Ñ` is unknown + //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + demo3!(🙃#""); + //~^ ERROR identifiers cannot contain emoji + //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 +} diff --git a/tests/ui/rust-2024/reserved-guarded-strings-lexing.stderr b/tests/ui/rust-2024/reserved-guarded-strings-lexing.stderr new file mode 100644 index 00000000000..e2e1ac42f05 --- /dev/null +++ b/tests/ui/rust-2024/reserved-guarded-strings-lexing.stderr @@ -0,0 +1,271 @@ +error: prefix `Ñ` is unknown + --> $DIR/reserved-guarded-strings-lexing.rs:70:12 + | +LL | demo2!(Ñ"foo"); + | ^ unknown prefix + | + = note: prefixed identifiers and literals are reserved since Rust 2021 +help: consider inserting whitespace here + | +LL | demo2!(Ñ "foo"); + | + + +error: prefix `Ñ` is unknown + --> $DIR/reserved-guarded-strings-lexing.rs:72:12 + | +LL | demo4!(Ñ#""#); + | ^ unknown prefix + | + = note: prefixed identifiers and literals are reserved since Rust 2021 +help: consider inserting whitespace here + | +LL | demo4!(Ñ #""#); + | + + +error: identifiers cannot contain emoji: `🙃` + --> $DIR/reserved-guarded-strings-lexing.rs:76:12 + | +LL | demo3!(🙃#""); + | ^^ + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-lexing.rs:28:12 + | +LL | demo3!(## "foo"); + | ^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +note: the lint level is defined here + --> $DIR/reserved-guarded-strings-lexing.rs:4:9 + | +LL | #![warn(rust_2024_guarded_string_incompatible_syntax)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo3!(# # "foo"); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-lexing.rs:31:12 + | +LL | demo4!(### "foo"); + | ^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo4!(# ## "foo"); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-lexing.rs:31:13 + | +LL | demo4!(### "foo"); + | ^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo4!(## # "foo"); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-lexing.rs:36:12 + | +LL | demo4!(## "foo"#); + | ^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo4!(# # "foo"#); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-lexing.rs:39:12 + | +LL | demo7!(### "foo"###); + | ^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo7!(# ## "foo"###); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-lexing.rs:39:13 + | +LL | demo7!(### "foo"###); + | ^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo7!(## # "foo"###); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-lexing.rs:39:21 + | +LL | demo7!(### "foo"###); + | ^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo7!(### "foo"# ##); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-lexing.rs:39:22 + | +LL | demo7!(### "foo"###); + | ^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo7!(### "foo"## #); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-lexing.rs:49:12 + | +LL | demo5!(###"foo"#); + | ^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo5!(# ##"foo"#); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-lexing.rs:49:13 + | +LL | demo5!(###"foo"#); + | ^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo5!(## #"foo"#); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-lexing.rs:49:14 + | +LL | demo5!(###"foo"#); + | ^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo5!(### "foo"#); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-lexing.rs:56:12 + | +LL | demo5!(#"foo"###); + | ^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo5!(# "foo"###); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-lexing.rs:56:18 + | +LL | demo5!(#"foo"###); + | ^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo5!(#"foo"# ##); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-lexing.rs:56:19 + | +LL | demo5!(#"foo"###); + | ^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo5!(#"foo"## #); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-lexing.rs:63:17 + | +LL | demo4!("foo"###); + | ^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo4!("foo"# ##); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-lexing.rs:63:18 + | +LL | demo4!("foo"###); + | ^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo4!("foo"## #); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-lexing.rs:72:13 + | +LL | demo4!(Ñ#""#); + | ^^^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo4!(Ñ# ""#); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-lexing.rs:76:13 + | +LL | demo3!(🙃#""); + | ^^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo3!(🙃# ""); + | + + +error: aborting due to 3 previous errors; 18 warnings emitted + diff --git a/tests/ui/rust-2024/reserved-guarded-strings-migration.fixed b/tests/ui/rust-2024/reserved-guarded-strings-migration.fixed new file mode 100644 index 00000000000..d92df7b5375 --- /dev/null +++ b/tests/ui/rust-2024/reserved-guarded-strings-migration.fixed @@ -0,0 +1,99 @@ +//@ check-pass +//@ run-rustfix +//@ edition:2021 + +#![warn(rust_2024_guarded_string_incompatible_syntax)] + +macro_rules! demo1 { + ( $a:tt ) => { println!("one tokens") }; +} + +macro_rules! demo2 { + ( $a:tt $b:tt ) => { println!("two tokens") }; +} + +macro_rules! demo3 { + ( $a:tt $b:tt $c:tt ) => { println!("three tokens") }; +} + +macro_rules! demo4 { + ( $a:tt $b:tt $c:tt $d:tt ) => { println!("four tokens") }; +} + +macro_rules! demo5 { + ( $a:tt $b:tt $c:tt $d:tt $e:tt ) => { println!("five tokens") }; +} + +macro_rules! demo6 { + ( $a:tt $b:tt $c:tt $d:tt $e:tt $f:tt ) => { println!("six tokens") }; +} + + +fn main() { + demo1!(""); + demo2!(# ""); + demo3!(# ""#); + demo2!(# "foo"); + demo3!(# "foo"#); + demo2!("foo"#); + + demo3!(# # "foo"); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + demo4!(# # # "foo"); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + demo4!(# # "foo"#); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + demo6!(# # # "foo"# #); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + + demo4!("foo"# # #); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + + demo2!(# ""); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + demo3!(# ""#); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + demo3!(# # ""); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + demo2!(# "foo"); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + demo3!(# # "foo"); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + demo3!(# "foo"#); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + demo4!(# # "foo"#); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + demo5!(# # "foo"# #); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 +} diff --git a/tests/ui/rust-2024/reserved-guarded-strings-migration.rs b/tests/ui/rust-2024/reserved-guarded-strings-migration.rs new file mode 100644 index 00000000000..5905f2abe32 --- /dev/null +++ b/tests/ui/rust-2024/reserved-guarded-strings-migration.rs @@ -0,0 +1,99 @@ +//@ check-pass +//@ run-rustfix +//@ edition:2021 + +#![warn(rust_2024_guarded_string_incompatible_syntax)] + +macro_rules! demo1 { + ( $a:tt ) => { println!("one tokens") }; +} + +macro_rules! demo2 { + ( $a:tt $b:tt ) => { println!("two tokens") }; +} + +macro_rules! demo3 { + ( $a:tt $b:tt $c:tt ) => { println!("three tokens") }; +} + +macro_rules! demo4 { + ( $a:tt $b:tt $c:tt $d:tt ) => { println!("four tokens") }; +} + +macro_rules! demo5 { + ( $a:tt $b:tt $c:tt $d:tt $e:tt ) => { println!("five tokens") }; +} + +macro_rules! demo6 { + ( $a:tt $b:tt $c:tt $d:tt $e:tt $f:tt ) => { println!("six tokens") }; +} + + +fn main() { + demo1!(""); + demo2!(# ""); + demo3!(# ""#); + demo2!(# "foo"); + demo3!(# "foo"#); + demo2!("foo"#); + + demo3!(## "foo"); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + demo4!(### "foo"); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + demo4!(## "foo"#); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + demo6!(### "foo"##); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + + demo4!("foo"###); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + + demo2!(#""); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + demo3!(#""#); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + demo3!(##""); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + demo2!(#"foo"); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + demo3!(##"foo"); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + demo3!(#"foo"#); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + demo4!(##"foo"#); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + demo5!(##"foo"##); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 +} diff --git a/tests/ui/rust-2024/reserved-guarded-strings-migration.stderr b/tests/ui/rust-2024/reserved-guarded-strings-migration.stderr new file mode 100644 index 00000000000..d7f8e5c9b4b --- /dev/null +++ b/tests/ui/rust-2024/reserved-guarded-strings-migration.stderr @@ -0,0 +1,293 @@ +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-migration.rs:40:12 + | +LL | demo3!(## "foo"); + | ^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +note: the lint level is defined here + --> $DIR/reserved-guarded-strings-migration.rs:5:9 + | +LL | #![warn(rust_2024_guarded_string_incompatible_syntax)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo3!(# # "foo"); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-migration.rs:43:12 + | +LL | demo4!(### "foo"); + | ^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo4!(# ## "foo"); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-migration.rs:43:13 + | +LL | demo4!(### "foo"); + | ^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo4!(## # "foo"); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-migration.rs:48:12 + | +LL | demo4!(## "foo"#); + | ^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo4!(# # "foo"#); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-migration.rs:51:12 + | +LL | demo6!(### "foo"##); + | ^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo6!(# ## "foo"##); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-migration.rs:51:13 + | +LL | demo6!(### "foo"##); + | ^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo6!(## # "foo"##); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-migration.rs:51:21 + | +LL | demo6!(### "foo"##); + | ^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo6!(### "foo"# #); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-migration.rs:59:17 + | +LL | demo4!("foo"###); + | ^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo4!("foo"# ##); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-migration.rs:59:18 + | +LL | demo4!("foo"###); + | ^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo4!("foo"## #); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-migration.rs:65:12 + | +LL | demo2!(#""); + | ^^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo2!(# ""); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-migration.rs:68:12 + | +LL | demo3!(#""#); + | ^^^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo3!(# ""#); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-migration.rs:71:12 + | +LL | demo3!(##""); + | ^^^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo3!(# #""); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-migration.rs:71:13 + | +LL | demo3!(##""); + | ^^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo3!(## ""); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-migration.rs:76:12 + | +LL | demo2!(#"foo"); + | ^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo2!(# "foo"); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-migration.rs:79:12 + | +LL | demo3!(##"foo"); + | ^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo3!(# #"foo"); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-migration.rs:79:13 + | +LL | demo3!(##"foo"); + | ^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo3!(## "foo"); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-migration.rs:84:12 + | +LL | demo3!(#"foo"#); + | ^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo3!(# "foo"#); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-migration.rs:87:12 + | +LL | demo4!(##"foo"#); + | ^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo4!(# #"foo"#); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-migration.rs:87:13 + | +LL | demo4!(##"foo"#); + | ^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo4!(## "foo"#); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-migration.rs:92:12 + | +LL | demo5!(##"foo"##); + | ^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo5!(# #"foo"##); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-migration.rs:92:13 + | +LL | demo5!(##"foo"##); + | ^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo5!(## "foo"##); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-migration.rs:92:19 + | +LL | demo5!(##"foo"##); + | ^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo5!(##"foo"# #); + | + + +warning: 22 warnings emitted + diff --git a/tests/ui/rust-2024/reserved-guarded-strings-via-macro-2.rs b/tests/ui/rust-2024/reserved-guarded-strings-via-macro-2.rs new file mode 100644 index 00000000000..3f9f373ba22 --- /dev/null +++ b/tests/ui/rust-2024/reserved-guarded-strings-via-macro-2.rs @@ -0,0 +1,18 @@ +//@ edition:2021 +//@ aux-build:reserved-guarded-strings-macro-2021.rs +//@ aux-build:reserved-guarded-strings-macro-2024.rs + +extern crate reserved_guarded_strings_macro_2021 as m2021; +extern crate reserved_guarded_strings_macro_2024 as m2024; + +fn main() { + // Ok: + m2021::number_of_tokens_in_a_guarded_string_literal!(); + m2021::number_of_tokens_in_a_guarded_unterminated_string_literal!(); + + // Error, even though *this* crate is 2021: + m2024::number_of_tokens_in_a_guarded_string_literal!(); + //~^ ERROR invalid string literal + m2024::number_of_tokens_in_a_guarded_unterminated_string_literal!(); + //~^ ERROR invalid string literal +} diff --git a/tests/ui/rust-2024/reserved-guarded-strings-via-macro-2.stderr b/tests/ui/rust-2024/reserved-guarded-strings-via-macro-2.stderr new file mode 100644 index 00000000000..1074c8a682b --- /dev/null +++ b/tests/ui/rust-2024/reserved-guarded-strings-via-macro-2.stderr @@ -0,0 +1,20 @@ +error: invalid string literal + --> $DIR/reserved-guarded-strings-via-macro-2.rs:14:5 + | +LL | m2024::number_of_tokens_in_a_guarded_string_literal!(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: unprefixed guarded string literals are reserved for future use since Rust 2024 + = note: this error originates in the macro `m2024::number_of_tokens_in_a_guarded_string_literal` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: invalid string literal + --> $DIR/reserved-guarded-strings-via-macro-2.rs:16:5 + | +LL | m2024::number_of_tokens_in_a_guarded_unterminated_string_literal!(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: unprefixed guarded string literals are reserved for future use since Rust 2024 + = note: this error originates in the macro `m2024::number_of_tokens_in_a_guarded_unterminated_string_literal` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors + diff --git a/tests/ui/rust-2024/reserved-guarded-strings-via-macro.rs b/tests/ui/rust-2024/reserved-guarded-strings-via-macro.rs new file mode 100644 index 00000000000..f9e3c1e3c51 --- /dev/null +++ b/tests/ui/rust-2024/reserved-guarded-strings-via-macro.rs @@ -0,0 +1,12 @@ +//@ run-pass +//@ compile-flags: -Zunstable-options +//@ edition:2024 +//@ aux-build:reserved-guarded-strings-macro-2021.rs + +extern crate reserved_guarded_strings_macro_2021 as m2021; + +fn main() { + // Ok, even though *this* crate is 2024: + assert_eq!(m2021::number_of_tokens_in_a_guarded_string_literal!(), 3); + assert_eq!(m2021::number_of_tokens_in_a_guarded_unterminated_string_literal!(), 2); +} diff --git a/tests/ui/rust-2024/reserved-guarded-strings.rs b/tests/ui/rust-2024/reserved-guarded-strings.rs new file mode 100644 index 00000000000..dab97039be0 --- /dev/null +++ b/tests/ui/rust-2024/reserved-guarded-strings.rs @@ -0,0 +1,74 @@ +//@ compile-flags: -Zunstable-options +//@ edition:2024 +// ignore-tidy-linelength + +macro_rules! demo1 { + ( $a:tt ) => { println!("one tokens") }; +} + +macro_rules! demo2 { + ( $a:tt $b:tt ) => { println!("two tokens") }; +} + +macro_rules! demo3 { + ( $a:tt $b:tt $c:tt ) => { println!("three tokens") }; +} + +macro_rules! demo4 { + ( $a:tt $b:tt $c:tt $d:tt ) => { println!("four tokens") }; +} + +macro_rules! demo5 { + ( $a:tt $b:tt $c:tt $d:tt $e:tt ) => { println!("five tokens") }; +} + +macro_rules! demo6 { + ( $a:tt $b:tt $c:tt $d:tt $e:tt $f:tt ) => { println!("six tokens") }; +} + +macro_rules! demo7 { + ( $a:tt $b:tt $c:tt $d:tt $e:tt $f:tt $g:tt ) => { println!("seven tokens") }; +} + +macro_rules! demon { + ( $($n:tt)* ) => { println!("unknown number of tokens") }; +} + +fn main() { + demo1!(""); + demo2!(# ""); + demo3!(# ""#); + demo2!(# "foo"); + demo3!(# "foo"#); + demo2!("foo"#); + + demo2!(blah"xx"); //~ ERROR prefix `blah` is unknown + demo2!(blah#"xx"#); + //~^ ERROR prefix `blah` is unknown + //~| ERROR invalid string literal + + demo2!(## "foo"); //~ ERROR invalid string literal + demo3!("foo"###); //~ ERROR invalid string literal + demo3!(### "foo"); //~ ERROR invalid string literal + demo3!(## "foo"#); //~ ERROR invalid string literal + demo5!(### "foo"###); + //~^ ERROR invalid string literal + //~| ERROR invalid string literal + + demo1!(#""); //~ ERROR invalid string literal + demo1!(#""#); //~ ERROR invalid string literal + demo1!(####""); //~ ERROR invalid string literal + demo1!(#"foo"); //~ ERROR invalid string literal + demo1!(###"foo"); //~ ERROR invalid string literal + demo1!(#"foo"#); //~ ERROR invalid string literal + demo1!(###"foo"#); //~ ERROR invalid string literal + demo1!(###"foo"##); //~ ERROR invalid string literal + demo1!(###"foo"###); //~ ERROR invalid string literal + demo2!(#"foo"###); + //~^ ERROR invalid string literal + //~| ERROR invalid string literal + + // More than 255 hashes + demon!(####################################################################################################################################################################################################################################################################"foo"); + //~^ ERROR invalid string literal +} diff --git a/tests/ui/rust-2024/reserved-guarded-strings.stderr b/tests/ui/rust-2024/reserved-guarded-strings.stderr new file mode 100644 index 00000000000..f465ba7944a --- /dev/null +++ b/tests/ui/rust-2024/reserved-guarded-strings.stderr @@ -0,0 +1,254 @@ +error: prefix `blah` is unknown + --> $DIR/reserved-guarded-strings.rs:45:12 + | +LL | demo2!(blah"xx"); + | ^^^^ unknown prefix + | + = note: prefixed identifiers and literals are reserved since Rust 2021 +help: consider inserting whitespace here + | +LL | demo2!(blah "xx"); + | + + +error: prefix `blah` is unknown + --> $DIR/reserved-guarded-strings.rs:46:12 + | +LL | demo2!(blah#"xx"#); + | ^^^^ unknown prefix + | + = note: prefixed identifiers and literals are reserved since Rust 2021 +help: consider inserting whitespace here + | +LL | demo2!(blah #"xx"#); + | + + +error: invalid string literal + --> $DIR/reserved-guarded-strings.rs:46:16 + | +LL | demo2!(blah#"xx"#); + | ^^^^^^ + | + = note: unprefixed guarded string literals are reserved for future use since Rust 2024 +help: consider inserting whitespace here + | +LL | demo2!(blah# "xx"#); + | + + +error: invalid string literal + --> $DIR/reserved-guarded-strings.rs:50:12 + | +LL | demo2!(## "foo"); + | ^^ + | + = note: unprefixed guarded string literals are reserved for future use since Rust 2024 +help: consider inserting whitespace here + | +LL | demo2!(# # "foo"); + | + + +error: invalid string literal + --> $DIR/reserved-guarded-strings.rs:51:17 + | +LL | demo3!("foo"###); + | ^^ + | + = note: unprefixed guarded string literals are reserved for future use since Rust 2024 +help: consider inserting whitespace here + | +LL | demo3!("foo"# ##); + | + + +error: invalid string literal + --> $DIR/reserved-guarded-strings.rs:52:12 + | +LL | demo3!(### "foo"); + | ^^ + | + = note: unprefixed guarded string literals are reserved for future use since Rust 2024 +help: consider inserting whitespace here + | +LL | demo3!(# ## "foo"); + | + + +error: invalid string literal + --> $DIR/reserved-guarded-strings.rs:53:12 + | +LL | demo3!(## "foo"#); + | ^^ + | + = note: unprefixed guarded string literals are reserved for future use since Rust 2024 +help: consider inserting whitespace here + | +LL | demo3!(# # "foo"#); + | + + +error: invalid string literal + --> $DIR/reserved-guarded-strings.rs:54:12 + | +LL | demo5!(### "foo"###); + | ^^ + | + = note: unprefixed guarded string literals are reserved for future use since Rust 2024 +help: consider inserting whitespace here + | +LL | demo5!(# ## "foo"###); + | + + +error: invalid string literal + --> $DIR/reserved-guarded-strings.rs:54:21 + | +LL | demo5!(### "foo"###); + | ^^ + | + = note: unprefixed guarded string literals are reserved for future use since Rust 2024 +help: consider inserting whitespace here + | +LL | demo5!(### "foo"# ##); + | + + +error: invalid string literal + --> $DIR/reserved-guarded-strings.rs:58:12 + | +LL | demo1!(#""); + | ^^^ + | + = note: unprefixed guarded string literals are reserved for future use since Rust 2024 +help: consider inserting whitespace here + | +LL | demo1!(# ""); + | + + +error: invalid string literal + --> $DIR/reserved-guarded-strings.rs:59:12 + | +LL | demo1!(#""#); + | ^^^^ + | + = note: unprefixed guarded string literals are reserved for future use since Rust 2024 +help: consider inserting whitespace here + | +LL | demo1!(# ""#); + | + + +error: invalid string literal + --> $DIR/reserved-guarded-strings.rs:60:12 + | +LL | demo1!(####""); + | ^^^^^^ + | + = note: unprefixed guarded string literals are reserved for future use since Rust 2024 +help: consider inserting whitespace here + | +LL | demo1!(# ###""); + | + + +error: invalid string literal + --> $DIR/reserved-guarded-strings.rs:61:12 + | +LL | demo1!(#"foo"); + | ^^^^^^ + | + = note: unprefixed guarded string literals are reserved for future use since Rust 2024 +help: consider inserting whitespace here + | +LL | demo1!(# "foo"); + | + + +error: invalid string literal + --> $DIR/reserved-guarded-strings.rs:62:12 + | +LL | demo1!(###"foo"); + | ^^^^^^^^ + | + = note: unprefixed guarded string literals are reserved for future use since Rust 2024 +help: consider inserting whitespace here + | +LL | demo1!(# ##"foo"); + | + + +error: invalid string literal + --> $DIR/reserved-guarded-strings.rs:63:12 + | +LL | demo1!(#"foo"#); + | ^^^^^^^ + | + = note: unprefixed guarded string literals are reserved for future use since Rust 2024 +help: consider inserting whitespace here + | +LL | demo1!(# "foo"#); + | + + +error: invalid string literal + --> $DIR/reserved-guarded-strings.rs:64:12 + | +LL | demo1!(###"foo"#); + | ^^^^^^^^^ + | + = note: unprefixed guarded string literals are reserved for future use since Rust 2024 +help: consider inserting whitespace here + | +LL | demo1!(# ##"foo"#); + | + + +error: invalid string literal + --> $DIR/reserved-guarded-strings.rs:65:12 + | +LL | demo1!(###"foo"##); + | ^^^^^^^^^^ + | + = note: unprefixed guarded string literals are reserved for future use since Rust 2024 +help: consider inserting whitespace here + | +LL | demo1!(# ##"foo"##); + | + + +error: invalid string literal + --> $DIR/reserved-guarded-strings.rs:66:12 + | +LL | demo1!(###"foo"###); + | ^^^^^^^^^^^ + | + = note: unprefixed guarded string literals are reserved for future use since Rust 2024 +help: consider inserting whitespace here + | +LL | demo1!(# ##"foo"###); + | + + +error: invalid string literal + --> $DIR/reserved-guarded-strings.rs:67:12 + | +LL | demo2!(#"foo"###); + | ^^^^^^^ + | + = note: unprefixed guarded string literals are reserved for future use since Rust 2024 +help: consider inserting whitespace here + | +LL | demo2!(# "foo"###); + | + + +error: invalid string literal + --> $DIR/reserved-guarded-strings.rs:67:19 + | +LL | demo2!(#"foo"###); + | ^^ + | + = note: unprefixed guarded string literals are reserved for future use since Rust 2024 +help: consider inserting whitespace here + | +LL | demo2!(#"foo"## #); + | + + +error: invalid string literal + --> $DIR/reserved-guarded-strings.rs:72:12 + | +LL | ...n!(####################################################################################################################################################################################################################################################################"foo... + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: unprefixed guarded string literals are reserved for future use since Rust 2024 +help: consider inserting whitespace here + | +LL | demon!(# ###################################################################################################################################################################################################################################################################"foo"); + | + + +error: aborting due to 21 previous errors + From 8da92b5ce24a218347b331ddfbe7d08db6aa73f3 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Tue, 8 Oct 2024 16:13:54 -0700 Subject: [PATCH 094/357] compiler: Factor rustc_target::abi::* out of middle::ty::layout --- compiler/rustc_middle/Cargo.toml | 1 + compiler/rustc_middle/src/ty/layout.rs | 24 +++++++++++++++++------- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_middle/Cargo.toml b/compiler/rustc_middle/Cargo.toml index b23589afb58..8cb602d9ea8 100644 --- a/compiler/rustc_middle/Cargo.toml +++ b/compiler/rustc_middle/Cargo.toml @@ -12,6 +12,7 @@ field-offset = "0.3.5" gsgdt = "0.1.2" polonius-engine = "0.13.0" rustc-rayon-core = { version = "0.5.0", optional = true } +rustc_abi = { path = "../rustc_abi" } rustc_apfloat = "0.2.0" rustc_arena = { path = "../rustc_arena" } rustc_ast = { path = "../rustc_ast" } diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 4ba2a9b1d73..6c12b691c26 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -2,11 +2,15 @@ use std::num::NonZero; use std::ops::Bound; use std::{cmp, fmt}; +use rustc_abi::Primitive::{self, Float, Int, Pointer}; +use rustc_abi::{ + Abi, AddressSpace, Align, FieldsShape, HasDataLayout, Integer, LayoutCalculator, LayoutS, + PointeeInfo, PointerKind, ReprOptions, Scalar, Size, TagEncoding, TargetDataLayout, Variants, +}; use rustc_error_messages::DiagMessage; use rustc_errors::{ Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, IntoDiagArg, Level, }; -use rustc_hir as hir; use rustc_hir::LangItem; use rustc_hir::def_id::DefId; use rustc_index::IndexVec; @@ -15,10 +19,11 @@ use rustc_session::config::OptLevel; use rustc_span::symbol::{Symbol, sym}; use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span}; use rustc_target::abi::call::FnAbi; -use rustc_target::abi::*; +use rustc_target::abi::{FieldIdx, TyAbiInterface, VariantIdx, call}; use rustc_target::spec::abi::Abi as SpecAbi; use rustc_target::spec::{HasTargetSpec, HasWasmCAbiOpt, PanicStrategy, Target, WasmCAbi}; use tracing::debug; +use {rustc_abi as abi, rustc_hir as hir}; use crate::error::UnsupportedFnAbi; use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; @@ -27,9 +32,10 @@ use crate::ty::normalize_erasing_regions::NormalizationError; use crate::ty::{self, CoroutineArgsExt, Ty, TyCtxt, TypeVisitableExt}; #[extension(pub trait IntegerExt)] -impl Integer { +impl abi::Integer { #[inline] fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>, signed: bool) -> Ty<'tcx> { + use abi::Integer::{I8, I16, I32, I64, I128}; match (*self, signed) { (I8, false) => tcx.types.u8, (I16, false) => tcx.types.u16, @@ -44,7 +50,8 @@ impl Integer { } } - fn from_int_ty(cx: &C, ity: ty::IntTy) -> Integer { + fn from_int_ty(cx: &C, ity: ty::IntTy) -> abi::Integer { + use abi::Integer::{I8, I16, I32, I64, I128}; match ity { ty::IntTy::I8 => I8, ty::IntTy::I16 => I16, @@ -54,7 +61,8 @@ impl Integer { ty::IntTy::Isize => cx.data_layout().ptr_sized_integer(), } } - fn from_uint_ty(cx: &C, ity: ty::UintTy) -> Integer { + fn from_uint_ty(cx: &C, ity: ty::UintTy) -> abi::Integer { + use abi::Integer::{I8, I16, I32, I64, I128}; match ity { ty::UintTy::U8 => I8, ty::UintTy::U16 => I16, @@ -102,7 +110,7 @@ impl Integer { tcx.data_layout().c_enum_min_size } else { // repr(Rust) enums try to be as small as possible - I8 + Integer::I8 }; // If there are no negative values, we can use the unsigned fit. @@ -115,9 +123,10 @@ impl Integer { } #[extension(pub trait FloatExt)] -impl Float { +impl abi::Float { #[inline] fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { + use abi::Float::*; match *self { F16 => tcx.types.f16, F32 => tcx.types.f32, @@ -127,6 +136,7 @@ impl Float { } fn from_float_ty(fty: ty::FloatTy) -> Self { + use abi::Float::*; match fty { ty::FloatTy::F16 => F16, ty::FloatTy::F32 => F32, From 11c48bee11150987e4cce40ff83d0dc083d5c172 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Tue, 8 Oct 2024 16:58:27 -0700 Subject: [PATCH 095/357] compiler: Factor rustc_target::abi::* out of ty_utils --- compiler/rustc_ty_utils/Cargo.toml | 1 + compiler/rustc_ty_utils/src/abi.rs | 4 +++- compiler/rustc_ty_utils/src/layout.rs | 20 +++++++++++++------- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_ty_utils/Cargo.toml b/compiler/rustc_ty_utils/Cargo.toml index 01d5251bfa0..40356e0c978 100644 --- a/compiler/rustc_ty_utils/Cargo.toml +++ b/compiler/rustc_ty_utils/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" [dependencies] # tidy-alphabetical-start itertools = "0.12" +rustc_abi = { path = "../rustc_abi" } rustc_ast_ir = { path = "../rustc_ast_ir" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index 3d6c09bf89c..deda16b76b5 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -1,5 +1,8 @@ use std::iter; +use rustc_abi::Float::*; +use rustc_abi::Primitive::{Float, Pointer}; +use rustc_abi::{Abi, AddressSpace, PointerKind, Scalar, Size}; use rustc_hir as hir; use rustc_hir::lang_items::LangItem; use rustc_middle::bug; @@ -14,7 +17,6 @@ use rustc_target::abi::call::{ ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, Conv, FnAbi, PassMode, Reg, RegKind, RiscvInterruptKind, }; -use rustc_target::abi::*; use rustc_target::spec::abi::Abi as SpecAbi; use tracing::debug; diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 34c9f1b63c0..afdfa2e80c1 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -2,7 +2,12 @@ use std::fmt::Debug; use std::iter; use hir::def_id::DefId; -use rustc_hir as hir; +use rustc_abi::Integer::{I8, I32}; +use rustc_abi::Primitive::{self, Float, Int, Pointer}; +use rustc_abi::{ + Abi, AbiAndPrefAlign, AddressSpace, Align, FieldsShape, HasDataLayout, LayoutCalculatorError, + LayoutS, Niche, ReprOptions, Scalar, Size, StructKind, TagEncoding, Variants, WrappingRange, +}; use rustc_index::bit_set::BitSet; use rustc_index::{IndexSlice, IndexVec}; use rustc_middle::bug; @@ -18,8 +23,9 @@ use rustc_middle::ty::{ use rustc_session::{DataTypeKind, FieldInfo, FieldKind, SizeKind, VariantInfo}; use rustc_span::sym; use rustc_span::symbol::Symbol; -use rustc_target::abi::*; +use rustc_target::abi::{FIRST_VARIANT, FieldIdx, Layout, VariantIdx}; use tracing::{debug, instrument, trace}; +use {rustc_abi as abi, rustc_hir as hir}; use crate::errors::{ MultipleArrayFieldsSimdType, NonPrimitiveSimdType, OversizedSimdType, ZeroLengthSimdType, @@ -202,9 +208,9 @@ fn layout_of_uncached<'tcx>( value: Int(I32, false), valid_range: WrappingRange { start: 0, end: 0x10FFFF }, })), - ty::Int(ity) => scalar(Int(Integer::from_int_ty(dl, ity), true)), - ty::Uint(ity) => scalar(Int(Integer::from_uint_ty(dl, ity), false)), - ty::Float(fty) => scalar(Float(Float::from_float_ty(fty))), + ty::Int(ity) => scalar(Int(abi::Integer::from_int_ty(dl, ity), true)), + ty::Uint(ity) => scalar(Int(abi::Integer::from_uint_ty(dl, ity), false)), + ty::Float(fty) => scalar(Float(abi::Float::from_float_ty(fty))), ty::FnPtr(..) => { let mut ptr = scalar_unit(Pointer(dl.instruction_address_space)); ptr.valid_range_mut().start = 1; @@ -563,7 +569,7 @@ fn layout_of_uncached<'tcx>( } let get_discriminant_type = - |min, max| Integer::repr_discr(tcx, ty, &def.repr(), min, max); + |min, max| abi::Integer::repr_discr(tcx, ty, &def.repr(), min, max); let discriminants_iter = || { def.is_enum() @@ -816,7 +822,7 @@ fn coroutine_layout<'tcx>( // `info.variant_fields` already accounts for the reserved variants, so no need to add them. let max_discr = (info.variant_fields.len() - 1) as u128; - let discr_int = Integer::fit_unsigned(max_discr); + let discr_int = abi::Integer::fit_unsigned(max_discr); let tag = Scalar::Initialized { value: Primitive::Int(discr_int, /* signed = */ false), valid_range: WrappingRange { start: 0, end: max_discr }, From 9d95c8bd1606b914a0fc1ae9ba21efb3490491ce Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Tue, 8 Oct 2024 16:59:24 -0700 Subject: [PATCH 096/357] compiler: Factor rustc_target::abi out of const_eval --- compiler/rustc_const_eval/Cargo.toml | 1 + .../rustc_const_eval/src/interpret/operand.rs | 15 ++++++++------- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_const_eval/Cargo.toml b/compiler/rustc_const_eval/Cargo.toml index c4f8841d71c..41136019a88 100644 --- a/compiler/rustc_const_eval/Cargo.toml +++ b/compiler/rustc_const_eval/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" [dependencies] # tidy-alphabetical-start either = "1" +rustc_abi = { path = "../rustc_abi" } rustc_apfloat = "0.2.0" rustc_ast = { path = "../rustc_ast" } rustc_attr = { path = "../rustc_attr" } diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index 3b5af113e99..cd5e2aeca85 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -4,13 +4,14 @@ use std::assert_matches::assert_matches; use either::{Either, Left, Right}; +use rustc_abi as abi; +use rustc_abi::{Abi, HasDataLayout, Size}; use rustc_hir::def::Namespace; use rustc_middle::mir::interpret::ScalarSizeMismatch; use rustc_middle::ty::layout::{HasParamEnv, HasTyCtxt, LayoutOf, TyAndLayout}; use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter}; use rustc_middle::ty::{ConstInt, ScalarInt, Ty, TyCtxt}; use rustc_middle::{bug, mir, span_bug, ty}; -use rustc_target::abi::{self, Abi, HasDataLayout, Size}; use tracing::trace; use super::{ @@ -117,7 +118,7 @@ impl Immediate { match (self, abi) { (Immediate::Scalar(scalar), Abi::Scalar(s)) => { assert_eq!(scalar.size(), s.size(cx), "{msg}: scalar value has wrong size"); - if !matches!(s.primitive(), abi::Pointer(..)) { + if !matches!(s.primitive(), abi::Primitive::Pointer(..)) { // This is not a pointer, it should not carry provenance. assert!( matches!(scalar, Scalar::Int(..)), @@ -131,7 +132,7 @@ impl Immediate { a.size(cx), "{msg}: first component of scalar pair has wrong size" ); - if !matches!(a.primitive(), abi::Pointer(..)) { + if !matches!(a.primitive(), abi::Primitive::Pointer(..)) { assert!( matches!(a_val, Scalar::Int(..)), "{msg}: first component of scalar pair should be an integer, but has provenance" @@ -142,7 +143,7 @@ impl Immediate { b.size(cx), "{msg}: second component of scalar pair has wrong size" ); - if !matches!(b.primitive(), abi::Pointer(..)) { + if !matches!(b.primitive(), abi::Primitive::Pointer(..)) { assert!( matches!(b_val, Scalar::Int(..)), "{msg}: second component of scalar pair should be an integer, but has provenance" @@ -572,7 +573,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { assert_eq!(size, mplace.layout.size, "abi::Scalar size does not match layout size"); let scalar = alloc.read_scalar( alloc_range(Size::ZERO, size), - /*read_provenance*/ matches!(s, abi::Pointer(_)), + /*read_provenance*/ matches!(s, abi::Primitive::Pointer(_)), )?; Some(ImmTy::from_scalar(scalar, mplace.layout)) } @@ -588,11 +589,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { assert!(b_offset.bytes() > 0); // in `operand_field` we use the offset to tell apart the fields let a_val = alloc.read_scalar( alloc_range(Size::ZERO, a_size), - /*read_provenance*/ matches!(a, abi::Pointer(_)), + /*read_provenance*/ matches!(a, abi::Primitive::Pointer(_)), )?; let b_val = alloc.read_scalar( alloc_range(b_offset, b_size), - /*read_provenance*/ matches!(b, abi::Pointer(_)), + /*read_provenance*/ matches!(b, abi::Primitive::Pointer(_)), )?; Some(ImmTy::from_immediate(Immediate::ScalarPair(a_val, b_val), mplace.layout)) } From ff17ce2f6a9110ff45ca2b9e14de255a47cbbaa8 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Tue, 8 Oct 2024 17:25:22 -0700 Subject: [PATCH 097/357] compiler: Factor rustc_target::abi out of hir_typeck --- compiler/rustc_hir_typeck/Cargo.toml | 1 + compiler/rustc_hir_typeck/src/intrinsicck.rs | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_hir_typeck/Cargo.toml b/compiler/rustc_hir_typeck/Cargo.toml index 73a775690d6..894402a8c2e 100644 --- a/compiler/rustc_hir_typeck/Cargo.toml +++ b/compiler/rustc_hir_typeck/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" [dependencies] # tidy-alphabetical-start itertools = "0.12" +rustc_abi = { path = "../rustc_abi" } rustc_ast = { path = "../rustc_ast" } rustc_ast_ir = { path = "../rustc_ast_ir" } rustc_attr = { path = "../rustc_attr" } diff --git a/compiler/rustc_hir_typeck/src/intrinsicck.rs b/compiler/rustc_hir_typeck/src/intrinsicck.rs index a4121adf628..8a7005ac328 100644 --- a/compiler/rustc_hir_typeck/src/intrinsicck.rs +++ b/compiler/rustc_hir_typeck/src/intrinsicck.rs @@ -1,4 +1,5 @@ use hir::HirId; +use rustc_abi::Primitive::Pointer; use rustc_errors::codes::*; use rustc_errors::struct_span_code_err; use rustc_hir as hir; @@ -6,7 +7,7 @@ use rustc_index::Idx; use rustc_middle::bug; use rustc_middle::ty::layout::{LayoutError, SizeSkeleton}; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt}; -use rustc_target::abi::{Pointer, VariantIdx}; +use rustc_target::abi::VariantIdx; use tracing::trace; use super::FnCtxt; From 839cf1c1a4f60575f9000b9f6d5676ec1efbe3e8 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Tue, 8 Oct 2024 17:27:32 -0700 Subject: [PATCH 098/357] compiler: Factor rustc_target::abi out of cg_ssa --- compiler/rustc_codegen_ssa/Cargo.toml | 1 + compiler/rustc_codegen_ssa/src/mir/operand.rs | 5 +++-- compiler/rustc_codegen_ssa/src/mir/place.rs | 6 +++--- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml index 58baf40b581..dffb7a7271e 100644 --- a/compiler/rustc_codegen_ssa/Cargo.toml +++ b/compiler/rustc_codegen_ssa/Cargo.toml @@ -14,6 +14,7 @@ itertools = "0.12" jobserver = "0.1.28" pathdiff = "0.2.0" regex = "1.4" +rustc_abi = { path = "../rustc_abi" } rustc_arena = { path = "../rustc_arena" } rustc_ast = { path = "../rustc_ast" } rustc_attr = { path = "../rustc_attr" } diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs index 0bcd7d6d081..88ceff327d0 100644 --- a/compiler/rustc_codegen_ssa/src/mir/operand.rs +++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs @@ -3,12 +3,13 @@ use std::fmt; use arrayvec::ArrayVec; use either::Either; +use rustc_abi as abi; +use rustc_abi::{Abi, Align, Size}; use rustc_middle::bug; use rustc_middle::mir::interpret::{Pointer, Scalar, alloc_range}; use rustc_middle::mir::{self, ConstValue}; use rustc_middle::ty::Ty; use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; -use rustc_target::abi::{self, Abi, Align, Size}; use tracing::debug; use super::place::{PlaceRef, PlaceValue}; @@ -207,7 +208,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { match alloc.0.read_scalar( bx, alloc_range(start, size), - /*read_provenance*/ matches!(s.primitive(), abi::Pointer(_)), + /*read_provenance*/ matches!(s.primitive(), abi::Primitive::Pointer(_)), ) { Ok(val) => bx.scalar_to_backend(val, s, ty), Err(_) => bx.const_poison(ty), diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs index 0b764ae7747..a7d5541481a 100644 --- a/compiler/rustc_codegen_ssa/src/mir/place.rs +++ b/compiler/rustc_codegen_ssa/src/mir/place.rs @@ -1,10 +1,10 @@ +use rustc_abi::Primitive::{Int, Pointer}; +use rustc_abi::{Align, FieldsShape, Size, TagEncoding, Variants}; use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout}; use rustc_middle::ty::{self, Ty}; use rustc_middle::{bug, mir}; -use rustc_target::abi::{ - Align, FieldsShape, Int, Pointer, Size, TagEncoding, VariantIdx, Variants, -}; +use rustc_target::abi::VariantIdx; use tracing::{debug, instrument}; use super::operand::OperandValue; From 1379ef592aa201095f0e827a4f28d27cbc3fdb05 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Tue, 8 Oct 2024 17:29:00 -0700 Subject: [PATCH 099/357] compiler: Factor rustc_target::abi out of cg_llvm --- compiler/rustc_codegen_llvm/Cargo.toml | 1 + compiler/rustc_codegen_llvm/src/abi.rs | 4 +++- compiler/rustc_codegen_llvm/src/builder.rs | 9 +++++---- compiler/rustc_codegen_llvm/src/common.rs | 4 +++- compiler/rustc_codegen_llvm/src/type_of.rs | 3 ++- 5 files changed, 14 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_codegen_llvm/Cargo.toml b/compiler/rustc_codegen_llvm/Cargo.toml index a93baf88413..03a871297c4 100644 --- a/compiler/rustc_codegen_llvm/Cargo.toml +++ b/compiler/rustc_codegen_llvm/Cargo.toml @@ -14,6 +14,7 @@ libc = "0.2" measureme = "11" object = { version = "0.36.3", default-features = false, features = ["std", "read"] } rustc-demangle = "0.1.21" +rustc_abi = { path = "../rustc_abi" } rustc_ast = { path = "../rustc_ast" } rustc_attr = { path = "../rustc_attr" } rustc_codegen_ssa = { path = "../rustc_codegen_ssa" } diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs index 6a29eb5fa04..2fe5ed32daa 100644 --- a/compiler/rustc_codegen_llvm/src/abi.rs +++ b/compiler/rustc_codegen_llvm/src/abi.rs @@ -1,6 +1,9 @@ use std::cmp; use libc::c_uint; +use rustc_abi as abi; +use rustc_abi::Primitive::Int; +use rustc_abi::{HasDataLayout, Size}; use rustc_codegen_ssa::MemFlags; use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue}; use rustc_codegen_ssa::mir::place::{PlaceRef, PlaceValue}; @@ -11,7 +14,6 @@ pub(crate) use rustc_middle::ty::layout::{WIDE_PTR_ADDR, WIDE_PTR_EXTRA}; use rustc_middle::{bug, ty}; use rustc_session::config; pub(crate) use rustc_target::abi::call::*; -use rustc_target::abi::{self, HasDataLayout, Int, Size}; use rustc_target::spec::SanitizerSet; pub(crate) use rustc_target::spec::abi::Abi; use smallvec::SmallVec; diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 30d7ba4421b..dbf5298d64b 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -3,6 +3,8 @@ use std::ops::Deref; use std::{iter, ptr}; use libc::{c_char, c_uint}; +use rustc_abi as abi; +use rustc_abi::{Align, Size, WrappingRange}; use rustc_codegen_ssa::MemFlags; use rustc_codegen_ssa::common::{IntPredicate, RealPredicate, SynchronizationScope, TypeKind}; use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue}; @@ -20,7 +22,6 @@ use rustc_sanitizers::{cfi, kcfi}; use rustc_session::config::OptLevel; use rustc_span::Span; use rustc_target::abi::call::FnAbi; -use rustc_target::abi::{self, Align, Size, WrappingRange}; use rustc_target::spec::{HasTargetSpec, SanitizerSet, Target}; use smallvec::SmallVec; use tracing::{debug, instrument}; @@ -505,12 +506,12 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } match scalar.primitive() { - abi::Int(..) => { + abi::Primitive::Int(..) => { if !scalar.is_always_valid(bx) { bx.range_metadata(load, scalar.valid_range(bx)); } } - abi::Pointer(_) => { + abi::Primitive::Pointer(_) => { if !scalar.valid_range(bx).contains(0) { bx.nonnull_metadata(load); } @@ -521,7 +522,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } } } - abi::Float(_) => {} + abi::Primitive::Float(_) => {} } } diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs index 31d59905446..4ca19ab2f12 100644 --- a/compiler/rustc_codegen_llvm/src/common.rs +++ b/compiler/rustc_codegen_llvm/src/common.rs @@ -1,6 +1,9 @@ //! Code that is useful in various codegen modules. use libc::{c_char, c_uint}; +use rustc_abi as abi; +use rustc_abi::Primitive::Pointer; +use rustc_abi::{AddressSpace, HasDataLayout}; use rustc_ast::Mutability; use rustc_codegen_ssa::traits::*; use rustc_data_structures::stable_hasher::{Hash128, HashStable, StableHasher}; @@ -9,7 +12,6 @@ use rustc_middle::bug; use rustc_middle::mir::interpret::{ConstAllocation, GlobalAlloc, Scalar}; use rustc_middle::ty::TyCtxt; use rustc_session::cstore::DllImport; -use rustc_target::abi::{self, AddressSpace, HasDataLayout, Pointer}; use tracing::debug; use crate::consts::const_alloc_to_llvm; diff --git a/compiler/rustc_codegen_llvm/src/type_of.rs b/compiler/rustc_codegen_llvm/src/type_of.rs index 7071dd86ee0..1af666f818b 100644 --- a/compiler/rustc_codegen_llvm/src/type_of.rs +++ b/compiler/rustc_codegen_llvm/src/type_of.rs @@ -1,11 +1,12 @@ use std::fmt::Write; +use rustc_abi::Primitive::{Float, Int, Pointer}; +use rustc_abi::{Abi, Align, FieldsShape, Scalar, Size, Variants}; use rustc_codegen_ssa::traits::*; use rustc_middle::bug; use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths}; use rustc_middle::ty::{self, CoroutineArgsExt, Ty, TypeVisitableExt}; -use rustc_target::abi::{Abi, Align, FieldsShape, Float, Int, Pointer, Scalar, Size, Variants}; use tracing::debug; use crate::common::*; From b3beb4efc7cd2240a3ef96dd1e35cbd148ef97ef Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Tue, 8 Oct 2024 17:26:42 -0700 Subject: [PATCH 100/357] cg_clif: Factor out rustc_target::abi --- compiler/rustc_codegen_cranelift/src/discriminant.rs | 3 ++- compiler/rustc_codegen_cranelift/src/lib.rs | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_codegen_cranelift/src/discriminant.rs b/compiler/rustc_codegen_cranelift/src/discriminant.rs index e7ac084558a..d462dcd63a9 100644 --- a/compiler/rustc_codegen_cranelift/src/discriminant.rs +++ b/compiler/rustc_codegen_cranelift/src/discriminant.rs @@ -3,7 +3,8 @@ //! Adapted from //! () -use rustc_target::abi::{Int, TagEncoding, Variants}; +use rustc_abi::Primitive::Int; +use rustc_abi::{TagEncoding, Variants}; use crate::prelude::*; diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index f6b7981395a..b6f9ce8fc29 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/src/lib.rs @@ -15,6 +15,7 @@ extern crate jobserver; #[macro_use] extern crate rustc_middle; +extern crate rustc_abi; extern crate rustc_ast; extern crate rustc_codegen_ssa; extern crate rustc_data_structures; From d92aee556d92214f972ed91499e61474ad38aa9d Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Tue, 8 Oct 2024 17:27:02 -0700 Subject: [PATCH 101/357] cg_gcc: Factor out rustc_target::abi --- compiler/rustc_codegen_gcc/src/builder.rs | 7 ++++--- compiler/rustc_codegen_gcc/src/common.rs | 4 +++- compiler/rustc_codegen_gcc/src/lib.rs | 1 + compiler/rustc_codegen_gcc/src/type_of.rs | 8 ++++---- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs index acd53588831..b611f9ba8bc 100644 --- a/compiler/rustc_codegen_gcc/src/builder.rs +++ b/compiler/rustc_codegen_gcc/src/builder.rs @@ -7,6 +7,8 @@ use gccjit::{ BinaryOp, Block, ComparisonOp, Context, Function, LValue, Location, RValue, ToRValue, Type, UnaryOp, }; +use rustc_abi as abi; +use rustc_abi::{Align, HasDataLayout, Size, TargetDataLayout, WrappingRange}; use rustc_apfloat::{Float, Round, Status, ieee}; use rustc_codegen_ssa::MemFlags; use rustc_codegen_ssa::common::{ @@ -28,7 +30,6 @@ use rustc_middle::ty::{Instance, ParamEnv, Ty, TyCtxt}; use rustc_span::Span; use rustc_span::def_id::DefId; use rustc_target::abi::call::FnAbi; -use rustc_target::abi::{self, Align, HasDataLayout, Size, TargetDataLayout, WrappingRange}; use rustc_target::spec::{HasTargetSpec, HasWasmCAbiOpt, Target, WasmCAbi}; use crate::common::{SignType, TypeReflection, type_is_pointer}; @@ -998,12 +999,12 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { ) { let vr = scalar.valid_range(bx); match scalar.primitive() { - abi::Int(..) => { + abi::Primitive::Int(..) => { if !scalar.is_always_valid(bx) { bx.range_metadata(load, vr); } } - abi::Pointer(_) if vr.start < vr.end && !vr.contains(0) => { + abi::Primitive::Pointer(_) if vr.start < vr.end && !vr.contains(0) => { bx.nonnull_metadata(load); } _ => {} diff --git a/compiler/rustc_codegen_gcc/src/common.rs b/compiler/rustc_codegen_gcc/src/common.rs index 726b126e727..0d3e7083d56 100644 --- a/compiler/rustc_codegen_gcc/src/common.rs +++ b/compiler/rustc_codegen_gcc/src/common.rs @@ -1,11 +1,13 @@ use gccjit::{LValue, RValue, ToRValue, Type}; +use rustc_abi as abi; +use rustc_abi::HasDataLayout; +use rustc_abi::Primitive::Pointer; use rustc_codegen_ssa::traits::{ BaseTypeCodegenMethods, ConstCodegenMethods, MiscCodegenMethods, StaticCodegenMethods, }; use rustc_middle::mir::Mutability; use rustc_middle::mir::interpret::{ConstAllocation, GlobalAlloc, Scalar}; use rustc_middle::ty::layout::LayoutOf; -use rustc_target::abi::{self, HasDataLayout, Pointer}; use crate::consts::const_alloc_to_gcc; use crate::context::CodegenCx; diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs index a7a32e285d8..7486eefeb85 100644 --- a/compiler/rustc_codegen_gcc/src/lib.rs +++ b/compiler/rustc_codegen_gcc/src/lib.rs @@ -32,6 +32,7 @@ extern crate tempfile; extern crate tracing; // The rustc crates we need +extern crate rustc_abi; extern crate rustc_apfloat; extern crate rustc_ast; extern crate rustc_attr; diff --git a/compiler/rustc_codegen_gcc/src/type_of.rs b/compiler/rustc_codegen_gcc/src/type_of.rs index 5b0d862ae6d..183e9ddf8bf 100644 --- a/compiler/rustc_codegen_gcc/src/type_of.rs +++ b/compiler/rustc_codegen_gcc/src/type_of.rs @@ -1,6 +1,9 @@ use std::fmt::Write; use gccjit::{Struct, Type}; +use rustc_abi as abi; +use rustc_abi::Primitive::*; +use rustc_abi::{Abi, FieldsShape, Integer, PointeeInfo, Size, Variants}; use rustc_codegen_ssa::traits::{ BaseTypeCodegenMethods, DerivedTypeCodegenMethods, LayoutTypeCodegenMethods, }; @@ -8,11 +11,8 @@ use rustc_middle::bug; use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, CoroutineArgsExt, Ty, TypeVisitableExt}; +use rustc_target::abi::TyAbiInterface; use rustc_target::abi::call::{CastTarget, FnAbi, Reg}; -use rustc_target::abi::{ - self, Abi, FieldsShape, Float, Int, Integer, PointeeInfo, Pointer, Size, TyAbiInterface, - Variants, -}; use crate::abi::{FnAbiGcc, FnAbiGccExt, GccType}; use crate::context::CodegenCx; From 43e198a3ae23f469e1c87b099789af1bc025fe50 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Tue, 8 Oct 2024 17:32:52 -0700 Subject: [PATCH 102/357] compiler: Seal off the rustc_target::abi enum glob imports --- Cargo.lock | 6 ++++++ compiler/rustc_target/src/abi/mod.rs | 5 ++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 502920350d5..faca0619673 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3416,6 +3416,7 @@ dependencies = [ "measureme", "object 0.36.4", "rustc-demangle", + "rustc_abi", "rustc_ast", "rustc_attr", "rustc_codegen_ssa", @@ -3456,6 +3457,7 @@ dependencies = [ "object 0.36.4", "pathdiff", "regex", + "rustc_abi", "rustc_arena", "rustc_ast", "rustc_attr", @@ -3493,6 +3495,7 @@ name = "rustc_const_eval" version = "0.0.0" dependencies = [ "either", + "rustc_abi", "rustc_apfloat", "rustc_ast", "rustc_attr", @@ -3772,6 +3775,7 @@ name = "rustc_hir_typeck" version = "0.0.0" dependencies = [ "itertools", + "rustc_abi", "rustc_ast", "rustc_ast_ir", "rustc_attr", @@ -4027,6 +4031,7 @@ dependencies = [ "gsgdt", "polonius-engine", "rustc-rayon-core", + "rustc_abi", "rustc_apfloat", "rustc_arena", "rustc_ast", @@ -4522,6 +4527,7 @@ name = "rustc_ty_utils" version = "0.0.0" dependencies = [ "itertools", + "rustc_abi", "rustc_ast_ir", "rustc_data_structures", "rustc_errors", diff --git a/compiler/rustc_target/src/abi/mod.rs b/compiler/rustc_target/src/abi/mod.rs index fc92e755fea..b744d5ad4ed 100644 --- a/compiler/rustc_target/src/abi/mod.rs +++ b/compiler/rustc_target/src/abi/mod.rs @@ -1,9 +1,8 @@ use std::fmt; use std::ops::Deref; -pub use Float::*; -pub use Integer::*; -pub use Primitive::*; +use Float::*; +use Primitive::*; use rustc_data_structures::intern::Interned; use rustc_macros::HashStable_Generic; From af5a7045486404145544e3ec2ec2ec450b31e6f6 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Tue, 8 Oct 2024 18:31:44 -0700 Subject: [PATCH 103/357] Fix quotation marks around debug line in `src/ci/run.sh` Without this change, the markdown-style backticks are treated as a shell command substitution, which fails like so: /checkout/src/ci/run.sh: line 58: DISABLE_CI_RUSTC_IF_INCOMPATIBLE: command not found debug: configured. --- src/ci/run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ci/run.sh b/src/ci/run.sh index 1ce54f9ecb3..3962c354c10 100755 --- a/src/ci/run.sh +++ b/src/ci/run.sh @@ -55,7 +55,7 @@ fi # If runner uses an incompatible option and `FORCE_CI_RUSTC` is not defined, # switch to in-tree rustc. if [ "$FORCE_CI_RUSTC" == "" ]; then - echo "debug: `DISABLE_CI_RUSTC_IF_INCOMPATIBLE` configured." + echo 'debug: `DISABLE_CI_RUSTC_IF_INCOMPATIBLE` configured.' DISABLE_CI_RUSTC_IF_INCOMPATIBLE=1 fi From 6f854ce34303636647f2c6019e4abbf432e81cbb Mon Sep 17 00:00:00 2001 From: Frank Rehwinkel Date: Tue, 8 Oct 2024 21:35:46 -0400 Subject: [PATCH 104/357] epoll: test case showing too much clock sync --- .../pass-dep/libc/libc-epoll-clock-sync.rs | 104 ++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 src/tools/miri/tests/pass-dep/libc/libc-epoll-clock-sync.rs diff --git a/src/tools/miri/tests/pass-dep/libc/libc-epoll-clock-sync.rs b/src/tools/miri/tests/pass-dep/libc/libc-epoll-clock-sync.rs new file mode 100644 index 00000000000..56c2615b8a7 --- /dev/null +++ b/src/tools/miri/tests/pass-dep/libc/libc-epoll-clock-sync.rs @@ -0,0 +1,104 @@ +//@only-target: linux +// ensure single way to order the thread tests +//@compile-flags: -Zmiri-preemption-rate=0 + +use std::convert::TryInto; +use std::thread; +use std::thread::spawn; + +#[track_caller] +fn check_epoll_wait(epfd: i32, expected_notifications: &[(u32, u64)]) { + let epoll_event = libc::epoll_event { events: 0, u64: 0 }; + let mut array: [libc::epoll_event; N] = [epoll_event; N]; + let maxsize = N; + let array_ptr = array.as_mut_ptr(); + let res = unsafe { libc::epoll_wait(epfd, array_ptr, maxsize.try_into().unwrap(), 0) }; + if res < 0 { + panic!("epoll_wait failed: {}", std::io::Error::last_os_error()); + } + assert_eq!( + res, + expected_notifications.len().try_into().unwrap(), + "got wrong number of notifications" + ); + let slice = unsafe { std::slice::from_raw_parts(array_ptr, res.try_into().unwrap()) }; + for (return_event, expected_event) in slice.iter().zip(expected_notifications.iter()) { + let event = return_event.events; + let data = return_event.u64; + assert_eq!(event, expected_event.0, "got wrong events"); + assert_eq!(data, expected_event.1, "got wrong data"); + } +} + +fn common_setup() -> (i32, [i32; 2], [i32; 2]) { + // Create an epoll instance. + let epfd = unsafe { libc::epoll_create1(0) }; + assert_ne!(epfd, -1); + + // Create two socketpair instances. + let mut fds_a = [-1, -1]; + let res = unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds_a.as_mut_ptr()) }; + assert_eq!(res, 0); + + let mut fds_b = [-1, -1]; + let res = unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds_b.as_mut_ptr()) }; + assert_eq!(res, 0); + + // Register both pipe read ends. + let mut ev = libc::epoll_event { + events: (libc::EPOLLIN | libc::EPOLLET) as _, + u64: u64::try_from(fds_a[1]).unwrap(), + }; + let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fds_a[1], &mut ev) }; + assert_eq!(res, 0); + + let mut ev = libc::epoll_event { + events: (libc::EPOLLIN | libc::EPOLLET) as _, + u64: u64::try_from(fds_b[1]).unwrap(), + }; + let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fds_b[1], &mut ev) }; + assert_eq!(res, 0); + + (epfd, fds_a, fds_b) +} + +// Test that the clock sync that happens through an epoll_wait only synchronizes with the clock(s) +// that were reported. It is possible more events had become ready but the epoll_wait didn't +// provide room for them all. +// +// Well before the fix, this fails to report UB. +fn main() { + let (epfd, fds_a, fds_b) = common_setup(); + + static mut VAL_ONE: u8 = 40; // This one will be read soundly. + static mut VAL_TWO: u8 = 50; // This one will be read unsoundly. + let thread1 = spawn(move || { + unsafe { VAL_ONE = 41 }; + + let data = "abcde".as_bytes().as_ptr(); + let res = unsafe { libc::write(fds_a[0], data as *const libc::c_void, 5) }; + assert_eq!(res, 5); + + unsafe { VAL_TWO = 51 }; + + let res = unsafe { libc::write(fds_b[0], data as *const libc::c_void, 5) }; + assert_eq!(res, 5); + }); + thread::yield_now(); + + // With room for one event: check result from epoll_wait. + let expected_event = u32::try_from(libc::EPOLLIN).unwrap(); + let expected_value = u64::try_from(fds_a[1]).unwrap(); + check_epoll_wait::<1>(epfd, &[(expected_event, expected_value)]); + + #[allow(static_mut_refs)] + unsafe { + assert_eq!(VAL_ONE, 41) // This one is not UB + }; + #[allow(static_mut_refs)] + unsafe { + assert_eq!(VAL_TWO, 51) // This one should be UB but isn't (yet). + }; + + thread1.join().unwrap(); +} From f2d1edfea5689ac638904080ddb972c40e7acc8c Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Sat, 28 Sep 2024 01:46:03 -0400 Subject: [PATCH 105/357] Change a few `&Option` into `Option<&T>` --- library/std/src/sys/pal/sgx/net.rs | 14 +++++++------- .../std/src/sys/pal/unix/process/process_common.rs | 4 ++-- .../std/src/sys/pal/unix/process/process_unix.rs | 2 +- library/test/src/lib.rs | 11 ++++++----- library/test/src/test_result.rs | 8 ++++---- 5 files changed, 20 insertions(+), 19 deletions(-) diff --git a/library/std/src/sys/pal/sgx/net.rs b/library/std/src/sys/pal/sgx/net.rs index 44913ffe3a9..c966886d163 100644 --- a/library/std/src/sys/pal/sgx/net.rs +++ b/library/std/src/sys/pal/sgx/net.rs @@ -78,9 +78,8 @@ fn io_err_to_addr(result: io::Result<&SocketAddr>) -> io::Result { } } -fn addr_to_sockaddr(addr: &Option) -> io::Result { - addr.as_ref() - .ok_or(io::ErrorKind::AddrNotAvailable)? +fn addr_to_sockaddr(addr: Option<&str>) -> io::Result { + addr.ok_or(io::ErrorKind::AddrNotAvailable)? .to_socket_addrs() // unwrap OK: if an iterator is returned, we're guaranteed to get exactly one entry .map(|mut it| it.next().unwrap()) @@ -161,11 +160,11 @@ impl TcpStream { } pub fn peer_addr(&self) -> io::Result { - addr_to_sockaddr(&self.peer_addr) + addr_to_sockaddr(self.peer_addr.as_deref()) } pub fn socket_addr(&self) -> io::Result { - addr_to_sockaddr(&self.inner.local_addr) + addr_to_sockaddr(self.inner.local_addr.as_deref()) } pub fn shutdown(&self, _: Shutdown) -> io::Result<()> { @@ -255,13 +254,14 @@ impl TcpListener { } pub fn socket_addr(&self) -> io::Result { - addr_to_sockaddr(&self.inner.local_addr) + addr_to_sockaddr(self.inner.local_addr.as_deref()) } pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> { let (fd, local_addr, peer_addr) = usercalls::accept_stream(self.inner.inner.raw())?; let peer_addr = Some(peer_addr); - let ret_peer = addr_to_sockaddr(&peer_addr).unwrap_or_else(|_| ([0; 4], 0).into()); + let ret_peer = + addr_to_sockaddr(peer_addr.as_deref()).unwrap_or_else(|_| ([0; 4], 0).into()); Ok((TcpStream { inner: Socket::new(fd, local_addr), peer_addr }, ret_peer)) } diff --git a/library/std/src/sys/pal/unix/process/process_common.rs b/library/std/src/sys/pal/unix/process/process_common.rs index d9c41d43487..13290fed762 100644 --- a/library/std/src/sys/pal/unix/process/process_common.rs +++ b/library/std/src/sys/pal/unix/process/process_common.rs @@ -312,8 +312,8 @@ impl Command { } #[allow(dead_code)] - pub fn get_cwd(&self) -> &Option { - &self.cwd + pub fn get_cwd(&self) -> Option<&CStr> { + self.cwd.as_deref() } #[allow(dead_code)] pub fn get_uid(&self) -> Option { diff --git a/library/std/src/sys/pal/unix/process/process_unix.rs b/library/std/src/sys/pal/unix/process/process_unix.rs index 5d30f388da1..0fa6551772f 100644 --- a/library/std/src/sys/pal/unix/process/process_unix.rs +++ b/library/std/src/sys/pal/unix/process/process_unix.rs @@ -335,7 +335,7 @@ impl Command { cvt(libc::setuid(u as uid_t))?; } } - if let Some(ref cwd) = *self.get_cwd() { + if let Some(ref cwd) = self.get_cwd() { cvt(libc::chdir(cwd.as_ptr()))?; } diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs index 4b2c65cfdf5..30ccfe2af8d 100644 --- a/library/test/src/lib.rs +++ b/library/test/src/lib.rs @@ -650,8 +650,8 @@ fn run_test_in_process( io::set_output_capture(None); let test_result = match result { - Ok(()) => calc_result(&desc, Ok(()), &time_opts, &exec_time), - Err(e) => calc_result(&desc, Err(e.as_ref()), &time_opts, &exec_time), + Ok(()) => calc_result(&desc, Ok(()), time_opts.as_ref(), exec_time.as_ref()), + Err(e) => calc_result(&desc, Err(e.as_ref()), time_opts.as_ref(), exec_time.as_ref()), }; let stdout = data.lock().unwrap_or_else(|e| e.into_inner()).to_vec(); let message = CompletedTest::new(id, desc, test_result, exec_time, stdout); @@ -712,7 +712,8 @@ fn spawn_test_subprocess( formatters::write_stderr_delimiter(&mut test_output, &desc.name); test_output.extend_from_slice(&stderr); - let result = get_result_from_exit_code(&desc, status, &time_opts, &exec_time); + let result = + get_result_from_exit_code(&desc, status, time_opts.as_ref(), exec_time.as_ref()); (result, test_output, exec_time) })(); @@ -724,8 +725,8 @@ fn run_test_in_spawned_subprocess(desc: TestDesc, runnable_test: RunnableTest) - let builtin_panic_hook = panic::take_hook(); let record_result = Arc::new(move |panic_info: Option<&'_ PanicHookInfo<'_>>| { let test_result = match panic_info { - Some(info) => calc_result(&desc, Err(info.payload()), &None, &None), - None => calc_result(&desc, Ok(()), &None, &None), + Some(info) => calc_result(&desc, Err(info.payload()), None, None), + None => calc_result(&desc, Ok(()), None, None), }; // We don't support serializing TrFailedMsg, so just diff --git a/library/test/src/test_result.rs b/library/test/src/test_result.rs index c5f4b03bfc9..79fe07bc1ac 100644 --- a/library/test/src/test_result.rs +++ b/library/test/src/test_result.rs @@ -42,8 +42,8 @@ pub enum TestResult { pub fn calc_result<'a>( desc: &TestDesc, task_result: Result<(), &'a (dyn Any + 'static + Send)>, - time_opts: &Option, - exec_time: &Option, + time_opts: Option<&time::TestTimeOptions>, + exec_time: Option<&time::TestExecTime>, ) -> TestResult { let result = match (&desc.should_panic, task_result) { (&ShouldPanic::No, Ok(())) | (&ShouldPanic::Yes, Err(_)) => TestResult::TrOk, @@ -96,8 +96,8 @@ pub fn calc_result<'a>( pub fn get_result_from_exit_code( desc: &TestDesc, status: ExitStatus, - time_opts: &Option, - exec_time: &Option, + time_opts: Option<&time::TestTimeOptions>, + exec_time: Option<&time::TestExecTime>, ) -> TestResult { let result = match status.code() { Some(TR_OK) => TestResult::TrOk, From d2f93c97079a5c7e2b3fff6d3a63f862ce88bb3f Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Wed, 2 Oct 2024 14:25:14 -0400 Subject: [PATCH 106/357] Update library/std/src/sys/pal/unix/process/process_unix.rs Co-authored-by: Josh Stone --- library/std/src/sys/pal/unix/process/process_unix.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/sys/pal/unix/process/process_unix.rs b/library/std/src/sys/pal/unix/process/process_unix.rs index 0fa6551772f..4551d49e841 100644 --- a/library/std/src/sys/pal/unix/process/process_unix.rs +++ b/library/std/src/sys/pal/unix/process/process_unix.rs @@ -335,7 +335,7 @@ impl Command { cvt(libc::setuid(u as uid_t))?; } } - if let Some(ref cwd) = self.get_cwd() { + if let Some(cwd) = self.get_cwd() { cvt(libc::chdir(cwd.as_ptr()))?; } From 442d766cc12014a4a2c5b207ad41019b97fce03b Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Tue, 8 Oct 2024 20:21:27 -0400 Subject: [PATCH 107/357] fix ref in process_vxworks.rs --- library/std/src/sys/pal/unix/process/process_vxworks.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/sys/pal/unix/process/process_vxworks.rs b/library/std/src/sys/pal/unix/process/process_vxworks.rs index 2d9a304c495..6add0850a70 100644 --- a/library/std/src/sys/pal/unix/process/process_vxworks.rs +++ b/library/std/src/sys/pal/unix/process/process_vxworks.rs @@ -57,7 +57,7 @@ impl Command { t!(cvt_r(|| libc::dup2(fd, libc::STDERR_FILENO))); } - if let Some(ref cwd) = *self.get_cwd() { + if let Some(cwd) = *self.get_cwd() { t!(cvt(libc::chdir(cwd.as_ptr()))); } From a278f157241e296ced392a81be5be7e8f608bd3c Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Tue, 8 Oct 2024 22:17:16 -0400 Subject: [PATCH 108/357] Update library/std/src/sys/pal/unix/process/process_vxworks.rs Co-authored-by: Josh Stone --- library/std/src/sys/pal/unix/process/process_vxworks.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/sys/pal/unix/process/process_vxworks.rs b/library/std/src/sys/pal/unix/process/process_vxworks.rs index 6add0850a70..38daf6af918 100644 --- a/library/std/src/sys/pal/unix/process/process_vxworks.rs +++ b/library/std/src/sys/pal/unix/process/process_vxworks.rs @@ -57,7 +57,7 @@ impl Command { t!(cvt_r(|| libc::dup2(fd, libc::STDERR_FILENO))); } - if let Some(cwd) = *self.get_cwd() { + if let Some(cwd) = self.get_cwd() { t!(cvt(libc::chdir(cwd.as_ptr()))); } From 4474018500b8a18edc5fc26003740287779bc8ac Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Wed, 9 Oct 2024 07:45:48 +0300 Subject: [PATCH 109/357] fix `ci_rustc_if_unchanged_logic` test Signed-off-by: onur-ozkan --- src/bootstrap/src/core/builder/tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index 4a96ecf1421..ab36193f8b6 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -239,7 +239,7 @@ fn ci_rustc_if_unchanged_logic() { builder.run_step_descriptions(&Builder::get_step_descriptions(config.cmd.kind()), &[]); let compiler_path = build.src.join("compiler"); - let library_path = build.src.join("compiler"); + let library_path = build.src.join("library"); let commit = get_closest_merge_commit(Some(&builder.config.src), &builder.config.git_config(), &[ From fe87487b367e31ec76df3f3124e5d70a0f60a20d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= Date: Wed, 9 Oct 2024 04:49:27 +0000 Subject: [PATCH 110/357] Ignore broken-pipe-no-ice on apple for now --- tests/run-make/broken-pipe-no-ice/rmake.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/run-make/broken-pipe-no-ice/rmake.rs b/tests/run-make/broken-pipe-no-ice/rmake.rs index d1db0bc7368..378c3289cb7 100644 --- a/tests/run-make/broken-pipe-no-ice/rmake.rs +++ b/tests/run-make/broken-pipe-no-ice/rmake.rs @@ -5,6 +5,12 @@ //@ ignore-cross-compile (needs to run test binary) +//@ ignore-apple +// FIXME(#131436): on macOS rustc is still reporting the std broken pipe io error panick but it +// doesn't fail with 101 exit status (it terminates with a wait status of SIGPIPE). It doesn't say +// Internal Compiler Error strangely, but it doesn't even go through normal diagnostic infra. Very +// strange. + #![feature(anonymous_pipe)] use std::io::Read; From 461b49d96dd012dd13e172a166b7dad9ed7543d9 Mon Sep 17 00:00:00 2001 From: ultrabear Date: Wed, 18 Sep 2024 19:16:28 -0700 Subject: [PATCH 111/357] stabilize `{slice,array}::from_mut` --- library/core/src/array/mod.rs | 3 ++- library/core/src/lib.rs | 2 -- library/core/src/slice/raw.rs | 3 ++- library/core/tests/lib.rs | 2 -- 4 files changed, 4 insertions(+), 6 deletions(-) diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 24c42bc85dd..a95046162d2 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -146,7 +146,8 @@ pub const fn from_ref(s: &T) -> &[T; 1] { /// Converts a mutable reference to `T` into a mutable reference to an array of length 1 (without copying). #[stable(feature = "array_from_ref", since = "1.53.0")] -#[rustc_const_unstable(feature = "const_array_from_ref", issue = "90206")] +#[rustc_const_stable(feature = "const_array_from_ref", since = "CURRENT_RUSTC_VERSION")] +#[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn from_mut(s: &mut T) -> &mut [T; 1] { // SAFETY: Converting `&mut T` to `&mut [T; 1]` is sound. unsafe { &mut *(s as *mut T).cast::<[T; 1]>() } diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index e323e88f261..96ab5755328 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -114,7 +114,6 @@ #![feature(const_align_offset)] #![feature(const_alloc_layout)] #![feature(const_arguments_as_str)] -#![feature(const_array_from_ref)] #![feature(const_array_into_iter_constructors)] #![feature(const_bigint_helper_methods)] #![feature(const_black_box)] @@ -145,7 +144,6 @@ #![feature(const_replace)] #![feature(const_size_of_val)] #![feature(const_size_of_val_raw)] -#![feature(const_slice_from_ref)] #![feature(const_strict_overflow_ops)] #![feature(const_swap)] #![feature(const_try)] diff --git a/library/core/src/slice/raw.rs b/library/core/src/slice/raw.rs index 84e916b9a84..998f9360332 100644 --- a/library/core/src/slice/raw.rs +++ b/library/core/src/slice/raw.rs @@ -204,7 +204,8 @@ pub const fn from_ref(s: &T) -> &[T] { /// Converts a reference to T into a slice of length 1 (without copying). #[stable(feature = "from_ref", since = "1.28.0")] -#[rustc_const_unstable(feature = "const_slice_from_ref", issue = "90206")] +#[rustc_const_stable(feature = "const_slice_from_ref", since = "CURRENT_RUSTC_VERSION")] +#[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[must_use] pub const fn from_mut(s: &mut T) -> &mut [T] { array::from_mut(s) diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 196e91ee3e9..0d4ec96f842 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -16,7 +16,6 @@ #![feature(clone_to_uninit)] #![feature(const_align_of_val_raw)] #![feature(const_align_offset)] -#![feature(const_array_from_ref)] #![feature(const_black_box)] #![feature(const_hash)] #![feature(const_heap)] @@ -31,7 +30,6 @@ #![feature(const_pointer_is_aligned)] #![feature(const_ptr_write)] #![feature(const_result)] -#![feature(const_slice_from_ref)] #![feature(const_three_way_compare)] #![feature(const_trait_impl)] #![feature(core_intrinsics)] From 622d5898c2d825028ff2703fa46a140c175d5fbf Mon Sep 17 00:00:00 2001 From: Zalathar Date: Wed, 9 Oct 2024 13:51:26 +1100 Subject: [PATCH 112/357] Rename directive `needs-profiler-support` to `needs-profiler-runtime` --- src/tools/compiletest/src/command-list.rs | 2 +- src/tools/compiletest/src/common.rs | 2 +- src/tools/compiletest/src/header.rs | 2 +- src/tools/compiletest/src/header/needs.rs | 4 ++-- src/tools/compiletest/src/header/tests.rs | 4 ++-- tests/run-make/cross-lang-lto-pgo-smoketest-clang/rmake.rs | 2 +- tests/run-make/optimization-remarks-dir-pgo/rmake.rs | 2 +- tests/run-make/pgo-branch-weights/rmake.rs | 2 +- tests/run-make/pgo-gen-lto/rmake.rs | 2 +- tests/run-make/pgo-gen/rmake.rs | 2 +- tests/run-make/pgo-indirect-call-promotion/rmake.rs | 2 +- tests/run-make/pgo-use/rmake.rs | 2 +- tests/run-make/profile/rmake.rs | 2 +- tests/run-make/track-pgo-dep-info/rmake.rs | 2 +- tests/ui/coverage-attr/bad-attr-ice.rs | 2 +- tests/ui/issues/issue-85461.rs | 2 +- 16 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/tools/compiletest/src/command-list.rs b/src/tools/compiletest/src/command-list.rs index b34c276ab19..53db55d0c10 100644 --- a/src/tools/compiletest/src/command-list.rs +++ b/src/tools/compiletest/src/command-list.rs @@ -129,7 +129,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "needs-git-hash", "needs-llvm-components", "needs-llvm-zstd", - "needs-profiler-support", + "needs-profiler-runtime", "needs-relocation-model-pic", "needs-run-enabled", "needs-rust-lld", diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 17ec6ea4301..37f8a3df82e 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -385,7 +385,7 @@ pub struct Config { pub git_merge_commit_email: String, /// True if the profiler runtime is enabled for this target. - /// Used by the "needs-profiler-support" header in test files. + /// Used by the "needs-profiler-runtime" directive in test files. pub profiler_support: bool, } diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index a6830a6aa17..bd0ed6321bc 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -851,7 +851,7 @@ fn iter_header( // FIXME(jieyouxu): I feel like there's a better way to do this, leaving for later. if mode == Mode::CoverageRun { let extra_directives: &[&str] = &[ - "needs-profiler-support", + "needs-profiler-runtime", // FIXME(pietroalbini): this test currently does not work on cross-compiled targets // because remote-test is not capable of sending back the *.profraw files generated by // the LLVM instrumentation. diff --git a/src/tools/compiletest/src/header/needs.rs b/src/tools/compiletest/src/header/needs.rs index f5dd722ed37..ca7600d4dcb 100644 --- a/src/tools/compiletest/src/header/needs.rs +++ b/src/tools/compiletest/src/header/needs.rs @@ -100,9 +100,9 @@ pub(super) fn handle_needs( ignore_reason: "ignored on targets without unwinding support", }, Need { - name: "needs-profiler-support", + name: "needs-profiler-runtime", condition: cache.profiler_support, - ignore_reason: "ignored when profiler support is disabled", + ignore_reason: "ignored when the profiler runtime is not available", }, Need { name: "needs-force-clang-based-tests", diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs index 18e26635ac0..9b1294ad5fe 100644 --- a/src/tools/compiletest/src/header/tests.rs +++ b/src/tools/compiletest/src/header/tests.rs @@ -370,10 +370,10 @@ fn sanitizers() { #[test] fn profiler_support() { let config: Config = cfg().profiler_support(false).build(); - assert!(check_ignore(&config, "//@ needs-profiler-support")); + assert!(check_ignore(&config, "//@ needs-profiler-runtime")); let config: Config = cfg().profiler_support(true).build(); - assert!(!check_ignore(&config, "//@ needs-profiler-support")); + assert!(!check_ignore(&config, "//@ needs-profiler-runtime")); } #[test] diff --git a/tests/run-make/cross-lang-lto-pgo-smoketest-clang/rmake.rs b/tests/run-make/cross-lang-lto-pgo-smoketest-clang/rmake.rs index 03c9af4bb89..50790e18cec 100644 --- a/tests/run-make/cross-lang-lto-pgo-smoketest-clang/rmake.rs +++ b/tests/run-make/cross-lang-lto-pgo-smoketest-clang/rmake.rs @@ -9,7 +9,7 @@ // RUSTBUILD_FORCE_CLANG_BASED_TESTS and only runs tests which contain "clang" in their // name. -//@ needs-profiler-support +//@ needs-profiler-runtime // FIXME(Oneirical): Except that due to the reliance on llvm-profdata, this test // never runs, because `x86_64-gnu-debug` does not have the `profiler_builtins` crate. diff --git a/tests/run-make/optimization-remarks-dir-pgo/rmake.rs b/tests/run-make/optimization-remarks-dir-pgo/rmake.rs index 228c43cc5f1..471ce89f188 100644 --- a/tests/run-make/optimization-remarks-dir-pgo/rmake.rs +++ b/tests/run-make/optimization-remarks-dir-pgo/rmake.rs @@ -4,7 +4,7 @@ // the output remark files. // See https://github.com/rust-lang/rust/pull/114439 -//@ needs-profiler-support +//@ needs-profiler-runtime //@ ignore-cross-compile use run_make_support::{ diff --git a/tests/run-make/pgo-branch-weights/rmake.rs b/tests/run-make/pgo-branch-weights/rmake.rs index 105c2fafc5a..1893248e307 100644 --- a/tests/run-make/pgo-branch-weights/rmake.rs +++ b/tests/run-make/pgo-branch-weights/rmake.rs @@ -7,7 +7,7 @@ // If the test passes, the expected function call count was added to the use-phase LLVM-IR. // See https://github.com/rust-lang/rust/pull/66631 -//@ needs-profiler-support +//@ needs-profiler-runtime //@ ignore-cross-compile use std::path::Path; diff --git a/tests/run-make/pgo-gen-lto/rmake.rs b/tests/run-make/pgo-gen-lto/rmake.rs index 53d1623bf58..4f7ae9fb24c 100644 --- a/tests/run-make/pgo-gen-lto/rmake.rs +++ b/tests/run-make/pgo-gen-lto/rmake.rs @@ -2,7 +2,7 @@ // should be generated. // See https://github.com/rust-lang/rust/pull/48346 -//@ needs-profiler-support +//@ needs-profiler-runtime // Reason: this exercises LTO profiling //@ ignore-cross-compile // Reason: the compiled binary is executed diff --git a/tests/run-make/pgo-gen/rmake.rs b/tests/run-make/pgo-gen/rmake.rs index ad2f6388e8f..5cd5a4583ed 100644 --- a/tests/run-make/pgo-gen/rmake.rs +++ b/tests/run-make/pgo-gen/rmake.rs @@ -3,7 +3,7 @@ // optimizes code. This test checks that these files are generated. // See https://github.com/rust-lang/rust/pull/48346 -//@ needs-profiler-support +//@ needs-profiler-runtime //@ ignore-cross-compile use run_make_support::{cwd, has_extension, has_prefix, run, rustc, shallow_find_files}; diff --git a/tests/run-make/pgo-indirect-call-promotion/rmake.rs b/tests/run-make/pgo-indirect-call-promotion/rmake.rs index 28232eb2566..ce9754f13b9 100644 --- a/tests/run-make/pgo-indirect-call-promotion/rmake.rs +++ b/tests/run-make/pgo-indirect-call-promotion/rmake.rs @@ -5,7 +5,7 @@ // whether it can make a direct call instead of the indirect call. // See https://github.com/rust-lang/rust/pull/66631 -//@ needs-profiler-support +//@ needs-profiler-runtime // Reason: llvm_profdata is used //@ ignore-cross-compile // Reason: the compiled binary is executed diff --git a/tests/run-make/pgo-use/rmake.rs b/tests/run-make/pgo-use/rmake.rs index 276af9ea263..c09a82353b9 100644 --- a/tests/run-make/pgo-use/rmake.rs +++ b/tests/run-make/pgo-use/rmake.rs @@ -5,7 +5,7 @@ // be marked as cold. // See https://github.com/rust-lang/rust/pull/60262 -//@ needs-profiler-support +//@ needs-profiler-runtime //@ ignore-cross-compile use run_make_support::{ diff --git a/tests/run-make/profile/rmake.rs b/tests/run-make/profile/rmake.rs index 4287ab0a931..58a1b53c040 100644 --- a/tests/run-make/profile/rmake.rs +++ b/tests/run-make/profile/rmake.rs @@ -6,7 +6,7 @@ // See https://github.com/rust-lang/rust/pull/42433 //@ ignore-cross-compile -//@ needs-profiler-support +//@ needs-profiler-runtime use run_make_support::{path, run, rustc}; diff --git a/tests/run-make/track-pgo-dep-info/rmake.rs b/tests/run-make/track-pgo-dep-info/rmake.rs index 84f4e0bd383..5869dbf9c24 100644 --- a/tests/run-make/track-pgo-dep-info/rmake.rs +++ b/tests/run-make/track-pgo-dep-info/rmake.rs @@ -6,7 +6,7 @@ //@ ignore-cross-compile // Reason: the binary is executed -//@ needs-profiler-support +//@ needs-profiler-runtime use run_make_support::{llvm_profdata, rfs, run, rustc}; diff --git a/tests/ui/coverage-attr/bad-attr-ice.rs b/tests/ui/coverage-attr/bad-attr-ice.rs index ae4d27d65eb..55c86d260d4 100644 --- a/tests/ui/coverage-attr/bad-attr-ice.rs +++ b/tests/ui/coverage-attr/bad-attr-ice.rs @@ -1,7 +1,7 @@ #![cfg_attr(feat, feature(coverage_attribute))] //@ revisions: feat nofeat //@ compile-flags: -Cinstrument-coverage -//@ needs-profiler-support +//@ needs-profiler-runtime // Malformed `#[coverage(..)]` attributes should not cause an ICE when built // with `-Cinstrument-coverage`. diff --git a/tests/ui/issues/issue-85461.rs b/tests/ui/issues/issue-85461.rs index 7fe7a4aa579..72538081ccb 100644 --- a/tests/ui/issues/issue-85461.rs +++ b/tests/ui/issues/issue-85461.rs @@ -1,6 +1,6 @@ //@ compile-flags: -Cinstrument-coverage -Ccodegen-units=4 --crate-type dylib -Copt-level=0 //@ build-pass -//@ needs-profiler-support +//@ needs-profiler-runtime //@ needs-dynamic-linking // Regression test for #85461 where MSVC sometimes fails to link instrument-coverage binaries From 8320a0116b66b6148b03ca280123c54d3c9ee218 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Wed, 9 Oct 2024 14:03:10 +1100 Subject: [PATCH 113/357] Rename `profiler_support` to `profiler_runtime` throughout compiletest --- src/bootstrap/src/core/build_steps/test.rs | 2 +- src/tools/compiletest/src/common.rs | 2 +- src/tools/compiletest/src/header/needs.rs | 6 +++--- src/tools/compiletest/src/header/tests.rs | 22 +++++++++++----------- src/tools/compiletest/src/lib.rs | 4 ++-- src/tools/compiletest/src/main.rs | 2 +- 6 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 7a49b68b91e..0dd3d0b3bd1 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -2082,7 +2082,7 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the } if builder.config.profiler_enabled(target) { - cmd.arg("--profiler-support"); + cmd.arg("--profiler-runtime"); } cmd.env("RUST_TEST_TMPDIR", builder.tempdir()); diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 37f8a3df82e..a5418ad8384 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -386,7 +386,7 @@ pub struct Config { /// True if the profiler runtime is enabled for this target. /// Used by the "needs-profiler-runtime" directive in test files. - pub profiler_support: bool, + pub profiler_runtime: bool, } impl Config { diff --git a/src/tools/compiletest/src/header/needs.rs b/src/tools/compiletest/src/header/needs.rs index ca7600d4dcb..c304cb86015 100644 --- a/src/tools/compiletest/src/header/needs.rs +++ b/src/tools/compiletest/src/header/needs.rs @@ -101,7 +101,7 @@ pub(super) fn handle_needs( }, Need { name: "needs-profiler-runtime", - condition: cache.profiler_support, + condition: cache.profiler_runtime, ignore_reason: "ignored when the profiler runtime is not available", }, Need { @@ -220,7 +220,7 @@ pub(super) struct CachedNeedsConditions { sanitizer_memtag: bool, sanitizer_shadow_call_stack: bool, sanitizer_safestack: bool, - profiler_support: bool, + profiler_runtime: bool, xray: bool, rust_lld: bool, dlltool: bool, @@ -247,7 +247,7 @@ impl CachedNeedsConditions { sanitizer_memtag: sanitizers.contains(&Sanitizer::Memtag), sanitizer_shadow_call_stack: sanitizers.contains(&Sanitizer::ShadowCallStack), sanitizer_safestack: sanitizers.contains(&Sanitizer::Safestack), - profiler_support: config.profiler_support, + profiler_runtime: config.profiler_runtime, xray: config.target_cfg().xray, // For tests using the `needs-rust-lld` directive (e.g. for `-Clink-self-contained=+linker`), diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs index 9b1294ad5fe..10ec2a1806f 100644 --- a/src/tools/compiletest/src/header/tests.rs +++ b/src/tools/compiletest/src/header/tests.rs @@ -69,7 +69,7 @@ struct ConfigBuilder { llvm_version: Option, git_hash: bool, system_llvm: bool, - profiler_support: bool, + profiler_runtime: bool, } impl ConfigBuilder { @@ -113,8 +113,8 @@ impl ConfigBuilder { self } - fn profiler_support(&mut self, s: bool) -> &mut Self { - self.profiler_support = s; + fn profiler_runtime(&mut self, is_available: bool) -> &mut Self { + self.profiler_runtime = is_available; self } @@ -162,8 +162,8 @@ impl ConfigBuilder { if self.system_llvm { args.push("--system-llvm".to_owned()); } - if self.profiler_support { - args.push("--profiler-support".to_owned()); + if self.profiler_runtime { + args.push("--profiler-runtime".to_owned()); } args.push("--rustc-path".to_string()); @@ -368,11 +368,11 @@ fn sanitizers() { } #[test] -fn profiler_support() { - let config: Config = cfg().profiler_support(false).build(); +fn profiler_runtime() { + let config: Config = cfg().profiler_runtime(false).build(); assert!(check_ignore(&config, "//@ needs-profiler-runtime")); - let config: Config = cfg().profiler_support(true).build(); + let config: Config = cfg().profiler_runtime(true).build(); assert!(!check_ignore(&config, "//@ needs-profiler-runtime")); } @@ -573,12 +573,12 @@ fn families() { #[test] fn ignore_coverage() { - // Indicate profiler support so that "coverage-run" tests aren't skipped. - let config = cfg().mode("coverage-map").profiler_support(true).build(); + // Indicate profiler runtime availability so that "coverage-run" tests aren't skipped. + let config = cfg().mode("coverage-map").profiler_runtime(true).build(); assert!(check_ignore(&config, "//@ ignore-coverage-map")); assert!(!check_ignore(&config, "//@ ignore-coverage-run")); - let config = cfg().mode("coverage-run").profiler_support(true).build(); + let config = cfg().mode("coverage-run").profiler_runtime(true).build(); assert!(!check_ignore(&config, "//@ ignore-coverage-map")); assert!(check_ignore(&config, "//@ ignore-coverage-run")); } diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index d9f64cddf5d..98375a21b04 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -153,7 +153,7 @@ pub fn parse_config(args: Vec) -> Config { .optflag("", "force-rerun", "rerun tests even if the inputs are unchanged") .optflag("", "only-modified", "only run tests that result been modified") .optflag("", "nocapture", "") - .optflag("", "profiler-support", "is the profiler runtime enabled for this target") + .optflag("", "profiler-runtime", "is the profiler runtime enabled for this target") .optflag("h", "help", "show this message") .reqopt("", "channel", "current Rust channel", "CHANNEL") .optflag( @@ -355,7 +355,7 @@ pub fn parse_config(args: Vec) -> Config { nightly_branch: matches.opt_str("nightly-branch").unwrap(), git_merge_commit_email: matches.opt_str("git-merge-commit-email").unwrap(), - profiler_support: matches.opt_present("profiler-support"), + profiler_runtime: matches.opt_present("profiler-runtime"), } } diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index 9f3eef3776d..b0f87593f95 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -22,7 +22,7 @@ fn main() { eprintln!("warning: `tidy` is not installed; diffs will not be generated"); } - if !config.profiler_support && config.mode == Mode::CoverageRun { + if !config.profiler_runtime && config.mode == Mode::CoverageRun { let actioned = if config.bless { "blessed" } else { "checked" }; eprintln!( r#" From 7a0e8bd1fd9998765ac99a640566c57eeda9882e Mon Sep 17 00:00:00 2001 From: Zalathar Date: Wed, 9 Oct 2024 14:08:13 +1100 Subject: [PATCH 114/357] No need to cache the `profiler_runtime` flag This cache struct entry was a relic from when profiler availability was communicated via an environment variable rather than a command-line flag. --- src/tools/compiletest/src/header/needs.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/tools/compiletest/src/header/needs.rs b/src/tools/compiletest/src/header/needs.rs index c304cb86015..a744fb61b9c 100644 --- a/src/tools/compiletest/src/header/needs.rs +++ b/src/tools/compiletest/src/header/needs.rs @@ -101,7 +101,7 @@ pub(super) fn handle_needs( }, Need { name: "needs-profiler-runtime", - condition: cache.profiler_runtime, + condition: config.profiler_runtime, ignore_reason: "ignored when the profiler runtime is not available", }, Need { @@ -220,7 +220,6 @@ pub(super) struct CachedNeedsConditions { sanitizer_memtag: bool, sanitizer_shadow_call_stack: bool, sanitizer_safestack: bool, - profiler_runtime: bool, xray: bool, rust_lld: bool, dlltool: bool, @@ -247,7 +246,6 @@ impl CachedNeedsConditions { sanitizer_memtag: sanitizers.contains(&Sanitizer::Memtag), sanitizer_shadow_call_stack: sanitizers.contains(&Sanitizer::ShadowCallStack), sanitizer_safestack: sanitizers.contains(&Sanitizer::Safestack), - profiler_runtime: config.profiler_runtime, xray: config.target_cfg().xray, // For tests using the `needs-rust-lld` directive (e.g. for `-Clink-self-contained=+linker`), From becf664e4930ce59fb01905e4c6af38c2df5382e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= <39484203+jieyouxu@users.noreply.github.com> Date: Wed, 9 Oct 2024 18:52:28 +0800 Subject: [PATCH 115/357] Match std RUSTFLAGS for host and target for `mir-opt` test --- src/bootstrap/src/core/build_steps/test.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 7a49b68b91e..5bf4f19b3c4 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -1697,7 +1697,11 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the builder.ensure(TestHelpers { target: compiler.host }); // ensure that `libproc_macro` is available on the host. - builder.ensure(compile::Std::new(compiler, compiler.host)); + if suite == "mir-opt" { + builder.ensure(compile::Std::new_for_mir_opt_tests(compiler, compiler.host)); + } else { + builder.ensure(compile::Std::new(compiler, compiler.host)); + } // As well as the target if suite != "mir-opt" { From f90c97c915f69369e167d4d0eeff8ac914ebb764 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 9 Oct 2024 14:20:02 +0200 Subject: [PATCH 116/357] explain the review bot use --- src/tools/miri/CONTRIBUTING.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/tools/miri/CONTRIBUTING.md b/src/tools/miri/CONTRIBUTING.md index 7a32962886c..d0bcf68eacb 100644 --- a/src/tools/miri/CONTRIBUTING.md +++ b/src/tools/miri/CONTRIBUTING.md @@ -45,6 +45,14 @@ process for such contributions: This process is largely informal, and its primary goal is to more clearly communicate expectations. Please get in touch with us if you have any questions! +### Managing the review state + +Most PRs bounce back and forth between the reviewer and the author several times, so it is good to +keep track of who is expected to take the next step. We are using the `S-waiting-for-review` and +`S-waiting-for-author` labels for that. If a reviewer asked you to do some changes and you think +they are all taken care of, post a comment saying `@rustbot ready` to mark a PR as ready for the +next round of review. + ## Preparing the build environment Miri heavily relies on internal and unstable rustc interfaces to execute MIR, From 01e248ff974e310be5fb88d374cbed64aa5c4a25 Mon Sep 17 00:00:00 2001 From: Nicola Krumschmidt Date: Wed, 9 Oct 2024 14:39:28 +0200 Subject: [PATCH 117/357] Decouple WASIp2 sockets from WasiFd --- library/std/src/os/wasi/mod.rs | 2 + library/std/src/sys/pal/wasip2/net.rs | 74 ++++++++++++++++++++------- 2 files changed, 58 insertions(+), 18 deletions(-) diff --git a/library/std/src/os/wasi/mod.rs b/library/std/src/os/wasi/mod.rs index 33b50c9e53b..2ee6aa46600 100644 --- a/library/std/src/os/wasi/mod.rs +++ b/library/std/src/os/wasi/mod.rs @@ -36,6 +36,8 @@ pub mod ffi; pub mod fs; pub mod io; + +#[cfg(all(target_os = "wasi", target_env = "p1"))] pub mod net; /// A prelude for conveniently writing platform-specific code. diff --git a/library/std/src/sys/pal/wasip2/net.rs b/library/std/src/sys/pal/wasip2/net.rs index c40eb229ba9..06e623df843 100644 --- a/library/std/src/sys/pal/wasip2/net.rs +++ b/library/std/src/sys/pal/wasip2/net.rs @@ -2,13 +2,12 @@ use libc::{c_int, c_void, size_t}; -use super::fd::WasiFd; use crate::ffi::CStr; use crate::io::{self, BorrowedBuf, BorrowedCursor, IoSlice, IoSliceMut}; use crate::net::{Shutdown, SocketAddr}; -use crate::os::wasi::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd}; +use crate::os::wasi::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}; use crate::sys::unsupported; -use crate::sys_common::net::{TcpListener, getsockopt, setsockopt, sockaddr_to_addr}; +use crate::sys_common::net::{getsockopt, setsockopt, sockaddr_to_addr}; use crate::sys_common::{AsInner, FromInner, IntoInner}; use crate::time::{Duration, Instant}; use crate::{cmp, mem, str}; @@ -71,7 +70,9 @@ pub fn cvt_gai(err: c_int) -> io::Result<()> { pub fn init() {} -pub struct Socket(WasiFd); +pub struct WasiSocket(OwnedFd); + +pub struct Socket(WasiSocket); impl Socket { pub fn new(addr: &SocketAddr, ty: c_int) -> io::Result { @@ -327,22 +328,66 @@ impl Socket { } } -impl AsInner for Socket { +impl AsInner for WasiSocket { #[inline] - fn as_inner(&self) -> &WasiFd { + fn as_inner(&self) -> &OwnedFd { &self.0 } } -impl IntoInner for Socket { - fn into_inner(self) -> WasiFd { +impl IntoInner for WasiSocket { + fn into_inner(self) -> OwnedFd { self.0 } } -impl FromInner for Socket { - fn from_inner(inner: WasiFd) -> Socket { - Socket(inner) +impl FromInner for WasiSocket { + fn from_inner(owned_fd: OwnedFd) -> Self { + Self(owned_fd) + } +} + +impl AsFd for WasiSocket { + fn as_fd(&self) -> BorrowedFd<'_> { + self.0.as_fd() + } +} + +impl AsRawFd for WasiSocket { + #[inline] + fn as_raw_fd(&self) -> RawFd { + self.0.as_raw_fd() + } +} + +impl IntoRawFd for WasiSocket { + fn into_raw_fd(self) -> RawFd { + self.0.into_raw_fd() + } +} + +impl FromRawFd for WasiSocket { + unsafe fn from_raw_fd(raw_fd: RawFd) -> Self { + unsafe { Self(FromRawFd::from_raw_fd(raw_fd)) } + } +} + +impl AsInner for Socket { + #[inline] + fn as_inner(&self) -> &WasiSocket { + &self.0 + } +} + +impl IntoInner for Socket { + fn into_inner(self) -> WasiSocket { + self.0 + } +} + +impl FromInner for Socket { + fn from_inner(sock: WasiSocket) -> Socket { + Socket(sock) } } @@ -370,10 +415,3 @@ impl FromRawFd for Socket { unsafe { Self(FromRawFd::from_raw_fd(raw_fd)) } } } - -impl AsInner for TcpListener { - #[inline] - fn as_inner(&self) -> &Socket { - &self.socket() - } -} From de60931645a1baf5edddd9f0c9027c0e494b46fb Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 9 Oct 2024 06:01:25 -0700 Subject: [PATCH 118/357] Add "reference" as a known compiletest header This adds the "reference" compiletest header so that the Rust reference can add annotations to the test suite in order to link tests to individual rules in the reference. Tooling in the reference repo will be responsible for collecting these annotations and linking to the tests. More details are in MCP 783: https://github.com/rust-lang/compiler-team/issues/783 --- src/tools/compiletest/src/command-list.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tools/compiletest/src/command-list.rs b/src/tools/compiletest/src/command-list.rs index b34c276ab19..8349c3085cc 100644 --- a/src/tools/compiletest/src/command-list.rs +++ b/src/tools/compiletest/src/command-list.rs @@ -208,6 +208,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "pretty-compare-only", "pretty-expanded", "pretty-mode", + "reference", "regex-error-pattern", "remap-src-base", "revisions", From 6774856e0c81f6cbedd772d295a21005d04a9224 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Wed, 9 Oct 2024 15:34:45 +0200 Subject: [PATCH 119/357] add more crash tests --- tests/crashes/130956.rs | 37 ++++++++++++++++++++++++++++++++++++ tests/crashes/130967.rs | 13 +++++++++++++ tests/crashes/131046.rs | 15 +++++++++++++++ tests/crashes/131048.rs | 7 +++++++ tests/crashes/131050.rs | 27 ++++++++++++++++++++++++++ tests/crashes/131052.rs | 8 ++++++++ tests/crashes/131101.rs | 12 ++++++++++++ tests/crashes/131102.rs | 4 ++++ tests/crashes/131103.rs | 6 ++++++ tests/crashes/131190.rs | 19 +++++++++++++++++++ tests/crashes/131227.rs | 16 ++++++++++++++++ tests/crashes/131292.rs | 7 +++++++ tests/crashes/131294-2.rs | 25 ++++++++++++++++++++++++ tests/crashes/131294.rs | 16 ++++++++++++++++ tests/crashes/131295.rs | 9 +++++++++ tests/crashes/131298.rs | 12 ++++++++++++ tests/crashes/131342-2.rs | 40 +++++++++++++++++++++++++++++++++++++++ tests/crashes/131342.rs | 16 ++++++++++++++++ tests/crashes/131347.rs | 9 +++++++++ tests/crashes/131373.rs | 33 ++++++++++++++++++++++++++++++++ tests/crashes/131406.rs | 12 ++++++++++++ 21 files changed, 343 insertions(+) create mode 100644 tests/crashes/130956.rs create mode 100644 tests/crashes/130967.rs create mode 100644 tests/crashes/131046.rs create mode 100644 tests/crashes/131048.rs create mode 100644 tests/crashes/131050.rs create mode 100644 tests/crashes/131052.rs create mode 100644 tests/crashes/131101.rs create mode 100644 tests/crashes/131102.rs create mode 100644 tests/crashes/131103.rs create mode 100644 tests/crashes/131190.rs create mode 100644 tests/crashes/131227.rs create mode 100644 tests/crashes/131292.rs create mode 100644 tests/crashes/131294-2.rs create mode 100644 tests/crashes/131294.rs create mode 100644 tests/crashes/131295.rs create mode 100644 tests/crashes/131298.rs create mode 100644 tests/crashes/131342-2.rs create mode 100644 tests/crashes/131342.rs create mode 100644 tests/crashes/131347.rs create mode 100644 tests/crashes/131373.rs create mode 100644 tests/crashes/131406.rs diff --git a/tests/crashes/130956.rs b/tests/crashes/130956.rs new file mode 100644 index 00000000000..ebb986d123f --- /dev/null +++ b/tests/crashes/130956.rs @@ -0,0 +1,37 @@ +//@ known-bug: #130956 + +mod impl_trait_mod { + use super::*; + pub type OpaqueBlock = impl Trait; + pub type OpaqueIf = impl Trait; + + pub struct BlockWrapper(OpaqueBlock); + pub struct IfWrapper(pub OpaqueIf); + + pub fn if_impl() -> Parser { + bind(option(block()), |_| block()) + } +} +use impl_trait_mod::*; + +pub trait Trait { + type Assoc; +} +pub struct Parser

(P); +pub struct Bind(P, F); +impl Trait for Bind { type Assoc = (); } +impl Trait for BlockWrapper { type Assoc = (); } +impl Trait for IfWrapper { type Assoc = (); } + +pub fn block() -> Parser { + loop {} +} +pub fn option(arg: Parser

) -> Parser { + bind(arg, |_| block()) +} +fn bind Parser>(_: Parser

+ pub fn map_pending_obligations(&self, f: F) -> R where F: Fn(&O) -> P, + R: FromIterator

, { self.nodes .iter() diff --git a/compiler/rustc_hir_analysis/src/autoderef.rs b/compiler/rustc_hir_analysis/src/autoderef.rs index 8d11328743c..5a66c31a0cc 100644 --- a/compiler/rustc_hir_analysis/src/autoderef.rs +++ b/compiler/rustc_hir_analysis/src/autoderef.rs @@ -1,4 +1,5 @@ use rustc_infer::infer::InferCtxt; +use rustc_infer::traits::PredicateObligations; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt}; use rustc_session::Limit; use rustc_span::Span; @@ -23,7 +24,7 @@ struct AutoderefSnapshot<'tcx> { reached_recursion_limit: bool, steps: Vec<(Ty<'tcx>, AutoderefKind)>, cur_ty: Ty<'tcx>, - obligations: Vec>, + obligations: PredicateObligations<'tcx>, } pub struct Autoderef<'a, 'tcx> { @@ -119,7 +120,7 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> { state: AutoderefSnapshot { steps: vec![], cur_ty: infcx.resolve_vars_if_possible(base_ty), - obligations: vec![], + obligations: PredicateObligations::new(), at_start: true, reached_recursion_limit: false, }, @@ -165,7 +166,7 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> { pub fn structurally_normalize( &self, ty: Ty<'tcx>, - ) -> Option<(Ty<'tcx>, Vec>)> { + ) -> Option<(Ty<'tcx>, PredicateObligations<'tcx>)> { let ocx = ObligationCtxt::new(self.infcx); let Ok(normalized_ty) = ocx.structurally_normalize( &traits::ObligationCause::misc(self.span, self.body_id), @@ -204,11 +205,11 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> { self.state.steps.len() } - pub fn into_obligations(self) -> Vec> { + pub fn into_obligations(self) -> PredicateObligations<'tcx> { self.state.obligations } - pub fn current_obligations(&self) -> Vec> { + pub fn current_obligations(&self) -> PredicateObligations<'tcx> { self.state.obligations.clone() } diff --git a/compiler/rustc_hir_typeck/src/autoderef.rs b/compiler/rustc_hir_typeck/src/autoderef.rs index d2d6da8f32b..e4ca1cee757 100644 --- a/compiler/rustc_hir_typeck/src/autoderef.rs +++ b/compiler/rustc_hir_typeck/src/autoderef.rs @@ -5,6 +5,7 @@ use std::iter; use itertools::Itertools; use rustc_hir_analysis::autoderef::{Autoderef, AutoderefKind}; use rustc_infer::infer::InferOk; +use rustc_infer::traits::PredicateObligations; use rustc_middle::ty::adjustment::{Adjust, Adjustment, OverloadedDeref}; use rustc_middle::ty::{self, Ty}; use rustc_span::Span; @@ -36,10 +37,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> InferOk<'tcx, Vec>> { let steps = autoderef.steps(); if steps.is_empty() { - return InferOk { obligations: vec![], value: vec![] }; + return InferOk { obligations: PredicateObligations::new(), value: vec![] }; } - let mut obligations = vec![]; + let mut obligations = PredicateObligations::new(); let targets = steps.iter().skip(1).map(|&(ty, _)| ty).chain(iter::once(autoderef.final_ty(false))); let steps: Vec<_> = steps diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index fcaa5751152..fd6ac7de14a 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -8,7 +8,7 @@ use rustc_hir as hir; use rustc_hir::lang_items::LangItem; use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer; use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferOk, InferResult}; -use rustc_infer::traits::ObligationCauseCode; +use rustc_infer::traits::{ObligationCauseCode, PredicateObligations}; use rustc_macros::{TypeFoldable, TypeVisitable}; use rustc_middle::span_bug; use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt}; @@ -805,7 +805,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // [c1]: https://github.com/rust-lang/rust/pull/45072#issuecomment-341089706 // [c2]: https://github.com/rust-lang/rust/pull/45072#issuecomment-341096796 self.commit_if_ok(|_| { - let mut all_obligations = vec![]; + let mut all_obligations = PredicateObligations::new(); let supplied_sig = self.instantiate_binder_with_fresh_vars( self.tcx.def_span(expr_def_id), BoundRegionConversionTime::FnCall, diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index bd0b9870298..f81bc727aa1 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -46,6 +46,7 @@ use rustc_infer::infer::relate::RelateResult; use rustc_infer::infer::{Coercion, DefineOpaqueTypes, InferOk, InferResult}; use rustc_infer::traits::{ IfExpressionCause, MatchExpressionArmCause, Obligation, PredicateObligation, + PredicateObligations, }; use rustc_middle::lint::in_external_macro; use rustc_middle::span_bug; @@ -120,7 +121,7 @@ fn simple<'tcx>(kind: Adjust<'tcx>) -> impl FnOnce(Ty<'tcx>) -> Vec( adj: Vec>, target: Ty<'tcx>, - obligations: Vec>, + obligations: PredicateObligations<'tcx>, ) -> CoerceResult<'tcx> { Ok(InferOk { value: (adj, target), obligations }) } @@ -184,7 +185,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // Coercing from `!` to any type is allowed: if a.is_never() { if self.coerce_never { - return success(simple(Adjust::NeverToAny)(b), b, vec![]); + return success(simple(Adjust::NeverToAny)(b), b, PredicateObligations::new()); } else { // Otherwise the only coercion we can do is unification. return self.unify_and(a, b, identity); @@ -278,7 +279,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // Two unresolved type variables: create a `Coerce` predicate. let target_ty = if self.use_lub { self.next_ty_var(self.cause.span) } else { b }; - let mut obligations = Vec::with_capacity(2); + let mut obligations = PredicateObligations::with_capacity(2); for &source_ty in &[a, b] { if source_ty != target_ty { obligations.push(Obligation::new( @@ -744,7 +745,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // Check the obligations of the cast -- for example, when casting // `usize` to `dyn* Clone + 'static`: - let mut obligations: Vec<_> = predicates + let obligations = predicates .iter() .map(|predicate| { // For each existential predicate (e.g., `?Self: Clone`) instantiate @@ -764,21 +765,21 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { ty::OutlivesPredicate(a, b_region), ))), ), + // Enforce that the type is `usize`/pointer-sized. + Obligation::new( + self.tcx, + self.cause.clone(), + self.param_env, + ty::TraitRef::new( + self.tcx, + self.tcx + .require_lang_item(hir::LangItem::PointerLike, Some(self.cause.span)), + [a], + ), + ), ]) .collect(); - // Enforce that the type is `usize`/pointer-sized. - obligations.push(Obligation::new( - self.tcx, - self.cause.clone(), - self.param_env, - ty::TraitRef::new( - self.tcx, - self.tcx.require_lang_item(hir::LangItem::PointerLike, Some(self.cause.span)), - [a], - ), - )); - Ok(InferOk { value: ( vec![Adjustment { kind: Adjust::Pointer(PointerCoercion::DynStar), target: b }], diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs index 2aad9a043f9..693cb4465cc 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs @@ -1,6 +1,6 @@ //! A utility module to inspect currently ambiguous obligations in the current context. -use rustc_infer::traits::{self, ObligationCause}; +use rustc_infer::traits::{self, ObligationCause, PredicateObligations}; use rustc_middle::traits::solve::Goal; use rustc_middle::ty::{self, Ty, TypeVisitableExt}; use rustc_span::Span; @@ -15,10 +15,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Returns a list of all obligations whose self type has been unified /// with the unconstrained type `self_ty`. #[instrument(skip(self), level = "debug")] - pub(crate) fn obligations_for_self_ty( - &self, - self_ty: ty::TyVid, - ) -> Vec> { + pub(crate) fn obligations_for_self_ty(&self, self_ty: ty::TyVid) -> PredicateObligations<'tcx> { if self.next_trait_solver() { self.obligations_for_self_ty_next(self_ty) } else { @@ -75,10 +72,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub(crate) fn obligations_for_self_ty_next( &self, self_ty: ty::TyVid, - ) -> Vec> { + ) -> PredicateObligations<'tcx> { let obligations = self.fulfillment_cx.borrow().pending_obligations(); debug!(?obligations); - let mut obligations_for_self_ty = vec![]; + let mut obligations_for_self_ty = PredicateObligations::new(); for obligation in obligations { let mut visitor = NestedObligationsForSelfTy { fcx: self, @@ -103,7 +100,7 @@ struct NestedObligationsForSelfTy<'a, 'tcx> { fcx: &'a FnCtxt<'a, 'tcx>, self_ty: ty::TyVid, root_cause: &'a ObligationCause<'tcx>, - obligations_for_self_ty: &'a mut Vec>, + obligations_for_self_ty: &'a mut PredicateObligations<'tcx>, } impl<'a, 'tcx> ProofTreeVisitor<'tcx> for NestedObligationsForSelfTy<'a, 'tcx> { diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs index cb8b1df2c6e..2de5947b16f 100644 --- a/compiler/rustc_hir_typeck/src/method/mod.rs +++ b/compiler/rustc_hir_typeck/src/method/mod.rs @@ -12,6 +12,7 @@ use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Namespace}; use rustc_hir::def_id::DefId; use rustc_infer::infer::{self, InferOk}; +use rustc_infer::traits::PredicateObligations; use rustc_middle::query::Providers; use rustc_middle::traits::ObligationCause; use rustc_middle::ty::{ @@ -412,7 +413,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } debug!("lookup_in_trait_adjusted: method_item={:?}", method_item); - let mut obligations = vec![]; + let mut obligations = PredicateObligations::new(); // FIXME(effects): revisit when binops get `#[const_trait]` diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs index 7791bd73628..1d3d32ef749 100644 --- a/compiler/rustc_infer/src/infer/canonical/query_response.rs +++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs @@ -28,7 +28,8 @@ use crate::infer::region_constraints::{Constraint, RegionConstraintData}; use crate::infer::{DefineOpaqueTypes, InferCtxt, InferOk, InferResult}; use crate::traits::query::NoSolution; use crate::traits::{ - Obligation, ObligationCause, PredicateObligation, ScrubbedTraitError, TraitEngine, + Obligation, ObligationCause, PredicateObligation, PredicateObligations, ScrubbedTraitError, + TraitEngine, }; impl<'tcx> InferCtxt<'tcx> { @@ -493,7 +494,7 @@ impl<'tcx> InferCtxt<'tcx> { ), }; - let mut obligations = vec![]; + let mut obligations = PredicateObligations::new(); // Carry all newly resolved opaque types to the caller's scope for &(a, b) in &query_response.value.opaque_types { @@ -598,7 +599,7 @@ impl<'tcx> InferCtxt<'tcx> { variables1: &OriginalQueryValues<'tcx>, variables2: impl Fn(BoundVar) -> GenericArg<'tcx>, ) -> InferResult<'tcx, ()> { - let mut obligations = vec![]; + let mut obligations = PredicateObligations::new(); for (index, value1) in variables1.var_values.iter().enumerate() { let value2 = variables2(BoundVar::new(index)); diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index bc813305ba4..7ef714475fc 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -50,7 +50,9 @@ use tracing::{debug, instrument}; use type_variable::TypeVariableOrigin; use crate::infer::region_constraints::UndoLog; -use crate::traits::{self, ObligationCause, ObligationInspector, PredicateObligation, TraitEngine}; +use crate::traits::{ + self, ObligationCause, ObligationInspector, PredicateObligations, TraitEngine, +}; pub mod at; pub mod canonical; @@ -68,7 +70,7 @@ pub(crate) mod snapshot; mod type_variable; /// `InferOk<'tcx, ()>` is used a lot. It may seem like a useless wrapper -/// around `Vec>`, but it has one important property: +/// around `PredicateObligations<'tcx>`, but it has one important property: /// because `InferOk` is marked with `#[must_use]`, if you have a method /// `InferCtxt::f` that returns `InferResult<'tcx, ()>` and you call it with /// `infcx.f()?;` you'll get a warning about the obligations being discarded @@ -78,7 +80,7 @@ mod type_variable; #[derive(Debug)] pub struct InferOk<'tcx, T> { pub value: T, - pub obligations: Vec>, + pub obligations: PredicateObligations<'tcx>, } pub type InferResult<'tcx, T> = Result, TypeError<'tcx>>; @@ -658,7 +660,7 @@ impl<'tcx, T> InferOk<'tcx, T> { } impl<'tcx> InferOk<'tcx, ()> { - pub fn into_obligations(self) -> Vec> { + pub fn into_obligations(self) -> PredicateObligations<'tcx> { self.obligations } } diff --git a/compiler/rustc_infer/src/infer/opaque_types/mod.rs b/compiler/rustc_infer/src/infer/opaque_types/mod.rs index 365ddaba138..853ae6d2641 100644 --- a/compiler/rustc_infer/src/infer/opaque_types/mod.rs +++ b/compiler/rustc_infer/src/infer/opaque_types/mod.rs @@ -16,7 +16,7 @@ use tracing::{debug, instrument}; use super::DefineOpaqueTypes; use crate::errors::OpaqueHiddenTypeDiag; use crate::infer::{InferCtxt, InferOk}; -use crate::traits::{self, Obligation}; +use crate::traits::{self, Obligation, PredicateObligations}; mod table; @@ -46,14 +46,14 @@ impl<'tcx> InferCtxt<'tcx> { ) -> InferOk<'tcx, T> { // We handle opaque types differently in the new solver. if self.next_trait_solver() { - return InferOk { value, obligations: vec![] }; + return InferOk { value, obligations: PredicateObligations::new() }; } if !value.has_opaque_types() { - return InferOk { value, obligations: vec![] }; + return InferOk { value, obligations: PredicateObligations::new() }; } - let mut obligations = vec![]; + let mut obligations = PredicateObligations::new(); let value = value.fold_with(&mut BottomUpFolder { tcx: self.tcx, lt_op: |lt| lt, diff --git a/compiler/rustc_infer/src/infer/projection.rs b/compiler/rustc_infer/src/infer/projection.rs index b78f9d49268..1bee9632110 100644 --- a/compiler/rustc_infer/src/infer/projection.rs +++ b/compiler/rustc_infer/src/infer/projection.rs @@ -2,7 +2,7 @@ use rustc_middle::traits::ObligationCause; use rustc_middle::ty::{self, Ty}; use super::InferCtxt; -use crate::traits::{Obligation, PredicateObligation}; +use crate::traits::{Obligation, PredicateObligations}; impl<'tcx> InferCtxt<'tcx> { /// Instead of normalizing an associated type projection, @@ -17,7 +17,7 @@ impl<'tcx> InferCtxt<'tcx> { projection_ty: ty::AliasTy<'tcx>, cause: ObligationCause<'tcx>, recursion_depth: usize, - obligations: &mut Vec>, + obligations: &mut PredicateObligations<'tcx>, ) -> Ty<'tcx> { debug_assert!(!self.next_trait_solver()); let ty_var = self.next_ty_var(self.tcx.def_span(projection_ty.def_id)); diff --git a/compiler/rustc_infer/src/infer/relate/lattice.rs b/compiler/rustc_infer/src/infer/relate/lattice.rs index 7eb61abfbc1..4eb77a99be7 100644 --- a/compiler/rustc_infer/src/infer/relate/lattice.rs +++ b/compiler/rustc_infer/src/infer/relate/lattice.rs @@ -27,7 +27,7 @@ use tracing::{debug, instrument}; use super::StructurallyRelateAliases; use super::combine::PredicateEmittingRelation; use crate::infer::{DefineOpaqueTypes, InferCtxt, SubregionOrigin, TypeTrace}; -use crate::traits::{Obligation, PredicateObligation}; +use crate::traits::{Obligation, PredicateObligations}; #[derive(Clone, Copy)] pub(crate) enum LatticeOpKind { @@ -52,7 +52,7 @@ pub(crate) struct LatticeOp<'infcx, 'tcx> { param_env: ty::ParamEnv<'tcx>, // Mutable fields kind: LatticeOpKind, - obligations: Vec>, + obligations: PredicateObligations<'tcx>, } impl<'infcx, 'tcx> LatticeOp<'infcx, 'tcx> { @@ -62,10 +62,10 @@ impl<'infcx, 'tcx> LatticeOp<'infcx, 'tcx> { param_env: ty::ParamEnv<'tcx>, kind: LatticeOpKind, ) -> LatticeOp<'infcx, 'tcx> { - LatticeOp { infcx, trace, param_env, kind, obligations: vec![] } + LatticeOp { infcx, trace, param_env, kind, obligations: PredicateObligations::new() } } - pub(crate) fn into_obligations(self) -> Vec> { + pub(crate) fn into_obligations(self) -> PredicateObligations<'tcx> { self.obligations } } diff --git a/compiler/rustc_infer/src/infer/relate/type_relating.rs b/compiler/rustc_infer/src/infer/relate/type_relating.rs index 35103c070c2..009271a8378 100644 --- a/compiler/rustc_infer/src/infer/relate/type_relating.rs +++ b/compiler/rustc_infer/src/infer/relate/type_relating.rs @@ -11,7 +11,7 @@ use tracing::{debug, instrument}; use crate::infer::BoundRegionConversionTime::HigherRankedType; use crate::infer::relate::{PredicateEmittingRelation, StructurallyRelateAliases}; use crate::infer::{DefineOpaqueTypes, InferCtxt, SubregionOrigin, TypeTrace}; -use crate::traits::{Obligation, PredicateObligation}; +use crate::traits::{Obligation, PredicateObligations}; /// Enforce that `a` is equal to or a subtype of `b`. pub(crate) struct TypeRelating<'infcx, 'tcx> { @@ -24,7 +24,7 @@ pub(crate) struct TypeRelating<'infcx, 'tcx> { // Mutable fields. ambient_variance: ty::Variance, - obligations: Vec>, + obligations: PredicateObligations<'tcx>, /// The cache only tracks the `ambient_variance` as it's the /// only field which is mutable and which meaningfully changes /// the result when relating types. @@ -65,12 +65,12 @@ impl<'infcx, 'tcx> TypeRelating<'infcx, 'tcx> { param_env, define_opaque_types, ambient_variance, - obligations: vec![], + obligations: PredicateObligations::new(), cache: Default::default(), } } - pub(crate) fn into_obligations(self) -> Vec> { + pub(crate) fn into_obligations(self) -> PredicateObligations<'tcx> { self.obligations } } diff --git a/compiler/rustc_infer/src/traits/engine.rs b/compiler/rustc_infer/src/traits/engine.rs index a076cdad672..ba1516655b0 100644 --- a/compiler/rustc_infer/src/traits/engine.rs +++ b/compiler/rustc_infer/src/traits/engine.rs @@ -3,7 +3,7 @@ use std::fmt::Debug; use rustc_hir::def_id::DefId; use rustc_middle::ty::{self, Ty, Upcast}; -use super::{ObligationCause, PredicateObligation}; +use super::{ObligationCause, PredicateObligation, PredicateObligations}; use crate::infer::InferCtxt; use crate::traits::Obligation; @@ -20,7 +20,7 @@ pub enum ScrubbedTraitError<'tcx> { /// An ambiguity. This goal may hold if further inference is done. Ambiguity, /// An old-solver-style cycle error, which will fatal. - Cycle(Vec>), + Cycle(PredicateObligations<'tcx>), } impl<'tcx> ScrubbedTraitError<'tcx> { @@ -62,7 +62,7 @@ pub trait TraitEngine<'tcx, E: 'tcx>: 'tcx { fn register_predicate_obligations( &mut self, infcx: &InferCtxt<'tcx>, - obligations: Vec>, + obligations: PredicateObligations<'tcx>, ) { for obligation in obligations { self.register_predicate_obligation(infcx, obligation); @@ -84,7 +84,7 @@ pub trait TraitEngine<'tcx, E: 'tcx>: 'tcx { self.collect_remaining_errors(infcx) } - fn pending_obligations(&self) -> Vec>; + fn pending_obligations(&self) -> PredicateObligations<'tcx>; /// Among all pending obligations, collect those are stalled on a inference variable which has /// changed since the last call to `select_where_possible`. Those obligations are marked as @@ -92,7 +92,7 @@ pub trait TraitEngine<'tcx, E: 'tcx>: 'tcx { fn drain_unstalled_obligations( &mut self, infcx: &InferCtxt<'tcx>, - ) -> Vec>; + ) -> PredicateObligations<'tcx>; } pub trait FromSolverError<'tcx, E>: Debug + 'tcx { diff --git a/compiler/rustc_infer/src/traits/mod.rs b/compiler/rustc_infer/src/traits/mod.rs index 34b0fe3e967..2d02391c57a 100644 --- a/compiler/rustc_infer/src/traits/mod.rs +++ b/compiler/rustc_infer/src/traits/mod.rs @@ -84,6 +84,8 @@ pub type PredicateObligation<'tcx> = Obligation<'tcx, ty::Predicate<'tcx>>; pub type TraitObligation<'tcx> = Obligation<'tcx, ty::TraitPredicate<'tcx>>; pub type PolyTraitObligation<'tcx> = Obligation<'tcx, ty::PolyTraitPredicate<'tcx>>; +pub type PredicateObligations<'tcx> = Vec>; + impl<'tcx> PredicateObligation<'tcx> { /// Flips the polarity of the inner predicate. /// diff --git a/compiler/rustc_infer/src/traits/project.rs b/compiler/rustc_infer/src/traits/project.rs index 64b72de3986..cab2ce9f5a0 100644 --- a/compiler/rustc_infer/src/traits/project.rs +++ b/compiler/rustc_infer/src/traits/project.rs @@ -6,7 +6,7 @@ use rustc_middle::traits::EvaluationResult; use rustc_middle::ty; use tracing::{debug, info}; -use super::PredicateObligation; +use super::PredicateObligations; use crate::infer::snapshot::undo_log::InferCtxtUndoLogs; pub(crate) type UndoLog<'tcx> = @@ -20,7 +20,7 @@ pub struct MismatchedProjectionTypes<'tcx> { #[derive(Clone)] pub struct Normalized<'tcx, T> { pub value: T, - pub obligations: Vec>, + pub obligations: PredicateObligations<'tcx>, } pub type NormalizedTerm<'tcx> = Normalized<'tcx, ty::Term<'tcx>>; @@ -191,7 +191,7 @@ impl<'tcx> ProjectionCache<'_, 'tcx> { info!("ProjectionCacheEntry::complete({:?}) - completing {:?}", key, ty); let mut ty = ty.clone(); if result.must_apply_considering_regions() { - ty.obligations = vec![]; + ty.obligations = PredicateObligations::new(); } map.insert(key, ProjectionCacheEntry::NormalizedTerm { ty, diff --git a/compiler/rustc_trait_selection/src/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/mod.rs index cb7efeaae0b..82695688ae8 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/mod.rs @@ -2,7 +2,7 @@ use std::ops::Deref; use rustc_errors::DiagCtxtHandle; use rustc_infer::infer::InferCtxt; -use rustc_infer::traits::PredicateObligation; +use rustc_infer::traits::PredicateObligations; use rustc_macros::extension; use rustc_middle::bug; use rustc_middle::ty::{self, Ty}; @@ -28,8 +28,7 @@ pub struct TypeErrCtxt<'a, 'tcx> { pub normalize_fn_sig: Box) -> ty::PolyFnSig<'tcx> + 'a>, - pub autoderef_steps: - Box) -> Vec<(Ty<'tcx>, Vec>)> + 'a>, + pub autoderef_steps: Box) -> Vec<(Ty<'tcx>, PredicateObligations<'tcx>)> + 'a>, } #[extension(pub trait InferCtxtErrorExt<'tcx>)] @@ -45,7 +44,7 @@ impl<'tcx> InferCtxt<'tcx> { normalize_fn_sig: Box::new(|fn_sig| fn_sig), autoderef_steps: Box::new(|ty| { debug_assert!(false, "shouldn't be using autoderef_steps outside of typeck"); - vec![(ty, vec![])] + vec![(ty, PredicateObligations::new())] }), } } diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index 081d7a6a769..8ec4427091d 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -7,7 +7,7 @@ use rustc_infer::traits::query::NoSolution; use rustc_infer::traits::solve::{CandidateSource, GoalSource, MaybeCause}; use rustc_infer::traits::{ self, FromSolverError, MismatchedProjectionTypes, Obligation, ObligationCause, - ObligationCauseCode, PredicateObligation, SelectionError, TraitEngine, + ObligationCauseCode, PredicateObligation, PredicateObligations, SelectionError, TraitEngine, }; use rustc_middle::bug; use rustc_middle::ty::error::{ExpectedFound, TypeError}; @@ -49,8 +49,8 @@ struct ObligationStorage<'tcx> { /// We cannot eagerly return these as error so we instead store them here /// to avoid recomputing them each time `select_where_possible` is called. /// This also allows us to return the correct `FulfillmentError` for them. - overflowed: Vec>, - pending: Vec>, + overflowed: PredicateObligations<'tcx>, + pending: PredicateObligations<'tcx>, } impl<'tcx> ObligationStorage<'tcx> { @@ -58,13 +58,13 @@ impl<'tcx> ObligationStorage<'tcx> { self.pending.push(obligation); } - fn clone_pending(&self) -> Vec> { + fn clone_pending(&self) -> PredicateObligations<'tcx> { let mut obligations = self.pending.clone(); obligations.extend(self.overflowed.iter().cloned()); obligations } - fn take_pending(&mut self) -> Vec> { + fn take_pending(&mut self) -> PredicateObligations<'tcx> { let mut obligations = mem::take(&mut self.pending); obligations.append(&mut self.overflowed); obligations @@ -197,14 +197,11 @@ where errors } - fn pending_obligations(&self) -> Vec> { + fn pending_obligations(&self) -> PredicateObligations<'tcx> { self.obligations.clone_pending() } - fn drain_unstalled_obligations( - &mut self, - _: &InferCtxt<'tcx>, - ) -> Vec> { + fn drain_unstalled_obligations(&mut self, _: &InferCtxt<'tcx>) -> PredicateObligations<'tcx> { self.obligations.take_pending() } } diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index b29e41beab5..f4a2483cebf 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -11,6 +11,7 @@ use rustc_errors::{Diag, EmissionGuarantee}; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, TyCtxtInferExt}; +use rustc_infer::traits::PredicateObligations; use rustc_middle::bug; use rustc_middle::traits::query::NoSolution; use rustc_middle::traits::solve::{CandidateSource, Certainty, Goal}; @@ -279,7 +280,7 @@ fn equate_impl_headers<'tcx>( param_env: ty::ParamEnv<'tcx>, impl1: &ty::ImplHeader<'tcx>, impl2: &ty::ImplHeader<'tcx>, -) -> Option>> { +) -> Option> { let result = match (impl1.trait_ref, impl2.trait_ref) { (Some(impl1_ref), Some(impl2_ref)) => infcx @@ -491,7 +492,7 @@ fn plug_infer_with_placeholders<'tcx>( else { bug!("we always expect to be able to plug an infer var with placeholder") }; - assert_eq!(obligations, &[]); + assert_eq!(obligations.len(), 0); } else { ty.super_visit_with(self); } @@ -514,7 +515,7 @@ fn plug_infer_with_placeholders<'tcx>( else { bug!("we always expect to be able to plug an infer var with placeholder") }; - assert_eq!(obligations, &[]); + assert_eq!(obligations.len(), 0); } else { ct.super_visit_with(self); } @@ -545,7 +546,7 @@ fn plug_infer_with_placeholders<'tcx>( else { bug!("we always expect to be able to plug an infer var with placeholder") }; - assert_eq!(obligations, &[]); + assert_eq!(obligations.len(), 0); } } } diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs index d562692c1a8..eda3f6e8023 100644 --- a/compiler/rustc_trait_selection/src/traits/engine.rs +++ b/compiler/rustc_trait_selection/src/traits/engine.rs @@ -10,6 +10,7 @@ use rustc_infer::infer::canonical::{ }; use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk, RegionResolutionError, TypeTrace}; +use rustc_infer::traits::PredicateObligations; use rustc_macros::extension; use rustc_middle::arena::ArenaAllocatable; use rustc_middle::traits::query::NoSolution; @@ -208,7 +209,7 @@ where /// getting ignored. You can make a new `ObligationCtxt` if this /// needs to be done in a loop, for example. #[must_use] - pub fn into_pending_obligations(self) -> Vec> { + pub fn into_pending_obligations(self) -> PredicateObligations<'tcx> { self.engine.borrow().pending_obligations() } diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 33b8cf03701..3e3834a11c6 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -6,7 +6,8 @@ use rustc_data_structures::obligation_forest::{ }; use rustc_infer::infer::DefineOpaqueTypes; use rustc_infer::traits::{ - FromSolverError, PolyTraitObligation, ProjectionCacheKey, SelectionError, TraitEngine, + FromSolverError, PolyTraitObligation, PredicateObligations, ProjectionCacheKey, SelectionError, + TraitEngine, }; use rustc_middle::bug; use rustc_middle::mir::interpret::ErrorHandled; @@ -27,6 +28,8 @@ use crate::traits::normalize::normalize_with_depth_to; use crate::traits::project::{PolyProjectionObligation, ProjectionCacheKeyExt as _}; use crate::traits::query::evaluate_obligation::InferCtxtExt; +pub(crate) type PendingPredicateObligations<'tcx> = Vec>; + impl<'tcx> ForestObligation for PendingPredicateObligation<'tcx> { /// Note that we include both the `ParamEnv` and the `Predicate`, /// as the `ParamEnv` can influence whether fulfillment succeeds @@ -161,15 +164,16 @@ where fn drain_unstalled_obligations( &mut self, infcx: &InferCtxt<'tcx>, - ) -> Vec> { - let mut processor = DrainProcessor { removed_predicates: Vec::new(), infcx }; + ) -> PredicateObligations<'tcx> { + let mut processor = + DrainProcessor { removed_predicates: PredicateObligations::new(), infcx }; let outcome: Outcome<_, _> = self.predicates.process_obligations(&mut processor); assert!(outcome.errors.is_empty()); return processor.removed_predicates; struct DrainProcessor<'a, 'tcx> { infcx: &'a InferCtxt<'tcx>, - removed_predicates: Vec>, + removed_predicates: PredicateObligations<'tcx>, } impl<'tcx> ObligationProcessor for DrainProcessor<'_, 'tcx> { @@ -190,7 +194,7 @@ where ) -> ProcessResult, !> { assert!(self.needs_process_obligation(pending_obligation)); self.removed_predicates.push(pending_obligation.obligation.clone()); - ProcessResult::Changed(vec![]) + ProcessResult::Changed(Default::default()) } fn process_backedge<'c, I>( @@ -207,7 +211,7 @@ where } } - fn pending_obligations(&self) -> Vec> { + fn pending_obligations(&self) -> PredicateObligations<'tcx> { self.predicates.map_pending_obligations(|o| o.obligation.clone()) } } @@ -216,7 +220,7 @@ struct FulfillProcessor<'a, 'tcx> { selcx: SelectionContext<'a, 'tcx>, } -fn mk_pending(os: Vec>) -> Vec> { +fn mk_pending<'tcx>(os: PredicateObligations<'tcx>) -> PendingPredicateObligations<'tcx> { os.into_iter() .map(|o| PendingPredicateObligation { obligation: o, stalled_on: vec![] }) .collect() @@ -321,7 +325,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { let infcx = self.selcx.infcx; if obligation.predicate.has_aliases() { - let mut obligations = Vec::new(); + let mut obligations = PredicateObligations::new(); let predicate = normalize_with_depth_to( &mut self.selcx, obligation.param_env, @@ -369,7 +373,10 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { | ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..)) | ty::PredicateKind::ConstEquate(..) => { let pred = ty::Binder::dummy(infcx.enter_forall_and_leak_universe(binder)); - ProcessResult::Changed(mk_pending(vec![obligation.with(infcx.tcx, pred)])) + let mut obligations = PredicateObligations::with_capacity(1); + obligations.push(obligation.with(infcx.tcx, pred)); + + ProcessResult::Changed(mk_pending(obligations)) } ty::PredicateKind::Ambiguous => ProcessResult::Unchanged, ty::PredicateKind::NormalizesTo(..) => { @@ -395,7 +402,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { infcx.region_outlives_predicate(&obligation.cause, Binder::dummy(data)); } - ProcessResult::Changed(vec![]) + ProcessResult::Changed(Default::default()) } ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate( @@ -405,7 +412,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { if infcx.considering_regions { infcx.register_region_obligation_with_cause(t_a, r_b, &obligation.cause); } - ProcessResult::Changed(vec![]) + ProcessResult::Changed(Default::default()) } ty::PredicateKind::Clause(ty::ClauseKind::Projection(ref data)) => { @@ -422,7 +429,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { if !self.selcx.tcx().is_dyn_compatible(trait_def_id) { ProcessResult::Error(FulfillmentErrorCode::Select(Unimplemented)) } else { - ProcessResult::Changed(vec![]) + ProcessResult::Changed(Default::default()) } } @@ -451,7 +458,9 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { pending_obligation.stalled_on.extend([var]); return ProcessResult::Unchanged; } - ty::ConstKind::Error(_) => return ProcessResult::Changed(vec![]), + ty::ConstKind::Error(_) => { + return ProcessResult::Changed(PendingPredicateObligations::new()); + } ty::ConstKind::Value(ty, _) => ty, ty::ConstKind::Unevaluated(uv) => { infcx.tcx.type_of(uv.def).instantiate(infcx.tcx, uv.args) @@ -460,7 +469,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { // `>::Output` when this is an `Expr` representing // `lhs + rhs`. ty::ConstKind::Expr(_) => { - return ProcessResult::Changed(mk_pending(vec![])); + return ProcessResult::Changed(mk_pending(PredicateObligations::new())); } ty::ConstKind::Placeholder(_) => { bug!("placeholder const {:?} in old solver", ct) @@ -568,7 +577,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { obligation.param_env, obligation.cause.span, ) { - Ok(()) => ProcessResult::Changed(vec![]), + Ok(()) => ProcessResult::Changed(Default::default()), Err(NotConstEvaluatable::MentionsInfer) => { pending_obligation.stalled_on.clear(); pending_obligation.stalled_on.extend( @@ -722,7 +731,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { debug!("process_child_obligations: coinductive match"); Ok(()) } else { - let cycle: Vec<_> = cycle.map(|c| c.obligation.clone()).collect(); + let cycle = cycle.map(|c| c.obligation.clone()).collect(); Err(FulfillmentErrorCode::Cycle(cycle)) } } @@ -745,7 +754,7 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> { "selecting trait at depth {} evaluated to holds", obligation.recursion_depth ); - return ProcessResult::Changed(vec![]); + return ProcessResult::Changed(Default::default()); } } @@ -809,7 +818,7 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> { .projection_cache() .complete(key, EvaluationResult::EvaluatedToOk); } - return ProcessResult::Changed(vec![]); + return ProcessResult::Changed(Default::default()); } else { debug!("Does NOT hold: {:?}", obligation); } @@ -826,9 +835,12 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> { ProcessResult::Unchanged } // Let the caller handle the recursion - ProjectAndUnifyResult::Recursive => ProcessResult::Changed(mk_pending(vec![ - project_obligation.with(tcx, project_obligation.predicate), - ])), + ProjectAndUnifyResult::Recursive => { + let mut obligations = PredicateObligations::with_capacity(1); + obligations.push(project_obligation.with(tcx, project_obligation.predicate)); + + ProcessResult::Changed(mk_pending(obligations)) + } ProjectAndUnifyResult::MismatchedProjectionTypes(e) => { ProcessResult::Error(FulfillmentErrorCode::Project(e)) } diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 655bef0bab7..0fb795fc184 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -114,7 +114,7 @@ impl<'tcx> Debug for FulfillmentError<'tcx> { pub enum FulfillmentErrorCode<'tcx> { /// Inherently impossible to fulfill; this trait is implemented if and only /// if it is already implemented. - Cycle(Vec>), + Cycle(PredicateObligations<'tcx>), Select(SelectionError<'tcx>), Project(MismatchedProjectionTypes<'tcx>), Subtype(ExpectedFound>, TypeError<'tcx>), // always comes from a SubtypePredicate diff --git a/compiler/rustc_trait_selection/src/traits/normalize.rs b/compiler/rustc_trait_selection/src/traits/normalize.rs index a7130cbd28f..7eac3559348 100644 --- a/compiler/rustc_trait_selection/src/traits/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/normalize.rs @@ -4,7 +4,7 @@ use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_infer::infer::InferOk; use rustc_infer::infer::at::At; use rustc_infer::traits::{ - FromSolverError, Normalized, Obligation, PredicateObligation, TraitEngine, + FromSolverError, Normalized, Obligation, PredicateObligations, TraitEngine, }; use rustc_macros::extension; use rustc_middle::traits::{ObligationCause, ObligationCauseCode, Reveal}; @@ -29,7 +29,7 @@ impl<'tcx> At<'_, 'tcx> { /// projection may be fallible. fn normalize>>(&self, value: T) -> InferOk<'tcx, T> { if self.infcx.next_trait_solver() { - InferOk { value, obligations: Vec::new() } + InferOk { value, obligations: PredicateObligations::new() } } else { let mut selcx = SelectionContext::new(self.infcx); let Normalized { value, obligations } = @@ -83,7 +83,7 @@ pub(crate) fn normalize_with_depth<'a, 'b, 'tcx, T>( where T: TypeFoldable>, { - let mut obligations = Vec::new(); + let mut obligations = PredicateObligations::new(); let value = normalize_with_depth_to(selcx, param_env, cause, depth, value, &mut obligations); Normalized { value, obligations } } @@ -95,14 +95,14 @@ pub(crate) fn normalize_with_depth_to<'a, 'b, 'tcx, T>( cause: ObligationCause<'tcx>, depth: usize, value: T, - obligations: &mut Vec>, + obligations: &mut PredicateObligations<'tcx>, ) -> T where T: TypeFoldable>, { debug!(obligations.len = obligations.len()); let mut normalizer = AssocTypeNormalizer::new(selcx, param_env, cause, depth, obligations); - let result = ensure_sufficient_stack(|| normalizer.fold(value)); + let result = ensure_sufficient_stack(|| AssocTypeNormalizer::fold(&mut normalizer, value)); debug!(?result, obligations.len = normalizer.obligations.len()); debug!(?normalizer.obligations,); result @@ -128,7 +128,7 @@ struct AssocTypeNormalizer<'a, 'b, 'tcx> { selcx: &'a mut SelectionContext<'b, 'tcx>, param_env: ty::ParamEnv<'tcx>, cause: ObligationCause<'tcx>, - obligations: &'a mut Vec>, + obligations: &'a mut PredicateObligations<'tcx>, depth: usize, universes: Vec>, } @@ -139,7 +139,7 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> { param_env: ty::ParamEnv<'tcx>, cause: ObligationCause<'tcx>, depth: usize, - obligations: &'a mut Vec>, + obligations: &'a mut PredicateObligations<'tcx>, ) -> AssocTypeNormalizer<'a, 'b, 'tcx> { debug_assert!(!selcx.infcx.next_trait_solver()); AssocTypeNormalizer { selcx, param_env, cause, obligations, depth, universes: vec![] } diff --git a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs index f1faff2c036..339e4bf1f22 100644 --- a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs +++ b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs @@ -77,7 +77,7 @@ fn implied_outlives_bounds<'a, 'tcx>( else { return vec![]; }; - assert_eq!(&obligations, &[]); + assert_eq!(obligations.len(), 0); // Because of #109628, we may have unexpected placeholders. Ignore them! // FIXME(#109628): panic in this case once the issue is fixed. diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 9cd99d99fc3..7f7c9bced18 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -9,7 +9,7 @@ use rustc_hir::def::DefKind; use rustc_hir::lang_items::LangItem; use rustc_infer::infer::DefineOpaqueTypes; use rustc_infer::infer::resolve::OpportunisticRegionResolver; -use rustc_infer::traits::ObligationCauseCode; +use rustc_infer::traits::{ObligationCauseCode, PredicateObligations}; pub use rustc_middle::traits::Reveal; use rustc_middle::traits::select::OverflowError; use rustc_middle::traits::{BuiltinImplSource, ImplSource, ImplSourceUserDefinedData}; @@ -146,7 +146,7 @@ impl<'tcx> ProjectionCandidateSet<'tcx> { /// of the old return type, which was: /// ```ignore (not-rust) /// Result< -/// Result>>, InProgress>, +/// Result>, InProgress>, /// MismatchedProjectionTypes<'tcx>, /// > /// ``` @@ -155,7 +155,7 @@ pub(super) enum ProjectAndUnifyResult<'tcx> { /// projection cannot be normalized because the required trait bound does /// not hold, this is returned, with `obligations` being a predicate that /// cannot be proven. - Holds(Vec>), + Holds(PredicateObligations<'tcx>), /// The projection cannot be normalized due to ambiguity. Resolving some /// inference variables in the projection may fix this. FailedNormalization, @@ -231,7 +231,7 @@ fn project_and_unify_term<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionObligation<'tcx>, ) -> ProjectAndUnifyResult<'tcx> { - let mut obligations = vec![]; + let mut obligations = PredicateObligations::new(); let infcx = selcx.infcx; let normalized = match opt_normalize_projection_term( @@ -289,7 +289,7 @@ pub fn normalize_projection_ty<'a, 'b, 'tcx>( projection_ty: ty::AliasTy<'tcx>, cause: ObligationCause<'tcx>, depth: usize, - obligations: &mut Vec>, + obligations: &mut PredicateObligations<'tcx>, ) -> Term<'tcx> { opt_normalize_projection_term( selcx, @@ -330,7 +330,7 @@ pub(super) fn opt_normalize_projection_term<'a, 'b, 'tcx>( projection_term: ty::AliasTerm<'tcx>, cause: ObligationCause<'tcx>, depth: usize, - obligations: &mut Vec>, + obligations: &mut PredicateObligations<'tcx>, ) -> Result>, InProgress> { let infcx = selcx.infcx; debug_assert!(!selcx.infcx.next_trait_solver()); @@ -452,7 +452,8 @@ pub(super) fn opt_normalize_projection_term<'a, 'b, 'tcx>( Ok(Some(result.value)) } Ok(Projected::NoProgress(projected_ty)) => { - let result = Normalized { value: projected_ty, obligations: vec![] }; + let result = + Normalized { value: projected_ty, obligations: PredicateObligations::new() }; if use_cache { infcx.inner.borrow_mut().projection_cache().insert_term(cache_key, result.clone()); } @@ -519,13 +520,14 @@ fn normalize_to_error<'a, 'tcx>( selcx.infcx.next_const_var(cause.span).into() } }; - let trait_obligation = Obligation { + let mut obligations = PredicateObligations::new(); + obligations.push(Obligation { cause, recursion_depth: depth, param_env, predicate: trait_ref.upcast(selcx.tcx()), - }; - Normalized { value: new_value, obligations: vec![trait_obligation] } + }); + Normalized { value: new_value, obligations } } /// Confirm and normalize the given inherent projection. @@ -536,7 +538,7 @@ pub fn normalize_inherent_projection<'a, 'b, 'tcx>( alias_ty: ty::AliasTy<'tcx>, cause: ObligationCause<'tcx>, depth: usize, - obligations: &mut Vec>, + obligations: &mut PredicateObligations<'tcx>, ) -> Ty<'tcx> { let tcx = selcx.tcx(); @@ -604,7 +606,7 @@ pub fn compute_inherent_assoc_ty_args<'a, 'b, 'tcx>( alias_ty: ty::AliasTy<'tcx>, cause: ObligationCause<'tcx>, depth: usize, - obligations: &mut Vec>, + obligations: &mut PredicateObligations<'tcx>, ) -> ty::GenericArgsRef<'tcx> { let tcx = selcx.tcx(); @@ -657,15 +659,15 @@ enum Projected<'tcx> { struct Progress<'tcx> { term: ty::Term<'tcx>, - obligations: Vec>, + obligations: PredicateObligations<'tcx>, } impl<'tcx> Progress<'tcx> { fn error(tcx: TyCtxt<'tcx>, guar: ErrorGuaranteed) -> Self { - Progress { term: Ty::new_error(tcx, guar).into(), obligations: vec![] } + Progress { term: Ty::new_error(tcx, guar).into(), obligations: PredicateObligations::new() } } - fn with_addl_obligations(mut self, mut obligations: Vec>) -> Self { + fn with_addl_obligations(mut self, mut obligations: PredicateObligations<'tcx>) -> Self { self.obligations.append(&mut obligations); self } @@ -1351,7 +1353,7 @@ fn confirm_select_candidate<'cx, 'tcx>( fn confirm_coroutine_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTermObligation<'tcx>, - nested: Vec>, + nested: PredicateObligations<'tcx>, ) -> Progress<'tcx> { let self_ty = selcx.infcx.shallow_resolve(obligation.predicate.self_ty()); let ty::Coroutine(_, args) = self_ty.kind() else { @@ -1410,7 +1412,7 @@ fn confirm_coroutine_candidate<'cx, 'tcx>( fn confirm_future_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTermObligation<'tcx>, - nested: Vec>, + nested: PredicateObligations<'tcx>, ) -> Progress<'tcx> { let self_ty = selcx.infcx.shallow_resolve(obligation.predicate.self_ty()); let ty::Coroutine(_, args) = self_ty.kind() else { @@ -1458,7 +1460,7 @@ fn confirm_future_candidate<'cx, 'tcx>( fn confirm_iterator_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTermObligation<'tcx>, - nested: Vec>, + nested: PredicateObligations<'tcx>, ) -> Progress<'tcx> { let self_ty = selcx.infcx.shallow_resolve(obligation.predicate.self_ty()); let ty::Coroutine(_, args) = self_ty.kind() else { @@ -1504,7 +1506,7 @@ fn confirm_iterator_candidate<'cx, 'tcx>( fn confirm_async_iterator_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTermObligation<'tcx>, - nested: Vec>, + nested: PredicateObligations<'tcx>, ) -> Progress<'tcx> { let ty::Coroutine(_, args) = selcx.infcx.shallow_resolve(obligation.predicate.self_ty()).kind() else { @@ -1558,7 +1560,7 @@ fn confirm_async_iterator_candidate<'cx, 'tcx>( fn confirm_builtin_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTermObligation<'tcx>, - data: Vec>, + data: PredicateObligations<'tcx>, ) -> Progress<'tcx> { let tcx = selcx.tcx(); let self_ty = obligation.predicate.self_ty(); @@ -1569,17 +1571,17 @@ fn confirm_builtin_candidate<'cx, 'tcx>( let discriminant_def_id = tcx.require_lang_item(LangItem::Discriminant, None); assert_eq!(discriminant_def_id, item_def_id); - (self_ty.discriminant_ty(tcx).into(), Vec::new()) + (self_ty.discriminant_ty(tcx).into(), PredicateObligations::new()) } else if tcx.is_lang_item(trait_def_id, LangItem::AsyncDestruct) { let destructor_def_id = tcx.associated_item_def_ids(trait_def_id)[0]; assert_eq!(destructor_def_id, item_def_id); - (self_ty.async_destructor_ty(tcx).into(), Vec::new()) + (self_ty.async_destructor_ty(tcx).into(), PredicateObligations::new()) } else if tcx.is_lang_item(trait_def_id, LangItem::PointeeTrait) { let metadata_def_id = tcx.require_lang_item(LangItem::Metadata, None); assert_eq!(metadata_def_id, item_def_id); - let mut obligations = Vec::new(); + let mut obligations = PredicateObligations::new(); let normalize = |ty| { normalize_with_depth_to( selcx, @@ -1627,7 +1629,7 @@ fn confirm_builtin_candidate<'cx, 'tcx>( fn confirm_fn_pointer_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTermObligation<'tcx>, - nested: Vec>, + nested: PredicateObligations<'tcx>, ) -> Progress<'tcx> { let tcx = selcx.tcx(); let fn_type = selcx.infcx.shallow_resolve(obligation.predicate.self_ty()); @@ -1663,7 +1665,7 @@ fn confirm_fn_pointer_candidate<'cx, 'tcx>( fn confirm_closure_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTermObligation<'tcx>, - nested: Vec>, + nested: PredicateObligations<'tcx>, ) -> Progress<'tcx> { let tcx = selcx.tcx(); let self_ty = selcx.infcx.shallow_resolve(obligation.predicate.self_ty()); @@ -1782,7 +1784,7 @@ fn confirm_callable_candidate<'cx, 'tcx>( fn confirm_async_closure_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTermObligation<'tcx>, - nested: Vec>, + nested: PredicateObligations<'tcx>, ) -> Progress<'tcx> { let tcx = selcx.tcx(); let self_ty = selcx.infcx.shallow_resolve(obligation.predicate.self_ty()); @@ -1934,7 +1936,7 @@ fn confirm_async_closure_candidate<'cx, 'tcx>( fn confirm_async_fn_kind_helper_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTermObligation<'tcx>, - nested: Vec>, + nested: PredicateObligations<'tcx>, ) -> Progress<'tcx> { let [ // We already checked that the goal_kind >= closure_kind @@ -1987,7 +1989,7 @@ fn confirm_param_env_candidate<'cx, 'tcx>( ); let cache_projection = cache_entry.projection_term; - let mut nested_obligations = Vec::new(); + let mut nested_obligations = PredicateObligations::new(); let obligation_projection = obligation.predicate; let obligation_projection = ensure_sufficient_stack(|| { normalize_with_depth_to( @@ -2034,7 +2036,7 @@ fn confirm_param_env_candidate<'cx, 'tcx>( ); debug!("confirm_param_env_candidate: {}", msg); let err = Ty::new_error_with_message(infcx.tcx, obligation.cause.span, msg); - Progress { term: err.into(), obligations: vec![] } + Progress { term: err.into(), obligations: PredicateObligations::new() } } } } @@ -2047,6 +2049,7 @@ fn confirm_impl_candidate<'cx, 'tcx>( let tcx = selcx.tcx(); let ImplSourceUserDefinedData { impl_def_id, args, mut nested } = impl_impl_source; + let assoc_item_id = obligation.predicate.def_id; let trait_def_id = tcx.trait_id_of_impl(impl_def_id).unwrap(); @@ -2102,7 +2105,7 @@ fn confirm_impl_candidate<'cx, 'tcx>( fn assoc_ty_own_obligations<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTermObligation<'tcx>, - nested: &mut Vec>, + nested: &mut PredicateObligations<'tcx>, ) { let tcx = selcx.tcx(); let predicates = tcx diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index 36b24eac5c4..18412b844ff 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -4,6 +4,7 @@ use rustc_data_structures::sso::SsoHashMap; use rustc_data_structures::stack::ensure_sufficient_stack; +use rustc_infer::traits::PredicateObligations; use rustc_macros::extension; pub use rustc_middle::traits::query::NormalizationResult; use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable}; @@ -20,8 +21,7 @@ use crate::infer::canonical::OriginalQueryValues; use crate::infer::{InferCtxt, InferOk}; use crate::traits::normalize::needs_normalization; use crate::traits::{ - BoundVarReplacer, Normalized, ObligationCause, PlaceholderReplacer, PredicateObligation, - Reveal, ScrubbedTraitError, + BoundVarReplacer, Normalized, ObligationCause, PlaceholderReplacer, Reveal, ScrubbedTraitError, }; #[extension(pub trait QueryNormalizeExt<'tcx>)] @@ -80,7 +80,9 @@ impl<'a, 'tcx> At<'a, 'tcx> { match crate::solve::deeply_normalize_with_skipped_universes::<_, ScrubbedTraitError<'tcx>>( self, value, universes, ) { - Ok(value) => return Ok(Normalized { value, obligations: vec![] }), + Ok(value) => { + return Ok(Normalized { value, obligations: PredicateObligations::new() }); + } Err(_errors) => { return Err(NoSolution); } @@ -88,14 +90,14 @@ impl<'a, 'tcx> At<'a, 'tcx> { } if !needs_normalization(&value, self.param_env.reveal()) { - return Ok(Normalized { value, obligations: vec![] }); + return Ok(Normalized { value, obligations: PredicateObligations::new() }); } let mut normalizer = QueryNormalizer { infcx: self.infcx, cause: self.cause, param_env: self.param_env, - obligations: vec![], + obligations: PredicateObligations::new(), cache: SsoHashMap::new(), anon_depth: 0, universes, @@ -164,7 +166,7 @@ struct QueryNormalizer<'a, 'tcx> { infcx: &'a InferCtxt<'tcx>, cause: &'a ObligationCause<'tcx>, param_env: ty::ParamEnv<'tcx>, - obligations: Vec>, + obligations: PredicateObligations<'tcx>, cache: SsoHashMap, Ty<'tcx>>, anon_depth: usize, universes: Vec>, diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs index a765de92afd..5ae8c87ec02 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs @@ -2,7 +2,7 @@ use std::fmt; use rustc_errors::ErrorGuaranteed; use rustc_infer::infer::canonical::Certainty; -use rustc_infer::traits::PredicateObligation; +use rustc_infer::traits::PredicateObligations; use rustc_middle::traits::query::NoSolution; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::{ParamEnvAnd, TyCtxt}; @@ -103,13 +103,13 @@ pub trait QueryTypeOp<'tcx>: fmt::Debug + Copy + TypeFoldable> + 't ( Self::QueryResponse, Option>>, - Vec>, + PredicateObligations<'tcx>, Certainty, ), NoSolution, > { if let Some(result) = QueryTypeOp::try_fast_path(infcx.tcx, &query_key) { - return Ok((result, None, vec![], Certainty::Proven)); + return Ok((result, None, PredicateObligations::new(), Certainty::Proven)); } let mut canonical_var_values = OriginalQueryValues::default(); diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 20adda6f0de..52048ca79f9 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -12,7 +12,9 @@ use hir::LangItem; use hir::def_id::DefId; use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; use rustc_hir as hir; -use rustc_infer::traits::{Obligation, ObligationCause, PolyTraitObligation, SelectionError}; +use rustc_infer::traits::{ + Obligation, ObligationCause, PolyTraitObligation, PredicateObligations, SelectionError, +}; use rustc_middle::ty::fast_reject::DeepRejectCtxt; use rustc_middle::ty::{self, ToPolyTraitRef, Ty, TypeVisitableExt}; use rustc_middle::{bug, span_bug}; @@ -963,7 +965,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { 0, // We're *intentionally* throwing these away, // since we don't actually use them. - &mut vec![], + &mut PredicateObligations::new(), ) .as_type() .unwrap(); diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 5141e969608..cc5c7532b50 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -24,7 +24,7 @@ use rustc_span::def_id::DefId; use tracing::{debug, instrument}; use super::SelectionCandidate::{self, *}; -use super::{BuiltinImplConditions, SelectionContext}; +use super::{BuiltinImplConditions, PredicateObligations, SelectionContext}; use crate::traits::normalize::{normalize_with_depth, normalize_with_depth_to}; use crate::traits::util::{self, closure_trait_ref_and_return_type}; use crate::traits::{ @@ -85,7 +85,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // No nested obligations or confirmation process. The checks that we do in // candidate assembly are sufficient. - AsyncFnKindHelperCandidate => ImplSource::Builtin(BuiltinImplSource::Misc, vec![]), + AsyncFnKindHelperCandidate => { + ImplSource::Builtin(BuiltinImplSource::Misc, PredicateObligations::new()) + } CoroutineCandidate => { let vtable_coroutine = self.confirm_coroutine_candidate(obligation)?; @@ -121,7 +123,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // This indicates something like `Trait + Send: Send`. In this case, we know that // this holds because that's what the object type is telling us, and there's really // no additional obligations to prove and no types in particular to unify, etc. - ImplSource::Builtin(BuiltinImplSource::Misc, Vec::new()) + ImplSource::Builtin(BuiltinImplSource::Misc, PredicateObligations::new()) } BuiltinUnsizeCandidate => self.confirm_builtin_unsize_candidate(obligation)?, @@ -149,7 +151,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, obligation: &PolyTraitObligation<'tcx>, idx: usize, - ) -> Result>, SelectionError<'tcx>> { + ) -> Result, SelectionError<'tcx>> { let tcx = self.tcx(); let placeholder_trait_predicate = @@ -179,7 +181,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { HigherRankedType, candidate, ); - let mut obligations = Vec::new(); + let mut obligations = PredicateObligations::new(); let candidate = normalize_with_depth_to( self, obligation.param_env, @@ -226,7 +228,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, obligation: &PolyTraitObligation<'tcx>, param: ty::PolyTraitRef<'tcx>, - ) -> Vec> { + ) -> PredicateObligations<'tcx> { debug!(?obligation, ?param, "confirm_param_candidate"); // During evaluation, we already checked that this @@ -249,7 +251,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, obligation: &PolyTraitObligation<'tcx>, has_nested: bool, - ) -> Vec> { + ) -> PredicateObligations<'tcx> { debug!(?obligation, ?has_nested, "confirm_builtin_candidate"); let tcx = self.tcx(); @@ -279,7 +281,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { nested, ) } else { - vec![] + PredicateObligations::new() }; debug!(?obligations); @@ -291,7 +293,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn confirm_transmutability_candidate( &mut self, obligation: &PolyTraitObligation<'tcx>, - ) -> Result>, SelectionError<'tcx>> { + ) -> Result, SelectionError<'tcx>> { use rustc_transmute::{Answer, Assume, Condition}; /// Generate sub-obligations for reference-to-reference transmutations. @@ -301,7 +303,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { (src_lifetime, src_ty, src_mut): (ty::Region<'tcx>, Ty<'tcx>, Mutability), (dst_lifetime, dst_ty, dst_mut): (ty::Region<'tcx>, Ty<'tcx>, Mutability), assume: Assume, - ) -> Vec> { + ) -> PredicateObligations<'tcx> { let make_transmute_obl = |src, dst| { let transmute_trait = obligation.predicate.def_id(); let assume = obligation.predicate.skip_binder().trait_ref.args.const_at(2); @@ -347,7 +349,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // Given a transmutation from `&'a (mut) Src` and `&'dst (mut) Dst`, // it is always the case that `Src` must be transmutable into `Dst`, // and that that `'src` must outlive `'dst`. - let mut obls = vec![make_transmute_obl(src_ty, dst_ty)]; + let mut obls = PredicateObligations::with_capacity(1); + obls.push(make_transmute_obl(src_ty, dst_ty)); if !assume.lifetimes { obls.push(make_outlives_obl(src_lifetime, dst_lifetime)); } @@ -382,7 +385,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation: &PolyTraitObligation<'tcx>, cond: Condition>, assume: Assume, - ) -> Vec> { + ) -> PredicateObligations<'tcx> { match cond { // FIXME(bryangarza): Add separate `IfAny` case, instead of treating as `IfAll` // Not possible until the trait solver supports disjunctions of obligations @@ -424,7 +427,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let fully_flattened = match maybe_transmutable { Answer::No(_) => Err(Unimplemented)?, Answer::If(cond) => flatten_answer_tree(self.tcx(), obligation, cond, assume), - Answer::Yes => vec![], + Answer::Yes => PredicateObligations::new(), }; debug!(?fully_flattened); @@ -439,7 +442,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn confirm_auto_impl_candidate( &mut self, obligation: &PolyTraitObligation<'tcx>, - ) -> Result>, SelectionError<'tcx>> { + ) -> Result, SelectionError<'tcx>> { debug!(?obligation, "confirm_auto_impl_candidate"); let self_ty = obligation.predicate.self_ty().map_bound(|ty| self.infcx.shallow_resolve(ty)); @@ -453,14 +456,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation: &PolyTraitObligation<'tcx>, trait_def_id: DefId, nested: ty::Binder<'tcx, Vec>>, - ) -> Vec> { + ) -> PredicateObligations<'tcx> { debug!(?nested, "vtable_auto_impl"); ensure_sufficient_stack(|| { let cause = obligation.derived_cause(ObligationCauseCode::BuiltinDerived); let poly_trait_ref = obligation.predicate.to_poly_trait_ref(); let trait_ref = self.infcx.enter_forall_and_leak_universe(poly_trait_ref); - let trait_obligations: Vec> = self.impl_or_trait_obligations( + let trait_obligations = self.impl_or_trait_obligations( &cause, obligation.recursion_depth + 1, obligation.param_env, @@ -566,7 +569,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ); let object_trait_ref = object_trait_ref.with_self_ty(self.tcx(), self_ty); - let mut nested = vec![]; + let mut nested = PredicateObligations::new(); let mut supertraits = util::supertraits(tcx, ty::Binder::dummy(object_trait_ref)); let unnormalized_upcast_trait_ref = @@ -706,7 +709,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, obligation: &PolyTraitObligation<'tcx>, fn_host_effect: ty::Const<'tcx>, - ) -> Result>, SelectionError<'tcx>> { + ) -> Result, SelectionError<'tcx>> { debug!(?obligation, "confirm_fn_pointer_candidate"); let placeholder_predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate); let self_ty = self.infcx.shallow_resolve(placeholder_predicate.self_ty()); @@ -750,7 +753,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn confirm_trait_alias_candidate( &mut self, obligation: &PolyTraitObligation<'tcx>, - ) -> Vec> { + ) -> PredicateObligations<'tcx> { debug!(?obligation, "confirm_trait_alias_candidate"); let predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate); @@ -775,7 +778,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn confirm_coroutine_candidate( &mut self, obligation: &PolyTraitObligation<'tcx>, - ) -> Result>, SelectionError<'tcx>> { + ) -> Result, SelectionError<'tcx>> { let placeholder_predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate); let self_ty = self.infcx.shallow_resolve(placeholder_predicate.self_ty()); let ty::Coroutine(coroutine_def_id, args) = *self_ty.kind() else { @@ -805,7 +808,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn confirm_future_candidate( &mut self, obligation: &PolyTraitObligation<'tcx>, - ) -> Result>, SelectionError<'tcx>> { + ) -> Result, SelectionError<'tcx>> { let placeholder_predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate); let self_ty = self.infcx.shallow_resolve(placeholder_predicate.self_ty()); let ty::Coroutine(coroutine_def_id, args) = *self_ty.kind() else { @@ -835,7 +838,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn confirm_iterator_candidate( &mut self, obligation: &PolyTraitObligation<'tcx>, - ) -> Result>, SelectionError<'tcx>> { + ) -> Result, SelectionError<'tcx>> { let placeholder_predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate); let self_ty = self.infcx.shallow_resolve(placeholder_predicate.self_ty()); let ty::Coroutine(coroutine_def_id, args) = *self_ty.kind() else { @@ -865,7 +868,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn confirm_async_iterator_candidate( &mut self, obligation: &PolyTraitObligation<'tcx>, - ) -> Result>, SelectionError<'tcx>> { + ) -> Result, SelectionError<'tcx>> { let placeholder_predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate); let self_ty = self.infcx.shallow_resolve(placeholder_predicate.self_ty()); let ty::Coroutine(coroutine_def_id, args) = *self_ty.kind() else { @@ -896,7 +899,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn confirm_closure_candidate( &mut self, obligation: &PolyTraitObligation<'tcx>, - ) -> Result>, SelectionError<'tcx>> { + ) -> Result, SelectionError<'tcx>> { let placeholder_predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate); let self_ty: Ty<'_> = self.infcx.shallow_resolve(placeholder_predicate.self_ty()); @@ -926,13 +929,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn confirm_async_closure_candidate( &mut self, obligation: &PolyTraitObligation<'tcx>, - ) -> Result>, SelectionError<'tcx>> { + ) -> Result, SelectionError<'tcx>> { let placeholder_predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate); let self_ty = self.infcx.shallow_resolve(placeholder_predicate.self_ty()); let tcx = self.tcx(); - let mut nested = vec![]; + let mut nested = PredicateObligations::new(); let (trait_ref, kind_ty) = match *self_ty.kind() { ty::CoroutineClosure(_, args) => { let args = args.as_coroutine_closure(); @@ -1055,7 +1058,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, obligation: TraitObligation<'tcx>, found_trait_ref: ty::PolyTraitRef<'tcx>, - ) -> Result>, SelectionError<'tcx>> { + ) -> Result, SelectionError<'tcx>> { let found_trait_ref = self.infcx.instantiate_binder_with_fresh_vars( obligation.cause.span, HigherRankedType, @@ -1210,7 +1213,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // words, if the object type is `Foo + Send`, this would create an obligation for // the `Send` check.) // - Projection predicates - let mut nested: Vec<_> = data + let mut nested: PredicateObligations<'_> = data .iter() .map(|predicate| predicate_to_obligation(predicate.with_self_ty(tcx, source))) .collect(); @@ -1254,7 +1257,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let tail_field = def.non_enum_variant().tail(); let tail_field_ty = tcx.type_of(tail_field.did); - let mut nested = vec![]; + let mut nested = PredicateObligations::new(); // Extract `TailField` and `TailField` from `Struct` and `Struct`, // normalizing in the process, since `type_of` returns something directly from @@ -1339,7 +1342,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, obligation: &PolyTraitObligation<'tcx>, impl_def_id: Option, - ) -> Result>, SelectionError<'tcx>> { + ) -> Result, SelectionError<'tcx>> { let Some(host_effect_index) = self.tcx().generics_of(obligation.predicate.def_id()).host_effect_index else { @@ -1353,7 +1356,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let tcx = self.tcx(); let self_ty = obligation.self_ty().map_bound(|ty| self.infcx.shallow_resolve(ty)); - let mut nested = vec![]; + let mut nested = PredicateObligations::new(); let cause = obligation.derived_cause(ObligationCauseCode::BuiltinDerived); // If we have a custom `impl const Drop`, then diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index fba1d1025ca..621babe9104 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -18,7 +18,7 @@ use rustc_infer::infer::BoundRegionConversionTime::{self, HigherRankedType}; use rustc_infer::infer::DefineOpaqueTypes; use rustc_infer::infer::at::ToTrace; use rustc_infer::infer::relate::TypeRelation; -use rustc_infer::traits::TraitObligation; +use rustc_infer::traits::{PredicateObligations, TraitObligation}; use rustc_middle::bug; use rustc_middle::dep_graph::{DepNodeIndex, dep_kinds}; use rustc_middle::mir::interpret::ErrorHandled; @@ -1067,7 +1067,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { && fresh_trait_pred.has_aliases() && fresh_trait_pred.is_global() { - let mut nested_obligations = Vec::new(); + let mut nested_obligations = PredicateObligations::new(); let predicate = normalize_with_depth_to( this, param_env, @@ -1715,7 +1715,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) -> ProjectionMatchesProjection { debug_assert_eq!(obligation.predicate.def_id, env_predicate.projection_def_id()); - let mut nested_obligations = Vec::new(); + let mut nested_obligations = PredicateObligations::new(); let infer_predicate = self.infcx.instantiate_binder_with_fresh_vars( obligation.cause.span, BoundRegionConversionTime::HigherRankedType, @@ -2410,7 +2410,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { recursion_depth: usize, trait_def_id: DefId, types: ty::Binder<'tcx, Vec>>, - ) -> Vec> { + ) -> PredicateObligations<'tcx> { // Because the types were potentially derived from // higher-ranked obligations they may reference late-bound // regions. For example, `for<'a> Foo<&'a i32> : Copy` would @@ -2552,9 +2552,9 @@ impl<'tcx> SelectionContext<'_, 'tcx> { b_data: &'tcx ty::List>, a_region: ty::Region<'tcx>, b_region: ty::Region<'tcx>, - ) -> SelectionResult<'tcx, Vec>> { + ) -> SelectionResult<'tcx, PredicateObligations<'tcx>> { let tcx = self.tcx(); - let mut nested = vec![]; + let mut nested = PredicateObligations::new(); // We may upcast to auto traits that are either explicitly listed in // the object type's bounds, or implied by the principal trait ref's @@ -2705,7 +2705,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { &mut self, obligation: &PolyTraitObligation<'tcx>, where_clause_trait_ref: ty::PolyTraitRef<'tcx>, - ) -> Result>, ()> { + ) -> Result, ()> { self.match_poly_trait_ref(obligation, where_clause_trait_ref) } @@ -2716,7 +2716,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { &mut self, obligation: &PolyTraitObligation<'tcx>, poly_trait_ref: ty::PolyTraitRef<'tcx>, - ) -> Result>, ()> { + ) -> Result, ()> { let predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate); let trait_ref = self.infcx.instantiate_binder_with_fresh_vars( obligation.cause.span, @@ -2797,7 +2797,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { def_id: DefId, // of impl or trait args: GenericArgsRef<'tcx>, // for impl or trait parent_trait_pred: ty::Binder<'tcx, ty::TraitPredicate<'tcx>>, - ) -> Vec> { + ) -> PredicateObligations<'tcx> { let tcx = self.tcx(); // To allow for one-pass evaluation of the nested obligation, @@ -2817,7 +2817,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { let predicates = tcx.predicates_of(def_id); assert_eq!(predicates.parent, None); let predicates = predicates.instantiate_own(tcx, args); - let mut obligations = Vec::with_capacity(predicates.len()); + let mut obligations = PredicateObligations::with_capacity(predicates.len()); for (index, (predicate, span)) in predicates.into_iter().enumerate() { let cause = if tcx.is_lang_item(parent_trait_pred.def_id(), LangItem::CoerceUnsized) { cause.clone() diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index a849cdfe125..07e68e5a3e8 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -2,7 +2,7 @@ use std::iter; use rustc_hir as hir; use rustc_hir::lang_items::LangItem; -use rustc_infer::traits::ObligationCauseCode; +use rustc_infer::traits::{ObligationCauseCode, PredicateObligations}; use rustc_middle::bug; use rustc_middle::ty::{ self, GenericArg, GenericArgKind, GenericArgsRef, Ty, TyCtxt, TypeSuperVisitable, @@ -27,7 +27,7 @@ pub fn obligations<'tcx>( recursion_depth: usize, arg: GenericArg<'tcx>, span: Span, -) -> Option>> { +) -> Option> { // Handle the "livelock" case (see comment above) by bailing out if necessary. let arg = match arg.unpack() { GenericArgKind::Type(ty) => { @@ -61,11 +61,18 @@ pub fn obligations<'tcx>( .into() } // There is nothing we have to do for lifetimes. - GenericArgKind::Lifetime(..) => return Some(Vec::new()), + GenericArgKind::Lifetime(..) => return Some(PredicateObligations::new()), }; - let mut wf = - WfPredicates { infcx, param_env, body_id, span, out: vec![], recursion_depth, item: None }; + let mut wf = WfPredicates { + infcx, + param_env, + body_id, + span, + out: PredicateObligations::new(), + recursion_depth, + item: None, + }; wf.compute(arg); debug!("wf::obligations({:?}, body_id={:?}) = {:?}", arg, body_id, wf.out); @@ -82,7 +89,7 @@ pub fn unnormalized_obligations<'tcx>( infcx: &InferCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, arg: GenericArg<'tcx>, -) -> Option>> { +) -> Option> { debug_assert_eq!(arg, infcx.resolve_vars_if_possible(arg)); // However, if `arg` IS an unresolved inference variable, returns `None`, @@ -93,7 +100,7 @@ pub fn unnormalized_obligations<'tcx>( } if let ty::GenericArgKind::Lifetime(..) = arg.unpack() { - return Some(vec![]); + return Some(PredicateObligations::new()); } let mut wf = WfPredicates { @@ -101,7 +108,7 @@ pub fn unnormalized_obligations<'tcx>( param_env, body_id: CRATE_DEF_ID, span: DUMMY_SP, - out: vec![], + out: PredicateObligations::new(), recursion_depth: 0, item: None, }; @@ -120,13 +127,13 @@ pub fn trait_obligations<'tcx>( trait_pred: ty::TraitPredicate<'tcx>, span: Span, item: &'tcx hir::Item<'tcx>, -) -> Vec> { +) -> PredicateObligations<'tcx> { let mut wf = WfPredicates { infcx, param_env, body_id, span, - out: vec![], + out: PredicateObligations::new(), recursion_depth: 0, item: Some(item), }; @@ -147,13 +154,13 @@ pub fn clause_obligations<'tcx>( body_id: LocalDefId, clause: ty::Clause<'tcx>, span: Span, -) -> Vec> { +) -> PredicateObligations<'tcx> { let mut wf = WfPredicates { infcx, param_env, body_id, span, - out: vec![], + out: PredicateObligations::new(), recursion_depth: 0, item: None, }; @@ -192,7 +199,7 @@ struct WfPredicates<'a, 'tcx> { param_env: ty::ParamEnv<'tcx>, body_id: LocalDefId, span: Span, - out: Vec>, + out: PredicateObligations<'tcx>, recursion_depth: usize, item: Option<&'tcx hir::Item<'tcx>>, } @@ -323,7 +330,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { traits::ObligationCause::new(self.span, self.body_id, code) } - fn normalize(self, infcx: &InferCtxt<'tcx>) -> Vec> { + fn normalize(self, infcx: &InferCtxt<'tcx>) -> PredicateObligations<'tcx> { // Do not normalize `wf` obligations with the new solver. // // The current deep normalization routine with the new solver does not @@ -336,7 +343,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { let cause = self.cause(ObligationCauseCode::WellFormed(None)); let param_env = self.param_env; - let mut obligations = Vec::with_capacity(self.out.len()); + let mut obligations = PredicateObligations::with_capacity(self.out.len()); for mut obligation in self.out { assert!(!obligation.has_escaping_bound_vars()); let mut selcx = traits::SelectionContext::new(infcx); @@ -553,7 +560,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { &mut self, def_id: DefId, args: GenericArgsRef<'tcx>, - ) -> Vec> { + ) -> PredicateObligations<'tcx> { let predicates = self.tcx().predicates_of(def_id); let mut origins = vec![def_id; predicates.predicates.len()]; let mut head = predicates; diff --git a/compiler/rustc_traits/src/normalize_projection_ty.rs b/compiler/rustc_traits/src/normalize_projection_ty.rs index 3102da218db..4c2b7e4769a 100644 --- a/compiler/rustc_traits/src/normalize_projection_ty.rs +++ b/compiler/rustc_traits/src/normalize_projection_ty.rs @@ -1,5 +1,6 @@ use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::infer::canonical::{Canonical, QueryResponse}; +use rustc_infer::traits::PredicateObligations; use rustc_middle::query::Providers; use rustc_middle::ty::{ParamEnvAnd, TyCtxt}; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; @@ -30,7 +31,7 @@ fn normalize_canonicalized_projection_ty<'tcx>( debug_assert!(!ocx.infcx.next_trait_solver()); let selcx = &mut SelectionContext::new(ocx.infcx); let cause = ObligationCause::dummy(); - let mut obligations = vec![]; + let mut obligations = PredicateObligations::new(); let answer = traits::normalize_projection_ty(selcx, param_env, goal, cause, 0, &mut obligations); ocx.register_obligations(obligations); @@ -99,7 +100,7 @@ fn normalize_canonicalized_inherent_projection_ty<'tcx>( |ocx, ParamEnvAnd { param_env, value: goal }| { let selcx = &mut SelectionContext::new(ocx.infcx); let cause = ObligationCause::dummy(); - let mut obligations = vec![]; + let mut obligations = PredicateObligations::new(); let answer = traits::normalize_inherent_projection( selcx, param_env, From 8de8f46f789e5e61a0129fd9a7cf0c942a6301d8 Mon Sep 17 00:00:00 2001 From: GnomedDev Date: Thu, 10 Oct 2024 19:56:21 +0100 Subject: [PATCH 232/357] Swap PredicateObligation to ThinVec --- Cargo.lock | 5 +- .../src/obligation_forest/mod.rs | 3 +- .../src/obligation_forest/tests.rs | 68 ++++++++++--------- compiler/rustc_infer/Cargo.toml | 1 + compiler/rustc_infer/src/traits/mod.rs | 3 +- compiler/rustc_middle/src/traits/mod.rs | 9 +-- compiler/rustc_trait_selection/Cargo.toml | 1 + .../src/solve/fulfill.rs | 4 +- .../src/traits/fulfill.rs | 3 +- compiler/rustc_type_ir/Cargo.toml | 3 +- compiler/rustc_type_ir/src/fold.rs | 7 ++ compiler/rustc_type_ir/src/visit.rs | 8 +++ 12 files changed, 73 insertions(+), 42 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c62c379f70d..501d143890b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "addr2line" @@ -3857,6 +3857,7 @@ dependencies = [ "rustc_target", "rustc_type_ir", "smallvec", + "thin-vec", "tracing", ] @@ -4490,6 +4491,7 @@ dependencies = [ "rustc_transmute", "rustc_type_ir", "smallvec", + "thin-vec", "tracing", ] @@ -4561,6 +4563,7 @@ dependencies = [ "rustc_span", "rustc_type_ir_macros", "smallvec", + "thin-vec", "tracing", ] diff --git a/compiler/rustc_data_structures/src/obligation_forest/mod.rs b/compiler/rustc_data_structures/src/obligation_forest/mod.rs index aca99b9fab1..34a2464972a 100644 --- a/compiler/rustc_data_structures/src/obligation_forest/mod.rs +++ b/compiler/rustc_data_structures/src/obligation_forest/mod.rs @@ -75,6 +75,7 @@ use std::fmt::Debug; use std::hash; use std::marker::PhantomData; +use thin_vec::ThinVec; use tracing::debug; use crate::fx::{FxHashMap, FxHashSet}; @@ -141,7 +142,7 @@ pub trait ObligationProcessor { #[derive(Debug)] pub enum ProcessResult { Unchanged, - Changed(Vec), + Changed(ThinVec), Error(E), } diff --git a/compiler/rustc_data_structures/src/obligation_forest/tests.rs b/compiler/rustc_data_structures/src/obligation_forest/tests.rs index 8391e98ba8b..739ef74e3f7 100644 --- a/compiler/rustc_data_structures/src/obligation_forest/tests.rs +++ b/compiler/rustc_data_structures/src/obligation_forest/tests.rs @@ -1,5 +1,7 @@ use std::fmt; +use thin_vec::thin_vec; + use super::*; impl<'a> super::ForestObligation for &'a str { @@ -101,9 +103,9 @@ fn push_pop() { // |-> A.3 let TestOutcome { completed: ok, errors: err, .. } = forest.process_obligations(&mut C( |obligation| match *obligation { - "A" => ProcessResult::Changed(vec!["A.1", "A.2", "A.3"]), + "A" => ProcessResult::Changed(thin_vec!["A.1", "A.2", "A.3"]), "B" => ProcessResult::Error("B is for broken"), - "C" => ProcessResult::Changed(vec![]), + "C" => ProcessResult::Changed(thin_vec![]), "A.1" | "A.2" | "A.3" => ProcessResult::Unchanged, _ => unreachable!(), }, @@ -123,8 +125,8 @@ fn push_pop() { |obligation| match *obligation { "A.1" => ProcessResult::Unchanged, "A.2" => ProcessResult::Unchanged, - "A.3" => ProcessResult::Changed(vec!["A.3.i"]), - "D" => ProcessResult::Changed(vec!["D.1", "D.2"]), + "A.3" => ProcessResult::Changed(thin_vec!["A.3.i"]), + "D" => ProcessResult::Changed(thin_vec!["D.1", "D.2"]), "A.3.i" | "D.1" | "D.2" => ProcessResult::Unchanged, _ => unreachable!(), }, @@ -139,11 +141,11 @@ fn push_pop() { // |-> D.2 |-> D.2.i let TestOutcome { completed: ok, errors: err, .. } = forest.process_obligations(&mut C( |obligation| match *obligation { - "A.1" => ProcessResult::Changed(vec![]), + "A.1" => ProcessResult::Changed(thin_vec![]), "A.2" => ProcessResult::Error("A is for apple"), - "A.3.i" => ProcessResult::Changed(vec![]), - "D.1" => ProcessResult::Changed(vec!["D.1.i"]), - "D.2" => ProcessResult::Changed(vec!["D.2.i"]), + "A.3.i" => ProcessResult::Changed(thin_vec![]), + "D.1" => ProcessResult::Changed(thin_vec!["D.1.i"]), + "D.2" => ProcessResult::Changed(thin_vec!["D.2.i"]), "D.1.i" | "D.2.i" => ProcessResult::Unchanged, _ => unreachable!(), }, @@ -158,7 +160,7 @@ fn push_pop() { let TestOutcome { completed: ok, errors: err, .. } = forest.process_obligations(&mut C( |obligation| match *obligation { "D.1.i" => ProcessResult::Error("D is for dumb"), - "D.2.i" => ProcessResult::Changed(vec![]), + "D.2.i" => ProcessResult::Changed(thin_vec![]), _ => panic!("unexpected obligation {:?}", obligation), }, |_| {}, @@ -184,10 +186,10 @@ fn success_in_grandchildren() { let TestOutcome { completed: ok, errors: err, .. } = forest.process_obligations(&mut C( |obligation| match *obligation { - "A" => ProcessResult::Changed(vec!["A.1", "A.2", "A.3"]), - "A.1" => ProcessResult::Changed(vec![]), - "A.2" => ProcessResult::Changed(vec!["A.2.i", "A.2.ii"]), - "A.3" => ProcessResult::Changed(vec![]), + "A" => ProcessResult::Changed(thin_vec!["A.1", "A.2", "A.3"]), + "A.1" => ProcessResult::Changed(thin_vec![]), + "A.2" => ProcessResult::Changed(thin_vec!["A.2.i", "A.2.ii"]), + "A.3" => ProcessResult::Changed(thin_vec![]), "A.2.i" | "A.2.ii" => ProcessResult::Unchanged, _ => unreachable!(), }, @@ -201,7 +203,7 @@ fn success_in_grandchildren() { let TestOutcome { completed: ok, errors: err, .. } = forest.process_obligations(&mut C( |obligation| match *obligation { "A.2.i" => ProcessResult::Unchanged, - "A.2.ii" => ProcessResult::Changed(vec![]), + "A.2.ii" => ProcessResult::Changed(thin_vec![]), _ => unreachable!(), }, |_| {}, @@ -211,7 +213,7 @@ fn success_in_grandchildren() { let TestOutcome { completed: ok, errors: err, .. } = forest.process_obligations(&mut C( |obligation| match *obligation { - "A.2.i" => ProcessResult::Changed(vec!["A.2.i.a"]), + "A.2.i" => ProcessResult::Changed(thin_vec!["A.2.i.a"]), "A.2.i.a" => ProcessResult::Unchanged, _ => unreachable!(), }, @@ -222,7 +224,7 @@ fn success_in_grandchildren() { let TestOutcome { completed: ok, errors: err, .. } = forest.process_obligations(&mut C( |obligation| match *obligation { - "A.2.i.a" => ProcessResult::Changed(vec![]), + "A.2.i.a" => ProcessResult::Changed(thin_vec![]), _ => unreachable!(), }, |_| {}, @@ -247,7 +249,7 @@ fn to_errors_no_throw() { forest.register_obligation("A"); let TestOutcome { completed: ok, errors: err, .. } = forest.process_obligations(&mut C( |obligation| match *obligation { - "A" => ProcessResult::Changed(vec!["A.1", "A.2", "A.3"]), + "A" => ProcessResult::Changed(thin_vec!["A.1", "A.2", "A.3"]), "A.1" | "A.2" | "A.3" => ProcessResult::Unchanged, _ => unreachable!(), }, @@ -269,7 +271,7 @@ fn diamond() { forest.register_obligation("A"); let TestOutcome { completed: ok, errors: err, .. } = forest.process_obligations(&mut C( |obligation| match *obligation { - "A" => ProcessResult::Changed(vec!["A.1", "A.2"]), + "A" => ProcessResult::Changed(thin_vec!["A.1", "A.2"]), "A.1" | "A.2" => ProcessResult::Unchanged, _ => unreachable!(), }, @@ -280,8 +282,8 @@ fn diamond() { let TestOutcome { completed: ok, errors: err, .. } = forest.process_obligations(&mut C( |obligation| match *obligation { - "A.1" => ProcessResult::Changed(vec!["D"]), - "A.2" => ProcessResult::Changed(vec!["D"]), + "A.1" => ProcessResult::Changed(thin_vec!["D"]), + "A.2" => ProcessResult::Changed(thin_vec!["D"]), "D" => ProcessResult::Unchanged, _ => unreachable!(), }, @@ -295,7 +297,7 @@ fn diamond() { |obligation| match *obligation { "D" => { d_count += 1; - ProcessResult::Changed(vec![]) + ProcessResult::Changed(thin_vec![]) } _ => unreachable!(), }, @@ -313,7 +315,7 @@ fn diamond() { forest.register_obligation("A'"); let TestOutcome { completed: ok, errors: err, .. } = forest.process_obligations(&mut C( |obligation| match *obligation { - "A'" => ProcessResult::Changed(vec!["A'.1", "A'.2"]), + "A'" => ProcessResult::Changed(thin_vec!["A'.1", "A'.2"]), "A'.1" | "A'.2" => ProcessResult::Unchanged, _ => unreachable!(), }, @@ -324,8 +326,8 @@ fn diamond() { let TestOutcome { completed: ok, errors: err, .. } = forest.process_obligations(&mut C( |obligation| match *obligation { - "A'.1" => ProcessResult::Changed(vec!["D'", "A'"]), - "A'.2" => ProcessResult::Changed(vec!["D'"]), + "A'.1" => ProcessResult::Changed(thin_vec!["D'", "A'"]), + "A'.2" => ProcessResult::Changed(thin_vec!["D'"]), "D'" | "A'" => ProcessResult::Unchanged, _ => unreachable!(), }, @@ -366,7 +368,7 @@ fn done_dependency() { let TestOutcome { completed: ok, errors: err, .. } = forest.process_obligations(&mut C( |obligation| match *obligation { - "A: Sized" | "B: Sized" | "C: Sized" => ProcessResult::Changed(vec![]), + "A: Sized" | "B: Sized" | "C: Sized" => ProcessResult::Changed(thin_vec![]), _ => unreachable!(), }, |_| {}, @@ -379,7 +381,9 @@ fn done_dependency() { forest.register_obligation("(A,B,C): Sized"); let TestOutcome { completed: ok, errors: err, .. } = forest.process_obligations(&mut C( |obligation| match *obligation { - "(A,B,C): Sized" => ProcessResult::Changed(vec!["A: Sized", "B: Sized", "C: Sized"]), + "(A,B,C): Sized" => { + ProcessResult::Changed(thin_vec!["A: Sized", "B: Sized", "C: Sized"]) + } _ => unreachable!(), }, |_| {}, @@ -399,10 +403,10 @@ fn orphan() { let TestOutcome { completed: ok, errors: err, .. } = forest.process_obligations(&mut C( |obligation| match *obligation { - "A" => ProcessResult::Changed(vec!["D", "E"]), + "A" => ProcessResult::Changed(thin_vec!["D", "E"]), "B" => ProcessResult::Unchanged, - "C1" => ProcessResult::Changed(vec![]), - "C2" => ProcessResult::Changed(vec![]), + "C1" => ProcessResult::Changed(thin_vec![]), + "C2" => ProcessResult::Changed(thin_vec![]), "D" | "E" => ProcessResult::Unchanged, _ => unreachable!(), }, @@ -416,7 +420,7 @@ fn orphan() { let TestOutcome { completed: ok, errors: err, .. } = forest.process_obligations(&mut C( |obligation| match *obligation { "D" | "E" => ProcessResult::Unchanged, - "B" => ProcessResult::Changed(vec!["D"]), + "B" => ProcessResult::Changed(thin_vec!["D"]), _ => unreachable!(), }, |_| {}, @@ -459,7 +463,7 @@ fn simultaneous_register_and_error() { let TestOutcome { completed: ok, errors: err, .. } = forest.process_obligations(&mut C( |obligation| match *obligation { "A" => ProcessResult::Error("An error"), - "B" => ProcessResult::Changed(vec!["A"]), + "B" => ProcessResult::Changed(thin_vec!["A"]), _ => unreachable!(), }, |_| {}, @@ -474,7 +478,7 @@ fn simultaneous_register_and_error() { let TestOutcome { completed: ok, errors: err, .. } = forest.process_obligations(&mut C( |obligation| match *obligation { "A" => ProcessResult::Error("An error"), - "B" => ProcessResult::Changed(vec!["A"]), + "B" => ProcessResult::Changed(thin_vec!["A"]), _ => unreachable!(), }, |_| {}, diff --git a/compiler/rustc_infer/Cargo.toml b/compiler/rustc_infer/Cargo.toml index 1f616710200..ef5a1468c87 100644 --- a/compiler/rustc_infer/Cargo.toml +++ b/compiler/rustc_infer/Cargo.toml @@ -21,5 +21,6 @@ rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } rustc_type_ir = { path = "../rustc_type_ir" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } +thin-vec = "0.2.12" tracing = "0.1" # tidy-alphabetical-end diff --git a/compiler/rustc_infer/src/traits/mod.rs b/compiler/rustc_infer/src/traits/mod.rs index 2d02391c57a..ac641ef5652 100644 --- a/compiler/rustc_infer/src/traits/mod.rs +++ b/compiler/rustc_infer/src/traits/mod.rs @@ -17,6 +17,7 @@ use rustc_middle::traits::solve::Certainty; pub use rustc_middle::traits::*; use rustc_middle::ty::{self, Ty, TyCtxt, Upcast}; use rustc_span::Span; +use thin_vec::ThinVec; pub use self::ImplSource::*; pub use self::SelectionError::*; @@ -84,7 +85,7 @@ pub type PredicateObligation<'tcx> = Obligation<'tcx, ty::Predicate<'tcx>>; pub type TraitObligation<'tcx> = Obligation<'tcx, ty::TraitPredicate<'tcx>>; pub type PolyTraitObligation<'tcx> = Obligation<'tcx, ty::PolyTraitPredicate<'tcx>>; -pub type PredicateObligations<'tcx> = Vec>; +pub type PredicateObligations<'tcx> = ThinVec>; impl<'tcx> PredicateObligation<'tcx> { /// Flips the polarity of the inner predicate. diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index caa86da8a85..8ee8b4c4823 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -25,6 +25,7 @@ use rustc_span::{DUMMY_SP, Span}; // FIXME: Remove this import and import via `solve::` pub use rustc_type_ir::solve::{BuiltinImplSource, Reveal}; use smallvec::{SmallVec, smallvec}; +use thin_vec::ThinVec; pub use self::select::{EvaluationCache, EvaluationResult, OverflowError, SelectionCache}; use crate::mir::ConstraintCategory; @@ -625,14 +626,14 @@ pub enum ImplSource<'tcx, N> { /// for some type parameter. The `Vec` represents the /// obligations incurred from normalizing the where-clause (if /// any). - Param(Vec), + Param(ThinVec), /// Successful resolution for a builtin impl. - Builtin(BuiltinImplSource, Vec), + Builtin(BuiltinImplSource, ThinVec), } impl<'tcx, N> ImplSource<'tcx, N> { - pub fn nested_obligations(self) -> Vec { + pub fn nested_obligations(self) -> ThinVec { match self { ImplSource::UserDefined(i) => i.nested, ImplSource::Param(n) | ImplSource::Builtin(_, n) => n, @@ -686,7 +687,7 @@ impl<'tcx, N> ImplSource<'tcx, N> { pub struct ImplSourceUserDefinedData<'tcx, N> { pub impl_def_id: DefId, pub args: GenericArgsRef<'tcx>, - pub nested: Vec, + pub nested: ThinVec, } #[derive(Clone, Debug, PartialEq, Eq, Hash, HashStable, PartialOrd, Ord)] diff --git a/compiler/rustc_trait_selection/Cargo.toml b/compiler/rustc_trait_selection/Cargo.toml index f023a0eb53a..d4bb84838cc 100644 --- a/compiler/rustc_trait_selection/Cargo.toml +++ b/compiler/rustc_trait_selection/Cargo.toml @@ -26,5 +26,6 @@ rustc_target = { path = "../rustc_target" } rustc_transmute = { path = "../rustc_transmute", features = ["rustc"] } rustc_type_ir = { path = "../rustc_type_ir" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } +thin-vec = "0.2" tracing = "0.1" # tidy-alphabetical-end diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index 8ec4427091d..d9dc772eca9 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -2,6 +2,7 @@ use std::marker::PhantomData; use std::mem; use std::ops::ControlFlow; +use rustc_data_structures::thinvec::ExtractIf; use rustc_infer::infer::InferCtxt; use rustc_infer::traits::query::NoSolution; use rustc_infer::traits::solve::{CandidateSource, GoalSource, MaybeCause}; @@ -81,7 +82,8 @@ impl<'tcx> ObligationStorage<'tcx> { // we get all obligations involved in the overflow. We pretty much check: if // we were to do another step of `select_where_possible`, which goals would // change. - self.overflowed.extend(self.pending.extract_if(|o| { + // FIXME: is merged, this can be removed. + self.overflowed.extend(ExtractIf::new(&mut self.pending, |o| { let goal = o.clone().into(); let result = <&SolverDelegate<'tcx>>::from(infcx) .evaluate_root_goal(goal, GenerateProofTree::No) diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 3e3834a11c6..e56f1866970 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -14,6 +14,7 @@ use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::ty::abstract_const::NotConstEvaluatable; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::{self, Binder, Const, GenericArgsRef, TypeVisitableExt}; +use thin_vec::ThinVec; use tracing::{debug, debug_span, instrument}; use super::project::{self, ProjectAndUnifyResult}; @@ -28,7 +29,7 @@ use crate::traits::normalize::normalize_with_depth_to; use crate::traits::project::{PolyProjectionObligation, ProjectionCacheKeyExt as _}; use crate::traits::query::evaluate_obligation::InferCtxtExt; -pub(crate) type PendingPredicateObligations<'tcx> = Vec>; +pub(crate) type PendingPredicateObligations<'tcx> = ThinVec>; impl<'tcx> ForestObligation for PendingPredicateObligation<'tcx> { /// Note that we include both the `ParamEnv` and the `Predicate`, diff --git a/compiler/rustc_type_ir/Cargo.toml b/compiler/rustc_type_ir/Cargo.toml index 98cc116bd00..8d97ec72830 100644 --- a/compiler/rustc_type_ir/Cargo.toml +++ b/compiler/rustc_type_ir/Cargo.toml @@ -17,6 +17,7 @@ rustc_serialize = { path = "../rustc_serialize", optional = true } rustc_span = { path = "../rustc_span", optional = true } rustc_type_ir_macros = { path = "../rustc_type_ir_macros" } smallvec = { version = "1.8.1", default-features = false } +thin-vec = "0.2.12" tracing = "0.1" # tidy-alphabetical-end @@ -30,7 +31,7 @@ nightly = [ "smallvec/may_dangle", "smallvec/union", "rustc_index/nightly", - "rustc_ast_ir/nightly" + "rustc_ast_ir/nightly", ] [lints.rust] diff --git a/compiler/rustc_type_ir/src/fold.rs b/compiler/rustc_type_ir/src/fold.rs index 64ce6fd69e6..8209d6f5fe3 100644 --- a/compiler/rustc_type_ir/src/fold.rs +++ b/compiler/rustc_type_ir/src/fold.rs @@ -48,6 +48,7 @@ use std::mem; use rustc_index::{Idx, IndexVec}; +use thin_vec::ThinVec; use tracing::instrument; use crate::data_structures::Lrc; @@ -322,6 +323,12 @@ impl> TypeFoldable for Vec { } } +impl> TypeFoldable for ThinVec { + fn try_fold_with>(self, folder: &mut F) -> Result { + self.into_iter().map(|t| t.try_fold_with(folder)).collect() + } +} + impl> TypeFoldable for Box<[T]> { fn try_fold_with>(self, folder: &mut F) -> Result { Vec::from(self).try_fold_with(folder).map(Vec::into_boxed_slice) diff --git a/compiler/rustc_type_ir/src/visit.rs b/compiler/rustc_type_ir/src/visit.rs index 0ba7e2bd552..71c3646498b 100644 --- a/compiler/rustc_type_ir/src/visit.rs +++ b/compiler/rustc_type_ir/src/visit.rs @@ -47,6 +47,7 @@ use std::ops::ControlFlow; use rustc_ast_ir::visit::VisitorResult; use rustc_ast_ir::{try_visit, walk_visitable_list}; use rustc_index::{Idx, IndexVec}; +use thin_vec::ThinVec; use crate::data_structures::Lrc; use crate::inherent::*; @@ -184,6 +185,13 @@ impl> TypeVisitable for Vec { } } +impl> TypeVisitable for ThinVec { + fn visit_with>(&self, visitor: &mut V) -> V::Result { + walk_visitable_list!(visitor, self.iter()); + V::Result::output() + } +} + // `TypeFoldable` isn't impl'd for `&[T]`. It doesn't make sense in the general // case, because we can't return a new slice. But note that there are a couple // of trivial impls of `TypeFoldable` for specific slice types elsewhere. From cae29b2fc3a1d3563ebfd3c9649b90902e3a3fa1 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sat, 12 Oct 2024 10:48:43 -0400 Subject: [PATCH 233/357] Import another update --- RELEASES.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/RELEASES.md b/RELEASES.md index 4bdee5f66ed..df61e649a5b 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -7,6 +7,7 @@ Language -------- - [Don't make statement nonterminals match pattern nonterminals](https://github.com/rust-lang/rust/pull/120221/) - [Patterns matching empty types can now be omitted in common cases](https://github.com/rust-lang/rust/pull/122792) +- [Enforce supertrait outlives obligations when using trait impls](https://github.com/rust-lang/rust/pull/124336) - [`addr_of(_mut)!` macros and the newly stabilized `&raw (const|mut)` are now safe to use with all static items](https://github.com/rust-lang/rust/pull/125834) - [size_of_val_raw: for length 0 this is safe to call](https://github.com/rust-lang/rust/pull/126152/) - [Reorder trait bound modifiers *after* `for<...>` binder in trait bounds](https://github.com/rust-lang/rust/pull/127054/) @@ -27,6 +28,8 @@ Compiler -------- - [Promote riscv64gc-unknown-linux-musl to tier 2](https://github.com/rust-lang/rust/pull/122049) - [Promote Mac Catalyst targets `aarch64-apple-ios-macabi` and `x86_64-apple-ios-macabi` to Tier 2, and ship them with rustup](https://github.com/rust-lang/rust/pull/126450) +- [Add tier 3 NuttX based targets for RISC-V and ARM](https://github.com/rust-lang/rust/pull/127755) +- [Add tier 3 powerpc-unknown-linux-muslspe target](https://github.com/rust-lang/rust/pull/127905) - [Improved diagnostics to explain why a pattern is unreachable](https://github.com/rust-lang/rust/pull/128034) - [The compiler now triggers the unreachable code warning properly for async functions that don't return/are `-> !`](https://github.com/rust-lang/rust/pull/128443) - [Promote `aarch64-apple-darwin` to Tier 1](https://github.com/rust-lang/rust/pull/128592) @@ -41,7 +44,7 @@ Libraries - [Implement DoubleEnded and ExactSize for Take and Take](https://github.com/rust-lang/rust/pull/106943/) - [Stabilize Wasm relaxed SIMD](https://github.com/rust-lang/rust/pull/117468/) - [Stabilize const `{integer}::from_str_radix` i.e. `const_int_from_str`](https://github.com/rust-lang/rust/pull/124941/) -- [CloneToUninit impls](https://github.com/rust-lang/rust/pull/126877/) +- [Generalize `{Rc,Arc}::make_mut()` to `Path`, `OsStr`, and `CStr`.](https://github.com/rust-lang/rust/pull/126877) - [impl `Default` for collection iterators that don't already have it](https://github.com/rust-lang/rust/pull/128261/) From 1efffe720d40e0c88efe820da01f99d031a4c4d1 Mon Sep 17 00:00:00 2001 From: DianQK Date: Sat, 12 Oct 2024 22:36:14 +0800 Subject: [PATCH 234/357] `LLVMConstInt` only allows integer types --- compiler/rustc_codegen_llvm/src/common.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs index 4ca19ab2f12..0ced37b53a8 100644 --- a/compiler/rustc_codegen_llvm/src/common.rs +++ b/compiler/rustc_codegen_llvm/src/common.rs @@ -5,6 +5,7 @@ use rustc_abi as abi; use rustc_abi::Primitive::Pointer; use rustc_abi::{AddressSpace, HasDataLayout}; use rustc_ast::Mutability; +use rustc_codegen_ssa::common::TypeKind; use rustc_codegen_ssa::traits::*; use rustc_data_structures::stable_hasher::{Hash128, HashStable, StableHasher}; use rustc_hir::def_id::DefId; @@ -146,6 +147,10 @@ impl<'ll, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> { } fn const_int(&self, t: &'ll Type, i: i64) -> &'ll Value { + debug_assert!( + self.type_kind(t) == TypeKind::Integer, + "only allows integer types in const_int" + ); unsafe { llvm::LLVMConstInt(t, i as u64, True) } } @@ -176,10 +181,18 @@ impl<'ll, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> { } fn const_uint(&self, t: &'ll Type, i: u64) -> &'ll Value { + debug_assert!( + self.type_kind(t) == TypeKind::Integer, + "only allows integer types in const_uint" + ); unsafe { llvm::LLVMConstInt(t, i, False) } } fn const_uint_big(&self, t: &'ll Type, u: u128) -> &'ll Value { + debug_assert!( + self.type_kind(t) == TypeKind::Integer, + "only allows integer types in const_uint_big" + ); unsafe { let words = [u as u64, (u >> 64) as u64]; llvm::LLVMConstIntOfArbitraryPrecision(t, 2, words.as_ptr()) From a0661ec331e87758fd7e4a4b45f460200e8394ec Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 12 Oct 2024 19:48:28 +0200 Subject: [PATCH 235/357] remove const_cow_is_borrowed feature gate --- library/alloc/src/borrow.rs | 2 -- library/alloc/src/lib.rs | 1 - library/alloc/tests/lib.rs | 1 - 3 files changed, 4 deletions(-) diff --git a/library/alloc/src/borrow.rs b/library/alloc/src/borrow.rs index f86face3f90..dbfd2e74abe 100644 --- a/library/alloc/src/borrow.rs +++ b/library/alloc/src/borrow.rs @@ -225,7 +225,6 @@ impl Cow<'_, B> { /// assert!(!bull.is_borrowed()); /// ``` #[unstable(feature = "cow_is_borrowed", issue = "65143")] - #[rustc_const_unstable(feature = "const_cow_is_borrowed", issue = "65143")] pub const fn is_borrowed(&self) -> bool { match *self { Borrowed(_) => true, @@ -248,7 +247,6 @@ impl Cow<'_, B> { /// assert!(!bull.is_owned()); /// ``` #[unstable(feature = "cow_is_borrowed", issue = "65143")] - #[rustc_const_unstable(feature = "const_cow_is_borrowed", issue = "65143")] pub const fn is_owned(&self) -> bool { !self.is_borrowed() } diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index c60c0743c7e..e6b137b4a37 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -108,7 +108,6 @@ #![feature(coerce_unsized)] #![feature(const_align_of_val)] #![feature(const_box)] -#![feature(const_cow_is_borrowed)] #![feature(const_eval_select)] #![feature(const_heap)] #![feature(const_maybe_uninit_write)] diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs index f43143c6cef..36aa312036d 100644 --- a/library/alloc/tests/lib.rs +++ b/library/alloc/tests/lib.rs @@ -4,7 +4,6 @@ #![feature(assert_matches)] #![feature(btree_extract_if)] #![feature(cow_is_borrowed)] -#![feature(const_cow_is_borrowed)] #![feature(const_heap)] #![cfg_attr(bootstrap, feature(const_mut_refs))] #![feature(const_ptr_write)] From 56c0612003f6a86614fe910e504f81fdb23b0994 Mon Sep 17 00:00:00 2001 From: Yoh Deadfall Date: Wed, 9 Oct 2024 22:28:28 +0300 Subject: [PATCH 236/357] Fixed pthread get/set name for macOS --- .../src/shims/unix/freebsd/foreign_items.rs | 1 + .../src/shims/unix/linux/foreign_items.rs | 13 ++++--- .../src/shims/unix/macos/foreign_items.rs | 38 ++++++++++++++++--- .../src/shims/unix/solarish/foreign_items.rs | 4 ++ src/tools/miri/src/shims/unix/thread.rs | 30 +++++++++------ .../tests/pass-dep/libc/pthread-threadname.rs | 28 +++++++++++++- 6 files changed, 91 insertions(+), 23 deletions(-) diff --git a/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs b/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs index e89dd488a2f..4789e2ed3bb 100644 --- a/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs @@ -39,6 +39,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.read_scalar(thread)?, this.read_scalar(name)?, this.read_scalar(len)?, + false, )?; } diff --git a/src/tools/miri/src/shims/unix/linux/foreign_items.rs b/src/tools/miri/src/shims/unix/linux/foreign_items.rs index 3722cc2f3ca..4e8961a54c4 100644 --- a/src/tools/miri/src/shims/unix/linux/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/linux/foreign_items.rs @@ -84,6 +84,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.read_scalar(name)?, TASK_COMM_LEN, )?; + let res = if res { Scalar::from_u32(0) } else { this.eval_libc("ERANGE") }; this.write_scalar(res, dest)?; } "pthread_getname_np" => { @@ -93,14 +94,16 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // In case of glibc, the length of the output buffer must // be not shorter than TASK_COMM_LEN. let len = this.read_scalar(len)?; - let res = if len.to_target_usize(this)? < TASK_COMM_LEN as u64 { - this.eval_libc("ERANGE") - } else { - this.pthread_getname_np( + let res = if len.to_target_usize(this)? >= TASK_COMM_LEN as u64 + && this.pthread_getname_np( this.read_scalar(thread)?, this.read_scalar(name)?, len, - )? + /* truncate*/ false, + )? { + Scalar::from_u32(0) + } else { + this.eval_libc("ERANGE") }; this.write_scalar(res, dest)?; } diff --git a/src/tools/miri/src/shims/unix/macos/foreign_items.rs b/src/tools/miri/src/shims/unix/macos/foreign_items.rs index 2751d379dc0..b199992245c 100644 --- a/src/tools/miri/src/shims/unix/macos/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/macos/foreign_items.rs @@ -164,13 +164,28 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Threading "pthread_setname_np" => { let [name] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + + // The real implementation has logic in two places: + // * in userland at https://github.com/apple-oss-distributions/libpthread/blob/c032e0b076700a0a47db75528a282b8d3a06531a/src/pthread.c#L1178-L1200, + // * in kernel at https://github.com/apple-oss-distributions/xnu/blob/8d741a5de7ff4191bf97d57b9f54c2f6d4a15585/bsd/kern/proc_info.c#L3218-L3227. + // + // The function in libc calls the kernel to validate + // the security policies and the input. If all of the requirements + // are met, then the name is set and 0 is returned. Otherwise, if + // the specified name is lomnger than MAXTHREADNAMESIZE, then + // ENAMETOOLONG is returned. + // + // FIXME: the real implementation maybe returns ESRCH if the thread ID is invalid. let thread = this.pthread_self()?; - let max_len = this.eval_libc("MAXTHREADNAMESIZE").to_target_usize(this)?; - let res = this.pthread_setname_np( + let res = if this.pthread_setname_np( thread, this.read_scalar(name)?, - max_len.try_into().unwrap(), - )?; + this.eval_libc("MAXTHREADNAMESIZE").to_target_usize(this)?.try_into().unwrap(), + )? { + Scalar::from_u32(0) + } else { + this.eval_libc("ENAMETOOLONG") + }; // Contrary to the manpage, `pthread_setname_np` on macOS still // returns an integer indicating success. this.write_scalar(res, dest)?; @@ -178,10 +193,23 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "pthread_getname_np" => { let [thread, name, len] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let res = this.pthread_getname_np( + + // The function's behavior isn't portable between platforms. + // In case of macOS, a truncated name (due to a too small buffer) + // does not lead to an error. + // + // For details, see the implementation at + // https://github.com/apple-oss-distributions/libpthread/blob/c032e0b076700a0a47db75528a282b8d3a06531a/src/pthread.c#L1160-L1175. + // The key part is the strlcpy, which truncates the resulting value, + // but always null terminates (except for zero sized buffers). + // + // FIXME: the real implementation returns ESRCH if the thread ID is invalid. + let res = Scalar::from_u32(0); + this.pthread_getname_np( this.read_scalar(thread)?, this.read_scalar(name)?, this.read_scalar(len)?, + /* truncate */ true, )?; this.write_scalar(res, dest)?; } diff --git a/src/tools/miri/src/shims/unix/solarish/foreign_items.rs b/src/tools/miri/src/shims/unix/solarish/foreign_items.rs index c10098f2733..7f3d0f07bdc 100644 --- a/src/tools/miri/src/shims/unix/solarish/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/solarish/foreign_items.rs @@ -31,16 +31,20 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.read_scalar(name)?, max_len, )?; + let res = if res { Scalar::from_u32(0) } else { this.eval_libc("ERANGE") }; this.write_scalar(res, dest)?; } "pthread_getname_np" => { let [thread, name, len] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + // https://github.com/illumos/illumos-gate/blob/c56822be04b6c157c8b6f2281e47214c3b86f657/usr/src/lib/libc/port/threads/thr.c#L2449-L2480 let res = this.pthread_getname_np( this.read_scalar(thread)?, this.read_scalar(name)?, this.read_scalar(len)?, + /* truncate */ false, )?; + let res = if res { Scalar::from_u32(0) } else { this.eval_libc("ERANGE") }; this.write_scalar(res, dest)?; } diff --git a/src/tools/miri/src/shims/unix/thread.rs b/src/tools/miri/src/shims/unix/thread.rs index 5515524f2f1..7f97afc8e4b 100644 --- a/src/tools/miri/src/shims/unix/thread.rs +++ b/src/tools/miri/src/shims/unix/thread.rs @@ -63,38 +63,41 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { interp_ok(Scalar::from_uint(thread_id.to_u32(), this.libc_ty_layout("pthread_t").size)) } - /// Set the name of the current thread. `max_name_len` is the maximal length of the name - /// including the null terminator. + /// Set the name of the specified thread. If the name including the null terminator + /// is longer than `name_max_len`, then `false` is returned. fn pthread_setname_np( &mut self, thread: Scalar, name: Scalar, - max_name_len: usize, - ) -> InterpResult<'tcx, Scalar> { + name_max_len: usize, + ) -> InterpResult<'tcx, bool> { let this = self.eval_context_mut(); let thread = thread.to_int(this.libc_ty_layout("pthread_t").size)?; let thread = ThreadId::try_from(thread).unwrap(); let name = name.to_pointer(this)?; - let name = this.read_c_str(name)?.to_owned(); // Comparing with `>=` to account for null terminator. - if name.len() >= max_name_len { - return interp_ok(this.eval_libc("ERANGE")); + if name.len() >= name_max_len { + return interp_ok(false); } this.set_thread_name(thread, name); - interp_ok(Scalar::from_u32(0)) + interp_ok(true) } + /// Get the name of the specified thread. If the thread name doesn't fit + /// the buffer, then if `truncate` is set the truncated name is written out, + /// otherwise `false` is returned. fn pthread_getname_np( &mut self, thread: Scalar, name_out: Scalar, len: Scalar, - ) -> InterpResult<'tcx, Scalar> { + truncate: bool, + ) -> InterpResult<'tcx, bool> { let this = self.eval_context_mut(); let thread = thread.to_int(this.libc_ty_layout("pthread_t").size)?; @@ -104,9 +107,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // FIXME: we should use the program name if the thread name is not set let name = this.get_thread_name(thread).unwrap_or(b"").to_owned(); - let (success, _written) = this.write_c_str(&name, name_out, len)?; + let name = match truncate { + true => &name[..name.len().min(len.try_into().unwrap_or(usize::MAX).saturating_sub(1))], + false => &name, + }; - interp_ok(if success { Scalar::from_u32(0) } else { this.eval_libc("ERANGE") }) + let (success, _written) = this.write_c_str(name, name_out, len)?; + + interp_ok(success) } fn sched_yield(&mut self) -> InterpResult<'tcx, ()> { diff --git a/src/tools/miri/tests/pass-dep/libc/pthread-threadname.rs b/src/tools/miri/tests/pass-dep/libc/pthread-threadname.rs index a2cc7bfbe46..d0cd6e8d385 100644 --- a/src/tools/miri/tests/pass-dep/libc/pthread-threadname.rs +++ b/src/tools/miri/tests/pass-dep/libc/pthread-threadname.rs @@ -74,6 +74,26 @@ fn main() { // large enough for the thread name. #[cfg(target_os = "linux")] assert_eq!(get_thread_name(&mut buf[..15]), libc::ERANGE); + + // Solaris compatible implementations return an error, + // if the buffer is shorter than the thread name. + #[cfg(any(target_os = "illumos", target_os = "solaris"))] + assert_eq!(get_thread_name(&mut buf[..4]), libc::ERANGE); + + // For libc implementation for macOS it's not an error + // for a buffer being too short for the thread name. + #[cfg(target_os = "macos")] + { + // Ensure that a zero sized buffer returns no error. + assert_eq!(get_thread_name(&mut buf[..0]), 0); + + // Ensure that a shorter tnan required buffer still returns no error, + // and gives a prefix of the thread name. + assert_eq!(get_thread_name(&mut buf[..4]), 0); + let cstr = CStr::from_bytes_until_nul(&buf).unwrap(); + assert_eq!(cstr.to_bytes_with_nul().len(), 4); + assert!(short_name.as_bytes().starts_with(cstr.to_bytes())); + } }) .unwrap() .join() @@ -105,8 +125,12 @@ fn main() { // But with a too long name it should fail (except on FreeBSD where the // function has no return, hence cannot indicate failure). - #[cfg(not(target_os = "freebsd"))] - assert_ne!(set_thread_name(&CString::new(long_name).unwrap()), 0); + // On macOS, the error code is different. + #[cfg(not(any(target_os = "freebsd", target_os = "macos")))] + assert_eq!(set_thread_name(&CString::new(long_name).unwrap()), libc::ERANGE); + + #[cfg(target_os = "macos")] + assert_eq!(set_thread_name(&CString::new(long_name).unwrap()), libc::ENAMETOOLONG); }) .unwrap() .join() From a495a79db95c15071eb787359feaf71424321dd0 Mon Sep 17 00:00:00 2001 From: Yoh Deadfall Date: Fri, 11 Oct 2024 18:31:34 +0300 Subject: [PATCH 237/357] Fixed get thread name behavior for FreeBSD --- .../miri/src/shims/unix/freebsd/foreign_items.rs | 7 +++++-- .../miri/tests/pass-dep/libc/pthread-threadname.rs | 11 +++++------ 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs b/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs index 4789e2ed3bb..5204e57705a 100644 --- a/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs @@ -34,12 +34,15 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "pthread_get_name_np" => { let [thread, name, len] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - // FreeBSD's pthread_get_name_np does not return anything. + // FreeBSD's pthread_get_name_np does not return anything + // and uses strlcpy, which truncates the resulting value, + // but always adds a null terminator (except for zero-sized buffers). + // https://github.com/freebsd/freebsd-src/blob/c2d93a803acef634bd0eede6673aeea59e90c277/lib/libthr/thread/thr_info.c#L119-L144 this.pthread_getname_np( this.read_scalar(thread)?, this.read_scalar(name)?, this.read_scalar(len)?, - false, + /* truncate */ true, )?; } diff --git a/src/tools/miri/tests/pass-dep/libc/pthread-threadname.rs b/src/tools/miri/tests/pass-dep/libc/pthread-threadname.rs index d0cd6e8d385..74b15466202 100644 --- a/src/tools/miri/tests/pass-dep/libc/pthread-threadname.rs +++ b/src/tools/miri/tests/pass-dep/libc/pthread-threadname.rs @@ -79,10 +79,9 @@ fn main() { // if the buffer is shorter than the thread name. #[cfg(any(target_os = "illumos", target_os = "solaris"))] assert_eq!(get_thread_name(&mut buf[..4]), libc::ERANGE); - - // For libc implementation for macOS it's not an error - // for a buffer being too short for the thread name. - #[cfg(target_os = "macos")] + // On macOS and FreeBSD it's not an error for the buffer to be + // too short for the thread name -- they truncate instead. + #[cfg(any(target_os = "freebsd", target_os = "macos"))] { // Ensure that a zero sized buffer returns no error. assert_eq!(get_thread_name(&mut buf[..0]), 0); @@ -123,8 +122,8 @@ fn main() { // Also test directly calling pthread_setname to check its return value. assert_eq!(set_thread_name(&cstr), 0); - // But with a too long name it should fail (except on FreeBSD where the - // function has no return, hence cannot indicate failure). + // But with a too long name it should fail (except on FreeBSD where + // names of arbitrary size seem to be supported). // On macOS, the error code is different. #[cfg(not(any(target_os = "freebsd", target_os = "macos")))] assert_eq!(set_thread_name(&CString::new(long_name).unwrap()), libc::ERANGE); From 276d112d664ec7b584ce3768accb91c702552513 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sat, 12 Oct 2024 15:20:06 -0400 Subject: [PATCH 238/357] Add stabilized APIs --- RELEASES.md | 86 +++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 81 insertions(+), 5 deletions(-) diff --git a/RELEASES.md b/RELEASES.md index df61e649a5b..79881c46bde 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -41,18 +41,94 @@ Compiler Libraries --------- -- [Implement DoubleEnded and ExactSize for Take and Take](https://github.com/rust-lang/rust/pull/106943/) -- [Stabilize Wasm relaxed SIMD](https://github.com/rust-lang/rust/pull/117468/) -- [Stabilize const `{integer}::from_str_radix` i.e. `const_int_from_str`](https://github.com/rust-lang/rust/pull/124941/) - [Generalize `{Rc,Arc}::make_mut()` to `Path`, `OsStr`, and `CStr`.](https://github.com/rust-lang/rust/pull/126877) -- [impl `Default` for collection iterators that don't already have it](https://github.com/rust-lang/rust/pull/128261/) - Stabilized APIs --------------- +- [`std::thread::Builder::spawn_unchecked`](https://doc.rust-lang.org/stable/std/thread/struct.Builder.html#method.spawn_unchecked) +- [`std::str::CharIndices::offset`](https://doc.rust-lang.org/nightly/std/str/struct.CharIndices.html#method.offset) +- [`std::option::Option::is_none_or`](https://doc.rust-lang.org/nightly/std/option/enum.Option.html#method.is_none_or) +- [`[T]::is_sorted`](https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.is_sorted) +- [`[T]::is_sorted_by`](https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.is_sorted_by) +- [`[T]::is_sorted_by_key`](https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.is_sorted_by_key) +- [`Iterator::is_sorted`](https://doc.rust-lang.org/nightly/std/iter/trait.Iterator.html#method.is_sorted) +- [`Iterator::is_sorted_by`](https://doc.rust-lang.org/nightly/std/iter/trait.Iterator.html#method.is_sorted_by) +- [`Iterator::is_sorted_by_key`](https://doc.rust-lang.org/nightly/std/iter/trait.Iterator.html#method.is_sorted_by_key) +- [`std::future::Ready::into_inner`](https://doc.rust-lang.org/nightly/std/future/struct.Ready.html#method.into_inner) +- [`std::iter::repeat_n`](https://doc.rust-lang.org/nightly/std/iter/fn.repeat_n.html) +- [`impl DoubleEndedIterator for Take>`](https://doc.rust-lang.org/nightly/std/iter/struct.Take.html#impl-DoubleEndedIterator-for-Take%3CRepeat%3CT%3E%3E) +- [`impl ExactSizeIterator for Take>`](https://doc.rust-lang.org/nightly/std/iter/struct.Take.html#impl-ExactSizeIterator-for-Take%3CRepeat%3CT%3E%3E) +- [`impl ExactSizeIterator for Take>`](https://doc.rust-lang.org/nightly/std/iter/struct.Take.html#impl-ExactSizeIterator-for-Take%3CRepeatWith%3CF%3E%3E) +- [`impl Default for std::collections::binary_heap::Iter`](https://doc.rust-lang.org/nightly/std/collections/binary_heap/struct.Iter.html#impl-Default-for-Iter%3C'_,+T%3E) +- [`impl Default for std::collections::btree_map::RangeMut`](https://doc.rust-lang.org/nightly/std/collections/btree_map/struct.RangeMut.html#impl-Default-for-RangeMut%3C'_,+K,+V%3E) +- [`impl Default for std::collections::btree_map::ValuesMut`](https://doc.rust-lang.org/nightly/std/collections/btree_map/struct.ValuesMut.html#impl-Default-for-ValuesMut%3C'_,+K,+V%3E) +- [`impl Default for std::collections::vec_deque::Iter`](https://doc.rust-lang.org/nightly/std/collections/vec_deque/struct.Iter.html#impl-Default-for-Iter%3C'_,+T%3E) +- [`impl Default for std::collections::vec_deque::IterMut`](https://doc.rust-lang.org/nightly/std/collections/vec_deque/struct.IterMut.html#impl-Default-for-IterMut%3C'_,+T%3E) +- [`Rc::new_uninit`](https://doc.rust-lang.org/nightly/std/rc/struct.Rc.html#method.new_uninit) +- [`Rc::assume_init`](https://doc.rust-lang.org/nightly/std/rc/struct.Rc.html#method.assume_init) +- [`Rc<[T]>::new_uninit_slice`](https://doc.rust-lang.org/nightly/std/rc/struct.Rc.html#method.new_uninit_slice) +- [`Rc<[MaybeUninit]>::assume_init`](https://doc.rust-lang.org/nightly/std/rc/struct.Rc.html#method.assume_init-1) +- [`Arc::new_uninit`](https://doc.rust-lang.org/nightly/std/sync/struct.Arc.html#method.new_uninit) +- [`Arc::assume_init`](https://doc.rust-lang.org/nightly/std/sync/struct.Arc.html#method.assume_init) +- [`Arc<[T]>::new_uninit_slice`](https://doc.rust-lang.org/nightly/std/sync/struct.Arc.html#method.new_uninit_slice) +- [`Arc<[MaybeUninit]>::assume_init`](https://doc.rust-lang.org/nightly/std/sync/struct.Arc.html#method.assume_init-1) +- [`Box::new_uninit`](https://doc.rust-lang.org/nightly/std/boxed/struct.Box.html#method.new_uninit) +- [`Box::assume_init`](https://doc.rust-lang.org/nightly/std/boxed/struct.Box.html#method.assume_init) +- [`Box<[T]>::new_uninit_slice`](https://doc.rust-lang.org/nightly/std/boxed/struct.Box.html#method.new_uninit_slice) +- [`Box<[MaybeUninit]>::assume_init`](https://doc.rust-lang.org/nightly/std/boxed/struct.Box.html#method.assume_init-1) +- [`core::arch::x86_64::_bextri_u64`](https://doc.rust-lang.org/stable/core/arch/x86_64/fn._bextri_u64.html) +- [`core::arch::x86_64::_bextri_u32`](https://doc.rust-lang.org/stable/core/arch/x86_64/fn._bextri_u32.html) +- [`core::arch::x86::_mm_broadcastsi128_si256`](https://doc.rust-lang.org/stable/core/arch/x86/fn._mm_broadcastsi128_si256.html) +- [`core::arch::x86::_mm256_stream_load_si256`](https://doc.rust-lang.org/stable/core/arch/x86/fn._mm256_stream_load_si256.html) +- [`core::arch::x86::_tzcnt_u16`](https://doc.rust-lang.org/stable/core/arch/x86/fn._tzcnt_u16.html) +- [`core::arch::x86::_mm_extracti_si64`](https://doc.rust-lang.org/stable/core/arch/x86/fn._mm_extracti_si64.html) +- [`core::arch::x86::_mm_inserti_si64`](https://doc.rust-lang.org/stable/core/arch/x86/fn._mm_inserti_si64.html) +- [`core::arch::x86::_mm_storeu_si16`](https://doc.rust-lang.org/stable/core/arch/x86/fn._mm_storeu_si16.html) +- [`core::arch::x86::_mm_storeu_si32`](https://doc.rust-lang.org/stable/core/arch/x86/fn._mm_storeu_si32.html) +- [`core::arch::x86::_mm_storeu_si64`](https://doc.rust-lang.org/stable/core/arch/x86/fn._mm_storeu_si64.html) +- [`core::arch::x86::_mm_loadu_si16`](https://doc.rust-lang.org/stable/core/arch/x86/fn._mm_loadu_si16.html) +- [`core::arch::x86::_mm_loadu_si32`](https://doc.rust-lang.org/stable/core/arch/x86/fn._mm_loadu_si32.html) +- [`core::arch::wasm32::u8x16_relaxed_swizzle`](https://doc.rust-lang.org/nightly/core/arch/wasm32/fn.u8x16_relaxed_swizzle.html) +- [`core::arch::wasm32::i8x16_relaxed_swizzle`](https://doc.rust-lang.org/nightly/core/arch/wasm32/fn.i8x16_relaxed_swizzle.html) +- [`core::arch::wasm32::i32x4_relaxed_trunc_f32x4`](https://doc.rust-lang.org/nightly/core/arch/wasm32/fn.i32x4_relaxed_trunc_f32x4.html) +- [`core::arch::wasm32::u32x4_relaxed_trunc_f32x4`](https://doc.rust-lang.org/nightly/core/arch/wasm32/fn.u32x4_relaxed_trunc_f32x4.html) +- [`core::arch::wasm32::i32x4_relaxed_trunc_f64x2_zero`](https://doc.rust-lang.org/nightly/core/arch/wasm32/fn.i32x4_relaxed_trunc_f64x2_zero.html) +- [`core::arch::wasm32::u32x4_relaxed_trunc_f64x2_zero`](https://doc.rust-lang.org/nightly/core/arch/wasm32/fn.u32x4_relaxed_trunc_f64x2_zero.html) +- [`core::arch::wasm32::f32x4_relaxed_madd`](https://doc.rust-lang.org/nightly/core/arch/wasm32/fn.f32x4_relaxed_madd.html) +- [`core::arch::wasm32::f32x4_relaxed_nmadd`](https://doc.rust-lang.org/nightly/core/arch/wasm32/fn.f32x4_relaxed_nmadd.html) +- [`core::arch::wasm32::f64x2_relaxed_madd`](https://doc.rust-lang.org/nightly/core/arch/wasm32/fn.f64x2_relaxed_madd.html) +- [`core::arch::wasm32::f64x2_relaxed_nmadd`](https://doc.rust-lang.org/nightly/core/arch/wasm32/fn.f64x2_relaxed_nmadd.html) +- [`core::arch::wasm32::i8x16_relaxed_laneselect`](https://doc.rust-lang.org/nightly/core/arch/wasm32/fn.i8x16_relaxed_laneselect.html) +- [`core::arch::wasm32::u8x16_relaxed_laneselect`](https://doc.rust-lang.org/nightly/core/arch/wasm32/fn.u8x16_relaxed_laneselect.html) +- [`core::arch::wasm32::i16x8_relaxed_laneselect`](https://doc.rust-lang.org/nightly/core/arch/wasm32/fn.i16x8_relaxed_laneselect.html) +- [`core::arch::wasm32::u16x8_relaxed_laneselect`](https://doc.rust-lang.org/nightly/core/arch/wasm32/fn.u16x8_relaxed_laneselect.html) +- [`core::arch::wasm32::i32x4_relaxed_laneselect`](https://doc.rust-lang.org/nightly/core/arch/wasm32/fn.i32x4_relaxed_laneselect.html) +- [`core::arch::wasm32::u32x4_relaxed_laneselect`](https://doc.rust-lang.org/nightly/core/arch/wasm32/fn.u32x4_relaxed_laneselect.html) +- [`core::arch::wasm32::i64x2_relaxed_laneselect`](https://doc.rust-lang.org/nightly/core/arch/wasm32/fn.i64x2_relaxed_laneselect.html) +- [`core::arch::wasm32::u64x2_relaxed_laneselect`](https://doc.rust-lang.org/nightly/core/arch/wasm32/fn.u64x2_relaxed_laneselect.html) +- [`core::arch::wasm32::f32x4_relaxed_min`](https://doc.rust-lang.org/nightly/core/arch/wasm32/fn.f32x4_relaxed_min.html) +- [`core::arch::wasm32::f32x4_relaxed_max`](https://doc.rust-lang.org/nightly/core/arch/wasm32/fn.f32x4_relaxed_max.html) +- [`core::arch::wasm32::f64x2_relaxed_min`](https://doc.rust-lang.org/nightly/core/arch/wasm32/fn.f64x2_relaxed_min.html) +- [`core::arch::wasm32::f64x2_relaxed_max`](https://doc.rust-lang.org/nightly/core/arch/wasm32/fn.f64x2_relaxed_max.html) +- [`core::arch::wasm32::i16x8_relaxed_q15mulr`](https://doc.rust-lang.org/nightly/core/arch/wasm32/fn.i16x8_relaxed_q15mulr.html) +- [`core::arch::wasm32::u16x8_relaxed_q15mulr`](https://doc.rust-lang.org/nightly/core/arch/wasm32/fn.u16x8_relaxed_q15mulr.html) +- [`core::arch::wasm32::i16x8_relaxed_dot_i8x16_i7x16`](https://doc.rust-lang.org/nightly/core/arch/wasm32/fn.i16x8_relaxed_dot_i8x16_i7x16.html) +- [`core::arch::wasm32::u16x8_relaxed_dot_i8x16_i7x16`](https://doc.rust-lang.org/nightly/core/arch/wasm32/fn.u16x8_relaxed_dot_i8x16_i7x16.html) +- [`core::arch::wasm32::i32x4_relaxed_dot_i8x16_i7x16_add`](https://doc.rust-lang.org/nightly/core/arch/wasm32/fn.i32x4_relaxed_dot_i8x16_i7x16_add.html) +- [`core::arch::wasm32::u32x4_relaxed_dot_i8x16_i7x16_add`](https://doc.rust-lang.org/nightly/core/arch/wasm32/fn.u32x4_relaxed_dot_i8x16_i7x16_add.html) + +These APIs are now stable in const contexts: + +- [`std::task::Waker::from_raw`](https://doc.rust-lang.org/nightly/std/task/struct.Waker.html#method.from_raw) +- [`std::task::Waker::waker`](https://doc.rust-lang.org/nightly/std/task/struct.Waker.html#method.from_raw) +- [`std::task::Context::from_waker`](https://doc.rust-lang.org/nightly/std/task/struct.Context.html#method.from_waker) +- [`std::task::Context::waker`](https://doc.rust-lang.org/nightly/std/task/struct.Context.html#method.waker) +- [`$integer::from_str_radix`](https://doc.rust-lang.org/nightly/std/primitive.u32.html#method.from_str_radix) +- [`std::num::ParseIntError::kind`](https://doc.rust-lang.org/nightly/std/num/struct.ParseIntError.html#method.kind) + Cargo From 5b2985f8df7cfd6497cd7ea60e3ea4b129cb0f2f Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sat, 12 Oct 2024 15:20:58 -0400 Subject: [PATCH 239/357] Add explicit link to PR --- RELEASES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASES.md b/RELEASES.md index 79881c46bde..1213a596024 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -140,7 +140,7 @@ Cargo Compatibility Notes ------------------- - We now [disallow setting some built-in cfgs via the command-line](https://github.com/rust-lang/rust/pull/126158) with the newly added [`explicit_builtin_cfgs_in_flags`](https://doc.rust-lang.org/rustc/lints/listing/deny-by-default.html#explicit-builtin-cfgs-in-flags) lint in order to prevent incoherent state, eg. `windows` cfg active but target is Linux based. The appropriate [`rustc` flag](https://doc.rust-lang.org/rustc/command-line-arguments.html) should be used instead. -- The standard library has a new implementation of `binary_search` which is significantly improves performance (#128254). However when a sorted slice has multiple values which compare equal, the new implementation may select a different value among the equal ones than the old implementation. +- The standard library has a new implementation of `binary_search` which is significantly improves performance ([#128254](https://github.com/rust-lang/rust/pull/128254)). However when a sorted slice has multiple values which compare equal, the new implementation may select a different value among the equal ones than the old implementation. - [illumos/Solaris now sets `MSG_NOSIGNAL` when writing to sockets](https://github.com/rust-lang/rust/pull/128259). This avoids killing the process with SIGPIPE when writing to a closed socket, which matches the existing behavior on other UNIX targets. - [Removes a problematic hack that always passed the --whole-archive linker flag for tests, which may cause linker errors for code accidentally relying on it.](https://github.com/rust-lang/rust/pull/128400) - The WebAssembly target features `multivalue` and `reference-types` are now From 4bc21e318cc26f688468188b88758202071b0a19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sat, 12 Oct 2024 22:07:46 +0200 Subject: [PATCH 240/357] remove a couple of redundant String to String conversion --- compiler/rustc_borrowck/src/diagnostics/move_errors.rs | 2 +- compiler/rustc_codegen_llvm/src/asm.rs | 2 +- compiler/rustc_middle/src/ty/diagnostics.rs | 2 +- compiler/rustc_session/src/utils.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs index 98417e8c7a3..3871816777c 100644 --- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs @@ -706,7 +706,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { suggestions.push(( pat_span, format!("consider removing the {to_remove}"), - suggestion.to_string(), + suggestion, )); } } diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index 82ca3f519f7..298cac2fd6e 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -154,7 +154,7 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { // We prefer the latter because it matches the behavior of // Clang. if late && matches!(reg, InlineAsmRegOrRegClass::Reg(_)) { - constraints.push(reg_to_llvm(reg, Some(&in_value.layout)).to_string()); + constraints.push(reg_to_llvm(reg, Some(&in_value.layout))); } else { constraints.push(format!("{}", op_idx[&idx])); } diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index 751f0c71eb4..354ca746b46 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -325,7 +325,7 @@ pub fn suggest_constraining_type_params<'a>( let suggestion = if span_to_replace.is_some() { constraint.clone() } else if constraint.starts_with('<') { - constraint.to_string() + constraint.clone() } else if bound_list_non_empty { format!(" + {constraint}") } else { diff --git a/compiler/rustc_session/src/utils.rs b/compiler/rustc_session/src/utils.rs index 37528a4425f..9182789cf02 100644 --- a/compiler/rustc_session/src/utils.rs +++ b/compiler/rustc_session/src/utils.rs @@ -137,7 +137,7 @@ pub fn extra_compiler_flags() -> Option<(Vec, bool)> { let content = if arg.len() == a.len() { // A space-separated option, like `-C incremental=foo` or `--crate-type rlib` match args.next() { - Some(arg) => arg.to_string(), + Some(arg) => arg, None => continue, } } else if arg.get(a.len()..a.len() + 1) == Some("=") { From 19f6c17df486c5f70c1000ecada39c62b9c93550 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Tue, 1 Oct 2024 17:11:48 -0400 Subject: [PATCH 241/357] Stabilize `const_option` This makes the following API stable in const contexts: impl Option { pub const fn as_mut(&mut self) -> Option<&mut T>; pub const fn expect(self, msg: &str) -> T; pub const fn unwrap(self) -> T; pub const unsafe fn unwrap_unchecked(self) -> T; pub const fn take(&mut self) -> Option; pub const fn replace(&mut self, value: T) -> Option; } impl Option<&T> { pub const fn copied(self) -> Option where T: Copy; } impl Option<&mut T> { pub const fn copied(self) -> Option where T: Copy; } impl Option> { pub const fn transpose(self) -> Result, E> } impl Option> { pub const fn flatten(self) -> Option; } The following functions make use of the unstable `const_precise_live_drops` feature: - `expect` - `unwrap` - `unwrap_unchecked` - `transpose` - `flatten` Fixes: --- compiler/rustc_middle/src/lib.rs | 1 - compiler/rustc_serialize/src/lib.rs | 1 - library/alloc/src/lib.rs | 1 - library/core/src/array/ascii.rs | 1 - library/core/src/lib.rs | 1 - library/core/src/option.rs | 30 ++++++++++++------- library/core/src/ptr/non_null.rs | 2 -- library/core/src/time.rs | 1 - library/core/tests/lib.rs | 1 - .../clippy/tests/ui/doc/doc-fixable.fixed | 2 +- src/tools/clippy/tests/ui/doc/doc-fixable.rs | 2 +- src/tools/miri/src/lib.rs | 1 - tests/ui/consts/const-unwrap.rs | 10 +++++-- tests/ui/consts/const-unwrap.stderr | 12 ++++++-- 14 files changed, 37 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index 70e61df1ab4..e9b73d25ba2 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -37,7 +37,6 @@ #![feature(box_as_ptr)] #![feature(box_patterns)] #![feature(closure_track_caller)] -#![feature(const_option)] #![feature(const_type_name)] #![feature(core_intrinsics)] #![feature(coroutines)] diff --git a/compiler/rustc_serialize/src/lib.rs b/compiler/rustc_serialize/src/lib.rs index b7977a848ce..47f72298e22 100644 --- a/compiler/rustc_serialize/src/lib.rs +++ b/compiler/rustc_serialize/src/lib.rs @@ -10,7 +10,6 @@ test(attr(allow(unused_variables), deny(warnings))) )] #![doc(rust_logo)] -#![feature(const_option)] #![feature(core_intrinsics)] #![feature(min_specialization)] #![feature(never_type)] diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 1d7b7a03454..ec6ffa7a105 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -112,7 +112,6 @@ #![feature(const_eval_select)] #![feature(const_heap)] #![feature(const_maybe_uninit_write)] -#![feature(const_option)] #![feature(const_pin)] #![feature(const_size_of_val)] #![feature(const_vec_string_slice)] diff --git a/library/core/src/array/ascii.rs b/library/core/src/array/ascii.rs index 05797b042ee..e2faef855bc 100644 --- a/library/core/src/array/ascii.rs +++ b/library/core/src/array/ascii.rs @@ -9,7 +9,6 @@ impl [u8; N] { /// /// ``` /// #![feature(ascii_char)] - /// #![feature(const_option)] /// /// const HEX_DIGITS: [std::ascii::Char; 16] = /// *b"0123456789abcdef".as_ascii().unwrap(); diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 61fe024300e..726aa209fdf 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -131,7 +131,6 @@ #![feature(const_maybe_uninit_assume_init)] #![feature(const_nonnull_new)] #![feature(const_num_midpoint)] -#![feature(const_option)] #![feature(const_option_ext)] #![feature(const_pin)] #![feature(const_pointer_is_aligned)] diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 154e52e288b..84ccb7a1f66 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -723,7 +723,8 @@ impl Option { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_option", issue = "67441")] + #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] + #[rustc_const_stable(feature = "const_option", since = "CURRENT_RUSTC_VERSION")] pub const fn as_mut(&mut self) -> Option<&mut T> { match *self { Some(ref mut x) => Some(x), @@ -924,7 +925,8 @@ impl Option { #[track_caller] #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "option_expect")] - #[rustc_const_unstable(feature = "const_option", issue = "67441")] + #[rustc_allow_const_fn_unstable(const_precise_live_drops)] + #[rustc_const_stable(feature = "const_option", since = "CURRENT_RUSTC_VERSION")] pub const fn expect(self, msg: &str) -> T { match self { Some(val) => val, @@ -962,7 +964,8 @@ impl Option { #[track_caller] #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "option_unwrap")] - #[rustc_const_unstable(feature = "const_option", issue = "67441")] + #[rustc_allow_const_fn_unstable(const_precise_live_drops)] + #[rustc_const_stable(feature = "const_option", since = "CURRENT_RUSTC_VERSION")] pub const fn unwrap(self) -> T { match self { Some(val) => val, @@ -1069,7 +1072,8 @@ impl Option { #[inline] #[track_caller] #[stable(feature = "option_result_unwrap_unchecked", since = "1.58.0")] - #[rustc_const_unstable(feature = "const_option", issue = "67441")] + #[rustc_allow_const_fn_unstable(const_precise_live_drops)] + #[rustc_const_stable(feature = "const_option", since = "CURRENT_RUSTC_VERSION")] pub const unsafe fn unwrap_unchecked(self) -> T { match self { Some(val) => val, @@ -1712,7 +1716,8 @@ impl Option { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_option", issue = "67441")] + #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] + #[rustc_const_stable(feature = "const_option", since = "CURRENT_RUSTC_VERSION")] pub const fn take(&mut self) -> Option { // FIXME(const-hack) replace `mem::replace` by `mem::take` when the latter is const ready mem::replace(self, None) @@ -1769,8 +1774,9 @@ impl Option { /// assert_eq!(old, None); /// ``` #[inline] - #[rustc_const_unstable(feature = "const_option", issue = "67441")] #[stable(feature = "option_replace", since = "1.31.0")] + #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] + #[rustc_const_stable(feature = "const_option", since = "CURRENT_RUSTC_VERSION")] pub const fn replace(&mut self, value: T) -> Option { mem::replace(self, Some(value)) } @@ -1878,7 +1884,7 @@ impl Option<&T> { /// ``` #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "copied", since = "1.35.0")] - #[rustc_const_unstable(feature = "const_option", issue = "67441")] + #[rustc_const_stable(feature = "const_option", since = "CURRENT_RUSTC_VERSION")] pub const fn copied(self) -> Option where T: Copy, @@ -1931,7 +1937,8 @@ impl Option<&mut T> { /// ``` #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "copied", since = "1.35.0")] - #[rustc_const_unstable(feature = "const_option", issue = "67441")] + #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] + #[rustc_const_stable(feature = "const_option", since = "CURRENT_RUSTC_VERSION")] pub const fn copied(self) -> Option where T: Copy, @@ -1986,7 +1993,8 @@ impl Option> { /// ``` #[inline] #[stable(feature = "transpose_result", since = "1.33.0")] - #[rustc_const_unstable(feature = "const_option", issue = "67441")] + #[rustc_allow_const_fn_unstable(const_precise_live_drops)] + #[rustc_const_stable(feature = "const_option", since = "CURRENT_RUSTC_VERSION")] pub const fn transpose(self) -> Result, E> { match self { Some(Ok(x)) => Ok(Some(x)), @@ -2009,7 +2017,6 @@ const fn unwrap_failed() -> ! { #[cfg_attr(feature = "panic_immediate_abort", inline)] #[cold] #[track_caller] -#[rustc_const_unstable(feature = "const_option", issue = "67441")] const fn expect_failed(msg: &str) -> ! { panic_display(&msg) } @@ -2534,7 +2541,8 @@ impl Option> { /// ``` #[inline] #[stable(feature = "option_flattening", since = "1.40.0")] - #[rustc_const_unstable(feature = "const_option", issue = "67441")] + #[rustc_allow_const_fn_unstable(const_precise_live_drops)] + #[rustc_const_stable(feature = "const_option", since = "CURRENT_RUSTC_VERSION")] pub const fn flatten(self) -> Option { // FIXME(const-hack): could be written with `and_then` match self { diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index dc1a7c6220e..980d4a3cf6c 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -1211,7 +1211,6 @@ impl NonNull { /// /// ``` /// #![feature(const_nonnull_new)] - /// #![feature(const_option)] /// #![feature(const_pointer_is_aligned)] /// use std::ptr::NonNull; /// @@ -1264,7 +1263,6 @@ impl NonNull { /// /// ``` /// #![feature(const_pointer_is_aligned)] - /// #![feature(const_option)] /// #![feature(const_nonnull_new)] /// use std::ptr::NonNull; /// diff --git a/library/core/src/time.rs b/library/core/src/time.rs index a997874dd9c..f7ea7e06e9c 100644 --- a/library/core/src/time.rs +++ b/library/core/src/time.rs @@ -626,7 +626,6 @@ impl Duration { /// ``` #[stable(feature = "duration_abs_diff", since = "1.81.0")] #[rustc_const_stable(feature = "duration_abs_diff", since = "1.81.0")] - #[rustc_allow_const_fn_unstable(const_option)] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 02777886b45..9e15bb1dd8f 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -24,7 +24,6 @@ #![feature(const_ipv6)] #![feature(const_likely)] #![feature(const_nonnull_new)] -#![feature(const_option)] #![feature(const_option_ext)] #![feature(const_pin)] #![feature(const_pointer_is_aligned)] diff --git a/src/tools/clippy/tests/ui/doc/doc-fixable.fixed b/src/tools/clippy/tests/ui/doc/doc-fixable.fixed index edfffe8fcfe..355f2bc7736 100644 --- a/src/tools/clippy/tests/ui/doc/doc-fixable.fixed +++ b/src/tools/clippy/tests/ui/doc/doc-fixable.fixed @@ -3,7 +3,7 @@ #![allow(dead_code, incomplete_features)] #![warn(clippy::doc_markdown)] -#![feature(custom_inner_attributes, generic_const_exprs, const_option)] +#![feature(custom_inner_attributes, generic_const_exprs)] #![rustfmt::skip] /// The `foo_bar` function does _nothing_. See also `foo::bar`. (note the dot there) diff --git a/src/tools/clippy/tests/ui/doc/doc-fixable.rs b/src/tools/clippy/tests/ui/doc/doc-fixable.rs index 3c0f6913e32..9ced2677622 100644 --- a/src/tools/clippy/tests/ui/doc/doc-fixable.rs +++ b/src/tools/clippy/tests/ui/doc/doc-fixable.rs @@ -3,7 +3,7 @@ #![allow(dead_code, incomplete_features)] #![warn(clippy::doc_markdown)] -#![feature(custom_inner_attributes, generic_const_exprs, const_option)] +#![feature(custom_inner_attributes, generic_const_exprs)] #![rustfmt::skip] /// The foo_bar function does _nothing_. See also foo::bar. (note the dot there) diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs index 330147c8f1c..f089d1e1bcc 100644 --- a/src/tools/miri/src/lib.rs +++ b/src/tools/miri/src/lib.rs @@ -1,6 +1,5 @@ #![feature(rustc_private)] #![feature(cell_update)] -#![feature(const_option)] #![feature(float_gamma)] #![feature(map_try_insert)] #![feature(never_type)] diff --git a/tests/ui/consts/const-unwrap.rs b/tests/ui/consts/const-unwrap.rs index bc79c7db2fc..ea0a15af1be 100644 --- a/tests/ui/consts/const-unwrap.rs +++ b/tests/ui/consts/const-unwrap.rs @@ -1,11 +1,15 @@ //@ check-fail - -#![feature(const_option)] +// Verify that panicking `const_option` methods do the correct thing const FOO: i32 = Some(42i32).unwrap(); const BAR: i32 = Option::::None.unwrap(); -//~^ERROR: evaluation of constant value failed +//~^ ERROR: evaluation of constant value failed +//~| NOTE: the evaluated program panicked + +const BAZ: i32 = Option::::None.expect("absolutely not!"); +//~^ ERROR: evaluation of constant value failed +//~| NOTE: absolutely not! fn main() { println!("{}", FOO); diff --git a/tests/ui/consts/const-unwrap.stderr b/tests/ui/consts/const-unwrap.stderr index fee22a1d070..aa5dd9a5c36 100644 --- a/tests/ui/consts/const-unwrap.stderr +++ b/tests/ui/consts/const-unwrap.stderr @@ -1,9 +1,15 @@ error[E0080]: evaluation of constant value failed - --> $DIR/const-unwrap.rs:7:18 + --> $DIR/const-unwrap.rs:6:18 | LL | const BAR: i32 = Option::::None.unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'called `Option::unwrap()` on a `None` value', $DIR/const-unwrap.rs:7:38 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'called `Option::unwrap()` on a `None` value', $DIR/const-unwrap.rs:6:38 -error: aborting due to 1 previous error +error[E0080]: evaluation of constant value failed + --> $DIR/const-unwrap.rs:10:18 + | +LL | const BAZ: i32 = Option::::None.expect("absolutely not!"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'absolutely not!', $DIR/const-unwrap.rs:10:38 + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0080`. From 46b41b4fc89d10099dcb04a876bd95be8426519a Mon Sep 17 00:00:00 2001 From: printfn Date: Sat, 12 Oct 2024 21:57:50 +0000 Subject: [PATCH 242/357] Update unicode-width to 0.2.0 --- Cargo.lock | 32 +++++++++++++++++++------------- compiler/rustc_parse/Cargo.toml | 2 +- compiler/rustc_span/Cargo.toml | 2 +- 3 files changed, 21 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c62c379f70d..b50b44bd077 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -96,7 +96,7 @@ version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccaf7e9dfbb6ab22c82e473cd1a8a7bd313c19a5b7e40970f3d89ef5a5c9e81e" dependencies = [ - "unicode-width", + "unicode-width 0.1.14", "yansi-term", ] @@ -107,7 +107,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24e35ed54e5ea7997c14ed4c70ba043478db1112e98263b3b035907aa197d991" dependencies = [ "anstyle", - "unicode-width", + "unicode-width 0.1.14", ] [[package]] @@ -168,7 +168,7 @@ dependencies = [ "anstyle", "anstyle-lossy", "html-escape", - "unicode-width", + "unicode-width 0.1.14", ] [[package]] @@ -737,7 +737,7 @@ dependencies = [ "encode_unicode", "lazy_static", "libc", - "unicode-width", + "unicode-width 0.1.14", "windows-sys 0.52.0", ] @@ -1425,7 +1425,7 @@ version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" dependencies = [ - "unicode-width", + "unicode-width 0.1.14", ] [[package]] @@ -1788,7 +1788,7 @@ dependencies = [ "instant", "number_prefix", "portable-atomic", - "unicode-width", + "unicode-width 0.1.14", ] [[package]] @@ -2590,7 +2590,7 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2ad9b889f1b12e0b9ee24db044b5129150d5eada288edc800f789928dc8c0e3" dependencies = [ - "unicode-width", + "unicode-width 0.1.14", ] [[package]] @@ -2601,7 +2601,7 @@ checksum = "9ad43c07024ef767f9160710b3a6773976194758c7919b17e63b863db0bdf7fb" dependencies = [ "bytecount", "fnv", - "unicode-width", + "unicode-width 0.1.14", ] [[package]] @@ -4188,7 +4188,7 @@ dependencies = [ "thin-vec", "tracing", "unicode-normalization", - "unicode-width", + "unicode-width 0.2.0", ] [[package]] @@ -4422,7 +4422,7 @@ dependencies = [ "sha1", "sha2", "tracing", - "unicode-width", + "unicode-width 0.2.0", ] [[package]] @@ -4687,7 +4687,7 @@ dependencies = [ "tracing-subscriber", "unicode-properties", "unicode-segmentation", - "unicode-width", + "unicode-width 0.1.14", ] [[package]] @@ -5097,7 +5097,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c998b0c8b921495196a48aabaf1901ff28be0760136e31604f7967b0792050e" dependencies = [ "papergrid", - "unicode-width", + "unicode-width 0.1.14", ] [[package]] @@ -5646,6 +5646,12 @@ version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" +[[package]] +name = "unicode-width" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd" + [[package]] name = "unicode-xid" version = "0.2.6" @@ -5894,7 +5900,7 @@ dependencies = [ "bumpalo", "leb128", "memchr", - "unicode-width", + "unicode-width 0.1.14", "wasm-encoder 0.219.0", ] diff --git a/compiler/rustc_parse/Cargo.toml b/compiler/rustc_parse/Cargo.toml index c59ae48a07d..2360914a0ab 100644 --- a/compiler/rustc_parse/Cargo.toml +++ b/compiler/rustc_parse/Cargo.toml @@ -20,7 +20,7 @@ rustc_span = { path = "../rustc_span" } thin-vec = "0.2.12" tracing = "0.1" unicode-normalization = "0.1.11" -unicode-width = "0.1.4" +unicode-width = "0.2.0" # tidy-alphabetical-end [dev-dependencies] diff --git a/compiler/rustc_span/Cargo.toml b/compiler/rustc_span/Cargo.toml index c52d1fcc07f..781fe6a11fe 100644 --- a/compiler/rustc_span/Cargo.toml +++ b/compiler/rustc_span/Cargo.toml @@ -19,5 +19,5 @@ scoped-tls = "1.0" sha1 = "0.10.0" sha2 = "0.10.1" tracing = "0.1" -unicode-width = "0.1.4" +unicode-width = "0.2.0" # tidy-alphabetical-end From 4d59c33780c6d264da8bf37d82a74a4d95bba7e7 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sat, 12 Oct 2024 16:37:27 +1100 Subject: [PATCH 243/357] Rename `HeaderLine` to `DirectiveLine` --- src/tools/compiletest/src/header.rs | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 63d05886166..c833793585d 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -57,7 +57,7 @@ impl EarlyProps { &mut poisoned, testfile, rdr, - &mut |HeaderLine { directive: ln, .. }| { + &mut |DirectiveLine { directive: ln, .. }| { parse_and_update_aux(config, ln, &mut props.aux); config.parse_and_update_revisions(ln, &mut props.revisions); }, @@ -344,7 +344,7 @@ impl TestProps { &mut poisoned, testfile, file, - &mut |HeaderLine { header_revision, directive: ln, .. }| { + &mut |DirectiveLine { header_revision, directive: ln, .. }| { if header_revision.is_some() && header_revision != test_revision { return; } @@ -680,7 +680,7 @@ impl TestProps { /// Extract an `(Option, directive)` directive from a line if comment is present. /// -/// See [`HeaderLine`] for a diagram. +/// See [`DirectiveLine`] for a diagram. pub fn line_directive<'line>( comment: &str, original_line: &'line str, @@ -745,7 +745,7 @@ const KNOWN_JSONDOCCK_DIRECTIVE_NAMES: &[&str] = /// ^^^^^^^^^^^^^^^^^ directive /// ^^^^^^^^^^^^^^^^^^^^^^^^^^^ original_line /// ``` -struct HeaderLine<'ln> { +struct DirectiveLine<'ln> { line_number: usize, /// Raw line from the test file, including comment prefix and any revision. original_line: &'ln str, @@ -803,7 +803,7 @@ fn iter_header( poisoned: &mut bool, testfile: &Path, rdr: impl Read, - it: &mut dyn FnMut(HeaderLine<'_>), + it: &mut dyn FnMut(DirectiveLine<'_>), ) { if testfile.is_dir() { return; @@ -824,7 +824,12 @@ fn iter_header( ]; // Process the extra implied directives, with a dummy line number of 0. for directive in extra_directives { - it(HeaderLine { line_number: 0, original_line: "", header_revision: None, directive }); + it(DirectiveLine { + line_number: 0, + original_line: "", + header_revision: None, + directive, + }); } } @@ -897,7 +902,7 @@ fn iter_header( } } - it(HeaderLine { + it(DirectiveLine { line_number, original_line, header_revision, @@ -1292,7 +1297,7 @@ pub fn make_test_description( &mut local_poisoned, path, src, - &mut |HeaderLine { header_revision, original_line, directive: ln, line_number }| { + &mut |DirectiveLine { header_revision, original_line, directive: ln, line_number }| { if header_revision.is_some() && header_revision != test_revision { return; } From f51088021cbb7c683c4de83c42dac2b9e4dbead2 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sat, 12 Oct 2024 16:33:18 +1100 Subject: [PATCH 244/357] Remove the one thing that was checking a directive's `original_line` --- src/tools/compiletest/src/header.rs | 32 ++++------------------------- 1 file changed, 4 insertions(+), 28 deletions(-) diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index c833793585d..c5f163dab1e 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -738,17 +738,13 @@ const KNOWN_JSONDOCCK_DIRECTIVE_NAMES: &[&str] = /// ```text /// //@ compile-flags: -O /// ^^^^^^^^^^^^^^^^^ directive -/// ^^^^^^^^^^^^^^^^^^^^^ original_line /// /// //@ [foo] compile-flags: -O /// ^^^ header_revision /// ^^^^^^^^^^^^^^^^^ directive -/// ^^^^^^^^^^^^^^^^^^^^^^^^^^^ original_line /// ``` struct DirectiveLine<'ln> { line_number: usize, - /// Raw line from the test file, including comment prefix and any revision. - original_line: &'ln str, /// Some header directives start with a revision name in square brackets /// (e.g. `[foo]`), and only apply to that revision of the test. /// If present, this field contains the revision name (e.g. `foo`). @@ -824,12 +820,7 @@ fn iter_header( ]; // Process the extra implied directives, with a dummy line number of 0. for directive in extra_directives { - it(DirectiveLine { - line_number: 0, - original_line: "", - header_revision: None, - directive, - }); + it(DirectiveLine { line_number: 0, header_revision: None, directive }); } } @@ -846,11 +837,6 @@ fn iter_header( if rdr.read_line(&mut ln).unwrap() == 0 { break; } - - // Assume that any directives will be found before the first - // module or function. This doesn't seem to be an optimization - // with a warm page cache. Maybe with a cold one. - let original_line = &ln; let ln = ln.trim(); // Assume that any directives will be found before the first module or function. This @@ -904,7 +890,6 @@ fn iter_header( it(DirectiveLine { line_number, - original_line, header_revision, directive: non_revisioned_directive_line, }); @@ -1291,13 +1276,14 @@ pub fn make_test_description( let mut local_poisoned = false; + // Scan through the test file to handle `ignore-*`, `only-*`, and `needs-*` directives. iter_header( config.mode, &config.suite, &mut local_poisoned, path, src, - &mut |DirectiveLine { header_revision, original_line, directive: ln, line_number }| { + &mut |DirectiveLine { header_revision, directive: ln, line_number }| { if header_revision.is_some() && header_revision != test_revision { return; } @@ -1322,17 +1308,7 @@ pub fn make_test_description( }; } - if let Some((_, post)) = original_line.trim_start().split_once("//") { - let post = post.trim_start(); - if post.starts_with("ignore-tidy") { - // Not handled by compiletest. - } else { - decision!(cfg::handle_ignore(config, ln)); - } - } else { - decision!(cfg::handle_ignore(config, ln)); - } - + decision!(cfg::handle_ignore(config, ln)); decision!(cfg::handle_only(config, ln)); decision!(needs::handle_needs(&cache.needs, config, ln)); decision!(ignore_llvm(config, ln)); From 9f0f0352f7b6fd9c4062cc4f161ae35d33fb37c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= <39484203+jieyouxu@users.noreply.github.com> Date: Sun, 13 Oct 2024 00:35:25 +0800 Subject: [PATCH 245/357] Error on trying to use revisions in `run-make` tests Currently `run-make` tests do not support revisions. --- src/tools/compiletest/src/header.rs | 17 +++++++++++++---- src/tools/compiletest/src/header/tests.rs | 2 +- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 63d05886166..b0aa50e8940 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -59,7 +59,7 @@ impl EarlyProps { rdr, &mut |HeaderLine { directive: ln, .. }| { parse_and_update_aux(config, ln, &mut props.aux); - config.parse_and_update_revisions(ln, &mut props.revisions); + config.parse_and_update_revisions(testfile, ln, &mut props.revisions); }, ); @@ -391,7 +391,7 @@ impl TestProps { has_edition = true; } - config.parse_and_update_revisions(ln, &mut self.revisions); + config.parse_and_update_revisions(testfile, ln, &mut self.revisions); if let Some(flags) = config.parse_name_value_directive(ln, RUN_FLAGS) { self.run_flags.extend(split_flags(&flags)); @@ -907,12 +907,21 @@ fn iter_header( } impl Config { - fn parse_and_update_revisions(&self, line: &str, existing: &mut Vec) { + fn parse_and_update_revisions(&self, testfile: &Path, line: &str, existing: &mut Vec) { if let Some(raw) = self.parse_name_value_directive(line, "revisions") { + if self.mode == Mode::RunMake { + panic!("`run-make` tests do not support revisions: {}", testfile.display()); + } + let mut duplicates: HashSet<_> = existing.iter().cloned().collect(); for revision in raw.split_whitespace().map(|r| r.to_string()) { if !duplicates.insert(revision.clone()) { - panic!("Duplicate revision: `{}` in line `{}`", revision, raw); + panic!( + "duplicate revision: `{}` in line `{}`: {}", + revision, + raw, + testfile.display() + ); } existing.push(revision); } diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs index 22dfa349e2b..c3c9496c4d2 100644 --- a/src/tools/compiletest/src/header/tests.rs +++ b/src/tools/compiletest/src/header/tests.rs @@ -423,7 +423,7 @@ fn test_extract_version_range() { } #[test] -#[should_panic(expected = "Duplicate revision: `rpass1` in line ` rpass1 rpass1`")] +#[should_panic(expected = "duplicate revision: `rpass1` in line ` rpass1 rpass1`")] fn test_duplicate_revisions() { let config: Config = cfg().build(); parse_rs(&config, "//@ revisions: rpass1 rpass1"); From c128b4c4334fc0ed67c242eaf60a369df6bea054 Mon Sep 17 00:00:00 2001 From: Andreas Molzer Date: Sun, 13 Oct 2024 02:35:09 +0200 Subject: [PATCH 246/357] Fix typo thing->thin referring to pointer --- library/core/src/ptr/const_ptr.rs | 2 +- library/core/src/ptr/mut_ptr.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 7b91b1bcb3b..0122c00f890 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -72,7 +72,7 @@ impl *const T { /// /// The resulting pointer will have provenance of `self`. This operation is semantically the /// same as creating a new pointer with the data pointer value of `self` but the metadata of - /// `meta`, being fat or thing depending on the `meta` operand. + /// `meta`, being fat or thin depending on the `meta` operand. /// /// # Examples /// diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index e1a181158af..a57097f8cbd 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -54,7 +54,7 @@ impl *mut T { /// /// The resulting pointer will have provenance of `self`. This operation is semantically the /// same as creating a new pointer with the data pointer value of `self` but the metadata of - /// `meta`, being fat or thing depending on the `meta` operand. + /// `meta`, being fat or thin depending on the `meta` operand. /// /// # Examples /// From feecfaa18d87e3f5dc9258fafa9d9ab9c1ebe5f6 Mon Sep 17 00:00:00 2001 From: beetrees Date: Mon, 18 Mar 2024 00:02:49 +0000 Subject: [PATCH 247/357] Fix bug where `option_env!` would return `None` when env var is present but not valid Unicode --- compiler/rustc_builtin_macros/src/env.rs | 34 +++++++++++++++---- compiler/rustc_builtin_macros/src/util.rs | 32 +++++++++++++---- library/core/src/macros/mod.rs | 18 +++++----- .../non-unicode-env/non_unicode_env.rs | 1 + .../non-unicode-env/non_unicode_env.stderr | 10 +++++- 5 files changed, 72 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/env.rs b/compiler/rustc_builtin_macros/src/env.rs index 25583cda5a2..43e2bf1796f 100644 --- a/compiler/rustc_builtin_macros/src/env.rs +++ b/compiler/rustc_builtin_macros/src/env.rs @@ -15,7 +15,7 @@ use rustc_span::symbol::{Ident, Symbol, kw, sym}; use thin_vec::thin_vec; use crate::errors; -use crate::util::{expr_to_string, get_exprs_from_tts, get_single_str_from_tts}; +use crate::util::{expr_to_string, get_exprs_from_tts, get_single_expr_from_tts}; fn lookup_env<'cx>(cx: &'cx ExtCtxt<'_>, var: Symbol) -> Result { let var = var.as_str(); @@ -32,19 +32,28 @@ pub(crate) fn expand_option_env<'cx>( sp: Span, tts: TokenStream, ) -> MacroExpanderResult<'cx> { - let ExpandResult::Ready(mac) = get_single_str_from_tts(cx, sp, tts, "option_env!") else { + let ExpandResult::Ready(mac_expr) = get_single_expr_from_tts(cx, sp, tts, "option_env!") else { + return ExpandResult::Retry(()); + }; + let var_expr = match mac_expr { + Ok(var_expr) => var_expr, + Err(guar) => return ExpandResult::Ready(DummyResult::any(sp, guar)), + }; + let ExpandResult::Ready(mac) = + expr_to_string(cx, var_expr.clone(), "argument must be a string literal") + else { return ExpandResult::Retry(()); }; let var = match mac { - Ok(var) => var, + Ok((var, _)) => var, Err(guar) => return ExpandResult::Ready(DummyResult::any(sp, guar)), }; let sp = cx.with_def_site_ctxt(sp); - let value = lookup_env(cx, var).ok(); - cx.sess.psess.env_depinfo.borrow_mut().insert((var, value)); + let value = lookup_env(cx, var); + cx.sess.psess.env_depinfo.borrow_mut().insert((var, value.as_ref().ok().copied())); let e = match value { - None => { + Err(VarError::NotPresent) => { let lt = cx.lifetime(sp, Ident::new(kw::StaticLifetime, sp)); cx.expr_path(cx.path_all( sp, @@ -58,7 +67,18 @@ pub(crate) fn expand_option_env<'cx>( ))], )) } - Some(value) => { + Err(VarError::NotUnicode(_)) => { + let ExprKind::Lit(token::Lit { + kind: LitKind::Str | LitKind::StrRaw(..), symbol, .. + }) = &var_expr.kind + else { + unreachable!("`expr_to_string` ensures this is a string lit") + }; + + let guar = cx.dcx().emit_err(errors::EnvNotUnicode { span: sp, var: *symbol }); + return ExpandResult::Ready(DummyResult::any(sp, guar)); + } + Ok(value) => { cx.expr_call_global(sp, cx.std_path(&[sym::option, sym::Option, sym::Some]), thin_vec![ cx.expr_str(sp, value) ]) diff --git a/compiler/rustc_builtin_macros/src/util.rs b/compiler/rustc_builtin_macros/src/util.rs index d7b03a43ecb..2a28dfaf3c4 100644 --- a/compiler/rustc_builtin_macros/src/util.rs +++ b/compiler/rustc_builtin_macros/src/util.rs @@ -171,6 +171,30 @@ pub(crate) fn get_single_str_spanned_from_tts( tts: TokenStream, name: &str, ) -> ExpandResult, ()> { + let ExpandResult::Ready(ret) = get_single_expr_from_tts(cx, span, tts, name) else { + return ExpandResult::Retry(()); + }; + let ret = match ret { + Ok(ret) => ret, + Err(e) => return ExpandResult::Ready(Err(e)), + }; + expr_to_spanned_string(cx, ret, "argument must be a string literal").map(|res| { + res.map_err(|err| match err { + Ok((err, _)) => err.emit(), + Err(guar) => guar, + }) + .map(|(symbol, _style, span)| (symbol, span)) + }) +} + +/// Interpreting `tts` as a comma-separated sequence of expressions, +/// expect exactly one expression, or emit an error and return `Err`. +pub(crate) fn get_single_expr_from_tts( + cx: &mut ExtCtxt<'_>, + span: Span, + tts: TokenStream, + name: &str, +) -> ExpandResult, ErrorGuaranteed>, ()> { let mut p = cx.new_parser_from_tts(tts); if p.token == token::Eof { let guar = cx.dcx().emit_err(errors::OnlyOneArgument { span, name }); @@ -185,13 +209,7 @@ pub(crate) fn get_single_str_spanned_from_tts( if p.token != token::Eof { cx.dcx().emit_err(errors::OnlyOneArgument { span, name }); } - expr_to_spanned_string(cx, ret, "argument must be a string literal").map(|res| { - res.map_err(|err| match err { - Ok((err, _)) => err.emit(), - Err(guar) => guar, - }) - .map(|(symbol, _style, span)| (symbol, span)) - }) + ExpandResult::Ready(Ok(ret)) } /// Extracts comma-separated expressions from `tts`. diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index aa0646846e4..2839a242a90 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -1107,17 +1107,19 @@ pub(crate) mod builtin { /// /// If the named environment variable is present at compile time, this will /// expand into an expression of type `Option<&'static str>` whose value is - /// `Some` of the value of the environment variable. If the environment - /// variable is not present, then this will expand to `None`. See - /// [`Option`][Option] for more information on this type. Use - /// [`std::env::var`] instead if you want to read the value at runtime. + /// `Some` of the value of the environment variable (a compilation error + /// will be emitted if the environment variable is not a valid Unicode + /// string). If the environment variable is not present, then this will + /// expand to `None`. See [`Option`][Option] for more information on this + /// type. Use [`std::env::var`] instead if you want to read the value at + /// runtime. /// /// [`std::env::var`]: ../std/env/fn.var.html /// - /// A compile time error is never emitted when using this macro regardless - /// of whether the environment variable is present or not. - /// To emit a compile error if the environment variable is not present, - /// use the [`env!`] macro instead. + /// A compile time error is only emitted when using this macro if the + /// environment variable exists and is not a valid Unicode string. To also + /// emit a compile error if the environment variable is not present, use the + /// [`env!`] macro instead. /// /// # Examples /// diff --git a/tests/run-make/non-unicode-env/non_unicode_env.rs b/tests/run-make/non-unicode-env/non_unicode_env.rs index 865fc937365..3efa4842d94 100644 --- a/tests/run-make/non-unicode-env/non_unicode_env.rs +++ b/tests/run-make/non-unicode-env/non_unicode_env.rs @@ -1,3 +1,4 @@ fn main() { let _ = env!("NON_UNICODE_VAR"); + let _ = option_env!("NON_UNICODE_VAR"); } diff --git a/tests/run-make/non-unicode-env/non_unicode_env.stderr b/tests/run-make/non-unicode-env/non_unicode_env.stderr index c4dcd7b2eb7..1f260ac9c07 100644 --- a/tests/run-make/non-unicode-env/non_unicode_env.stderr +++ b/tests/run-make/non-unicode-env/non_unicode_env.stderr @@ -6,5 +6,13 @@ error: environment variable `NON_UNICODE_VAR` is not a valid Unicode string | = note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 1 previous error +error: environment variable `NON_UNICODE_VAR` is not a valid Unicode string + --> non_unicode_env.rs:3:13 + | +3 | let _ = option_env!("NON_UNICODE_VAR"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in the macro `option_env` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors From 3c6ed4e5418fe8dbc40cfe8c3895dccde8cd7498 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sun, 13 Oct 2024 17:26:25 +1100 Subject: [PATCH 248/357] Move debugger setup code out of `lib.rs` --- src/tools/compiletest/src/debuggers.rs | 272 +++++++++++++++++ src/tools/compiletest/src/header.rs | 2 +- src/tools/compiletest/src/lib.rs | 281 +----------------- .../compiletest/src/runtest/debuginfo.rs | 2 +- src/tools/compiletest/src/tests.rs | 7 +- 5 files changed, 290 insertions(+), 274 deletions(-) create mode 100644 src/tools/compiletest/src/debuggers.rs diff --git a/src/tools/compiletest/src/debuggers.rs b/src/tools/compiletest/src/debuggers.rs new file mode 100644 index 00000000000..b605bc813f1 --- /dev/null +++ b/src/tools/compiletest/src/debuggers.rs @@ -0,0 +1,272 @@ +use std::env; +use std::ffi::OsString; +use std::path::PathBuf; +use std::process::Command; +use std::sync::Arc; + +use crate::common::{Config, Debugger}; + +pub(crate) fn configure_cdb(config: &Config) -> Option> { + config.cdb.as_ref()?; + + Some(Arc::new(Config { debugger: Some(Debugger::Cdb), ..config.clone() })) +} + +pub(crate) fn configure_gdb(config: &Config) -> Option> { + config.gdb_version?; + + if config.matches_env("msvc") { + return None; + } + + if config.remote_test_client.is_some() && !config.target.contains("android") { + println!( + "WARNING: debuginfo tests are not available when \ + testing with remote" + ); + return None; + } + + if config.target.contains("android") { + println!( + "{} debug-info test uses tcp 5039 port.\ + please reserve it", + config.target + ); + + // android debug-info test uses remote debugger so, we test 1 thread + // at once as they're all sharing the same TCP port to communicate + // over. + // + // we should figure out how to lift this restriction! (run them all + // on different ports allocated dynamically). + env::set_var("RUST_TEST_THREADS", "1"); + } + + Some(Arc::new(Config { debugger: Some(Debugger::Gdb), ..config.clone() })) +} + +pub(crate) fn configure_lldb(config: &Config) -> Option> { + config.lldb_python_dir.as_ref()?; + + if let Some(350) = config.lldb_version { + println!( + "WARNING: The used version of LLDB (350) has a \ + known issue that breaks debuginfo tests. See \ + issue #32520 for more information. Skipping all \ + LLDB-based tests!", + ); + return None; + } + + Some(Arc::new(Config { debugger: Some(Debugger::Lldb), ..config.clone() })) +} + +/// Returns `true` if the given target is an Android target for the +/// purposes of GDB testing. +pub(crate) fn is_android_gdb_target(target: &str) -> bool { + matches!( + &target[..], + "arm-linux-androideabi" | "armv7-linux-androideabi" | "aarch64-linux-android" + ) +} + +/// Returns `true` if the given target is a MSVC target for the purposes of CDB testing. +fn is_pc_windows_msvc_target(target: &str) -> bool { + target.ends_with("-pc-windows-msvc") +} + +fn find_cdb(target: &str) -> Option { + if !(cfg!(windows) && is_pc_windows_msvc_target(target)) { + return None; + } + + let pf86 = env::var_os("ProgramFiles(x86)").or_else(|| env::var_os("ProgramFiles"))?; + let cdb_arch = if cfg!(target_arch = "x86") { + "x86" + } else if cfg!(target_arch = "x86_64") { + "x64" + } else if cfg!(target_arch = "aarch64") { + "arm64" + } else if cfg!(target_arch = "arm") { + "arm" + } else { + return None; // No compatible CDB.exe in the Windows 10 SDK + }; + + let mut path = PathBuf::new(); + path.push(pf86); + path.push(r"Windows Kits\10\Debuggers"); // We could check 8.1 etc. too? + path.push(cdb_arch); + path.push(r"cdb.exe"); + + if !path.exists() { + return None; + } + + Some(path.into_os_string()) +} + +/// Returns Path to CDB +pub(crate) fn analyze_cdb( + cdb: Option, + target: &str, +) -> (Option, Option<[u16; 4]>) { + let cdb = cdb.map(OsString::from).or_else(|| find_cdb(target)); + + let mut version = None; + if let Some(cdb) = cdb.as_ref() { + if let Ok(output) = Command::new(cdb).arg("/version").output() { + if let Some(first_line) = String::from_utf8_lossy(&output.stdout).lines().next() { + version = extract_cdb_version(&first_line); + } + } + } + + (cdb, version) +} + +pub(crate) fn extract_cdb_version(full_version_line: &str) -> Option<[u16; 4]> { + // Example full_version_line: "cdb version 10.0.18362.1" + let version = full_version_line.rsplit(' ').next()?; + let mut components = version.split('.'); + let major: u16 = components.next().unwrap().parse().unwrap(); + let minor: u16 = components.next().unwrap().parse().unwrap(); + let patch: u16 = components.next().unwrap_or("0").parse().unwrap(); + let build: u16 = components.next().unwrap_or("0").parse().unwrap(); + Some([major, minor, patch, build]) +} + +/// Returns (Path to GDB, GDB Version) +pub(crate) fn analyze_gdb( + gdb: Option, + target: &str, + android_cross_path: &PathBuf, +) -> (Option, Option) { + #[cfg(not(windows))] + const GDB_FALLBACK: &str = "gdb"; + #[cfg(windows)] + const GDB_FALLBACK: &str = "gdb.exe"; + + let fallback_gdb = || { + if is_android_gdb_target(target) { + let mut gdb_path = match android_cross_path.to_str() { + Some(x) => x.to_owned(), + None => panic!("cannot find android cross path"), + }; + gdb_path.push_str("/bin/gdb"); + gdb_path + } else { + GDB_FALLBACK.to_owned() + } + }; + + let gdb = match gdb { + None => fallback_gdb(), + Some(ref s) if s.is_empty() => fallback_gdb(), // may be empty if configure found no gdb + Some(ref s) => s.to_owned(), + }; + + let mut version_line = None; + if let Ok(output) = Command::new(&gdb).arg("--version").output() { + if let Some(first_line) = String::from_utf8_lossy(&output.stdout).lines().next() { + version_line = Some(first_line.to_string()); + } + } + + let version = match version_line { + Some(line) => extract_gdb_version(&line), + None => return (None, None), + }; + + (Some(gdb), version) +} + +pub(crate) fn extract_gdb_version(full_version_line: &str) -> Option { + let full_version_line = full_version_line.trim(); + + // GDB versions look like this: "major.minor.patch?.yyyymmdd?", with both + // of the ? sections being optional + + // We will parse up to 3 digits for each component, ignoring the date + + // We skip text in parentheses. This avoids accidentally parsing + // the openSUSE version, which looks like: + // GNU gdb (GDB; openSUSE Leap 15.0) 8.1 + // This particular form is documented in the GNU coding standards: + // https://www.gnu.org/prep/standards/html_node/_002d_002dversion.html#g_t_002d_002dversion + + let unbracketed_part = full_version_line.split('[').next().unwrap(); + let mut splits = unbracketed_part.trim_end().rsplit(' '); + let version_string = splits.next().unwrap(); + + let mut splits = version_string.split('.'); + let major = splits.next().unwrap(); + let minor = splits.next().unwrap(); + let patch = splits.next(); + + let major: u32 = major.parse().unwrap(); + let (minor, patch): (u32, u32) = match minor.find(not_a_digit) { + None => { + let minor = minor.parse().unwrap(); + let patch: u32 = match patch { + Some(patch) => match patch.find(not_a_digit) { + None => patch.parse().unwrap(), + Some(idx) if idx > 3 => 0, + Some(idx) => patch[..idx].parse().unwrap(), + }, + None => 0, + }; + (minor, patch) + } + // There is no patch version after minor-date (e.g. "4-2012"). + Some(idx) => { + let minor = minor[..idx].parse().unwrap(); + (minor, 0) + } + }; + + Some(((major * 1000) + minor) * 1000 + patch) +} + +/// Returns LLDB version +pub(crate) fn extract_lldb_version(full_version_line: &str) -> Option { + // Extract the major LLDB version from the given version string. + // LLDB version strings are different for Apple and non-Apple platforms. + // The Apple variant looks like this: + // + // LLDB-179.5 (older versions) + // lldb-300.2.51 (new versions) + // + // We are only interested in the major version number, so this function + // will return `Some(179)` and `Some(300)` respectively. + // + // Upstream versions look like: + // lldb version 6.0.1 + // + // There doesn't seem to be a way to correlate the Apple version + // with the upstream version, and since the tests were originally + // written against Apple versions, we make a fake Apple version by + // multiplying the first number by 100. This is a hack. + + let full_version_line = full_version_line.trim(); + + if let Some(apple_ver) = + full_version_line.strip_prefix("LLDB-").or_else(|| full_version_line.strip_prefix("lldb-")) + { + if let Some(idx) = apple_ver.find(not_a_digit) { + let version: u32 = apple_ver[..idx].parse().unwrap(); + return Some(version); + } + } else if let Some(lldb_ver) = full_version_line.strip_prefix("lldb version ") { + if let Some(idx) = lldb_ver.find(not_a_digit) { + let version: u32 = lldb_ver[..idx].parse().ok()?; + return Some(version * 100); + } + } + None +} + +fn not_a_digit(c: char) -> bool { + !c.is_ascii_digit() +} diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 63d05886166..a47cab50f21 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -9,11 +9,11 @@ use std::process::Command; use tracing::*; use crate::common::{Config, Debugger, FailMode, Mode, PassMode}; +use crate::debuggers::{extract_cdb_version, extract_gdb_version}; use crate::header::auxiliary::{AuxProps, parse_and_update_aux}; use crate::header::cfg::{MatchOutcome, parse_cfg_name_directive}; use crate::header::needs::CachedNeedsConditions; use crate::util::static_regex; -use crate::{extract_cdb_version, extract_gdb_version}; pub(crate) mod auxiliary; mod cfg; diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index 30d1644b148..18000e5602c 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -10,6 +10,7 @@ mod tests; pub mod common; pub mod compute_diff; +mod debuggers; pub mod errors; pub mod header; mod json; @@ -36,8 +37,8 @@ use walkdir::WalkDir; use self::header::{EarlyProps, make_test_description}; use crate::common::{ - Config, Debugger, Mode, PassMode, TestPaths, UI_EXTENSIONS, expected_output_path, - output_base_dir, output_relative_path, + Config, Mode, PassMode, TestPaths, UI_EXTENSIONS, expected_output_path, output_base_dir, + output_relative_path, }; use crate::header::HeadersCache; use crate::util::logv; @@ -204,9 +205,11 @@ pub fn parse_config(args: Vec) -> Config { let target = opt_str2(matches.opt_str("target")); let android_cross_path = opt_path(matches, "android-cross-path"); - let (cdb, cdb_version) = analyze_cdb(matches.opt_str("cdb"), &target); - let (gdb, gdb_version) = analyze_gdb(matches.opt_str("gdb"), &target, &android_cross_path); - let lldb_version = matches.opt_str("lldb-version").as_deref().and_then(extract_lldb_version); + let (cdb, cdb_version) = debuggers::analyze_cdb(matches.opt_str("cdb"), &target); + let (gdb, gdb_version) = + debuggers::analyze_gdb(matches.opt_str("gdb"), &target, &android_cross_path); + let lldb_version = + matches.opt_str("lldb-version").as_deref().and_then(debuggers::extract_lldb_version); let color = match matches.opt_str("color").as_deref() { Some("auto") | None => ColorConfig::AutoColor, Some("always") => ColorConfig::AlwaysColor, @@ -443,9 +446,9 @@ pub fn run_tests(config: Arc) { if let Mode::DebugInfo = config.mode { // Debugging emscripten code doesn't make sense today if !config.target.contains("emscripten") { - configs.extend(configure_cdb(&config)); - configs.extend(configure_gdb(&config)); - configs.extend(configure_lldb(&config)); + configs.extend(debuggers::configure_cdb(&config)); + configs.extend(debuggers::configure_gdb(&config)); + configs.extend(debuggers::configure_lldb(&config)); } } else { configs.push(config.clone()); @@ -498,62 +501,6 @@ pub fn run_tests(config: Arc) { } } -fn configure_cdb(config: &Config) -> Option> { - config.cdb.as_ref()?; - - Some(Arc::new(Config { debugger: Some(Debugger::Cdb), ..config.clone() })) -} - -fn configure_gdb(config: &Config) -> Option> { - config.gdb_version?; - - if config.matches_env("msvc") { - return None; - } - - if config.remote_test_client.is_some() && !config.target.contains("android") { - println!( - "WARNING: debuginfo tests are not available when \ - testing with remote" - ); - return None; - } - - if config.target.contains("android") { - println!( - "{} debug-info test uses tcp 5039 port.\ - please reserve it", - config.target - ); - - // android debug-info test uses remote debugger so, we test 1 thread - // at once as they're all sharing the same TCP port to communicate - // over. - // - // we should figure out how to lift this restriction! (run them all - // on different ports allocated dynamically). - env::set_var("RUST_TEST_THREADS", "1"); - } - - Some(Arc::new(Config { debugger: Some(Debugger::Gdb), ..config.clone() })) -} - -fn configure_lldb(config: &Config) -> Option> { - config.lldb_python_dir.as_ref()?; - - if let Some(350) = config.lldb_version { - println!( - "WARNING: The used version of LLDB (350) has a \ - known issue that breaks debuginfo tests. See \ - issue #32520 for more information. Skipping all \ - LLDB-based tests!", - ); - return None; - } - - Some(Arc::new(Config { debugger: Some(Debugger::Lldb), ..config.clone() })) -} - pub fn test_opts(config: &Config) -> test::TestOpts { if env::var("RUST_TEST_NOCAPTURE").is_ok() { eprintln!( @@ -981,212 +928,6 @@ fn make_test_closure( })) } -/// Returns `true` if the given target is an Android target for the -/// purposes of GDB testing. -fn is_android_gdb_target(target: &str) -> bool { - matches!( - &target[..], - "arm-linux-androideabi" | "armv7-linux-androideabi" | "aarch64-linux-android" - ) -} - -/// Returns `true` if the given target is a MSVC target for the purposes of CDB testing. -fn is_pc_windows_msvc_target(target: &str) -> bool { - target.ends_with("-pc-windows-msvc") -} - -fn find_cdb(target: &str) -> Option { - if !(cfg!(windows) && is_pc_windows_msvc_target(target)) { - return None; - } - - let pf86 = env::var_os("ProgramFiles(x86)").or_else(|| env::var_os("ProgramFiles"))?; - let cdb_arch = if cfg!(target_arch = "x86") { - "x86" - } else if cfg!(target_arch = "x86_64") { - "x64" - } else if cfg!(target_arch = "aarch64") { - "arm64" - } else if cfg!(target_arch = "arm") { - "arm" - } else { - return None; // No compatible CDB.exe in the Windows 10 SDK - }; - - let mut path = PathBuf::new(); - path.push(pf86); - path.push(r"Windows Kits\10\Debuggers"); // We could check 8.1 etc. too? - path.push(cdb_arch); - path.push(r"cdb.exe"); - - if !path.exists() { - return None; - } - - Some(path.into_os_string()) -} - -/// Returns Path to CDB -fn analyze_cdb(cdb: Option, target: &str) -> (Option, Option<[u16; 4]>) { - let cdb = cdb.map(OsString::from).or_else(|| find_cdb(target)); - - let mut version = None; - if let Some(cdb) = cdb.as_ref() { - if let Ok(output) = Command::new(cdb).arg("/version").output() { - if let Some(first_line) = String::from_utf8_lossy(&output.stdout).lines().next() { - version = extract_cdb_version(&first_line); - } - } - } - - (cdb, version) -} - -fn extract_cdb_version(full_version_line: &str) -> Option<[u16; 4]> { - // Example full_version_line: "cdb version 10.0.18362.1" - let version = full_version_line.rsplit(' ').next()?; - let mut components = version.split('.'); - let major: u16 = components.next().unwrap().parse().unwrap(); - let minor: u16 = components.next().unwrap().parse().unwrap(); - let patch: u16 = components.next().unwrap_or("0").parse().unwrap(); - let build: u16 = components.next().unwrap_or("0").parse().unwrap(); - Some([major, minor, patch, build]) -} - -/// Returns (Path to GDB, GDB Version) -fn analyze_gdb( - gdb: Option, - target: &str, - android_cross_path: &PathBuf, -) -> (Option, Option) { - #[cfg(not(windows))] - const GDB_FALLBACK: &str = "gdb"; - #[cfg(windows)] - const GDB_FALLBACK: &str = "gdb.exe"; - - let fallback_gdb = || { - if is_android_gdb_target(target) { - let mut gdb_path = match android_cross_path.to_str() { - Some(x) => x.to_owned(), - None => panic!("cannot find android cross path"), - }; - gdb_path.push_str("/bin/gdb"); - gdb_path - } else { - GDB_FALLBACK.to_owned() - } - }; - - let gdb = match gdb { - None => fallback_gdb(), - Some(ref s) if s.is_empty() => fallback_gdb(), // may be empty if configure found no gdb - Some(ref s) => s.to_owned(), - }; - - let mut version_line = None; - if let Ok(output) = Command::new(&gdb).arg("--version").output() { - if let Some(first_line) = String::from_utf8_lossy(&output.stdout).lines().next() { - version_line = Some(first_line.to_string()); - } - } - - let version = match version_line { - Some(line) => extract_gdb_version(&line), - None => return (None, None), - }; - - (Some(gdb), version) -} - -fn extract_gdb_version(full_version_line: &str) -> Option { - let full_version_line = full_version_line.trim(); - - // GDB versions look like this: "major.minor.patch?.yyyymmdd?", with both - // of the ? sections being optional - - // We will parse up to 3 digits for each component, ignoring the date - - // We skip text in parentheses. This avoids accidentally parsing - // the openSUSE version, which looks like: - // GNU gdb (GDB; openSUSE Leap 15.0) 8.1 - // This particular form is documented in the GNU coding standards: - // https://www.gnu.org/prep/standards/html_node/_002d_002dversion.html#g_t_002d_002dversion - - let unbracketed_part = full_version_line.split('[').next().unwrap(); - let mut splits = unbracketed_part.trim_end().rsplit(' '); - let version_string = splits.next().unwrap(); - - let mut splits = version_string.split('.'); - let major = splits.next().unwrap(); - let minor = splits.next().unwrap(); - let patch = splits.next(); - - let major: u32 = major.parse().unwrap(); - let (minor, patch): (u32, u32) = match minor.find(not_a_digit) { - None => { - let minor = minor.parse().unwrap(); - let patch: u32 = match patch { - Some(patch) => match patch.find(not_a_digit) { - None => patch.parse().unwrap(), - Some(idx) if idx > 3 => 0, - Some(idx) => patch[..idx].parse().unwrap(), - }, - None => 0, - }; - (minor, patch) - } - // There is no patch version after minor-date (e.g. "4-2012"). - Some(idx) => { - let minor = minor[..idx].parse().unwrap(); - (minor, 0) - } - }; - - Some(((major * 1000) + minor) * 1000 + patch) -} - -/// Returns LLDB version -fn extract_lldb_version(full_version_line: &str) -> Option { - // Extract the major LLDB version from the given version string. - // LLDB version strings are different for Apple and non-Apple platforms. - // The Apple variant looks like this: - // - // LLDB-179.5 (older versions) - // lldb-300.2.51 (new versions) - // - // We are only interested in the major version number, so this function - // will return `Some(179)` and `Some(300)` respectively. - // - // Upstream versions look like: - // lldb version 6.0.1 - // - // There doesn't seem to be a way to correlate the Apple version - // with the upstream version, and since the tests were originally - // written against Apple versions, we make a fake Apple version by - // multiplying the first number by 100. This is a hack. - - let full_version_line = full_version_line.trim(); - - if let Some(apple_ver) = - full_version_line.strip_prefix("LLDB-").or_else(|| full_version_line.strip_prefix("lldb-")) - { - if let Some(idx) = apple_ver.find(not_a_digit) { - let version: u32 = apple_ver[..idx].parse().unwrap(); - return Some(version); - } - } else if let Some(lldb_ver) = full_version_line.strip_prefix("lldb version ") { - if let Some(idx) = lldb_ver.find(not_a_digit) { - let version: u32 = lldb_ver[..idx].parse().ok()?; - return Some(version * 100); - } - } - None -} - -fn not_a_digit(c: char) -> bool { - !c.is_ascii_digit() -} - fn check_overlapping_tests(found_paths: &HashSet) { let mut collisions = Vec::new(); for path in found_paths { diff --git a/src/tools/compiletest/src/runtest/debuginfo.rs b/src/tools/compiletest/src/runtest/debuginfo.rs index 36127414ab1..bd0845b4524 100644 --- a/src/tools/compiletest/src/runtest/debuginfo.rs +++ b/src/tools/compiletest/src/runtest/debuginfo.rs @@ -9,8 +9,8 @@ use tracing::debug; use super::debugger::DebuggerCommands; use super::{Debugger, Emit, ProcRes, TestCx, Truncated, WillExecute}; use crate::common::Config; +use crate::debuggers::{extract_gdb_version, is_android_gdb_target}; use crate::util::logv; -use crate::{extract_gdb_version, is_android_gdb_target}; impl TestCx<'_> { pub(super) fn run_debuginfo_test(&self) { diff --git a/src/tools/compiletest/src/tests.rs b/src/tools/compiletest/src/tests.rs index 7c2e7b0f023..680579c59ae 100644 --- a/src/tools/compiletest/src/tests.rs +++ b/src/tools/compiletest/src/tests.rs @@ -1,5 +1,8 @@ -use super::header::extract_llvm_version; -use super::*; +use std::ffi::OsString; + +use crate::debuggers::{extract_gdb_version, extract_lldb_version}; +use crate::header::extract_llvm_version; +use crate::is_test; #[test] fn test_extract_gdb_version() { From b2b0d240a284567c27da2fe6015128bc8e506441 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 13 Oct 2024 09:13:33 +0200 Subject: [PATCH 249/357] rework threadname test for more consistency --- .../tests/pass-dep/libc/pthread-threadname.rs | 177 +++++++++++------- .../miri/tests/pass/concurrency/threadname.rs | 13 ++ 2 files changed, 125 insertions(+), 65 deletions(-) diff --git a/src/tools/miri/tests/pass-dep/libc/pthread-threadname.rs b/src/tools/miri/tests/pass-dep/libc/pthread-threadname.rs index 74b15466202..404ef7cc42d 100644 --- a/src/tools/miri/tests/pass-dep/libc/pthread-threadname.rs +++ b/src/tools/miri/tests/pass-dep/libc/pthread-threadname.rs @@ -1,9 +1,23 @@ //@ignore-target: windows # No pthreads on Windows -use std::ffi::CStr; -#[cfg(not(target_os = "freebsd"))] -use std::ffi::CString; +use std::ffi::{CStr, CString}; use std::thread; +const MAX_THREAD_NAME_LEN: usize = { + cfg_if::cfg_if! { + if #[cfg(any(target_os = "linux"))] { + 16 + } else if #[cfg(any(target_os = "illumos", target_os = "solaris"))] { + 32 + } else if #[cfg(target_os = "macos")] { + libc::MAXTHREADNAMESIZE // 64, at the time of writing + } else if #[cfg(target_os = "freebsd")] { + usize::MAX // as far as I can tell + } else { + panic!() + } + } +}; + fn main() { // The short name should be shorter than 16 bytes which POSIX promises // for thread names. The length includes a null terminator. @@ -52,46 +66,64 @@ fn main() { } thread::Builder::new() - .name(short_name.clone()) .spawn(move || { - // Rust remembers the full thread name itself. - assert_eq!(thread::current().name(), Some(short_name.as_str())); - - // Note that glibc requires 15 bytes long buffer exculding a null terminator. - // Otherwise, `pthread_getname_np` returns an error. - let mut buf = vec![0u8; short_name.len().max(15) + 1]; - assert_eq!(get_thread_name(&mut buf), 0); - - let cstr = CStr::from_bytes_until_nul(&buf).unwrap(); - // POSIX seems to promise at least 15 chars excluding a null terminator. - assert_eq!(short_name.as_bytes(), cstr.to_bytes()); - - // Also test directly calling pthread_setname to check its return value. + // Set short thread name. + let cstr = CString::new(short_name.clone()).unwrap(); + assert!(cstr.to_bytes_with_nul().len() <= MAX_THREAD_NAME_LEN); // this should fit assert_eq!(set_thread_name(&cstr), 0); - // For glibc used by linux-gnu there should be a failue, - // if a shorter than 16 bytes buffer is provided, even if that would be - // large enough for the thread name. - #[cfg(target_os = "linux")] - assert_eq!(get_thread_name(&mut buf[..15]), libc::ERANGE); + // Now get it again, in various ways. - // Solaris compatible implementations return an error, - // if the buffer is shorter than the thread name. - #[cfg(any(target_os = "illumos", target_os = "solaris"))] - assert_eq!(get_thread_name(&mut buf[..4]), libc::ERANGE); - // On macOS and FreeBSD it's not an error for the buffer to be - // too short for the thread name -- they truncate instead. - #[cfg(any(target_os = "freebsd", target_os = "macos"))] - { - // Ensure that a zero sized buffer returns no error. - assert_eq!(get_thread_name(&mut buf[..0]), 0); + // POSIX seems to promise at least 15 chars excluding a null terminator. + let mut buf = vec![0u8; short_name.len().max(15) + 1]; + assert_eq!(get_thread_name(&mut buf), 0); + let cstr = CStr::from_bytes_until_nul(&buf).unwrap(); + assert_eq!(cstr.to_bytes(), short_name.as_bytes()); - // Ensure that a shorter tnan required buffer still returns no error, - // and gives a prefix of the thread name. - assert_eq!(get_thread_name(&mut buf[..4]), 0); - let cstr = CStr::from_bytes_until_nul(&buf).unwrap(); - assert_eq!(cstr.to_bytes_with_nul().len(), 4); - assert!(short_name.as_bytes().starts_with(cstr.to_bytes())); + // Test what happens when the buffer is shorter than 16, but still long enough. + let res = get_thread_name(&mut buf[..15]); + cfg_if::cfg_if! { + if #[cfg(target_os = "linux")] { + // For glibc used by linux-gnu there should be a failue, + // if a shorter than 16 bytes buffer is provided, even if that would be + // large enough for the thread name. + assert_eq!(res, libc::ERANGE); + } else { + // Everywhere else, this should work. + assert_eq!(res, 0); + // POSIX seems to promise at least 15 chars excluding a null terminator. + let cstr = CStr::from_bytes_until_nul(&buf).unwrap(); + assert_eq!(short_name.as_bytes(), cstr.to_bytes()); + } + } + + // Test what happens when the buffer is too short even for the short name. + let res = get_thread_name(&mut buf[..4]); + cfg_if::cfg_if! { + if #[cfg(any(target_os = "freebsd", target_os = "macos"))] { + // On macOS and FreeBSD it's not an error for the buffer to be + // too short for the thread name -- they truncate instead. + assert_eq!(res, 0); + let cstr = CStr::from_bytes_until_nul(&buf).unwrap(); + assert_eq!(cstr.to_bytes_with_nul().len(), 4); + assert!(short_name.as_bytes().starts_with(cstr.to_bytes())); + } else { + // The rest should give an error. + assert_eq!(res, libc::ERANGE); + } + } + + // Test zero-sized buffer. + let res = get_thread_name(&mut []); + cfg_if::cfg_if! { + if #[cfg(any(target_os = "freebsd", target_os = "macos"))] { + // On macOS and FreeBSD it's not an error for the buffer to be + // too short for the thread name -- even with size 0. + assert_eq!(res, 0); + } else { + // The rest should give an error. + assert_eq!(res, libc::ERANGE); + } } }) .unwrap() @@ -99,37 +131,52 @@ fn main() { .unwrap(); thread::Builder::new() - .name(long_name.clone()) .spawn(move || { - // Rust remembers the full thread name itself. - assert_eq!(thread::current().name(), Some(long_name.as_str())); - - // But the system is limited -- make sure we successfully set a truncation. - // Note that there's no specific to glibc buffer requirement, since the value - // `long_name` is longer than 16 bytes including a null terminator. - let mut buf = vec![0u8; long_name.len() + 1]; - assert_eq!(get_thread_name(&mut buf), 0); - - let cstr = CStr::from_bytes_until_nul(&buf).unwrap(); - // POSIX seems to promise at least 15 chars excluding a null terminator. - assert!( - cstr.to_bytes().len() >= 15, - "name is too short: len={}", - cstr.to_bytes().len() - ); - assert!(long_name.as_bytes().starts_with(cstr.to_bytes())); - - // Also test directly calling pthread_setname to check its return value. + // Set full thread name. + let cstr = CString::new(long_name.clone()).unwrap(); + let res = set_thread_name(&cstr); + cfg_if::cfg_if! { + if #[cfg(target_os = "freebsd")] { + // Names of all size are supported. + assert!(cstr.to_bytes_with_nul().len() <= MAX_THREAD_NAME_LEN); + assert_eq!(res, 0); + } else if #[cfg(target_os = "macos")] { + // Name is too long. + assert!(cstr.to_bytes_with_nul().len() > MAX_THREAD_NAME_LEN); + assert_eq!(res, libc::ENAMETOOLONG); + } else { + // Name is too long. + assert!(cstr.to_bytes_with_nul().len() > MAX_THREAD_NAME_LEN); + assert_eq!(res, libc::ERANGE); + } + } + // Set the longest name we can. + let truncated_name = &long_name[..long_name.len().min(MAX_THREAD_NAME_LEN - 1)]; + let cstr = CString::new(truncated_name).unwrap(); assert_eq!(set_thread_name(&cstr), 0); - // But with a too long name it should fail (except on FreeBSD where - // names of arbitrary size seem to be supported). - // On macOS, the error code is different. - #[cfg(not(any(target_os = "freebsd", target_os = "macos")))] - assert_eq!(set_thread_name(&CString::new(long_name).unwrap()), libc::ERANGE); + // Now get it again, in various ways. - #[cfg(target_os = "macos")] - assert_eq!(set_thread_name(&CString::new(long_name).unwrap()), libc::ENAMETOOLONG); + // This name should round-trip properly. + let mut buf = vec![0u8; long_name.len() + 1]; + assert_eq!(get_thread_name(&mut buf), 0); + let cstr = CStr::from_bytes_until_nul(&buf).unwrap(); + assert_eq!(cstr.to_bytes(), truncated_name.as_bytes()); + + // Test what happens when our buffer is just one byte too small. + let res = get_thread_name(&mut buf[..truncated_name.len()]); + cfg_if::cfg_if! { + if #[cfg(any(target_os = "freebsd", target_os = "macos"))] { + // On macOS and FreeBSD it's not an error for the buffer to be + // too short for the thread name -- they truncate instead. + assert_eq!(res, 0); + let cstr = CStr::from_bytes_until_nul(&buf).unwrap(); + assert_eq!(cstr.to_bytes(), &truncated_name.as_bytes()[..(truncated_name.len() - 1)]); + } else { + // The rest should give an error. + assert_eq!(res, libc::ERANGE); + } + } }) .unwrap() .join() diff --git a/src/tools/miri/tests/pass/concurrency/threadname.rs b/src/tools/miri/tests/pass/concurrency/threadname.rs index 6dd5f1f5c91..41cac6459b2 100644 --- a/src/tools/miri/tests/pass/concurrency/threadname.rs +++ b/src/tools/miri/tests/pass/concurrency/threadname.rs @@ -16,6 +16,19 @@ fn main() { .join() .unwrap(); + // Long thread name. + let long_name = std::iter::once("test_named_thread_truncation") + .chain(std::iter::repeat(" long").take(100)) + .collect::(); + thread::Builder::new() + .name(long_name.clone()) + .spawn(move || { + assert_eq!(thread::current().name().unwrap(), long_name); + }) + .unwrap() + .join() + .unwrap(); + // Also check main thread name. assert_eq!(thread::current().name().unwrap(), "main"); } From 1ebfd9705165cf6902dae1eacc49cb4c0a0e142e Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 12 Oct 2024 19:08:34 +0200 Subject: [PATCH 250/357] merge const_ipv4 / const_ipv6 feature gate into 'ip' feature gate --- library/core/src/lib.rs | 2 -- library/core/src/net/ip_addr.rs | 14 -------------- library/core/tests/lib.rs | 3 --- library/std/src/lib.rs | 3 --- 4 files changed, 22 deletions(-) diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 726aa209fdf..6851664a89e 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -124,8 +124,6 @@ #![feature(const_hash)] #![feature(const_heap)] #![feature(const_index_range_slice_index)] -#![feature(const_ipv4)] -#![feature(const_ipv6)] #![feature(const_likely)] #![feature(const_make_ascii)] #![feature(const_maybe_uninit_assume_init)] diff --git a/library/core/src/net/ip_addr.rs b/library/core/src/net/ip_addr.rs index 919f681f911..fbf61cf614b 100644 --- a/library/core/src/net/ip_addr.rs +++ b/library/core/src/net/ip_addr.rs @@ -295,7 +295,6 @@ impl IpAddr { /// assert_eq!(IpAddr::V4(Ipv4Addr::new(80, 9, 12, 3)).is_global(), true); /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0x1c9, 0, 0, 0xafc8, 0, 0x1)).is_global(), true); /// ``` - #[rustc_const_unstable(feature = "const_ip", issue = "76205")] #[unstable(feature = "ip", issue = "27709")] #[must_use] #[inline] @@ -348,7 +347,6 @@ impl IpAddr { /// true /// ); /// ``` - #[rustc_const_unstable(feature = "const_ip", issue = "76205")] #[unstable(feature = "ip", issue = "27709")] #[must_use] #[inline] @@ -776,7 +774,6 @@ impl Ipv4Addr { /// /// // For a complete overview see the IANA IPv4 Special-Purpose Address Registry. /// ``` - #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")] #[unstable(feature = "ip", issue = "27709")] #[must_use] #[inline] @@ -813,7 +810,6 @@ impl Ipv4Addr { /// assert_eq!(Ipv4Addr::new(100, 127, 255, 255).is_shared(), true); /// assert_eq!(Ipv4Addr::new(100, 128, 0, 0).is_shared(), false); /// ``` - #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")] #[unstable(feature = "ip", issue = "27709")] #[must_use] #[inline] @@ -841,7 +837,6 @@ impl Ipv4Addr { /// assert_eq!(Ipv4Addr::new(198, 19, 255, 255).is_benchmarking(), true); /// assert_eq!(Ipv4Addr::new(198, 20, 0, 0).is_benchmarking(), false); /// ``` - #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")] #[unstable(feature = "ip", issue = "27709")] #[must_use] #[inline] @@ -878,7 +873,6 @@ impl Ipv4Addr { /// // The broadcast address is not considered as reserved for future use by this implementation /// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_reserved(), false); /// ``` - #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")] #[unstable(feature = "ip", issue = "27709")] #[must_use] #[inline] @@ -1510,7 +1504,6 @@ impl Ipv6Addr { /// /// // For a complete overview see the IANA IPv6 Special-Purpose Address Registry. /// ``` - #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] #[unstable(feature = "ip", issue = "27709")] #[must_use] #[inline] @@ -1562,7 +1555,6 @@ impl Ipv6Addr { /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unique_local(), false); /// assert_eq!(Ipv6Addr::new(0xfc02, 0, 0, 0, 0, 0, 0, 0).is_unique_local(), true); /// ``` - #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] #[unstable(feature = "ip", issue = "27709")] #[must_use] #[inline] @@ -1591,7 +1583,6 @@ impl Ipv6Addr { /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_unicast(), true); /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).is_unicast(), false); /// ``` - #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] #[unstable(feature = "ip", issue = "27709")] #[must_use] #[inline] @@ -1643,7 +1634,6 @@ impl Ipv6Addr { /// assert_eq!(Ipv6Addr::new(0xfe80, 0, 0, 1, 0, 0, 0, 0).is_unicast_link_local(), true); /// assert_eq!(Ipv6Addr::new(0xfe81, 0, 0, 0, 0, 0, 0, 0).is_unicast_link_local(), true); /// ``` - #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] #[unstable(feature = "ip", issue = "27709")] #[must_use] #[inline] @@ -1668,7 +1658,6 @@ impl Ipv6Addr { /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_documentation(), false); /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_documentation(), true); /// ``` - #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] #[unstable(feature = "ip", issue = "27709")] #[must_use] #[inline] @@ -1729,7 +1718,6 @@ impl Ipv6Addr { /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_unicast_global(), false); /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unicast_global(), true); /// ``` - #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] #[unstable(feature = "ip", issue = "27709")] #[must_use] #[inline] @@ -1758,7 +1746,6 @@ impl Ipv6Addr { /// ); /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).multicast_scope(), None); /// ``` - #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] #[unstable(feature = "ip", issue = "27709")] #[must_use] #[inline] @@ -1818,7 +1805,6 @@ impl Ipv6Addr { /// /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_ipv4_mapped(), false); /// ``` - #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] #[unstable(feature = "ip", issue = "27709")] #[must_use] #[inline] diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 9e15bb1dd8f..7616c38cbc2 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -19,9 +19,6 @@ #![feature(const_black_box)] #![feature(const_hash)] #![feature(const_heap)] -#![feature(const_ip)] -#![feature(const_ipv4)] -#![feature(const_ipv6)] #![feature(const_likely)] #![feature(const_nonnull_new)] #![feature(const_option_ext)] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 65a9aa66c7c..057a57f7997 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -414,9 +414,6 @@ // tidy-alphabetical-start #![feature(const_collections_with_hasher)] #![feature(const_hash)] -#![feature(const_ip)] -#![feature(const_ipv4)] -#![feature(const_ipv6)] #![feature(thread_local_internals)] // tidy-alphabetical-end // From 40ca4d8cd3c708bddb4bbba83288d1fe25fe5ab2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= <39484203+jieyouxu@users.noreply.github.com> Date: Sun, 13 Oct 2024 15:59:55 +0800 Subject: [PATCH 251/357] Special case error message for a `build-fail` test that failed check build --- src/tools/compiletest/src/runtest.rs | 25 ++++++++++++++++--- .../compiletest/src/runtest/incremental.rs | 4 +-- src/tools/compiletest/src/runtest/ui.rs | 4 +-- 3 files changed, 26 insertions(+), 7 deletions(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 46f7b9c0e7d..29f9925de16 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -318,10 +318,29 @@ impl<'test> TestCx<'test> { } } - fn check_if_test_should_compile(&self, proc_res: &ProcRes, pm: Option) { - if self.should_compile_successfully(pm) { + fn check_if_test_should_compile( + &self, + fail_mode: Option, + pass_mode: Option, + proc_res: &ProcRes, + ) { + if self.should_compile_successfully(pass_mode) { if !proc_res.status.success() { - self.fatal_proc_rec("test compilation failed although it shouldn't!", proc_res); + match (fail_mode, pass_mode) { + (Some(FailMode::Build), Some(PassMode::Check)) => { + // A `build-fail` test needs to `check-pass`. + self.fatal_proc_rec( + "`build-fail` test is required to pass check build, but check build failed", + proc_res, + ); + } + _ => { + self.fatal_proc_rec( + "test compilation failed although it shouldn't!", + proc_res, + ); + } + } } } else { if proc_res.status.success() { diff --git a/src/tools/compiletest/src/runtest/incremental.rs b/src/tools/compiletest/src/runtest/incremental.rs index bf2b71fef43..591aff0defe 100644 --- a/src/tools/compiletest/src/runtest/incremental.rs +++ b/src/tools/compiletest/src/runtest/incremental.rs @@ -1,4 +1,4 @@ -use super::{TestCx, WillExecute}; +use super::{FailMode, TestCx, WillExecute}; use crate::errors; impl TestCx<'_> { @@ -96,7 +96,7 @@ impl TestCx<'_> { fn run_cfail_test(&self) { let pm = self.pass_mode(); let proc_res = self.compile_test(WillExecute::No, self.should_emit_metadata(pm)); - self.check_if_test_should_compile(&proc_res, pm); + self.check_if_test_should_compile(Some(FailMode::Build), pm, &proc_res); self.check_no_compiler_crash(&proc_res, self.props.should_ice); let output_to_check = self.get_output(&proc_res); diff --git a/src/tools/compiletest/src/runtest/ui.rs b/src/tools/compiletest/src/runtest/ui.rs index bd8ef952a86..bb747c68029 100644 --- a/src/tools/compiletest/src/runtest/ui.rs +++ b/src/tools/compiletest/src/runtest/ui.rs @@ -18,14 +18,14 @@ impl TestCx<'_> { let pm = Some(PassMode::Check); let proc_res = self.compile_test_general(WillExecute::No, Emit::Metadata, pm, Vec::new()); - self.check_if_test_should_compile(&proc_res, pm); + self.check_if_test_should_compile(self.props.fail_mode, pm, &proc_res); } let pm = self.pass_mode(); let should_run = self.should_run(pm); let emit_metadata = self.should_emit_metadata(pm); let proc_res = self.compile_test(should_run, emit_metadata); - self.check_if_test_should_compile(&proc_res, pm); + self.check_if_test_should_compile(self.props.fail_mode, pm, &proc_res); if matches!(proc_res.truncated, Truncated::Yes) && !self.props.dont_check_compiler_stdout && !self.props.dont_check_compiler_stderr From 90e4f10f6c40d8bcf290f2ea7bf9c9d310de9d65 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 13 Oct 2024 10:02:51 +0200 Subject: [PATCH 252/357] switch unicode-data back to 'static' --- library/core/src/lib.rs | 1 + library/core/src/unicode/unicode_data.rs | 16 ++++++++-------- .../unicode-table-generator/src/raw_emitter.rs | 8 ++++---- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 726aa209fdf..b21618e28a4 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -178,6 +178,7 @@ // tidy-alphabetical-start #![cfg_attr(bootstrap, feature(const_mut_refs))] #![cfg_attr(bootstrap, feature(const_refs_to_cell))] +#![cfg_attr(bootstrap, feature(const_refs_to_static))] #![feature(abi_unadjusted)] #![feature(adt_const_params)] #![feature(allow_internal_unsafe)] diff --git a/library/core/src/unicode/unicode_data.rs b/library/core/src/unicode/unicode_data.rs index db2e3ddd754..cba53bf5054 100644 --- a/library/core/src/unicode/unicode_data.rs +++ b/library/core/src/unicode/unicode_data.rs @@ -331,14 +331,14 @@ pub mod grapheme_extend { #[rustfmt::skip] pub mod lowercase { - const BITSET_CHUNKS_MAP: &'static [u8; 123] = &[ + static BITSET_CHUNKS_MAP: [u8; 123] = [ 14, 17, 0, 0, 9, 0, 0, 12, 13, 10, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0, 15, 0, 8, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 3, 18, 0, 7, ]; - const BITSET_INDEX_CHUNKS: &'static [[u8; 16]; 20] = &[ + static BITSET_INDEX_CHUNKS: [[u8; 16]; 20] = [ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 14, 56, 0], @@ -360,7 +360,7 @@ pub mod lowercase { [16, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [65, 41, 55, 12, 77, 63, 18, 1, 7, 64, 76, 20, 73, 74, 4, 45], ]; - const BITSET_CANONICAL: &'static [u64; 56] = &[ + static BITSET_CANONICAL: [u64; 56] = [ 0b0000000000000000000000000000000000000000000000000000000000000000, 0b1111111111111111110000000000000000000000000011111111111111111111, 0b1010101010101010101010101010101010101010101010101010100000000010, @@ -418,7 +418,7 @@ pub mod lowercase { 0b1110011001010001001011010010101001001110001001000011000100101001, 0b1110101111000000000000000000000000001111111111111111111111111100, ]; - const BITSET_MAPPING: &'static [(u8, u8); 22] = &[ + static BITSET_MAPPING: [(u8, u8); 22] = [ (0, 64), (1, 188), (1, 186), (1, 183), (1, 176), (1, 109), (1, 124), (1, 126), (1, 66), (1, 70), (1, 77), (2, 146), (2, 144), (2, 83), (3, 93), (3, 147), (3, 133), (4, 12), (4, 6), (5, 187), (6, 78), (7, 132), @@ -471,14 +471,14 @@ pub mod n { #[rustfmt::skip] pub mod uppercase { - const BITSET_CHUNKS_MAP: &'static [u8; 125] = &[ + static BITSET_CHUNKS_MAP: [u8; 125] = [ 12, 15, 6, 6, 0, 6, 6, 2, 4, 11, 6, 16, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 8, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 6, 14, 6, 10, 6, 6, 1, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 13, 6, 6, 6, 6, 9, 6, 3, ]; - const BITSET_INDEX_CHUNKS: &'static [[u8; 16]; 17] = &[ + static BITSET_INDEX_CHUNKS: [[u8; 16]; 17] = [ [44, 44, 5, 35, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 5, 1], [44, 44, 5, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44], [44, 44, 40, 44, 44, 44, 44, 44, 17, 17, 63, 17, 43, 29, 24, 23], @@ -497,7 +497,7 @@ pub mod uppercase { [58, 19, 2, 18, 10, 48, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44], [58, 38, 17, 27, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44], ]; - const BITSET_CANONICAL: &'static [u64; 44] = &[ + static BITSET_CANONICAL: [u64; 44] = [ 0b0000011111111111111111111111111000000000000000000000000000000000, 0b0000000000111111111111111111111111111111111111111111111111111111, 0b0101010101010101010101010101010101010101010101010101010000000001, @@ -543,7 +543,7 @@ pub mod uppercase { 0b1111011111111111000000000000000000000000000000000000000000000000, 0b1111111100000000111111110000000000111111000000001111111100000000, ]; - const BITSET_MAPPING: &'static [(u8, u8); 25] = &[ + static BITSET_MAPPING: [(u8, u8); 25] = [ (0, 187), (0, 177), (0, 171), (0, 167), (0, 164), (0, 32), (0, 47), (0, 51), (0, 121), (0, 117), (0, 109), (1, 150), (1, 148), (1, 142), (1, 134), (1, 131), (1, 64), (2, 164), (2, 146), (2, 20), (3, 146), (3, 140), (3, 134), (4, 178), (4, 171), diff --git a/src/tools/unicode-table-generator/src/raw_emitter.rs b/src/tools/unicode-table-generator/src/raw_emitter.rs index bfffa1eee60..8097d6a8caf 100644 --- a/src/tools/unicode-table-generator/src/raw_emitter.rs +++ b/src/tools/unicode-table-generator/src/raw_emitter.rs @@ -77,7 +77,7 @@ impl RawEmitter { writeln!( &mut self.file, - "const BITSET_CANONICAL: &'static [u64; {}] = &[{}];", + "static BITSET_CANONICAL: [u64; {}] = [{}];", canonicalized.canonical_words.len(), fmt_list(canonicalized.canonical_words.iter().map(|v| Bits(*v))), ) @@ -85,7 +85,7 @@ impl RawEmitter { self.bytes_used += 8 * canonicalized.canonical_words.len(); writeln!( &mut self.file, - "const BITSET_MAPPING: &'static [(u8, u8); {}] = &[{}];", + "static BITSET_MAPPING: [(u8, u8); {}] = [{}];", canonicalized.canonicalized_words.len(), fmt_list(&canonicalized.canonicalized_words), ) @@ -139,7 +139,7 @@ impl RawEmitter { writeln!( &mut self.file, - "const BITSET_CHUNKS_MAP: &'static [u8; {}] = &[{}];", + "static BITSET_CHUNKS_MAP: [u8; {}] = [{}];", chunk_indices.len(), fmt_list(&chunk_indices), ) @@ -147,7 +147,7 @@ impl RawEmitter { self.bytes_used += chunk_indices.len(); writeln!( &mut self.file, - "const BITSET_INDEX_CHUNKS: &'static [[u8; {}]; {}] = &[{}];", + "static BITSET_INDEX_CHUNKS: [[u8; {}]; {}] = [{}];", chunk_length, chunks.len(), fmt_list(chunks.iter()), From 2ae3b1b09a09ec9c034c4cc4ba822b11c2ccbd26 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 13 Oct 2024 12:24:54 +0200 Subject: [PATCH 253/357] sys/windows: remove miri hack that is only needed for win7 --- library/std/src/sys/pal/windows/c.rs | 2 +- library/std/src/sys/pal/windows/compat.rs | 8 ++------ 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/library/std/src/sys/pal/windows/c.rs b/library/std/src/sys/pal/windows/c.rs index b65ad7dbe8c..9ce3e912caf 100644 --- a/library/std/src/sys/pal/windows/c.rs +++ b/library/std/src/sys/pal/windows/c.rs @@ -175,9 +175,9 @@ extern "system" { pub fn WakeByAddressAll(address: *const c_void); } +// These are loaded by `load_synch_functions`. #[cfg(target_vendor = "win7")] compat_fn_optional! { - crate::sys::compat::load_synch_functions(); pub fn WaitOnAddress( address: *const c_void, compareaddress: *const c_void, diff --git a/library/std/src/sys/pal/windows/compat.rs b/library/std/src/sys/pal/windows/compat.rs index c8e25dd0c94..42999da1664 100644 --- a/library/std/src/sys/pal/windows/compat.rs +++ b/library/std/src/sys/pal/windows/compat.rs @@ -198,11 +198,10 @@ macro_rules! compat_fn_with_fallback { /// Optionally loaded functions. /// -/// Actual loading of the function defers to $load_functions. +/// Relies on the functions being pre-loaded elsewhere. #[cfg(target_vendor = "win7")] macro_rules! compat_fn_optional { - ($load_functions:expr; - $( + ($( $(#[$meta:meta])* $vis:vis fn $symbol:ident($($argname:ident: $argtype:ty),*) $(-> $rettype:ty)?; )+) => ( @@ -221,9 +220,6 @@ macro_rules! compat_fn_optional { #[inline(always)] pub fn option() -> Option { - // Miri does not understand the way we do preloading - // therefore load the function here instead. - #[cfg(miri)] $load_functions; NonNull::new(PTR.load(Ordering::Relaxed)).map(|f| unsafe { mem::transmute(f) }) } } From 8d0a0b000c385ca43cc8c46e63b492c7edbf8cf2 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 13 Oct 2024 12:27:09 +0200 Subject: [PATCH 254/357] remove outdated comment now that Miri is on CI --- library/std/src/sys/pal/windows/mod.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/library/std/src/sys/pal/windows/mod.rs b/library/std/src/sys/pal/windows/mod.rs index 1ea253e5e52..a9886012e8e 100644 --- a/library/std/src/sys/pal/windows/mod.rs +++ b/library/std/src/sys/pal/windows/mod.rs @@ -346,7 +346,6 @@ pub fn abort_internal() -> ! { } } -// miri is sensitive to changes here so check that miri is happy if touching this #[cfg(miri)] pub fn abort_internal() -> ! { crate::intrinsics::abort(); From a87f5ca917b5c3c10163601da74df2045ee8e6ea Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 13 Oct 2024 12:34:28 +0200 Subject: [PATCH 255/357] sys/unix: add comments for some Miri fallbacks --- library/std/src/sys/pal/unix/fs.rs | 2 +- library/std/src/sys/sync/thread_parking/mod.rs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/library/std/src/sys/pal/unix/fs.rs b/library/std/src/sys/pal/unix/fs.rs index 39aabf0b2d6..e80299f1868 100644 --- a/library/std/src/sys/pal/unix/fs.rs +++ b/library/std/src/sys/pal/unix/fs.rs @@ -899,7 +899,7 @@ impl DirEntry { target_os = "android", target_os = "hurd" ), - not(miri) + not(miri) // no dirfd on Miri ))] pub fn metadata(&self) -> io::Result { let fd = cvt(unsafe { dirfd(self.dir.dirp.0) })?; diff --git a/library/std/src/sys/sync/thread_parking/mod.rs b/library/std/src/sys/sync/thread_parking/mod.rs index 0ebc5e093ee..f4d8fa0a58c 100644 --- a/library/std/src/sys/sync/thread_parking/mod.rs +++ b/library/std/src/sys/sync/thread_parking/mod.rs @@ -23,6 +23,7 @@ cfg_if::cfg_if! { mod windows7; pub use windows7::Parker; } else if #[cfg(all(target_vendor = "apple", not(miri)))] { + // Doesn't work in Miri, see . mod darwin; pub use darwin::Parker; } else if #[cfg(target_os = "xous")] { From 204e6af3eaf305c62cc1908475dfa13dd7bcaab2 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 13 Oct 2024 09:41:31 -0400 Subject: [PATCH 256/357] Remove const trait bound modifier hack --- compiler/rustc_ast_lowering/src/lib.rs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 263e4a9379f..365924ef782 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1327,14 +1327,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // takes care of rejecting invalid modifier combinations and // const trait bounds in trait object types. GenericBound::Trait(ty, modifiers) => { - // Still, don't pass along the constness here; we don't want to - // synthesize any host effect args, it'd only cause problems. - let modifiers = TraitBoundModifiers { - constness: BoundConstness::Never, - ..*modifiers - }; - let trait_ref = this.lower_poly_trait_ref(ty, itctx, modifiers); - let polarity = this.lower_trait_bound_modifiers(modifiers); + let trait_ref = this.lower_poly_trait_ref(ty, itctx, *modifiers); + let polarity = this.lower_trait_bound_modifiers(*modifiers); Some((trait_ref, polarity)) } GenericBound::Outlives(lifetime) => { From ac20242fbba8c2caaa31e9612425a5ba8df3068c Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Sun, 13 Oct 2024 17:43:02 +0300 Subject: [PATCH 257/357] enable `download_ci_llvm` test Signed-off-by: onur-ozkan --- src/bootstrap/src/core/config/tests.rs | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/bootstrap/src/core/config/tests.rs b/src/bootstrap/src/core/config/tests.rs index 9c67010d88d..2611b6cf51b 100644 --- a/src/bootstrap/src/core/config/tests.rs +++ b/src/bootstrap/src/core/config/tests.rs @@ -10,6 +10,7 @@ use serde::Deserialize; use super::flags::Flags; use super::{ChangeIdWrapper, Config}; use crate::core::build_steps::clippy::get_clippy_rules_in_order; +use crate::core::build_steps::llvm; use crate::core::config::{LldMode, Target, TargetSelection, TomlConfig}; pub(crate) fn parse(config: &str) -> Config { @@ -19,13 +20,22 @@ pub(crate) fn parse(config: &str) -> Config { ) } -// FIXME: Resume this test after establishing a stabilized change tracking logic. -#[ignore] #[test] fn download_ci_llvm() { - assert!(parse("").llvm_from_ci); - assert!(parse("llvm.download-ci-llvm = true").llvm_from_ci); - assert!(!parse("llvm.download-ci-llvm = false").llvm_from_ci); + let config = parse(""); + let is_available = llvm::is_ci_llvm_available(&config, config.llvm_assertions); + if is_available { + assert!(config.llvm_from_ci); + } + + let config = parse("llvm.download-ci-llvm = true"); + let is_available = llvm::is_ci_llvm_available(&config, config.llvm_assertions); + if is_available { + assert!(config.llvm_from_ci); + } + + let config = parse("llvm.download-ci-llvm = false"); + assert!(!config.llvm_from_ci); let if_unchanged_config = parse("llvm.download-ci-llvm = \"if-unchanged\""); if if_unchanged_config.llvm_from_ci { From 6e6cbdd2df0ae5a025c458d95a4c84df1b6af092 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Sun, 13 Oct 2024 17:00:41 +0300 Subject: [PATCH 258/357] check `stage0`, `channel` and `version` files for CI rustc These files have important role for compiler builds, so include them in the "if-unchanged" rustc logic. Signed-off-by: onur-ozkan --- src/bootstrap/src/core/config/config.rs | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 3f025a198cb..f768470c4ff 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -2748,13 +2748,18 @@ impl Config { } }; - // Look for a version to compare to based on the current commit. - // Only commits merged by bors will have CI artifacts. - let commit = get_closest_merge_commit(Some(&self.src), &self.git_config(), &[ + let files_to_track = &[ self.src.join("compiler"), self.src.join("library"), - ]) - .unwrap(); + self.src.join("src/version"), + self.src.join("src/stage0"), + self.src.join("src/ci/channel"), + ]; + + // Look for a version to compare to based on the current commit. + // Only commits merged by bors will have CI artifacts. + let commit = + get_closest_merge_commit(Some(&self.src), &self.git_config(), files_to_track).unwrap(); if commit.is_empty() { println!("ERROR: could not find commit hash for downloading rustc"); println!("HELP: maybe your repository history is too shallow?"); @@ -2780,7 +2785,7 @@ impl Config { let has_changes = !t!(helpers::git(Some(&self.src)) .args(["diff-index", "--quiet", &commit]) .arg("--") - .args([self.src.join("compiler"), self.src.join("library")]) + .args(files_to_track) .as_command_mut() .status()) .success(); From b5e91a00c89a065f618693873ad7074a13ad6b90 Mon Sep 17 00:00:00 2001 From: Urgau Date: Sun, 13 Oct 2024 18:13:30 +0200 Subject: [PATCH 259/357] Also use outermost const-anon for impl items in `non_local_defs` lint --- compiler/rustc_lint/src/non_local_def.rs | 10 +++++++--- .../convoluted-locals-131474-with-mods.rs | 11 +++++++++++ .../lint/non-local-defs/convoluted-locals-131474.rs | 9 +++++++++ 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_lint/src/non_local_def.rs b/compiler/rustc_lint/src/non_local_def.rs index 6fecddb3319..3c31b879bd6 100644 --- a/compiler/rustc_lint/src/non_local_def.rs +++ b/compiler/rustc_lint/src/non_local_def.rs @@ -301,9 +301,13 @@ fn did_has_local_parent( return false; }; - peel_parent_while(tcx, parent_did, |tcx, did| tcx.def_kind(did) == DefKind::Mod) - .map(|parent_did| parent_did == impl_parent || Some(parent_did) == outermost_impl_parent) - .unwrap_or(false) + peel_parent_while(tcx, parent_did, |tcx, did| { + tcx.def_kind(did) == DefKind::Mod + || (tcx.def_kind(did) == DefKind::Const + && tcx.opt_item_name(did) == Some(kw::Underscore)) + }) + .map(|parent_did| parent_did == impl_parent || Some(parent_did) == outermost_impl_parent) + .unwrap_or(false) } /// Given a `DefId` checks if it satisfies `f` if it does check with it's parent and continue diff --git a/tests/ui/lint/non-local-defs/convoluted-locals-131474-with-mods.rs b/tests/ui/lint/non-local-defs/convoluted-locals-131474-with-mods.rs index cef0f0205e8..72fd056d461 100644 --- a/tests/ui/lint/non-local-defs/convoluted-locals-131474-with-mods.rs +++ b/tests/ui/lint/non-local-defs/convoluted-locals-131474-with-mods.rs @@ -31,4 +31,15 @@ const _: () = { }; }; +// https://github.com/rust-lang/rust/issues/131643 +const _: () = { + const _: () = { + impl tmp::InnerTest {} + }; + + mod tmp { + pub(super) struct InnerTest; + } +}; + fn main() {} diff --git a/tests/ui/lint/non-local-defs/convoluted-locals-131474.rs b/tests/ui/lint/non-local-defs/convoluted-locals-131474.rs index 4881723f13b..8e738544a71 100644 --- a/tests/ui/lint/non-local-defs/convoluted-locals-131474.rs +++ b/tests/ui/lint/non-local-defs/convoluted-locals-131474.rs @@ -21,4 +21,13 @@ const _: () = { }; }; +// https://github.com/rust-lang/rust/issues/131643 +const _: () = { + const _: () = { + impl InnerTest {} + }; + + struct InnerTest; +}; + fn main() {} From 725d1f7905821dd0d819e305a5c200713963f937 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Mon, 7 Oct 2024 16:11:39 +0200 Subject: [PATCH 260/357] core/net: add Ipv[46]Addr::from_octets, Ipv6Addr::from_segments --- library/core/src/net/ip_addr.rs | 77 +++++++++++++++++++++++++++++++ library/core/tests/lib.rs | 1 + library/core/tests/net/ip_addr.rs | 24 +++++++++- 3 files changed, 101 insertions(+), 1 deletion(-) diff --git a/library/core/src/net/ip_addr.rs b/library/core/src/net/ip_addr.rs index 919f681f911..bd08ce2ee34 100644 --- a/library/core/src/net/ip_addr.rs +++ b/library/core/src/net/ip_addr.rs @@ -600,6 +600,24 @@ impl Ipv4Addr { self.octets } + /// Creates an `Ipv4Addr` from a four element byte array. + /// + /// # Examples + /// + /// ``` + /// #![feature(ip_from)] + /// use std::net::Ipv4Addr; + /// + /// let addr = Ipv4Addr::from_octets([13u8, 12u8, 11u8, 10u8]); + /// assert_eq!(Ipv4Addr::new(13, 12, 11, 10), addr); + /// ``` + #[unstable(feature = "ip_from", issue = "131360")] + #[must_use] + #[inline] + pub const fn from_octets(octets: [u8; 4]) -> Ipv4Addr { + Ipv4Addr { octets } + } + /// Returns [`true`] for the special 'unspecified' address (`0.0.0.0`). /// /// This property is defined in _UNIX Network Programming, Second Edition_, @@ -1400,6 +1418,36 @@ impl Ipv6Addr { ] } + /// Creates an `Ipv6Addr` from an eight element 16-bit array. + /// + /// # Examples + /// + /// ``` + /// #![feature(ip_from)] + /// use std::net::Ipv6Addr; + /// + /// let addr = Ipv6Addr::from_segments([ + /// 525u16, 524u16, 523u16, 522u16, + /// 521u16, 520u16, 519u16, 518u16, + /// ]); + /// assert_eq!( + /// Ipv6Addr::new( + /// 0x20d, 0x20c, + /// 0x20b, 0x20a, + /// 0x209, 0x208, + /// 0x207, 0x206 + /// ), + /// addr + /// ); + /// ``` + #[unstable(feature = "ip_from", issue = "131360")] + #[must_use] + #[inline] + pub const fn from_segments(segments: [u16; 8]) -> Ipv6Addr { + let [a, b, c, d, e, f, g, h] = segments; + Ipv6Addr::new(a, b, c, d, e, f, g, h) + } + /// Returns [`true`] for the special 'unspecified' address (`::`). /// /// This property is defined in [IETF RFC 4291]. @@ -1941,6 +1989,35 @@ impl Ipv6Addr { pub const fn octets(&self) -> [u8; 16] { self.octets } + + /// Creates an `Ipv6Addr` from a sixteen element byte array. + /// + /// # Examples + /// + /// ``` + /// #![feature(ip_from)] + /// use std::net::Ipv6Addr; + /// + /// let addr = Ipv6Addr::from_octets([ + /// 25u8, 24u8, 23u8, 22u8, 21u8, 20u8, 19u8, 18u8, + /// 17u8, 16u8, 15u8, 14u8, 13u8, 12u8, 11u8, 10u8, + /// ]); + /// assert_eq!( + /// Ipv6Addr::new( + /// 0x1918, 0x1716, + /// 0x1514, 0x1312, + /// 0x1110, 0x0f0e, + /// 0x0d0c, 0x0b0a + /// ), + /// addr + /// ); + /// ``` + #[unstable(feature = "ip_from", issue = "131360")] + #[must_use] + #[inline] + pub const fn from_octets(octets: [u8; 16]) -> Ipv6Addr { + Ipv6Addr { octets } + } } /// Writes an Ipv6Addr, conforming to the canonical style described by diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 196e91ee3e9..28636f7f5d7 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -57,6 +57,7 @@ #![feature(hashmap_internals)] #![feature(int_roundings)] #![feature(ip)] +#![feature(ip_from)] #![feature(is_ascii_octdigit)] #![feature(isqrt)] #![feature(iter_advance_by)] diff --git a/library/core/tests/net/ip_addr.rs b/library/core/tests/net/ip_addr.rs index a10b51c550d..707f9a160e1 100644 --- a/library/core/tests/net/ip_addr.rs +++ b/library/core/tests/net/ip_addr.rs @@ -494,6 +494,7 @@ fn ipv6_properties() { let octets = &[$($octet),*]; assert_eq!(&ip!($s).octets(), octets); assert_eq!(Ipv6Addr::from(*octets), ip!($s)); + assert_eq!(Ipv6Addr::from_octets(*octets), ip!($s)); let unspecified: u32 = 1 << 0; let loopback: u32 = 1 << 1; @@ -846,15 +847,19 @@ fn ipv6_from_constructors() { #[test] fn ipv4_from_octets() { - assert_eq!(Ipv4Addr::from([127, 0, 0, 1]), Ipv4Addr::new(127, 0, 0, 1)) + assert_eq!(Ipv4Addr::from([127, 0, 0, 1]), Ipv4Addr::new(127, 0, 0, 1)); + assert_eq!(Ipv4Addr::from_octets([127, 0, 0, 1]), Ipv4Addr::new(127, 0, 0, 1)); } #[test] fn ipv6_from_segments() { let from_u16s = Ipv6Addr::from([0x0011, 0x2233, 0x4455, 0x6677, 0x8899, 0xaabb, 0xccdd, 0xeeff]); + let from_u16s_explicit = + Ipv6Addr::from_segments([0x0011, 0x2233, 0x4455, 0x6677, 0x8899, 0xaabb, 0xccdd, 0xeeff]); let new = Ipv6Addr::new(0x0011, 0x2233, 0x4455, 0x6677, 0x8899, 0xaabb, 0xccdd, 0xeeff); assert_eq!(new, from_u16s); + assert_eq!(new, from_u16s_explicit); } #[test] @@ -865,7 +870,15 @@ fn ipv6_from_octets() { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, ]); + let from_u16s_explicit = + Ipv6Addr::from_segments([0x0011, 0x2233, 0x4455, 0x6677, 0x8899, 0xaabb, 0xccdd, 0xeeff]); + let from_u8s_explicit = Ipv6Addr::from_octets([ + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, + 0xff, + ]); assert_eq!(from_u16s, from_u8s); + assert_eq!(from_u16s, from_u16s_explicit); + assert_eq!(from_u16s_explicit, from_u8s_explicit); } #[test] @@ -915,6 +928,9 @@ fn ipv4_const() { const OCTETS: [u8; 4] = IP_ADDRESS.octets(); assert_eq!(OCTETS, [127, 0, 0, 1]); + const FROM_OCTETS: Ipv4Addr = Ipv4Addr::from_octets(OCTETS); + assert_eq!(IP_ADDRESS, FROM_OCTETS); + const IS_UNSPECIFIED: bool = IP_ADDRESS.is_unspecified(); assert!(!IS_UNSPECIFIED); @@ -971,9 +987,15 @@ fn ipv6_const() { const SEGMENTS: [u16; 8] = IP_ADDRESS.segments(); assert_eq!(SEGMENTS, [0, 0, 0, 0, 0, 0, 0, 1]); + const FROM_SEGMENTS: Ipv6Addr = Ipv6Addr::from_segments(SEGMENTS); + assert_eq!(IP_ADDRESS, FROM_SEGMENTS); + const OCTETS: [u8; 16] = IP_ADDRESS.octets(); assert_eq!(OCTETS, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]); + const FROM_OCTETS: Ipv6Addr = Ipv6Addr::from_octets(OCTETS); + assert_eq!(IP_ADDRESS, FROM_OCTETS); + const IS_UNSPECIFIED: bool = IP_ADDRESS.is_unspecified(); assert!(!IS_UNSPECIFIED); From 0b7e39908ee6314dd8b8561dd4c8a47ce3ba2f38 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Sun, 13 Oct 2024 20:27:24 +0200 Subject: [PATCH 261/357] core/net: use hex for ipv6 doctests for consistency. --- library/core/src/net/ip_addr.rs | 62 +++++++++++++-------------------- 1 file changed, 25 insertions(+), 37 deletions(-) diff --git a/library/core/src/net/ip_addr.rs b/library/core/src/net/ip_addr.rs index bd08ce2ee34..05e1f3ee7a2 100644 --- a/library/core/src/net/ip_addr.rs +++ b/library/core/src/net/ip_addr.rs @@ -1427,15 +1427,13 @@ impl Ipv6Addr { /// use std::net::Ipv6Addr; /// /// let addr = Ipv6Addr::from_segments([ - /// 525u16, 524u16, 523u16, 522u16, - /// 521u16, 520u16, 519u16, 518u16, + /// 0x20du16, 0x20cu16, 0x20bu16, 0x20au16, + /// 0x209u16, 0x208u16, 0x207u16, 0x206u16, /// ]); /// assert_eq!( /// Ipv6Addr::new( - /// 0x20d, 0x20c, - /// 0x20b, 0x20a, - /// 0x209, 0x208, - /// 0x207, 0x206 + /// 0x20d, 0x20c, 0x20b, 0x20a, + /// 0x209, 0x208, 0x207, 0x206, /// ), /// addr /// ); @@ -1980,7 +1978,7 @@ impl Ipv6Addr { /// use std::net::Ipv6Addr; /// /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).octets(), - /// [255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); + /// [0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); /// ``` #[rustc_const_stable(feature = "const_ip_32", since = "1.32.0")] #[stable(feature = "ipv6_to_octets", since = "1.12.0")] @@ -1999,15 +1997,13 @@ impl Ipv6Addr { /// use std::net::Ipv6Addr; /// /// let addr = Ipv6Addr::from_octets([ - /// 25u8, 24u8, 23u8, 22u8, 21u8, 20u8, 19u8, 18u8, - /// 17u8, 16u8, 15u8, 14u8, 13u8, 12u8, 11u8, 10u8, + /// 0x19u8, 0x18u8, 0x17u8, 0x16u8, 0x15u8, 0x14u8, 0x13u8, 0x12u8, + /// 0x11u8, 0x10u8, 0x0fu8, 0x0eu8, 0x0du8, 0x0cu8, 0x0bu8, 0x0au8, /// ]); /// assert_eq!( /// Ipv6Addr::new( - /// 0x1918, 0x1716, - /// 0x1514, 0x1312, - /// 0x1110, 0x0f0e, - /// 0x0d0c, 0x0b0a + /// 0x1918, 0x1716, 0x1514, 0x1312, + /// 0x1110, 0x0f0e, 0x0d0c, 0x0b0a, /// ), /// addr /// ); @@ -2190,15 +2186,13 @@ impl From<[u8; 16]> for Ipv6Addr { /// use std::net::Ipv6Addr; /// /// let addr = Ipv6Addr::from([ - /// 25u8, 24u8, 23u8, 22u8, 21u8, 20u8, 19u8, 18u8, - /// 17u8, 16u8, 15u8, 14u8, 13u8, 12u8, 11u8, 10u8, + /// 0x19u8, 0x18u8, 0x17u8, 0x16u8, 0x15u8, 0x14u8, 0x13u8, 0x12u8, + /// 0x11u8, 0x10u8, 0x0fu8, 0x0eu8, 0x0du8, 0x0cu8, 0x0bu8, 0x0au8, /// ]); /// assert_eq!( /// Ipv6Addr::new( - /// 0x1918, 0x1716, - /// 0x1514, 0x1312, - /// 0x1110, 0x0f0e, - /// 0x0d0c, 0x0b0a + /// 0x1918, 0x1716, 0x1514, 0x1312, + /// 0x1110, 0x0f0e, 0x0d0c, 0x0b0a, /// ), /// addr /// ); @@ -2219,15 +2213,13 @@ impl From<[u16; 8]> for Ipv6Addr { /// use std::net::Ipv6Addr; /// /// let addr = Ipv6Addr::from([ - /// 525u16, 524u16, 523u16, 522u16, - /// 521u16, 520u16, 519u16, 518u16, + /// 0x20du16, 0x20cu16, 0x20bu16, 0x20au16, + /// 0x209u16, 0x208u16, 0x207u16, 0x206u16, /// ]); /// assert_eq!( /// Ipv6Addr::new( - /// 0x20d, 0x20c, - /// 0x20b, 0x20a, - /// 0x209, 0x208, - /// 0x207, 0x206 + /// 0x20d, 0x20c, 0x20b, 0x20a, + /// 0x209, 0x208, 0x207, 0x206, /// ), /// addr /// ); @@ -2249,15 +2241,13 @@ impl From<[u8; 16]> for IpAddr { /// use std::net::{IpAddr, Ipv6Addr}; /// /// let addr = IpAddr::from([ - /// 25u8, 24u8, 23u8, 22u8, 21u8, 20u8, 19u8, 18u8, - /// 17u8, 16u8, 15u8, 14u8, 13u8, 12u8, 11u8, 10u8, + /// 0x19u8, 0x18u8, 0x17u8, 0x16u8, 0x15u8, 0x14u8, 0x13u8, 0x12u8, + /// 0x11u8, 0x10u8, 0x0fu8, 0x0eu8, 0x0du8, 0x0cu8, 0x0bu8, 0x0au8, /// ]); /// assert_eq!( /// IpAddr::V6(Ipv6Addr::new( - /// 0x1918, 0x1716, - /// 0x1514, 0x1312, - /// 0x1110, 0x0f0e, - /// 0x0d0c, 0x0b0a + /// 0x1918, 0x1716, 0x1514, 0x1312, + /// 0x1110, 0x0f0e, 0x0d0c, 0x0b0a, /// )), /// addr /// ); @@ -2278,15 +2268,13 @@ impl From<[u16; 8]> for IpAddr { /// use std::net::{IpAddr, Ipv6Addr}; /// /// let addr = IpAddr::from([ - /// 525u16, 524u16, 523u16, 522u16, - /// 521u16, 520u16, 519u16, 518u16, + /// 0x20du16, 0x20cu16, 0x20bu16, 0x20au16, + /// 0x209u16, 0x208u16, 0x207u16, 0x206u16, /// ]); /// assert_eq!( /// IpAddr::V6(Ipv6Addr::new( - /// 0x20d, 0x20c, - /// 0x20b, 0x20a, - /// 0x209, 0x208, - /// 0x207, 0x206 + /// 0x20d, 0x20c, 0x20b, 0x20a, + /// 0x209, 0x208, 0x207, 0x206, /// )), /// addr /// ); From 9e0a7b99b5d3677d3c90b11b57ec56a6a2c4f162 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonathan=20D=C3=B6nszelmann?= Date: Sun, 13 Oct 2024 21:08:47 +0200 Subject: [PATCH 262/357] rename rcbox in other places as per review comments --- library/alloc/src/rc.rs | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index e6f27f53639..e98ae7c31ad 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -289,7 +289,7 @@ struct RcInner { } /// Calculate layout for `RcInner` using the inner value's layout -fn rcbox_layout_for_value_layout(layout: Layout) -> Layout { +fn rc_inner_layout_for_value_layout(layout: Layout) -> Layout { // Calculate layout using the given value layout. // Previously, layout was calculated on the expression // `&*(ptr as *const RcInner)`, but this created a misaligned @@ -2009,17 +2009,17 @@ impl Rc { /// Allocates an `RcInner` with sufficient space for /// a possibly-unsized inner value where the value has the layout provided. /// - /// The function `mem_to_rcbox` is called with the data pointer + /// The function `mem_to_rc_inner` is called with the data pointer /// and must return back a (potentially fat)-pointer for the `RcInner`. #[cfg(not(no_global_oom_handling))] unsafe fn allocate_for_layout( value_layout: Layout, allocate: impl FnOnce(Layout) -> Result, AllocError>, - mem_to_rcbox: impl FnOnce(*mut u8) -> *mut RcInner, + mem_to_rc_inner: impl FnOnce(*mut u8) -> *mut RcInner, ) -> *mut RcInner { - let layout = rcbox_layout_for_value_layout(value_layout); + let layout = rc_inner_layout_for_value_layout(value_layout); unsafe { - Rc::try_allocate_for_layout(value_layout, allocate, mem_to_rcbox) + Rc::try_allocate_for_layout(value_layout, allocate, mem_to_rc_inner) .unwrap_or_else(|_| handle_alloc_error(layout)) } } @@ -2028,21 +2028,21 @@ impl Rc { /// a possibly-unsized inner value where the value has the layout provided, /// returning an error if allocation fails. /// - /// The function `mem_to_rcbox` is called with the data pointer + /// The function `mem_to_rc_inner` is called with the data pointer /// and must return back a (potentially fat)-pointer for the `RcInner`. #[inline] unsafe fn try_allocate_for_layout( value_layout: Layout, allocate: impl FnOnce(Layout) -> Result, AllocError>, - mem_to_rcbox: impl FnOnce(*mut u8) -> *mut RcInner, + mem_to_rc_inner: impl FnOnce(*mut u8) -> *mut RcInner, ) -> Result<*mut RcInner, AllocError> { - let layout = rcbox_layout_for_value_layout(value_layout); + let layout = rc_inner_layout_for_value_layout(value_layout); // Allocate for the layout. let ptr = allocate(layout)?; // Initialize the RcInner - let inner = mem_to_rcbox(ptr.as_non_null_ptr().as_ptr()); + let inner = mem_to_rc_inner(ptr.as_non_null_ptr().as_ptr()); unsafe { debug_assert_eq!(Layout::for_value_raw(inner), layout); @@ -3784,7 +3784,7 @@ impl UniqueRcUninit { let ptr = unsafe { Rc::allocate_for_layout( layout, - |layout_for_rcbox| alloc.allocate(layout_for_rcbox), + |layout_for_rc_inner| alloc.allocate(layout_for_rc_inner), |mem| mem.with_metadata_of(ptr::from_ref(for_value) as *const RcInner), ) }; @@ -3820,10 +3820,10 @@ impl Drop for UniqueRcUninit { // * new() produced a pointer safe to deallocate. // * We own the pointer unless into_rc() was called, which forgets us. unsafe { - self.alloc - .take() - .unwrap() - .deallocate(self.ptr.cast(), rcbox_layout_for_value_layout(self.layout_for_value)); + self.alloc.take().unwrap().deallocate( + self.ptr.cast(), + rc_inner_layout_for_value_layout(self.layout_for_value), + ); } } } From d858dfedbbde119f2ea707fea253e99c824ec252 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Mon, 14 Oct 2024 05:30:45 +0900 Subject: [PATCH 263/357] Fix clobber_abi and disallow SVE-related registers in Arm64EC inline assembly --- compiler/rustc_target/src/asm/aarch64.rs | 37 ++++++++++++------------ compiler/rustc_target/src/asm/mod.rs | 17 +++++++++-- tests/codegen/asm-arm64ec-clobbers.rs | 36 +++++++++++++++++++++++ tests/ui/asm/aarch64/aarch64-sve.rs | 28 ++++++++++++++++++ tests/ui/asm/aarch64/arm64ec-sve.rs | 31 ++++++++++++++++++++ tests/ui/asm/aarch64/arm64ec-sve.stderr | 14 +++++++++ 6 files changed, 143 insertions(+), 20 deletions(-) create mode 100644 tests/codegen/asm-arm64ec-clobbers.rs create mode 100644 tests/ui/asm/aarch64/aarch64-sve.rs create mode 100644 tests/ui/asm/aarch64/arm64ec-sve.rs create mode 100644 tests/ui/asm/aarch64/arm64ec-sve.stderr diff --git a/compiler/rustc_target/src/asm/aarch64.rs b/compiler/rustc_target/src/asm/aarch64.rs index 74970a26b23..fdd9adabc8e 100644 --- a/compiler/rustc_target/src/asm/aarch64.rs +++ b/compiler/rustc_target/src/asm/aarch64.rs @@ -64,6 +64,7 @@ impl AArch64InlineAsmRegClass { neon: I8, I16, I32, I64, F16, F32, F64, F128, VecI8(8), VecI16(4), VecI32(2), VecI64(1), VecF16(4), VecF32(2), VecF64(1), VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF16(8), VecF32(4), VecF64(2); + // Note: When adding support for SVE vector types, they must be rejected for Arm64EC. }, Self::preg => &[], } @@ -96,7 +97,7 @@ fn restricted_for_arm64ec( _is_clobber: bool, ) -> Result<(), &'static str> { if arch == InlineAsmArch::Arm64EC { - Err("x13, x14, x23, x24, x28, v16-v31 cannot be used for Arm64EC") + Err("x13, x14, x23, x24, x28, v16-v31, p*, ffr cannot be used for Arm64EC") } else { Ok(()) } @@ -165,23 +166,23 @@ def_regs! { v29: vreg = ["v29", "b29", "h29", "s29", "d29", "q29", "z29"] % restricted_for_arm64ec, v30: vreg = ["v30", "b30", "h30", "s30", "d30", "q30", "z30"] % restricted_for_arm64ec, v31: vreg = ["v31", "b31", "h31", "s31", "d31", "q31", "z31"] % restricted_for_arm64ec, - p0: preg = ["p0"], - p1: preg = ["p1"], - p2: preg = ["p2"], - p3: preg = ["p3"], - p4: preg = ["p4"], - p5: preg = ["p5"], - p6: preg = ["p6"], - p7: preg = ["p7"], - p8: preg = ["p8"], - p9: preg = ["p9"], - p10: preg = ["p10"], - p11: preg = ["p11"], - p12: preg = ["p12"], - p13: preg = ["p13"], - p14: preg = ["p14"], - p15: preg = ["p15"], - ffr: preg = ["ffr"], + p0: preg = ["p0"] % restricted_for_arm64ec, + p1: preg = ["p1"] % restricted_for_arm64ec, + p2: preg = ["p2"] % restricted_for_arm64ec, + p3: preg = ["p3"] % restricted_for_arm64ec, + p4: preg = ["p4"] % restricted_for_arm64ec, + p5: preg = ["p5"] % restricted_for_arm64ec, + p6: preg = ["p6"] % restricted_for_arm64ec, + p7: preg = ["p7"] % restricted_for_arm64ec, + p8: preg = ["p8"] % restricted_for_arm64ec, + p9: preg = ["p9"] % restricted_for_arm64ec, + p10: preg = ["p10"] % restricted_for_arm64ec, + p11: preg = ["p11"] % restricted_for_arm64ec, + p12: preg = ["p12"] % restricted_for_arm64ec, + p13: preg = ["p13"] % restricted_for_arm64ec, + p14: preg = ["p14"] % restricted_for_arm64ec, + p15: preg = ["p15"] % restricted_for_arm64ec, + ffr: preg = ["ffr"] % restricted_for_arm64ec, #error = ["x19", "w19"] => "x19 is used internally by LLVM and cannot be used as an operand for inline asm", #error = ["x29", "w29", "fp", "wfp"] => diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs index 73ae1ae96ae..4b539eb8e20 100644 --- a/compiler/rustc_target/src/asm/mod.rs +++ b/compiler/rustc_target/src/asm/mod.rs @@ -890,6 +890,7 @@ pub enum InlineAsmClobberAbi { Arm, AArch64, AArch64NoX18, + Arm64EC, RiscV, LoongArch, S390x, @@ -932,7 +933,7 @@ impl InlineAsmClobberAbi { _ => Err(&["C", "system", "efiapi"]), }, InlineAsmArch::Arm64EC => match name { - "C" | "system" => Ok(InlineAsmClobberAbi::AArch64NoX18), + "C" | "system" => Ok(InlineAsmClobberAbi::Arm64EC), _ => Err(&["C", "system"]), }, InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => match name { @@ -1033,7 +1034,6 @@ impl InlineAsmClobberAbi { p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, ffr, - } }, InlineAsmClobberAbi::AArch64NoX18 => clobbered_regs! { @@ -1052,7 +1052,20 @@ impl InlineAsmClobberAbi { p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, ffr, + } + }, + InlineAsmClobberAbi::Arm64EC => clobbered_regs! { + AArch64 AArch64InlineAsmReg { + // x13 and x14 cannot be used in Arm64EC. + x0, x1, x2, x3, x4, x5, x6, x7, + x8, x9, x10, x11, x12, x15, + x16, x17, x30, + // Technically the low 64 bits of v8-v15 are preserved, but + // we have no way of expressing this using clobbers. + v0, v1, v2, v3, v4, v5, v6, v7, + v8, v9, v10, v11, v12, v13, v14, v15, + // v16-v31, p*, and ffr cannot be used in Arm64EC. } }, InlineAsmClobberAbi::Arm => clobbered_regs! { diff --git a/tests/codegen/asm-arm64ec-clobbers.rs b/tests/codegen/asm-arm64ec-clobbers.rs new file mode 100644 index 00000000000..2ec61907947 --- /dev/null +++ b/tests/codegen/asm-arm64ec-clobbers.rs @@ -0,0 +1,36 @@ +//@ assembly-output: emit-asm +//@ compile-flags: --target arm64ec-pc-windows-msvc +//@ needs-llvm-components: aarch64 + +#![crate_type = "rlib"] +#![feature(no_core, rustc_attrs, lang_items, asm_experimental_arch)] +#![no_core] + +#[lang = "sized"] +trait Sized {} + +#[rustc_builtin_macro] +macro_rules! asm { + () => {}; +} + +// CHECK-LABEL: @cc_clobber +// CHECK: call void asm sideeffect "", "~{cc}"() +#[no_mangle] +pub unsafe fn cc_clobber() { + asm!("", options(nostack, nomem)); +} + +// CHECK-LABEL: @no_clobber +// CHECK: call void asm sideeffect "", ""() +#[no_mangle] +pub unsafe fn no_clobber() { + asm!("", options(nostack, nomem, preserves_flags)); +} + +// CHECK-LABEL: @clobber_abi +// CHECK: asm sideeffect "", "={w0},={w1},={w2},={w3},={w4},={w5},={w6},={w7},={w8},={w9},={w10},={w11},={w12},={w15},={w16},={w17},={w30},={q0},={q1},={q2},={q3},={q4},={q5},={q6},={q7},={q8},={q9},={q10},={q11},={q12},={q13},={q14},={q15}"() +#[no_mangle] +pub unsafe fn clobber_abi() { + asm!("", clobber_abi("C"), options(nostack, nomem, preserves_flags)); +} diff --git a/tests/ui/asm/aarch64/aarch64-sve.rs b/tests/ui/asm/aarch64/aarch64-sve.rs new file mode 100644 index 00000000000..8cdc9dd4266 --- /dev/null +++ b/tests/ui/asm/aarch64/aarch64-sve.rs @@ -0,0 +1,28 @@ +//@ only-aarch64 +//@ build-pass +//@ needs-asm-support + +#![crate_type = "rlib"] +#![feature(no_core, rustc_attrs, lang_items)] +#![no_core] + +// AArch64 test corresponding to arm64ec-sve.rs. + +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} + +impl Copy for f64 {} + +#[rustc_builtin_macro] +macro_rules! asm { + () => {}; +} + +fn f(x: f64) { + unsafe { + asm!("", out("p0") _); + asm!("", out("ffr") _); + } +} diff --git a/tests/ui/asm/aarch64/arm64ec-sve.rs b/tests/ui/asm/aarch64/arm64ec-sve.rs new file mode 100644 index 00000000000..389b365a754 --- /dev/null +++ b/tests/ui/asm/aarch64/arm64ec-sve.rs @@ -0,0 +1,31 @@ +//@ compile-flags: --target arm64ec-pc-windows-msvc +//@ needs-asm-support +//@ needs-llvm-components: aarch64 + +#![crate_type = "rlib"] +#![feature(no_core, rustc_attrs, lang_items, asm_experimental_arch)] +#![no_core] + +// SVE cannot be used for Arm64EC +// https://github.com/rust-lang/rust/pull/131332#issuecomment-2401189142 + +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} + +impl Copy for f64 {} + +#[rustc_builtin_macro] +macro_rules! asm { + () => {}; +} + +fn f(x: f64) { + unsafe { + asm!("", out("p0") _); + //~^ ERROR cannot use register `p0` + asm!("", out("ffr") _); + //~^ ERROR cannot use register `ffr` + } +} diff --git a/tests/ui/asm/aarch64/arm64ec-sve.stderr b/tests/ui/asm/aarch64/arm64ec-sve.stderr new file mode 100644 index 00000000000..3e1a5d57004 --- /dev/null +++ b/tests/ui/asm/aarch64/arm64ec-sve.stderr @@ -0,0 +1,14 @@ +error: cannot use register `p0`: x13, x14, x23, x24, x28, v16-v31, p*, ffr cannot be used for Arm64EC + --> $DIR/arm64ec-sve.rs:26:18 + | +LL | asm!("", out("p0") _); + | ^^^^^^^^^^^ + +error: cannot use register `ffr`: x13, x14, x23, x24, x28, v16-v31, p*, ffr cannot be used for Arm64EC + --> $DIR/arm64ec-sve.rs:28:18 + | +LL | asm!("", out("ffr") _); + | ^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + From 67ebb6c20b0cf8dfb587fd1085413232ccd8260c Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Mon, 14 Oct 2024 06:04:07 +0900 Subject: [PATCH 264/357] Fix AArch64InlineAsmReg::emit --- compiler/rustc_codegen_llvm/src/asm.rs | 51 ++------------------ compiler/rustc_target/src/asm/aarch64.rs | 60 ++++++++++++++++++++++-- 2 files changed, 62 insertions(+), 49 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index 298cac2fd6e..d1d7d0cf4ce 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -542,57 +542,16 @@ fn xmm_reg_index(reg: InlineAsmReg) -> Option { /// If the register is an AArch64 integer register then return its index. fn a64_reg_index(reg: InlineAsmReg) -> Option { - use AArch64InlineAsmReg::*; - // Unlike `a64_vreg_index`, we can't subtract `x0` to get the u32 because - // `x19` and `x29` are missing and the integer constants for the - // `x0`..`x30` enum variants don't all match the register number. E.g. the - // integer constant for `x18` is 18, but the constant for `x20` is 19. - Some(match reg { - InlineAsmReg::AArch64(r) => match r { - x0 => 0, - x1 => 1, - x2 => 2, - x3 => 3, - x4 => 4, - x5 => 5, - x6 => 6, - x7 => 7, - x8 => 8, - x9 => 9, - x10 => 10, - x11 => 11, - x12 => 12, - x13 => 13, - x14 => 14, - x15 => 15, - x16 => 16, - x17 => 17, - x18 => 18, - // x19 is reserved - x20 => 20, - x21 => 21, - x22 => 22, - x23 => 23, - x24 => 24, - x25 => 25, - x26 => 26, - x27 => 27, - x28 => 28, - // x29 is reserved - x30 => 30, - _ => return None, - }, - _ => return None, - }) + match reg { + InlineAsmReg::AArch64(r) => r.reg_index(), + _ => None, + } } /// If the register is an AArch64 vector register then return its index. fn a64_vreg_index(reg: InlineAsmReg) -> Option { - use AArch64InlineAsmReg::*; match reg { - InlineAsmReg::AArch64(reg) if reg as u32 >= v0 as u32 && reg as u32 <= v31 as u32 => { - Some(reg as u32 - v0 as u32) - } + InlineAsmReg::AArch64(reg) => reg.vreg_index(), _ => None, } } diff --git a/compiler/rustc_target/src/asm/aarch64.rs b/compiler/rustc_target/src/asm/aarch64.rs index 74970a26b23..8b173f9bb99 100644 --- a/compiler/rustc_target/src/asm/aarch64.rs +++ b/compiler/rustc_target/src/asm/aarch64.rs @@ -200,12 +200,66 @@ impl AArch64InlineAsmReg { _arch: InlineAsmArch, modifier: Option, ) -> fmt::Result { - let (prefix, index) = if (self as u32) < Self::v0 as u32 { - (modifier.unwrap_or('x'), self as u32 - Self::x0 as u32) + let (prefix, index) = if let Some(index) = self.reg_index() { + (modifier.unwrap_or('x'), index) + } else if let Some(index) = self.vreg_index() { + (modifier.unwrap_or('v'), index) } else { - (modifier.unwrap_or('v'), self as u32 - Self::v0 as u32) + return out.write_str(self.name()); }; assert!(index < 32); write!(out, "{prefix}{index}") } + + /// If the register is an integer register then return its index. + pub fn reg_index(self) -> Option { + // Unlike `vreg_index`, we can't subtract `x0` to get the u32 because + // `x19` and `x29` are missing and the integer constants for the + // `x0`..`x30` enum variants don't all match the register number. E.g. the + // integer constant for `x18` is 18, but the constant for `x20` is 19. + use AArch64InlineAsmReg::*; + Some(match self { + x0 => 0, + x1 => 1, + x2 => 2, + x3 => 3, + x4 => 4, + x5 => 5, + x6 => 6, + x7 => 7, + x8 => 8, + x9 => 9, + x10 => 10, + x11 => 11, + x12 => 12, + x13 => 13, + x14 => 14, + x15 => 15, + x16 => 16, + x17 => 17, + x18 => 18, + // x19 is reserved + x20 => 20, + x21 => 21, + x22 => 22, + x23 => 23, + x24 => 24, + x25 => 25, + x26 => 26, + x27 => 27, + x28 => 28, + // x29 is reserved + x30 => 30, + _ => return None, + }) + } + + /// If the register is a vector register then return its index. + pub fn vreg_index(self) -> Option { + use AArch64InlineAsmReg::*; + if self as u32 >= v0 as u32 && self as u32 <= v31 as u32 { + return Some(self as u32 - v0 as u32); + } + None + } } From ceced5322c9d2e3957e33e1944a3486731ccfa1e Mon Sep 17 00:00:00 2001 From: surechen Date: Wed, 9 Oct 2024 11:14:59 +0800 Subject: [PATCH 265/357] Special treatment empty tuple when suggest adding a string literal in format macro. For example: ```rust let s = "123"; println!({}, "sss", s); ``` Suggest: `println!("{:?} {} {}", {}, "sss", s);` fixes #130170 --- compiler/rustc_builtin_macros/src/format.rs | 22 +++++++-- ...y-block-unit-tuple-suggestion-130170.fixed | 13 ++++++ ...mpty-block-unit-tuple-suggestion-130170.rs | 13 ++++++ ...-block-unit-tuple-suggestion-130170.stderr | 46 +++++++++++++++++++ 4 files changed, 90 insertions(+), 4 deletions(-) create mode 100644 tests/ui/macros/format-empty-block-unit-tuple-suggestion-130170.fixed create mode 100644 tests/ui/macros/format-empty-block-unit-tuple-suggestion-130170.rs create mode 100644 tests/ui/macros/format-empty-block-unit-tuple-suggestion-130170.stderr diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs index 9501e93bad5..32730ac3867 100644 --- a/compiler/rustc_builtin_macros/src/format.rs +++ b/compiler/rustc_builtin_macros/src/format.rs @@ -195,12 +195,26 @@ fn make_format_args( Applicability::MaybeIncorrect, ); } else { - let sugg_fmt = match args.explicit_args().len() { - 0 => "{}".to_string(), - count => { - format!("{}{{}}", "{} ".repeat(count)) + // `{}` or `()` + let should_suggest = |kind: &ExprKind| -> bool { + match kind { + ExprKind::Block(b, None) if b.stmts.is_empty() => true, + ExprKind::Tup(v) if v.is_empty() => true, + _ => false, } }; + + let mut sugg_fmt = String::new(); + for kind in std::iter::once(&efmt.kind) + .chain(args.explicit_args().into_iter().map(|a| &a.expr.kind)) + { + sugg_fmt.push_str(if should_suggest(kind) { + "{:?} " + } else { + "{} " + }); + } + sugg_fmt = sugg_fmt.trim_end().to_string(); err.span_suggestion( unexpanded_fmt_span.shrink_to_lo(), "you might be missing a string literal to format with", diff --git a/tests/ui/macros/format-empty-block-unit-tuple-suggestion-130170.fixed b/tests/ui/macros/format-empty-block-unit-tuple-suggestion-130170.fixed new file mode 100644 index 00000000000..1ca5125fe8b --- /dev/null +++ b/tests/ui/macros/format-empty-block-unit-tuple-suggestion-130170.fixed @@ -0,0 +1,13 @@ +//@ run-rustfix + +fn main() { + let s = "123"; + println!("{:?} {} {}", {}, "sss", s); + //~^ ERROR format argument must be a string literal + println!("{:?}", {}); + //~^ ERROR format argument must be a string literal + println!("{} {} {} {:?}", s, "sss", s, {}); + //~^ ERROR format argument must be a string literal + println!("{:?} {} {:?}", (), s, {}); + //~^ ERROR format argument must be a string literal +} diff --git a/tests/ui/macros/format-empty-block-unit-tuple-suggestion-130170.rs b/tests/ui/macros/format-empty-block-unit-tuple-suggestion-130170.rs new file mode 100644 index 00000000000..c09b2a04061 --- /dev/null +++ b/tests/ui/macros/format-empty-block-unit-tuple-suggestion-130170.rs @@ -0,0 +1,13 @@ +//@ run-rustfix + +fn main() { + let s = "123"; + println!({}, "sss", s); + //~^ ERROR format argument must be a string literal + println!({}); + //~^ ERROR format argument must be a string literal + println!(s, "sss", s, {}); + //~^ ERROR format argument must be a string literal + println!((), s, {}); + //~^ ERROR format argument must be a string literal +} diff --git a/tests/ui/macros/format-empty-block-unit-tuple-suggestion-130170.stderr b/tests/ui/macros/format-empty-block-unit-tuple-suggestion-130170.stderr new file mode 100644 index 00000000000..81fca8c03cc --- /dev/null +++ b/tests/ui/macros/format-empty-block-unit-tuple-suggestion-130170.stderr @@ -0,0 +1,46 @@ +error: format argument must be a string literal + --> $DIR/format-empty-block-unit-tuple-suggestion-130170.rs:5:14 + | +LL | println!({}, "sss", s); + | ^^ + | +help: you might be missing a string literal to format with + | +LL | println!("{:?} {} {}", {}, "sss", s); + | +++++++++++++ + +error: format argument must be a string literal + --> $DIR/format-empty-block-unit-tuple-suggestion-130170.rs:7:14 + | +LL | println!({}); + | ^^ + | +help: you might be missing a string literal to format with + | +LL | println!("{:?}", {}); + | +++++++ + +error: format argument must be a string literal + --> $DIR/format-empty-block-unit-tuple-suggestion-130170.rs:9:14 + | +LL | println!(s, "sss", s, {}); + | ^ + | +help: you might be missing a string literal to format with + | +LL | println!("{} {} {} {:?}", s, "sss", s, {}); + | ++++++++++++++++ + +error: format argument must be a string literal + --> $DIR/format-empty-block-unit-tuple-suggestion-130170.rs:11:14 + | +LL | println!((), s, {}); + | ^^ + | +help: you might be missing a string literal to format with + | +LL | println!("{:?} {} {:?}", (), s, {}); + | +++++++++++++++ + +error: aborting due to 4 previous errors + From f8ac1c44dba23d425cb630a9e8b334a5781462fb Mon Sep 17 00:00:00 2001 From: Ayush Singh Date: Sat, 31 Aug 2024 03:02:30 +0530 Subject: [PATCH 266/357] uefi: Implement getcwd and chdir - Using EFI Shell Protocol. These functions do not make much sense unless a shell is present. - Return the exe dir in case shell protocol is missing. Signed-off-by: Ayush Singh --- library/std/src/sys/pal/uefi/helpers.rs | 24 ++++++---- library/std/src/sys/pal/uefi/os.rs | 63 +++++++++++++++++++++++-- 2 files changed, 73 insertions(+), 14 deletions(-) diff --git a/library/std/src/sys/pal/uefi/helpers.rs b/library/std/src/sys/pal/uefi/helpers.rs index bd8a6684b64..4ced7065c82 100644 --- a/library/std/src/sys/pal/uefi/helpers.rs +++ b/library/std/src/sys/pal/uefi/helpers.rs @@ -177,16 +177,8 @@ pub(crate) fn device_path_to_text(path: NonNull) -> io::R ) }; - // SAFETY: `convert_device_path_to_text` returns a pointer to a null-terminated UTF-16 - // string, and that string cannot be deallocated prior to dropping the `WStrUnits`, so - // it's safe for `WStrUnits` to use. - let path_len = unsafe { - WStrUnits::new(path_ptr) - .ok_or(io::const_io_error!(io::ErrorKind::InvalidData, "Invalid path"))? - .count() - }; - - let path = OsString::from_wide(unsafe { slice::from_raw_parts(path_ptr.cast(), path_len) }); + let path = os_string_from_raw(path_ptr) + .ok_or(io::const_io_error!(io::ErrorKind::InvalidData, "Invalid path"))?; if let Some(boot_services) = crate::os::uefi::env::boot_services() { let boot_services: NonNull = boot_services.cast(); @@ -420,3 +412,15 @@ impl Drop for OwnedTable { unsafe { crate::alloc::dealloc(self.ptr as *mut u8, self.layout) }; } } + +/// Create OsString from a pointer to NULL terminated UTF-16 string +pub(crate) fn os_string_from_raw(ptr: *mut r_efi::efi::Char16) -> Option { + let path_len = unsafe { WStrUnits::new(ptr)?.count() }; + Some(OsString::from_wide(unsafe { slice::from_raw_parts(ptr.cast(), path_len) })) +} + +/// Create NULL terminated UTF-16 string +pub(crate) fn os_string_to_raw(s: &OsStr) -> Option> { + let temp = s.encode_wide().chain(Some(0)).collect::>(); + if temp[..temp.len() - 1].contains(&0) { None } else { Some(temp) } +} diff --git a/library/std/src/sys/pal/uefi/os.rs b/library/std/src/sys/pal/uefi/os.rs index 9aee67d622f..4eb7698b43a 100644 --- a/library/std/src/sys/pal/uefi/os.rs +++ b/library/std/src/sys/pal/uefi/os.rs @@ -1,7 +1,7 @@ use r_efi::efi::Status; use r_efi::efi::protocols::{device_path, loaded_image_device_path}; -use super::{RawOsError, helpers, unsupported}; +use super::{RawOsError, helpers, unsupported_err}; use crate::error::Error as StdError; use crate::ffi::{OsStr, OsString}; use crate::marker::PhantomData; @@ -125,11 +125,32 @@ pub fn error_string(errno: RawOsError) -> String { } pub fn getcwd() -> io::Result { - unsupported() + match uefi_shell::open_shell() { + Some(shell) => { + // SAFETY: path_ptr is managed by UEFI shell and should not be deallocated + let path_ptr = unsafe { ((*shell.as_ptr()).get_cur_dir)(crate::ptr::null_mut()) }; + helpers::os_string_from_raw(path_ptr) + .map(PathBuf::from) + .ok_or(io::const_io_error!(io::ErrorKind::InvalidData, "Invalid path")) + } + None => { + let mut t = current_exe()?; + // SAFETY: This should never fail since the disk prefix will be present even for root + // executables + assert!(t.pop()); + Ok(t) + } + } } -pub fn chdir(_: &path::Path) -> io::Result<()> { - unsupported() +pub fn chdir(p: &path::Path) -> io::Result<()> { + let shell = uefi_shell::open_shell().ok_or(unsupported_err())?; + + let mut p = helpers::os_string_to_raw(p.as_os_str()) + .ok_or(io::const_io_error!(io::ErrorKind::InvalidData, "Invalid path"))?; + + let r = unsafe { ((*shell.as_ptr()).set_cur_dir)(crate::ptr::null_mut(), p.as_mut_ptr()) }; + if r.is_error() { Err(io::Error::from_raw_os_error(r.as_usize())) } else { Ok(()) } } pub struct SplitPaths<'a>(!, PhantomData<&'a ()>); @@ -239,3 +260,37 @@ pub fn exit(code: i32) -> ! { pub fn getpid() -> u32 { panic!("no pids on this platform") } + +mod uefi_shell { + use r_efi::protocols::shell; + + use super::super::helpers; + use crate::ptr::NonNull; + use crate::sync::atomic::{AtomicPtr, Ordering}; + + pub fn open_shell() -> Option> { + static LAST_VALID_HANDLE: AtomicPtr = + AtomicPtr::new(crate::ptr::null_mut()); + + if let Some(handle) = NonNull::new(LAST_VALID_HANDLE.load(Ordering::Acquire)) { + if let Ok(protocol) = helpers::open_protocol::( + handle, + r_efi::protocols::shell::PROTOCOL_GUID, + ) { + return Some(protocol); + } + } + + let handles = helpers::locate_handles(shell::PROTOCOL_GUID).ok()?; + for handle in handles { + if let Ok(protocol) = + helpers::open_protocol::(handle, shell::PROTOCOL_GUID) + { + LAST_VALID_HANDLE.store(handle.as_ptr(), Ordering::Release); + return Some(protocol); + } + } + + None + } +} From 874b03ec28beba617951efef505fe3e320900454 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 10 Oct 2024 11:21:16 +1100 Subject: [PATCH 267/357] Remove `ResultsCursor::contains`. It's hardly worth it, and it needs to be removed so that `GenKillAnalysis` can be removed. --- compiler/rustc_mir_dataflow/src/framework/cursor.rs | 11 ----------- .../rustc_mir_dataflow/src/impls/storage_liveness.rs | 2 +- compiler/rustc_mir_transform/src/elaborate_drops.rs | 2 +- compiler/rustc_mir_transform/src/ref_prop.rs | 2 +- .../clippy/clippy_utils/src/mir/possible_borrower.rs | 4 ++-- 5 files changed, 5 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_mir_dataflow/src/framework/cursor.rs b/compiler/rustc_mir_dataflow/src/framework/cursor.rs index 7cfaef22689..5ebb343f4e1 100644 --- a/compiler/rustc_mir_dataflow/src/framework/cursor.rs +++ b/compiler/rustc_mir_dataflow/src/framework/cursor.rs @@ -7,7 +7,6 @@ use rustc_index::bit_set::BitSet; use rustc_middle::mir::{self, BasicBlock, Location}; use super::{Analysis, Direction, Effect, EffectIndex, Results}; -use crate::framework::BitSetExt; /// Allows random access inspection of the results of a dataflow analysis. /// @@ -221,16 +220,6 @@ where } } -impl<'mir, 'tcx, A> ResultsCursor<'mir, 'tcx, A> -where - A: crate::GenKillAnalysis<'tcx>, - A::Domain: BitSetExt, -{ - pub fn contains(&self, elem: A::Idx) -> bool { - self.get().contains(elem) - } -} - #[derive(Clone, Copy, Debug)] struct CursorPosition { block: BasicBlock, diff --git a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs index 34ac5809a2e..fe223a3abd8 100644 --- a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs +++ b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs @@ -364,7 +364,7 @@ where fn visit_local(&mut self, local: Local, context: PlaceContext, loc: Location) { if PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) == context { self.borrowed_locals.seek_before_primary_effect(loc); - if !self.borrowed_locals.contains(local) { + if !self.borrowed_locals.get().contains(local) { self.trans.kill(local); } } diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs index c35aec42408..f4ac4d9fee6 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drops.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs @@ -133,7 +133,7 @@ impl InitializationData<'_, '_> { } fn maybe_live_dead(&self, path: MovePathIndex) -> (bool, bool) { - (self.inits.contains(path), self.uninits.contains(path)) + (self.inits.get().contains(path), self.uninits.get().contains(path)) } } diff --git a/compiler/rustc_mir_transform/src/ref_prop.rs b/compiler/rustc_mir_transform/src/ref_prop.rs index a62a892716f..53e53d9d5ba 100644 --- a/compiler/rustc_mir_transform/src/ref_prop.rs +++ b/compiler/rustc_mir_transform/src/ref_prop.rs @@ -179,7 +179,7 @@ fn compute_replacement<'tcx>( } else { // This is a proper dereference. We can only allow it if `target` is live. maybe_dead.seek_after_primary_effect(loc); - let maybe_dead = maybe_dead.contains(target.local); + let maybe_dead = maybe_dead.get().contains(target.local); !maybe_dead } }; diff --git a/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs b/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs index 6bb434a466f..a00196c4b51 100644 --- a/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs +++ b/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs @@ -213,7 +213,7 @@ impl<'b, 'tcx> PossibleBorrowerMap<'b, 'tcx> { self.bitset.0.clear(); let maybe_live = &mut self.maybe_live; if let Some(bitset) = self.map.get(&borrowed) { - for b in bitset.iter().filter(move |b| maybe_live.contains(*b)) { + for b in bitset.iter().filter(move |b| maybe_live.get().contains(*b)) { self.bitset.0.insert(b); } } else { @@ -238,6 +238,6 @@ impl<'b, 'tcx> PossibleBorrowerMap<'b, 'tcx> { pub fn local_is_alive_at(&mut self, local: mir::Local, at: mir::Location) -> bool { self.maybe_live.seek_after_primary_effect(at); - self.maybe_live.contains(local) + self.maybe_live.get().contains(local) } } From e0b83c34c3320de1f16c8f888d12f3b1aee18a26 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 10 Oct 2024 06:41:03 +1100 Subject: [PATCH 268/357] Remove `Engine::new_gen_kill`. This is an alternative to `Engine::new_generic` for gen/kill analyses. It's supposed to be an optimization, but it has negligible effect. The commit merges `Engine::new_generic` into `Engine::new`. This allows the removal of various other things: `GenKillSet`, `gen_kill_statement_effects_in_block`, `is_cfg_cyclic`. --- compiler/rustc_middle/src/mir/basic_blocks.rs | 7 -- .../src/framework/direction.rs | 66 ++------------ .../src/framework/engine.rs | 88 ++----------------- .../rustc_mir_dataflow/src/framework/mod.rs | 53 +---------- 4 files changed, 17 insertions(+), 197 deletions(-) diff --git a/compiler/rustc_middle/src/mir/basic_blocks.rs b/compiler/rustc_middle/src/mir/basic_blocks.rs index 4602c918160..3eb563d7d6e 100644 --- a/compiler/rustc_middle/src/mir/basic_blocks.rs +++ b/compiler/rustc_middle/src/mir/basic_blocks.rs @@ -26,7 +26,6 @@ type SwitchSources = FxHashMap<(BasicBlock, BasicBlock), SmallVec<[Option; struct Cache { predecessors: OnceLock, switch_sources: OnceLock, - is_cyclic: OnceLock, reverse_postorder: OnceLock>, dominators: OnceLock>, } @@ -37,12 +36,6 @@ impl<'tcx> BasicBlocks<'tcx> { BasicBlocks { basic_blocks, cache: Cache::default() } } - /// Returns true if control-flow graph contains a cycle reachable from the `START_BLOCK`. - #[inline] - pub fn is_cfg_cyclic(&self) -> bool { - *self.cache.is_cyclic.get_or_init(|| graph::is_cyclic(self)) - } - pub fn dominators(&self) -> &Dominators { self.cache.dominators.get_or_init(|| dominators(self)) } diff --git a/compiler/rustc_mir_dataflow/src/framework/direction.rs b/compiler/rustc_mir_dataflow/src/framework/direction.rs index 88a9a78f8ad..3e01f0512c4 100644 --- a/compiler/rustc_mir_dataflow/src/framework/direction.rs +++ b/compiler/rustc_mir_dataflow/src/framework/direction.rs @@ -5,7 +5,7 @@ use rustc_middle::mir::{ }; use super::visitor::{ResultsVisitable, ResultsVisitor}; -use super::{Analysis, Effect, EffectIndex, GenKillAnalysis, GenKillSet, SwitchIntTarget}; +use super::{Analysis, Effect, EffectIndex, SwitchIntTarget}; pub trait Direction { const IS_FORWARD: bool; @@ -29,19 +29,10 @@ pub trait Direction { state: &mut A::Domain, block: BasicBlock, block_data: &'mir mir::BasicBlockData<'tcx>, - statement_effect: Option<&dyn Fn(BasicBlock, &mut A::Domain)>, ) -> TerminatorEdges<'mir, 'tcx> where A: Analysis<'tcx>; - fn gen_kill_statement_effects_in_block<'tcx, A>( - analysis: &mut A, - trans: &mut GenKillSet, - block: BasicBlock, - block_data: &mir::BasicBlockData<'tcx>, - ) where - A: GenKillAnalysis<'tcx>; - fn visit_results_in_block<'mir, 'tcx, D, R>( state: &mut D, block: BasicBlock, @@ -73,7 +64,6 @@ impl Direction for Backward { state: &mut A::Domain, block: BasicBlock, block_data: &'mir mir::BasicBlockData<'tcx>, - statement_effect: Option<&dyn Fn(BasicBlock, &mut A::Domain)>, ) -> TerminatorEdges<'mir, 'tcx> where A: Analysis<'tcx>, @@ -82,31 +72,12 @@ impl Direction for Backward { let location = Location { block, statement_index: block_data.statements.len() }; analysis.apply_before_terminator_effect(state, terminator, location); let edges = analysis.apply_terminator_effect(state, terminator, location); - if let Some(statement_effect) = statement_effect { - statement_effect(block, state) - } else { - for (statement_index, statement) in block_data.statements.iter().enumerate().rev() { - let location = Location { block, statement_index }; - analysis.apply_before_statement_effect(state, statement, location); - analysis.apply_statement_effect(state, statement, location); - } - } - edges - } - - fn gen_kill_statement_effects_in_block<'tcx, A>( - analysis: &mut A, - trans: &mut GenKillSet, - block: BasicBlock, - block_data: &mir::BasicBlockData<'tcx>, - ) where - A: GenKillAnalysis<'tcx>, - { for (statement_index, statement) in block_data.statements.iter().enumerate().rev() { let location = Location { block, statement_index }; - analysis.before_statement_effect(trans, statement, location); - analysis.statement_effect(trans, statement, location); + analysis.apply_before_statement_effect(state, statement, location); + analysis.apply_statement_effect(state, statement, location); } + edges } fn apply_effects_in_range<'tcx, A>( @@ -330,42 +301,21 @@ impl Direction for Forward { state: &mut A::Domain, block: BasicBlock, block_data: &'mir mir::BasicBlockData<'tcx>, - statement_effect: Option<&dyn Fn(BasicBlock, &mut A::Domain)>, ) -> TerminatorEdges<'mir, 'tcx> where A: Analysis<'tcx>, { - if let Some(statement_effect) = statement_effect { - statement_effect(block, state) - } else { - for (statement_index, statement) in block_data.statements.iter().enumerate() { - let location = Location { block, statement_index }; - analysis.apply_before_statement_effect(state, statement, location); - analysis.apply_statement_effect(state, statement, location); - } + for (statement_index, statement) in block_data.statements.iter().enumerate() { + let location = Location { block, statement_index }; + analysis.apply_before_statement_effect(state, statement, location); + analysis.apply_statement_effect(state, statement, location); } - let terminator = block_data.terminator(); let location = Location { block, statement_index: block_data.statements.len() }; analysis.apply_before_terminator_effect(state, terminator, location); analysis.apply_terminator_effect(state, terminator, location) } - fn gen_kill_statement_effects_in_block<'tcx, A>( - analysis: &mut A, - trans: &mut GenKillSet, - block: BasicBlock, - block_data: &mir::BasicBlockData<'tcx>, - ) where - A: GenKillAnalysis<'tcx>, - { - for (statement_index, statement) in block_data.statements.iter().enumerate() { - let location = Location { block, statement_index }; - analysis.before_statement_effect(trans, statement, location); - analysis.statement_effect(trans, statement, location); - } - } - fn apply_effects_in_range<'tcx, A>( analysis: &mut A, state: &mut A::Domain, diff --git a/compiler/rustc_mir_dataflow/src/framework/engine.rs b/compiler/rustc_mir_dataflow/src/framework/engine.rs index 9d50e57d668..d6853b6ef82 100644 --- a/compiler/rustc_mir_dataflow/src/framework/engine.rs +++ b/compiler/rustc_mir_dataflow/src/framework/engine.rs @@ -5,7 +5,7 @@ use std::path::PathBuf; use rustc_data_structures::work_queue::WorkQueue; use rustc_hir::def_id::DefId; -use rustc_index::{Idx, IndexVec}; +use rustc_index::IndexVec; use rustc_middle::bug; use rustc_middle::mir::{self, BasicBlock, create_dump_file, dump_enabled, traversal}; use rustc_middle::ty::TyCtxt; @@ -16,13 +16,12 @@ use {rustc_ast as ast, rustc_graphviz as dot}; use super::fmt::DebugWithContext; use super::{ - Analysis, AnalysisDomain, Direction, GenKill, GenKillAnalysis, GenKillSet, JoinSemiLattice, - ResultsCursor, ResultsVisitor, graphviz, visit_results, + Analysis, AnalysisDomain, Direction, JoinSemiLattice, ResultsCursor, ResultsVisitor, graphviz, + visit_results, }; use crate::errors::{ DuplicateValuesFor, PathMustEndInFilename, RequiresAnArgument, UnknownFormatter, }; -use crate::framework::BitSetExt; type EntrySets<'tcx, A> = IndexVec>::Domain>; @@ -82,53 +81,6 @@ where entry_sets: IndexVec, pass_name: Option<&'static str>, analysis: A, - - /// Cached, cumulative transfer functions for each block. - // - // FIXME(ecstaticmorse): This boxed `Fn` trait object is invoked inside a tight loop for - // gen/kill problems on cyclic CFGs. This is not ideal, but it doesn't seem to degrade - // performance in practice. I've tried a few ways to avoid this, but they have downsides. See - // the message for the commit that added this FIXME for more information. - apply_statement_trans_for_block: Option>, -} - -impl<'mir, 'tcx, A, D, T> Engine<'mir, 'tcx, A> -where - A: GenKillAnalysis<'tcx, Idx = T, Domain = D>, - D: Clone + JoinSemiLattice + GenKill + BitSetExt, - T: Idx, -{ - /// Creates a new `Engine` to solve a gen-kill dataflow problem. - pub fn new_gen_kill(tcx: TyCtxt<'tcx>, body: &'mir mir::Body<'tcx>, mut analysis: A) -> Self { - // If there are no back-edges in the control-flow graph, we only ever need to apply the - // transfer function for each block exactly once (assuming that we process blocks in RPO). - // - // In this case, there's no need to compute the block transfer functions ahead of time. - if !body.basic_blocks.is_cfg_cyclic() { - return Self::new(tcx, body, analysis, None); - } - - // Otherwise, compute and store the cumulative transfer function for each block. - - let identity = GenKillSet::identity(analysis.domain_size(body)); - let mut trans_for_block = IndexVec::from_elem(identity, &body.basic_blocks); - - for (block, block_data) in body.basic_blocks.iter_enumerated() { - let trans = &mut trans_for_block[block]; - A::Direction::gen_kill_statement_effects_in_block( - &mut analysis, - trans, - block, - block_data, - ); - } - - let apply_trans = Box::new(move |bb: BasicBlock, state: &mut A::Domain| { - trans_for_block[bb].apply(state); - }); - - Self::new(tcx, body, analysis, Some(apply_trans as Box<_>)) - } } impl<'mir, 'tcx, A, D> Engine<'mir, 'tcx, A> @@ -138,19 +90,7 @@ where { /// Creates a new `Engine` to solve a dataflow problem with an arbitrary transfer /// function. - /// - /// Gen-kill problems should use `new_gen_kill`, which will coalesce transfer functions for - /// better performance. - pub fn new_generic(tcx: TyCtxt<'tcx>, body: &'mir mir::Body<'tcx>, analysis: A) -> Self { - Self::new(tcx, body, analysis, None) - } - - fn new( - tcx: TyCtxt<'tcx>, - body: &'mir mir::Body<'tcx>, - analysis: A, - apply_statement_trans_for_block: Option>, - ) -> Self { + pub(crate) fn new(tcx: TyCtxt<'tcx>, body: &'mir mir::Body<'tcx>, analysis: A) -> Self { let mut entry_sets = IndexVec::from_fn_n(|_| analysis.bottom_value(body), body.basic_blocks.len()); analysis.initialize_start_block(body, &mut entry_sets[mir::START_BLOCK]); @@ -160,7 +100,7 @@ where bug!("`initialize_start_block` is not yet supported for backward dataflow analyses"); } - Engine { analysis, tcx, body, pass_name: None, entry_sets, apply_statement_trans_for_block } + Engine { analysis, tcx, body, pass_name: None, entry_sets } } /// Adds an identifier to the graphviz output for this particular run of a dataflow analysis. @@ -177,14 +117,7 @@ where where A::Domain: DebugWithContext, { - let Engine { - mut analysis, - body, - mut entry_sets, - tcx, - apply_statement_trans_for_block, - pass_name, - } = self; + let Engine { mut analysis, body, mut entry_sets, tcx, pass_name } = self; let mut dirty_queue: WorkQueue = WorkQueue::with_none(body.basic_blocks.len()); @@ -213,13 +146,8 @@ where state.clone_from(&entry_sets[bb]); // Apply the block transfer function, using the cached one if it exists. - let edges = A::Direction::apply_effects_in_block( - &mut analysis, - &mut state, - bb, - bb_data, - apply_statement_trans_for_block.as_deref(), - ); + let edges = + A::Direction::apply_effects_in_block(&mut analysis, &mut state, bb, bb_data); A::Direction::join_state_into_successors_of( &mut analysis, diff --git a/compiler/rustc_mir_dataflow/src/framework/mod.rs b/compiler/rustc_mir_dataflow/src/framework/mod.rs index d0472e35fe0..459261a64ff 100644 --- a/compiler/rustc_mir_dataflow/src/framework/mod.rs +++ b/compiler/rustc_mir_dataflow/src/framework/mod.rs @@ -242,7 +242,7 @@ pub trait Analysis<'tcx>: AnalysisDomain<'tcx> { where Self: Sized, { - Engine::new_generic(tcx, body, self) + Engine::new(tcx, body, self) } } @@ -376,19 +376,6 @@ where ) { self.switch_int_edge_effects(block, discr, edge_effects); } - - /* Extension methods */ - #[inline] - fn into_engine<'mir>( - self, - tcx: TyCtxt<'tcx>, - body: &'mir mir::Body<'tcx>, - ) -> Engine<'mir, 'tcx, Self> - where - Self: Sized, - { - Engine::new_gen_kill(tcx, body, self) - } } /// The legal operations for a transfer function in a gen/kill problem. @@ -422,44 +409,6 @@ pub trait GenKill { } } -/// Stores a transfer function for a gen/kill problem. -/// -/// Calling `gen_`/`kill` on a `GenKillSet` will "build up" a transfer function so that it can be -/// applied multiple times efficiently. When there are multiple calls to `gen_` and/or `kill` for -/// the same element, the most recent one takes precedence. -#[derive(Clone)] -pub struct GenKillSet { - gen_: HybridBitSet, - kill: HybridBitSet, -} - -impl GenKillSet { - /// Creates a new transfer function that will leave the dataflow state unchanged. - pub fn identity(universe: usize) -> Self { - GenKillSet { - gen_: HybridBitSet::new_empty(universe), - kill: HybridBitSet::new_empty(universe), - } - } - - pub fn apply(&self, state: &mut impl BitSetExt) { - state.union(&self.gen_); - state.subtract(&self.kill); - } -} - -impl GenKill for GenKillSet { - fn gen_(&mut self, elem: T) { - self.gen_.insert(elem); - self.kill.remove(elem); - } - - fn kill(&mut self, elem: T) { - self.kill.insert(elem); - self.gen_.remove(elem); - } -} - impl GenKill for BitSet { fn gen_(&mut self, elem: T) { self.insert(elem); From 13968b4a70ad6be54efa8d9d388963040d5b6473 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 10 Oct 2024 06:46:08 +1100 Subject: [PATCH 269/357] Tweak `GenKillAnalysis` method arguments. `GenKillAnalysis` has very similar methods to `Analysis`, but the first two have a notable difference: the second argument is `&mut impl GenKill` instead of `&mut Self::Domain`. But thanks to the previous commit, this difference is no longer necessary. --- compiler/rustc_borrowck/src/dataflow.rs | 4 ++-- .../rustc_mir_dataflow/src/framework/mod.rs | 9 ++++---- .../src/impls/borrowed_locals.rs | 2 +- .../src/impls/initialized.rs | 8 +++---- .../rustc_mir_dataflow/src/impls/liveness.rs | 2 +- .../src/impls/storage_liveness.rs | 23 ++++--------------- 6 files changed, 16 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs index 5ea48d3fc7e..b0f5f638e67 100644 --- a/compiler/rustc_borrowck/src/dataflow.rs +++ b/compiler/rustc_borrowck/src/dataflow.rs @@ -518,7 +518,7 @@ impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> { fn before_statement_effect( &mut self, - trans: &mut impl GenKill, + trans: &mut Self::Domain, _statement: &mir::Statement<'tcx>, location: Location, ) { @@ -527,7 +527,7 @@ impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> { fn statement_effect( &mut self, - trans: &mut impl GenKill, + trans: &mut Self::Domain, stmt: &mir::Statement<'tcx>, location: Location, ) { diff --git a/compiler/rustc_mir_dataflow/src/framework/mod.rs b/compiler/rustc_mir_dataflow/src/framework/mod.rs index 459261a64ff..9d79b6f44a6 100644 --- a/compiler/rustc_mir_dataflow/src/framework/mod.rs +++ b/compiler/rustc_mir_dataflow/src/framework/mod.rs @@ -260,19 +260,18 @@ pub trait GenKillAnalysis<'tcx>: Analysis<'tcx> { fn domain_size(&self, body: &mir::Body<'tcx>) -> usize; - /// See `Analysis::apply_statement_effect`. Note how the second arg differs. + /// See `Analysis::apply_statement_effect`. fn statement_effect( &mut self, - trans: &mut impl GenKill, + trans: &mut Self::Domain, statement: &mir::Statement<'tcx>, location: Location, ); - /// See `Analysis::apply_before_statement_effect`. Note how the second arg - /// differs. + /// See `Analysis::apply_before_statement_effect`. fn before_statement_effect( &mut self, - _trans: &mut impl GenKill, + _trans: &mut Self::Domain, _statement: &mir::Statement<'tcx>, _location: Location, ) { diff --git a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs index 8b082ef2667..dc9a1d5f3ad 100644 --- a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs +++ b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs @@ -43,7 +43,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeBorrowedLocals { fn statement_effect( &mut self, - trans: &mut impl GenKill, + trans: &mut Self::Domain, statement: &Statement<'tcx>, location: Location, ) { diff --git a/compiler/rustc_mir_dataflow/src/impls/initialized.rs b/compiler/rustc_mir_dataflow/src/impls/initialized.rs index 25e8726cf61..bb61e7e9432 100644 --- a/compiler/rustc_mir_dataflow/src/impls/initialized.rs +++ b/compiler/rustc_mir_dataflow/src/impls/initialized.rs @@ -338,7 +338,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> { fn statement_effect( &mut self, - trans: &mut impl GenKill, + trans: &mut Self::Domain, statement: &mir::Statement<'tcx>, location: Location, ) { @@ -475,7 +475,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> { fn statement_effect( &mut self, - trans: &mut impl GenKill, + trans: &mut Self::Domain, _statement: &mir::Statement<'tcx>, location: Location, ) { @@ -602,7 +602,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for DefinitelyInitializedPlaces<'_, 'tcx> { fn statement_effect( &mut self, - trans: &mut impl GenKill, + trans: &mut Self::Domain, _statement: &mir::Statement<'tcx>, location: Location, ) { @@ -672,7 +672,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for EverInitializedPlaces<'_, 'tcx> { #[instrument(skip(self, trans), level = "debug")] fn statement_effect( &mut self, - trans: &mut impl GenKill, + trans: &mut Self::Domain, stmt: &mir::Statement<'tcx>, location: Location, ) { diff --git a/compiler/rustc_mir_dataflow/src/impls/liveness.rs b/compiler/rustc_mir_dataflow/src/impls/liveness.rs index 1559c131a37..af46d5543ba 100644 --- a/compiler/rustc_mir_dataflow/src/impls/liveness.rs +++ b/compiler/rustc_mir_dataflow/src/impls/liveness.rs @@ -50,7 +50,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeLiveLocals { fn statement_effect( &mut self, - trans: &mut impl GenKill, + trans: &mut Self::Domain, statement: &mir::Statement<'tcx>, location: Location, ) { diff --git a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs index fe223a3abd8..833cb968e36 100644 --- a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs +++ b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs @@ -46,12 +46,7 @@ impl<'a, 'tcx> crate::GenKillAnalysis<'tcx> for MaybeStorageLive<'a> { body.local_decls.len() } - fn statement_effect( - &mut self, - trans: &mut impl GenKill, - stmt: &Statement<'tcx>, - _: Location, - ) { + fn statement_effect(&mut self, trans: &mut Self::Domain, stmt: &Statement<'tcx>, _: Location) { match stmt.kind { StatementKind::StorageLive(l) => trans.gen_(l), StatementKind::StorageDead(l) => trans.kill(l), @@ -117,12 +112,7 @@ impl<'a, 'tcx> crate::GenKillAnalysis<'tcx> for MaybeStorageDead<'a> { body.local_decls.len() } - fn statement_effect( - &mut self, - trans: &mut impl GenKill, - stmt: &Statement<'tcx>, - _: Location, - ) { + fn statement_effect(&mut self, trans: &mut Self::Domain, stmt: &Statement<'tcx>, _: Location) { match stmt.kind { StatementKind::StorageLive(l) => trans.kill(l), StatementKind::StorageDead(l) => trans.gen_(l), @@ -192,7 +182,7 @@ impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'_, 'tcx> { fn before_statement_effect( &mut self, - trans: &mut impl GenKill, + trans: &mut Self::Domain, stmt: &Statement<'tcx>, loc: Location, ) { @@ -223,12 +213,7 @@ impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'_, 'tcx> { } } - fn statement_effect( - &mut self, - trans: &mut impl GenKill, - _: &Statement<'tcx>, - loc: Location, - ) { + fn statement_effect(&mut self, trans: &mut Self::Domain, _: &Statement<'tcx>, loc: Location) { // If we move from a place then it only stops needing storage *after* // that statement. self.check_for_move(trans, loc); From 525f655866fe933937bd67e54b7f51a44781c7bb Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 10 Oct 2024 10:14:58 +1100 Subject: [PATCH 270/357] Minimize use of `GenKill`. Thanks to the previous couple of commits, many uses of the `GenKill` trait can be replaced with a concrete type. --- compiler/rustc_borrowck/src/dataflow.rs | 8 +++++-- .../rustc_mir_dataflow/src/framework/mod.rs | 4 ++-- .../src/impls/initialized.rs | 14 +++++------ .../rustc_mir_dataflow/src/impls/liveness.rs | 24 +++++++------------ .../src/impls/storage_liveness.rs | 17 ++++++------- 5 files changed, 33 insertions(+), 34 deletions(-) diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs index b0f5f638e67..bef7ad02113 100644 --- a/compiler/rustc_borrowck/src/dataflow.rs +++ b/compiler/rustc_borrowck/src/dataflow.rs @@ -427,7 +427,7 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> { /// That means they went out of a nonlexical scope fn kill_loans_out_of_scope_at_location( &self, - trans: &mut impl GenKill, + trans: &mut >::Domain, location: Location, ) { // NOTE: The state associated with a given `location` @@ -447,7 +447,11 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> { } /// Kill any borrows that conflict with `place`. - fn kill_borrows_on_place(&self, trans: &mut impl GenKill, place: Place<'tcx>) { + fn kill_borrows_on_place( + &self, + trans: &mut >::Domain, + place: Place<'tcx>, + ) { debug!("kill_borrows_on_place: place={:?}", place); let other_borrows_of_local = self diff --git a/compiler/rustc_mir_dataflow/src/framework/mod.rs b/compiler/rustc_mir_dataflow/src/framework/mod.rs index 9d79b6f44a6..9e419f3ff9a 100644 --- a/compiler/rustc_mir_dataflow/src/framework/mod.rs +++ b/compiler/rustc_mir_dataflow/src/framework/mod.rs @@ -305,11 +305,11 @@ pub trait GenKillAnalysis<'tcx>: Analysis<'tcx> { ); /// See `Analysis::apply_switch_int_edge_effects`. - fn switch_int_edge_effects>( + fn switch_int_edge_effects( &mut self, _block: BasicBlock, _discr: &mir::Operand<'tcx>, - _edge_effects: &mut impl SwitchIntEdgeEffects, + _edge_effects: &mut impl SwitchIntEdgeEffects, ) { } } diff --git a/compiler/rustc_mir_dataflow/src/impls/initialized.rs b/compiler/rustc_mir_dataflow/src/impls/initialized.rs index bb61e7e9432..e5bcb64d641 100644 --- a/compiler/rustc_mir_dataflow/src/impls/initialized.rs +++ b/compiler/rustc_mir_dataflow/src/impls/initialized.rs @@ -270,7 +270,7 @@ impl<'tcx> HasMoveData<'tcx> for EverInitializedPlaces<'_, 'tcx> { impl<'a, 'tcx> MaybeInitializedPlaces<'a, 'tcx> { fn update_bits( - trans: &mut impl GenKill, + trans: &mut >::Domain, path: MovePathIndex, state: DropFlagState, ) { @@ -283,7 +283,7 @@ impl<'a, 'tcx> MaybeInitializedPlaces<'a, 'tcx> { impl<'tcx> MaybeUninitializedPlaces<'_, 'tcx> { fn update_bits( - trans: &mut impl GenKill, + trans: &mut >::Domain, path: MovePathIndex, state: DropFlagState, ) { @@ -296,7 +296,7 @@ impl<'tcx> MaybeUninitializedPlaces<'_, 'tcx> { impl<'a, 'tcx> DefinitelyInitializedPlaces<'a, 'tcx> { fn update_bits( - trans: &mut impl GenKill, + trans: &mut >::Domain, path: MovePathIndex, state: DropFlagState, ) { @@ -399,11 +399,11 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> { }); } - fn switch_int_edge_effects>( + fn switch_int_edge_effects( &mut self, block: mir::BasicBlock, discr: &mir::Operand<'tcx>, - edge_effects: &mut impl SwitchIntEdgeEffects, + edge_effects: &mut impl SwitchIntEdgeEffects, ) { if !self.tcx.sess.opts.unstable_opts.precise_enum_drop_elaboration { return; @@ -524,11 +524,11 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> { }); } - fn switch_int_edge_effects>( + fn switch_int_edge_effects( &mut self, block: mir::BasicBlock, discr: &mir::Operand<'tcx>, - edge_effects: &mut impl SwitchIntEdgeEffects, + edge_effects: &mut impl SwitchIntEdgeEffects, ) { if !self.tcx.sess.opts.unstable_opts.precise_enum_drop_elaboration { return; diff --git a/compiler/rustc_mir_dataflow/src/impls/liveness.rs b/compiler/rustc_mir_dataflow/src/impls/liveness.rs index af46d5543ba..07ecedeac59 100644 --- a/compiler/rustc_mir_dataflow/src/impls/liveness.rs +++ b/compiler/rustc_mir_dataflow/src/impls/liveness.rs @@ -89,12 +89,9 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeLiveLocals { } } -pub struct TransferFunction<'a, T>(pub &'a mut T); +pub struct TransferFunction<'a>(pub &'a mut BitSet); -impl<'tcx, T> Visitor<'tcx> for TransferFunction<'_, T> -where - T: GenKill, -{ +impl<'tcx> Visitor<'tcx> for TransferFunction<'_> { fn visit_place(&mut self, place: &mir::Place<'tcx>, context: PlaceContext, location: Location) { if let PlaceContext::MutatingUse(MutatingUseContext::Yield) = context { // The resume place is evaluated and assigned to only after coroutine resumes, so its @@ -108,10 +105,10 @@ where MutatingUseContext::Call | MutatingUseContext::AsmOutput, ) = context { - // For the associated terminators, this is only a `Def` when the terminator returns - // "successfully." As such, we handle this case separately in `call_return_effect` - // above. However, if the place looks like `*_5`, this is still unconditionally a use of - // `_5`. + // For the associated terminators, this is only a `Def` when the terminator + // returns "successfully." As such, we handle this case separately in + // `call_return_effect` above. However, if the place looks like `*_5`, this is + // still unconditionally a use of `_5`. } else { self.0.kill(place.local); } @@ -128,12 +125,9 @@ where } } -struct YieldResumeEffect<'a, T>(&'a mut T); +struct YieldResumeEffect<'a>(&'a mut BitSet); -impl<'tcx, T> Visitor<'tcx> for YieldResumeEffect<'_, T> -where - T: GenKill, -{ +impl<'tcx> Visitor<'tcx> for YieldResumeEffect<'_> { fn visit_place(&mut self, place: &mir::Place<'tcx>, context: PlaceContext, location: Location) { DefUse::apply(self.0, *place, context); self.visit_projection(place.as_ref(), context, location); @@ -151,7 +145,7 @@ enum DefUse { } impl DefUse { - fn apply(trans: &mut impl GenKill, place: Place<'_>, context: PlaceContext) { + fn apply(trans: &mut BitSet, place: Place<'_>, context: PlaceContext) { match DefUse::for_place(place, context) { Some(DefUse::Def) => trans.kill(place.local), Some(DefUse::Use) => trans.gen_(place.local), diff --git a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs index 833cb968e36..0f94defb1ab 100644 --- a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs +++ b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs @@ -5,7 +5,7 @@ use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; use super::MaybeBorrowedLocals; -use crate::{GenKill, ResultsCursor}; +use crate::{AnalysisDomain, GenKill, ResultsCursor}; pub struct MaybeStorageLive<'a> { always_live_locals: Cow<'a, BitSet>, @@ -330,22 +330,23 @@ impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'_, 'tcx> { impl<'tcx> MaybeRequiresStorage<'_, 'tcx> { /// Kill locals that are fully moved and have not been borrowed. - fn check_for_move(&mut self, trans: &mut impl GenKill, loc: Location) { + fn check_for_move( + &mut self, + trans: &mut >::Domain, + loc: Location, + ) { let body = self.borrowed_locals.body(); let mut visitor = MoveVisitor { trans, borrowed_locals: &mut self.borrowed_locals }; visitor.visit_location(body, loc); } } -struct MoveVisitor<'a, 'mir, 'tcx, T> { +struct MoveVisitor<'a, 'mir, 'tcx> { borrowed_locals: &'a mut BorrowedLocalsResults<'mir, 'tcx>, - trans: &'a mut T, + trans: &'a mut BitSet, } -impl<'tcx, T> Visitor<'tcx> for MoveVisitor<'_, '_, 'tcx, T> -where - T: GenKill, -{ +impl<'tcx> Visitor<'tcx> for MoveVisitor<'_, '_, 'tcx> { fn visit_local(&mut self, local: Local, context: PlaceContext, loc: Location) { if PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) == context { self.borrowed_locals.seek_before_primary_effect(loc); From 4dc1b4d0b1c0e96102f6d9b3a0ea91e46feaf8e9 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 10 Oct 2024 09:49:33 +1100 Subject: [PATCH 271/357] Remove `GenKillAnalysis`. It's now functionally identical to `Analysis`. --- compiler/rustc_borrowck/src/dataflow.rs | 18 +- .../rustc_mir_dataflow/src/framework/mod.rs | 159 ++---------------- .../src/impls/borrowed_locals.rs | 16 +- .../src/impls/initialized.rs | 62 +++---- .../rustc_mir_dataflow/src/impls/liveness.rs | 16 +- .../src/impls/storage_liveness.rs | 71 ++++---- compiler/rustc_mir_dataflow/src/lib.rs | 6 +- 7 files changed, 82 insertions(+), 266 deletions(-) diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs index bef7ad02113..2eef200e24c 100644 --- a/compiler/rustc_borrowck/src/dataflow.rs +++ b/compiler/rustc_borrowck/src/dataflow.rs @@ -513,14 +513,8 @@ impl<'tcx> rustc_mir_dataflow::AnalysisDomain<'tcx> for Borrows<'_, 'tcx> { /// region stops containing the CFG points reachable from the issuing location. /// - we also kill loans of conflicting places when overwriting a shared path: e.g. borrows of /// `a.b.c` when `a` is overwritten. -impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> { - type Idx = BorrowIndex; - - fn domain_size(&self, _: &mir::Body<'tcx>) -> usize { - self.borrow_set.len() - } - - fn before_statement_effect( +impl<'tcx> rustc_mir_dataflow::Analysis<'tcx> for Borrows<'_, 'tcx> { + fn apply_before_statement_effect( &mut self, trans: &mut Self::Domain, _statement: &mir::Statement<'tcx>, @@ -529,7 +523,7 @@ impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> { self.kill_loans_out_of_scope_at_location(trans, location); } - fn statement_effect( + fn apply_statement_effect( &mut self, trans: &mut Self::Domain, stmt: &mir::Statement<'tcx>, @@ -577,7 +571,7 @@ impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> { } } - fn before_terminator_effect( + fn apply_before_terminator_effect( &mut self, trans: &mut Self::Domain, _terminator: &mir::Terminator<'tcx>, @@ -586,7 +580,7 @@ impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> { self.kill_loans_out_of_scope_at_location(trans, location); } - fn terminator_effect<'mir>( + fn apply_terminator_effect<'mir>( &mut self, trans: &mut Self::Domain, terminator: &'mir mir::Terminator<'tcx>, @@ -604,7 +598,7 @@ impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> { terminator.edges() } - fn call_return_effect( + fn apply_call_return_effect( &mut self, _trans: &mut Self::Domain, _block: mir::BasicBlock, diff --git a/compiler/rustc_mir_dataflow/src/framework/mod.rs b/compiler/rustc_mir_dataflow/src/framework/mod.rs index 9e419f3ff9a..d7a62ecd2c1 100644 --- a/compiler/rustc_mir_dataflow/src/framework/mod.rs +++ b/compiler/rustc_mir_dataflow/src/framework/mod.rs @@ -1,9 +1,11 @@ //! A framework that can express both [gen-kill] and generic dataflow problems. //! -//! To use this framework, implement either the [`Analysis`] or the -//! [`GenKillAnalysis`] trait. If your transfer function can be expressed with only gen/kill -//! operations, prefer `GenKillAnalysis` since it will run faster while iterating to fixpoint. The -//! `impls` module contains several examples of gen/kill dataflow analyses. +//! To use this framework, implement the [`Analysis`] trait. There used to be a `GenKillAnalysis` +//! alternative trait for gen-kill analyses that would pre-compute the transfer function for each +//! block. It was intended as an optimization, but it ended up not being any faster than +//! `Analysis`. +//! +//! The `impls` module contains several examples of dataflow analyses. //! //! Create an `Engine` for your analysis using the `into_engine` method on the `Analysis` trait, //! then call `iterate_to_fixpoint`. From there, you can use a `ResultsCursor` to inspect the @@ -122,9 +124,9 @@ pub trait AnalysisDomain<'tcx> { /// /// # Convergence /// -/// When implementing this trait directly (not via [`GenKillAnalysis`]), it's possible to choose a -/// transfer function such that the analysis does not reach fixpoint. To guarantee convergence, -/// your transfer functions must maintain the following invariant: +/// When implementing this trait it's possible to choose a transfer function such that the analysis +/// does not reach fixpoint. To guarantee convergence, your transfer functions must maintain the +/// following invariant: /// /// > If the dataflow state **before** some point in the program changes to be greater /// than the prior state **before** that point, the dataflow state **after** that point must @@ -223,9 +225,7 @@ pub trait Analysis<'tcx>: AnalysisDomain<'tcx> { /// Creates an `Engine` to find the fixpoint for this dataflow problem. /// - /// You shouldn't need to override this outside this module, since the combination of the - /// default impl and the one for all `A: GenKillAnalysis` will do the right thing. - /// Its purpose is to enable method chaining like so: + /// You shouldn't need to override this. Its purpose is to enable method chaining like so: /// /// ```ignore (cross-crate-imports) /// let results = MyAnalysis::new(tcx, body) @@ -246,146 +246,7 @@ pub trait Analysis<'tcx>: AnalysisDomain<'tcx> { } } -/// A gen/kill dataflow problem. -/// -/// Each method in this trait has a corresponding one in `Analysis`. However, the first two methods -/// here only allow modification of the dataflow state via "gen" and "kill" operations. By defining -/// transfer functions for each statement in this way, the transfer function for an entire basic -/// block can be computed efficiently. The remaining methods match up with `Analysis` exactly. -/// -/// `Analysis` is automatically implemented for all implementers of `GenKillAnalysis` via a blanket -/// impl below. -pub trait GenKillAnalysis<'tcx>: Analysis<'tcx> { - type Idx: Idx; - - fn domain_size(&self, body: &mir::Body<'tcx>) -> usize; - - /// See `Analysis::apply_statement_effect`. - fn statement_effect( - &mut self, - trans: &mut Self::Domain, - statement: &mir::Statement<'tcx>, - location: Location, - ); - - /// See `Analysis::apply_before_statement_effect`. - fn before_statement_effect( - &mut self, - _trans: &mut Self::Domain, - _statement: &mir::Statement<'tcx>, - _location: Location, - ) { - } - - /// See `Analysis::apply_terminator_effect`. - fn terminator_effect<'mir>( - &mut self, - trans: &mut Self::Domain, - terminator: &'mir mir::Terminator<'tcx>, - location: Location, - ) -> TerminatorEdges<'mir, 'tcx>; - - /// See `Analysis::apply_before_terminator_effect`. - fn before_terminator_effect( - &mut self, - _trans: &mut Self::Domain, - _terminator: &mir::Terminator<'tcx>, - _location: Location, - ) { - } - - /* Edge-specific effects */ - - /// See `Analysis::apply_call_return_effect`. - fn call_return_effect( - &mut self, - trans: &mut Self::Domain, - block: BasicBlock, - return_places: CallReturnPlaces<'_, 'tcx>, - ); - - /// See `Analysis::apply_switch_int_edge_effects`. - fn switch_int_edge_effects( - &mut self, - _block: BasicBlock, - _discr: &mir::Operand<'tcx>, - _edge_effects: &mut impl SwitchIntEdgeEffects, - ) { - } -} - -// Blanket impl: any impl of `GenKillAnalysis` automatically impls `Analysis`. -impl<'tcx, A> Analysis<'tcx> for A -where - A: GenKillAnalysis<'tcx>, - A::Domain: GenKill + BitSetExt, -{ - fn apply_statement_effect( - &mut self, - state: &mut A::Domain, - statement: &mir::Statement<'tcx>, - location: Location, - ) { - self.statement_effect(state, statement, location); - } - - fn apply_before_statement_effect( - &mut self, - state: &mut A::Domain, - statement: &mir::Statement<'tcx>, - location: Location, - ) { - self.before_statement_effect(state, statement, location); - } - - fn apply_terminator_effect<'mir>( - &mut self, - state: &mut A::Domain, - terminator: &'mir mir::Terminator<'tcx>, - location: Location, - ) -> TerminatorEdges<'mir, 'tcx> { - self.terminator_effect(state, terminator, location) - } - - fn apply_before_terminator_effect( - &mut self, - state: &mut A::Domain, - terminator: &mir::Terminator<'tcx>, - location: Location, - ) { - self.before_terminator_effect(state, terminator, location); - } - - /* Edge-specific effects */ - - fn apply_call_return_effect( - &mut self, - state: &mut A::Domain, - block: BasicBlock, - return_places: CallReturnPlaces<'_, 'tcx>, - ) { - self.call_return_effect(state, block, return_places); - } - - fn apply_switch_int_edge_effects( - &mut self, - block: BasicBlock, - discr: &mir::Operand<'tcx>, - edge_effects: &mut impl SwitchIntEdgeEffects, - ) { - self.switch_int_edge_effects(block, discr, edge_effects); - } -} - /// The legal operations for a transfer function in a gen/kill problem. -/// -/// This abstraction exists because there are two different contexts in which we call the methods in -/// `GenKillAnalysis`. Sometimes we need to store a single transfer function that can be efficiently -/// applied multiple times, such as when computing the cumulative transfer function for each block. -/// These cases require a `GenKillSet`, which in turn requires two `BitSet`s of storage. Oftentimes, -/// however, we only need to apply an effect once. In *these* cases, it is more efficient to pass the -/// `BitSet` representing the state vector directly into the `*_effect` methods as opposed to -/// building up a `GenKillSet` and then throwing it away. pub trait GenKill { /// Inserts `elem` into the state vector. fn gen_(&mut self, elem: T); diff --git a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs index dc9a1d5f3ad..f4edbaf056c 100644 --- a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs +++ b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs @@ -2,7 +2,7 @@ use rustc_index::bit_set::BitSet; use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::*; -use crate::{AnalysisDomain, GenKill, GenKillAnalysis}; +use crate::{Analysis, AnalysisDomain, GenKill}; /// A dataflow analysis that tracks whether a pointer or reference could possibly exist that points /// to a given local. This analysis ignores fake borrows, so it should not be used by @@ -34,14 +34,8 @@ impl<'tcx> AnalysisDomain<'tcx> for MaybeBorrowedLocals { } } -impl<'tcx> GenKillAnalysis<'tcx> for MaybeBorrowedLocals { - type Idx = Local; - - fn domain_size(&self, body: &Body<'tcx>) -> usize { - body.local_decls.len() - } - - fn statement_effect( +impl<'tcx> Analysis<'tcx> for MaybeBorrowedLocals { + fn apply_statement_effect( &mut self, trans: &mut Self::Domain, statement: &Statement<'tcx>, @@ -50,7 +44,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeBorrowedLocals { self.transfer_function(trans).visit_statement(statement, location); } - fn terminator_effect<'mir>( + fn apply_terminator_effect<'mir>( &mut self, trans: &mut Self::Domain, terminator: &'mir Terminator<'tcx>, @@ -60,7 +54,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeBorrowedLocals { terminator.edges() } - fn call_return_effect( + fn apply_call_return_effect( &mut self, _trans: &mut Self::Domain, _block: BasicBlock, diff --git a/compiler/rustc_mir_dataflow/src/impls/initialized.rs b/compiler/rustc_mir_dataflow/src/impls/initialized.rs index e5bcb64d641..18a5ca3f6be 100644 --- a/compiler/rustc_mir_dataflow/src/impls/initialized.rs +++ b/compiler/rustc_mir_dataflow/src/impls/initialized.rs @@ -11,7 +11,7 @@ use crate::elaborate_drops::DropFlagState; use crate::framework::SwitchIntEdgeEffects; use crate::move_paths::{HasMoveData, InitIndex, InitKind, LookupResult, MoveData, MovePathIndex}; use crate::{ - AnalysisDomain, GenKill, GenKillAnalysis, MaybeReachable, drop_flag_effects, + Analysis, AnalysisDomain, GenKill, MaybeReachable, drop_flag_effects, drop_flag_effects_for_function_entry, drop_flag_effects_for_location, lattice, on_all_children_bits, on_lookup_result_bits, }; @@ -329,14 +329,8 @@ impl<'tcx> AnalysisDomain<'tcx> for MaybeInitializedPlaces<'_, 'tcx> { } } -impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> { - type Idx = MovePathIndex; - - fn domain_size(&self, _: &Body<'tcx>) -> usize { - self.move_data().move_paths.len() - } - - fn statement_effect( +impl<'tcx> Analysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> { + fn apply_statement_effect( &mut self, trans: &mut Self::Domain, statement: &mir::Statement<'tcx>, @@ -360,7 +354,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> { } } - fn terminator_effect<'mir>( + fn apply_terminator_effect<'mir>( &mut self, state: &mut Self::Domain, terminator: &'mir mir::Terminator<'tcx>, @@ -380,7 +374,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> { edges } - fn call_return_effect( + fn apply_call_return_effect( &mut self, trans: &mut Self::Domain, _block: mir::BasicBlock, @@ -399,7 +393,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> { }); } - fn switch_int_edge_effects( + fn apply_switch_int_edge_effects( &mut self, block: mir::BasicBlock, discr: &mir::Operand<'tcx>, @@ -466,14 +460,8 @@ impl<'tcx> AnalysisDomain<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> { } } -impl<'tcx> GenKillAnalysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> { - type Idx = MovePathIndex; - - fn domain_size(&self, _: &Body<'tcx>) -> usize { - self.move_data().move_paths.len() - } - - fn statement_effect( +impl<'tcx> Analysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> { + fn apply_statement_effect( &mut self, trans: &mut Self::Domain, _statement: &mir::Statement<'tcx>, @@ -487,7 +475,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> { // mutable borrow occurs. Places cannot become uninitialized through a mutable reference. } - fn terminator_effect<'mir>( + fn apply_terminator_effect<'mir>( &mut self, trans: &mut Self::Domain, terminator: &'mir mir::Terminator<'tcx>, @@ -505,7 +493,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> { } } - fn call_return_effect( + fn apply_call_return_effect( &mut self, trans: &mut Self::Domain, _block: mir::BasicBlock, @@ -524,7 +512,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> { }); } - fn switch_int_edge_effects( + fn apply_switch_int_edge_effects( &mut self, block: mir::BasicBlock, discr: &mir::Operand<'tcx>, @@ -593,14 +581,8 @@ impl<'a, 'tcx> AnalysisDomain<'tcx> for DefinitelyInitializedPlaces<'a, 'tcx> { } } -impl<'tcx> GenKillAnalysis<'tcx> for DefinitelyInitializedPlaces<'_, 'tcx> { - type Idx = MovePathIndex; - - fn domain_size(&self, _: &Body<'tcx>) -> usize { - self.move_data().move_paths.len() - } - - fn statement_effect( +impl<'tcx> Analysis<'tcx> for DefinitelyInitializedPlaces<'_, 'tcx> { + fn apply_statement_effect( &mut self, trans: &mut Self::Domain, _statement: &mir::Statement<'tcx>, @@ -611,7 +593,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for DefinitelyInitializedPlaces<'_, 'tcx> { }) } - fn terminator_effect<'mir>( + fn apply_terminator_effect<'mir>( &mut self, trans: &mut Self::Domain, terminator: &'mir mir::Terminator<'tcx>, @@ -623,7 +605,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for DefinitelyInitializedPlaces<'_, 'tcx> { terminator.edges() } - fn call_return_effect( + fn apply_call_return_effect( &mut self, trans: &mut Self::Domain, _block: mir::BasicBlock, @@ -662,15 +644,9 @@ impl<'tcx> AnalysisDomain<'tcx> for EverInitializedPlaces<'_, 'tcx> { } } -impl<'tcx> GenKillAnalysis<'tcx> for EverInitializedPlaces<'_, 'tcx> { - type Idx = InitIndex; - - fn domain_size(&self, _: &Body<'tcx>) -> usize { - self.move_data().inits.len() - } - +impl<'tcx> Analysis<'tcx> for EverInitializedPlaces<'_, 'tcx> { #[instrument(skip(self, trans), level = "debug")] - fn statement_effect( + fn apply_statement_effect( &mut self, trans: &mut Self::Domain, stmt: &mir::Statement<'tcx>, @@ -698,7 +674,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for EverInitializedPlaces<'_, 'tcx> { } #[instrument(skip(self, trans, terminator), level = "debug")] - fn terminator_effect<'mir>( + fn apply_terminator_effect<'mir>( &mut self, trans: &mut Self::Domain, terminator: &'mir mir::Terminator<'tcx>, @@ -720,7 +696,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for EverInitializedPlaces<'_, 'tcx> { terminator.edges() } - fn call_return_effect( + fn apply_call_return_effect( &mut self, trans: &mut Self::Domain, block: mir::BasicBlock, diff --git a/compiler/rustc_mir_dataflow/src/impls/liveness.rs b/compiler/rustc_mir_dataflow/src/impls/liveness.rs index 07ecedeac59..452fae379be 100644 --- a/compiler/rustc_mir_dataflow/src/impls/liveness.rs +++ b/compiler/rustc_mir_dataflow/src/impls/liveness.rs @@ -4,7 +4,7 @@ use rustc_middle::mir::{ self, CallReturnPlaces, Local, Location, Place, StatementKind, TerminatorEdges, }; -use crate::{Analysis, AnalysisDomain, Backward, GenKill, GenKillAnalysis}; +use crate::{Analysis, AnalysisDomain, Backward, GenKill}; /// A [live-variable dataflow analysis][liveness]. /// @@ -41,14 +41,8 @@ impl<'tcx> AnalysisDomain<'tcx> for MaybeLiveLocals { } } -impl<'tcx> GenKillAnalysis<'tcx> for MaybeLiveLocals { - type Idx = Local; - - fn domain_size(&self, body: &mir::Body<'tcx>) -> usize { - body.local_decls.len() - } - - fn statement_effect( +impl<'tcx> Analysis<'tcx> for MaybeLiveLocals { + fn apply_statement_effect( &mut self, trans: &mut Self::Domain, statement: &mir::Statement<'tcx>, @@ -57,7 +51,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeLiveLocals { TransferFunction(trans).visit_statement(statement, location); } - fn terminator_effect<'mir>( + fn apply_terminator_effect<'mir>( &mut self, trans: &mut Self::Domain, terminator: &'mir mir::Terminator<'tcx>, @@ -67,7 +61,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeLiveLocals { terminator.edges() } - fn call_return_effect( + fn apply_call_return_effect( &mut self, trans: &mut Self::Domain, _block: mir::BasicBlock, diff --git a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs index 0f94defb1ab..6ccd7dc17a2 100644 --- a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs +++ b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs @@ -5,7 +5,7 @@ use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; use super::MaybeBorrowedLocals; -use crate::{AnalysisDomain, GenKill, ResultsCursor}; +use crate::{Analysis, AnalysisDomain, GenKill, ResultsCursor}; pub struct MaybeStorageLive<'a> { always_live_locals: Cow<'a, BitSet>, @@ -17,7 +17,7 @@ impl<'a> MaybeStorageLive<'a> { } } -impl<'a, 'tcx> crate::AnalysisDomain<'tcx> for MaybeStorageLive<'a> { +impl<'a, 'tcx> AnalysisDomain<'tcx> for MaybeStorageLive<'a> { type Domain = BitSet; const NAME: &'static str = "maybe_storage_live"; @@ -39,14 +39,13 @@ impl<'a, 'tcx> crate::AnalysisDomain<'tcx> for MaybeStorageLive<'a> { } } -impl<'a, 'tcx> crate::GenKillAnalysis<'tcx> for MaybeStorageLive<'a> { - type Idx = Local; - - fn domain_size(&self, body: &Body<'tcx>) -> usize { - body.local_decls.len() - } - - fn statement_effect(&mut self, trans: &mut Self::Domain, stmt: &Statement<'tcx>, _: Location) { +impl<'a, 'tcx> Analysis<'tcx> for MaybeStorageLive<'a> { + fn apply_statement_effect( + &mut self, + trans: &mut Self::Domain, + stmt: &Statement<'tcx>, + _: Location, + ) { match stmt.kind { StatementKind::StorageLive(l) => trans.gen_(l), StatementKind::StorageDead(l) => trans.kill(l), @@ -54,7 +53,7 @@ impl<'a, 'tcx> crate::GenKillAnalysis<'tcx> for MaybeStorageLive<'a> { } } - fn terminator_effect<'mir>( + fn apply_terminator_effect<'mir>( &mut self, _trans: &mut Self::Domain, terminator: &'mir Terminator<'tcx>, @@ -64,7 +63,7 @@ impl<'a, 'tcx> crate::GenKillAnalysis<'tcx> for MaybeStorageLive<'a> { terminator.edges() } - fn call_return_effect( + fn apply_call_return_effect( &mut self, _trans: &mut Self::Domain, _block: BasicBlock, @@ -84,7 +83,7 @@ impl<'a> MaybeStorageDead<'a> { } } -impl<'a, 'tcx> crate::AnalysisDomain<'tcx> for MaybeStorageDead<'a> { +impl<'a, 'tcx> AnalysisDomain<'tcx> for MaybeStorageDead<'a> { type Domain = BitSet; const NAME: &'static str = "maybe_storage_dead"; @@ -105,14 +104,13 @@ impl<'a, 'tcx> crate::AnalysisDomain<'tcx> for MaybeStorageDead<'a> { } } -impl<'a, 'tcx> crate::GenKillAnalysis<'tcx> for MaybeStorageDead<'a> { - type Idx = Local; - - fn domain_size(&self, body: &Body<'tcx>) -> usize { - body.local_decls.len() - } - - fn statement_effect(&mut self, trans: &mut Self::Domain, stmt: &Statement<'tcx>, _: Location) { +impl<'a, 'tcx> Analysis<'tcx> for MaybeStorageDead<'a> { + fn apply_statement_effect( + &mut self, + trans: &mut Self::Domain, + stmt: &Statement<'tcx>, + _: Location, + ) { match stmt.kind { StatementKind::StorageLive(l) => trans.kill(l), StatementKind::StorageDead(l) => trans.gen_(l), @@ -120,7 +118,7 @@ impl<'a, 'tcx> crate::GenKillAnalysis<'tcx> for MaybeStorageDead<'a> { } } - fn terminator_effect<'mir>( + fn apply_terminator_effect<'mir>( &mut self, _: &mut Self::Domain, terminator: &'mir Terminator<'tcx>, @@ -130,7 +128,7 @@ impl<'a, 'tcx> crate::GenKillAnalysis<'tcx> for MaybeStorageDead<'a> { terminator.edges() } - fn call_return_effect( + fn apply_call_return_effect( &mut self, _trans: &mut Self::Domain, _block: BasicBlock, @@ -154,7 +152,7 @@ impl<'mir, 'tcx> MaybeRequiresStorage<'mir, 'tcx> { } } -impl<'tcx> crate::AnalysisDomain<'tcx> for MaybeRequiresStorage<'_, 'tcx> { +impl<'tcx> AnalysisDomain<'tcx> for MaybeRequiresStorage<'_, 'tcx> { type Domain = BitSet; const NAME: &'static str = "requires_storage"; @@ -173,21 +171,15 @@ impl<'tcx> crate::AnalysisDomain<'tcx> for MaybeRequiresStorage<'_, 'tcx> { } } -impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'_, 'tcx> { - type Idx = Local; - - fn domain_size(&self, body: &Body<'tcx>) -> usize { - body.local_decls.len() - } - - fn before_statement_effect( +impl<'tcx> Analysis<'tcx> for MaybeRequiresStorage<'_, 'tcx> { + fn apply_before_statement_effect( &mut self, trans: &mut Self::Domain, stmt: &Statement<'tcx>, loc: Location, ) { // If a place is borrowed in a statement, it needs storage for that statement. - self.borrowed_locals.mut_analysis().statement_effect(trans, stmt, loc); + self.borrowed_locals.mut_analysis().apply_statement_effect(trans, stmt, loc); match &stmt.kind { StatementKind::StorageDead(l) => trans.kill(*l), @@ -213,13 +205,18 @@ impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'_, 'tcx> { } } - fn statement_effect(&mut self, trans: &mut Self::Domain, _: &Statement<'tcx>, loc: Location) { + fn apply_statement_effect( + &mut self, + trans: &mut Self::Domain, + _: &Statement<'tcx>, + loc: Location, + ) { // If we move from a place then it only stops needing storage *after* // that statement. self.check_for_move(trans, loc); } - fn before_terminator_effect( + fn apply_before_terminator_effect( &mut self, trans: &mut Self::Domain, terminator: &Terminator<'tcx>, @@ -277,7 +274,7 @@ impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'_, 'tcx> { } } - fn terminator_effect<'t>( + fn apply_terminator_effect<'t>( &mut self, trans: &mut Self::Domain, terminator: &'t Terminator<'tcx>, @@ -318,7 +315,7 @@ impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'_, 'tcx> { terminator.edges() } - fn call_return_effect( + fn apply_call_return_effect( &mut self, trans: &mut Self::Domain, _block: BasicBlock, diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs index cd926c07641..d07928dcdc9 100644 --- a/compiler/rustc_mir_dataflow/src/lib.rs +++ b/compiler/rustc_mir_dataflow/src/lib.rs @@ -18,9 +18,9 @@ pub use self::drop_flag_effects::{ move_path_children_matching, on_all_children_bits, on_lookup_result_bits, }; pub use self::framework::{ - Analysis, AnalysisDomain, Backward, Direction, Engine, Forward, GenKill, GenKillAnalysis, - JoinSemiLattice, MaybeReachable, Results, ResultsCursor, ResultsVisitable, ResultsVisitor, - SwitchIntEdgeEffects, fmt, graphviz, lattice, visit_results, + Analysis, AnalysisDomain, Backward, Direction, Engine, Forward, GenKill, JoinSemiLattice, + MaybeReachable, Results, ResultsCursor, ResultsVisitable, ResultsVisitor, SwitchIntEdgeEffects, + fmt, graphviz, lattice, visit_results, }; use self::move_paths::MoveData; From ba13775319fa51933da6e90053a9f96778b15b6b Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 10 Oct 2024 11:46:29 +1100 Subject: [PATCH 272/357] Merge `AnalysisDomain` into `Analysis`. With `GenKillAnalysis` gone, there is no need for them to be separate. --- compiler/rustc_borrowck/src/dataflow.rs | 30 +++++++------- .../src/check_consts/resolver.rs | 9 +--- .../src/framework/engine.rs | 5 +-- .../rustc_mir_dataflow/src/framework/mod.rs | 41 +++++++++---------- .../rustc_mir_dataflow/src/framework/tests.rs | 4 +- .../src/impls/borrowed_locals.rs | 6 +-- .../src/impls/initialized.rs | 27 ++++-------- .../rustc_mir_dataflow/src/impls/liveness.rs | 10 ++--- .../src/impls/storage_liveness.rs | 20 +++------ compiler/rustc_mir_dataflow/src/lib.rs | 6 +-- .../rustc_mir_dataflow/src/value_analysis.rs | 9 +--- 11 files changed, 62 insertions(+), 105 deletions(-) diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs index 2eef200e24c..216cf8ac988 100644 --- a/compiler/rustc_borrowck/src/dataflow.rs +++ b/compiler/rustc_borrowck/src/dataflow.rs @@ -7,7 +7,7 @@ use rustc_middle::mir::{ use rustc_middle::ty::{RegionVid, TyCtxt}; use rustc_mir_dataflow::fmt::DebugWithContext; use rustc_mir_dataflow::impls::{EverInitializedPlaces, MaybeUninitializedPlaces}; -use rustc_mir_dataflow::{Analysis, AnalysisDomain, Forward, GenKill, Results, ResultsVisitable}; +use rustc_mir_dataflow::{Analysis, Forward, GenKill, Results, ResultsVisitable}; use tracing::debug; use crate::{BorrowSet, PlaceConflictBias, PlaceExt, RegionInferenceContext, places_conflict}; @@ -22,9 +22,9 @@ pub(crate) struct BorrowckResults<'a, 'tcx> { /// The transient state of the dataflow analyses used by the borrow checker. #[derive(Debug)] pub(crate) struct BorrowckDomain<'a, 'tcx> { - pub(crate) borrows: as AnalysisDomain<'tcx>>::Domain, - pub(crate) uninits: as AnalysisDomain<'tcx>>::Domain, - pub(crate) ever_inits: as AnalysisDomain<'tcx>>::Domain, + pub(crate) borrows: as Analysis<'tcx>>::Domain, + pub(crate) uninits: as Analysis<'tcx>>::Domain, + pub(crate) ever_inits: as Analysis<'tcx>>::Domain, } impl<'a, 'tcx> ResultsVisitable<'tcx> for BorrowckResults<'a, 'tcx> { @@ -427,7 +427,7 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> { /// That means they went out of a nonlexical scope fn kill_loans_out_of_scope_at_location( &self, - trans: &mut >::Domain, + trans: &mut >::Domain, location: Location, ) { // NOTE: The state associated with a given `location` @@ -449,7 +449,7 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> { /// Kill any borrows that conflict with `place`. fn kill_borrows_on_place( &self, - trans: &mut >::Domain, + trans: &mut >::Domain, place: Place<'tcx>, ) { debug!("kill_borrows_on_place: place={:?}", place); @@ -490,7 +490,14 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> { } } -impl<'tcx> rustc_mir_dataflow::AnalysisDomain<'tcx> for Borrows<'_, 'tcx> { +/// Forward dataflow computation of the set of borrows that are in scope at a particular location. +/// - we gen the introduced loans +/// - we kill loans on locals going out of (regular) scope +/// - we kill the loans going out of their region's NLL scope: in NLL terms, the frontier where a +/// region stops containing the CFG points reachable from the issuing location. +/// - we also kill loans of conflicting places when overwriting a shared path: e.g. borrows of +/// `a.b.c` when `a` is overwritten. +impl<'tcx> rustc_mir_dataflow::Analysis<'tcx> for Borrows<'_, 'tcx> { type Domain = BitSet; const NAME: &'static str = "borrows"; @@ -504,16 +511,7 @@ impl<'tcx> rustc_mir_dataflow::AnalysisDomain<'tcx> for Borrows<'_, 'tcx> { // no borrows of code region_scopes have been taken prior to // function execution, so this method has no effect. } -} -/// Forward dataflow computation of the set of borrows that are in scope at a particular location. -/// - we gen the introduced loans -/// - we kill loans on locals going out of (regular) scope -/// - we kill the loans going out of their region's NLL scope: in NLL terms, the frontier where a -/// region stops containing the CFG points reachable from the issuing location. -/// - we also kill loans of conflicting places when overwriting a shared path: e.g. borrows of -/// `a.b.c` when `a` is overwritten. -impl<'tcx> rustc_mir_dataflow::Analysis<'tcx> for Borrows<'_, 'tcx> { fn apply_before_statement_effect( &mut self, trans: &mut Self::Domain, diff --git a/compiler/rustc_const_eval/src/check_consts/resolver.rs b/compiler/rustc_const_eval/src/check_consts/resolver.rs index eb5024c36f4..74eb6b37fbb 100644 --- a/compiler/rustc_const_eval/src/check_consts/resolver.rs +++ b/compiler/rustc_const_eval/src/check_consts/resolver.rs @@ -11,7 +11,7 @@ use rustc_middle::mir::{ self, BasicBlock, CallReturnPlaces, Local, Location, Statement, StatementKind, TerminatorEdges, }; use rustc_mir_dataflow::fmt::DebugWithContext; -use rustc_mir_dataflow::{Analysis, AnalysisDomain, JoinSemiLattice}; +use rustc_mir_dataflow::{Analysis, JoinSemiLattice}; use super::{ConstCx, Qualif, qualifs}; @@ -310,7 +310,7 @@ impl JoinSemiLattice for State { } } -impl<'tcx, Q> AnalysisDomain<'tcx> for FlowSensitiveAnalysis<'_, '_, 'tcx, Q> +impl<'tcx, Q> Analysis<'tcx> for FlowSensitiveAnalysis<'_, '_, 'tcx, Q> where Q: Qualif, { @@ -328,12 +328,7 @@ where fn initialize_start_block(&self, _body: &mir::Body<'tcx>, state: &mut Self::Domain) { self.transfer_function(state).initialize_state(); } -} -impl<'tcx, Q> Analysis<'tcx> for FlowSensitiveAnalysis<'_, '_, 'tcx, Q> -where - Q: Qualif, -{ fn apply_statement_effect( &mut self, state: &mut Self::Domain, diff --git a/compiler/rustc_mir_dataflow/src/framework/engine.rs b/compiler/rustc_mir_dataflow/src/framework/engine.rs index d6853b6ef82..cbd1083d037 100644 --- a/compiler/rustc_mir_dataflow/src/framework/engine.rs +++ b/compiler/rustc_mir_dataflow/src/framework/engine.rs @@ -16,14 +16,13 @@ use {rustc_ast as ast, rustc_graphviz as dot}; use super::fmt::DebugWithContext; use super::{ - Analysis, AnalysisDomain, Direction, JoinSemiLattice, ResultsCursor, ResultsVisitor, graphviz, - visit_results, + Analysis, Direction, JoinSemiLattice, ResultsCursor, ResultsVisitor, graphviz, visit_results, }; use crate::errors::{ DuplicateValuesFor, PathMustEndInFilename, RequiresAnArgument, UnknownFormatter, }; -type EntrySets<'tcx, A> = IndexVec>::Domain>; +type EntrySets<'tcx, A> = IndexVec>::Domain>; /// A dataflow analysis that has converged to fixpoint. #[derive(Clone)] diff --git a/compiler/rustc_mir_dataflow/src/framework/mod.rs b/compiler/rustc_mir_dataflow/src/framework/mod.rs index d7a62ecd2c1..4e72ffabc6e 100644 --- a/compiler/rustc_mir_dataflow/src/framework/mod.rs +++ b/compiler/rustc_mir_dataflow/src/framework/mod.rs @@ -89,11 +89,26 @@ impl BitSetExt for ChunkedBitSet { } } -/// Defines the domain of a dataflow problem. +/// A dataflow problem with an arbitrarily complex transfer function. /// -/// This trait specifies the lattice on which this analysis operates (the domain) as well as its -/// initial value at the entry point of each basic block. -pub trait AnalysisDomain<'tcx> { +/// This trait specifies the lattice on which this analysis operates (the domain), its +/// initial value at the entry point of each basic block, and various operations. +/// +/// # Convergence +/// +/// When implementing this trait it's possible to choose a transfer function such that the analysis +/// does not reach fixpoint. To guarantee convergence, your transfer functions must maintain the +/// following invariant: +/// +/// > If the dataflow state **before** some point in the program changes to be greater +/// than the prior state **before** that point, the dataflow state **after** that point must +/// also change to be greater than the prior state **after** that point. +/// +/// This invariant guarantees that the dataflow state at a given point in the program increases +/// monotonically until fixpoint is reached. Note that this monotonicity requirement only applies +/// to the same point in the program at different points in time. The dataflow state at a given +/// point in the program may or may not be greater than the state at any preceding point. +pub trait Analysis<'tcx> { /// The type that holds the dataflow state at any given point in the program. type Domain: Clone + JoinSemiLattice; @@ -118,25 +133,7 @@ pub trait AnalysisDomain<'tcx> { // block where control flow could exit the MIR body (e.g., those terminated with `return` or // `resume`). It's not obvious how to handle `yield` points in coroutines, however. fn initialize_start_block(&self, body: &mir::Body<'tcx>, state: &mut Self::Domain); -} -/// A dataflow problem with an arbitrarily complex transfer function. -/// -/// # Convergence -/// -/// When implementing this trait it's possible to choose a transfer function such that the analysis -/// does not reach fixpoint. To guarantee convergence, your transfer functions must maintain the -/// following invariant: -/// -/// > If the dataflow state **before** some point in the program changes to be greater -/// than the prior state **before** that point, the dataflow state **after** that point must -/// also change to be greater than the prior state **after** that point. -/// -/// This invariant guarantees that the dataflow state at a given point in the program increases -/// monotonically until fixpoint is reached. Note that this monotonicity requirement only applies -/// to the same point in the program at different points in time. The dataflow state at a given -/// point in the program may or may not be greater than the state at any preceding point. -pub trait Analysis<'tcx>: AnalysisDomain<'tcx> { /// Updates the current dataflow state with the effect of evaluating a statement. fn apply_statement_effect( &mut self, diff --git a/compiler/rustc_mir_dataflow/src/framework/tests.rs b/compiler/rustc_mir_dataflow/src/framework/tests.rs index 1861f4cffc7..de171dbc313 100644 --- a/compiler/rustc_mir_dataflow/src/framework/tests.rs +++ b/compiler/rustc_mir_dataflow/src/framework/tests.rs @@ -154,7 +154,7 @@ impl MockAnalysis<'_, D> { } } -impl<'tcx, D: Direction> AnalysisDomain<'tcx> for MockAnalysis<'tcx, D> { +impl<'tcx, D: Direction> Analysis<'tcx> for MockAnalysis<'tcx, D> { type Domain = BitSet; type Direction = D; @@ -167,9 +167,7 @@ impl<'tcx, D: Direction> AnalysisDomain<'tcx> for MockAnalysis<'tcx, D> { fn initialize_start_block(&self, _: &mir::Body<'tcx>, _: &mut Self::Domain) { unimplemented!("This is never called since `MockAnalysis` is never iterated to fixpoint"); } -} -impl<'tcx, D: Direction> Analysis<'tcx> for MockAnalysis<'tcx, D> { fn apply_statement_effect( &mut self, state: &mut Self::Domain, diff --git a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs index f4edbaf056c..56c38cb02f9 100644 --- a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs +++ b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs @@ -2,7 +2,7 @@ use rustc_index::bit_set::BitSet; use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::*; -use crate::{Analysis, AnalysisDomain, GenKill}; +use crate::{Analysis, GenKill}; /// A dataflow analysis that tracks whether a pointer or reference could possibly exist that points /// to a given local. This analysis ignores fake borrows, so it should not be used by @@ -20,7 +20,7 @@ impl MaybeBorrowedLocals { } } -impl<'tcx> AnalysisDomain<'tcx> for MaybeBorrowedLocals { +impl<'tcx> Analysis<'tcx> for MaybeBorrowedLocals { type Domain = BitSet; const NAME: &'static str = "maybe_borrowed_locals"; @@ -32,9 +32,7 @@ impl<'tcx> AnalysisDomain<'tcx> for MaybeBorrowedLocals { fn initialize_start_block(&self, _: &Body<'tcx>, _: &mut Self::Domain) { // No locals are aliased on function entry } -} -impl<'tcx> Analysis<'tcx> for MaybeBorrowedLocals { fn apply_statement_effect( &mut self, trans: &mut Self::Domain, diff --git a/compiler/rustc_mir_dataflow/src/impls/initialized.rs b/compiler/rustc_mir_dataflow/src/impls/initialized.rs index 18a5ca3f6be..9bb50d1e056 100644 --- a/compiler/rustc_mir_dataflow/src/impls/initialized.rs +++ b/compiler/rustc_mir_dataflow/src/impls/initialized.rs @@ -11,9 +11,8 @@ use crate::elaborate_drops::DropFlagState; use crate::framework::SwitchIntEdgeEffects; use crate::move_paths::{HasMoveData, InitIndex, InitKind, LookupResult, MoveData, MovePathIndex}; use crate::{ - Analysis, AnalysisDomain, GenKill, MaybeReachable, drop_flag_effects, - drop_flag_effects_for_function_entry, drop_flag_effects_for_location, lattice, - on_all_children_bits, on_lookup_result_bits, + Analysis, GenKill, MaybeReachable, drop_flag_effects, drop_flag_effects_for_function_entry, + drop_flag_effects_for_location, lattice, on_all_children_bits, on_lookup_result_bits, }; /// `MaybeInitializedPlaces` tracks all places that might be @@ -270,7 +269,7 @@ impl<'tcx> HasMoveData<'tcx> for EverInitializedPlaces<'_, 'tcx> { impl<'a, 'tcx> MaybeInitializedPlaces<'a, 'tcx> { fn update_bits( - trans: &mut >::Domain, + trans: &mut >::Domain, path: MovePathIndex, state: DropFlagState, ) { @@ -283,7 +282,7 @@ impl<'a, 'tcx> MaybeInitializedPlaces<'a, 'tcx> { impl<'tcx> MaybeUninitializedPlaces<'_, 'tcx> { fn update_bits( - trans: &mut >::Domain, + trans: &mut >::Domain, path: MovePathIndex, state: DropFlagState, ) { @@ -296,7 +295,7 @@ impl<'tcx> MaybeUninitializedPlaces<'_, 'tcx> { impl<'a, 'tcx> DefinitelyInitializedPlaces<'a, 'tcx> { fn update_bits( - trans: &mut >::Domain, + trans: &mut >::Domain, path: MovePathIndex, state: DropFlagState, ) { @@ -307,7 +306,7 @@ impl<'a, 'tcx> DefinitelyInitializedPlaces<'a, 'tcx> { } } -impl<'tcx> AnalysisDomain<'tcx> for MaybeInitializedPlaces<'_, 'tcx> { +impl<'tcx> Analysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> { /// There can be many more `MovePathIndex` than there are locals in a MIR body. /// We use a chunked bitset to avoid paying too high a memory footprint. type Domain = MaybeReachable>; @@ -327,9 +326,7 @@ impl<'tcx> AnalysisDomain<'tcx> for MaybeInitializedPlaces<'_, 'tcx> { state.gen_(path); }); } -} -impl<'tcx> Analysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> { fn apply_statement_effect( &mut self, trans: &mut Self::Domain, @@ -436,7 +433,7 @@ impl<'tcx> Analysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> { } } -impl<'tcx> AnalysisDomain<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> { +impl<'tcx> Analysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> { /// There can be many more `MovePathIndex` than there are locals in a MIR body. /// We use a chunked bitset to avoid paying too high a memory footprint. type Domain = ChunkedBitSet; @@ -458,9 +455,7 @@ impl<'tcx> AnalysisDomain<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> { state.remove(path); }); } -} -impl<'tcx> Analysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> { fn apply_statement_effect( &mut self, trans: &mut Self::Domain, @@ -559,7 +554,7 @@ impl<'tcx> Analysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> { } } -impl<'a, 'tcx> AnalysisDomain<'tcx> for DefinitelyInitializedPlaces<'a, 'tcx> { +impl<'a, 'tcx> Analysis<'tcx> for DefinitelyInitializedPlaces<'a, 'tcx> { /// Use set intersection as the join operator. type Domain = lattice::Dual>; @@ -579,9 +574,7 @@ impl<'a, 'tcx> AnalysisDomain<'tcx> for DefinitelyInitializedPlaces<'a, 'tcx> { state.0.insert(path); }); } -} -impl<'tcx> Analysis<'tcx> for DefinitelyInitializedPlaces<'_, 'tcx> { fn apply_statement_effect( &mut self, trans: &mut Self::Domain, @@ -625,7 +618,7 @@ impl<'tcx> Analysis<'tcx> for DefinitelyInitializedPlaces<'_, 'tcx> { } } -impl<'tcx> AnalysisDomain<'tcx> for EverInitializedPlaces<'_, 'tcx> { +impl<'tcx> Analysis<'tcx> for EverInitializedPlaces<'_, 'tcx> { /// There can be many more `InitIndex` than there are locals in a MIR body. /// We use a chunked bitset to avoid paying too high a memory footprint. type Domain = ChunkedBitSet; @@ -642,9 +635,7 @@ impl<'tcx> AnalysisDomain<'tcx> for EverInitializedPlaces<'_, 'tcx> { state.insert(InitIndex::new(arg_init)); } } -} -impl<'tcx> Analysis<'tcx> for EverInitializedPlaces<'_, 'tcx> { #[instrument(skip(self, trans), level = "debug")] fn apply_statement_effect( &mut self, diff --git a/compiler/rustc_mir_dataflow/src/impls/liveness.rs b/compiler/rustc_mir_dataflow/src/impls/liveness.rs index 452fae379be..e06c1f2bb49 100644 --- a/compiler/rustc_mir_dataflow/src/impls/liveness.rs +++ b/compiler/rustc_mir_dataflow/src/impls/liveness.rs @@ -4,7 +4,7 @@ use rustc_middle::mir::{ self, CallReturnPlaces, Local, Location, Place, StatementKind, TerminatorEdges, }; -use crate::{Analysis, AnalysisDomain, Backward, GenKill}; +use crate::{Analysis, Backward, GenKill}; /// A [live-variable dataflow analysis][liveness]. /// @@ -25,7 +25,7 @@ use crate::{Analysis, AnalysisDomain, Backward, GenKill}; /// [liveness]: https://en.wikipedia.org/wiki/Live_variable_analysis pub struct MaybeLiveLocals; -impl<'tcx> AnalysisDomain<'tcx> for MaybeLiveLocals { +impl<'tcx> Analysis<'tcx> for MaybeLiveLocals { type Domain = BitSet; type Direction = Backward; @@ -39,9 +39,7 @@ impl<'tcx> AnalysisDomain<'tcx> for MaybeLiveLocals { fn initialize_start_block(&self, _: &mir::Body<'tcx>, _: &mut Self::Domain) { // No variables are live until we observe a use } -} -impl<'tcx> Analysis<'tcx> for MaybeLiveLocals { fn apply_statement_effect( &mut self, trans: &mut Self::Domain, @@ -219,7 +217,7 @@ impl<'a> MaybeTransitiveLiveLocals<'a> { } } -impl<'a, 'tcx> AnalysisDomain<'tcx> for MaybeTransitiveLiveLocals<'a> { +impl<'a, 'tcx> Analysis<'tcx> for MaybeTransitiveLiveLocals<'a> { type Domain = BitSet; type Direction = Backward; @@ -233,9 +231,7 @@ impl<'a, 'tcx> AnalysisDomain<'tcx> for MaybeTransitiveLiveLocals<'a> { fn initialize_start_block(&self, _: &mir::Body<'tcx>, _: &mut Self::Domain) { // No variables are live until we observe a use } -} -impl<'a, 'tcx> Analysis<'tcx> for MaybeTransitiveLiveLocals<'a> { fn apply_statement_effect( &mut self, trans: &mut Self::Domain, diff --git a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs index 6ccd7dc17a2..07769057096 100644 --- a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs +++ b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs @@ -5,7 +5,7 @@ use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; use super::MaybeBorrowedLocals; -use crate::{Analysis, AnalysisDomain, GenKill, ResultsCursor}; +use crate::{Analysis, GenKill, ResultsCursor}; pub struct MaybeStorageLive<'a> { always_live_locals: Cow<'a, BitSet>, @@ -17,7 +17,7 @@ impl<'a> MaybeStorageLive<'a> { } } -impl<'a, 'tcx> AnalysisDomain<'tcx> for MaybeStorageLive<'a> { +impl<'a, 'tcx> Analysis<'tcx> for MaybeStorageLive<'a> { type Domain = BitSet; const NAME: &'static str = "maybe_storage_live"; @@ -37,9 +37,7 @@ impl<'a, 'tcx> AnalysisDomain<'tcx> for MaybeStorageLive<'a> { on_entry.insert(arg); } } -} -impl<'a, 'tcx> Analysis<'tcx> for MaybeStorageLive<'a> { fn apply_statement_effect( &mut self, trans: &mut Self::Domain, @@ -83,7 +81,7 @@ impl<'a> MaybeStorageDead<'a> { } } -impl<'a, 'tcx> AnalysisDomain<'tcx> for MaybeStorageDead<'a> { +impl<'a, 'tcx> Analysis<'tcx> for MaybeStorageDead<'a> { type Domain = BitSet; const NAME: &'static str = "maybe_storage_dead"; @@ -102,9 +100,7 @@ impl<'a, 'tcx> AnalysisDomain<'tcx> for MaybeStorageDead<'a> { } } } -} -impl<'a, 'tcx> Analysis<'tcx> for MaybeStorageDead<'a> { fn apply_statement_effect( &mut self, trans: &mut Self::Domain, @@ -152,7 +148,7 @@ impl<'mir, 'tcx> MaybeRequiresStorage<'mir, 'tcx> { } } -impl<'tcx> AnalysisDomain<'tcx> for MaybeRequiresStorage<'_, 'tcx> { +impl<'tcx> Analysis<'tcx> for MaybeRequiresStorage<'_, 'tcx> { type Domain = BitSet; const NAME: &'static str = "requires_storage"; @@ -169,9 +165,7 @@ impl<'tcx> AnalysisDomain<'tcx> for MaybeRequiresStorage<'_, 'tcx> { on_entry.insert(arg); } } -} -impl<'tcx> Analysis<'tcx> for MaybeRequiresStorage<'_, 'tcx> { fn apply_before_statement_effect( &mut self, trans: &mut Self::Domain, @@ -327,11 +321,7 @@ impl<'tcx> Analysis<'tcx> for MaybeRequiresStorage<'_, 'tcx> { impl<'tcx> MaybeRequiresStorage<'_, 'tcx> { /// Kill locals that are fully moved and have not been borrowed. - fn check_for_move( - &mut self, - trans: &mut >::Domain, - loc: Location, - ) { + fn check_for_move(&mut self, trans: &mut >::Domain, loc: Location) { let body = self.borrowed_locals.body(); let mut visitor = MoveVisitor { trans, borrowed_locals: &mut self.borrowed_locals }; visitor.visit_location(body, loc); diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs index d07928dcdc9..b284f0308f9 100644 --- a/compiler/rustc_mir_dataflow/src/lib.rs +++ b/compiler/rustc_mir_dataflow/src/lib.rs @@ -18,9 +18,9 @@ pub use self::drop_flag_effects::{ move_path_children_matching, on_all_children_bits, on_lookup_result_bits, }; pub use self::framework::{ - Analysis, AnalysisDomain, Backward, Direction, Engine, Forward, GenKill, JoinSemiLattice, - MaybeReachable, Results, ResultsCursor, ResultsVisitable, ResultsVisitor, SwitchIntEdgeEffects, - fmt, graphviz, lattice, visit_results, + Analysis, Backward, Direction, Engine, Forward, GenKill, JoinSemiLattice, MaybeReachable, + Results, ResultsCursor, ResultsVisitable, ResultsVisitor, SwitchIntEdgeEffects, fmt, graphviz, + lattice, visit_results, }; use self::move_paths::MoveData; diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index aa09fe1dd45..faee40faa3f 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -51,7 +51,7 @@ use tracing::debug; use crate::fmt::DebugWithContext; use crate::lattice::{HasBottom, HasTop}; -use crate::{Analysis, AnalysisDomain, JoinSemiLattice, SwitchIntEdgeEffects}; +use crate::{Analysis, JoinSemiLattice, SwitchIntEdgeEffects}; pub trait ValueAnalysis<'tcx> { /// For each place of interest, the analysis tracks a value of the given type. @@ -334,7 +334,7 @@ pub trait ValueAnalysis<'tcx> { pub struct ValueAnalysisWrapper(pub T); -impl<'tcx, T: ValueAnalysis<'tcx>> AnalysisDomain<'tcx> for ValueAnalysisWrapper { +impl<'tcx, T: ValueAnalysis<'tcx>> Analysis<'tcx> for ValueAnalysisWrapper { type Domain = State; const NAME: &'static str = T::NAME; @@ -351,12 +351,7 @@ impl<'tcx, T: ValueAnalysis<'tcx>> AnalysisDomain<'tcx> for ValueAnalysisWrapper state.flood(PlaceRef { local: arg, projection: &[] }, self.0.map()); } } -} -impl<'tcx, T> Analysis<'tcx> for ValueAnalysisWrapper -where - T: ValueAnalysis<'tcx>, -{ fn apply_statement_effect( &mut self, state: &mut Self::Domain, From 33abf6a0c8b9a051c06dcb43935f3e15c96ade45 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 10 Oct 2024 12:06:25 +1100 Subject: [PATCH 273/357] Add defaults for `Analysis::apply_{call_return_effect,terminator_effect}`. To avoid some low-value boilerplate code. --- compiler/rustc_borrowck/src/dataflow.rs | 12 +----- .../rustc_mir_dataflow/src/framework/mod.rs | 17 +++++---- .../rustc_mir_dataflow/src/framework/tests.rs | 8 ---- .../src/impls/borrowed_locals.rs | 8 ---- .../src/impls/storage_liveness.rs | 38 ------------------- 5 files changed, 11 insertions(+), 72 deletions(-) diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs index 216cf8ac988..89ff12c1479 100644 --- a/compiler/rustc_borrowck/src/dataflow.rs +++ b/compiler/rustc_borrowck/src/dataflow.rs @@ -1,9 +1,7 @@ use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::graph; use rustc_index::bit_set::BitSet; -use rustc_middle::mir::{ - self, BasicBlock, Body, CallReturnPlaces, Location, Place, TerminatorEdges, -}; +use rustc_middle::mir::{self, BasicBlock, Body, Location, Place, TerminatorEdges}; use rustc_middle::ty::{RegionVid, TyCtxt}; use rustc_mir_dataflow::fmt::DebugWithContext; use rustc_mir_dataflow::impls::{EverInitializedPlaces, MaybeUninitializedPlaces}; @@ -595,14 +593,6 @@ impl<'tcx> rustc_mir_dataflow::Analysis<'tcx> for Borrows<'_, 'tcx> { } terminator.edges() } - - fn apply_call_return_effect( - &mut self, - _trans: &mut Self::Domain, - _block: mir::BasicBlock, - _return_places: CallReturnPlaces<'_, 'tcx>, - ) { - } } impl DebugWithContext for BorrowIndex {} diff --git a/compiler/rustc_mir_dataflow/src/framework/mod.rs b/compiler/rustc_mir_dataflow/src/framework/mod.rs index 4e72ffabc6e..959f1ea5340 100644 --- a/compiler/rustc_mir_dataflow/src/framework/mod.rs +++ b/compiler/rustc_mir_dataflow/src/framework/mod.rs @@ -164,10 +164,12 @@ pub trait Analysis<'tcx> { /// initialized here. fn apply_terminator_effect<'mir>( &mut self, - state: &mut Self::Domain, + _state: &mut Self::Domain, terminator: &'mir mir::Terminator<'tcx>, - location: Location, - ) -> TerminatorEdges<'mir, 'tcx>; + _location: Location, + ) -> TerminatorEdges<'mir, 'tcx> { + terminator.edges() + } /// Updates the current dataflow state with an effect that occurs immediately *before* the /// given terminator. @@ -192,10 +194,11 @@ pub trait Analysis<'tcx> { /// edges. fn apply_call_return_effect( &mut self, - state: &mut Self::Domain, - block: BasicBlock, - return_places: CallReturnPlaces<'_, 'tcx>, - ); + _state: &mut Self::Domain, + _block: BasicBlock, + _return_places: CallReturnPlaces<'_, 'tcx>, + ) { + } /// Updates the current dataflow state with the effect of taking a particular branch in a /// `SwitchInt` terminator. diff --git a/compiler/rustc_mir_dataflow/src/framework/tests.rs b/compiler/rustc_mir_dataflow/src/framework/tests.rs index de171dbc313..14fb6dfb50c 100644 --- a/compiler/rustc_mir_dataflow/src/framework/tests.rs +++ b/compiler/rustc_mir_dataflow/src/framework/tests.rs @@ -208,14 +208,6 @@ impl<'tcx, D: Direction> Analysis<'tcx> for MockAnalysis<'tcx, D> { let idx = self.effect(Effect::Before.at_index(location.statement_index)); assert!(state.insert(idx)); } - - fn apply_call_return_effect( - &mut self, - _state: &mut Self::Domain, - _block: BasicBlock, - _return_places: CallReturnPlaces<'_, 'tcx>, - ) { - } } #[derive(Clone, Copy, Debug, PartialEq, Eq)] diff --git a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs index 56c38cb02f9..859019fd1f6 100644 --- a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs +++ b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs @@ -51,14 +51,6 @@ impl<'tcx> Analysis<'tcx> for MaybeBorrowedLocals { self.transfer_function(trans).visit_terminator(terminator, location); terminator.edges() } - - fn apply_call_return_effect( - &mut self, - _trans: &mut Self::Domain, - _block: BasicBlock, - _return_places: CallReturnPlaces<'_, 'tcx>, - ) { - } } /// A `Visitor` that defines the transfer function for `MaybeBorrowedLocals`. diff --git a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs index 07769057096..c5fd2a631ff 100644 --- a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs +++ b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs @@ -50,25 +50,6 @@ impl<'a, 'tcx> Analysis<'tcx> for MaybeStorageLive<'a> { _ => (), } } - - fn apply_terminator_effect<'mir>( - &mut self, - _trans: &mut Self::Domain, - terminator: &'mir Terminator<'tcx>, - _: Location, - ) -> TerminatorEdges<'mir, 'tcx> { - // Terminators have no effect - terminator.edges() - } - - fn apply_call_return_effect( - &mut self, - _trans: &mut Self::Domain, - _block: BasicBlock, - _return_places: CallReturnPlaces<'_, 'tcx>, - ) { - // Nothing to do when a call returns successfully - } } pub struct MaybeStorageDead<'a> { @@ -113,25 +94,6 @@ impl<'a, 'tcx> Analysis<'tcx> for MaybeStorageDead<'a> { _ => (), } } - - fn apply_terminator_effect<'mir>( - &mut self, - _: &mut Self::Domain, - terminator: &'mir Terminator<'tcx>, - _: Location, - ) -> TerminatorEdges<'mir, 'tcx> { - // Terminators have no effect - terminator.edges() - } - - fn apply_call_return_effect( - &mut self, - _trans: &mut Self::Domain, - _block: BasicBlock, - _return_places: CallReturnPlaces<'_, 'tcx>, - ) { - // Nothing to do when a call returns successfully - } } type BorrowedLocalsResults<'mir, 'tcx> = ResultsCursor<'mir, 'tcx, MaybeBorrowedLocals>; From b6b6c12819bbffca3aa75298afb79cf1a70e0312 Mon Sep 17 00:00:00 2001 From: Tamme Dittrich Date: Mon, 14 Oct 2024 08:07:41 +0200 Subject: [PATCH 274/357] Update lint message for ABI not supported --- .../rustc_hir_analysis/src/check/check.rs | 6 +++--- compiler/rustc_lint_defs/src/builtin.rs | 2 +- tests/ui/abi/unsupported.aarch64.stderr | 20 +++++++++---------- tests/ui/abi/unsupported.arm.stderr | 18 ++++++++--------- tests/ui/abi/unsupported.i686.stderr | 14 ++++++------- tests/ui/abi/unsupported.riscv32.stderr | 18 ++++++++--------- tests/ui/abi/unsupported.riscv64.stderr | 18 ++++++++--------- tests/ui/abi/unsupported.x64.stderr | 18 ++++++++--------- 8 files changed, 57 insertions(+), 57 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 4429f6346e8..94da3d4ea84 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -61,9 +61,9 @@ pub fn check_abi_fn_ptr(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: Ab Some(true) => (), Some(false) | None => { tcx.node_span_lint(UNSUPPORTED_FN_PTR_CALLING_CONVENTIONS, hir_id, span, |lint| { - lint.primary_message( - "use of calling convention not supported on this target on function pointer", - ); + lint.primary_message(format!( + "the calling convention {abi} is not supported on this target" + )); }); } } diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 23dc5214fe2..da603df9a9a 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -3859,7 +3859,7 @@ declare_lint! { /// This will produce: /// /// ```text - /// warning: use of calling convention not supported on this target on function pointer + /// warning: the calling convention `"stdcall"` is not supported on this target /// --> $DIR/unsupported.rs:34:15 /// | /// LL | fn stdcall_ptr(f: extern "stdcall" fn()) { diff --git a/tests/ui/abi/unsupported.aarch64.stderr b/tests/ui/abi/unsupported.aarch64.stderr index 00a5b4b2ee1..82908ef88a8 100644 --- a/tests/ui/abi/unsupported.aarch64.stderr +++ b/tests/ui/abi/unsupported.aarch64.stderr @@ -1,4 +1,4 @@ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "ptx-kernel" is not supported on this target --> $DIR/unsupported.rs:35:15 | LL | fn ptx_ptr(f: extern "ptx-kernel" fn()) { @@ -14,7 +14,7 @@ error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target LL | extern "ptx-kernel" {} | ^^^^^^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "aapcs" is not supported on this target --> $DIR/unsupported.rs:49:17 | LL | fn aapcs_ptr(f: extern "aapcs" fn()) { @@ -29,7 +29,7 @@ error[E0570]: `"aapcs"` is not a supported ABI for the current target LL | extern "aapcs" {} | ^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "msp430-interrupt" is not supported on this target --> $DIR/unsupported.rs:71:18 | LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) { @@ -44,7 +44,7 @@ error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target LL | extern "msp430-interrupt" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "avr-interrupt" is not supported on this target --> $DIR/unsupported.rs:81:15 | LL | fn avr_ptr(f: extern "avr-interrupt" fn()) { @@ -59,7 +59,7 @@ error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target LL | extern "avr-interrupt" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "riscv-interrupt-m" is not supported on this target --> $DIR/unsupported.rs:94:17 | LL | fn riscv_ptr(f: extern "riscv-interrupt-m" fn()) { @@ -74,7 +74,7 @@ error[E0570]: `"riscv-interrupt-m"` is not a supported ABI for the current targe LL | extern "riscv-interrupt-m" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "x86-interrupt" is not supported on this target --> $DIR/unsupported.rs:116:15 | LL | fn x86_ptr(f: extern "x86-interrupt" fn()) { @@ -89,7 +89,7 @@ error[E0570]: `"x86-interrupt"` is not a supported ABI for the current target LL | extern "x86-interrupt" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "thiscall" is not supported on this target --> $DIR/unsupported.rs:139:20 | LL | fn thiscall_ptr(f: extern "thiscall" fn()) { @@ -104,7 +104,7 @@ error[E0570]: `"thiscall"` is not a supported ABI for the current target LL | extern "thiscall" {} | ^^^^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "stdcall" is not supported on this target --> $DIR/unsupported.rs:170:19 | LL | fn stdcall_ptr(f: extern "stdcall" fn()) { @@ -123,7 +123,7 @@ LL | extern "stdcall" {} = note: for more information, see issue #87678 = note: `#[warn(unsupported_calling_conventions)]` on by default -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "C-cmse-nonsecure-call" is not supported on this target --> $DIR/unsupported.rs:195:21 | LL | fn cmse_call_ptr(f: extern "C-cmse-nonsecure-call" fn()) { @@ -132,7 +132,7 @@ LL | fn cmse_call_ptr(f: extern "C-cmse-nonsecure-call" fn()) { = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #130260 -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "C-cmse-nonsecure-entry" is not supported on this target --> $DIR/unsupported.rs:203:22 | LL | fn cmse_entry_ptr(f: extern "C-cmse-nonsecure-entry" fn()) { diff --git a/tests/ui/abi/unsupported.arm.stderr b/tests/ui/abi/unsupported.arm.stderr index dfb5ceb0c33..39ec5d16fcd 100644 --- a/tests/ui/abi/unsupported.arm.stderr +++ b/tests/ui/abi/unsupported.arm.stderr @@ -1,4 +1,4 @@ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "ptx-kernel" is not supported on this target --> $DIR/unsupported.rs:35:15 | LL | fn ptx_ptr(f: extern "ptx-kernel" fn()) { @@ -14,7 +14,7 @@ error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target LL | extern "ptx-kernel" {} | ^^^^^^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "msp430-interrupt" is not supported on this target --> $DIR/unsupported.rs:71:18 | LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) { @@ -29,7 +29,7 @@ error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target LL | extern "msp430-interrupt" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "avr-interrupt" is not supported on this target --> $DIR/unsupported.rs:81:15 | LL | fn avr_ptr(f: extern "avr-interrupt" fn()) { @@ -44,7 +44,7 @@ error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target LL | extern "avr-interrupt" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "riscv-interrupt-m" is not supported on this target --> $DIR/unsupported.rs:94:17 | LL | fn riscv_ptr(f: extern "riscv-interrupt-m" fn()) { @@ -59,7 +59,7 @@ error[E0570]: `"riscv-interrupt-m"` is not a supported ABI for the current targe LL | extern "riscv-interrupt-m" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "x86-interrupt" is not supported on this target --> $DIR/unsupported.rs:116:15 | LL | fn x86_ptr(f: extern "x86-interrupt" fn()) { @@ -74,7 +74,7 @@ error[E0570]: `"x86-interrupt"` is not a supported ABI for the current target LL | extern "x86-interrupt" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "thiscall" is not supported on this target --> $DIR/unsupported.rs:139:20 | LL | fn thiscall_ptr(f: extern "thiscall" fn()) { @@ -89,7 +89,7 @@ error[E0570]: `"thiscall"` is not a supported ABI for the current target LL | extern "thiscall" {} | ^^^^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "stdcall" is not supported on this target --> $DIR/unsupported.rs:170:19 | LL | fn stdcall_ptr(f: extern "stdcall" fn()) { @@ -108,7 +108,7 @@ LL | extern "stdcall" {} = note: for more information, see issue #87678 = note: `#[warn(unsupported_calling_conventions)]` on by default -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "C-cmse-nonsecure-call" is not supported on this target --> $DIR/unsupported.rs:195:21 | LL | fn cmse_call_ptr(f: extern "C-cmse-nonsecure-call" fn()) { @@ -117,7 +117,7 @@ LL | fn cmse_call_ptr(f: extern "C-cmse-nonsecure-call" fn()) { = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #130260 -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "C-cmse-nonsecure-entry" is not supported on this target --> $DIR/unsupported.rs:203:22 | LL | fn cmse_entry_ptr(f: extern "C-cmse-nonsecure-entry" fn()) { diff --git a/tests/ui/abi/unsupported.i686.stderr b/tests/ui/abi/unsupported.i686.stderr index 6537ce66057..1dc01a66aab 100644 --- a/tests/ui/abi/unsupported.i686.stderr +++ b/tests/ui/abi/unsupported.i686.stderr @@ -1,4 +1,4 @@ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "ptx-kernel" is not supported on this target --> $DIR/unsupported.rs:35:15 | LL | fn ptx_ptr(f: extern "ptx-kernel" fn()) { @@ -14,7 +14,7 @@ error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target LL | extern "ptx-kernel" {} | ^^^^^^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "aapcs" is not supported on this target --> $DIR/unsupported.rs:49:17 | LL | fn aapcs_ptr(f: extern "aapcs" fn()) { @@ -29,7 +29,7 @@ error[E0570]: `"aapcs"` is not a supported ABI for the current target LL | extern "aapcs" {} | ^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "msp430-interrupt" is not supported on this target --> $DIR/unsupported.rs:71:18 | LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) { @@ -44,7 +44,7 @@ error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target LL | extern "msp430-interrupt" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "avr-interrupt" is not supported on this target --> $DIR/unsupported.rs:81:15 | LL | fn avr_ptr(f: extern "avr-interrupt" fn()) { @@ -59,7 +59,7 @@ error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target LL | extern "avr-interrupt" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "riscv-interrupt-m" is not supported on this target --> $DIR/unsupported.rs:94:17 | LL | fn riscv_ptr(f: extern "riscv-interrupt-m" fn()) { @@ -74,7 +74,7 @@ error[E0570]: `"riscv-interrupt-m"` is not a supported ABI for the current targe LL | extern "riscv-interrupt-m" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "C-cmse-nonsecure-call" is not supported on this target --> $DIR/unsupported.rs:195:21 | LL | fn cmse_call_ptr(f: extern "C-cmse-nonsecure-call" fn()) { @@ -83,7 +83,7 @@ LL | fn cmse_call_ptr(f: extern "C-cmse-nonsecure-call" fn()) { = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #130260 -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "C-cmse-nonsecure-entry" is not supported on this target --> $DIR/unsupported.rs:203:22 | LL | fn cmse_entry_ptr(f: extern "C-cmse-nonsecure-entry" fn()) { diff --git a/tests/ui/abi/unsupported.riscv32.stderr b/tests/ui/abi/unsupported.riscv32.stderr index a53f85f28bc..e7d5197feeb 100644 --- a/tests/ui/abi/unsupported.riscv32.stderr +++ b/tests/ui/abi/unsupported.riscv32.stderr @@ -1,4 +1,4 @@ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "ptx-kernel" is not supported on this target --> $DIR/unsupported.rs:35:15 | LL | fn ptx_ptr(f: extern "ptx-kernel" fn()) { @@ -14,7 +14,7 @@ error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target LL | extern "ptx-kernel" {} | ^^^^^^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "aapcs" is not supported on this target --> $DIR/unsupported.rs:49:17 | LL | fn aapcs_ptr(f: extern "aapcs" fn()) { @@ -29,7 +29,7 @@ error[E0570]: `"aapcs"` is not a supported ABI for the current target LL | extern "aapcs" {} | ^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "msp430-interrupt" is not supported on this target --> $DIR/unsupported.rs:71:18 | LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) { @@ -44,7 +44,7 @@ error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target LL | extern "msp430-interrupt" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "avr-interrupt" is not supported on this target --> $DIR/unsupported.rs:81:15 | LL | fn avr_ptr(f: extern "avr-interrupt" fn()) { @@ -59,7 +59,7 @@ error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target LL | extern "avr-interrupt" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "x86-interrupt" is not supported on this target --> $DIR/unsupported.rs:116:15 | LL | fn x86_ptr(f: extern "x86-interrupt" fn()) { @@ -74,7 +74,7 @@ error[E0570]: `"x86-interrupt"` is not a supported ABI for the current target LL | extern "x86-interrupt" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "thiscall" is not supported on this target --> $DIR/unsupported.rs:139:20 | LL | fn thiscall_ptr(f: extern "thiscall" fn()) { @@ -89,7 +89,7 @@ error[E0570]: `"thiscall"` is not a supported ABI for the current target LL | extern "thiscall" {} | ^^^^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "stdcall" is not supported on this target --> $DIR/unsupported.rs:170:19 | LL | fn stdcall_ptr(f: extern "stdcall" fn()) { @@ -108,7 +108,7 @@ LL | extern "stdcall" {} = note: for more information, see issue #87678 = note: `#[warn(unsupported_calling_conventions)]` on by default -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "C-cmse-nonsecure-call" is not supported on this target --> $DIR/unsupported.rs:195:21 | LL | fn cmse_call_ptr(f: extern "C-cmse-nonsecure-call" fn()) { @@ -117,7 +117,7 @@ LL | fn cmse_call_ptr(f: extern "C-cmse-nonsecure-call" fn()) { = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #130260 -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "C-cmse-nonsecure-entry" is not supported on this target --> $DIR/unsupported.rs:203:22 | LL | fn cmse_entry_ptr(f: extern "C-cmse-nonsecure-entry" fn()) { diff --git a/tests/ui/abi/unsupported.riscv64.stderr b/tests/ui/abi/unsupported.riscv64.stderr index a53f85f28bc..e7d5197feeb 100644 --- a/tests/ui/abi/unsupported.riscv64.stderr +++ b/tests/ui/abi/unsupported.riscv64.stderr @@ -1,4 +1,4 @@ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "ptx-kernel" is not supported on this target --> $DIR/unsupported.rs:35:15 | LL | fn ptx_ptr(f: extern "ptx-kernel" fn()) { @@ -14,7 +14,7 @@ error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target LL | extern "ptx-kernel" {} | ^^^^^^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "aapcs" is not supported on this target --> $DIR/unsupported.rs:49:17 | LL | fn aapcs_ptr(f: extern "aapcs" fn()) { @@ -29,7 +29,7 @@ error[E0570]: `"aapcs"` is not a supported ABI for the current target LL | extern "aapcs" {} | ^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "msp430-interrupt" is not supported on this target --> $DIR/unsupported.rs:71:18 | LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) { @@ -44,7 +44,7 @@ error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target LL | extern "msp430-interrupt" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "avr-interrupt" is not supported on this target --> $DIR/unsupported.rs:81:15 | LL | fn avr_ptr(f: extern "avr-interrupt" fn()) { @@ -59,7 +59,7 @@ error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target LL | extern "avr-interrupt" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "x86-interrupt" is not supported on this target --> $DIR/unsupported.rs:116:15 | LL | fn x86_ptr(f: extern "x86-interrupt" fn()) { @@ -74,7 +74,7 @@ error[E0570]: `"x86-interrupt"` is not a supported ABI for the current target LL | extern "x86-interrupt" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "thiscall" is not supported on this target --> $DIR/unsupported.rs:139:20 | LL | fn thiscall_ptr(f: extern "thiscall" fn()) { @@ -89,7 +89,7 @@ error[E0570]: `"thiscall"` is not a supported ABI for the current target LL | extern "thiscall" {} | ^^^^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "stdcall" is not supported on this target --> $DIR/unsupported.rs:170:19 | LL | fn stdcall_ptr(f: extern "stdcall" fn()) { @@ -108,7 +108,7 @@ LL | extern "stdcall" {} = note: for more information, see issue #87678 = note: `#[warn(unsupported_calling_conventions)]` on by default -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "C-cmse-nonsecure-call" is not supported on this target --> $DIR/unsupported.rs:195:21 | LL | fn cmse_call_ptr(f: extern "C-cmse-nonsecure-call" fn()) { @@ -117,7 +117,7 @@ LL | fn cmse_call_ptr(f: extern "C-cmse-nonsecure-call" fn()) { = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #130260 -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "C-cmse-nonsecure-entry" is not supported on this target --> $DIR/unsupported.rs:203:22 | LL | fn cmse_entry_ptr(f: extern "C-cmse-nonsecure-entry" fn()) { diff --git a/tests/ui/abi/unsupported.x64.stderr b/tests/ui/abi/unsupported.x64.stderr index 45ba9a6649c..bbca754dd41 100644 --- a/tests/ui/abi/unsupported.x64.stderr +++ b/tests/ui/abi/unsupported.x64.stderr @@ -1,4 +1,4 @@ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "ptx-kernel" is not supported on this target --> $DIR/unsupported.rs:35:15 | LL | fn ptx_ptr(f: extern "ptx-kernel" fn()) { @@ -14,7 +14,7 @@ error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target LL | extern "ptx-kernel" {} | ^^^^^^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "aapcs" is not supported on this target --> $DIR/unsupported.rs:49:17 | LL | fn aapcs_ptr(f: extern "aapcs" fn()) { @@ -29,7 +29,7 @@ error[E0570]: `"aapcs"` is not a supported ABI for the current target LL | extern "aapcs" {} | ^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "msp430-interrupt" is not supported on this target --> $DIR/unsupported.rs:71:18 | LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) { @@ -44,7 +44,7 @@ error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target LL | extern "msp430-interrupt" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "avr-interrupt" is not supported on this target --> $DIR/unsupported.rs:81:15 | LL | fn avr_ptr(f: extern "avr-interrupt" fn()) { @@ -59,7 +59,7 @@ error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target LL | extern "avr-interrupt" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "riscv-interrupt-m" is not supported on this target --> $DIR/unsupported.rs:94:17 | LL | fn riscv_ptr(f: extern "riscv-interrupt-m" fn()) { @@ -74,7 +74,7 @@ error[E0570]: `"riscv-interrupt-m"` is not a supported ABI for the current targe LL | extern "riscv-interrupt-m" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "thiscall" is not supported on this target --> $DIR/unsupported.rs:139:20 | LL | fn thiscall_ptr(f: extern "thiscall" fn()) { @@ -89,7 +89,7 @@ error[E0570]: `"thiscall"` is not a supported ABI for the current target LL | extern "thiscall" {} | ^^^^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "stdcall" is not supported on this target --> $DIR/unsupported.rs:170:19 | LL | fn stdcall_ptr(f: extern "stdcall" fn()) { @@ -108,7 +108,7 @@ LL | extern "stdcall" {} = note: for more information, see issue #87678 = note: `#[warn(unsupported_calling_conventions)]` on by default -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "C-cmse-nonsecure-call" is not supported on this target --> $DIR/unsupported.rs:195:21 | LL | fn cmse_call_ptr(f: extern "C-cmse-nonsecure-call" fn()) { @@ -117,7 +117,7 @@ LL | fn cmse_call_ptr(f: extern "C-cmse-nonsecure-call" fn()) { = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #130260 -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "C-cmse-nonsecure-entry" is not supported on this target --> $DIR/unsupported.rs:203:22 | LL | fn cmse_entry_ptr(f: extern "C-cmse-nonsecure-entry" fn()) { From cec59864393bfd7efab2834b895fc73fbb59f78e Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sun, 13 Oct 2024 23:22:57 +1100 Subject: [PATCH 275/357] Document various parts of compiletest's `lib.rs` --- src/tools/compiletest/src/lib.rs | 127 +++++++++++++++++++++++++++---- 1 file changed, 114 insertions(+), 13 deletions(-) diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index 18000e5602c..2e66c084dd7 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -43,6 +43,11 @@ use crate::common::{ use crate::header::HeadersCache; use crate::util::logv; +/// Creates the `Config` instance for this invocation of compiletest. +/// +/// The config mostly reflects command-line arguments, but there might also be +/// some code here that inspects environment variables or even runs executables +/// (e.g. when discovering debugger versions). pub fn parse_config(args: Vec) -> Config { let mut opts = Options::new(); opts.reqopt("", "compile-lib-path", "path to host shared libraries", "PATH") @@ -413,6 +418,7 @@ pub fn opt_str2(maybestr: Option) -> String { } } +/// Called by `main` after the config has been parsed. pub fn run_tests(config: Arc) { // If we want to collect rustfix coverage information, // we first make sure that the coverage file does not exist. @@ -454,6 +460,8 @@ pub fn run_tests(config: Arc) { configs.push(config.clone()); }; + // Discover all of the tests in the test suite directory, and build a libtest + // structure for each test (or each revision of a multi-revision test). let mut tests = Vec::new(); for c in configs { let mut found_paths = HashSet::new(); @@ -463,7 +471,12 @@ pub fn run_tests(config: Arc) { tests.sort_by(|a, b| a.desc.name.as_slice().cmp(&b.desc.name.as_slice())); + // Delegate to libtest to filter and run the big list of structures created + // during test discovery. When libtest decides to run a test, it will invoke + // the corresponding closure created by `make_test_closure`. let res = test::run_tests_console(&opts, tests); + + // Check the outcome reported by libtest. match res { Ok(true) => {} Ok(false) => { @@ -532,6 +545,11 @@ pub fn test_opts(config: &Config) -> test::TestOpts { } } +/// Creates libtest structures for every test/revision in the test suite directory. +/// +/// This always inspects _all_ test files in the suite (e.g. all 17k+ ui tests), +/// regardless of whether any filters/tests were specified on the command-line, +/// because filtering is handled later by libtest. pub fn make_tests( config: Arc, tests: &mut Vec, @@ -610,10 +628,17 @@ fn common_inputs_stamp(config: &Config) -> Stamp { stamp } +/// Returns a list of modified/untracked test files that should be run when +/// the `--only-modified` flag is in use. +/// +/// (Might be inaccurate in some cases.) fn modified_tests(config: &Config, dir: &Path) -> Result, String> { + // If `--only-modified` wasn't passed, the list of modified tests won't be + // used for anything, so avoid some work and just return an empty list. if !config.only_modified { return Ok(vec![]); } + let files = get_git_modified_files(&config.git_config(), Some(dir), &vec!["rs", "stderr", "fixed"])? .unwrap_or(vec![]); @@ -634,6 +659,8 @@ fn modified_tests(config: &Config, dir: &Path) -> Result, String> { Ok(full_paths) } +/// Recursively scans a directory to find test files and create test structures +/// that will be handed over to libtest. fn collect_tests_from_dir( config: Arc, cache: &HeadersCache, @@ -650,6 +677,8 @@ fn collect_tests_from_dir( return Ok(()); } + // For run-make tests, a "test file" is actually a directory that contains + // an `rmake.rs` or `Makefile`" if config.mode == Mode::RunMake { if dir.join("Makefile").exists() && dir.join("rmake.rs").exists() { return Err(io::Error::other( @@ -663,6 +692,7 @@ fn collect_tests_from_dir( relative_dir: relative_dir_path.parent().unwrap().to_path_buf(), }; tests.extend(make_test(config, cache, &paths, inputs, poisoned)); + // This directory is a test, so don't try to find other tests inside it. return Ok(()); } } @@ -677,22 +707,27 @@ fn collect_tests_from_dir( fs::create_dir_all(&build_dir).unwrap(); // Add each `.rs` file as a test, and recurse further on any - // subdirectories we find, except for `aux` directories. + // subdirectories we find, except for `auxiliary` directories. // FIXME: this walks full tests tree, even if we have something to ignore // use walkdir/ignore like in tidy? for file in fs::read_dir(dir)? { let file = file?; let file_path = file.path(); let file_name = file.file_name(); + if is_test(&file_name) && (!config.only_modified || modified_tests.contains(&file_path)) { + // We found a test file, so create the corresponding libtest structures. debug!("found test file: {:?}", file_path.display()); + + // Record the stem of the test file, to check for overlaps later. let rel_test_path = relative_dir_path.join(file_path.file_stem().unwrap()); found_paths.insert(rel_test_path); + let paths = TestPaths { file: file_path, relative_dir: relative_dir_path.to_path_buf() }; - tests.extend(make_test(config.clone(), cache, &paths, inputs, poisoned)) } else if file_path.is_dir() { + // Recurse to find more tests in a subdirectory. let relative_file_path = relative_dir_path.join(file.file_name()); if &file_name != "auxiliary" { debug!("found directory: {:?}", file_path.display()); @@ -728,6 +763,8 @@ pub fn is_test(file_name: &OsString) -> bool { !invalid_prefixes.iter().any(|p| file_name.starts_with(p)) } +/// For a single test file, creates one or more test structures (one per revision) +/// that can be handed over to libtest to run, possibly in parallel. fn make_test( config: Arc, cache: &HeadersCache, @@ -735,6 +772,9 @@ fn make_test( inputs: &Stamp, poisoned: &mut bool, ) -> Vec { + // For run-make tests, each "test file" is actually a _directory_ containing + // an `rmake.rs` or `Makefile`. But for the purposes of directive parsing, + // we want to look at that recipe file, not the directory itself. let test_path = if config.mode == Mode::RunMake { if testpaths.file.join("rmake.rs").exists() && testpaths.file.join("Makefile").exists() { panic!("run-make tests cannot have both `rmake.rs` and `Makefile`"); @@ -750,26 +790,40 @@ fn make_test( } else { PathBuf::from(&testpaths.file) }; + + // Scan the test file to discover its revisions, if any. let early_props = EarlyProps::from_file(&config, &test_path); - // Incremental tests are special, they inherently cannot be run in parallel. - // `runtest::run` will be responsible for iterating over revisions. + // Normally we create one libtest structure per revision, with two exceptions: + // - If a test doesn't use revisions, create a dummy revision (None) so that + // the test can still run. + // - Incremental tests inherently can't run their revisions in parallel, so + // we treat them like non-revisioned tests here. Incremental revisions are + // handled internally by `runtest::run` instead. let revisions = if early_props.revisions.is_empty() || config.mode == Mode::Incremental { vec![None] } else { early_props.revisions.iter().map(|r| Some(r.as_str())).collect() }; + // For each revision (or the sole dummy revision), create and return a + // `test::TestDescAndFn` that can be handed over to libtest. revisions .into_iter() .map(|revision| { + // Create a test name and description to hand over to libtest. let src_file = std::fs::File::open(&test_path).expect("open test file to parse ignores"); let test_name = crate::make_test_name(&config, testpaths, revision); + // Create a libtest description for the test/revision. + // This is where `ignore-*`/`only-*`/`needs-*` directives are handled, + // because they need to set the libtest ignored flag. let mut desc = make_test_description( &config, cache, test_name, &test_path, src_file, revision, poisoned, ); - // Ignore tests that already run and are up to date with respect to inputs. + + // If a test's inputs haven't changed since the last time it ran, + // mark it as ignored so that libtest will skip it. if !config.force_rerun && is_up_to_date(&config, testpaths, &early_props, revision, inputs) { @@ -777,18 +831,25 @@ fn make_test( // Keep this in sync with the "up-to-date" message detected by bootstrap. desc.ignore_message = Some("up-to-date"); } - test::TestDescAndFn { - desc, - testfn: make_test_closure(config.clone(), testpaths, revision), - } + + // Create the callback that will run this test/revision when libtest calls it. + let testfn = make_test_closure(config.clone(), testpaths, revision); + + test::TestDescAndFn { desc, testfn } }) .collect() } +/// The path of the `stamp` file that gets created or updated whenever a +/// particular test completes successfully. fn stamp(config: &Config, testpaths: &TestPaths, revision: Option<&str>) -> PathBuf { output_base_dir(config, testpaths, revision).join("stamp") } +/// Returns a list of files that, if modified, would cause this test to no +/// longer be up-to-date. +/// +/// (Might be inaccurate in some cases.) fn files_related_to_test( config: &Config, testpaths: &TestPaths, @@ -824,46 +885,61 @@ fn files_related_to_test( related } +/// Checks whether a particular test/revision is "up-to-date", meaning that no +/// relevant files/settings have changed since the last time the test succeeded. +/// +/// (This is not very reliable in some circumstances, so the `--force-rerun` +/// flag can be used to ignore up-to-date checking and always re-run tests.) fn is_up_to_date( config: &Config, testpaths: &TestPaths, props: &EarlyProps, revision: Option<&str>, - inputs: &Stamp, + inputs: &Stamp, // Last-modified timestamp of the compiler, compiletest etc ) -> bool { let stamp_name = stamp(config, testpaths, revision); - // Check hash. + // Check the config hash inside the stamp file. let contents = match fs::read_to_string(&stamp_name) { Ok(f) => f, Err(ref e) if e.kind() == ErrorKind::InvalidData => panic!("Can't read stamp contents"), + // The test hasn't succeeded yet, so it is not up-to-date. Err(_) => return false, }; let expected_hash = runtest::compute_stamp_hash(config); if contents != expected_hash { + // Some part of compiletest configuration has changed since the test + // last succeeded, so it is not up-to-date. return false; } - // Check timestamps. + // Check the timestamp of the stamp file against the last modified time + // of all files known to be relevant to the test. let mut inputs = inputs.clone(); for path in files_related_to_test(config, testpaths, props, revision) { inputs.add_path(&path); } + // If no relevant files have been modified since the stamp file was last + // written, the test is up-to-date. inputs < Stamp::from_path(&stamp_name) } +/// The maximum of a set of file-modified timestamps. #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] struct Stamp { time: SystemTime, } impl Stamp { + /// Creates a timestamp holding the last-modified time of the specified file. fn from_path(path: &Path) -> Self { let mut stamp = Stamp { time: SystemTime::UNIX_EPOCH }; stamp.add_path(path); stamp } + /// Updates this timestamp to the last-modified time of the specified file, + /// if it is later than the currently-stored timestamp. fn add_path(&mut self, path: &Path) { let modified = fs::metadata(path) .and_then(|metadata| metadata.modified()) @@ -871,6 +947,9 @@ impl Stamp { self.time = self.time.max(modified); } + /// Updates this timestamp to the most recent last-modified time of all files + /// recursively contained in the given directory, if it is later than the + /// currently-stored timestamp. fn add_dir(&mut self, path: &Path) { for entry in WalkDir::new(path) { let entry = entry.unwrap(); @@ -886,6 +965,7 @@ impl Stamp { } } +/// Creates a name for this test/revision that can be handed over to libtest. fn make_test_name( config: &Config, testpaths: &TestPaths, @@ -914,20 +994,41 @@ fn make_test_name( )) } +/// Creates a callback for this test/revision that libtest will call when it +/// decides to actually run the underlying test. fn make_test_closure( config: Arc, testpaths: &TestPaths, revision: Option<&str>, ) -> test::TestFn { - let config = config.clone(); let testpaths = testpaths.clone(); let revision = revision.map(str::to_owned); + + // This callback is the link between compiletest's test discovery code, + // and the parts of compiletest that know how to run an individual test. test::DynTestFn(Box::new(move || { runtest::run(config, &testpaths, revision.as_deref()); Ok(()) })) } +/// Checks that test discovery didn't find any tests whose name stem is a prefix +/// of some other tests's name. +/// +/// For example, suppose the test suite contains these two test files: +/// - `tests/rustdoc/primitive.rs` +/// - `tests/rustdoc/primitive/no_std.rs` +/// +/// The test runner might put the output from those tests in these directories: +/// - `$build/test/rustdoc/primitive/` +/// - `$build/test/rustdoc/primitive/no_std/` +/// +/// Because one output path is a subdirectory of the other, the two tests might +/// interfere with each other in unwanted ways, especially if the test runner +/// decides to delete test output directories to clean them between runs. +/// To avoid problems, we forbid test names from overlapping in this way. +/// +/// See for more context. fn check_overlapping_tests(found_paths: &HashSet) { let mut collisions = Vec::new(); for path in found_paths { From 9f42f9491dd291fcd57ee0646d98c3d31440fc15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= <39484203+jieyouxu@users.noreply.github.com> Date: Mon, 14 Oct 2024 19:33:40 +0800 Subject: [PATCH 276/357] triagebot: tag PRs affecting compiletest with `A-compiletest` --- triagebot.toml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/triagebot.toml b/triagebot.toml index 60ec1043aad..33dcbfa55a4 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -431,6 +431,11 @@ trigger_files = [ "src/tools/run-make-support" ] +[autolabel."A-compiletest"] +trigger_files = [ + "src/tools/compiletest" +] + [notify-zulip."I-prioritize"] zulip_stream = 245100 # #t-compiler/wg-prioritization/alerts topic = "#{number} {title}" From c6e1fbf8ebbbec0d7b2deee86a1bc67ec98e1541 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 14 Oct 2024 22:40:13 +1100 Subject: [PATCH 277/357] Fix up-to-date checking for run-make tests This special case in `output_base_dir` had the unfortunate side-effect of causing all run-make tests to share the same `stamp` file. So as soon as any one of them succeeded, all of the failed tests would be considered up-to-date and would no longer run in subsequent test invocations. --- src/tools/compiletest/src/common.rs | 10 ++-------- tests/run-make/README.md | 2 +- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index a5418ad8384..1ee00a3a4e8 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -759,14 +759,8 @@ pub fn output_testname_unique( /// test/revision should reside. Example: /// /path/to/build/host-triple/test/ui/relative/testname.revision.mode/ pub fn output_base_dir(config: &Config, testpaths: &TestPaths, revision: Option<&str>) -> PathBuf { - // In run-make tests, constructing a relative path + unique testname causes a double layering - // since revisions are not supported, causing unnecessary nesting. - if config.mode == Mode::RunMake { - output_relative_path(config, &testpaths.relative_dir) - } else { - output_relative_path(config, &testpaths.relative_dir) - .join(output_testname_unique(config, testpaths, revision)) - } + output_relative_path(config, &testpaths.relative_dir) + .join(output_testname_unique(config, testpaths, revision)) } /// Absolute path to the base filename used as output for the given diff --git a/tests/run-make/README.md b/tests/run-make/README.md index 40359903473..9e1eaa881c9 100644 --- a/tests/run-make/README.md +++ b/tests/run-make/README.md @@ -29,7 +29,7 @@ The setup for the `rmake.rs` version is a 3-stage process: structure within `build//test/run-make/` ``` - / + // rmake.exe # recipe binary rmake_out/ # sources from test sources copied over ``` From 7500e09b8baa6d21c85a699ef359c8c4e6175629 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 13 Oct 2024 09:16:03 -0400 Subject: [PATCH 278/357] Move trait bound modifiers into hir::PolyTraitRef --- compiler/rustc_ast_lowering/src/lib.rs | 43 +++++++++---------- .../src/diagnostics/region_errors.rs | 4 +- .../src/diagnostics/region_name.rs | 2 +- compiler/rustc_hir/src/hir.rs | 15 ++++--- compiler/rustc_hir/src/intravisit.rs | 4 +- .../rustc_hir_analysis/src/check/wfcheck.rs | 2 +- .../src/collect/predicates_of.rs | 2 +- .../src/collect/resolve_bound_vars.rs | 4 +- .../src/hir_ty_lowering/bounds.rs | 8 ++-- .../src/hir_ty_lowering/dyn_compatibility.rs | 9 ++-- .../src/hir_ty_lowering/errors.rs | 8 ++-- .../src/hir_ty_lowering/lint.rs | 4 +- compiler/rustc_hir_pretty/src/lib.rs | 14 +++--- .../src/fn_ctxt/suggestions.rs | 4 +- compiler/rustc_lint/src/traits.rs | 5 ++- compiler/rustc_middle/src/ty/diagnostics.rs | 3 +- .../infer/nice_region_error/find_anon_type.rs | 2 +- .../nice_region_error/static_impl_trait.rs | 2 +- .../error_reporting/infer/note_and_explain.rs | 4 +- .../src/error_reporting/infer/suggest.rs | 5 ++- .../src/error_reporting/traits/mod.rs | 2 +- .../src/error_reporting/traits/suggestions.rs | 6 +-- .../src/traits/dyn_compatibility.rs | 2 +- src/librustdoc/clean/mod.rs | 8 ++-- .../src/implied_bounds_in_impls.rs | 6 ++- src/tools/clippy/clippy_lints/src/len_zero.rs | 2 +- .../clippy/clippy_lints/src/lifetimes.rs | 4 +- .../clippy_lints/src/manual_async_fn.rs | 2 +- .../clippy_lints/src/needless_maybe_sized.rs | 8 ++-- .../clippy/clippy_lints/src/trait_bounds.rs | 15 ++++--- .../clippy_lints/src/types/borrowed_box.rs | 2 +- .../clippy_lints/src/types/type_complexity.rs | 1 - 32 files changed, 102 insertions(+), 100 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 365924ef782..b19ccc59a71 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1225,7 +1225,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { itctx, TraitBoundModifiers::NONE, ); - let bound = (bound, hir::TraitBoundModifier::None); let bounds = this.arena.alloc_from_iter([bound]); let lifetime_bound = this.elided_dyn_bound(t.span); (bounds, lifetime_bound) @@ -1328,8 +1327,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // const trait bounds in trait object types. GenericBound::Trait(ty, modifiers) => { let trait_ref = this.lower_poly_trait_ref(ty, itctx, *modifiers); - let polarity = this.lower_trait_bound_modifiers(*modifiers); - Some((trait_ref, polarity)) + Some(trait_ref) } GenericBound::Outlives(lifetime) => { if lifetime_bound.is_none() { @@ -1958,21 +1956,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { span_ext: DUMMY_SP, }); - hir::GenericBound::Trait( - hir::PolyTraitRef { - bound_generic_params: &[], - trait_ref: hir::TraitRef { - path: self.make_lang_item_path( - trait_lang_item, - opaque_ty_span, - Some(bound_args), - ), - hir_ref_id: self.next_id(), - }, - span: opaque_ty_span, + hir::GenericBound::Trait(hir::PolyTraitRef { + bound_generic_params: &[], + modifiers: hir::TraitBoundModifier::None, + trait_ref: hir::TraitRef { + path: self.make_lang_item_path(trait_lang_item, opaque_ty_span, Some(bound_args)), + hir_ref_id: self.next_id(), }, - hir::TraitBoundModifier::None, - ) + span: opaque_ty_span, + }) } #[instrument(level = "trace", skip(self))] @@ -1982,10 +1974,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { itctx: ImplTraitContext, ) -> hir::GenericBound<'hir> { match tpb { - GenericBound::Trait(p, modifiers) => hir::GenericBound::Trait( - self.lower_poly_trait_ref(p, itctx, *modifiers), - self.lower_trait_bound_modifiers(*modifiers), - ), + GenericBound::Trait(p, modifiers) => { + hir::GenericBound::Trait(self.lower_poly_trait_ref(p, itctx, *modifiers)) + } GenericBound::Outlives(lifetime) => { hir::GenericBound::Outlives(self.lower_lifetime(lifetime)) } @@ -2194,7 +2185,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let bound_generic_params = self.lower_lifetime_binder(p.trait_ref.ref_id, &p.bound_generic_params); let trait_ref = self.lower_trait_ref(modifiers, &p.trait_ref, itctx); - hir::PolyTraitRef { bound_generic_params, trait_ref, span: self.lower_span(p.span) } + let modifiers = self.lower_trait_bound_modifiers(modifiers); + hir::PolyTraitRef { + bound_generic_params, + modifiers, + trait_ref, + span: self.lower_span(p.span), + } } fn lower_mt(&mut self, mt: &MutTy, itctx: ImplTraitContext) -> hir::MutTy<'hir> { @@ -2634,10 +2631,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { Res::Def(DefKind::Trait | DefKind::TraitAlias, _) => { let principal = hir::PolyTraitRef { bound_generic_params: &[], + modifiers: hir::TraitBoundModifier::None, trait_ref: hir::TraitRef { path, hir_ref_id: hir_id }, span: self.lower_span(span), }; - let principal = (principal, hir::TraitBoundModifier::None); // The original ID is taken by the `PolyTraitRef`, // so the `Ty` itself needs a different one. diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 39175b406a4..6333d59a1bc 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -254,7 +254,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { debug!(?hrtb_bounds); hrtb_bounds.iter().for_each(|bound| { - let Trait(PolyTraitRef { trait_ref, span: trait_span, .. }, _) = bound else { + let Trait(PolyTraitRef { trait_ref, span: trait_span, .. }) = bound else { return; }; diag.span_note(*trait_span, fluent::borrowck_limitations_implies_static); @@ -277,7 +277,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { return; }; bounds.iter().for_each(|bd| { - if let Trait(PolyTraitRef { trait_ref: tr_ref, .. }, _) = bd + if let Trait(PolyTraitRef { trait_ref: tr_ref, .. }) = bd && let Def(_, res_defid) = tr_ref.path.res && res_defid == trait_res_defid // trait id matches && let TyKind::Path(Resolved(_, path)) = bounded_ty.kind diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index 1a5f9bdb154..b4b8373ac97 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -837,7 +837,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { hir_ty ); }; - if let hir::OpaqueTy { bounds: [hir::GenericBound::Trait(trait_ref, _)], .. } = opaque_ty + if let hir::OpaqueTy { bounds: [hir::GenericBound::Trait(trait_ref)], .. } = opaque_ty && let Some(segment) = trait_ref.trait_ref.path.segments.last() && let Some(args) = segment.args && let [constraint] = args.constraints diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 2ef6fa53f4e..1e9cbba94c7 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -520,7 +520,7 @@ pub enum TraitBoundModifier { #[derive(Clone, Copy, Debug, HashStable_Generic)] pub enum GenericBound<'hir> { - Trait(PolyTraitRef<'hir>, TraitBoundModifier), + Trait(PolyTraitRef<'hir>), Outlives(&'hir Lifetime), Use(&'hir [PreciseCapturingArg<'hir>], Span), } @@ -528,7 +528,7 @@ pub enum GenericBound<'hir> { impl GenericBound<'_> { pub fn trait_ref(&self) -> Option<&TraitRef<'_>> { match self { - GenericBound::Trait(data, _) => Some(&data.trait_ref), + GenericBound::Trait(data) => Some(&data.trait_ref), _ => None, } } @@ -2874,11 +2874,7 @@ pub enum TyKind<'hir> { OpaqueDef(&'hir OpaqueTy<'hir>, &'hir [GenericArg<'hir>]), /// A trait object type `Bound1 + Bound2 + Bound3` /// where `Bound` is a trait or a lifetime. - TraitObject( - &'hir [(PolyTraitRef<'hir>, TraitBoundModifier)], - &'hir Lifetime, - TraitObjectSyntax, - ), + TraitObject(&'hir [PolyTraitRef<'hir>], &'hir Lifetime, TraitObjectSyntax), /// Unused for now. Typeof(&'hir AnonConst), /// `TyKind::Infer` means the type should be inferred instead of it having been @@ -3182,6 +3178,11 @@ pub struct PolyTraitRef<'hir> { /// The `'a` in `for<'a> Foo<&'a T>`. pub bound_generic_params: &'hir [GenericParam<'hir>], + /// The constness and polarity of the trait ref. + /// + /// The `async` modifier is lowered directly into a different trait for now. + pub modifiers: TraitBoundModifier, + /// The `Foo<&'a T>` in `for<'a> Foo<&'a T>`. pub trait_ref: TraitRef<'hir>, diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 58916d05865..ffe519b0e7d 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -905,7 +905,7 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) -> V::Resul try_visit!(visitor.visit_array_length(length)); } TyKind::TraitObject(bounds, ref lifetime, _syntax) => { - for (bound, _modifier) in bounds { + for bound in bounds { try_visit!(visitor.visit_poly_trait_ref(bound)); } try_visit!(visitor.visit_lifetime(lifetime)); @@ -1160,7 +1160,7 @@ pub fn walk_param_bound<'v, V: Visitor<'v>>( bound: &'v GenericBound<'v>, ) -> V::Result { match *bound { - GenericBound::Trait(ref typ, _modifier) => visitor.visit_poly_trait_ref(typ), + GenericBound::Trait(ref typ) => visitor.visit_poly_trait_ref(typ), GenericBound::Outlives(ref lifetime) => visitor.visit_lifetime(lifetime), GenericBound::Use(args, _) => { walk_list!(visitor, visit_precise_capturing_arg, args); diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 3a9d2640eee..1d78ea0c919 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -832,7 +832,7 @@ impl<'tcx> TypeVisitor> for GATArgsCollector<'tcx> { fn could_be_self(trait_def_id: LocalDefId, ty: &hir::Ty<'_>) -> bool { match ty.kind { - hir::TyKind::TraitObject([(trait_ref, _)], ..) => match trait_ref.trait_ref.path.segments { + hir::TyKind::TraitObject([trait_ref], ..) => match trait_ref.trait_ref.path.segments { [s] => s.res.opt_def_id() == Some(trait_def_id.to_def_id()), _ => false, }, diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 6d30f7c7b9d..a87b29b3093 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -866,7 +866,7 @@ impl<'tcx> ItemCtxt<'tcx> { #[instrument(level = "trace", skip(self))] fn bound_defines_assoc_item(&self, b: &hir::GenericBound<'_>, assoc_name: Ident) -> bool { match b { - hir::GenericBound::Trait(poly_trait_ref, _) => { + hir::GenericBound::Trait(poly_trait_ref) => { let trait_ref = &poly_trait_ref.trait_ref; if let Some(trait_did) = trait_ref.trait_def_id() { self.tcx.trait_may_define_assoc_item(trait_did, assoc_name) diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index c8852a3a369..cb7f0901c7e 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -644,7 +644,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { debug!(?bounds, ?lifetime, "TraitObject"); let scope = Scope::TraitRefBoundary { s: self.scope }; self.with(scope, |this| { - for (bound, _) in bounds { + for bound in bounds { this.visit_poly_trait_ref_inner( bound, NonLifetimeBinderAllowed::Deny("trait object types"), @@ -1918,7 +1918,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { return None; } predicate.bounds.iter().find_map(|bound| { - let hir::GenericBound::Trait(trait_, _) = bound else { + let hir::GenericBound::Trait(trait_) = bound else { return None; }; BoundVarContext::supertrait_hrtb_vars( diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index 45cd46e3df2..8f7ca089c91 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -44,10 +44,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let mut unbounds: SmallVec<[_; 1]> = SmallVec::new(); let mut search_bounds = |hir_bounds: &'tcx [hir::GenericBound<'tcx>]| { for hir_bound in hir_bounds { - let hir::GenericBound::Trait(ptr, modifier) = hir_bound else { + let hir::GenericBound::Trait(ptr) = hir_bound else { continue; }; - match modifier { + match ptr.modifiers { hir::TraitBoundModifier::Maybe => unbounds.push(ptr), hir::TraitBoundModifier::Negative => { if let Some(sized_def_id) = sized_def_id @@ -156,8 +156,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { { for hir_bound in hir_bounds { match hir_bound { - hir::GenericBound::Trait(poly_trait_ref, modifier) => { - let (constness, polarity) = match modifier { + hir::GenericBound::Trait(poly_trait_ref) => { + let (constness, polarity) = match poly_trait_ref.modifiers { hir::TraitBoundModifier::Const => { (ty::BoundConstness::Const, ty::PredicatePolarity::Positive) } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs index 394a263fbb5..98822eec2ac 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs @@ -30,7 +30,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { &self, span: Span, hir_id: hir::HirId, - hir_trait_bounds: &[(hir::PolyTraitRef<'tcx>, hir::TraitBoundModifier)], + hir_trait_bounds: &[hir::PolyTraitRef<'tcx>], lifetime: &hir::Lifetime, representation: DynKind, ) -> Ty<'tcx> { @@ -39,8 +39,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let mut bounds = Bounds::default(); let mut potential_assoc_types = Vec::new(); let dummy_self = self.tcx().types.trait_object_dummy_self; - for (trait_bound, modifier) in hir_trait_bounds.iter().rev() { - if *modifier == hir::TraitBoundModifier::Maybe { + for trait_bound in hir_trait_bounds.iter().rev() { + // FIXME: This doesn't handle `? const`. + if trait_bound.modifiers == hir::TraitBoundModifier::Maybe { continue; } if let GenericArgCountResult { @@ -263,7 +264,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let args = tcx.mk_args(&args); let span = i.bottom().1; - let empty_generic_args = hir_trait_bounds.iter().any(|(hir_bound, _)| { + let empty_generic_args = hir_trait_bounds.iter().any(|hir_bound| { hir_bound.trait_ref.path.res == Res::Def(DefKind::Trait, trait_ref.def_id) && hir_bound.span.contains(span) }); diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs index a735b8cc2a4..01768c89cca 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -718,7 +718,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { &self, associated_types: FxIndexMap>, potential_assoc_types: Vec, - trait_bounds: &[(hir::PolyTraitRef<'_>, hir::TraitBoundModifier)], + trait_bounds: &[hir::PolyTraitRef<'_>], ) { if associated_types.values().all(|v| v.is_empty()) { return; @@ -764,12 +764,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // related to issue #91997, turbofishes added only when in an expr or pat let mut in_expr_or_pat = false; if let ([], [bound]) = (&potential_assoc_types[..], &trait_bounds) { - let grandparent = tcx.parent_hir_node(tcx.parent_hir_id(bound.0.trait_ref.hir_ref_id)); + let grandparent = tcx.parent_hir_node(tcx.parent_hir_id(bound.trait_ref.hir_ref_id)); in_expr_or_pat = match grandparent { hir::Node::Expr(_) | hir::Node::Pat(_) => true, _ => false, }; - match bound.0.trait_ref.path.segments { + match bound.trait_ref.path.segments { // FIXME: `trait_ref.path.span` can point to a full path with multiple // segments, even though `trait_ref.path.segments` is of length `1`. Work // around that bug here, even though it should be fixed elsewhere. @@ -810,7 +810,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // and we can then use their span to indicate this to the user. let bound_names = trait_bounds .iter() - .filter_map(|(poly_trait_ref, _)| { + .filter_map(|poly_trait_ref| { let path = poly_trait_ref.trait_ref.path.segments.last()?; let args = path.args?; diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs index 11c0450bfe2..fd49e7e4439 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs @@ -50,7 +50,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .ok() .is_some_and(|s| s.trim_end().ends_with('<')); - let is_global = poly_trait_ref.0.trait_ref.path.is_global(); + let is_global = poly_trait_ref.trait_ref.path.is_global(); let mut sugg = vec![( self_ty.span.shrink_to_lo(), @@ -211,7 +211,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // Check if trait object is safe for suggesting dynamic dispatch. let is_dyn_compatible = match self_ty.kind { hir::TyKind::TraitObject(objects, ..) => { - objects.iter().all(|(o, _)| match o.trait_ref.path.res { + objects.iter().all(|o| match o.trait_ref.path.res { Res::Def(DefKind::Trait, id) => tcx.is_dyn_compatible(id), _ => false, }) diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 9fe6a8ee342..9ebfd4f15ab 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -301,16 +301,13 @@ impl<'a> State<'a> { self.word_space("dyn"); } let mut first = true; - for (bound, modifier) in bounds { + for bound in bounds { if first { first = false; } else { self.nbsp(); self.word_space("+"); } - if *modifier == TraitBoundModifier::Maybe { - self.word("?"); - } self.print_poly_trait_ref(bound); } if !lifetime.is_elided() { @@ -679,6 +676,10 @@ impl<'a> State<'a> { } fn print_poly_trait_ref(&mut self, t: &hir::PolyTraitRef<'_>) { + // FIXME: This isn't correct! + if t.modifiers == TraitBoundModifier::Maybe { + self.word("?"); + } self.print_formal_generic_params(t.bound_generic_params); self.print_trait_ref(&t.trait_ref); } @@ -2077,10 +2078,7 @@ impl<'a> State<'a> { } match bound { - GenericBound::Trait(tref, modifier) => { - if modifier == &TraitBoundModifier::Maybe { - self.word("?"); - } + GenericBound::Trait(tref) => { self.print_poly_trait_ref(tref); } GenericBound::Outlives(lt) => { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 1df4d32f3cb..3e9e5326156 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -849,7 +849,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { hir::FnRetTy::Return(hir_ty) => { if let hir::TyKind::OpaqueDef(op_ty, ..) = hir_ty.kind // FIXME: account for RPITIT. - && let [hir::GenericBound::Trait(trait_ref, _)] = op_ty.bounds + && let [hir::GenericBound::Trait(trait_ref)] = op_ty.bounds && let Some(hir::PathSegment { args: Some(generic_args), .. }) = trait_ref.trait_ref.path.segments.last() && let [constraint] = generic_args.constraints @@ -1035,7 +1035,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // extract all bounds from the source code using their spans let all_matching_bounds_strs = predicates_from_where .filter_map(|bound| match bound { - GenericBound::Trait(_, _) => { + GenericBound::Trait(_) => { self.tcx.sess.source_map().span_to_snippet(bound.span()).ok() } _ => None, diff --git a/compiler/rustc_lint/src/traits.rs b/compiler/rustc_lint/src/traits.rs index c0a01b0065e..5a3666dcbd4 100644 --- a/compiler/rustc_lint/src/traits.rs +++ b/compiler/rustc_lint/src/traits.rs @@ -112,10 +112,11 @@ impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints { fn check_ty(&mut self, cx: &LateContext<'_>, ty: &'tcx hir::Ty<'tcx>) { let hir::TyKind::TraitObject(bounds, _lifetime, _syntax) = &ty.kind else { return }; - for (bound, modifier) in &bounds[..] { + for bound in &bounds[..] { let def_id = bound.trait_ref.trait_def_id(); if def_id.is_some_and(|def_id| cx.tcx.is_lang_item(def_id, LangItem::Drop)) - && *modifier != hir::TraitBoundModifier::Maybe + // FIXME: ?Drop is not a thing. + && bound.modifiers != hir::TraitBoundModifier::Maybe { let Some(def_id) = cx.tcx.get_diagnostic_item(sym::needs_drop) else { return }; cx.emit_span_lint(DYN_DROP, bound.span, DropGlue { tcx: cx.tcx, def_id }); diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index 354ca746b46..4f408ee1574 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -192,7 +192,8 @@ fn suggest_changing_unsized_bound( .iter() .enumerate() .filter(|(_, bound)| { - if let hir::GenericBound::Trait(poly, hir::TraitBoundModifier::Maybe) = bound + if let hir::GenericBound::Trait(poly) = bound + && poly.modifiers == hir::TraitBoundModifier::Maybe && poly.trait_ref.trait_def_id() == def_id { true diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs index 7a44c2ad661..2ecd28f4868 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs @@ -86,7 +86,7 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> { } hir::TyKind::TraitObject(bounds, ..) => { - for (bound, _) in bounds { + for bound in bounds { self.current_index.shift_in(1); self.visit_poly_trait_ref(bound); self.current_index.shift_out(1); diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs index a6ecd1cc987..8541621b23b 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs @@ -599,7 +599,7 @@ impl<'a, 'tcx> Visitor<'tcx> for HirTraitObjectVisitor<'a> { _, ) = t.kind { - for (ptr, _) in poly_trait_refs { + for ptr in poly_trait_refs { if Some(self.1) == ptr.trait_ref.trait_def_id() { self.0.push(ptr.span); } diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs index cf0ab630f2e..62204f63dd0 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs @@ -894,7 +894,9 @@ fn foo(&self) -> Self::T { String::new() } // FIXME: we would want to call `resolve_vars_if_possible` on `ty` before suggesting. let trait_bounds = bounds.iter().filter_map(|bound| match bound { - hir::GenericBound::Trait(ptr, hir::TraitBoundModifier::None) => Some(ptr), + hir::GenericBound::Trait(ptr) if ptr.modifiers == hir::TraitBoundModifier::None => { + Some(ptr) + } _ => None, }); diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs index 709b6eb18e3..fc2d0ba36f0 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs @@ -740,9 +740,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { ) if std::iter::zip(*last_bounds, *exp_bounds).all(|(left, right)| match ( left, right, ) { - (hir::GenericBound::Trait(tl, ml), hir::GenericBound::Trait(tr, mr)) + // FIXME: Suspicious + (hir::GenericBound::Trait(tl), hir::GenericBound::Trait(tr)) if tl.trait_ref.trait_def_id() == tr.trait_ref.trait_def_id() - && ml == mr => + && tl.modifiers == tr.modifiers => { true } diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs index becc1acfb66..ba57909fc23 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs @@ -439,7 +439,7 @@ pub fn report_dyn_incompatibility<'tcx>( if tcx.parent_hir_node(hir_id).fn_sig().is_some() { // Do not suggest `impl Trait` when dealing with things like super-traits. err.span_suggestion_verbose( - ty.span.until(trait_ref.0.span), + ty.span.until(trait_ref.span), "consider using an opaque type instead", "impl ", Applicability::MaybeIncorrect, diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 87834c329e1..733baaa99e5 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -3074,11 +3074,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { match ty.kind { hir::TyKind::TraitObject(traits, _, _) => { let (span, kw) = match traits { - [(first, _), ..] if first.span.lo() == ty.span.lo() => { + [first, ..] if first.span.lo() == ty.span.lo() => { // Missing `dyn` in front of trait object. (ty.span.shrink_to_lo(), "dyn ") } - [(first, _), ..] => (ty.span.until(first.span), ""), + [first, ..] => (ty.span.until(first.span), ""), [] => span_bug!(ty.span, "trait object with no traits: {ty:?}"), }; let needs_parens = traits.len() != 1; @@ -5162,7 +5162,7 @@ pub fn suggest_desugaring_async_fn_to_impl_future_in_trait<'tcx>( let async_span = tcx.sess.source_map().span_extend_while_whitespace(async_span); let future = tcx.hir_node_by_def_id(opaque_def_id).expect_opaque_ty(); - let [hir::GenericBound::Trait(trait_ref, _)] = future.bounds else { + let [hir::GenericBound::Trait(trait_ref)] = future.bounds else { // `async fn` should always lower to a single bound... but don't ICE. return None; }; diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs index 45e7de942fb..364a13b3a75 100644 --- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs +++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs @@ -125,7 +125,7 @@ fn sized_trait_bound_spans<'tcx>( bounds: hir::GenericBounds<'tcx>, ) -> impl 'tcx + Iterator { bounds.iter().filter_map(move |b| match b { - hir::GenericBound::Trait(trait_ref, hir::TraitBoundModifier::None) + hir::GenericBound::Trait(trait_ref) if trait_has_sized_self( tcx, trait_ref.trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise()), diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index fa73733360c..1ddad917b78 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -214,15 +214,15 @@ fn clean_generic_bound<'tcx>( ) -> Option { Some(match *bound { hir::GenericBound::Outlives(lt) => GenericBound::Outlives(clean_lifetime(lt, cx)), - hir::GenericBound::Trait(ref t, modifier) => { + hir::GenericBound::Trait(ref t) => { // `T: ~const Destruct` is hidden because `T: Destruct` is a no-op. - if modifier == hir::TraitBoundModifier::MaybeConst + if t.modifiers == hir::TraitBoundModifier::MaybeConst && cx.tcx.lang_items().destruct_trait() == Some(t.trait_ref.trait_def_id().unwrap()) { return None; } - GenericBound::TraitBound(clean_poly_trait_ref(t, cx), modifier) + GenericBound::TraitBound(clean_poly_trait_ref(t, cx), t.modifiers) } hir::GenericBound::Use(args, ..) => { GenericBound::Use(args.iter().map(|arg| arg.name()).collect()) @@ -1833,7 +1833,7 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T } TyKind::Path(_) => clean_qpath(ty, cx), TyKind::TraitObject(bounds, lifetime, _) => { - let bounds = bounds.iter().map(|(bound, _)| clean_poly_trait_ref(bound, cx)).collect(); + let bounds = bounds.iter().map(|bound| clean_poly_trait_ref(bound, cx)).collect(); let lifetime = if !lifetime.is_elided() { Some(clean_lifetime(lifetime, cx)) } else { None }; DynTrait(bounds, lifetime) diff --git a/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs b/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs index 5f349d78053..590d9afd1b4 100644 --- a/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs +++ b/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs @@ -242,7 +242,8 @@ fn collect_supertrait_bounds<'tcx>(cx: &LateContext<'tcx>, bounds: GenericBounds bounds .iter() .filter_map(|bound| { - if let GenericBound::Trait(poly_trait, TraitBoundModifier::None) = bound + if let GenericBound::Trait(poly_trait) = bound + && let TraitBoundModifier::None = poly_trait.modifiers && let [.., path] = poly_trait.trait_ref.path.segments && poly_trait.bound_generic_params.is_empty() && let Some(trait_def_id) = path.res.opt_def_id() @@ -307,7 +308,8 @@ fn check<'tcx>(cx: &LateContext<'tcx>, bounds: GenericBounds<'tcx>) { // This involves some extra logic when generic arguments are present, since // simply comparing trait `DefId`s won't be enough. We also need to compare the generics. for (index, bound) in bounds.iter().enumerate() { - if let GenericBound::Trait(poly_trait, TraitBoundModifier::None) = bound + if let GenericBound::Trait(poly_trait) = bound + && let TraitBoundModifier::None = poly_trait.modifiers && let [.., path] = poly_trait.trait_ref.path.segments && let implied_args = path.args.map_or([].as_slice(), |a| a.args) && let implied_constraints = path.args.map_or([].as_slice(), |a| a.constraints) diff --git a/src/tools/clippy/clippy_lints/src/len_zero.rs b/src/tools/clippy/clippy_lints/src/len_zero.rs index 311bbce14bd..035ee40348c 100644 --- a/src/tools/clippy/clippy_lints/src/len_zero.rs +++ b/src/tools/clippy/clippy_lints/src/len_zero.rs @@ -310,7 +310,7 @@ fn extract_future_output<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<& if let ty::Alias(_, alias_ty) = ty.kind() && let Some(Node::OpaqueTy(opaque)) = cx.tcx.hir().get_if_local(alias_ty.def_id) && let OpaqueTyOrigin::AsyncFn { .. } = opaque.origin - && let [GenericBound::Trait(trait_ref, _)] = &opaque.bounds + && let [GenericBound::Trait(trait_ref)] = &opaque.bounds && let Some(segment) = trait_ref.trait_ref.path.segments.last() && let Some(generic_args) = segment.args && let [constraint] = generic_args.constraints diff --git a/src/tools/clippy/clippy_lints/src/lifetimes.rs b/src/tools/clippy/clippy_lints/src/lifetimes.rs index ec28671a061..a7c48eb216a 100644 --- a/src/tools/clippy/clippy_lints/src/lifetimes.rs +++ b/src/tools/clippy/clippy_lints/src/lifetimes.rs @@ -163,7 +163,7 @@ fn check_fn_inner<'tcx>( if visitor.lts.iter().any(|lt| matches!(lt.res, LifetimeName::Param(_))) { return; } - if let GenericBound::Trait(ref trait_ref, _) = *bound { + if let GenericBound::Trait(ref trait_ref) = *bound { let params = &trait_ref .trait_ref .path @@ -438,7 +438,7 @@ impl<'tcx> Visitor<'tcx> for RefVisitor<'_, 'tcx> { if !lt.is_elided() { self.unelided_trait_object_lifetime = true; } - for (bound, _) in bounds { + for bound in bounds { self.visit_poly_trait_ref(bound); } }, diff --git a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs index 81115cffdca..67255c1af79 100644 --- a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs +++ b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs @@ -107,7 +107,7 @@ fn future_trait_ref<'tcx>( ) -> Option<(&'tcx TraitRef<'tcx>, Vec)> { if let TyKind::OpaqueDef(opaque, bounds) = ty.kind && let Some(trait_ref) = opaque.bounds.iter().find_map(|bound| { - if let GenericBound::Trait(poly, _) = bound { + if let GenericBound::Trait(poly) = bound { Some(&poly.trait_ref) } else { None diff --git a/src/tools/clippy/clippy_lints/src/needless_maybe_sized.rs b/src/tools/clippy/clippy_lints/src/needless_maybe_sized.rs index bb44ff37b20..a56024f08d5 100644 --- a/src/tools/clippy/clippy_lints/src/needless_maybe_sized.rs +++ b/src/tools/clippy/clippy_lints/src/needless_maybe_sized.rs @@ -40,7 +40,6 @@ struct Bound<'tcx> { ident: Ident, trait_bound: &'tcx PolyTraitRef<'tcx>, - modifier: TraitBoundModifier, predicate_pos: usize, bound_pos: usize, @@ -65,11 +64,10 @@ fn type_param_bounds<'tcx>(generics: &'tcx Generics<'tcx>) -> impl Iterator Some(Bound { + &GenericBound::Trait(ref trait_bound) => Some(Bound { param, ident, trait_bound, - modifier, predicate_pos, bound_pos, }), @@ -120,13 +118,13 @@ impl LateLintPass<'_> for NeedlessMaybeSized { let maybe_sized_params: DefIdMap<_> = type_param_bounds(generics) .filter(|bound| { bound.trait_bound.trait_ref.trait_def_id() == Some(sized_trait) - && bound.modifier == TraitBoundModifier::Maybe + && bound.trait_bound.modifiers == TraitBoundModifier::Maybe }) .map(|bound| (bound.param, bound)) .collect(); for bound in type_param_bounds(generics) { - if bound.modifier == TraitBoundModifier::None + if bound.trait_bound.modifiers == TraitBoundModifier::None && let Some(sized_bound) = maybe_sized_params.get(&bound.param) && let Some(path) = path_to_sized_bound(cx, bound.trait_bound) { diff --git a/src/tools/clippy/clippy_lints/src/trait_bounds.rs b/src/tools/clippy/clippy_lints/src/trait_bounds.rs index 3c3973857e7..38befdee574 100644 --- a/src/tools/clippy/clippy_lints/src/trait_bounds.rs +++ b/src/tools/clippy/clippy_lints/src/trait_bounds.rs @@ -182,7 +182,7 @@ impl<'tcx> LateLintPass<'tcx> for TraitBounds { // Iterate the bounds and add them to our seen hash // If we haven't yet seen it, add it to the fixed traits - for (bound, _) in bounds { + for bound in bounds { let Some(def_id) = bound.trait_ref.trait_def_id() else { continue; }; @@ -197,9 +197,9 @@ impl<'tcx> LateLintPass<'tcx> for TraitBounds { // If the number of unique traits isn't the same as the number of traits in the bounds, // there must be 1 or more duplicates if bounds.len() != unique_traits.len() { - let mut bounds_span = bounds[0].0.span; + let mut bounds_span = bounds[0].span; - for (bound, _) in bounds.iter().skip(1) { + for bound in bounds.iter().skip(1) { bounds_span = bounds_span.to(bound.span); } @@ -229,7 +229,8 @@ impl TraitBounds { /// this MSRV? See for details. fn cannot_combine_maybe_bound(&self, cx: &LateContext<'_>, bound: &GenericBound<'_>) -> bool { if !self.msrv.meets(msrvs::MAYBE_BOUND_IN_WHERE) - && let GenericBound::Trait(tr, TraitBoundModifier::Maybe) = bound + && let GenericBound::Trait(tr) = bound + && let TraitBoundModifier::Maybe = tr.modifiers { cx.tcx.lang_items().get(LangItem::Sized) == tr.trait_ref.path.res.opt_def_id() } else { @@ -375,11 +376,11 @@ impl Default for ComparableTraitRef { } fn get_trait_info_from_bound<'a>(bound: &'a GenericBound<'_>) -> Option<(Res, &'a [PathSegment<'a>], Span)> { - if let GenericBound::Trait(t, tbm) = bound { + if let GenericBound::Trait(t) = bound { let trait_path = t.trait_ref.path; let trait_span = { let path_span = trait_path.span; - if let TraitBoundModifier::Maybe = tbm { + if let TraitBoundModifier::Maybe = t.modifiers { path_span.with_lo(path_span.lo() - BytePos(1)) // include the `?` } else { path_span @@ -430,7 +431,7 @@ fn rollup_traits( let mut repeated_res = false; let only_comparable_trait_refs = |bound: &GenericBound<'_>| { - if let GenericBound::Trait(t, _) = bound { + if let GenericBound::Trait(t) = bound { Some((into_comparable_trait_ref(&t.trait_ref), t.span)) } else { None diff --git a/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs b/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs index 2fcfc71a8c7..eb7ffbbe360 100644 --- a/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs +++ b/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs @@ -82,7 +82,7 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, lt: &Lifetime, m // Returns true if given type is `Any` trait. fn is_any_trait(cx: &LateContext<'_>, t: &hir::Ty<'_>) -> bool { if let TyKind::TraitObject(traits, ..) = t.kind { - return traits.iter().any(|(bound, _)| { + return traits.iter().any(|bound| { if let Some(trait_did) = bound.trait_ref.trait_def_id() && cx.tcx.is_diagnostic_item(sym::Any, trait_did) { diff --git a/src/tools/clippy/clippy_lints/src/types/type_complexity.rs b/src/tools/clippy/clippy_lints/src/types/type_complexity.rs index 0b64fddb447..b89bd6a8d05 100644 --- a/src/tools/clippy/clippy_lints/src/types/type_complexity.rs +++ b/src/tools/clippy/clippy_lints/src/types/type_complexity.rs @@ -55,7 +55,6 @@ impl<'tcx> Visitor<'tcx> for TypeComplexityVisitor { TyKind::TraitObject(param_bounds, _, _) => { let has_lifetime_parameters = param_bounds.iter().any(|bound| { bound - .0 .bound_generic_params .iter() .any(|param| matches!(param.kind, GenericParamKind::Lifetime { .. })) From 95dba280b9e471fc2dce93195d3b6f4aeb31279c Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 13 Oct 2024 09:31:22 -0400 Subject: [PATCH 279/357] Move trait bound modifiers into ast::PolyTraitRef --- compiler/rustc_ast/src/ast.rs | 21 ++++++-- compiler/rustc_ast/src/mut_visit.rs | 4 +- compiler/rustc_ast/src/util/classify.rs | 2 +- compiler/rustc_ast/src/visit.rs | 4 +- compiler/rustc_ast_lowering/src/item.rs | 4 +- compiler/rustc_ast_lowering/src/lib.rs | 15 +++--- .../rustc_ast_passes/src/ast_validation.rs | 16 ++++--- compiler/rustc_ast_pretty/src/pprust/state.rs | 48 +++++++++---------- .../src/deriving/smart_ptr.rs | 10 ++-- compiler/rustc_expand/src/build.rs | 21 ++++---- .../rustc_parse/src/parser/diagnostics.rs | 2 +- compiler/rustc_parse/src/parser/path.rs | 4 +- compiler/rustc_parse/src/parser/ty.rs | 14 ++++-- .../rustc_resolve/src/late/diagnostics.rs | 37 +++++++------- .../clippy/clippy_utils/src/ast_utils.rs | 5 +- src/tools/rustfmt/src/spanned.rs | 2 +- src/tools/rustfmt/src/types.rs | 12 ++--- 17 files changed, 118 insertions(+), 103 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 937031324f5..883391a2b60 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -308,7 +308,7 @@ impl TraitBoundModifiers { #[derive(Clone, Encodable, Decodable, Debug)] pub enum GenericBound { - Trait(PolyTraitRef, TraitBoundModifiers), + Trait(PolyTraitRef), Outlives(Lifetime), /// Precise capturing syntax: `impl Sized + use<'a>` Use(ThinVec, Span), @@ -1213,10 +1213,12 @@ impl Expr { pub fn to_bound(&self) -> Option { match &self.kind { - ExprKind::Path(None, path) => Some(GenericBound::Trait( - PolyTraitRef::new(ThinVec::new(), path.clone(), self.span), + ExprKind::Path(None, path) => Some(GenericBound::Trait(PolyTraitRef::new( + ThinVec::new(), + path.clone(), TraitBoundModifiers::NONE, - )), + self.span, + ))), _ => None, } } @@ -2965,6 +2967,9 @@ pub struct PolyTraitRef { /// The `'a` in `for<'a> Foo<&'a T>`. pub bound_generic_params: ThinVec, + // Optional constness, asyncness, or polarity. + pub modifiers: TraitBoundModifiers, + /// The `Foo<&'a T>` in `<'a> Foo<&'a T>`. pub trait_ref: TraitRef, @@ -2972,9 +2977,15 @@ pub struct PolyTraitRef { } impl PolyTraitRef { - pub fn new(generic_params: ThinVec, path: Path, span: Span) -> Self { + pub fn new( + generic_params: ThinVec, + path: Path, + modifiers: TraitBoundModifiers, + span: Span, + ) -> Self { PolyTraitRef { bound_generic_params: generic_params, + modifiers, trait_ref: TraitRef { path, ref_id: DUMMY_NODE_ID }, span, } diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 1a7da46913d..b03c8aaa53b 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -913,7 +913,7 @@ fn walk_fn_ret_ty(vis: &mut T, fn_ret_ty: &mut FnRetTy) { fn walk_param_bound(vis: &mut T, pb: &mut GenericBound) { match pb { - GenericBound::Trait(ty, _modifier) => vis.visit_poly_trait_ref(ty), + GenericBound::Trait(trait_ref) => vis.visit_poly_trait_ref(trait_ref), GenericBound::Outlives(lifetime) => walk_lifetime(vis, lifetime), GenericBound::Use(args, span) => { for arg in args { @@ -1034,7 +1034,7 @@ fn walk_trait_ref(vis: &mut T, TraitRef { path, ref_id }: &mut Tr } fn walk_poly_trait_ref(vis: &mut T, p: &mut PolyTraitRef) { - let PolyTraitRef { bound_generic_params, trait_ref, span } = p; + let PolyTraitRef { bound_generic_params, modifiers: _, trait_ref, span } = p; bound_generic_params.flat_map_in_place(|param| vis.flat_map_generic_param(param)); vis.visit_trait_ref(trait_ref); vis.visit_span(span); diff --git a/compiler/rustc_ast/src/util/classify.rs b/compiler/rustc_ast/src/util/classify.rs index a517f17c82c..695ebd168ee 100644 --- a/compiler/rustc_ast/src/util/classify.rs +++ b/compiler/rustc_ast/src/util/classify.rs @@ -263,7 +263,7 @@ fn type_trailing_braced_mac_call(mut ty: &ast::Ty) -> Option<&ast::MacCall> { ast::TyKind::TraitObject(bounds, _) | ast::TyKind::ImplTrait(_, bounds) => { match bounds.last() { - Some(ast::GenericBound::Trait(bound, _)) => { + Some(ast::GenericBound::Trait(bound)) => { match path_return_type(&bound.trait_ref.path) { Some(trailing_ty) => ty = trailing_ty, None => break None, diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 4dcadb8517e..6593d5dbb5c 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -329,7 +329,7 @@ pub fn walk_poly_trait_ref<'a, V>(visitor: &mut V, trait_ref: &'a PolyTraitRef) where V: Visitor<'a>, { - let PolyTraitRef { bound_generic_params, trait_ref, span: _ } = trait_ref; + let PolyTraitRef { bound_generic_params, modifiers: _, trait_ref, span: _ } = trait_ref; walk_list!(visitor, visit_generic_param, bound_generic_params); visitor.visit_trait_ref(trait_ref) } @@ -720,7 +720,7 @@ impl WalkItemKind for ForeignItemKind { pub fn walk_param_bound<'a, V: Visitor<'a>>(visitor: &mut V, bound: &'a GenericBound) -> V::Result { match bound { - GenericBound::Trait(typ, _modifier) => visitor.visit_poly_trait_ref(typ), + GenericBound::Trait(trait_ref) => visitor.visit_poly_trait_ref(trait_ref), GenericBound::Outlives(lifetime) => visitor.visit_lifetime(lifetime, LifetimeCtxt::Bound), GenericBound::Use(args, _span) => { walk_list!(visitor, visit_precise_capturing_arg, args); diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 1273b50dff8..ce744cc56e1 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1504,8 +1504,8 @@ impl<'hir> LoweringContext<'_, 'hir> { for bound in &bound_pred.bounds { if !matches!( *bound, - GenericBound::Trait(_, TraitBoundModifiers { - polarity: BoundPolarity::Maybe(_), + GenericBound::Trait(PolyTraitRef { + modifiers: TraitBoundModifiers { polarity: BoundPolarity::Maybe(_), .. }, .. }) ) { diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index b19ccc59a71..cc15a48ddc6 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1219,11 +1219,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let bound = this.lower_poly_trait_ref( &PolyTraitRef { bound_generic_params: ThinVec::new(), + modifiers: TraitBoundModifiers::NONE, trait_ref: TraitRef { path: path.clone(), ref_id: t.id }, span: t.span, }, itctx, - TraitBoundModifiers::NONE, ); let bounds = this.arena.alloc_from_iter([bound]); let lifetime_bound = this.elided_dyn_bound(t.span); @@ -1325,8 +1325,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // We can safely ignore constness here since AST validation // takes care of rejecting invalid modifier combinations and // const trait bounds in trait object types. - GenericBound::Trait(ty, modifiers) => { - let trait_ref = this.lower_poly_trait_ref(ty, itctx, *modifiers); + GenericBound::Trait(ty) => { + let trait_ref = this.lower_poly_trait_ref(ty, itctx); Some(trait_ref) } GenericBound::Outlives(lifetime) => { @@ -1974,9 +1974,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { itctx: ImplTraitContext, ) -> hir::GenericBound<'hir> { match tpb { - GenericBound::Trait(p, modifiers) => { - hir::GenericBound::Trait(self.lower_poly_trait_ref(p, itctx, *modifiers)) - } + GenericBound::Trait(p) => hir::GenericBound::Trait(self.lower_poly_trait_ref(p, itctx)), GenericBound::Outlives(lifetime) => { hir::GenericBound::Outlives(self.lower_lifetime(lifetime)) } @@ -2180,12 +2178,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &mut self, p: &PolyTraitRef, itctx: ImplTraitContext, - modifiers: ast::TraitBoundModifiers, ) -> hir::PolyTraitRef<'hir> { let bound_generic_params = self.lower_lifetime_binder(p.trait_ref.ref_id, &p.bound_generic_params); - let trait_ref = self.lower_trait_ref(modifiers, &p.trait_ref, itctx); - let modifiers = self.lower_trait_bound_modifiers(modifiers); + let trait_ref = self.lower_trait_ref(p.modifiers, &p.trait_ref, itctx); + let modifiers = self.lower_trait_bound_modifiers(p.modifiers); hir::PolyTraitRef { bound_generic_params, modifiers, diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 87e3a6871b9..40276a13eeb 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -1260,7 +1260,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { if !bound_pred.bound_generic_params.is_empty() { for bound in &bound_pred.bounds { match bound { - GenericBound::Trait(t, _) => { + GenericBound::Trait(t) => { if !t.bound_generic_params.is_empty() { self.dcx() .emit_err(errors::NestedLifetimes { span: t.span }); @@ -1280,8 +1280,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> { fn visit_param_bound(&mut self, bound: &'a GenericBound, ctxt: BoundKind) { match bound { - GenericBound::Trait(trait_ref, modifiers) => { - match (ctxt, modifiers.constness, modifiers.polarity) { + GenericBound::Trait(trait_ref) => { + match (ctxt, trait_ref.modifiers.constness, trait_ref.modifiers.polarity) { (BoundKind::SuperTraits, BoundConstness::Never, BoundPolarity::Maybe(_)) if !self.features.more_maybe_bounds => { @@ -1321,7 +1321,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } // Negative trait bounds are not allowed to have associated constraints - if let BoundPolarity::Negative(_) = modifiers.polarity + if let BoundPolarity::Negative(_) = trait_ref.modifiers.polarity && let Some(segment) = trait_ref.trait_ref.path.segments.last() { match segment.args.as_deref() { @@ -1669,7 +1669,9 @@ fn deny_equality_constraints( }), ) { for bound in bounds { - if let GenericBound::Trait(poly, TraitBoundModifiers::NONE) = bound { + if let GenericBound::Trait(poly) = bound + && poly.modifiers == TraitBoundModifiers::NONE + { if full_path.segments[..full_path.segments.len() - 1] .iter() .map(|segment| segment.ident.name) @@ -1697,7 +1699,9 @@ fn deny_equality_constraints( ) { if ident == potential_param.ident { for bound in bounds { - if let ast::GenericBound::Trait(poly, TraitBoundModifiers::NONE) = bound { + if let ast::GenericBound::Trait(poly) = bound + && poly.modifiers == TraitBoundModifiers::NONE + { suggest(poly, potential_assoc, predicate); } } diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index 44a5a2d0baf..f1f2784ad60 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -8,7 +8,6 @@ mod item; use std::borrow::Cow; -use ast::TraitBoundModifiers; use rustc_ast::attr::AttrIdGenerator; use rustc_ast::ptr::P; use rustc_ast::token::{ @@ -1253,6 +1252,27 @@ impl<'a> State<'a> { fn print_poly_trait_ref(&mut self, t: &ast::PolyTraitRef) { self.print_formal_generic_params(&t.bound_generic_params); + + let ast::TraitBoundModifiers { constness, asyncness, polarity } = t.modifiers; + match constness { + ast::BoundConstness::Never => {} + ast::BoundConstness::Always(_) | ast::BoundConstness::Maybe(_) => { + self.word_space(constness.as_str()); + } + } + match asyncness { + ast::BoundAsyncness::Normal => {} + ast::BoundAsyncness::Async(_) => { + self.word_space(asyncness.as_str()); + } + } + match polarity { + ast::BoundPolarity::Positive => {} + ast::BoundPolarity::Negative(_) | ast::BoundPolarity::Maybe(_) => { + self.word(polarity.as_str()); + } + } + self.print_trait_ref(&t.trait_ref) } @@ -1740,31 +1760,7 @@ impl<'a> State<'a> { } match bound { - GenericBound::Trait( - tref, - TraitBoundModifiers { constness, asyncness, polarity }, - ) => { - match constness { - ast::BoundConstness::Never => {} - ast::BoundConstness::Always(_) | ast::BoundConstness::Maybe(_) => { - self.word_space(constness.as_str()); - } - } - - match asyncness { - ast::BoundAsyncness::Normal => {} - ast::BoundAsyncness::Async(_) => { - self.word_space(asyncness.as_str()); - } - } - - match polarity { - ast::BoundPolarity::Positive => {} - ast::BoundPolarity::Negative(_) | ast::BoundPolarity::Maybe(_) => { - self.word(polarity.as_str()); - } - } - + GenericBound::Trait(tref) => { self.print_poly_trait_ref(tref); } GenericBound::Outlives(lt) => self.print_lifetime(*lt), diff --git a/compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs b/compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs index e3878d90e41..731945f5cbf 100644 --- a/compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs +++ b/compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs @@ -333,12 +333,12 @@ fn contains_maybe_sized_bound_on_pointee(predicates: &[WherePredicate], pointee: } fn is_maybe_sized_bound(bound: &GenericBound) -> bool { - if let GenericBound::Trait( - trait_ref, - TraitBoundModifiers { polarity: ast::BoundPolarity::Maybe(_), .. }, - ) = bound + if let GenericBound::Trait(trait_ref) = bound + && let TraitBoundModifiers { polarity: ast::BoundPolarity::Maybe(_), .. } = + trait_ref.modifiers + && is_sized_marker(&trait_ref.trait_ref.path) { - is_sized_marker(&trait_ref.trait_ref.path) + true } else { false } diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs index b5945759d43..2c1ee004e1d 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -143,24 +143,25 @@ impl<'a> ExtCtxt<'a> { ast::TraitRef { path, ref_id: ast::DUMMY_NODE_ID } } - pub fn poly_trait_ref(&self, span: Span, path: ast::Path) -> ast::PolyTraitRef { + pub fn poly_trait_ref(&self, span: Span, path: ast::Path, is_const: bool) -> ast::PolyTraitRef { ast::PolyTraitRef { bound_generic_params: ThinVec::new(), + modifiers: ast::TraitBoundModifiers { + polarity: ast::BoundPolarity::Positive, + constness: if is_const { + ast::BoundConstness::Maybe(DUMMY_SP) + } else { + ast::BoundConstness::Never + }, + asyncness: ast::BoundAsyncness::Normal, + }, trait_ref: self.trait_ref(path), span, } } pub fn trait_bound(&self, path: ast::Path, is_const: bool) -> ast::GenericBound { - ast::GenericBound::Trait(self.poly_trait_ref(path.span, path), ast::TraitBoundModifiers { - polarity: ast::BoundPolarity::Positive, - constness: if is_const { - ast::BoundConstness::Maybe(DUMMY_SP) - } else { - ast::BoundConstness::Never - }, - asyncness: ast::BoundAsyncness::Normal, - }) + ast::GenericBound::Trait(self.poly_trait_ref(path.span, path, is_const)) } pub fn lifetime(&self, span: Span, ident: Ident) -> ast::Lifetime { diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index f32307f6ed4..a9384501547 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -2113,7 +2113,7 @@ impl<'a> Parser<'a> { && let Some(poly) = bounds .iter() .filter_map(|bound| match bound { - ast::GenericBound::Trait(poly, _) => Some(poly), + ast::GenericBound::Trait(poly) => Some(poly), _ => None, }) .last() diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index 162ff3b94de..2f19a9b6b20 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -948,8 +948,8 @@ impl<'a> Parser<'a> { { return Ok((false, seg.ident, seg.args.as_deref().cloned())); } else if let ast::TyKind::TraitObject(bounds, ast::TraitObjectSyntax::None) = &ty.kind - && let [ast::GenericBound::Trait(trait_ref, ast::TraitBoundModifiers::NONE)] = - bounds.as_slice() + && let [ast::GenericBound::Trait(trait_ref)] = bounds.as_slice() + && trait_ref.modifiers == ast::TraitBoundModifiers::NONE && let [seg] = trait_ref.trait_ref.path.segments.as_slice() { return Ok((true, seg.ident, seg.args.as_deref().cloned())); diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 625a4cabdf2..6820ccaa18b 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -419,8 +419,13 @@ impl<'a> Parser<'a> { lo: Span, parse_plus: bool, ) -> PResult<'a, TyKind> { - let poly_trait_ref = PolyTraitRef::new(generic_params, path, lo.to(self.prev_token.span)); - let bounds = vec![GenericBound::Trait(poly_trait_ref, TraitBoundModifiers::NONE)]; + let poly_trait_ref = PolyTraitRef::new( + generic_params, + path, + TraitBoundModifiers::NONE, + lo.to(self.prev_token.span), + ); + let bounds = vec![GenericBound::Trait(poly_trait_ref)]; self.parse_remaining_bounds(bounds, parse_plus) } @@ -1085,8 +1090,9 @@ impl<'a> Parser<'a> { } } - let poly_trait = PolyTraitRef::new(lifetime_defs, path, lo.to(self.prev_token.span)); - Ok(GenericBound::Trait(poly_trait, modifiers)) + let poly_trait = + PolyTraitRef::new(lifetime_defs, path, modifiers, lo.to(self.prev_token.span)); + Ok(GenericBound::Trait(poly_trait)) } // recovers a `Fn(..)` parenthesized-style path from `fn(..)` diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index fce5ec36c66..5fbc817b91a 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -519,11 +519,12 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { continue; }; for bound in bounds { - let ast::GenericBound::Trait(trait_ref, ast::TraitBoundModifiers::NONE) = bound - else { + let ast::GenericBound::Trait(trait_ref) = bound else { continue; }; - if base_error.span == trait_ref.span { + if trait_ref.modifiers == ast::TraitBoundModifiers::NONE + && base_error.span == trait_ref.span + { err.span_suggestion_verbose( constraint.ident.span.between(trait_ref.span), "you might have meant to write a path instead of an associated type bound", @@ -837,7 +838,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { ); if bounds.iter().all(|bound| match bound { ast::GenericBound::Outlives(_) | ast::GenericBound::Use(..) => true, - ast::GenericBound::Trait(tr, _) => tr.span == base_error.span, + ast::GenericBound::Trait(tr) => tr.span == base_error.span, }) { let mut sugg = vec![]; if base_error.span != start_span { @@ -1210,7 +1211,8 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { let param = generics.params.iter().find_map(|param| { // Only consider type params with exactly one trait bound. if let [bound] = &*param.bounds - && let ast::GenericBound::Trait(tref, ast::TraitBoundModifiers::NONE) = bound + && let ast::GenericBound::Trait(tref) = bound + && tref.modifiers == ast::TraitBoundModifiers::NONE && tref.span == span && param.ident.span.eq_ctxt(span) { @@ -1333,8 +1335,9 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { } if let ( [ast::PathSegment { args: None, .. }], - [ast::GenericBound::Trait(poly_trait_ref, ast::TraitBoundModifiers::NONE)], + [ast::GenericBound::Trait(poly_trait_ref)], ) = (&type_param_path.segments[..], &bounds[..]) + && poly_trait_ref.modifiers == ast::TraitBoundModifiers::NONE { if let [ast::PathSegment { ident, args: None, .. }] = &poly_trait_ref.trait_ref.path.segments[..] @@ -2814,7 +2817,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { && bounded_ty.id == binder { for bound in bounds { - if let ast::GenericBound::Trait(poly_trait_ref, _) = bound + if let ast::GenericBound::Trait(poly_trait_ref) = bound && let span = poly_trait_ref .span .with_hi(poly_trait_ref.trait_ref.path.span.lo()) @@ -3233,7 +3236,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { let mut lt_finder = LifetimeFinder { lifetime: lt.span, found: None, seen: vec![] }; for bound in arg_refs { - if let ast::GenericBound::Trait(trait_ref, _) = bound { + if let ast::GenericBound::Trait(trait_ref) = bound { lt_finder.visit_trait_ref(&trait_ref.trait_ref); } } @@ -3444,17 +3447,15 @@ fn mk_where_bound_predicate( span: DUMMY_SP, bound_generic_params: ThinVec::new(), bounded_ty: ast::ptr::P(ty.clone()), - bounds: vec![ast::GenericBound::Trait( - ast::PolyTraitRef { - bound_generic_params: ThinVec::new(), - trait_ref: ast::TraitRef { - path: ast::Path { segments: modified_segments, span: DUMMY_SP, tokens: None }, - ref_id: DUMMY_NODE_ID, - }, - span: DUMMY_SP, + bounds: vec![ast::GenericBound::Trait(ast::PolyTraitRef { + bound_generic_params: ThinVec::new(), + modifiers: ast::TraitBoundModifiers::NONE, + trait_ref: ast::TraitRef { + path: ast::Path { segments: modified_segments, span: DUMMY_SP, tokens: None }, + ref_id: DUMMY_NODE_ID, }, - ast::TraitBoundModifiers::NONE, - )], + span: DUMMY_SP, + })], }; Some(new_where_bound_predicate) diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs index 68f74e52ed7..31585698475 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs @@ -783,7 +783,8 @@ pub fn eq_str_lit(l: &StrLit, r: &StrLit) -> bool { } pub fn eq_poly_ref_trait(l: &PolyTraitRef, r: &PolyTraitRef) -> bool { - eq_path(&l.trait_ref.path, &r.trait_ref.path) + l.modifiers == r.modifiers + && eq_path(&l.trait_ref.path, &r.trait_ref.path) && over(&l.bound_generic_params, &r.bound_generic_params, |l, r| { eq_generic_param(l, r) }) @@ -817,7 +818,7 @@ pub fn eq_generic_param(l: &GenericParam, r: &GenericParam) -> bool { pub fn eq_generic_bound(l: &GenericBound, r: &GenericBound) -> bool { use GenericBound::*; match (l, r) { - (Trait(ptr1, tbm1), Trait(ptr2, tbm2)) => tbm1 == tbm2 && eq_poly_ref_trait(ptr1, ptr2), + (Trait(ptr1), Trait(ptr2)) => eq_poly_ref_trait(ptr1, ptr2), (Outlives(l), Outlives(r)) => eq_id(l.ident, r.ident), _ => false, } diff --git a/src/tools/rustfmt/src/spanned.rs b/src/tools/rustfmt/src/spanned.rs index 555a9240798..4d684f3c635 100644 --- a/src/tools/rustfmt/src/spanned.rs +++ b/src/tools/rustfmt/src/spanned.rs @@ -180,7 +180,7 @@ impl Spanned for ast::GenericArg { impl Spanned for ast::GenericBound { fn span(&self) -> Span { match *self { - ast::GenericBound::Trait(ref ptr, _) => ptr.span, + ast::GenericBound::Trait(ref ptr) => ptr.span, ast::GenericBound::Outlives(ref l) => l.ident.span, ast::GenericBound::Use(_, span) => span, } diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs index f75c4f0fad7..a7bd8312bb8 100644 --- a/src/tools/rustfmt/src/types.rs +++ b/src/tools/rustfmt/src/types.rs @@ -610,16 +610,14 @@ impl Rewrite for ast::GenericBound { fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult { match *self { - ast::GenericBound::Trait( - ref poly_trait_ref, - ast::TraitBoundModifiers { + ast::GenericBound::Trait(ref poly_trait_ref) => { + let snippet = context.snippet(self.span()); + let has_paren = snippet.starts_with('(') && snippet.ends_with(')'); + let ast::TraitBoundModifiers { constness, asyncness, polarity, - }, - ) => { - let snippet = context.snippet(self.span()); - let has_paren = snippet.starts_with('(') && snippet.ends_with(')'); + } = poly_trait_ref.modifiers; let mut constness = constness.as_str().to_string(); if !constness.is_empty() { constness.push(' '); From 67b85e2a1f4e7632e5805fcc6e6a6f53501dd357 Mon Sep 17 00:00:00 2001 From: Urgau Date: Mon, 14 Oct 2024 16:37:54 +0200 Subject: [PATCH 280/357] Add fast-path when computing the default visibility --- compiler/rustc_monomorphize/src/partitioning.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs index 5bd484d7bb0..9bf7e67417e 100644 --- a/compiler/rustc_monomorphize/src/partitioning.rs +++ b/compiler/rustc_monomorphize/src/partitioning.rs @@ -119,6 +119,7 @@ use rustc_middle::util::Providers; use rustc_session::CodegenUnits; use rustc_session::config::{DumpMonoStatsFormat, SwitchWithOptPath}; use rustc_span::symbol::Symbol; +use rustc_target::spec::SymbolVisibility; use tracing::debug; use crate::collector::{self, MonoItemCollectionStrategy, UsageMap}; @@ -904,6 +905,11 @@ fn mono_item_visibility<'tcx>( } fn default_visibility(tcx: TyCtxt<'_>, id: DefId, is_generic: bool) -> Visibility { + // Fast-path to avoid expensive query call below + if tcx.sess.default_visibility() == SymbolVisibility::Interposable { + return Visibility::Default; + } + let export_level = if is_generic { // Generic functions never have export-level C. SymbolExportLevel::Rust @@ -913,6 +919,7 @@ fn default_visibility(tcx: TyCtxt<'_>, id: DefId, is_generic: bool) -> Visibilit _ => SymbolExportLevel::Rust, } }; + match export_level { // C-export level items remain at `Default` to allow C code to // access and interpose them. From 5e6170b97f81b83041666170ceeadefe04d00fb4 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 14 Oct 2024 17:04:30 +0200 Subject: [PATCH 281/357] Preparing for merge from rustc --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index eb4dfcf57cf..8b9e7efdff9 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -7067e4aee45c18cfa1c6af3bf79bd097684fb294 +17a19e684cdf3ca088af8b4da6a6209d128913f4 From 543d226589d152a27a5c150e415b451e50986c79 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 14 Oct 2024 17:09:44 +0200 Subject: [PATCH 282/357] clippy --- src/tools/miri/src/intrinsics/mod.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/tools/miri/src/intrinsics/mod.rs b/src/tools/miri/src/intrinsics/mod.rs index 9f772cfa982..13eac60f911 100644 --- a/src/tools/miri/src/intrinsics/mod.rs +++ b/src/tools/miri/src/intrinsics/mod.rs @@ -301,6 +301,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let b = this.read_scalar(b)?.to_f32()?; let c = this.read_scalar(c)?.to_f32()?; let fuse: bool = this.machine.rng.get_mut().gen(); + #[allow(clippy::arithmetic_side_effects)] // float ops don't overflow let res = if fuse { // FIXME: Using host floats, to work around https://github.com/rust-lang/rustc_apfloat/issues/11 a.to_host().mul_add(b.to_host(), c.to_host()).to_soft() @@ -316,6 +317,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let b = this.read_scalar(b)?.to_f64()?; let c = this.read_scalar(c)?.to_f64()?; let fuse: bool = this.machine.rng.get_mut().gen(); + #[allow(clippy::arithmetic_side_effects)] // float ops don't overflow let res = if fuse { // FIXME: Using host floats, to work around https://github.com/rust-lang/rustc_apfloat/issues/11 a.to_host().mul_add(b.to_host(), c.to_host()).to_soft() From 89323bff8bc7a32eda6c7b311b16991c014725bf Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 12 Oct 2024 13:38:23 +0200 Subject: [PATCH 283/357] pthread_mutex: store mutex ID outside adressable memory, so it can be trusted --- src/tools/miri/src/concurrency/sync.rs | 16 +- src/tools/miri/src/helpers.rs | 7 +- src/tools/miri/src/machine.rs | 16 +- src/tools/miri/src/shims/unix/sync.rs | 255 +++++++++++------- .../libc_pthread_mutex_move.init.stderr | 4 +- .../concurrency/libc_pthread_mutex_move.rs | 4 +- ...hread_mutex_move.static_initializer.stderr | 4 +- 7 files changed, 180 insertions(+), 126 deletions(-) diff --git a/src/tools/miri/src/concurrency/sync.rs b/src/tools/miri/src/concurrency/sync.rs index e1e748e7945..364f368f15d 100644 --- a/src/tools/miri/src/concurrency/sync.rs +++ b/src/tools/miri/src/concurrency/sync.rs @@ -167,8 +167,10 @@ pub struct SynchronizationObjects { mutexes: IndexVec, rwlocks: IndexVec, condvars: IndexVec, - futexes: FxHashMap, pub(super) init_onces: IndexVec, + + /// Futex info for the futex at the given address. + futexes: FxHashMap, } // Private extension trait for local helper methods @@ -277,17 +279,9 @@ pub(super) trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { /// Eagerly create and initialize a new mutex. - fn mutex_create( - &mut self, - lock: &MPlaceTy<'tcx>, - offset: u64, - data: Option>, - ) -> InterpResult<'tcx, MutexId> { + fn mutex_create(&mut self) -> MutexId { let this = self.eval_context_mut(); - this.create_id(lock, offset, |ecx| &mut ecx.machine.sync.mutexes, Mutex { - data, - ..Default::default() - }) + this.machine.sync.mutexes.push(Default::default()) } /// Lazily create a new mutex. diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index 8bd429deefc..9ec325863ff 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -223,14 +223,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } /// Evaluates the scalar at the specified path. - fn eval_path(&self, path: &[&str]) -> OpTy<'tcx> { + fn eval_path(&self, path: &[&str]) -> MPlaceTy<'tcx> { let this = self.eval_context_ref(); let instance = resolve_path(*this.tcx, path, Namespace::ValueNS); // We don't give a span -- this isn't actually used directly by the program anyway. - let const_val = this.eval_global(instance).unwrap_or_else(|err| { + this.eval_global(instance).unwrap_or_else(|err| { panic!("failed to evaluate required Rust item: {path:?}\n{err:?}") - }); - const_val.into() + }) } fn eval_path_scalar(&self, path: &[&str]) -> Scalar { let this = self.eval_context_ref(); diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index af0ca00a0c0..60d096b92f2 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -1,6 +1,7 @@ //! Global machine state as well as implementation of the interpreter engine //! `Machine` trait. +use std::any::Any; use std::borrow::Cow; use std::cell::RefCell; use std::collections::hash_map::Entry; @@ -336,6 +337,11 @@ pub struct AllocExtra<'tcx> { /// if this allocation is leakable. The backtrace is not /// pruned yet; that should be done before printing it. pub backtrace: Option>>, + /// Synchronization primitives like to attach extra data to particular addresses. We store that + /// inside the relevant allocation, to ensure that everything is removed when the allocation is + /// freed. + /// This maps offsets to synchronization-primitive-specific data. + pub sync: FxHashMap>, } // We need a `Clone` impl because the machine passes `Allocation` through `Cow`... @@ -348,7 +354,7 @@ impl<'tcx> Clone for AllocExtra<'tcx> { impl VisitProvenance for AllocExtra<'_> { fn visit_provenance(&self, visit: &mut VisitWith<'_>) { - let AllocExtra { borrow_tracker, data_race, weak_memory, backtrace: _ } = self; + let AllocExtra { borrow_tracker, data_race, weak_memory, backtrace: _, sync: _ } = self; borrow_tracker.visit_provenance(visit); data_race.visit_provenance(visit); @@ -1187,7 +1193,13 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { .insert(id, (ecx.machine.current_span(), None)); } - interp_ok(AllocExtra { borrow_tracker, data_race, weak_memory, backtrace }) + interp_ok(AllocExtra { + borrow_tracker, + data_race, + weak_memory, + backtrace, + sync: FxHashMap::default(), + }) } fn adjust_alloc_root_pointer( diff --git a/src/tools/miri/src/shims/unix/sync.rs b/src/tools/miri/src/shims/unix/sync.rs index b05f340861e..86c75575f35 100644 --- a/src/tools/miri/src/shims/unix/sync.rs +++ b/src/tools/miri/src/shims/unix/sync.rs @@ -4,8 +4,37 @@ use rustc_target::abi::Size; use crate::*; -// pthread_mutexattr_t is either 4 or 8 bytes, depending on the platform. -// We ignore the platform layout and store our own fields: +/// Do a bytewise comparison of the two places, using relaxed atomic reads. +/// This is used to check if a mutex matches its static initializer value. +fn bytewise_equal_atomic_relaxed<'tcx>( + ecx: &MiriInterpCx<'tcx>, + left: &MPlaceTy<'tcx>, + right: &MPlaceTy<'tcx>, +) -> InterpResult<'tcx, bool> { + let size = left.layout.size; + assert_eq!(size, right.layout.size); + + // We do this in chunks of 4, so that we are okay to race with (sufficiently aligned) + // 4-byte atomic accesses. + assert!(size.bytes() % 4 == 0); + for i in 0..(size.bytes() / 4) { + let offset = Size::from_bytes(i.strict_mul(4)); + let load = |place: &MPlaceTy<'tcx>| { + let byte = place.offset(offset, ecx.machine.layouts.u32, ecx)?; + ecx.read_scalar_atomic(&byte, AtomicReadOrd::Relaxed)?.to_u32() + }; + let left = load(left)?; + let right = load(right)?; + if left != right { + return interp_ok(false); + } + } + + interp_ok(true) +} + +// # pthread_mutexattr_t +// We store some data directly inside the type, ignoring the platform layout: // - kind: i32 #[inline] @@ -49,52 +78,54 @@ fn mutexattr_set_kind<'tcx>( /// field *not* PTHREAD_MUTEX_DEFAULT but this special flag. const PTHREAD_MUTEX_KIND_UNCHANGED: i32 = 0x8000000; +// # pthread_mutex_t +// We store some data directly inside the type, ignoring the platform layout: +// - init: u32 + /// The mutex kind. #[derive(Debug, Clone, Copy)] -pub enum MutexKind { +enum MutexKind { Normal, Default, Recursive, ErrorCheck, } -#[derive(Debug)] +#[derive(Debug, Clone, Copy)] /// Additional data that we attach with each mutex instance. -pub struct AdditionalMutexData { - /// The mutex kind, used by some mutex implementations like pthreads mutexes. - pub kind: MutexKind, - - /// The address of the mutex. - pub address: u64, +pub struct MutexData { + id: MutexId, + kind: MutexKind, } -// pthread_mutex_t is between 4 and 48 bytes, depending on the platform. -// We ignore the platform layout and store our own fields: -// - id: u32 +/// If `init` is set to this, we consider the mutex initialized. +const MUTEX_INIT_COOKIE: u32 = 0xcafe_affe; -fn mutex_id_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> InterpResult<'tcx, u64> { - // When adding a new OS, make sure we also support all its static initializers in - // `mutex_kind_from_static_initializer`! +/// To ensure an initialized mutex that was moved somewhere else can be distinguished from +/// a statically initialized mutex that is used the first time, we pick some offset within +/// `pthread_mutex_t` and use it as an "initialized" flag. +fn mutex_init_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> InterpResult<'tcx, Size> { let offset = match &*ecx.tcx.sess.target.os { "linux" | "illumos" | "solaris" | "freebsd" | "android" => 0, // macOS stores a signature in the first bytes, so we have to move to offset 4. "macos" => 4, os => throw_unsup_format!("`pthread_mutex` is not supported on {os}"), }; + let offset = Size::from_bytes(offset); // Sanity-check this against PTHREAD_MUTEX_INITIALIZER (but only once): - // the id must start out as 0. - // FIXME on some platforms (e.g linux) there are more static initializers for - // recursive or error checking mutexes. We should also add thme in this sanity check. + // the `init` field start out as `false`. static SANITY: AtomicBool = AtomicBool::new(false); if !SANITY.swap(true, Ordering::Relaxed) { let check_static_initializer = |name| { let static_initializer = ecx.eval_path(&["libc", name]); - let id_field = static_initializer - .offset(Size::from_bytes(offset), ecx.machine.layouts.u32, ecx) - .unwrap(); - let id = ecx.read_scalar(&id_field).unwrap().to_u32().unwrap(); - assert_eq!(id, 0, "{name} is incompatible with our pthread_mutex layout: id is not 0"); + let init_field = + static_initializer.offset(offset, ecx.machine.layouts.u32, ecx).unwrap(); + let init = ecx.read_scalar(&init_field).unwrap().to_u32().unwrap(); + assert_ne!( + init, MUTEX_INIT_COOKIE, + "{name} is incompatible with our pthread_mutex layout: `init` is equal to our cookie" + ); }; check_static_initializer("PTHREAD_MUTEX_INITIALIZER"); @@ -120,42 +151,69 @@ fn mutex_create<'tcx>( ecx: &mut MiriInterpCx<'tcx>, mutex_ptr: &OpTy<'tcx>, kind: MutexKind, -) -> InterpResult<'tcx> { +) -> InterpResult<'tcx, MutexId> { let mutex = ecx.deref_pointer(mutex_ptr)?; - let address = mutex.ptr().addr().bytes(); - let data = Box::new(AdditionalMutexData { address, kind }); - ecx.mutex_create(&mutex, mutex_id_offset(ecx)?, Some(data))?; - interp_ok(()) + let init_field = mutex.offset(mutex_init_offset(ecx)?, ecx.machine.layouts.u32, ecx)?; + + let id = ecx.mutex_create(); + let (alloc, offset, _) = ecx.ptr_get_alloc_id(mutex.ptr(), 0)?; + let (alloc_extra, _machine) = ecx.get_alloc_extra_mut(alloc)?; + alloc_extra.sync.insert(offset, Box::new(MutexData { id, kind })); + // Mark this as "initialized". + ecx.write_scalar_atomic( + Scalar::from_u32(MUTEX_INIT_COOKIE), + &init_field, + AtomicWriteOrd::Relaxed, + )?; + interp_ok(id) } /// Returns the `MutexId` of the mutex stored at `mutex_op`. /// /// `mutex_get_id` will also check if the mutex has been moved since its first use and /// return an error if it has. -fn mutex_get_id<'tcx>( - ecx: &mut MiriInterpCx<'tcx>, +fn mutex_get_data<'tcx, 'a>( + ecx: &'a mut MiriInterpCx<'tcx>, mutex_ptr: &OpTy<'tcx>, -) -> InterpResult<'tcx, MutexId> { +) -> InterpResult<'tcx, MutexData> { let mutex = ecx.deref_pointer(mutex_ptr)?; - let address = mutex.ptr().addr().bytes(); + let init_field = mutex.offset(mutex_init_offset(ecx)?, ecx.machine.layouts.u32, ecx)?; - let id = ecx.mutex_get_or_create_id(&mutex, mutex_id_offset(ecx)?, |ecx| { - // This is called if a static initializer was used and the lock has not been assigned - // an ID yet. We have to determine the mutex kind from the static initializer. + // Check if this is already initialized. Needs to be atomic because we can race with another + // thread initializing. Needs to be an RMW operation to ensure we read the *latest* value. + // So we just try to replace MUTEX_INIT_COOKIE with itself. + let init_cookie = Scalar::from_u32(MUTEX_INIT_COOKIE); + let (_init, success) = ecx + .atomic_compare_exchange_scalar( + &init_field, + &ImmTy::from_scalar(init_cookie, ecx.machine.layouts.u32), + init_cookie, + AtomicRwOrd::Acquire, + AtomicReadOrd::Acquire, + /* can_fail_spuriously */ false, + )? + .to_scalar_pair(); + if success.to_bool()? { + // If it is initialized, it must be found in the "sync primitive" table, + // or else it has been moved illegally. + let (alloc, offset, _) = ecx.ptr_get_alloc_id(mutex.ptr(), 0)?; + let (alloc_extra, _machine) = ecx.get_alloc_extra_mut(alloc)?; + alloc_extra + .sync + .get(&offset) + .and_then(|s| s.downcast_ref::()) + .copied() + .ok_or_else(|| err_ub_format!("`pthread_mutex_t` can't be moved after first use")) + .into() + } else { + // Not yet initialized. This must be a static initializer, figure out the kind + // from that. We don't need to worry about races since we are the interpreter + // and don't let any other tread take a step. let kind = mutex_kind_from_static_initializer(ecx, &mutex)?; - - interp_ok(Some(Box::new(AdditionalMutexData { kind, address }))) - })?; - - // Check that the mutex has not been moved since last use. - let data = ecx - .mutex_get_data::(id) - .expect("data should always exist for pthreads"); - if data.address != address { - throw_ub_format!("pthread_mutex_t can't be moved after first use") + // And then create the mutex like this. + let id = mutex_create(ecx, mutex_ptr, kind)?; + interp_ok(MutexData { id, kind }) } - - interp_ok(id) } /// Returns the kind of a static initializer. @@ -163,25 +221,28 @@ fn mutex_kind_from_static_initializer<'tcx>( ecx: &MiriInterpCx<'tcx>, mutex: &MPlaceTy<'tcx>, ) -> InterpResult<'tcx, MutexKind> { - interp_ok(match &*ecx.tcx.sess.target.os { - // Only linux has static initializers other than PTHREAD_MUTEX_DEFAULT. - "linux" => { - let offset = if ecx.pointer_size().bytes() == 8 { 16 } else { 12 }; - let kind_place = - mutex.offset(Size::from_bytes(offset), ecx.machine.layouts.i32, ecx)?; - let kind = ecx.read_scalar(&kind_place)?.to_i32()?; - // Here we give PTHREAD_MUTEX_DEFAULT priority so that - // PTHREAD_MUTEX_INITIALIZER behaves like `pthread_mutex_init` with a NULL argument. - if kind == ecx.eval_libc_i32("PTHREAD_MUTEX_DEFAULT") { - MutexKind::Default - } else { - mutex_translate_kind(ecx, kind)? - } - } - _ => MutexKind::Default, - }) + // All the static initializers recognized here *must* be checked in `mutex_init_offset`! + let is_initializer = + |name| bytewise_equal_atomic_relaxed(ecx, mutex, &ecx.eval_path(&["libc", name])); + + // PTHREAD_MUTEX_INITIALIZER is recognized on all targets. + if is_initializer("PTHREAD_MUTEX_INITIALIZER")? { + return interp_ok(MutexKind::Default); + } + // Support additional platform-specific initializers. + match &*ecx.tcx.sess.target.os { + "linux" => + if is_initializer("PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP")? { + return interp_ok(MutexKind::Recursive); + } else if is_initializer("PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP")? { + return interp_ok(MutexKind::ErrorCheck); + }, + _ => {} + } + throw_unsup_format!("unsupported static initializer used for `pthread_mutex_t"); } +/// Translates the mutex kind from what is stored in pthread_mutexattr_t to our enum. fn mutex_translate_kind<'tcx>( ecx: &MiriInterpCx<'tcx>, kind: i32, @@ -203,8 +264,8 @@ fn mutex_translate_kind<'tcx>( }) } -// pthread_rwlock_t is between 4 and 56 bytes, depending on the platform. -// We ignore the platform layout and store our own fields: +// # pthread_rwlock_t +// We store some data directly inside the type, ignoring the platform layout: // - id: u32 #[derive(Debug)] @@ -262,8 +323,8 @@ fn rwlock_get_id<'tcx>( interp_ok(id) } -// pthread_condattr_t. -// We ignore the platform layout and store our own fields: +// # pthread_condattr_t +// We store some data directly inside the type, ignoring the platform layout: // - clock: i32 #[inline] @@ -315,8 +376,8 @@ fn condattr_set_clock_id<'tcx>( ) } -// pthread_cond_t can be only 4 bytes in size, depending on the platform. -// We ignore the platform layout and store our own fields: +// # pthread_cond_t +// We store some data directly inside the type, ignoring the platform layout: // - id: u32 fn cond_id_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> InterpResult<'tcx, u64> { @@ -468,20 +529,16 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { ) -> InterpResult<'tcx> { let this = self.eval_context_mut(); - let id = mutex_get_id(this, mutex_op)?; - let kind = this - .mutex_get_data::(id) - .expect("data should always exist for pthread mutexes") - .kind; + let mutex = mutex_get_data(this, mutex_op)?; - let ret = if this.mutex_is_locked(id) { - let owner_thread = this.mutex_get_owner(id); + let ret = if this.mutex_is_locked(mutex.id) { + let owner_thread = this.mutex_get_owner(mutex.id); if owner_thread != this.active_thread() { - this.mutex_enqueue_and_block(id, Some((Scalar::from_i32(0), dest.clone()))); + this.mutex_enqueue_and_block(mutex.id, Some((Scalar::from_i32(0), dest.clone()))); return interp_ok(()); } else { // Trying to acquire the same mutex again. - match kind { + match mutex.kind { MutexKind::Default => throw_ub_format!( "trying to acquire default mutex already locked by the current thread" @@ -489,14 +546,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { MutexKind::Normal => throw_machine_stop!(TerminationInfo::Deadlock), MutexKind::ErrorCheck => this.eval_libc_i32("EDEADLK"), MutexKind::Recursive => { - this.mutex_lock(id); + this.mutex_lock(mutex.id); 0 } } } } else { // The mutex is unlocked. Let's lock it. - this.mutex_lock(id); + this.mutex_lock(mutex.id); 0 }; this.write_scalar(Scalar::from_i32(ret), dest)?; @@ -506,29 +563,25 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn pthread_mutex_trylock(&mut self, mutex_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); - let id = mutex_get_id(this, mutex_op)?; - let kind = this - .mutex_get_data::(id) - .expect("data should always exist for pthread mutexes") - .kind; + let mutex = mutex_get_data(this, mutex_op)?; - interp_ok(Scalar::from_i32(if this.mutex_is_locked(id) { - let owner_thread = this.mutex_get_owner(id); + interp_ok(Scalar::from_i32(if this.mutex_is_locked(mutex.id) { + let owner_thread = this.mutex_get_owner(mutex.id); if owner_thread != this.active_thread() { this.eval_libc_i32("EBUSY") } else { - match kind { + match mutex.kind { MutexKind::Default | MutexKind::Normal | MutexKind::ErrorCheck => this.eval_libc_i32("EBUSY"), MutexKind::Recursive => { - this.mutex_lock(id); + this.mutex_lock(mutex.id); 0 } } } } else { // The mutex is unlocked. Let's lock it. - this.mutex_lock(id); + this.mutex_lock(mutex.id); 0 })) } @@ -536,20 +589,16 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn pthread_mutex_unlock(&mut self, mutex_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); - let id = mutex_get_id(this, mutex_op)?; - let kind = this - .mutex_get_data::(id) - .expect("data should always exist for pthread mutexes") - .kind; + let mutex = mutex_get_data(this, mutex_op)?; - if let Some(_old_locked_count) = this.mutex_unlock(id)? { + if let Some(_old_locked_count) = this.mutex_unlock(mutex.id)? { // The mutex was locked by the current thread. interp_ok(Scalar::from_i32(0)) } else { // The mutex was locked by another thread or not locked at all. See // the “Unlock When Not Owner” column in // https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_mutex_unlock.html. - match kind { + match mutex.kind { MutexKind::Default => throw_ub_format!( "unlocked a default mutex that was not locked by the current thread" @@ -569,9 +618,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Reading the field also has the side-effect that we detect double-`destroy` // since we make the field unint below. - let id = mutex_get_id(this, mutex_op)?; + let mutex = mutex_get_data(this, mutex_op)?; - if this.mutex_is_locked(id) { + if this.mutex_is_locked(mutex.id) { throw_ub_format!("destroyed a locked mutex"); } @@ -809,7 +858,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let this = self.eval_context_mut(); let id = cond_get_id(this, cond_op)?; - let mutex_id = mutex_get_id(this, mutex_op)?; + let mutex_id = mutex_get_data(this, mutex_op)?.id; this.condvar_wait( id, @@ -833,7 +882,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let this = self.eval_context_mut(); let id = cond_get_id(this, cond_op)?; - let mutex_id = mutex_get_id(this, mutex_op)?; + let mutex_id = mutex_get_data(this, mutex_op)?.id; // Extract the timeout. let clock_id = this diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.init.stderr b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.init.stderr index 15f397d4ac2..7df8e8be580 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.init.stderr +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.init.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: pthread_mutex_t can't be moved after first use +error: Undefined Behavior: `pthread_mutex_t` can't be moved after first use --> tests/fail-dep/concurrency/libc_pthread_mutex_move.rs:LL:CC | LL | libc::pthread_mutex_lock(&mut m2 as *mut _); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pthread_mutex_t can't be moved after first use + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `pthread_mutex_t` can't be moved after first use | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.rs b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.rs index c12a97a9ca1..6c1f967b2b0 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.rs +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.rs @@ -12,7 +12,7 @@ fn check() { assert_eq!(libc::pthread_mutex_init(&mut m as *mut _, std::ptr::null()), 0); let mut m2 = m; // move the mutex - libc::pthread_mutex_lock(&mut m2 as *mut _); //~[init] ERROR: pthread_mutex_t can't be moved after first use + libc::pthread_mutex_lock(&mut m2 as *mut _); //~[init] ERROR: can't be moved after first use } } @@ -23,6 +23,6 @@ fn check() { libc::pthread_mutex_lock(&mut m as *mut _); let mut m2 = m; // move the mutex - libc::pthread_mutex_unlock(&mut m2 as *mut _); //~[static_initializer] ERROR: pthread_mutex_t can't be moved after first use + libc::pthread_mutex_unlock(&mut m2 as *mut _); //~[static_initializer] ERROR: can't be moved after first use } } diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.static_initializer.stderr b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.static_initializer.stderr index ebc253bf7a6..acc018cb4ba 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.static_initializer.stderr +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.static_initializer.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: pthread_mutex_t can't be moved after first use +error: Undefined Behavior: `pthread_mutex_t` can't be moved after first use --> tests/fail-dep/concurrency/libc_pthread_mutex_move.rs:LL:CC | LL | libc::pthread_mutex_unlock(&mut m2 as *mut _); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pthread_mutex_t can't be moved after first use + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `pthread_mutex_t` can't be moved after first use | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information From 1389bb91149af588b0f89d903bf074b7be49565c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 12 Oct 2024 14:07:36 +0200 Subject: [PATCH 284/357] pthread_rwlock: also store ID outside addressable memory --- src/tools/miri/src/concurrency/sync.rs | 48 +---- src/tools/miri/src/shims/unix/macos/sync.rs | 2 +- src/tools/miri/src/shims/unix/sync.rs | 191 ++++++++++-------- .../concurrency/libx_pthread_rwlock_moved.rs | 2 +- .../libx_pthread_rwlock_moved.stderr | 4 +- 5 files changed, 112 insertions(+), 135 deletions(-) diff --git a/src/tools/miri/src/concurrency/sync.rs b/src/tools/miri/src/concurrency/sync.rs index 364f368f15d..b22684faec4 100644 --- a/src/tools/miri/src/concurrency/sync.rs +++ b/src/tools/miri/src/concurrency/sync.rs @@ -79,9 +79,6 @@ struct Mutex { queue: VecDeque, /// Mutex clock. This tracks the moment of the last unlock. clock: VClock, - - /// Additional data that can be set by shim implementations. - data: Option>, } declare_id!(RwLockId); @@ -118,9 +115,6 @@ struct RwLock { /// locks. /// This is only relevant when there is an active reader. clock_current_readers: VClock, - - /// Additional data that can be set by shim implementations. - data: Option>, } declare_id!(CondvarId); @@ -290,56 +284,22 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { &mut self, lock: &MPlaceTy<'tcx>, offset: u64, - initialize_data: impl for<'a> FnOnce( - &'a mut MiriInterpCx<'tcx>, - ) -> InterpResult<'tcx, Option>>, ) -> InterpResult<'tcx, MutexId> { let this = self.eval_context_mut(); this.get_or_create_id( lock, offset, |ecx| &mut ecx.machine.sync.mutexes, - |ecx| initialize_data(ecx).map(|data| Mutex { data, ..Default::default() }), + |_ecx| interp_ok(Mutex::default()), )? .ok_or_else(|| err_ub_format!("mutex has invalid ID")) .into() } - /// Retrieve the additional data stored for a mutex. - fn mutex_get_data<'a, T: 'static>(&'a mut self, id: MutexId) -> Option<&'a T> - where - 'tcx: 'a, - { - let this = self.eval_context_ref(); - this.machine.sync.mutexes[id].data.as_deref().and_then(|p| p.downcast_ref::()) - } - - fn rwlock_get_or_create_id( - &mut self, - lock: &MPlaceTy<'tcx>, - offset: u64, - initialize_data: impl for<'a> FnOnce( - &'a mut MiriInterpCx<'tcx>, - ) -> InterpResult<'tcx, Option>>, - ) -> InterpResult<'tcx, RwLockId> { + /// Eagerly create and initialize a new rwlock. + fn rwlock_create(&mut self) -> RwLockId { let this = self.eval_context_mut(); - this.get_or_create_id( - lock, - offset, - |ecx| &mut ecx.machine.sync.rwlocks, - |ecx| initialize_data(ecx).map(|data| RwLock { data, ..Default::default() }), - )? - .ok_or_else(|| err_ub_format!("rwlock has invalid ID")) - .into() - } - - /// Retrieve the additional data stored for a rwlock. - fn rwlock_get_data<'a, T: 'static>(&'a mut self, id: RwLockId) -> Option<&'a T> - where - 'tcx: 'a, - { - let this = self.eval_context_ref(); - this.machine.sync.rwlocks[id].data.as_deref().and_then(|p| p.downcast_ref::()) + this.machine.sync.rwlocks.push(Default::default()) } /// Eagerly create and initialize a new condvar. diff --git a/src/tools/miri/src/shims/unix/macos/sync.rs b/src/tools/miri/src/shims/unix/macos/sync.rs index 2f96849d0d2..1efe393a0e2 100644 --- a/src/tools/miri/src/shims/unix/macos/sync.rs +++ b/src/tools/miri/src/shims/unix/macos/sync.rs @@ -20,7 +20,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { // os_unfair_lock holds a 32-bit value, is initialized with zero and // must be assumed to be opaque. Therefore, we can just store our // internal mutex ID in the structure without anyone noticing. - this.mutex_get_or_create_id(&lock, 0, |_| interp_ok(None)) + this.mutex_get_or_create_id(&lock, /* offset */ 0) } } diff --git a/src/tools/miri/src/shims/unix/sync.rs b/src/tools/miri/src/shims/unix/sync.rs index 86c75575f35..1a4c4094c5d 100644 --- a/src/tools/miri/src/shims/unix/sync.rs +++ b/src/tools/miri/src/shims/unix/sync.rs @@ -33,6 +33,65 @@ fn bytewise_equal_atomic_relaxed<'tcx>( interp_ok(true) } +/// We designate an `init`` field in all primitives. +/// If `init` is set to this, we consider the primitive initialized. +const INIT_COOKIE: u32 = 0xcafe_affe; + +fn sync_create<'tcx, T: 'static + Copy>( + ecx: &mut MiriInterpCx<'tcx>, + primitive: &MPlaceTy<'tcx>, + init_offset: Size, + data: T, +) -> InterpResult<'tcx> { + let init_field = primitive.offset(init_offset, ecx.machine.layouts.u32, ecx)?; + + let (alloc, offset, _) = ecx.ptr_get_alloc_id(primitive.ptr(), 0)?; + let (alloc_extra, _machine) = ecx.get_alloc_extra_mut(alloc)?; + alloc_extra.sync.insert(offset, Box::new(data)); + // Mark this as "initialized". + ecx.write_scalar_atomic(Scalar::from_u32(INIT_COOKIE), &init_field, AtomicWriteOrd::Relaxed)?; + interp_ok(()) +} + +/// Checks if the primitive is initialized, and return its associated data if so. +/// Otherwise, return None. +fn sync_get_data<'tcx, T: 'static + Copy>( + ecx: &mut MiriInterpCx<'tcx>, + primitive: &MPlaceTy<'tcx>, + init_offset: Size, + name: &str, +) -> InterpResult<'tcx, Option> { + let init_field = primitive.offset(init_offset, ecx.machine.layouts.u32, ecx)?; + // Check if this is already initialized. Needs to be atomic because we can race with another + // thread initializing. Needs to be an RMW operation to ensure we read the *latest* value. + // So we just try to replace MUTEX_INIT_COOKIE with itself. + let init_cookie = Scalar::from_u32(INIT_COOKIE); + let (_init, success) = ecx + .atomic_compare_exchange_scalar( + &init_field, + &ImmTy::from_scalar(init_cookie, ecx.machine.layouts.u32), + init_cookie, + AtomicRwOrd::Acquire, + AtomicReadOrd::Acquire, + /* can_fail_spuriously */ false, + )? + .to_scalar_pair(); + if success.to_bool()? { + // If it is initialized, it must be found in the "sync primitive" table, + // or else it has been moved illegally. + let (alloc, offset, _) = ecx.ptr_get_alloc_id(primitive.ptr(), 0)?; + let (alloc_extra, _machine) = ecx.get_alloc_extra_mut(alloc)?; + let data = alloc_extra + .sync + .get(&offset) + .and_then(|s| s.downcast_ref::()) + .ok_or_else(|| err_ub_format!("`{name}` can't be moved after first use"))?; + interp_ok(Some(*data)) + } else { + interp_ok(None) + } +} + // # pthread_mutexattr_t // We store some data directly inside the type, ignoring the platform layout: // - kind: i32 @@ -98,23 +157,20 @@ pub struct MutexData { kind: MutexKind, } -/// If `init` is set to this, we consider the mutex initialized. -const MUTEX_INIT_COOKIE: u32 = 0xcafe_affe; - /// To ensure an initialized mutex that was moved somewhere else can be distinguished from /// a statically initialized mutex that is used the first time, we pick some offset within /// `pthread_mutex_t` and use it as an "initialized" flag. fn mutex_init_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> InterpResult<'tcx, Size> { let offset = match &*ecx.tcx.sess.target.os { "linux" | "illumos" | "solaris" | "freebsd" | "android" => 0, - // macOS stores a signature in the first bytes, so we have to move to offset 4. + // macOS stores a signature in the first bytes, so we move to offset 4. "macos" => 4, os => throw_unsup_format!("`pthread_mutex` is not supported on {os}"), }; let offset = Size::from_bytes(offset); // Sanity-check this against PTHREAD_MUTEX_INITIALIZER (but only once): - // the `init` field start out as `false`. + // the `init` field must start out not equal to MUTEX_INIT_COOKIE. static SANITY: AtomicBool = AtomicBool::new(false); if !SANITY.swap(true, Ordering::Relaxed) { let check_static_initializer = |name| { @@ -122,10 +178,7 @@ fn mutex_init_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> InterpResult<'tcx, Size> let init_field = static_initializer.offset(offset, ecx.machine.layouts.u32, ecx).unwrap(); let init = ecx.read_scalar(&init_field).unwrap().to_u32().unwrap(); - assert_ne!( - init, MUTEX_INIT_COOKIE, - "{name} is incompatible with our pthread_mutex layout: `init` is equal to our cookie" - ); + assert_ne!(init, INIT_COOKIE, "{name} is incompatible with our initialization cookie"); }; check_static_initializer("PTHREAD_MUTEX_INITIALIZER"); @@ -151,21 +204,12 @@ fn mutex_create<'tcx>( ecx: &mut MiriInterpCx<'tcx>, mutex_ptr: &OpTy<'tcx>, kind: MutexKind, -) -> InterpResult<'tcx, MutexId> { +) -> InterpResult<'tcx, MutexData> { let mutex = ecx.deref_pointer(mutex_ptr)?; - let init_field = mutex.offset(mutex_init_offset(ecx)?, ecx.machine.layouts.u32, ecx)?; - let id = ecx.mutex_create(); - let (alloc, offset, _) = ecx.ptr_get_alloc_id(mutex.ptr(), 0)?; - let (alloc_extra, _machine) = ecx.get_alloc_extra_mut(alloc)?; - alloc_extra.sync.insert(offset, Box::new(MutexData { id, kind })); - // Mark this as "initialized". - ecx.write_scalar_atomic( - Scalar::from_u32(MUTEX_INIT_COOKIE), - &init_field, - AtomicWriteOrd::Relaxed, - )?; - interp_ok(id) + let data = MutexData { id, kind }; + sync_create(ecx, &mutex, mutex_init_offset(ecx)?, data)?; + interp_ok(data) } /// Returns the `MutexId` of the mutex stored at `mutex_op`. @@ -177,42 +221,18 @@ fn mutex_get_data<'tcx, 'a>( mutex_ptr: &OpTy<'tcx>, ) -> InterpResult<'tcx, MutexData> { let mutex = ecx.deref_pointer(mutex_ptr)?; - let init_field = mutex.offset(mutex_init_offset(ecx)?, ecx.machine.layouts.u32, ecx)?; - // Check if this is already initialized. Needs to be atomic because we can race with another - // thread initializing. Needs to be an RMW operation to ensure we read the *latest* value. - // So we just try to replace MUTEX_INIT_COOKIE with itself. - let init_cookie = Scalar::from_u32(MUTEX_INIT_COOKIE); - let (_init, success) = ecx - .atomic_compare_exchange_scalar( - &init_field, - &ImmTy::from_scalar(init_cookie, ecx.machine.layouts.u32), - init_cookie, - AtomicRwOrd::Acquire, - AtomicReadOrd::Acquire, - /* can_fail_spuriously */ false, - )? - .to_scalar_pair(); - if success.to_bool()? { - // If it is initialized, it must be found in the "sync primitive" table, - // or else it has been moved illegally. - let (alloc, offset, _) = ecx.ptr_get_alloc_id(mutex.ptr(), 0)?; - let (alloc_extra, _machine) = ecx.get_alloc_extra_mut(alloc)?; - alloc_extra - .sync - .get(&offset) - .and_then(|s| s.downcast_ref::()) - .copied() - .ok_or_else(|| err_ub_format!("`pthread_mutex_t` can't be moved after first use")) - .into() + if let Some(data) = + sync_get_data::(ecx, &mutex, mutex_init_offset(ecx)?, "pthread_mutex_t")? + { + interp_ok(data) } else { // Not yet initialized. This must be a static initializer, figure out the kind // from that. We don't need to worry about races since we are the interpreter // and don't let any other tread take a step. let kind = mutex_kind_from_static_initializer(ecx, &mutex)?; // And then create the mutex like this. - let id = mutex_create(ecx, mutex_ptr, kind)?; - interp_ok(MutexData { id, kind }) + mutex_create(ecx, mutex_ptr, kind) } } @@ -266,61 +286,58 @@ fn mutex_translate_kind<'tcx>( // # pthread_rwlock_t // We store some data directly inside the type, ignoring the platform layout: -// - id: u32 +// - init: u32 -#[derive(Debug)] +/// If `init` is set to this, we consider the rwlock initialized. +const RWLOCK_INIT_COOKIE: u32 = 0xcafe_affe; + +#[derive(Debug, Copy, Clone)] /// Additional data that we attach with each rwlock instance. -pub struct AdditionalRwLockData { - /// The address of the rwlock. - pub address: u64, +pub struct RwLockData { + id: RwLockId, } -fn rwlock_id_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> InterpResult<'tcx, u64> { +fn rwlock_init_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> InterpResult<'tcx, Size> { let offset = match &*ecx.tcx.sess.target.os { "linux" | "illumos" | "solaris" | "freebsd" | "android" => 0, - // macOS stores a signature in the first bytes, so we have to move to offset 4. + // macOS stores a signature in the first bytes, so we move to offset 4. "macos" => 4, os => throw_unsup_format!("`pthread_rwlock` is not supported on {os}"), }; + let offset = Size::from_bytes(offset); // Sanity-check this against PTHREAD_RWLOCK_INITIALIZER (but only once): - // the id must start out as 0. + // the `init` field must start out not equal to RWLOCK_INIT_COOKIE. static SANITY: AtomicBool = AtomicBool::new(false); if !SANITY.swap(true, Ordering::Relaxed) { let static_initializer = ecx.eval_path(&["libc", "PTHREAD_RWLOCK_INITIALIZER"]); - let id_field = static_initializer - .offset(Size::from_bytes(offset), ecx.machine.layouts.u32, ecx) - .unwrap(); - let id = ecx.read_scalar(&id_field).unwrap().to_u32().unwrap(); - assert_eq!( - id, 0, - "PTHREAD_RWLOCK_INITIALIZER is incompatible with our pthread_rwlock layout: id is not 0" + let init_field = static_initializer.offset(offset, ecx.machine.layouts.u32, ecx).unwrap(); + let init = ecx.read_scalar(&init_field).unwrap().to_u32().unwrap(); + assert_ne!( + init, RWLOCK_INIT_COOKIE, + "PTHREAD_RWLOCK_INITIALIZER is incompatible with our initialization cookie" ); } interp_ok(offset) } -fn rwlock_get_id<'tcx>( +fn rwlock_get_data<'tcx>( ecx: &mut MiriInterpCx<'tcx>, rwlock_ptr: &OpTy<'tcx>, -) -> InterpResult<'tcx, RwLockId> { +) -> InterpResult<'tcx, RwLockData> { let rwlock = ecx.deref_pointer(rwlock_ptr)?; - let address = rwlock.ptr().addr().bytes(); + let init_offset = rwlock_init_offset(ecx)?; - let id = ecx.rwlock_get_or_create_id(&rwlock, rwlock_id_offset(ecx)?, |_| { - interp_ok(Some(Box::new(AdditionalRwLockData { address }))) - })?; - - // Check that the rwlock has not been moved since last use. - let data = ecx - .rwlock_get_data::(id) - .expect("data should always exist for pthreads"); - if data.address != address { - throw_ub_format!("pthread_rwlock_t can't be moved after first use") + if let Some(data) = sync_get_data::(ecx, &rwlock, init_offset, "pthread_rwlock_t")? + { + interp_ok(data) + } else { + let id = ecx.rwlock_create(); + let data = RwLockData { id }; + sync_create(ecx, &rwlock, init_offset, data)?; + interp_ok(data) } - - interp_ok(id) } // # pthread_condattr_t @@ -640,7 +657,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { ) -> InterpResult<'tcx> { let this = self.eval_context_mut(); - let id = rwlock_get_id(this, rwlock_op)?; + let id = rwlock_get_data(this, rwlock_op)?.id; if this.rwlock_is_write_locked(id) { this.rwlock_enqueue_and_block_reader(id, Scalar::from_i32(0), dest.clone()); @@ -655,7 +672,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn pthread_rwlock_tryrdlock(&mut self, rwlock_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); - let id = rwlock_get_id(this, rwlock_op)?; + let id = rwlock_get_data(this, rwlock_op)?.id; if this.rwlock_is_write_locked(id) { interp_ok(Scalar::from_i32(this.eval_libc_i32("EBUSY"))) @@ -672,7 +689,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { ) -> InterpResult<'tcx> { let this = self.eval_context_mut(); - let id = rwlock_get_id(this, rwlock_op)?; + let id = rwlock_get_data(this, rwlock_op)?.id; if this.rwlock_is_locked(id) { // Note: this will deadlock if the lock is already locked by this @@ -699,7 +716,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn pthread_rwlock_trywrlock(&mut self, rwlock_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); - let id = rwlock_get_id(this, rwlock_op)?; + let id = rwlock_get_data(this, rwlock_op)?.id; if this.rwlock_is_locked(id) { interp_ok(Scalar::from_i32(this.eval_libc_i32("EBUSY"))) @@ -712,7 +729,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn pthread_rwlock_unlock(&mut self, rwlock_op: &OpTy<'tcx>) -> InterpResult<'tcx, ()> { let this = self.eval_context_mut(); - let id = rwlock_get_id(this, rwlock_op)?; + let id = rwlock_get_data(this, rwlock_op)?.id; #[allow(clippy::if_same_then_else)] if this.rwlock_reader_unlock(id)? || this.rwlock_writer_unlock(id)? { @@ -727,7 +744,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Reading the field also has the side-effect that we detect double-`destroy` // since we make the field unint below. - let id = rwlock_get_id(this, rwlock_op)?; + let id = rwlock_get_data(this, rwlock_op)?.id; if this.rwlock_is_locked(id) { throw_ub_format!("destroyed a locked rwlock"); diff --git a/src/tools/miri/tests/fail-dep/concurrency/libx_pthread_rwlock_moved.rs b/src/tools/miri/tests/fail-dep/concurrency/libx_pthread_rwlock_moved.rs index 540729962a9..6af19b7df9b 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/libx_pthread_rwlock_moved.rs +++ b/src/tools/miri/tests/fail-dep/concurrency/libx_pthread_rwlock_moved.rs @@ -9,6 +9,6 @@ fn main() { // Move rwlock let mut rw2 = rw; - libc::pthread_rwlock_unlock(&mut rw2 as *mut _); //~ ERROR: pthread_rwlock_t can't be moved after first use + libc::pthread_rwlock_unlock(&mut rw2 as *mut _); //~ ERROR: can't be moved after first use } } diff --git a/src/tools/miri/tests/fail-dep/concurrency/libx_pthread_rwlock_moved.stderr b/src/tools/miri/tests/fail-dep/concurrency/libx_pthread_rwlock_moved.stderr index ce08fa8159c..fbc9119f110 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/libx_pthread_rwlock_moved.stderr +++ b/src/tools/miri/tests/fail-dep/concurrency/libx_pthread_rwlock_moved.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: pthread_rwlock_t can't be moved after first use +error: Undefined Behavior: `pthread_rwlock_t` can't be moved after first use --> tests/fail-dep/concurrency/libx_pthread_rwlock_moved.rs:LL:CC | LL | libc::pthread_rwlock_unlock(&mut rw2 as *mut _); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pthread_rwlock_t can't be moved after first use + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `pthread_rwlock_t` can't be moved after first use | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information From 17f0aed84c2856e088a26bb337092a195c1ee53b Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 12 Oct 2024 14:24:23 +0200 Subject: [PATCH 285/357] pthread_cond: also store ID outside addressable memory --- src/tools/miri/src/concurrency/sync.rs | 70 +----- src/tools/miri/src/shims/unix/sync.rs | 201 +++++++++--------- .../libc_pthread_cond_move.init.stderr | 4 +- .../concurrency/libc_pthread_cond_move.rs | 4 +- ...thread_cond_move.static_initializer.stderr | 4 +- 5 files changed, 110 insertions(+), 173 deletions(-) diff --git a/src/tools/miri/src/concurrency/sync.rs b/src/tools/miri/src/concurrency/sync.rs index b22684faec4..2901cb9ccb0 100644 --- a/src/tools/miri/src/concurrency/sync.rs +++ b/src/tools/miri/src/concurrency/sync.rs @@ -1,4 +1,3 @@ -use std::any::Any; use std::collections::VecDeque; use std::collections::hash_map::Entry; use std::ops::Not; @@ -129,9 +128,6 @@ struct Condvar { /// Contains the clock of the last thread to /// perform a condvar-signal. clock: VClock, - - /// Additional data that can be set by shim implementations. - data: Option>, } /// The futex state. @@ -220,32 +216,6 @@ pub(super) trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { }) } - /// Eagerly creates a Miri sync structure. - /// - /// `create_id` will store the index of the sync_structure in the memory pointed to by - /// `lock_op`, so that future calls to `get_or_create_id` will see it as initialized. - /// - `lock_op` must hold a pointer to the sync structure. - /// - `lock_layout` must be the memory layout of the sync structure. - /// - `offset` must be the offset inside the sync structure where its miri id will be stored. - /// - `get_objs` is described in `get_or_create_id`. - /// - `obj` must be the new sync object. - fn create_id( - &mut self, - lock: &MPlaceTy<'tcx>, - offset: u64, - get_objs: impl for<'a> Fn(&'a mut MiriInterpCx<'tcx>) -> &'a mut IndexVec, - obj: T, - ) -> InterpResult<'tcx, Id> { - let this = self.eval_context_mut(); - let offset = Size::from_bytes(offset); - assert!(lock.layout.size >= offset + this.machine.layouts.u32.size); - let id_place = lock.offset(offset, this.machine.layouts.u32, this)?; - - let new_index = get_objs(this).push(obj); - this.write_scalar(Scalar::from_u32(new_index.to_u32()), &id_place)?; - interp_ok(new_index) - } - fn condvar_reacquire_mutex( &mut self, mutex: MutexId, @@ -303,45 +273,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } /// Eagerly create and initialize a new condvar. - fn condvar_create( - &mut self, - condvar: &MPlaceTy<'tcx>, - offset: u64, - data: Option>, - ) -> InterpResult<'tcx, CondvarId> { + fn condvar_create(&mut self) -> CondvarId { let this = self.eval_context_mut(); - this.create_id(condvar, offset, |ecx| &mut ecx.machine.sync.condvars, Condvar { - data, - ..Default::default() - }) - } - - fn condvar_get_or_create_id( - &mut self, - lock: &MPlaceTy<'tcx>, - offset: u64, - initialize_data: impl for<'a> FnOnce( - &'a mut MiriInterpCx<'tcx>, - ) -> InterpResult<'tcx, Option>>, - ) -> InterpResult<'tcx, CondvarId> { - let this = self.eval_context_mut(); - this.get_or_create_id( - lock, - offset, - |ecx| &mut ecx.machine.sync.condvars, - |ecx| initialize_data(ecx).map(|data| Condvar { data, ..Default::default() }), - )? - .ok_or_else(|| err_ub_format!("condvar has invalid ID")) - .into() - } - - /// Retrieve the additional data stored for a condvar. - fn condvar_get_data<'a, T: 'static>(&'a mut self, id: CondvarId) -> Option<&'a T> - where - 'tcx: 'a, - { - let this = self.eval_context_ref(); - this.machine.sync.condvars[id].data.as_deref().and_then(|p| p.downcast_ref::()) + this.machine.sync.condvars.push(Default::default()) } #[inline] diff --git a/src/tools/miri/src/shims/unix/sync.rs b/src/tools/miri/src/shims/unix/sync.rs index 1a4c4094c5d..1942f25996e 100644 --- a/src/tools/miri/src/shims/unix/sync.rs +++ b/src/tools/miri/src/shims/unix/sync.rs @@ -37,7 +37,7 @@ fn bytewise_equal_atomic_relaxed<'tcx>( /// If `init` is set to this, we consider the primitive initialized. const INIT_COOKIE: u32 = 0xcafe_affe; -fn sync_create<'tcx, T: 'static + Copy>( +fn sync_init<'tcx, T: 'static + Copy>( ecx: &mut MiriInterpCx<'tcx>, primitive: &MPlaceTy<'tcx>, init_offset: Size, @@ -137,6 +137,28 @@ fn mutexattr_set_kind<'tcx>( /// field *not* PTHREAD_MUTEX_DEFAULT but this special flag. const PTHREAD_MUTEX_KIND_UNCHANGED: i32 = 0x8000000; +/// Translates the mutex kind from what is stored in pthread_mutexattr_t to our enum. +fn mutexattr_translate_kind<'tcx>( + ecx: &MiriInterpCx<'tcx>, + kind: i32, +) -> InterpResult<'tcx, MutexKind> { + interp_ok(if kind == (ecx.eval_libc_i32("PTHREAD_MUTEX_NORMAL")) { + MutexKind::Normal + } else if kind == ecx.eval_libc_i32("PTHREAD_MUTEX_ERRORCHECK") { + MutexKind::ErrorCheck + } else if kind == ecx.eval_libc_i32("PTHREAD_MUTEX_RECURSIVE") { + MutexKind::Recursive + } else if kind == ecx.eval_libc_i32("PTHREAD_MUTEX_DEFAULT") + || kind == PTHREAD_MUTEX_KIND_UNCHANGED + { + // We check this *last* since PTHREAD_MUTEX_DEFAULT may be numerically equal to one of the + // others, and we want an explicit `mutexattr_settype` to work as expected. + MutexKind::Default + } else { + throw_unsup_format!("unsupported type of mutex: {kind}"); + }) +} + // # pthread_mutex_t // We store some data directly inside the type, ignoring the platform layout: // - init: u32 @@ -170,7 +192,7 @@ fn mutex_init_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> InterpResult<'tcx, Size> let offset = Size::from_bytes(offset); // Sanity-check this against PTHREAD_MUTEX_INITIALIZER (but only once): - // the `init` field must start out not equal to MUTEX_INIT_COOKIE. + // the `init` field must start out not equal to INIT_COOKIE. static SANITY: AtomicBool = AtomicBool::new(false); if !SANITY.swap(true, Ordering::Relaxed) { let check_static_initializer = |name| { @@ -208,7 +230,7 @@ fn mutex_create<'tcx>( let mutex = ecx.deref_pointer(mutex_ptr)?; let id = ecx.mutex_create(); let data = MutexData { id, kind }; - sync_create(ecx, &mutex, mutex_init_offset(ecx)?, data)?; + sync_init(ecx, &mutex, mutex_init_offset(ecx)?, data)?; interp_ok(data) } @@ -259,38 +281,13 @@ fn mutex_kind_from_static_initializer<'tcx>( }, _ => {} } - throw_unsup_format!("unsupported static initializer used for `pthread_mutex_t"); -} - -/// Translates the mutex kind from what is stored in pthread_mutexattr_t to our enum. -fn mutex_translate_kind<'tcx>( - ecx: &MiriInterpCx<'tcx>, - kind: i32, -) -> InterpResult<'tcx, MutexKind> { - interp_ok(if kind == (ecx.eval_libc_i32("PTHREAD_MUTEX_NORMAL")) { - MutexKind::Normal - } else if kind == ecx.eval_libc_i32("PTHREAD_MUTEX_ERRORCHECK") { - MutexKind::ErrorCheck - } else if kind == ecx.eval_libc_i32("PTHREAD_MUTEX_RECURSIVE") { - MutexKind::Recursive - } else if kind == ecx.eval_libc_i32("PTHREAD_MUTEX_DEFAULT") - || kind == PTHREAD_MUTEX_KIND_UNCHANGED - { - // We check this *last* since PTHREAD_MUTEX_DEFAULT may be numerically equal to one of the - // others, and we want an explicit `mutexattr_settype` to work as expected. - MutexKind::Default - } else { - throw_unsup_format!("unsupported type of mutex: {kind}"); - }) + throw_unsup_format!("unsupported static initializer used for `pthread_mutex_t`"); } // # pthread_rwlock_t // We store some data directly inside the type, ignoring the platform layout: // - init: u32 -/// If `init` is set to this, we consider the rwlock initialized. -const RWLOCK_INIT_COOKIE: u32 = 0xcafe_affe; - #[derive(Debug, Copy, Clone)] /// Additional data that we attach with each rwlock instance. pub struct RwLockData { @@ -307,14 +304,14 @@ fn rwlock_init_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> InterpResult<'tcx, Size let offset = Size::from_bytes(offset); // Sanity-check this against PTHREAD_RWLOCK_INITIALIZER (but only once): - // the `init` field must start out not equal to RWLOCK_INIT_COOKIE. + // the `init` field must start out not equal to INIT_COOKIE. static SANITY: AtomicBool = AtomicBool::new(false); if !SANITY.swap(true, Ordering::Relaxed) { let static_initializer = ecx.eval_path(&["libc", "PTHREAD_RWLOCK_INITIALIZER"]); let init_field = static_initializer.offset(offset, ecx.machine.layouts.u32, ecx).unwrap(); let init = ecx.read_scalar(&init_field).unwrap().to_u32().unwrap(); assert_ne!( - init, RWLOCK_INIT_COOKIE, + init, INIT_COOKIE, "PTHREAD_RWLOCK_INITIALIZER is incompatible with our initialization cookie" ); } @@ -333,9 +330,16 @@ fn rwlock_get_data<'tcx>( { interp_ok(data) } else { + if !bytewise_equal_atomic_relaxed( + ecx, + &rwlock, + &ecx.eval_path(&["libc", "PTHREAD_RWLOCK_INITIALIZER"]), + )? { + throw_unsup_format!("unsupported static initializer used for `pthread_rwlock_t`"); + } let id = ecx.rwlock_create(); let data = RwLockData { id }; - sync_create(ecx, &rwlock, init_offset, data)?; + sync_init(ecx, &rwlock, init_offset, data)?; interp_ok(data) } } @@ -366,19 +370,6 @@ fn condattr_get_clock_id<'tcx>( .to_i32() } -fn cond_translate_clock_id<'tcx>( - ecx: &MiriInterpCx<'tcx>, - raw_id: i32, -) -> InterpResult<'tcx, ClockId> { - interp_ok(if raw_id == ecx.eval_libc_i32("CLOCK_REALTIME") { - ClockId::Realtime - } else if raw_id == ecx.eval_libc_i32("CLOCK_MONOTONIC") { - ClockId::Monotonic - } else { - throw_unsup_format!("unsupported clock id: {raw_id}"); - }) -} - fn condattr_set_clock_id<'tcx>( ecx: &mut MiriInterpCx<'tcx>, attr_ptr: &OpTy<'tcx>, @@ -393,30 +384,43 @@ fn condattr_set_clock_id<'tcx>( ) } +/// Translates the clock from what is stored in pthread_condattr_t to our enum. +fn condattr_translate_clock_id<'tcx>( + ecx: &MiriInterpCx<'tcx>, + raw_id: i32, +) -> InterpResult<'tcx, ClockId> { + interp_ok(if raw_id == ecx.eval_libc_i32("CLOCK_REALTIME") { + ClockId::Realtime + } else if raw_id == ecx.eval_libc_i32("CLOCK_MONOTONIC") { + ClockId::Monotonic + } else { + throw_unsup_format!("unsupported clock id: {raw_id}"); + }) +} + // # pthread_cond_t // We store some data directly inside the type, ignoring the platform layout: -// - id: u32 +// - init: u32 -fn cond_id_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> InterpResult<'tcx, u64> { +fn cond_init_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> InterpResult<'tcx, Size> { let offset = match &*ecx.tcx.sess.target.os { "linux" | "illumos" | "solaris" | "freebsd" | "android" => 0, - // macOS stores a signature in the first bytes, so we have to move to offset 4. + // macOS stores a signature in the first bytes, so we move to offset 4. "macos" => 4, os => throw_unsup_format!("`pthread_cond` is not supported on {os}"), }; + let offset = Size::from_bytes(offset); // Sanity-check this against PTHREAD_COND_INITIALIZER (but only once): - // the id must start out as 0. + // the `init` field must start out not equal to INIT_COOKIE. static SANITY: AtomicBool = AtomicBool::new(false); if !SANITY.swap(true, Ordering::Relaxed) { let static_initializer = ecx.eval_path(&["libc", "PTHREAD_COND_INITIALIZER"]); - let id_field = static_initializer - .offset(Size::from_bytes(offset), ecx.machine.layouts.u32, ecx) - .unwrap(); - let id = ecx.read_scalar(&id_field).unwrap().to_u32().unwrap(); - assert_eq!( - id, 0, - "PTHREAD_COND_INITIALIZER is incompatible with our pthread_cond layout: id is not 0" + let init_field = static_initializer.offset(offset, ecx.machine.layouts.u32, ecx).unwrap(); + let init = ecx.read_scalar(&init_field).unwrap().to_u32().unwrap(); + assert_ne!( + init, INIT_COOKIE, + "PTHREAD_COND_INITIALIZER is incompatible with our initialization cookie" ); } @@ -429,36 +433,45 @@ enum ClockId { Monotonic, } -#[derive(Debug)] +#[derive(Debug, Copy, Clone)] /// Additional data that we attach with each cond instance. -struct AdditionalCondData { - /// The address of the cond. - address: u64, - - /// The clock id of the cond. - clock_id: ClockId, +struct CondData { + id: CondvarId, + clock: ClockId, } -fn cond_get_id<'tcx>( +fn cond_create<'tcx>( ecx: &mut MiriInterpCx<'tcx>, cond_ptr: &OpTy<'tcx>, -) -> InterpResult<'tcx, CondvarId> { + clock: ClockId, +) -> InterpResult<'tcx, CondData> { let cond = ecx.deref_pointer(cond_ptr)?; - let address = cond.ptr().addr().bytes(); - let id = ecx.condvar_get_or_create_id(&cond, cond_id_offset(ecx)?, |_ecx| { + let id = ecx.condvar_create(); + let data = CondData { id, clock }; + sync_init(ecx, &cond, cond_init_offset(ecx)?, data)?; + interp_ok(data) +} + +fn cond_get_data<'tcx>( + ecx: &mut MiriInterpCx<'tcx>, + cond_ptr: &OpTy<'tcx>, +) -> InterpResult<'tcx, CondData> { + let cond = ecx.deref_pointer(cond_ptr)?; + let init_offset = cond_init_offset(ecx)?; + + if let Some(data) = sync_get_data::(ecx, &cond, init_offset, "pthread_cond_t")? { + interp_ok(data) + } else { // This used the static initializer. The clock there is always CLOCK_REALTIME. - interp_ok(Some(Box::new(AdditionalCondData { address, clock_id: ClockId::Realtime }))) - })?; - - // Check that the mutex has not been moved since last use. - let data = ecx - .condvar_get_data::(id) - .expect("data should always exist for pthreads"); - if data.address != address { - throw_ub_format!("pthread_cond_t can't be moved after first use") + if !bytewise_equal_atomic_relaxed( + ecx, + &cond, + &ecx.eval_path(&["libc", "PTHREAD_COND_INITIALIZER"]), + )? { + throw_unsup_format!("unsupported static initializer used for `pthread_cond_t`"); + } + cond_create(ecx, cond_ptr, ClockId::Realtime) } - - interp_ok(id) } impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} @@ -531,7 +544,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let kind = if this.ptr_is_null(attr)? { MutexKind::Default } else { - mutex_translate_kind(this, mutexattr_get_kind(this, attr_op)?)? + mutexattr_translate_kind(this, mutexattr_get_kind(this, attr_op)?)? }; mutex_create(this, mutex_op, kind)?; @@ -839,29 +852,23 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } else { condattr_get_clock_id(this, attr_op)? }; - let clock_id = cond_translate_clock_id(this, clock_id)?; + let clock_id = condattr_translate_clock_id(this, clock_id)?; - let cond = this.deref_pointer(cond_op)?; - let address = cond.ptr().addr().bytes(); - this.condvar_create( - &cond, - cond_id_offset(this)?, - Some(Box::new(AdditionalCondData { address, clock_id })), - )?; + cond_create(this, cond_op, clock_id)?; interp_ok(()) } fn pthread_cond_signal(&mut self, cond_op: &OpTy<'tcx>) -> InterpResult<'tcx, ()> { let this = self.eval_context_mut(); - let id = cond_get_id(this, cond_op)?; + let id = cond_get_data(this, cond_op)?.id; this.condvar_signal(id)?; interp_ok(()) } fn pthread_cond_broadcast(&mut self, cond_op: &OpTy<'tcx>) -> InterpResult<'tcx, ()> { let this = self.eval_context_mut(); - let id = cond_get_id(this, cond_op)?; + let id = cond_get_data(this, cond_op)?.id; while this.condvar_signal(id)? {} interp_ok(()) } @@ -874,11 +881,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { ) -> InterpResult<'tcx> { let this = self.eval_context_mut(); - let id = cond_get_id(this, cond_op)?; + let data = cond_get_data(this, cond_op)?; let mutex_id = mutex_get_data(this, mutex_op)?.id; this.condvar_wait( - id, + data.id, mutex_id, None, // no timeout Scalar::from_i32(0), @@ -898,14 +905,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { ) -> InterpResult<'tcx> { let this = self.eval_context_mut(); - let id = cond_get_id(this, cond_op)?; + let data = cond_get_data(this, cond_op)?; let mutex_id = mutex_get_data(this, mutex_op)?.id; // Extract the timeout. - let clock_id = this - .condvar_get_data::(id) - .expect("additional data should always be present for pthreads") - .clock_id; let duration = match this .read_timespec(&this.deref_pointer_as(abstime_op, this.libc_ty_layout("timespec"))?)? { @@ -916,7 +919,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { return interp_ok(()); } }; - let timeout_clock = match clock_id { + let timeout_clock = match data.clock { ClockId::Realtime => { this.check_no_isolation("`pthread_cond_timedwait` with `CLOCK_REALTIME`")?; TimeoutClock::RealTime @@ -925,7 +928,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { }; this.condvar_wait( - id, + data.id, mutex_id, Some((timeout_clock, TimeoutAnchor::Absolute, duration)), Scalar::from_i32(0), @@ -941,7 +944,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Reading the field also has the side-effect that we detect double-`destroy` // since we make the field unint below. - let id = cond_get_id(this, cond_op)?; + let id = cond_get_data(this, cond_op)?.id; if this.condvar_is_awaited(id) { throw_ub_format!("destroying an awaited conditional variable"); } diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_cond_move.init.stderr b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_cond_move.init.stderr index 6e90c490a23..9a8ddc0b523 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_cond_move.init.stderr +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_cond_move.init.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: pthread_cond_t can't be moved after first use +error: Undefined Behavior: `pthread_cond_t` can't be moved after first use --> tests/fail-dep/concurrency/libc_pthread_cond_move.rs:LL:CC | LL | libc::pthread_cond_destroy(cond2.as_mut_ptr()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pthread_cond_t can't be moved after first use + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `pthread_cond_t` can't be moved after first use | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_cond_move.rs b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_cond_move.rs index 8fd0caac751..4db904ab5e2 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_cond_move.rs +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_cond_move.rs @@ -18,7 +18,7 @@ fn check() { // move pthread_cond_t let mut cond2 = cond; - libc::pthread_cond_destroy(cond2.as_mut_ptr()); //~[init] ERROR: pthread_cond_t can't be moved after first use + libc::pthread_cond_destroy(cond2.as_mut_ptr()); //~[init] ERROR: can't be moved after first use } } @@ -32,6 +32,6 @@ fn check() { // move pthread_cond_t let mut cond2 = cond; - libc::pthread_cond_destroy(&mut cond2 as *mut _); //~[static_initializer] ERROR: pthread_cond_t can't be moved after first use + libc::pthread_cond_destroy(&mut cond2 as *mut _); //~[static_initializer] ERROR: can't be moved after first use } } diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_cond_move.static_initializer.stderr b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_cond_move.static_initializer.stderr index ba726ac7f38..8a7c0dee127 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_cond_move.static_initializer.stderr +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_cond_move.static_initializer.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: pthread_cond_t can't be moved after first use +error: Undefined Behavior: `pthread_cond_t` can't be moved after first use --> tests/fail-dep/concurrency/libc_pthread_cond_move.rs:LL:CC | LL | libc::pthread_cond_destroy(&mut cond2 as *mut _); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pthread_cond_t can't be moved after first use + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `pthread_cond_t` can't be moved after first use | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information From 8f342edd7c77108576b0be5568280ad52d6fd621 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 12 Oct 2024 14:36:14 +0200 Subject: [PATCH 286/357] macOS os_unfair_lock: also store ID outside addressable memory --- src/tools/miri/src/concurrency/sync.rs | 50 ++++++--------------- src/tools/miri/src/machine.rs | 6 +++ src/tools/miri/src/shims/unix/macos/sync.rs | 19 ++++++-- src/tools/miri/src/shims/unix/sync.rs | 16 +++---- 4 files changed, 42 insertions(+), 49 deletions(-) diff --git a/src/tools/miri/src/concurrency/sync.rs b/src/tools/miri/src/concurrency/sync.rs index 2901cb9ccb0..015fe2727f1 100644 --- a/src/tools/miri/src/concurrency/sync.rs +++ b/src/tools/miri/src/concurrency/sync.rs @@ -236,48 +236,26 @@ pub(super) trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { } } +impl SynchronizationObjects { + pub fn mutex_create(&mut self) -> MutexId { + self.mutexes.push(Default::default()) + } + + pub fn rwlock_create(&mut self) -> RwLockId { + self.rwlocks.push(Default::default()) + } + + pub fn condvar_create(&mut self) -> CondvarId { + self.condvars.push(Default::default()) + } +} + // Public interface to synchronization primitives. Please note that in most // cases, the function calls are infallible and it is the client's (shim // implementation's) responsibility to detect and deal with erroneous // situations. impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { - /// Eagerly create and initialize a new mutex. - fn mutex_create(&mut self) -> MutexId { - let this = self.eval_context_mut(); - this.machine.sync.mutexes.push(Default::default()) - } - - /// Lazily create a new mutex. - /// `initialize_data` must return any additional data that a user wants to associate with the mutex. - fn mutex_get_or_create_id( - &mut self, - lock: &MPlaceTy<'tcx>, - offset: u64, - ) -> InterpResult<'tcx, MutexId> { - let this = self.eval_context_mut(); - this.get_or_create_id( - lock, - offset, - |ecx| &mut ecx.machine.sync.mutexes, - |_ecx| interp_ok(Mutex::default()), - )? - .ok_or_else(|| err_ub_format!("mutex has invalid ID")) - .into() - } - - /// Eagerly create and initialize a new rwlock. - fn rwlock_create(&mut self) -> RwLockId { - let this = self.eval_context_mut(); - this.machine.sync.rwlocks.push(Default::default()) - } - - /// Eagerly create and initialize a new condvar. - fn condvar_create(&mut self) -> CondvarId { - let this = self.eval_context_mut(); - this.machine.sync.condvars.push(Default::default()) - } - #[inline] /// Get the id of the thread that currently owns this lock. fn mutex_get_owner(&mut self, id: MutexId) -> ThreadId { diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 60d096b92f2..d5734ea3c83 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -362,6 +362,12 @@ impl VisitProvenance for AllocExtra<'_> { } } +impl<'tcx> AllocExtra<'tcx> { + pub fn get_sync(&self, offset: Size) -> Option<&T> { + self.sync.get(&offset).and_then(|s| s.downcast_ref::()) + } +} + /// Precomputed layouts of primitive types pub struct PrimitiveLayouts<'tcx> { pub unit: TyAndLayout<'tcx>, diff --git a/src/tools/miri/src/shims/unix/macos/sync.rs b/src/tools/miri/src/shims/unix/macos/sync.rs index 1efe393a0e2..f135a0df0a7 100644 --- a/src/tools/miri/src/shims/unix/macos/sync.rs +++ b/src/tools/miri/src/shims/unix/macos/sync.rs @@ -12,15 +12,26 @@ use crate::*; +struct LockData { + id: MutexId, +} + impl<'tcx> EvalContextExtPriv<'tcx> for crate::MiriInterpCx<'tcx> {} trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { fn os_unfair_lock_getid(&mut self, lock_ptr: &OpTy<'tcx>) -> InterpResult<'tcx, MutexId> { let this = self.eval_context_mut(); let lock = this.deref_pointer(lock_ptr)?; - // os_unfair_lock holds a 32-bit value, is initialized with zero and - // must be assumed to be opaque. Therefore, we can just store our - // internal mutex ID in the structure without anyone noticing. - this.mutex_get_or_create_id(&lock, /* offset */ 0) + // We store the mutex ID in the `sync` metadata. This means that when the lock is moved, + // that's just implicitly creating a new lock at the new location. + let (alloc, offset, _) = this.ptr_get_alloc_id(lock.ptr(), 0)?; + let (alloc_extra, machine) = this.get_alloc_extra_mut(alloc)?; + if let Some(data) = alloc_extra.get_sync::(offset) { + interp_ok(data.id) + } else { + let id = machine.sync.mutex_create(); + alloc_extra.sync.insert(offset, Box::new(LockData { id })); + interp_ok(id) + } } } diff --git a/src/tools/miri/src/shims/unix/sync.rs b/src/tools/miri/src/shims/unix/sync.rs index 1942f25996e..abc2980440f 100644 --- a/src/tools/miri/src/shims/unix/sync.rs +++ b/src/tools/miri/src/shims/unix/sync.rs @@ -80,11 +80,9 @@ fn sync_get_data<'tcx, T: 'static + Copy>( // If it is initialized, it must be found in the "sync primitive" table, // or else it has been moved illegally. let (alloc, offset, _) = ecx.ptr_get_alloc_id(primitive.ptr(), 0)?; - let (alloc_extra, _machine) = ecx.get_alloc_extra_mut(alloc)?; + let alloc_extra = ecx.get_alloc_extra(alloc)?; let data = alloc_extra - .sync - .get(&offset) - .and_then(|s| s.downcast_ref::()) + .get_sync::(offset) .ok_or_else(|| err_ub_format!("`{name}` can't be moved after first use"))?; interp_ok(Some(*data)) } else { @@ -174,7 +172,7 @@ enum MutexKind { #[derive(Debug, Clone, Copy)] /// Additional data that we attach with each mutex instance. -pub struct MutexData { +struct MutexData { id: MutexId, kind: MutexKind, } @@ -228,7 +226,7 @@ fn mutex_create<'tcx>( kind: MutexKind, ) -> InterpResult<'tcx, MutexData> { let mutex = ecx.deref_pointer(mutex_ptr)?; - let id = ecx.mutex_create(); + let id = ecx.machine.sync.mutex_create(); let data = MutexData { id, kind }; sync_init(ecx, &mutex, mutex_init_offset(ecx)?, data)?; interp_ok(data) @@ -290,7 +288,7 @@ fn mutex_kind_from_static_initializer<'tcx>( #[derive(Debug, Copy, Clone)] /// Additional data that we attach with each rwlock instance. -pub struct RwLockData { +struct RwLockData { id: RwLockId, } @@ -337,7 +335,7 @@ fn rwlock_get_data<'tcx>( )? { throw_unsup_format!("unsupported static initializer used for `pthread_rwlock_t`"); } - let id = ecx.rwlock_create(); + let id = ecx.machine.sync.rwlock_create(); let data = RwLockData { id }; sync_init(ecx, &rwlock, init_offset, data)?; interp_ok(data) @@ -446,7 +444,7 @@ fn cond_create<'tcx>( clock: ClockId, ) -> InterpResult<'tcx, CondData> { let cond = ecx.deref_pointer(cond_ptr)?; - let id = ecx.condvar_create(); + let id = ecx.machine.sync.condvar_create(); let data = CondData { id, clock }; sync_init(ecx, &cond, cond_init_offset(ecx)?, data)?; interp_ok(data) From 0f7d321684e3cae9872d1a9e7d22119ef418fd75 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 12 Oct 2024 15:02:08 +0200 Subject: [PATCH 287/357] Windows InitOnce: also store ID outside addressable memory --- src/tools/miri/src/concurrency/init_once.rs | 17 --- src/tools/miri/src/concurrency/sync.rs | 145 ++++++++++---------- src/tools/miri/src/machine.rs | 6 - src/tools/miri/src/shims/unix/sync.rs | 90 +++--------- src/tools/miri/src/shims/windows/sync.rs | 21 ++- 5 files changed, 114 insertions(+), 165 deletions(-) diff --git a/src/tools/miri/src/concurrency/init_once.rs b/src/tools/miri/src/concurrency/init_once.rs index 488edc91dff..c3c04428c94 100644 --- a/src/tools/miri/src/concurrency/init_once.rs +++ b/src/tools/miri/src/concurrency/init_once.rs @@ -2,7 +2,6 @@ use std::collections::VecDeque; use rustc_index::Idx; -use super::sync::EvalContextExtPriv as _; use super::vector_clock::VClock; use crate::*; @@ -27,22 +26,6 @@ pub(super) struct InitOnce { impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { - fn init_once_get_or_create_id( - &mut self, - lock: &MPlaceTy<'tcx>, - offset: u64, - ) -> InterpResult<'tcx, InitOnceId> { - let this = self.eval_context_mut(); - this.get_or_create_id( - lock, - offset, - |ecx| &mut ecx.machine.sync.init_onces, - |_| interp_ok(Default::default()), - )? - .ok_or_else(|| err_ub_format!("init_once has invalid ID")) - .into() - } - #[inline] fn init_once_status(&mut self, id: InitOnceId) -> InitOnceStatus { let this = self.eval_context_ref(); diff --git a/src/tools/miri/src/concurrency/sync.rs b/src/tools/miri/src/concurrency/sync.rs index 015fe2727f1..e42add0d509 100644 --- a/src/tools/miri/src/concurrency/sync.rs +++ b/src/tools/miri/src/concurrency/sync.rs @@ -11,11 +11,6 @@ use super::init_once::InitOnce; use super::vector_clock::VClock; use crate::*; -pub trait SyncId { - fn from_u32(id: u32) -> Self; - fn to_u32(&self) -> u32; -} - /// We cannot use the `newtype_index!` macro because we have to use 0 as a /// sentinel value meaning that the identifier is not assigned. This is because /// the pthreads static initializers initialize memory with zeros (see the @@ -27,16 +22,6 @@ macro_rules! declare_id { #[derive(Clone, Copy, Debug, PartialOrd, Ord, PartialEq, Eq, Hash)] pub struct $name(std::num::NonZero); - impl $crate::concurrency::sync::SyncId for $name { - // Panics if `id == 0`. - fn from_u32(id: u32) -> Self { - Self(std::num::NonZero::new(id).unwrap()) - } - fn to_u32(&self) -> u32 { - self.0.get() - } - } - impl $crate::VisitProvenance for $name { fn visit_provenance(&self, _visit: &mut VisitWith<'_>) {} } @@ -55,12 +40,6 @@ macro_rules! declare_id { usize::try_from(self.0.get() - 1).unwrap() } } - - impl $name { - pub fn to_u32_scalar(&self) -> Scalar { - Scalar::from_u32(self.0.get()) - } - } }; } pub(super) use declare_id; @@ -166,56 +145,6 @@ pub struct SynchronizationObjects { // Private extension trait for local helper methods impl<'tcx> EvalContextExtPriv<'tcx> for crate::MiriInterpCx<'tcx> {} pub(super) trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { - /// Lazily initialize the ID of this Miri sync structure. - /// If memory stores '0', that indicates uninit and we generate a new instance. - /// Returns `None` if memory stores a non-zero invalid ID. - /// - /// `get_objs` must return the `IndexVec` that stores all the objects of this type. - /// `create_obj` must create the new object if initialization is needed. - #[inline] - fn get_or_create_id( - &mut self, - lock: &MPlaceTy<'tcx>, - offset: u64, - get_objs: impl for<'a> Fn(&'a mut MiriInterpCx<'tcx>) -> &'a mut IndexVec, - create_obj: impl for<'a> FnOnce(&'a mut MiriInterpCx<'tcx>) -> InterpResult<'tcx, T>, - ) -> InterpResult<'tcx, Option> { - let this = self.eval_context_mut(); - let offset = Size::from_bytes(offset); - assert!(lock.layout.size >= offset + this.machine.layouts.u32.size); - let id_place = lock.offset(offset, this.machine.layouts.u32, this)?; - let next_index = get_objs(this).next_index(); - - // Since we are lazy, this update has to be atomic. - let (old, success) = this - .atomic_compare_exchange_scalar( - &id_place, - &ImmTy::from_uint(0u32, this.machine.layouts.u32), - Scalar::from_u32(next_index.to_u32()), - AtomicRwOrd::Relaxed, // deliberately *no* synchronization - AtomicReadOrd::Relaxed, - false, - )? - .to_scalar_pair(); - - interp_ok(if success.to_bool().expect("compare_exchange's second return value is a bool") { - // We set the in-memory ID to `next_index`, now also create this object in the machine - // state. - let obj = create_obj(this)?; - let new_index = get_objs(this).push(obj); - assert_eq!(next_index, new_index); - Some(new_index) - } else { - let id = Id::from_u32(old.to_u32().expect("layout is u32")); - if get_objs(this).get(id).is_none() { - // The in-memory ID is invalid. - None - } else { - Some(id) - } - }) - } - fn condvar_reacquire_mutex( &mut self, mutex: MutexId, @@ -248,6 +177,80 @@ impl SynchronizationObjects { pub fn condvar_create(&mut self) -> CondvarId { self.condvars.push(Default::default()) } + + pub fn init_once_create(&mut self) -> InitOnceId { + self.init_onces.push(Default::default()) + } +} + +impl<'tcx> AllocExtra<'tcx> { + pub fn get_sync(&self, offset: Size) -> Option<&T> { + self.sync.get(&offset).and_then(|s| s.downcast_ref::()) + } +} + +/// We designate an `init`` field in all primitives. +/// If `init` is set to this, we consider the primitive initialized. +pub const LAZY_INIT_COOKIE: u32 = 0xcafe_affe; + +/// Helper for lazily initialized `alloc_extra.sync` data: +/// this forces an immediate init. +pub fn lazy_sync_init<'tcx, T: 'static + Copy>( + ecx: &mut MiriInterpCx<'tcx>, + primitive: &MPlaceTy<'tcx>, + init_offset: Size, + data: T, +) -> InterpResult<'tcx> { + let init_field = primitive.offset(init_offset, ecx.machine.layouts.u32, ecx)?; + + let (alloc, offset, _) = ecx.ptr_get_alloc_id(primitive.ptr(), 0)?; + let (alloc_extra, _machine) = ecx.get_alloc_extra_mut(alloc)?; + alloc_extra.sync.insert(offset, Box::new(data)); + // Mark this as "initialized". + ecx.write_scalar_atomic( + Scalar::from_u32(LAZY_INIT_COOKIE), + &init_field, + AtomicWriteOrd::Relaxed, + )?; + interp_ok(()) +} + +/// Helper for lazily initialized `alloc_extra.sync` data: +/// Checks if the primitive is initialized, and return its associated data if so. +/// Otherwise, return None. +pub fn lazy_sync_get_data<'tcx, T: 'static + Copy>( + ecx: &mut MiriInterpCx<'tcx>, + primitive: &MPlaceTy<'tcx>, + init_offset: Size, + name: &str, +) -> InterpResult<'tcx, Option> { + let init_field = primitive.offset(init_offset, ecx.machine.layouts.u32, ecx)?; + // Check if this is already initialized. Needs to be atomic because we can race with another + // thread initializing. Needs to be an RMW operation to ensure we read the *latest* value. + // So we just try to replace MUTEX_INIT_COOKIE with itself. + let init_cookie = Scalar::from_u32(LAZY_INIT_COOKIE); + let (_init, success) = ecx + .atomic_compare_exchange_scalar( + &init_field, + &ImmTy::from_scalar(init_cookie, ecx.machine.layouts.u32), + init_cookie, + AtomicRwOrd::Acquire, + AtomicReadOrd::Acquire, + /* can_fail_spuriously */ false, + )? + .to_scalar_pair(); + if success.to_bool()? { + // If it is initialized, it must be found in the "sync primitive" table, + // or else it has been moved illegally. + let (alloc, offset, _) = ecx.ptr_get_alloc_id(primitive.ptr(), 0)?; + let alloc_extra = ecx.get_alloc_extra(alloc)?; + let data = alloc_extra + .get_sync::(offset) + .ok_or_else(|| err_ub_format!("`{name}` can't be moved after first use"))?; + interp_ok(Some(*data)) + } else { + interp_ok(None) + } } // Public interface to synchronization primitives. Please note that in most diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index d5734ea3c83..60d096b92f2 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -362,12 +362,6 @@ impl VisitProvenance for AllocExtra<'_> { } } -impl<'tcx> AllocExtra<'tcx> { - pub fn get_sync(&self, offset: Size) -> Option<&T> { - self.sync.get(&offset).and_then(|s| s.downcast_ref::()) - } -} - /// Precomputed layouts of primitive types pub struct PrimitiveLayouts<'tcx> { pub unit: TyAndLayout<'tcx>, diff --git a/src/tools/miri/src/shims/unix/sync.rs b/src/tools/miri/src/shims/unix/sync.rs index abc2980440f..efbe09a2a5d 100644 --- a/src/tools/miri/src/shims/unix/sync.rs +++ b/src/tools/miri/src/shims/unix/sync.rs @@ -2,10 +2,13 @@ use std::sync::atomic::{AtomicBool, Ordering}; use rustc_target::abi::Size; +use crate::concurrency::sync::{LAZY_INIT_COOKIE, lazy_sync_get_data, lazy_sync_init}; use crate::*; -/// Do a bytewise comparison of the two places, using relaxed atomic reads. -/// This is used to check if a mutex matches its static initializer value. +/// Do a bytewise comparison of the two places, using relaxed atomic reads. This is used to check if +/// a synchronization primitive matches its static initializer value. +/// +/// The reads happen in chunks of 4, so all racing accesses must also use that access size. fn bytewise_equal_atomic_relaxed<'tcx>( ecx: &MiriInterpCx<'tcx>, left: &MPlaceTy<'tcx>, @@ -33,63 +36,6 @@ fn bytewise_equal_atomic_relaxed<'tcx>( interp_ok(true) } -/// We designate an `init`` field in all primitives. -/// If `init` is set to this, we consider the primitive initialized. -const INIT_COOKIE: u32 = 0xcafe_affe; - -fn sync_init<'tcx, T: 'static + Copy>( - ecx: &mut MiriInterpCx<'tcx>, - primitive: &MPlaceTy<'tcx>, - init_offset: Size, - data: T, -) -> InterpResult<'tcx> { - let init_field = primitive.offset(init_offset, ecx.machine.layouts.u32, ecx)?; - - let (alloc, offset, _) = ecx.ptr_get_alloc_id(primitive.ptr(), 0)?; - let (alloc_extra, _machine) = ecx.get_alloc_extra_mut(alloc)?; - alloc_extra.sync.insert(offset, Box::new(data)); - // Mark this as "initialized". - ecx.write_scalar_atomic(Scalar::from_u32(INIT_COOKIE), &init_field, AtomicWriteOrd::Relaxed)?; - interp_ok(()) -} - -/// Checks if the primitive is initialized, and return its associated data if so. -/// Otherwise, return None. -fn sync_get_data<'tcx, T: 'static + Copy>( - ecx: &mut MiriInterpCx<'tcx>, - primitive: &MPlaceTy<'tcx>, - init_offset: Size, - name: &str, -) -> InterpResult<'tcx, Option> { - let init_field = primitive.offset(init_offset, ecx.machine.layouts.u32, ecx)?; - // Check if this is already initialized. Needs to be atomic because we can race with another - // thread initializing. Needs to be an RMW operation to ensure we read the *latest* value. - // So we just try to replace MUTEX_INIT_COOKIE with itself. - let init_cookie = Scalar::from_u32(INIT_COOKIE); - let (_init, success) = ecx - .atomic_compare_exchange_scalar( - &init_field, - &ImmTy::from_scalar(init_cookie, ecx.machine.layouts.u32), - init_cookie, - AtomicRwOrd::Acquire, - AtomicReadOrd::Acquire, - /* can_fail_spuriously */ false, - )? - .to_scalar_pair(); - if success.to_bool()? { - // If it is initialized, it must be found in the "sync primitive" table, - // or else it has been moved illegally. - let (alloc, offset, _) = ecx.ptr_get_alloc_id(primitive.ptr(), 0)?; - let alloc_extra = ecx.get_alloc_extra(alloc)?; - let data = alloc_extra - .get_sync::(offset) - .ok_or_else(|| err_ub_format!("`{name}` can't be moved after first use"))?; - interp_ok(Some(*data)) - } else { - interp_ok(None) - } -} - // # pthread_mutexattr_t // We store some data directly inside the type, ignoring the platform layout: // - kind: i32 @@ -198,7 +144,10 @@ fn mutex_init_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> InterpResult<'tcx, Size> let init_field = static_initializer.offset(offset, ecx.machine.layouts.u32, ecx).unwrap(); let init = ecx.read_scalar(&init_field).unwrap().to_u32().unwrap(); - assert_ne!(init, INIT_COOKIE, "{name} is incompatible with our initialization cookie"); + assert_ne!( + init, LAZY_INIT_COOKIE, + "{name} is incompatible with our initialization cookie" + ); }; check_static_initializer("PTHREAD_MUTEX_INITIALIZER"); @@ -228,7 +177,7 @@ fn mutex_create<'tcx>( let mutex = ecx.deref_pointer(mutex_ptr)?; let id = ecx.machine.sync.mutex_create(); let data = MutexData { id, kind }; - sync_init(ecx, &mutex, mutex_init_offset(ecx)?, data)?; + lazy_sync_init(ecx, &mutex, mutex_init_offset(ecx)?, data)?; interp_ok(data) } @@ -243,7 +192,7 @@ fn mutex_get_data<'tcx, 'a>( let mutex = ecx.deref_pointer(mutex_ptr)?; if let Some(data) = - sync_get_data::(ecx, &mutex, mutex_init_offset(ecx)?, "pthread_mutex_t")? + lazy_sync_get_data::(ecx, &mutex, mutex_init_offset(ecx)?, "pthread_mutex_t")? { interp_ok(data) } else { @@ -302,14 +251,14 @@ fn rwlock_init_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> InterpResult<'tcx, Size let offset = Size::from_bytes(offset); // Sanity-check this against PTHREAD_RWLOCK_INITIALIZER (but only once): - // the `init` field must start out not equal to INIT_COOKIE. + // the `init` field must start out not equal to LAZY_INIT_COOKIE. static SANITY: AtomicBool = AtomicBool::new(false); if !SANITY.swap(true, Ordering::Relaxed) { let static_initializer = ecx.eval_path(&["libc", "PTHREAD_RWLOCK_INITIALIZER"]); let init_field = static_initializer.offset(offset, ecx.machine.layouts.u32, ecx).unwrap(); let init = ecx.read_scalar(&init_field).unwrap().to_u32().unwrap(); assert_ne!( - init, INIT_COOKIE, + init, LAZY_INIT_COOKIE, "PTHREAD_RWLOCK_INITIALIZER is incompatible with our initialization cookie" ); } @@ -324,7 +273,8 @@ fn rwlock_get_data<'tcx>( let rwlock = ecx.deref_pointer(rwlock_ptr)?; let init_offset = rwlock_init_offset(ecx)?; - if let Some(data) = sync_get_data::(ecx, &rwlock, init_offset, "pthread_rwlock_t")? + if let Some(data) = + lazy_sync_get_data::(ecx, &rwlock, init_offset, "pthread_rwlock_t")? { interp_ok(data) } else { @@ -337,7 +287,7 @@ fn rwlock_get_data<'tcx>( } let id = ecx.machine.sync.rwlock_create(); let data = RwLockData { id }; - sync_init(ecx, &rwlock, init_offset, data)?; + lazy_sync_init(ecx, &rwlock, init_offset, data)?; interp_ok(data) } } @@ -410,14 +360,14 @@ fn cond_init_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> InterpResult<'tcx, Size> let offset = Size::from_bytes(offset); // Sanity-check this against PTHREAD_COND_INITIALIZER (but only once): - // the `init` field must start out not equal to INIT_COOKIE. + // the `init` field must start out not equal to LAZY_INIT_COOKIE. static SANITY: AtomicBool = AtomicBool::new(false); if !SANITY.swap(true, Ordering::Relaxed) { let static_initializer = ecx.eval_path(&["libc", "PTHREAD_COND_INITIALIZER"]); let init_field = static_initializer.offset(offset, ecx.machine.layouts.u32, ecx).unwrap(); let init = ecx.read_scalar(&init_field).unwrap().to_u32().unwrap(); assert_ne!( - init, INIT_COOKIE, + init, LAZY_INIT_COOKIE, "PTHREAD_COND_INITIALIZER is incompatible with our initialization cookie" ); } @@ -446,7 +396,7 @@ fn cond_create<'tcx>( let cond = ecx.deref_pointer(cond_ptr)?; let id = ecx.machine.sync.condvar_create(); let data = CondData { id, clock }; - sync_init(ecx, &cond, cond_init_offset(ecx)?, data)?; + lazy_sync_init(ecx, &cond, cond_init_offset(ecx)?, data)?; interp_ok(data) } @@ -457,7 +407,7 @@ fn cond_get_data<'tcx>( let cond = ecx.deref_pointer(cond_ptr)?; let init_offset = cond_init_offset(ecx)?; - if let Some(data) = sync_get_data::(ecx, &cond, init_offset, "pthread_cond_t")? { + if let Some(data) = lazy_sync_get_data::(ecx, &cond, init_offset, "pthread_cond_t")? { interp_ok(data) } else { // This used the static initializer. The clock there is always CLOCK_REALTIME. diff --git a/src/tools/miri/src/shims/windows/sync.rs b/src/tools/miri/src/shims/windows/sync.rs index 6755c23039e..de780361b5d 100644 --- a/src/tools/miri/src/shims/windows/sync.rs +++ b/src/tools/miri/src/shims/windows/sync.rs @@ -3,8 +3,14 @@ use std::time::Duration; use rustc_target::abi::Size; use crate::concurrency::init_once::InitOnceStatus; +use crate::concurrency::sync::{lazy_sync_get_data, lazy_sync_init}; use crate::*; +#[derive(Copy, Clone)] +struct InitOnceData { + id: InitOnceId, +} + impl<'tcx> EvalContextExtPriv<'tcx> for crate::MiriInterpCx<'tcx> {} trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { // Windows sync primitives are pointer sized. @@ -12,8 +18,21 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { fn init_once_get_id(&mut self, init_once_ptr: &OpTy<'tcx>) -> InterpResult<'tcx, InitOnceId> { let this = self.eval_context_mut(); + let init_once = this.deref_pointer(init_once_ptr)?; - this.init_once_get_or_create_id(&init_once, 0) + let init_offset = Size::ZERO; + + if let Some(data) = + lazy_sync_get_data::(this, &init_once, init_offset, "INIT_ONCE")? + { + interp_ok(data.id) + } else { + // TODO: check that this is still all-zero. + let id = this.machine.sync.init_once_create(); + let data = InitOnceData { id }; + lazy_sync_init(this, &init_once, init_offset, data)?; + interp_ok(id) + } } /// Returns `true` if we were succssful, `false` if we would block. From e3cfe456d67aa428b5144ef760e65b1b7b893e47 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 12 Oct 2024 15:12:46 +0200 Subject: [PATCH 288/357] make lazy_sync_get_data also take a closure to initialize if needed --- src/tools/miri/src/concurrency/sync.rs | 17 ++++++---- src/tools/miri/src/shims/unix/sync.rs | 43 +++++++----------------- src/tools/miri/src/shims/windows/sync.rs | 23 ++++++------- 3 files changed, 32 insertions(+), 51 deletions(-) diff --git a/src/tools/miri/src/concurrency/sync.rs b/src/tools/miri/src/concurrency/sync.rs index e42add0d509..11110c6e754 100644 --- a/src/tools/miri/src/concurrency/sync.rs +++ b/src/tools/miri/src/concurrency/sync.rs @@ -201,12 +201,11 @@ pub fn lazy_sync_init<'tcx, T: 'static + Copy>( init_offset: Size, data: T, ) -> InterpResult<'tcx> { - let init_field = primitive.offset(init_offset, ecx.machine.layouts.u32, ecx)?; - let (alloc, offset, _) = ecx.ptr_get_alloc_id(primitive.ptr(), 0)?; let (alloc_extra, _machine) = ecx.get_alloc_extra_mut(alloc)?; alloc_extra.sync.insert(offset, Box::new(data)); // Mark this as "initialized". + let init_field = primitive.offset(init_offset, ecx.machine.layouts.u32, ecx)?; ecx.write_scalar_atomic( Scalar::from_u32(LAZY_INIT_COOKIE), &init_field, @@ -217,18 +216,19 @@ pub fn lazy_sync_init<'tcx, T: 'static + Copy>( /// Helper for lazily initialized `alloc_extra.sync` data: /// Checks if the primitive is initialized, and return its associated data if so. -/// Otherwise, return None. +/// Otherwise, calls `new_data` to initialize the primitive. pub fn lazy_sync_get_data<'tcx, T: 'static + Copy>( ecx: &mut MiriInterpCx<'tcx>, primitive: &MPlaceTy<'tcx>, init_offset: Size, name: &str, -) -> InterpResult<'tcx, Option> { - let init_field = primitive.offset(init_offset, ecx.machine.layouts.u32, ecx)?; + new_data: impl FnOnce(&mut MiriInterpCx<'tcx>) -> InterpResult<'tcx, T>, +) -> InterpResult<'tcx, T> { // Check if this is already initialized. Needs to be atomic because we can race with another // thread initializing. Needs to be an RMW operation to ensure we read the *latest* value. // So we just try to replace MUTEX_INIT_COOKIE with itself. let init_cookie = Scalar::from_u32(LAZY_INIT_COOKIE); + let init_field = primitive.offset(init_offset, ecx.machine.layouts.u32, ecx)?; let (_init, success) = ecx .atomic_compare_exchange_scalar( &init_field, @@ -239,6 +239,7 @@ pub fn lazy_sync_get_data<'tcx, T: 'static + Copy>( /* can_fail_spuriously */ false, )? .to_scalar_pair(); + if success.to_bool()? { // If it is initialized, it must be found in the "sync primitive" table, // or else it has been moved illegally. @@ -247,9 +248,11 @@ pub fn lazy_sync_get_data<'tcx, T: 'static + Copy>( let data = alloc_extra .get_sync::(offset) .ok_or_else(|| err_ub_format!("`{name}` can't be moved after first use"))?; - interp_ok(Some(*data)) + interp_ok(*data) } else { - interp_ok(None) + let data = new_data(ecx)?; + lazy_sync_init(ecx, primitive, init_offset, data)?; + interp_ok(data) } } diff --git a/src/tools/miri/src/shims/unix/sync.rs b/src/tools/miri/src/shims/unix/sync.rs index efbe09a2a5d..5b4c136c233 100644 --- a/src/tools/miri/src/shims/unix/sync.rs +++ b/src/tools/miri/src/shims/unix/sync.rs @@ -190,19 +190,11 @@ fn mutex_get_data<'tcx, 'a>( mutex_ptr: &OpTy<'tcx>, ) -> InterpResult<'tcx, MutexData> { let mutex = ecx.deref_pointer(mutex_ptr)?; - - if let Some(data) = - lazy_sync_get_data::(ecx, &mutex, mutex_init_offset(ecx)?, "pthread_mutex_t")? - { - interp_ok(data) - } else { - // Not yet initialized. This must be a static initializer, figure out the kind - // from that. We don't need to worry about races since we are the interpreter - // and don't let any other tread take a step. + lazy_sync_get_data(ecx, &mutex, mutex_init_offset(ecx)?, "pthread_mutex_t", |ecx| { let kind = mutex_kind_from_static_initializer(ecx, &mutex)?; - // And then create the mutex like this. - mutex_create(ecx, mutex_ptr, kind) - } + let id = ecx.machine.sync.mutex_create(); + interp_ok(MutexData { id, kind }) + }) } /// Returns the kind of a static initializer. @@ -271,13 +263,7 @@ fn rwlock_get_data<'tcx>( rwlock_ptr: &OpTy<'tcx>, ) -> InterpResult<'tcx, RwLockData> { let rwlock = ecx.deref_pointer(rwlock_ptr)?; - let init_offset = rwlock_init_offset(ecx)?; - - if let Some(data) = - lazy_sync_get_data::(ecx, &rwlock, init_offset, "pthread_rwlock_t")? - { - interp_ok(data) - } else { + lazy_sync_get_data(ecx, &rwlock, rwlock_init_offset(ecx)?, "pthread_rwlock_t", |ecx| { if !bytewise_equal_atomic_relaxed( ecx, &rwlock, @@ -286,10 +272,8 @@ fn rwlock_get_data<'tcx>( throw_unsup_format!("unsupported static initializer used for `pthread_rwlock_t`"); } let id = ecx.machine.sync.rwlock_create(); - let data = RwLockData { id }; - lazy_sync_init(ecx, &rwlock, init_offset, data)?; - interp_ok(data) - } + interp_ok(RwLockData { id }) + }) } // # pthread_condattr_t @@ -405,12 +389,7 @@ fn cond_get_data<'tcx>( cond_ptr: &OpTy<'tcx>, ) -> InterpResult<'tcx, CondData> { let cond = ecx.deref_pointer(cond_ptr)?; - let init_offset = cond_init_offset(ecx)?; - - if let Some(data) = lazy_sync_get_data::(ecx, &cond, init_offset, "pthread_cond_t")? { - interp_ok(data) - } else { - // This used the static initializer. The clock there is always CLOCK_REALTIME. + lazy_sync_get_data(ecx, &cond, cond_init_offset(ecx)?, "pthread_cond_t", |ecx| { if !bytewise_equal_atomic_relaxed( ecx, &cond, @@ -418,8 +397,10 @@ fn cond_get_data<'tcx>( )? { throw_unsup_format!("unsupported static initializer used for `pthread_cond_t`"); } - cond_create(ecx, cond_ptr, ClockId::Realtime) - } + // This used the static initializer. The clock there is always CLOCK_REALTIME. + let id = ecx.machine.sync.condvar_create(); + interp_ok(CondData { id, clock: ClockId::Realtime }) + }) } impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} diff --git a/src/tools/miri/src/shims/windows/sync.rs b/src/tools/miri/src/shims/windows/sync.rs index de780361b5d..d0e82112a50 100644 --- a/src/tools/miri/src/shims/windows/sync.rs +++ b/src/tools/miri/src/shims/windows/sync.rs @@ -3,7 +3,7 @@ use std::time::Duration; use rustc_target::abi::Size; use crate::concurrency::init_once::InitOnceStatus; -use crate::concurrency::sync::{lazy_sync_get_data, lazy_sync_init}; +use crate::concurrency::sync::lazy_sync_get_data; use crate::*; #[derive(Copy, Clone)] @@ -16,23 +16,20 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { // Windows sync primitives are pointer sized. // We only use the first 4 bytes for the id. - fn init_once_get_id(&mut self, init_once_ptr: &OpTy<'tcx>) -> InterpResult<'tcx, InitOnceId> { + fn init_once_get_data( + &mut self, + init_once_ptr: &OpTy<'tcx>, + ) -> InterpResult<'tcx, InitOnceData> { let this = self.eval_context_mut(); let init_once = this.deref_pointer(init_once_ptr)?; let init_offset = Size::ZERO; - if let Some(data) = - lazy_sync_get_data::(this, &init_once, init_offset, "INIT_ONCE")? - { - interp_ok(data.id) - } else { + lazy_sync_get_data(this, &init_once, init_offset, "INIT_ONCE", |this| { // TODO: check that this is still all-zero. let id = this.machine.sync.init_once_create(); - let data = InitOnceData { id }; - lazy_sync_init(this, &init_once, init_offset, data)?; - interp_ok(id) - } + interp_ok(InitOnceData { id }) + }) } /// Returns `true` if we were succssful, `false` if we would block. @@ -74,7 +71,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { ) -> InterpResult<'tcx> { let this = self.eval_context_mut(); - let id = this.init_once_get_id(init_once_op)?; + let id = this.init_once_get_data(init_once_op)?.id; let flags = this.read_scalar(flags_op)?.to_u32()?; let pending_place = this.deref_pointer(pending_op)?; let context = this.read_pointer(context_op)?; @@ -120,7 +117,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { ) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); - let id = this.init_once_get_id(init_once_op)?; + let id = this.init_once_get_data(init_once_op)?.id; let flags = this.read_scalar(flags_op)?.to_u32()?; let context = this.read_pointer(context_op)?; From 9265a6e467d2c02a634d9e90b9963ab28a6d2b64 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 12 Oct 2024 15:22:59 +0200 Subject: [PATCH 289/357] turns out relaxed accesses suffice here --- src/tools/miri/src/concurrency/sync.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/miri/src/concurrency/sync.rs b/src/tools/miri/src/concurrency/sync.rs index 11110c6e754..2c6a7bf0f58 100644 --- a/src/tools/miri/src/concurrency/sync.rs +++ b/src/tools/miri/src/concurrency/sync.rs @@ -234,8 +234,8 @@ pub fn lazy_sync_get_data<'tcx, T: 'static + Copy>( &init_field, &ImmTy::from_scalar(init_cookie, ecx.machine.layouts.u32), init_cookie, - AtomicRwOrd::Acquire, - AtomicReadOrd::Acquire, + AtomicRwOrd::Relaxed, + AtomicReadOrd::Relaxed, /* can_fail_spuriously */ false, )? .to_scalar_pair(); From ba95d522581c6816ccb8f27c12b42087253c8305 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 12 Oct 2024 15:35:59 +0200 Subject: [PATCH 290/357] pick more clear names for the types --- src/tools/miri/src/shims/unix/macos/sync.rs | 6 ++--- src/tools/miri/src/shims/unix/sync.rs | 29 +++++++++------------ src/tools/miri/src/shims/windows/sync.rs | 6 ++--- 3 files changed, 19 insertions(+), 22 deletions(-) diff --git a/src/tools/miri/src/shims/unix/macos/sync.rs b/src/tools/miri/src/shims/unix/macos/sync.rs index f135a0df0a7..cd5b0ed1d07 100644 --- a/src/tools/miri/src/shims/unix/macos/sync.rs +++ b/src/tools/miri/src/shims/unix/macos/sync.rs @@ -12,7 +12,7 @@ use crate::*; -struct LockData { +struct MacOsUnfairLock { id: MutexId, } @@ -25,11 +25,11 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { // that's just implicitly creating a new lock at the new location. let (alloc, offset, _) = this.ptr_get_alloc_id(lock.ptr(), 0)?; let (alloc_extra, machine) = this.get_alloc_extra_mut(alloc)?; - if let Some(data) = alloc_extra.get_sync::(offset) { + if let Some(data) = alloc_extra.get_sync::(offset) { interp_ok(data.id) } else { let id = machine.sync.mutex_create(); - alloc_extra.sync.insert(offset, Box::new(LockData { id })); + alloc_extra.sync.insert(offset, Box::new(MacOsUnfairLock { id })); interp_ok(id) } } diff --git a/src/tools/miri/src/shims/unix/sync.rs b/src/tools/miri/src/shims/unix/sync.rs index 5b4c136c233..913f53adbbb 100644 --- a/src/tools/miri/src/shims/unix/sync.rs +++ b/src/tools/miri/src/shims/unix/sync.rs @@ -117,8 +117,7 @@ enum MutexKind { } #[derive(Debug, Clone, Copy)] -/// Additional data that we attach with each mutex instance. -struct MutexData { +struct PthreadMutex { id: MutexId, kind: MutexKind, } @@ -173,10 +172,10 @@ fn mutex_create<'tcx>( ecx: &mut MiriInterpCx<'tcx>, mutex_ptr: &OpTy<'tcx>, kind: MutexKind, -) -> InterpResult<'tcx, MutexData> { +) -> InterpResult<'tcx, PthreadMutex> { let mutex = ecx.deref_pointer(mutex_ptr)?; let id = ecx.machine.sync.mutex_create(); - let data = MutexData { id, kind }; + let data = PthreadMutex { id, kind }; lazy_sync_init(ecx, &mutex, mutex_init_offset(ecx)?, data)?; interp_ok(data) } @@ -188,12 +187,12 @@ fn mutex_create<'tcx>( fn mutex_get_data<'tcx, 'a>( ecx: &'a mut MiriInterpCx<'tcx>, mutex_ptr: &OpTy<'tcx>, -) -> InterpResult<'tcx, MutexData> { +) -> InterpResult<'tcx, PthreadMutex> { let mutex = ecx.deref_pointer(mutex_ptr)?; lazy_sync_get_data(ecx, &mutex, mutex_init_offset(ecx)?, "pthread_mutex_t", |ecx| { let kind = mutex_kind_from_static_initializer(ecx, &mutex)?; let id = ecx.machine.sync.mutex_create(); - interp_ok(MutexData { id, kind }) + interp_ok(PthreadMutex { id, kind }) }) } @@ -228,8 +227,7 @@ fn mutex_kind_from_static_initializer<'tcx>( // - init: u32 #[derive(Debug, Copy, Clone)] -/// Additional data that we attach with each rwlock instance. -struct RwLockData { +struct PthreadRwLock { id: RwLockId, } @@ -261,7 +259,7 @@ fn rwlock_init_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> InterpResult<'tcx, Size fn rwlock_get_data<'tcx>( ecx: &mut MiriInterpCx<'tcx>, rwlock_ptr: &OpTy<'tcx>, -) -> InterpResult<'tcx, RwLockData> { +) -> InterpResult<'tcx, PthreadRwLock> { let rwlock = ecx.deref_pointer(rwlock_ptr)?; lazy_sync_get_data(ecx, &rwlock, rwlock_init_offset(ecx)?, "pthread_rwlock_t", |ecx| { if !bytewise_equal_atomic_relaxed( @@ -272,7 +270,7 @@ fn rwlock_get_data<'tcx>( throw_unsup_format!("unsupported static initializer used for `pthread_rwlock_t`"); } let id = ecx.machine.sync.rwlock_create(); - interp_ok(RwLockData { id }) + interp_ok(PthreadRwLock { id }) }) } @@ -366,8 +364,7 @@ enum ClockId { } #[derive(Debug, Copy, Clone)] -/// Additional data that we attach with each cond instance. -struct CondData { +struct PthreadCondvar { id: CondvarId, clock: ClockId, } @@ -376,10 +373,10 @@ fn cond_create<'tcx>( ecx: &mut MiriInterpCx<'tcx>, cond_ptr: &OpTy<'tcx>, clock: ClockId, -) -> InterpResult<'tcx, CondData> { +) -> InterpResult<'tcx, PthreadCondvar> { let cond = ecx.deref_pointer(cond_ptr)?; let id = ecx.machine.sync.condvar_create(); - let data = CondData { id, clock }; + let data = PthreadCondvar { id, clock }; lazy_sync_init(ecx, &cond, cond_init_offset(ecx)?, data)?; interp_ok(data) } @@ -387,7 +384,7 @@ fn cond_create<'tcx>( fn cond_get_data<'tcx>( ecx: &mut MiriInterpCx<'tcx>, cond_ptr: &OpTy<'tcx>, -) -> InterpResult<'tcx, CondData> { +) -> InterpResult<'tcx, PthreadCondvar> { let cond = ecx.deref_pointer(cond_ptr)?; lazy_sync_get_data(ecx, &cond, cond_init_offset(ecx)?, "pthread_cond_t", |ecx| { if !bytewise_equal_atomic_relaxed( @@ -399,7 +396,7 @@ fn cond_get_data<'tcx>( } // This used the static initializer. The clock there is always CLOCK_REALTIME. let id = ecx.machine.sync.condvar_create(); - interp_ok(CondData { id, clock: ClockId::Realtime }) + interp_ok(PthreadCondvar { id, clock: ClockId::Realtime }) }) } diff --git a/src/tools/miri/src/shims/windows/sync.rs b/src/tools/miri/src/shims/windows/sync.rs index d0e82112a50..8771bb4a8ac 100644 --- a/src/tools/miri/src/shims/windows/sync.rs +++ b/src/tools/miri/src/shims/windows/sync.rs @@ -7,7 +7,7 @@ use crate::concurrency::sync::lazy_sync_get_data; use crate::*; #[derive(Copy, Clone)] -struct InitOnceData { +struct WindowsInitOnce { id: InitOnceId, } @@ -19,7 +19,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { fn init_once_get_data( &mut self, init_once_ptr: &OpTy<'tcx>, - ) -> InterpResult<'tcx, InitOnceData> { + ) -> InterpResult<'tcx, WindowsInitOnce> { let this = self.eval_context_mut(); let init_once = this.deref_pointer(init_once_ptr)?; @@ -28,7 +28,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { lazy_sync_get_data(this, &init_once, init_offset, "INIT_ONCE", |this| { // TODO: check that this is still all-zero. let id = this.machine.sync.init_once_create(); - interp_ok(InitOnceData { id }) + interp_ok(WindowsInitOnce { id }) }) } From 73fc00ff8c497af386cce222fe467371dc335885 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 14 Oct 2024 17:51:08 +0200 Subject: [PATCH 291/357] Delay ambiguous intra-doc link resolution after `Cache` has been populated --- src/librustdoc/clean/types.rs | 13 +- src/librustdoc/core.rs | 24 +- .../passes/calculate_doc_coverage.rs | 2 +- .../passes/check_doc_test_visibility.rs | 2 +- .../passes/collect_intra_doc_links.rs | 260 +++++++++++++++--- src/librustdoc/passes/collect_trait_impls.rs | 2 +- src/librustdoc/passes/lint.rs | 2 +- src/librustdoc/passes/mod.rs | 2 +- src/librustdoc/passes/propagate_doc_cfg.rs | 2 +- src/librustdoc/passes/propagate_stability.rs | 2 +- .../passes/strip_aliased_non_local.rs | 2 +- src/librustdoc/passes/strip_hidden.rs | 2 +- src/librustdoc/passes/strip_priv_imports.rs | 2 +- src/librustdoc/passes/strip_private.rs | 2 +- 14 files changed, 263 insertions(+), 56 deletions(-) diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index bc5bf4c0583..44d9a5fdbe8 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1228,15 +1228,14 @@ impl Attributes { for attr in self.other_attrs.lists(sym::doc).filter(|a| a.has_name(sym::alias)) { if let Some(values) = attr.meta_item_list() { for l in values { - match l.lit().unwrap().kind { - ast::LitKind::Str(s, _) => { - aliases.insert(s); - } - _ => unreachable!(), + if let Some(lit) = l.lit() + && let ast::LitKind::Str(s, _) = lit.kind + { + aliases.insert(s); } } - } else { - aliases.insert(attr.value_str().unwrap()); + } else if let Some(value) = attr.value_str() { + aliases.insert(value); } } aliases.into_iter().collect::>().into() diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index aaf4c80f997..9bebe1fb4c1 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -29,8 +29,9 @@ use crate::clean::inline::build_external_trait; use crate::clean::{self, ItemId}; use crate::config::{Options as RustdocOptions, OutputFormat, RenderOptions}; use crate::formats::cache::Cache; +use crate::passes; use crate::passes::Condition::*; -use crate::passes::{self}; +use crate::passes::collect_intra_doc_links::LinkCollector; pub(crate) struct DocContext<'tcx> { pub(crate) tcx: TyCtxt<'tcx>, @@ -427,6 +428,9 @@ pub(crate) fn run_global_ctxt( info!("Executing passes"); + let mut visited = FxHashMap::default(); + let mut ambiguous = FxIndexMap::default(); + for p in passes::defaults(show_coverage) { let run = match p.condition { Always => true, @@ -436,18 +440,30 @@ pub(crate) fn run_global_ctxt( }; if run { debug!("running pass {}", p.pass.name); - krate = tcx.sess.time(p.pass.name, || (p.pass.run)(krate, &mut ctxt)); + if let Some(run_fn) = p.pass.run { + krate = tcx.sess.time(p.pass.name, || run_fn(krate, &mut ctxt)); + } else { + let (k, LinkCollector { visited_links, ambiguous_links, .. }) = + passes::collect_intra_doc_links::collect_intra_doc_links(krate, &mut ctxt); + krate = k; + visited = visited_links; + ambiguous = ambiguous_links; + } } } tcx.sess.time("check_lint_expectations", || tcx.check_expectations(Some(sym::rustdoc))); + krate = tcx.sess.time("create_format_cache", || Cache::populate(&mut ctxt, krate)); + + let mut collector = + LinkCollector { cx: &mut ctxt, visited_links: visited, ambiguous_links: ambiguous }; + collector.resolve_ambiguities(); + if let Some(guar) = tcx.dcx().has_errors() { return Err(guar); } - krate = tcx.sess.time("create_format_cache", || Cache::populate(&mut ctxt, krate)); - Ok((krate, ctxt.render_options, ctxt.cache)) } diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs index abea5bcbc51..d27e737764d 100644 --- a/src/librustdoc/passes/calculate_doc_coverage.rs +++ b/src/librustdoc/passes/calculate_doc_coverage.rs @@ -20,7 +20,7 @@ use crate::visit::DocVisitor; pub(crate) const CALCULATE_DOC_COVERAGE: Pass = Pass { name: "calculate-doc-coverage", - run: calculate_doc_coverage, + run: Some(calculate_doc_coverage), description: "counts the number of items with and without documentation", }; diff --git a/src/librustdoc/passes/check_doc_test_visibility.rs b/src/librustdoc/passes/check_doc_test_visibility.rs index 1dc9af7ebe5..f4579d85531 100644 --- a/src/librustdoc/passes/check_doc_test_visibility.rs +++ b/src/librustdoc/passes/check_doc_test_visibility.rs @@ -20,7 +20,7 @@ use crate::visit::DocVisitor; pub(crate) const CHECK_DOC_TEST_VISIBILITY: Pass = Pass { name: "check_doc_test_visibility", - run: check_doc_test_visibility, + run: Some(check_doc_test_visibility), description: "run various visibility-related lints on doctests", }; diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index db235786cf4..81e7bcbd7d8 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -9,12 +9,12 @@ use std::ops::Range; use pulldown_cmark::LinkType; use rustc_ast::util::comments::may_have_doc_links; -use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; +use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet}; use rustc_data_structures::intern::Interned; use rustc_errors::{Applicability, Diag, DiagMessage}; use rustc_hir::def::Namespace::*; use rustc_hir::def::{DefKind, Namespace, PerNS}; -use rustc_hir::def_id::{CRATE_DEF_ID, DefId}; +use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LOCAL_CRATE}; use rustc_hir::{Mutability, Safety}; use rustc_middle::ty::{Ty, TyCtxt}; use rustc_middle::{bug, span_bug, ty}; @@ -30,23 +30,27 @@ use smallvec::{SmallVec, smallvec}; use tracing::{debug, info, instrument, trace}; use crate::clean::utils::find_nearest_parent_module; -use crate::clean::{self, Crate, Item, ItemLink, PrimitiveType}; +use crate::clean::{self, Crate, Item, ItemId, ItemLink, PrimitiveType}; use crate::core::DocContext; use crate::html::markdown::{MarkdownLink, MarkdownLinkRange, markdown_links}; use crate::lint::{BROKEN_INTRA_DOC_LINKS, PRIVATE_INTRA_DOC_LINKS}; use crate::passes::Pass; use crate::visit::DocVisitor; -pub(crate) const COLLECT_INTRA_DOC_LINKS: Pass = Pass { - name: "collect-intra-doc-links", - run: collect_intra_doc_links, - description: "resolves intra-doc links", -}; +pub(crate) const COLLECT_INTRA_DOC_LINKS: Pass = + Pass { name: "collect-intra-doc-links", run: None, description: "resolves intra-doc links" }; -fn collect_intra_doc_links(krate: Crate, cx: &mut DocContext<'_>) -> Crate { - let mut collector = LinkCollector { cx, visited_links: FxHashMap::default() }; +pub(crate) fn collect_intra_doc_links<'a, 'tcx>( + krate: Crate, + cx: &'a mut DocContext<'tcx>, +) -> (Crate, LinkCollector<'a, 'tcx>) { + let mut collector = LinkCollector { + cx, + visited_links: FxHashMap::default(), + ambiguous_links: FxIndexMap::default(), + }; collector.visit_crate(&krate); - krate + (krate, collector) } fn filter_assoc_items_by_name_and_namespace<'a>( @@ -61,7 +65,7 @@ fn filter_assoc_items_by_name_and_namespace<'a>( } #[derive(Copy, Clone, Debug, Hash, PartialEq)] -enum Res { +pub(crate) enum Res { Def(DefKind, DefId), Primitive(PrimitiveType), } @@ -234,7 +238,7 @@ impl UrlFragment { } #[derive(Clone, Debug, Hash, PartialEq, Eq)] -struct ResolutionInfo { +pub(crate) struct ResolutionInfo { item_id: DefId, module_id: DefId, dis: Option, @@ -243,18 +247,63 @@ struct ResolutionInfo { } #[derive(Clone)] -struct DiagnosticInfo<'a> { +pub(crate) struct DiagnosticInfo<'a> { item: &'a Item, dox: &'a str, ori_link: &'a str, link_range: MarkdownLinkRange, } -struct LinkCollector<'a, 'tcx> { - cx: &'a mut DocContext<'tcx>, +pub(crate) struct OwnedDiagnosticInfo { + item: Item, + dox: String, + ori_link: String, + link_range: MarkdownLinkRange, +} + +impl From> for OwnedDiagnosticInfo { + fn from(f: DiagnosticInfo<'_>) -> Self { + Self { + item: f.item.clone(), + dox: f.dox.to_string(), + ori_link: f.ori_link.to_string(), + link_range: f.link_range.clone(), + } + } +} + +impl OwnedDiagnosticInfo { + pub(crate) fn into_info(&self) -> DiagnosticInfo<'_> { + DiagnosticInfo { + item: &self.item, + ori_link: &self.ori_link, + dox: &self.dox, + link_range: self.link_range.clone(), + } + } +} + +pub(crate) struct LinkCollector<'a, 'tcx> { + pub(crate) cx: &'a mut DocContext<'tcx>, /// Cache the resolved links so we can avoid resolving (and emitting errors for) the same link. /// The link will be `None` if it could not be resolved (i.e. the error was cached). - visited_links: FxHashMap)>>, + pub(crate) visited_links: FxHashMap)>>, + /// These links are ambiguous. We need for the cache to have its paths filled. Unfortunately, + /// if we run the `LinkCollector` pass after `Cache::populate`, a lot of items that we need + /// to go through will be removed, making a lot of intra-doc links to not be inferred. + /// + /// So instead, we store the ambiguous links and we wait for cache paths to be filled before + /// inferring them (if possible). + /// + /// Key is `(item ID, path str)`. + pub(crate) ambiguous_links: FxIndexMap<(ItemId, String), Vec>, +} + +pub(crate) struct AmbiguousLinks { + disambiguator: Option, + link_text: Box, + diag_info: OwnedDiagnosticInfo, + resolved: Vec<(Res, Option)>, } impl<'a, 'tcx> LinkCollector<'a, 'tcx> { @@ -1001,6 +1050,10 @@ impl LinkCollector<'_, '_> { } } + pub(crate) fn save_link(&mut self, item_id: ItemId, link: ItemLink) { + self.cx.cache.intra_doc_links.entry(item_id).or_default().insert(link); + } + /// This is the entry point for resolving an intra-doc link. /// /// FIXME(jynelson): this is way too many arguments @@ -1024,7 +1077,7 @@ impl LinkCollector<'_, '_> { pp_link.as_ref().map_err(|err| err.report(self.cx, diag_info.clone())).ok()?; let disambiguator = *disambiguator; - let (mut res, fragment) = self.resolve_with_disambiguator_cached( + let mut resolved = self.resolve_with_disambiguator_cached( ResolutionInfo { item_id, module_id, @@ -1040,6 +1093,142 @@ impl LinkCollector<'_, '_> { false, )?; + if resolved.len() > 1 { + let links = AmbiguousLinks { + disambiguator, + link_text: link_text.clone(), + diag_info: diag_info.into(), + resolved, + }; + + self.ambiguous_links + .entry((item.item_id, path_str.to_string())) + .or_default() + .push(links); + None + } else if let Some((res, fragment)) = resolved.pop() { + self.compute_link(res, fragment, path_str, disambiguator, diag_info, link_text) + } else { + None + } + } + + /// Returns `true` if a link could be generated from the given intra-doc information. + /// + /// This is a very light version of `format::href_with_root_path` since we're only interested + /// about whether we can generate a link to an item or not. + /// + /// * If `original_did` is local, then we check if the item is reexported or public. + /// * If `original_did` is not local, then we check if the crate it comes from is a direct + /// public dependency. + fn validate_link(&self, original_did: DefId) -> bool { + let tcx = self.cx.tcx; + let def_kind = tcx.def_kind(original_did); + let did = match def_kind { + DefKind::AssocTy | DefKind::AssocFn | DefKind::AssocConst | DefKind::Variant => { + // documented on their parent's page + tcx.parent(original_did) + } + // If this a constructor, we get the parent (either a struct or a variant) and then + // generate the link for this item. + DefKind::Ctor(..) => return self.validate_link(tcx.parent(original_did)), + DefKind::ExternCrate => { + // Link to the crate itself, not the `extern crate` item. + if let Some(local_did) = original_did.as_local() { + tcx.extern_mod_stmt_cnum(local_did).unwrap_or(LOCAL_CRATE).as_def_id() + } else { + original_did + } + } + _ => original_did, + }; + + let cache = &self.cx.cache; + if !original_did.is_local() + && !cache.effective_visibilities.is_directly_public(tcx, did) + && !cache.document_private + && !cache.primitive_locations.values().any(|&id| id == did) + { + return false; + } + + cache.paths.get(&did).is_some() + || cache.external_paths.get(&did).is_some() + || !did.is_local() + } + + #[allow(rustc::potential_query_instability)] + pub(crate) fn resolve_ambiguities(&mut self) { + let mut ambiguous_links = mem::take(&mut self.ambiguous_links); + + for ((item_id, path_str), info_items) in ambiguous_links.iter_mut() { + for info in info_items { + info.resolved.retain(|(res, _)| match res { + Res::Def(_, def_id) => self.validate_link(*def_id), + // Primitive types are always valid. + Res::Primitive(_) => true, + }); + let diag_info = info.diag_info.into_info(); + match info.resolved.len() { + 1 => { + let (res, fragment) = info.resolved.pop().unwrap(); + if let Some(link) = self.compute_link( + res, + fragment, + path_str, + info.disambiguator, + diag_info, + &info.link_text, + ) { + self.save_link(*item_id, link); + } + } + 0 => { + report_diagnostic( + self.cx.tcx, + BROKEN_INTRA_DOC_LINKS, + format!( + "all items matching `{path_str}` are either private or doc(hidden)" + ), + &diag_info, + |diag, sp, _| { + if let Some(sp) = sp { + diag.span_label(sp, "unresolved link"); + } else { + diag.note("unresolved link"); + } + }, + ); + } + _ => { + let candidates = info + .resolved + .iter() + .map(|(res, fragment)| { + let def_id = if let Some(UrlFragment::Item(def_id)) = fragment { + Some(*def_id) + } else { + None + }; + (*res, def_id) + }) + .collect::>(); + ambiguity_error(self.cx, &diag_info, path_str, &candidates, true); + } + } + } + } + } + + fn compute_link( + &mut self, + mut res: Res, + fragment: Option, + path_str: &str, + disambiguator: Option, + diag_info: DiagnosticInfo<'_>, + link_text: &Box, + ) -> Option { // Check for a primitive which might conflict with a module // Report the ambiguity and require that the user specify which one they meant. // FIXME: could there ever be a primitive not in the type namespace? @@ -1055,7 +1244,7 @@ impl LinkCollector<'_, '_> { } else { // `[char]` when a `char` module is in scope let candidates = &[(res, res.def_id(self.cx.tcx)), (prim, None)]; - ambiguity_error(self.cx, &diag_info, path_str, candidates); + ambiguity_error(self.cx, &diag_info, path_str, candidates, true); return None; } } @@ -1085,7 +1274,7 @@ impl LinkCollector<'_, '_> { } res.def_id(self.cx.tcx).map(|page_id| ItemLink { - link: Box::::from(&*ori_link.link), + link: Box::::from(&*diag_info.ori_link), link_text: link_text.clone(), page_id, fragment, @@ -1107,7 +1296,7 @@ impl LinkCollector<'_, '_> { let page_id = clean::register_res(self.cx, rustc_hir::def::Res::Def(kind, id)); Some(ItemLink { - link: Box::::from(&*ori_link.link), + link: Box::::from(&*diag_info.ori_link), link_text: link_text.clone(), page_id, fragment, @@ -1220,10 +1409,10 @@ impl LinkCollector<'_, '_> { // If this call is intended to be recoverable, then pass true to silence. // This is only recoverable when path is failed to resolved. recoverable: bool, - ) -> Option<(Res, Option)> { + ) -> Option)>> { if let Some(res) = self.visited_links.get(&key) { if res.is_some() || cache_errors { - return res.clone(); + return res.clone().map(|r| vec![r]); } } @@ -1248,13 +1437,14 @@ impl LinkCollector<'_, '_> { // and after removing duplicated kinds, only one remains, the `ambiguity_error` function // won't emit an error. So at this point, we can just take the first candidate as it was // the first retrieved and use it to generate the link. - if let [candidate, _candidate2, ..] = *candidates - && !ambiguity_error(self.cx, &diag, &key.path_str, &candidates) - { - candidates = vec![candidate]; + if let [candidate, _candidate2, ..] = *candidates { + if !ambiguity_error(self.cx, &diag, &key.path_str, &candidates, false) { + candidates = vec![candidate]; + } } - if let &[(res, def_id)] = candidates.as_slice() { + let mut out = Vec::with_capacity(candidates.len()); + for (res, def_id) in candidates { let fragment = match (&key.extra_fragment, def_id) { (Some(_), Some(def_id)) => { report_anchor_conflict(self.cx, diag, def_id); @@ -1264,15 +1454,14 @@ impl LinkCollector<'_, '_> { (None, Some(def_id)) => Some(UrlFragment::Item(def_id)), (None, None) => None, }; - let r = Some((res, fragment)); - self.visited_links.insert(key, r.clone()); - return r; + out.push((res, fragment)); } - - if cache_errors { + if let [r] = out.as_slice() { + self.visited_links.insert(key, Some(r.clone())); + } else if cache_errors { self.visited_links.insert(key, None); } - None + Some(out) } /// After parsing the disambiguator, resolve the main part of the link. @@ -2046,6 +2235,7 @@ fn ambiguity_error( diag_info: &DiagnosticInfo<'_>, path_str: &str, candidates: &[(Res, Option)], + emit_error: bool, ) -> bool { let mut descrs = FxHashSet::default(); let kinds = candidates @@ -2061,6 +2251,8 @@ fn ambiguity_error( // There is no way for users to disambiguate at this point, so better return the first // candidate and not show a warning. return false; + } else if !emit_error { + return true; } let mut msg = format!("`{path_str}` is "); diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs index d1a1f0df3e7..f3589080322 100644 --- a/src/librustdoc/passes/collect_trait_impls.rs +++ b/src/librustdoc/passes/collect_trait_impls.rs @@ -16,7 +16,7 @@ use crate::visit::DocVisitor; pub(crate) const COLLECT_TRAIT_IMPLS: Pass = Pass { name: "collect-trait-impls", - run: collect_trait_impls, + run: Some(collect_trait_impls), description: "retrieves trait impls for items in the crate", }; diff --git a/src/librustdoc/passes/lint.rs b/src/librustdoc/passes/lint.rs index 593027ef7d2..35b62370abb 100644 --- a/src/librustdoc/passes/lint.rs +++ b/src/librustdoc/passes/lint.rs @@ -14,7 +14,7 @@ use crate::core::DocContext; use crate::visit::DocVisitor; pub(crate) const RUN_LINTS: Pass = - Pass { name: "run-lints", run: run_lints, description: "runs some of rustdoc's lints" }; + Pass { name: "run-lints", run: Some(run_lints), description: "runs some of rustdoc's lints" }; struct Linter<'a, 'tcx> { cx: &'a mut DocContext<'tcx>, diff --git a/src/librustdoc/passes/mod.rs b/src/librustdoc/passes/mod.rs index f5b78023721..9ba63d34144 100644 --- a/src/librustdoc/passes/mod.rs +++ b/src/librustdoc/passes/mod.rs @@ -47,7 +47,7 @@ pub(crate) use self::lint::RUN_LINTS; #[derive(Copy, Clone)] pub(crate) struct Pass { pub(crate) name: &'static str, - pub(crate) run: fn(clean::Crate, &mut DocContext<'_>) -> clean::Crate, + pub(crate) run: Option) -> clean::Crate>, pub(crate) description: &'static str, } diff --git a/src/librustdoc/passes/propagate_doc_cfg.rs b/src/librustdoc/passes/propagate_doc_cfg.rs index 6be51dd1560..350be37f553 100644 --- a/src/librustdoc/passes/propagate_doc_cfg.rs +++ b/src/librustdoc/passes/propagate_doc_cfg.rs @@ -13,7 +13,7 @@ use crate::passes::Pass; pub(crate) const PROPAGATE_DOC_CFG: Pass = Pass { name: "propagate-doc-cfg", - run: propagate_doc_cfg, + run: Some(propagate_doc_cfg), description: "propagates `#[doc(cfg(...))]` to child items", }; diff --git a/src/librustdoc/passes/propagate_stability.rs b/src/librustdoc/passes/propagate_stability.rs index f51e993bfa5..f55479687f8 100644 --- a/src/librustdoc/passes/propagate_stability.rs +++ b/src/librustdoc/passes/propagate_stability.rs @@ -16,7 +16,7 @@ use crate::passes::Pass; pub(crate) const PROPAGATE_STABILITY: Pass = Pass { name: "propagate-stability", - run: propagate_stability, + run: Some(propagate_stability), description: "propagates stability to child items", }; diff --git a/src/librustdoc/passes/strip_aliased_non_local.rs b/src/librustdoc/passes/strip_aliased_non_local.rs index 155ad543831..a078eec048e 100644 --- a/src/librustdoc/passes/strip_aliased_non_local.rs +++ b/src/librustdoc/passes/strip_aliased_non_local.rs @@ -8,7 +8,7 @@ use crate::passes::Pass; pub(crate) const STRIP_ALIASED_NON_LOCAL: Pass = Pass { name: "strip-aliased-non-local", - run: strip_aliased_non_local, + run: Some(strip_aliased_non_local), description: "strips all non-local private aliased items from the output", }; diff --git a/src/librustdoc/passes/strip_hidden.rs b/src/librustdoc/passes/strip_hidden.rs index 430f3d8a574..aba04283e59 100644 --- a/src/librustdoc/passes/strip_hidden.rs +++ b/src/librustdoc/passes/strip_hidden.rs @@ -16,7 +16,7 @@ use crate::passes::{ImplStripper, Pass}; pub(crate) const STRIP_HIDDEN: Pass = Pass { name: "strip-hidden", - run: strip_hidden, + run: Some(strip_hidden), description: "strips all `#[doc(hidden)]` items from the output", }; diff --git a/src/librustdoc/passes/strip_priv_imports.rs b/src/librustdoc/passes/strip_priv_imports.rs index 7b05756ae21..2e9f06bd0a3 100644 --- a/src/librustdoc/passes/strip_priv_imports.rs +++ b/src/librustdoc/passes/strip_priv_imports.rs @@ -8,7 +8,7 @@ use crate::passes::{ImportStripper, Pass}; pub(crate) const STRIP_PRIV_IMPORTS: Pass = Pass { name: "strip-priv-imports", - run: strip_priv_imports, + run: Some(strip_priv_imports), description: "strips all private import statements (`use`, `extern crate`) from a crate", }; diff --git a/src/librustdoc/passes/strip_private.rs b/src/librustdoc/passes/strip_private.rs index 1bafa450be9..78f0ad27740 100644 --- a/src/librustdoc/passes/strip_private.rs +++ b/src/librustdoc/passes/strip_private.rs @@ -8,7 +8,7 @@ use crate::passes::{ImplStripper, ImportStripper, Pass, Stripper}; pub(crate) const STRIP_PRIVATE: Pass = Pass { name: "strip-private", - run: strip_private, + run: Some(strip_private), description: "strips all private items from a crate which cannot be seen externally, \ implies strip-priv-imports", }; From d540e7285ca14393d2b51f486ecc0f26d2f986c7 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 14 Oct 2024 17:51:37 +0200 Subject: [PATCH 292/357] Add regression tests for #130233 --- .../intra-doc/filter-out-private-2.rs | 15 +++++++++++ .../intra-doc/filter-out-private-2.stderr | 14 ++++++++++ .../intra-doc/filter-out-private.rs | 13 ++++++++++ .../intra-doc/filter-out-private.stderr | 22 ++++++++++++++++ tests/rustdoc/intra-doc/filter-out-private.rs | 26 +++++++++++++++++++ 5 files changed, 90 insertions(+) create mode 100644 tests/rustdoc-ui/intra-doc/filter-out-private-2.rs create mode 100644 tests/rustdoc-ui/intra-doc/filter-out-private-2.stderr create mode 100644 tests/rustdoc-ui/intra-doc/filter-out-private.rs create mode 100644 tests/rustdoc-ui/intra-doc/filter-out-private.stderr create mode 100644 tests/rustdoc/intra-doc/filter-out-private.rs diff --git a/tests/rustdoc-ui/intra-doc/filter-out-private-2.rs b/tests/rustdoc-ui/intra-doc/filter-out-private-2.rs new file mode 100644 index 00000000000..9209203c99e --- /dev/null +++ b/tests/rustdoc-ui/intra-doc/filter-out-private-2.rs @@ -0,0 +1,15 @@ +// This test ensures that ambiguities (not) resolved at a later stage still emit an error. + +#![deny(rustdoc::broken_intra_doc_links)] +#![crate_name = "foo"] + +#[doc(hidden)] +pub struct Thing {} + +#[allow(non_snake_case)] +#[doc(hidden)] +pub fn Thing() {} + +/// Do stuff with [`Thing`]. +//~^ ERROR all items matching `Thing` are either private or doc(hidden) +pub fn repro(_: Thing) {} diff --git a/tests/rustdoc-ui/intra-doc/filter-out-private-2.stderr b/tests/rustdoc-ui/intra-doc/filter-out-private-2.stderr new file mode 100644 index 00000000000..394f919de94 --- /dev/null +++ b/tests/rustdoc-ui/intra-doc/filter-out-private-2.stderr @@ -0,0 +1,14 @@ +error: all items matching `Thing` are either private or doc(hidden) + --> $DIR/filter-out-private-2.rs:13:21 + | +LL | /// Do stuff with [`Thing`]. + | ^^^^^ unresolved link + | +note: the lint level is defined here + --> $DIR/filter-out-private-2.rs:3:9 + | +LL | #![deny(rustdoc::broken_intra_doc_links)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/rustdoc-ui/intra-doc/filter-out-private.rs b/tests/rustdoc-ui/intra-doc/filter-out-private.rs new file mode 100644 index 00000000000..f481b51dad0 --- /dev/null +++ b/tests/rustdoc-ui/intra-doc/filter-out-private.rs @@ -0,0 +1,13 @@ +// This test ensures that ambiguities resolved at a later stage still emit an error. + +#![deny(rustdoc::broken_intra_doc_links)] +#![crate_name = "foo"] + +pub struct Thing {} + +#[allow(non_snake_case)] +pub fn Thing() {} + +/// Do stuff with [`Thing`]. +//~^ ERROR `Thing` is both a function and a struct +pub fn repro(_: Thing) {} diff --git a/tests/rustdoc-ui/intra-doc/filter-out-private.stderr b/tests/rustdoc-ui/intra-doc/filter-out-private.stderr new file mode 100644 index 00000000000..1d1830b1f1c --- /dev/null +++ b/tests/rustdoc-ui/intra-doc/filter-out-private.stderr @@ -0,0 +1,22 @@ +error: `Thing` is both a function and a struct + --> $DIR/filter-out-private.rs:11:21 + | +LL | /// Do stuff with [`Thing`]. + | ^^^^^ ambiguous link + | +note: the lint level is defined here + --> $DIR/filter-out-private.rs:3:9 + | +LL | #![deny(rustdoc::broken_intra_doc_links)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: to link to the function, add parentheses + | +LL | /// Do stuff with [`Thing()`]. + | ++ +help: to link to the struct, prefix with `struct@` + | +LL | /// Do stuff with [`struct@Thing`]. + | +++++++ + +error: aborting due to 1 previous error + diff --git a/tests/rustdoc/intra-doc/filter-out-private.rs b/tests/rustdoc/intra-doc/filter-out-private.rs new file mode 100644 index 00000000000..70591b120d8 --- /dev/null +++ b/tests/rustdoc/intra-doc/filter-out-private.rs @@ -0,0 +1,26 @@ +// This test ensures that private/hidden items don't create ambiguity. +// This is a regression test for . + +#![deny(rustdoc::broken_intra_doc_links)] +#![crate_name = "foo"] + +pub struct Thing {} + +#[doc(hidden)] +#[allow(non_snake_case)] +pub fn Thing() {} + +pub struct Bar {} + +#[allow(non_snake_case)] +fn Bar() {} + +//@ has 'foo/fn.repro.html' +//@ has - '//*[@class="toggle top-doc"]/*[@class="docblock"]//a/@href' 'struct.Thing.html' +/// Do stuff with [`Thing`]. +pub fn repro(_: Thing) {} + +//@ has 'foo/fn.repro2.html' +//@ has - '//*[@class="toggle top-doc"]/*[@class="docblock"]//a/@href' 'struct.Bar.html' +/// Do stuff with [`Bar`]. +pub fn repro2(_: Bar) {} From f708d6de79a3e17074d03a641633e2f12972dc1a Mon Sep 17 00:00:00 2001 From: Michal Piotrowski Date: Mon, 14 Oct 2024 15:37:59 +0200 Subject: [PATCH 293/357] Fix match_same_arms in stable_mir --- compiler/stable_mir/src/mir/pretty.rs | 10 +++----- compiler/stable_mir/src/mir/visit.rs | 36 ++++++++++----------------- compiler/stable_mir/src/visitor.rs | 16 ++++++------ 3 files changed, 24 insertions(+), 38 deletions(-) diff --git a/compiler/stable_mir/src/mir/pretty.rs b/compiler/stable_mir/src/mir/pretty.rs index 74081af1d86..d71d96804f3 100644 --- a/compiler/stable_mir/src/mir/pretty.rs +++ b/compiler/stable_mir/src/mir/pretty.rs @@ -189,7 +189,9 @@ fn pretty_terminator_head(writer: &mut W, terminator: &TerminatorKind) fn pretty_successor_labels(terminator: &TerminatorKind) -> Vec { use self::TerminatorKind::*; match terminator { - Resume | Abort | Return | Unreachable => vec![], + Call { target: None, unwind: UnwindAction::Cleanup(_), .. } + | InlineAsm { destination: None, .. } => vec!["unwind".into()], + Resume | Abort | Return | Unreachable | Call { target: None, unwind: _, .. } => vec![], Goto { .. } => vec!["".to_string()], SwitchInt { targets, .. } => targets .branches() @@ -197,19 +199,15 @@ fn pretty_successor_labels(terminator: &TerminatorKind) -> Vec { .chain(iter::once("otherwise".into())) .collect(), Drop { unwind: UnwindAction::Cleanup(_), .. } => vec!["return".into(), "unwind".into()], - Drop { unwind: _, .. } => vec!["return".into()], Call { target: Some(_), unwind: UnwindAction::Cleanup(_), .. } => { vec!["return".into(), "unwind".into()] } - Call { target: Some(_), unwind: _, .. } => vec!["return".into()], - Call { target: None, unwind: UnwindAction::Cleanup(_), .. } => vec!["unwind".into()], - Call { target: None, unwind: _, .. } => vec![], + Drop { unwind: _, .. } | Call { target: Some(_), unwind: _, .. } => vec!["return".into()], Assert { unwind: UnwindAction::Cleanup(_), .. } => { vec!["success".into(), "unwind".into()] } Assert { unwind: _, .. } => vec!["success".into()], InlineAsm { destination: Some(_), .. } => vec!["goto".into(), "unwind".into()], - InlineAsm { destination: None, .. } => vec!["unwind".into()], } } diff --git a/compiler/stable_mir/src/mir/visit.rs b/compiler/stable_mir/src/mir/visit.rs index e2d1ff7fdd3..08fcfa01a06 100644 --- a/compiler/stable_mir/src/mir/visit.rs +++ b/compiler/stable_mir/src/mir/visit.rs @@ -194,27 +194,17 @@ pub trait MirVisitor { self.visit_place(place, PlaceContext::MUTATING, location); self.visit_rvalue(rvalue, location); } - StatementKind::FakeRead(_, place) => { + StatementKind::FakeRead(_, place) | StatementKind::PlaceMention(place) => { self.visit_place(place, PlaceContext::NON_MUTATING, location); } - StatementKind::SetDiscriminant { place, .. } => { + StatementKind::SetDiscriminant { place, .. } + | StatementKind::Deinit(place) + | StatementKind::Retag(_, place) => { self.visit_place(place, PlaceContext::MUTATING, location); } - StatementKind::Deinit(place) => { - self.visit_place(place, PlaceContext::MUTATING, location); - } - StatementKind::StorageLive(local) => { + StatementKind::StorageLive(local) | StatementKind::StorageDead(local) => { self.visit_local(local, PlaceContext::NON_USE, location); } - StatementKind::StorageDead(local) => { - self.visit_local(local, PlaceContext::NON_USE, location); - } - StatementKind::Retag(_, place) => { - self.visit_place(place, PlaceContext::MUTATING, location); - } - StatementKind::PlaceMention(place) => { - self.visit_place(place, PlaceContext::NON_MUTATING, location); - } StatementKind::AscribeUserType { place, projections, variance: _ } => { self.visit_place(place, PlaceContext::NON_USE, location); self.visit_user_type_projection(projections); @@ -234,8 +224,7 @@ pub trait MirVisitor { self.visit_operand(count, location); } }, - StatementKind::ConstEvalCounter => {} - StatementKind::Nop => {} + StatementKind::ConstEvalCounter | StatementKind::Nop => {} } } @@ -304,14 +293,15 @@ pub trait MirVisitor { location: Location, ) { match elem { - ProjectionElem::Deref => {} + ProjectionElem::Downcast(_idx) => {} + ProjectionElem::ConstantIndex { offset: _, min_length: _, from_end: _ } + | ProjectionElem::Deref + | ProjectionElem::Subslice { from: _, to: _, from_end: _ } => {} ProjectionElem::Field(_idx, ty) => self.visit_ty(ty, location), ProjectionElem::Index(local) => self.visit_local(local, ptx, location), - ProjectionElem::ConstantIndex { offset: _, min_length: _, from_end: _ } => {} - ProjectionElem::Subslice { from: _, to: _, from_end: _ } => {} - ProjectionElem::Downcast(_idx) => {} - ProjectionElem::OpaqueCast(ty) => self.visit_ty(ty, location), - ProjectionElem::Subtype(ty) => self.visit_ty(ty, location), + ProjectionElem::OpaqueCast(ty) | ProjectionElem::Subtype(ty) => { + self.visit_ty(ty, location) + } } } diff --git a/compiler/stable_mir/src/visitor.rs b/compiler/stable_mir/src/visitor.rs index 3c769b2d37c..48260285408 100644 --- a/compiler/stable_mir/src/visitor.rs +++ b/compiler/stable_mir/src/visitor.rs @@ -35,8 +35,7 @@ impl Visitable for Ty { match self.kind() { super::ty::TyKind::RigidTy(ty) => ty.visit(visitor)?, super::ty::TyKind::Alias(_, alias) => alias.args.visit(visitor)?, - super::ty::TyKind::Param(_) => {} - super::ty::TyKind::Bound(_, _) => {} + super::ty::TyKind::Param(_) | super::ty::TyKind::Bound(_, _) => {} } ControlFlow::Continue(()) } @@ -48,8 +47,7 @@ impl Visitable for TyConst { } fn super_visit(&self, visitor: &mut V) -> ControlFlow { match &self.kind { - crate::ty::TyConstKind::Param(_) => {} - crate::ty::TyConstKind::Bound(_, _) => {} + crate::ty::TyConstKind::Param(_) | crate::ty::TyConstKind::Bound(_, _) => {} crate::ty::TyConstKind::Unevaluated(_, args) => args.visit(visitor)?, crate::ty::TyConstKind::Value(ty, alloc) => { alloc.visit(visitor)?; @@ -166,17 +164,17 @@ impl Visitable for RigidTy { reg.visit(visitor); ty.visit(visitor) } - RigidTy::FnDef(_, args) => args.visit(visitor), + RigidTy::Adt(_, args) + | RigidTy::Closure(_, args) + | RigidTy::Coroutine(_, args, _) + | RigidTy::CoroutineWitness(_, args) + | RigidTy::FnDef(_, args) => args.visit(visitor), RigidTy::FnPtr(sig) => sig.visit(visitor), - RigidTy::Closure(_, args) => args.visit(visitor), - RigidTy::Coroutine(_, args, _) => args.visit(visitor), - RigidTy::CoroutineWitness(_, args) => args.visit(visitor), RigidTy::Dynamic(pred, r, _) => { pred.visit(visitor)?; r.visit(visitor) } RigidTy::Tuple(fields) => fields.visit(visitor), - RigidTy::Adt(_, args) => args.visit(visitor), } } } From 1412993757838712aa345247faf224733468d96e Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 14 Oct 2024 16:29:49 +0200 Subject: [PATCH 294/357] Avoid some needless monomorphizations --- src/tools/miri/src/concurrency/init_once.rs | 7 ++----- src/tools/miri/src/concurrency/thread.rs | 10 +++++----- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/src/tools/miri/src/concurrency/init_once.rs b/src/tools/miri/src/concurrency/init_once.rs index c3c04428c94..534f02545bd 100644 --- a/src/tools/miri/src/concurrency/init_once.rs +++ b/src/tools/miri/src/concurrency/init_once.rs @@ -2,6 +2,7 @@ use std::collections::VecDeque; use rustc_index::Idx; +use super::thread::DynUnblockCallback; use super::vector_clock::VClock; use crate::*; @@ -34,11 +35,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { /// Put the thread into the queue waiting for the initialization. #[inline] - fn init_once_enqueue_and_block( - &mut self, - id: InitOnceId, - callback: impl UnblockCallback<'tcx> + 'tcx, - ) { + fn init_once_enqueue_and_block(&mut self, id: InitOnceId, callback: DynUnblockCallback<'tcx>) { let this = self.eval_context_mut(); let thread = this.active_thread(); let init_once = &mut this.machine.sync.init_onces[id]; diff --git a/src/tools/miri/src/concurrency/thread.rs b/src/tools/miri/src/concurrency/thread.rs index dcae85109a5..3c5fb74fb76 100644 --- a/src/tools/miri/src/concurrency/thread.rs +++ b/src/tools/miri/src/concurrency/thread.rs @@ -50,7 +50,7 @@ pub trait UnblockCallback<'tcx>: VisitProvenance { fn timeout(self: Box, _ecx: &mut InterpCx<'tcx, MiriMachine<'tcx>>) -> InterpResult<'tcx>; } -type DynUnblockCallback<'tcx> = Box + 'tcx>; +pub type DynUnblockCallback<'tcx> = Box + 'tcx>; #[macro_export] macro_rules! callback { @@ -101,7 +101,7 @@ macro_rules! callback { } } - Callback { $($name,)* _phantom: std::marker::PhantomData } + Box::new(Callback { $($name,)* _phantom: std::marker::PhantomData }) }} } @@ -715,11 +715,11 @@ impl<'tcx> ThreadManager<'tcx> { &mut self, reason: BlockReason, timeout: Option, - callback: impl UnblockCallback<'tcx> + 'tcx, + callback: DynUnblockCallback<'tcx>, ) { let state = &mut self.threads[self.active_thread].state; assert!(state.is_enabled()); - *state = ThreadState::Blocked { reason, timeout, callback: Box::new(callback) } + *state = ThreadState::Blocked { reason, timeout, callback } } /// Change the active thread to some enabled thread. @@ -1032,7 +1032,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { &mut self, reason: BlockReason, timeout: Option<(TimeoutClock, TimeoutAnchor, Duration)>, - callback: impl UnblockCallback<'tcx> + 'tcx, + callback: DynUnblockCallback<'tcx>, ) { let this = self.eval_context_mut(); let timeout = timeout.map(|(clock, anchor, duration)| { From 5a8405a5fa55526af743a44abf9c57d1452afbaa Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 14 Oct 2024 14:18:13 -0400 Subject: [PATCH 295/357] Don't report on_unimplemented for negative traits --- .../rustc_hir_typeck/src/method/suggest.rs | 2 +- .../traits/fulfillment_errors.rs | 2 +- .../traits/on_unimplemented.rs | 20 +++++++++++-------- .../negative-bounds/on-unimplemented.rs | 12 +++++++++++ .../negative-bounds/on-unimplemented.stderr | 18 +++++++++++++++++ 5 files changed, 44 insertions(+), 10 deletions(-) create mode 100644 tests/ui/traits/negative-bounds/on-unimplemented.rs create mode 100644 tests/ui/traits/negative-bounds/on-unimplemented.stderr diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 4f726f3ed38..0933e90f8ba 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -952,7 +952,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { continue; } unimplemented_traits.entry(p.trait_ref.def_id).or_insert(( - predicate.kind().rebind(p.trait_ref), + predicate.kind().rebind(p), Obligation { cause: cause.clone(), param_env: self.param_env, diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 824c25db07d..26b0faca258 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -202,7 +202,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { notes, parent_label, append_const_msg, - } = self.on_unimplemented_note(main_trait_ref, o, &mut long_ty_file); + } = self.on_unimplemented_note(main_trait_predicate, o, &mut long_ty_file); let have_alt_message = message.is_some() || label.is_some(); let is_try_conversion = self.is_try_conversion(span, main_trait_ref.def_id()); diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs index c3100c48b0a..cd41ab9fa6c 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs @@ -9,7 +9,7 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_macros::LintDiagnostic; use rustc_middle::bug; use rustc_middle::ty::print::PrintTraitRefExt as _; -use rustc_middle::ty::{self, GenericArgsRef, GenericParamDefKind, TyCtxt}; +use rustc_middle::ty::{self, GenericArgsRef, GenericParamDefKind, ToPolyTraitRef, TyCtxt}; use rustc_parse_format::{ParseMode, Parser, Piece, Position}; use rustc_session::lint::builtin::UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES; use rustc_span::Span; @@ -108,14 +108,18 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { pub fn on_unimplemented_note( &self, - trait_ref: ty::PolyTraitRef<'tcx>, + trait_pred: ty::PolyTraitPredicate<'tcx>, obligation: &PredicateObligation<'tcx>, long_ty_file: &mut Option, ) -> OnUnimplementedNote { + if trait_pred.polarity() != ty::PredicatePolarity::Positive { + return OnUnimplementedNote::default(); + } + let (def_id, args) = self - .impl_similar_to(trait_ref, obligation) - .unwrap_or_else(|| (trait_ref.def_id(), trait_ref.skip_binder().args)); - let trait_ref = trait_ref.skip_binder(); + .impl_similar_to(trait_pred.to_poly_trait_ref(), obligation) + .unwrap_or_else(|| (trait_pred.def_id(), trait_pred.skip_binder().trait_ref.args)); + let trait_pred = trait_pred.skip_binder(); let mut flags = vec![]; // FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty): HIR is not present for RPITITs, @@ -144,13 +148,13 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { flags.push((sym::cause, Some("MainFunctionType".to_string()))); } - flags.push((sym::Trait, Some(trait_ref.print_trait_sugared().to_string()))); + flags.push((sym::Trait, Some(trait_pred.trait_ref.print_trait_sugared().to_string()))); // Add all types without trimmed paths or visible paths, ensuring they end up with // their "canonical" def path. ty::print::with_no_trimmed_paths!(ty::print::with_no_visible_paths!({ let generics = self.tcx.generics_of(def_id); - let self_ty = trait_ref.self_ty(); + let self_ty = trait_pred.self_ty(); // This is also included through the generics list as `Self`, // but the parser won't allow you to use it flags.push((sym::_Self, Some(self_ty.to_string()))); @@ -266,7 +270,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { })); if let Ok(Some(command)) = OnUnimplementedDirective::of_item(self.tcx, def_id) { - command.evaluate(self.tcx, trait_ref, &flags, long_ty_file) + command.evaluate(self.tcx, trait_pred.trait_ref, &flags, long_ty_file) } else { OnUnimplementedNote::default() } diff --git a/tests/ui/traits/negative-bounds/on-unimplemented.rs b/tests/ui/traits/negative-bounds/on-unimplemented.rs new file mode 100644 index 00000000000..34582590861 --- /dev/null +++ b/tests/ui/traits/negative-bounds/on-unimplemented.rs @@ -0,0 +1,12 @@ +#![feature(negative_bounds)] + +#[diagnostic::on_unimplemented(message = "this ain't fooing")] +trait Foo {} +struct NotFoo; + +fn hello() -> impl !Foo { + //~^ ERROR the trait bound `NotFoo: !Foo` is not satisfied + NotFoo +} + +fn main() {} diff --git a/tests/ui/traits/negative-bounds/on-unimplemented.stderr b/tests/ui/traits/negative-bounds/on-unimplemented.stderr new file mode 100644 index 00000000000..07483e788e5 --- /dev/null +++ b/tests/ui/traits/negative-bounds/on-unimplemented.stderr @@ -0,0 +1,18 @@ +error[E0277]: the trait bound `NotFoo: !Foo` is not satisfied + --> $DIR/on-unimplemented.rs:7:15 + | +LL | fn hello() -> impl !Foo { + | ^^^^^^^^^ the trait bound `NotFoo: !Foo` is not satisfied +LL | +LL | NotFoo + | ------ return type was inferred to be `NotFoo` here + | +help: this trait has no implementations, consider adding one + --> $DIR/on-unimplemented.rs:4:1 + | +LL | trait Foo {} + | ^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. From c3b696dec99e7646b84d8b43c05a113acf7d249c Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 14 Oct 2024 14:40:07 -0400 Subject: [PATCH 296/357] Suppress import errors for traits that couldve applied in method lookup on error --- compiler/rustc_hir_typeck/src/method/mod.rs | 2 ++ .../rustc_hir_typeck/src/method/suggest.rs | 8 ++++++++ tests/ui/use/unused-trait-with-method-err.rs | 17 +++++++++++++++++ .../use/unused-trait-with-method-err.stderr | 19 +++++++++++++++++++ 4 files changed, 46 insertions(+) create mode 100644 tests/ui/use/unused-trait-with-method-err.rs create mode 100644 tests/ui/use/unused-trait-with-method-err.stderr diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs index cb8b1df2c6e..1b65dc8214c 100644 --- a/compiler/rustc_hir_typeck/src/method/mod.rs +++ b/compiler/rustc_hir_typeck/src/method/mod.rs @@ -199,6 +199,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self_ty, segment, span, call_expr, self_expr, &pick, args, ); + // NOTE: on the failure path, we also record the possibly-used trait methods + // since an unused import warning is kinda distracting from the method error. for &import_id in &pick.import_ids { debug!("used_trait_import: {:?}", import_id); self.typeck_results.borrow_mut().used_trait_imports.insert(import_id); diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 4f726f3ed38..05c8912aec1 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -191,6 +191,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected: Expectation<'tcx>, trait_missing_method: bool, ) -> ErrorGuaranteed { + // NOTE: Reporting a method error should also suppress any unused trait errors, + // since the method error is very possibly the reason why the trait wasn't used. + for &import_id in + self.tcx.in_scope_traits(call_id).into_iter().flatten().flat_map(|c| &c.import_ids) + { + self.typeck_results.borrow_mut().used_trait_imports.insert(import_id); + } + let (span, sugg_span, source, item_name, args) = match self.tcx.hir_node(call_id) { hir::Node::Expr(&hir::Expr { kind: hir::ExprKind::MethodCall(segment, rcvr, args, _), diff --git a/tests/ui/use/unused-trait-with-method-err.rs b/tests/ui/use/unused-trait-with-method-err.rs new file mode 100644 index 00000000000..37684e1bf81 --- /dev/null +++ b/tests/ui/use/unused-trait-with-method-err.rs @@ -0,0 +1,17 @@ +// Test that we don't issue an unused import warning when there's +// a method lookup error and that trait was possibly applicable. + +use foo::Bar; + +mod foo { + pub trait Bar { + fn uwu(&self) {} + } +} + +struct Foo; + +fn main() { + Foo.uwu(); + //~^ ERROR no method named `uwu` found for struct `Foo` in the current scope +} diff --git a/tests/ui/use/unused-trait-with-method-err.stderr b/tests/ui/use/unused-trait-with-method-err.stderr new file mode 100644 index 00000000000..7ca4563673b --- /dev/null +++ b/tests/ui/use/unused-trait-with-method-err.stderr @@ -0,0 +1,19 @@ +error[E0599]: no method named `uwu` found for struct `Foo` in the current scope + --> $DIR/unused-trait-with-method-err.rs:15:9 + | +LL | struct Foo; + | ---------- method `uwu` not found for this struct +... +LL | Foo.uwu(); + | ^^^ method not found in `Foo` + | + = help: items from traits can only be used if the trait is implemented and in scope +note: `Bar` defines an item `uwu`, perhaps you need to implement it + --> $DIR/unused-trait-with-method-err.rs:7:5 + | +LL | pub trait Bar { + | ^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0599`. From 64259a7b8dec493da7fcd1296eea86fafbadc484 Mon Sep 17 00:00:00 2001 From: Yoh Deadfall Date: Mon, 14 Oct 2024 00:19:39 +0300 Subject: [PATCH 297/357] Added a variadic argument helper --- src/tools/miri/src/helpers.rs | 15 +++ src/tools/miri/src/shims/unix/fd.rs | 95 ++++++++++--------- src/tools/miri/src/shims/unix/fs.rs | 18 +--- .../src/shims/unix/linux/foreign_items.rs | 35 +++---- .../fs/unix_open_missing_required_mode.rs | 2 +- .../fs/unix_open_missing_required_mode.stderr | 6 +- 6 files changed, 86 insertions(+), 85 deletions(-) diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index 8bd429deefc..812cc4295fc 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -1180,6 +1180,21 @@ where throw_ub_format!("incorrect number of arguments: got {}, expected {}", args.len(), N) } +/// Check that the number of args is at least the minumim what we expect. +pub fn check_min_arg_count<'a, 'tcx, const N: usize>( + name: &'a str, + args: &'a [OpTy<'tcx>], +) -> InterpResult<'tcx, &'a [OpTy<'tcx>; N]> { + if let Some((ops, _)) = args.split_first_chunk() { + return interp_ok(ops); + } + throw_ub_format!( + "incorrect number of arguments for `{name}`: got {}, expected at least {}", + args.len(), + N + ) +} + pub fn isolation_abort_error<'tcx>(name: &str) -> InterpResult<'tcx> { throw_machine_stop!(TerminationInfo::UnsupportedInIsolation(format!( "{name} not available when isolation is enabled", diff --git a/src/tools/miri/src/shims/unix/fd.rs b/src/tools/miri/src/shims/unix/fd.rs index 34e29760da7..e3914640037 100644 --- a/src/tools/miri/src/shims/unix/fd.rs +++ b/src/tools/miri/src/shims/unix/fd.rs @@ -9,6 +9,7 @@ use std::rc::{Rc, Weak}; use rustc_target::abi::Size; +use crate::helpers::check_min_arg_count; use crate::shims::unix::linux::epoll::EpollReadyEvents; use crate::shims::unix::*; use crate::*; @@ -481,56 +482,62 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn fcntl(&mut self, args: &[OpTy<'tcx>]) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); - let [fd_num, cmd, ..] = args else { - throw_ub_format!( - "incorrect number of arguments for fcntl: got {}, expected at least 2", - args.len() - ); - }; + let [fd_num, cmd] = check_min_arg_count("fcntl", args)?; + let fd_num = this.read_scalar(fd_num)?.to_i32()?; let cmd = this.read_scalar(cmd)?.to_i32()?; + let f_getfd = this.eval_libc_i32("F_GETFD"); + let f_dupfd = this.eval_libc_i32("F_DUPFD"); + let f_dupfd_cloexec = this.eval_libc_i32("F_DUPFD_CLOEXEC"); + // We only support getting the flags for a descriptor. - if cmd == this.eval_libc_i32("F_GETFD") { - // Currently this is the only flag that `F_GETFD` returns. It is OK to just return the - // `FD_CLOEXEC` value without checking if the flag is set for the file because `std` - // always sets this flag when opening a file. However we still need to check that the - // file itself is open. - interp_ok(Scalar::from_i32(if this.machine.fds.is_fd_num(fd_num) { - this.eval_libc_i32("FD_CLOEXEC") - } else { - this.fd_not_found()? - })) - } else if cmd == this.eval_libc_i32("F_DUPFD") - || cmd == this.eval_libc_i32("F_DUPFD_CLOEXEC") - { - // Note that we always assume the FD_CLOEXEC flag is set for every open file, in part - // because exec() isn't supported. The F_DUPFD and F_DUPFD_CLOEXEC commands only - // differ in whether the FD_CLOEXEC flag is pre-set on the new file descriptor, - // thus they can share the same implementation here. - let [_, _, start, ..] = args else { - throw_ub_format!( - "incorrect number of arguments for fcntl with cmd=`F_DUPFD`/`F_DUPFD_CLOEXEC`: got {}, expected at least 3", - args.len() - ); - }; - let start = this.read_scalar(start)?.to_i32()?; - - match this.machine.fds.get(fd_num) { - Some(fd) => - interp_ok(Scalar::from_i32(this.machine.fds.insert_with_min_num(fd, start))), - None => interp_ok(Scalar::from_i32(this.fd_not_found()?)), - } - } else if this.tcx.sess.target.os == "macos" && cmd == this.eval_libc_i32("F_FULLFSYNC") { - // Reject if isolation is enabled. - if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op { - this.reject_in_isolation("`fcntl`", reject_with)?; - return this.set_last_error_and_return_i32(ErrorKind::PermissionDenied); + match cmd { + cmd if cmd == f_getfd => { + // Currently this is the only flag that `F_GETFD` returns. It is OK to just return the + // `FD_CLOEXEC` value without checking if the flag is set for the file because `std` + // always sets this flag when opening a file. However we still need to check that the + // file itself is open. + interp_ok(Scalar::from_i32(if this.machine.fds.is_fd_num(fd_num) { + this.eval_libc_i32("FD_CLOEXEC") + } else { + this.fd_not_found()? + })) } + cmd if cmd == f_dupfd || cmd == f_dupfd_cloexec => { + // Note that we always assume the FD_CLOEXEC flag is set for every open file, in part + // because exec() isn't supported. The F_DUPFD and F_DUPFD_CLOEXEC commands only + // differ in whether the FD_CLOEXEC flag is pre-set on the new file descriptor, + // thus they can share the same implementation here. + let cmd_name = if cmd == f_dupfd { + "fcntl(fd, F_DUPFD, ...)" + } else { + "fcntl(fd, F_DUPFD_CLOEXEC, ...)" + }; - this.ffullsync_fd(fd_num) - } else { - throw_unsup_format!("the {:#x} command is not supported for `fcntl`)", cmd); + let [_, _, start] = check_min_arg_count(cmd_name, args)?; + let start = this.read_scalar(start)?.to_i32()?; + + if let Some(fd) = this.machine.fds.get(fd_num) { + interp_ok(Scalar::from_i32(this.machine.fds.insert_with_min_num(fd, start))) + } else { + interp_ok(Scalar::from_i32(this.fd_not_found()?)) + } + } + cmd if this.tcx.sess.target.os == "macos" + && cmd == this.eval_libc_i32("F_FULLFSYNC") => + { + // Reject if isolation is enabled. + if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op { + this.reject_in_isolation("`fcntl`", reject_with)?; + return this.set_last_error_and_return_i32(ErrorKind::PermissionDenied); + } + + this.ffullsync_fd(fd_num) + } + cmd => { + throw_unsup_format!("fcntl: unsupported command {cmd:#x}"); + } } } diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs index 6c9a2beac2d..4b3ae8e0520 100644 --- a/src/tools/miri/src/shims/unix/fs.rs +++ b/src/tools/miri/src/shims/unix/fs.rs @@ -13,6 +13,7 @@ use rustc_target::abi::Size; use self::fd::FlockOp; use self::shims::time::system_time_to_duration; +use crate::helpers::check_min_arg_count; use crate::shims::os_str::bytes_to_os_str; use crate::shims::unix::fd::FileDescriptionRef; use crate::shims::unix::*; @@ -433,12 +434,7 @@ fn maybe_sync_file( impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn open(&mut self, args: &[OpTy<'tcx>]) -> InterpResult<'tcx, Scalar> { - let [path_raw, flag, ..] = args else { - throw_ub_format!( - "incorrect number of arguments for `open`: got {}, expected at least 2", - args.len() - ); - }; + let [path_raw, flag] = check_min_arg_count("open", args)?; let this = self.eval_context_mut(); @@ -492,14 +488,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Get the mode. On macOS, the argument type `mode_t` is actually `u16`, but // C integer promotion rules mean that on the ABI level, it gets passed as `u32` // (see https://github.com/rust-lang/rust/issues/71915). - let mode = if let Some(arg) = args.get(2) { - this.read_scalar(arg)?.to_u32()? - } else { - throw_ub_format!( - "incorrect number of arguments for `open` with `O_CREAT`: got {}, expected at least 3", - args.len() - ); - }; + let [_, _, mode] = check_min_arg_count("open(pathname, O_CREAT, ...)", args)?; + let mode = this.read_scalar(mode)?.to_u32()?; #[cfg(unix)] { diff --git a/src/tools/miri/src/shims/unix/linux/foreign_items.rs b/src/tools/miri/src/shims/unix/linux/foreign_items.rs index 1d31c12be6f..6c8345652c2 100644 --- a/src/tools/miri/src/shims/unix/linux/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/linux/foreign_items.rs @@ -5,6 +5,7 @@ use self::shims::unix::linux::epoll::EvalContextExt as _; use self::shims::unix::linux::eventfd::EvalContextExt as _; use self::shims::unix::linux::mem::EvalContextExt as _; use self::shims::unix::linux::sync::futex; +use crate::helpers::check_min_arg_count; use crate::machine::{SIGRTMAX, SIGRTMIN}; use crate::shims::unix::*; use crate::*; @@ -127,23 +128,15 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let sys_futex = this.eval_libc("SYS_futex").to_target_usize(this)?; let sys_eventfd2 = this.eval_libc("SYS_eventfd2").to_target_usize(this)?; - if args.is_empty() { - throw_ub_format!( - "incorrect number of arguments for syscall: got 0, expected at least 1" - ); - } - match this.read_target_usize(&args[0])? { + let [op] = check_min_arg_count("syscall", args)?; + match this.read_target_usize(op)? { // `libc::syscall(NR_GETRANDOM, buf.as_mut_ptr(), buf.len(), GRND_NONBLOCK)` // is called if a `HashMap` is created the regular way (e.g. HashMap). - id if id == sys_getrandom => { + num if num == sys_getrandom => { // Used by getrandom 0.1 // The first argument is the syscall id, so skip over it. - let [_, ptr, len, flags, ..] = args else { - throw_ub_format!( - "incorrect number of arguments for `getrandom` syscall: got {}, expected at least 4", - args.len() - ); - }; + let [_, ptr, len, flags] = + check_min_arg_count("syscall(SYS_getrandom, ...)", args)?; let ptr = this.read_pointer(ptr)?; let len = this.read_target_usize(len)?; @@ -156,22 +149,18 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(Scalar::from_target_usize(len, this), dest)?; } // `futex` is used by some synchronization primitives. - id if id == sys_futex => { + num if num == sys_futex => { futex(this, &args[1..], dest)?; } - id if id == sys_eventfd2 => { - let [_, initval, flags, ..] = args else { - throw_ub_format!( - "incorrect number of arguments for `eventfd2` syscall: got {}, expected at least 3", - args.len() - ); - }; + num if num == sys_eventfd2 => { + let [_, initval, flags] = + check_min_arg_count("syscall(SYS_evetfd2, ...)", args)?; let result = this.eventfd(initval, flags)?; this.write_int(result.to_i32()?, dest)?; } - id => { - throw_unsup_format!("can't execute syscall with ID {id}"); + num => { + throw_unsup_format!("syscall: unsupported syscall number {num}"); } } } diff --git a/src/tools/miri/tests/fail-dep/libc/fs/unix_open_missing_required_mode.rs b/src/tools/miri/tests/fail-dep/libc/fs/unix_open_missing_required_mode.rs index b763121080e..4b6f344a78e 100644 --- a/src/tools/miri/tests/fail-dep/libc/fs/unix_open_missing_required_mode.rs +++ b/src/tools/miri/tests/fail-dep/libc/fs/unix_open_missing_required_mode.rs @@ -8,5 +8,5 @@ fn main() { fn test_file_open_missing_needed_mode() { let name = b"missing_arg.txt\0"; let name_ptr = name.as_ptr().cast::(); - let _fd = unsafe { libc::open(name_ptr, libc::O_CREAT) }; //~ ERROR: Undefined Behavior: incorrect number of arguments for `open` with `O_CREAT`: got 2, expected at least 3 + let _fd = unsafe { libc::open(name_ptr, libc::O_CREAT) }; //~ ERROR: Undefined Behavior: incorrect number of arguments for `open(pathname, O_CREAT, ...)`: got 2, expected at least 3 } diff --git a/src/tools/miri/tests/fail-dep/libc/fs/unix_open_missing_required_mode.stderr b/src/tools/miri/tests/fail-dep/libc/fs/unix_open_missing_required_mode.stderr index 971a2d76053..ca9e3c6c4be 100644 --- a/src/tools/miri/tests/fail-dep/libc/fs/unix_open_missing_required_mode.stderr +++ b/src/tools/miri/tests/fail-dep/libc/fs/unix_open_missing_required_mode.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: incorrect number of arguments for `open` with `O_CREAT`: got 2, expected at least 3 +error: Undefined Behavior: incorrect number of arguments for `open(pathname, O_CREAT, ...)`: got 2, expected at least 3 --> tests/fail-dep/libc/fs/unix_open_missing_required_mode.rs:LL:CC | -LL | ...safe { libc::open(name_ptr, libc::O_CREAT) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect number of arguments for `open` with `O_CREAT`: got 2, expected at least 3 +LL | ... { libc::open(name_ptr, libc::O_CREAT) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect number of arguments for `open(pathname, O_CREAT, ...)`: got 2, expected at least 3 | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information From eb6062ce00cce6fa1973466e6b2fb376e3e89cc8 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Mon, 14 Oct 2024 15:27:37 -0400 Subject: [PATCH 298/357] Resolved python deprecation warning in publish_toolstate.py `utcnow()` is deprecated in favor of passing a timezone to `now()`. `utcnow()` would return a tz-naive datetime, while this returns a tz-aware datetime. For the purposes of the formatting we do, these are the same. --- src/tools/publish_toolstate.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/tools/publish_toolstate.py b/src/tools/publish_toolstate.py index 860d21876de..328b48e04d2 100755 --- a/src/tools/publish_toolstate.py +++ b/src/tools/publish_toolstate.py @@ -235,7 +235,9 @@ try: exit(0) cur_commit = sys.argv[1] - cur_datetime = datetime.datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ') + cur_datetime = datetime.datetime.now(datetime.timezone.utc).strftime( + '%Y-%m-%dT%H:%M:%SZ' + ) cur_commit_msg = sys.argv[2] save_message_to_path = sys.argv[3] github_token = sys.argv[4] From af9842428587d1bf05a8a432411b0ade0d5b2c8e Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 14 Oct 2024 21:36:37 +0200 Subject: [PATCH 299/357] add test ensuring a moved mutex deadlocks --- .../fail/concurrency/mutex-leak-move-deadlock.rs | 16 ++++++++++++++++ .../concurrency/mutex-leak-move-deadlock.stderr | 16 ++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 src/tools/miri/tests/fail/concurrency/mutex-leak-move-deadlock.rs create mode 100644 src/tools/miri/tests/fail/concurrency/mutex-leak-move-deadlock.stderr diff --git a/src/tools/miri/tests/fail/concurrency/mutex-leak-move-deadlock.rs b/src/tools/miri/tests/fail/concurrency/mutex-leak-move-deadlock.rs new file mode 100644 index 00000000000..b996fcaf45d --- /dev/null +++ b/src/tools/miri/tests/fail/concurrency/mutex-leak-move-deadlock.rs @@ -0,0 +1,16 @@ +//@error-in-other-file: deadlock +//@normalize-stderr-test: "src/sys/.*\.rs" -> "$$FILE" +//@normalize-stderr-test: "LL \| .*" -> "LL | $$CODE" +//@normalize-stderr-test: "\| +\^+" -> "| ^" +//@normalize-stderr-test: "\n *= note:.*" -> "" +use std::mem; +use std::sync::Mutex; + +fn main() { + let m = Mutex::new(0); + mem::forget(m.lock()); + // Move the lock while it is "held" (really: leaked) + let m2 = m; + // Now try to acquire the lock again. + let _guard = m2.lock(); +} diff --git a/src/tools/miri/tests/fail/concurrency/mutex-leak-move-deadlock.stderr b/src/tools/miri/tests/fail/concurrency/mutex-leak-move-deadlock.stderr new file mode 100644 index 00000000000..0ca8b3558d4 --- /dev/null +++ b/src/tools/miri/tests/fail/concurrency/mutex-leak-move-deadlock.stderr @@ -0,0 +1,16 @@ +error: deadlock: the evaluated program deadlocked + --> RUSTLIB/std/$FILE:LL:CC + | +LL | $CODE + | ^ the evaluated program deadlocked + | +note: inside `main` + --> tests/fail/concurrency/mutex-leak-move-deadlock.rs:LL:CC + | +LL | $CODE + | ^ + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + From b73e613e008fd4a07a52ec7cef7c3af7db716b3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20S=C3=A1nchez=20Mu=C3=B1oz?= Date: Mon, 14 Oct 2024 20:58:32 +0200 Subject: [PATCH 300/357] De-duplicate and move `adjust_nan` to `InterpCx` --- .../rustc_const_eval/src/interpret/cast.rs | 27 +++++++------------ .../src/interpret/eval_context.rs | 8 ++++++ .../src/interpret/operator.rs | 3 +-- src/tools/miri/src/operator.rs | 4 --- 4 files changed, 19 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs index 30b5a8d70bc..1def3d08328 100644 --- a/compiler/rustc_const_eval/src/interpret/cast.rs +++ b/compiler/rustc_const_eval/src/interpret/cast.rs @@ -334,19 +334,6 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { { use rustc_type_ir::TyKind::*; - fn adjust_nan< - 'tcx, - M: Machine<'tcx>, - F1: rustc_apfloat::Float + FloatConvert, - F2: rustc_apfloat::Float, - >( - ecx: &InterpCx<'tcx, M>, - f1: F1, - f2: F2, - ) -> F2 { - if f2.is_nan() { M::generate_nan(ecx, &[f1]) } else { f2 } - } - match *dest_ty.kind() { // float -> uint Uint(t) => { @@ -367,11 +354,17 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { } // float -> float Float(fty) => match fty { - FloatTy::F16 => Scalar::from_f16(adjust_nan(self, f, f.convert(&mut false).value)), - FloatTy::F32 => Scalar::from_f32(adjust_nan(self, f, f.convert(&mut false).value)), - FloatTy::F64 => Scalar::from_f64(adjust_nan(self, f, f.convert(&mut false).value)), + FloatTy::F16 => { + Scalar::from_f16(self.adjust_nan(f.convert(&mut false).value, &[f])) + } + FloatTy::F32 => { + Scalar::from_f32(self.adjust_nan(f.convert(&mut false).value, &[f])) + } + FloatTy::F64 => { + Scalar::from_f64(self.adjust_nan(f.convert(&mut false).value, &[f])) + } FloatTy::F128 => { - Scalar::from_f128(adjust_nan(self, f, f.convert(&mut false).value)) + Scalar::from_f128(self.adjust_nan(f.convert(&mut false).value, &[f])) } }, // That's it. diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index 5165f95afd5..02dd7821ef6 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -599,6 +599,14 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { pub fn generate_stacktrace(&self) -> Vec> { Frame::generate_stacktrace_from_stack(self.stack()) } + + pub fn adjust_nan(&self, f: F2, inputs: &[F1]) -> F2 + where + F1: rustc_apfloat::Float + rustc_apfloat::FloatConvert, + F2: rustc_apfloat::Float, + { + if f.is_nan() { M::generate_nan(self, inputs) } else { f } + } } #[doc(hidden)] diff --git a/compiler/rustc_const_eval/src/interpret/operator.rs b/compiler/rustc_const_eval/src/interpret/operator.rs index 52cd9b898bb..b28ac68ac54 100644 --- a/compiler/rustc_const_eval/src/interpret/operator.rs +++ b/compiler/rustc_const_eval/src/interpret/operator.rs @@ -64,8 +64,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { use rustc_middle::mir::BinOp::*; // Performs appropriate non-deterministic adjustments of NaN results. - let adjust_nan = - |f: F| -> F { if f.is_nan() { M::generate_nan(self, &[l, r]) } else { f } }; + let adjust_nan = |f: F| -> F { self.adjust_nan(f, &[l, r]) }; match bin_op { Eq => ImmTy::from_bool(l == r, *self.tcx), diff --git a/src/tools/miri/src/operator.rs b/src/tools/miri/src/operator.rs index c0911fa717f..8e06f4258d6 100644 --- a/src/tools/miri/src/operator.rs +++ b/src/tools/miri/src/operator.rs @@ -115,8 +115,4 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { nan } } - - fn adjust_nan, F2: Float>(&self, f: F2, inputs: &[F1]) -> F2 { - if f.is_nan() { self.generate_nan(inputs) } else { f } - } } From 4e438f7d6b7f6fbf2bb0c1ffe6ffe0b6bfc7fa38 Mon Sep 17 00:00:00 2001 From: George Bateman Date: Mon, 14 Oct 2024 20:47:24 +0100 Subject: [PATCH 301/357] Fix two const-hacks --- library/core/src/time.rs | 8 +++----- library/std/src/sys/pal/windows/args.rs | 19 ++++--------------- 2 files changed, 7 insertions(+), 20 deletions(-) diff --git a/library/core/src/time.rs b/library/core/src/time.rs index f7ea7e06e9c..51005ff795c 100644 --- a/library/core/src/time.rs +++ b/library/core/src/time.rs @@ -213,11 +213,9 @@ impl Duration { // SAFETY: nanos < NANOS_PER_SEC, therefore nanos is within the valid range Duration { secs, nanos: unsafe { Nanoseconds(nanos) } } } else { - // FIXME(const-hack): use `.expect` once that is possible. - let secs = match secs.checked_add((nanos / NANOS_PER_SEC) as u64) { - Some(secs) => secs, - None => panic!("overflow in Duration::new"), - }; + let secs = secs + .checked_add((nanos / NANOS_PER_SEC) as u64) + .expect("overflow in Duration::new"); let nanos = nanos % NANOS_PER_SEC; // SAFETY: nanos % NANOS_PER_SEC < NANOS_PER_SEC, therefore nanos is within the valid range Duration { secs, nanos: unsafe { Nanoseconds(nanos) } } diff --git a/library/std/src/sys/pal/windows/args.rs b/library/std/src/sys/pal/windows/args.rs index 848632ec2a7..e9fc19bcb99 100644 --- a/library/std/src/sys/pal/windows/args.rs +++ b/library/std/src/sys/pal/windows/args.rs @@ -18,17 +18,6 @@ use crate::sys_common::AsInner; use crate::sys_common::wstr::WStrUnits; use crate::{fmt, io, iter, vec}; -/// This is the const equivalent to `NonZero::new(n).unwrap()` -/// -/// FIXME(const-hack): This can be removed once `Option::unwrap` is stably const. -/// See the `const_option` feature (#67441). -const fn non_zero_u16(n: u16) -> NonZero { - match NonZero::new(n) { - Some(n) => n, - None => panic!("called `unwrap` on a `None` value"), - } -} - pub fn args() -> Args { // SAFETY: `GetCommandLineW` returns a pointer to a null terminated UTF-16 // string so it's safe for `WStrUnits` to use. @@ -66,10 +55,10 @@ fn parse_lp_cmd_line<'a, F: Fn() -> OsString>( lp_cmd_line: Option>, exe_name: F, ) -> Vec { - const BACKSLASH: NonZero = non_zero_u16(b'\\' as u16); - const QUOTE: NonZero = non_zero_u16(b'"' as u16); - const TAB: NonZero = non_zero_u16(b'\t' as u16); - const SPACE: NonZero = non_zero_u16(b' ' as u16); + const BACKSLASH: NonZero = NonZero::new(b'\\' as u16).unwrap(); + const QUOTE: NonZero = NonZero::new(b'"' as u16).unwrap(); + const TAB: NonZero = NonZero::new(b'\t' as u16).unwrap(); + const SPACE: NonZero = NonZero::new(b' ' as u16).unwrap(); let mut ret_val = Vec::new(); // If the cmd line pointer is null or it points to an empty string then From 4e14ad6d625baadc9f918b2b9c2a2bf39aef9f9b Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 14 Oct 2024 21:59:05 +0200 Subject: [PATCH 302/357] move lazy_sync helper methods to be with InterpCx --- src/tools/miri/src/concurrency/sync.rs | 155 ++++++++++++-------- src/tools/miri/src/shims/unix/macos/sync.rs | 12 +- src/tools/miri/src/shims/unix/sync.rs | 12 +- src/tools/miri/src/shims/windows/sync.rs | 3 +- 4 files changed, 103 insertions(+), 79 deletions(-) diff --git a/src/tools/miri/src/concurrency/sync.rs b/src/tools/miri/src/concurrency/sync.rs index 2c6a7bf0f58..e7e6c100cfe 100644 --- a/src/tools/miri/src/concurrency/sync.rs +++ b/src/tools/miri/src/concurrency/sync.rs @@ -193,75 +193,104 @@ impl<'tcx> AllocExtra<'tcx> { /// If `init` is set to this, we consider the primitive initialized. pub const LAZY_INIT_COOKIE: u32 = 0xcafe_affe; -/// Helper for lazily initialized `alloc_extra.sync` data: -/// this forces an immediate init. -pub fn lazy_sync_init<'tcx, T: 'static + Copy>( - ecx: &mut MiriInterpCx<'tcx>, - primitive: &MPlaceTy<'tcx>, - init_offset: Size, - data: T, -) -> InterpResult<'tcx> { - let (alloc, offset, _) = ecx.ptr_get_alloc_id(primitive.ptr(), 0)?; - let (alloc_extra, _machine) = ecx.get_alloc_extra_mut(alloc)?; - alloc_extra.sync.insert(offset, Box::new(data)); - // Mark this as "initialized". - let init_field = primitive.offset(init_offset, ecx.machine.layouts.u32, ecx)?; - ecx.write_scalar_atomic( - Scalar::from_u32(LAZY_INIT_COOKIE), - &init_field, - AtomicWriteOrd::Relaxed, - )?; - interp_ok(()) -} - -/// Helper for lazily initialized `alloc_extra.sync` data: -/// Checks if the primitive is initialized, and return its associated data if so. -/// Otherwise, calls `new_data` to initialize the primitive. -pub fn lazy_sync_get_data<'tcx, T: 'static + Copy>( - ecx: &mut MiriInterpCx<'tcx>, - primitive: &MPlaceTy<'tcx>, - init_offset: Size, - name: &str, - new_data: impl FnOnce(&mut MiriInterpCx<'tcx>) -> InterpResult<'tcx, T>, -) -> InterpResult<'tcx, T> { - // Check if this is already initialized. Needs to be atomic because we can race with another - // thread initializing. Needs to be an RMW operation to ensure we read the *latest* value. - // So we just try to replace MUTEX_INIT_COOKIE with itself. - let init_cookie = Scalar::from_u32(LAZY_INIT_COOKIE); - let init_field = primitive.offset(init_offset, ecx.machine.layouts.u32, ecx)?; - let (_init, success) = ecx - .atomic_compare_exchange_scalar( - &init_field, - &ImmTy::from_scalar(init_cookie, ecx.machine.layouts.u32), - init_cookie, - AtomicRwOrd::Relaxed, - AtomicReadOrd::Relaxed, - /* can_fail_spuriously */ false, - )? - .to_scalar_pair(); - - if success.to_bool()? { - // If it is initialized, it must be found in the "sync primitive" table, - // or else it has been moved illegally. - let (alloc, offset, _) = ecx.ptr_get_alloc_id(primitive.ptr(), 0)?; - let alloc_extra = ecx.get_alloc_extra(alloc)?; - let data = alloc_extra - .get_sync::(offset) - .ok_or_else(|| err_ub_format!("`{name}` can't be moved after first use"))?; - interp_ok(*data) - } else { - let data = new_data(ecx)?; - lazy_sync_init(ecx, primitive, init_offset, data)?; - interp_ok(data) - } -} - // Public interface to synchronization primitives. Please note that in most // cases, the function calls are infallible and it is the client's (shim // implementation's) responsibility to detect and deal with erroneous // situations. impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { + /// Helper for lazily initialized `alloc_extra.sync` data: + /// this forces an immediate init. + fn lazy_sync_init( + &mut self, + primitive: &MPlaceTy<'tcx>, + init_offset: Size, + data: T, + ) -> InterpResult<'tcx> { + let this = self.eval_context_mut(); + + let (alloc, offset, _) = this.ptr_get_alloc_id(primitive.ptr(), 0)?; + let (alloc_extra, _machine) = this.get_alloc_extra_mut(alloc)?; + alloc_extra.sync.insert(offset, Box::new(data)); + // Mark this as "initialized". + let init_field = primitive.offset(init_offset, this.machine.layouts.u32, this)?; + this.write_scalar_atomic( + Scalar::from_u32(LAZY_INIT_COOKIE), + &init_field, + AtomicWriteOrd::Relaxed, + )?; + interp_ok(()) + } + + /// Helper for lazily initialized `alloc_extra.sync` data: + /// Checks if the primitive is initialized, and return its associated data if so. + /// Otherwise, calls `new_data` to initialize the primitive. + fn lazy_sync_get_data( + &mut self, + primitive: &MPlaceTy<'tcx>, + init_offset: Size, + name: &str, + new_data: impl FnOnce(&mut MiriInterpCx<'tcx>) -> InterpResult<'tcx, T>, + ) -> InterpResult<'tcx, T> { + let this = self.eval_context_mut(); + + // Check if this is already initialized. Needs to be atomic because we can race with another + // thread initializing. Needs to be an RMW operation to ensure we read the *latest* value. + // So we just try to replace MUTEX_INIT_COOKIE with itself. + let init_cookie = Scalar::from_u32(LAZY_INIT_COOKIE); + let init_field = primitive.offset(init_offset, this.machine.layouts.u32, this)?; + let (_init, success) = this + .atomic_compare_exchange_scalar( + &init_field, + &ImmTy::from_scalar(init_cookie, this.machine.layouts.u32), + init_cookie, + AtomicRwOrd::Relaxed, + AtomicReadOrd::Relaxed, + /* can_fail_spuriously */ false, + )? + .to_scalar_pair(); + + if success.to_bool()? { + // If it is initialized, it must be found in the "sync primitive" table, + // or else it has been moved illegally. + let (alloc, offset, _) = this.ptr_get_alloc_id(primitive.ptr(), 0)?; + let alloc_extra = this.get_alloc_extra(alloc)?; + let data = alloc_extra + .get_sync::(offset) + .ok_or_else(|| err_ub_format!("`{name}` can't be moved after first use"))?; + interp_ok(*data) + } else { + let data = new_data(this)?; + this.lazy_sync_init(primitive, init_offset, data)?; + interp_ok(data) + } + } + + /// Get the synchronization primitive associated with the given pointer, + /// or initialize a new one. + fn get_sync_or_init<'a, T: 'static>( + &'a mut self, + ptr: Pointer, + new: impl FnOnce(&'a mut MiriMachine<'tcx>) -> InterpResult<'tcx, T>, + ) -> InterpResult<'tcx, &'a T> + where + 'tcx: 'a, + { + let this = self.eval_context_mut(); + // Ensure there is memory behind this pointer, so that this allocation + // is truly the only place where the data could be stored. + this.check_ptr_access(ptr, Size::from_bytes(1), CheckInAllocMsg::InboundsTest)?; + + let (alloc, offset, _) = this.ptr_get_alloc_id(ptr, 0)?; + let (alloc_extra, machine) = this.get_alloc_extra_mut(alloc)?; + // Due to borrow checker reasons, we have to do the lookup twice. + if alloc_extra.get_sync::(offset).is_none() { + let new = new(machine)?; + alloc_extra.sync.insert(offset, Box::new(new)); + } + interp_ok(alloc_extra.get_sync::(offset).unwrap()) + } + #[inline] /// Get the id of the thread that currently owns this lock. fn mutex_get_owner(&mut self, id: MutexId) -> ThreadId { diff --git a/src/tools/miri/src/shims/unix/macos/sync.rs b/src/tools/miri/src/shims/unix/macos/sync.rs index cd5b0ed1d07..25e1ff42fb9 100644 --- a/src/tools/miri/src/shims/unix/macos/sync.rs +++ b/src/tools/miri/src/shims/unix/macos/sync.rs @@ -23,15 +23,11 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { let lock = this.deref_pointer(lock_ptr)?; // We store the mutex ID in the `sync` metadata. This means that when the lock is moved, // that's just implicitly creating a new lock at the new location. - let (alloc, offset, _) = this.ptr_get_alloc_id(lock.ptr(), 0)?; - let (alloc_extra, machine) = this.get_alloc_extra_mut(alloc)?; - if let Some(data) = alloc_extra.get_sync::(offset) { - interp_ok(data.id) - } else { + let data = this.get_sync_or_init(lock.ptr(), |machine| { let id = machine.sync.mutex_create(); - alloc_extra.sync.insert(offset, Box::new(MacOsUnfairLock { id })); - interp_ok(id) - } + interp_ok(MacOsUnfairLock { id }) + })?; + interp_ok(data.id) } } diff --git a/src/tools/miri/src/shims/unix/sync.rs b/src/tools/miri/src/shims/unix/sync.rs index 913f53adbbb..8eb874a4565 100644 --- a/src/tools/miri/src/shims/unix/sync.rs +++ b/src/tools/miri/src/shims/unix/sync.rs @@ -2,7 +2,7 @@ use std::sync::atomic::{AtomicBool, Ordering}; use rustc_target::abi::Size; -use crate::concurrency::sync::{LAZY_INIT_COOKIE, lazy_sync_get_data, lazy_sync_init}; +use crate::concurrency::sync::LAZY_INIT_COOKIE; use crate::*; /// Do a bytewise comparison of the two places, using relaxed atomic reads. This is used to check if @@ -176,7 +176,7 @@ fn mutex_create<'tcx>( let mutex = ecx.deref_pointer(mutex_ptr)?; let id = ecx.machine.sync.mutex_create(); let data = PthreadMutex { id, kind }; - lazy_sync_init(ecx, &mutex, mutex_init_offset(ecx)?, data)?; + ecx.lazy_sync_init(&mutex, mutex_init_offset(ecx)?, data)?; interp_ok(data) } @@ -189,7 +189,7 @@ fn mutex_get_data<'tcx, 'a>( mutex_ptr: &OpTy<'tcx>, ) -> InterpResult<'tcx, PthreadMutex> { let mutex = ecx.deref_pointer(mutex_ptr)?; - lazy_sync_get_data(ecx, &mutex, mutex_init_offset(ecx)?, "pthread_mutex_t", |ecx| { + ecx.lazy_sync_get_data(&mutex, mutex_init_offset(ecx)?, "pthread_mutex_t", |ecx| { let kind = mutex_kind_from_static_initializer(ecx, &mutex)?; let id = ecx.machine.sync.mutex_create(); interp_ok(PthreadMutex { id, kind }) @@ -261,7 +261,7 @@ fn rwlock_get_data<'tcx>( rwlock_ptr: &OpTy<'tcx>, ) -> InterpResult<'tcx, PthreadRwLock> { let rwlock = ecx.deref_pointer(rwlock_ptr)?; - lazy_sync_get_data(ecx, &rwlock, rwlock_init_offset(ecx)?, "pthread_rwlock_t", |ecx| { + ecx.lazy_sync_get_data(&rwlock, rwlock_init_offset(ecx)?, "pthread_rwlock_t", |ecx| { if !bytewise_equal_atomic_relaxed( ecx, &rwlock, @@ -377,7 +377,7 @@ fn cond_create<'tcx>( let cond = ecx.deref_pointer(cond_ptr)?; let id = ecx.machine.sync.condvar_create(); let data = PthreadCondvar { id, clock }; - lazy_sync_init(ecx, &cond, cond_init_offset(ecx)?, data)?; + ecx.lazy_sync_init(&cond, cond_init_offset(ecx)?, data)?; interp_ok(data) } @@ -386,7 +386,7 @@ fn cond_get_data<'tcx>( cond_ptr: &OpTy<'tcx>, ) -> InterpResult<'tcx, PthreadCondvar> { let cond = ecx.deref_pointer(cond_ptr)?; - lazy_sync_get_data(ecx, &cond, cond_init_offset(ecx)?, "pthread_cond_t", |ecx| { + ecx.lazy_sync_get_data(&cond, cond_init_offset(ecx)?, "pthread_cond_t", |ecx| { if !bytewise_equal_atomic_relaxed( ecx, &cond, diff --git a/src/tools/miri/src/shims/windows/sync.rs b/src/tools/miri/src/shims/windows/sync.rs index 8771bb4a8ac..3701f479e5c 100644 --- a/src/tools/miri/src/shims/windows/sync.rs +++ b/src/tools/miri/src/shims/windows/sync.rs @@ -3,7 +3,6 @@ use std::time::Duration; use rustc_target::abi::Size; use crate::concurrency::init_once::InitOnceStatus; -use crate::concurrency::sync::lazy_sync_get_data; use crate::*; #[derive(Copy, Clone)] @@ -25,7 +24,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { let init_once = this.deref_pointer(init_once_ptr)?; let init_offset = Size::ZERO; - lazy_sync_get_data(this, &init_once, init_offset, "INIT_ONCE", |this| { + this.lazy_sync_get_data(&init_once, init_offset, "INIT_ONCE", |this| { // TODO: check that this is still all-zero. let id = this.machine.sync.init_once_create(); interp_ok(WindowsInitOnce { id }) From 10aa255541964bceddaac8f49d7a11f1d736e24d Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Mon, 14 Oct 2024 22:32:32 +0200 Subject: [PATCH 303/357] improve error messages for `C-cmse-nonsecure-entry` functions --- compiler/rustc_hir_analysis/messages.ftl | 15 +- compiler/rustc_hir_analysis/src/errors.rs | 17 +- .../src/hir_ty_lowering/cmse.rs | 157 +++++++++++------- .../cmse-nonsecure-entry/generics.rs | 77 +++++++++ .../cmse-nonsecure-entry/generics.stderr | 78 +++++++++ .../params-on-registers.rs | 16 -- .../cmse-nonsecure-entry/params-on-stack.rs | 21 --- .../params-on-stack.stderr | 4 - .../cmse-nonsecure-entry/params-via-stack.rs | 26 +++ .../params-via-stack.stderr | 43 +++++ .../cmse-nonsecure-entry/return-via-stack.rs | 84 ++++++++++ .../return-via-stack.stderr | 84 ++++++++++ .../trustzone-only.stderr | 9 + .../cmse-nonsecure-entry/via-registers.rs | 89 ++++++++++ 14 files changed, 612 insertions(+), 108 deletions(-) create mode 100644 tests/ui/cmse-nonsecure/cmse-nonsecure-entry/generics.rs create mode 100644 tests/ui/cmse-nonsecure/cmse-nonsecure-entry/generics.stderr delete mode 100644 tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-registers.rs delete mode 100644 tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.rs delete mode 100644 tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.stderr create mode 100644 tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-via-stack.rs create mode 100644 tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-via-stack.stderr create mode 100644 tests/ui/cmse-nonsecure/cmse-nonsecure-entry/return-via-stack.rs create mode 100644 tests/ui/cmse-nonsecure/cmse-nonsecure-entry/return-via-stack.stderr create mode 100644 tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.stderr create mode 100644 tests/ui/cmse-nonsecure/cmse-nonsecure-entry/via-registers.rs diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index da814cd2d69..a9f30ffd6da 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -68,18 +68,21 @@ hir_analysis_closure_implicit_hrtb = implicit types in closure signatures are fo hir_analysis_cmse_call_generic = function pointers with the `"C-cmse-nonsecure-call"` ABI cannot contain generics in their type -hir_analysis_cmse_call_inputs_stack_spill = - arguments for `"C-cmse-nonsecure-call"` function too large to pass via registers +hir_analysis_cmse_entry_generic = + functions with the `"C-cmse-nonsecure-entry"` ABI cannot contain generics in their type + +hir_analysis_cmse_inputs_stack_spill = + arguments for `"{$abi_name}"` function too large to pass via registers .label = {$plural -> [false] this argument doesn't *[true] these arguments don't } fit in the available registers - .note = functions with the `"C-cmse-nonsecure-call"` ABI must pass all their arguments via the 4 32-bit available argument registers + .note = functions with the `"{$abi_name}"` ABI must pass all their arguments via the 4 32-bit available argument registers -hir_analysis_cmse_call_output_stack_spill = - return value of `"C-cmse-nonsecure-call"` function too large to pass via registers +hir_analysis_cmse_output_stack_spill = + return value of `"{$abi_name}"` function too large to pass via registers .label = this type doesn't fit in the available registers - .note1 = functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers + .note1 = functions with the `"{$abi_name}"` ABI must pass their result via the available return registers .note2 = the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size hir_analysis_coerce_unsized_may = the trait `{$trait_name}` may only be implemented for a coercion between structures diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 9099703e812..af4445a7fd4 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -1627,23 +1627,25 @@ pub(crate) struct InvalidReceiverTy<'tcx> { pub(crate) struct EffectsWithoutNextSolver; #[derive(Diagnostic)] -#[diag(hir_analysis_cmse_call_inputs_stack_spill, code = E0798)] +#[diag(hir_analysis_cmse_inputs_stack_spill, code = E0798)] #[note] -pub(crate) struct CmseCallInputsStackSpill { +pub(crate) struct CmseInputsStackSpill { #[primary_span] #[label] pub span: Span, pub plural: bool, + pub abi_name: &'static str, } #[derive(Diagnostic)] -#[diag(hir_analysis_cmse_call_output_stack_spill, code = E0798)] +#[diag(hir_analysis_cmse_output_stack_spill, code = E0798)] #[note(hir_analysis_note1)] #[note(hir_analysis_note2)] -pub(crate) struct CmseCallOutputStackSpill { +pub(crate) struct CmseOutputStackSpill { #[primary_span] #[label] pub span: Span, + pub abi_name: &'static str, } #[derive(Diagnostic)] @@ -1659,3 +1661,10 @@ pub(crate) struct BadReturnTypeNotation { #[primary_span] pub span: Span, } + +#[derive(Diagnostic)] +#[diag(hir_analysis_cmse_entry_generic, code = E0798)] +pub(crate) struct CmseEntryGeneric { + #[primary_span] + pub span: Span, +} diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs index a562759da11..672dc8ddeda 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs @@ -1,8 +1,8 @@ use rustc_errors::{DiagCtxtHandle, E0781, struct_span_code_err}; use rustc_hir::{self as hir, HirId}; +use rustc_middle::bug; use rustc_middle::ty::layout::LayoutError; use rustc_middle::ty::{self, ParamEnv, TyCtxt}; -use rustc_span::Span; use rustc_target::spec::abi; use crate::errors; @@ -17,61 +17,104 @@ pub(crate) fn validate_cmse_abi<'tcx>( abi: abi::Abi, fn_sig: ty::PolyFnSig<'tcx>, ) { - if let abi::Abi::CCmseNonSecureCall = abi { - let hir_node = tcx.hir_node(hir_id); - let hir::Node::Ty(hir::Ty { - span: bare_fn_span, - kind: hir::TyKind::BareFn(bare_fn_ty), - .. - }) = hir_node - else { - let span = match tcx.parent_hir_node(hir_id) { - hir::Node::Item(hir::Item { - kind: hir::ItemKind::ForeignMod { .. }, span, .. - }) => *span, - _ => tcx.hir().span(hir_id), + let abi_name = abi.name(); + + match abi { + abi::Abi::CCmseNonSecureCall => { + let hir_node = tcx.hir_node(hir_id); + let hir::Node::Ty(hir::Ty { + span: bare_fn_span, + kind: hir::TyKind::BareFn(bare_fn_ty), + .. + }) = hir_node + else { + let span = match tcx.parent_hir_node(hir_id) { + hir::Node::Item(hir::Item { + kind: hir::ItemKind::ForeignMod { .. }, + span, + .. + }) => *span, + _ => tcx.hir().span(hir_id), + }; + struct_span_code_err!( + tcx.dcx(), + span, + E0781, + "the `\"C-cmse-nonsecure-call\"` ABI is only allowed on function pointers" + ) + .emit(); + return; }; - struct_span_code_err!( - tcx.dcx(), - span, - E0781, - "the `\"C-cmse-nonsecure-call\"` ABI is only allowed on function pointers" - ) - .emit(); - return; - }; - match is_valid_cmse_inputs(tcx, fn_sig) { - Ok(Ok(())) => {} - Ok(Err(index)) => { - // fn(x: u32, u32, u32, u16, y: u16) -> u32, - // ^^^^^^ - let span = bare_fn_ty.param_names[index] - .span - .to(bare_fn_ty.decl.inputs[index].span) - .to(bare_fn_ty.decl.inputs.last().unwrap().span); - let plural = bare_fn_ty.param_names.len() - index != 1; - dcx.emit_err(errors::CmseCallInputsStackSpill { span, plural }); - } - Err(layout_err) => { - if let Some(err) = cmse_layout_err(layout_err, *bare_fn_span) { - dcx.emit_err(err); + match is_valid_cmse_inputs(tcx, fn_sig) { + Ok(Ok(())) => {} + Ok(Err(index)) => { + // fn(x: u32, u32, u32, u16, y: u16) -> u32, + // ^^^^^^ + let span = bare_fn_ty.param_names[index] + .span + .to(bare_fn_ty.decl.inputs[index].span) + .to(bare_fn_ty.decl.inputs.last().unwrap().span); + let plural = bare_fn_ty.param_names.len() - index != 1; + dcx.emit_err(errors::CmseInputsStackSpill { span, plural, abi_name }); + } + Err(layout_err) => { + if should_emit_generic_error(abi, layout_err) { + dcx.emit_err(errors::CmseCallGeneric { span: *bare_fn_span }); + } } } + + match is_valid_cmse_output(tcx, fn_sig) { + Ok(true) => {} + Ok(false) => { + let span = bare_fn_ty.decl.output.span(); + dcx.emit_err(errors::CmseOutputStackSpill { span, abi_name }); + } + Err(layout_err) => { + if should_emit_generic_error(abi, layout_err) { + dcx.emit_err(errors::CmseCallGeneric { span: *bare_fn_span }); + } + } + }; } + abi::Abi::CCmseNonSecureEntry => { + let hir_node = tcx.hir_node(hir_id); + let Some(hir::FnSig { decl, span: fn_sig_span, .. }) = hir_node.fn_sig() else { + // might happen when this ABI is used incorrectly. That will be handled elsewhere + return; + }; - match is_valid_cmse_output(tcx, fn_sig) { - Ok(true) => {} - Ok(false) => { - let span = bare_fn_ty.decl.output.span(); - dcx.emit_err(errors::CmseCallOutputStackSpill { span }); - } - Err(layout_err) => { - if let Some(err) = cmse_layout_err(layout_err, *bare_fn_span) { - dcx.emit_err(err); + match is_valid_cmse_inputs(tcx, fn_sig) { + Ok(Ok(())) => {} + Ok(Err(index)) => { + // fn f(x: u32, y: u32, z: u32, w: u16, q: u16) -> u32, + // ^^^^^^ + let span = decl.inputs[index].span.to(decl.inputs.last().unwrap().span); + let plural = decl.inputs.len() - index != 1; + dcx.emit_err(errors::CmseInputsStackSpill { span, plural, abi_name }); + } + Err(layout_err) => { + if should_emit_generic_error(abi, layout_err) { + dcx.emit_err(errors::CmseEntryGeneric { span: *fn_sig_span }); + } } } - }; + + match is_valid_cmse_output(tcx, fn_sig) { + Ok(true) => {} + Ok(false) => { + let span = decl.output.span(); + dcx.emit_err(errors::CmseOutputStackSpill { span, abi_name }); + } + Err(layout_err) => { + if should_emit_generic_error(abi, layout_err) { + dcx.emit_err(errors::CmseEntryGeneric { span: *fn_sig_span }); + } + } + }; + } + _ => (), } } @@ -152,22 +195,22 @@ fn is_valid_cmse_output<'tcx>( Ok(ret_ty == tcx.types.i64 || ret_ty == tcx.types.u64 || ret_ty == tcx.types.f64) } -fn cmse_layout_err<'tcx>( - layout_err: &'tcx LayoutError<'tcx>, - span: Span, -) -> Option { +fn should_emit_generic_error<'tcx>(abi: abi::Abi, layout_err: &'tcx LayoutError<'tcx>) -> bool { use LayoutError::*; match layout_err { Unknown(ty) => { - if ty.is_impl_trait() { - None // prevent double reporting of this error - } else { - Some(errors::CmseCallGeneric { span }) + match abi { + abi::Abi::CCmseNonSecureCall => { + // prevent double reporting of this error + !ty.is_impl_trait() + } + abi::Abi::CCmseNonSecureEntry => true, + _ => bug!("invalid ABI: {abi}"), } } SizeOverflow(..) | NormalizationFailure(..) | ReferencesError(..) | Cycle(..) => { - None // not our job to report these + false // not our job to report these } } } diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/generics.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/generics.rs new file mode 100644 index 00000000000..a264bba6f3c --- /dev/null +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/generics.rs @@ -0,0 +1,77 @@ +//@ compile-flags: --target thumbv8m.main-none-eabi --crate-type lib +//@ needs-llvm-components: arm +#![feature(cmse_nonsecure_entry, c_variadic, no_core, lang_items)] +#![no_core] +#[lang = "sized"] +pub trait Sized {} +#[lang = "copy"] +pub trait Copy {} +impl Copy for u32 {} + +#[repr(C)] +struct Wrapper(T); + +impl Wrapper { + extern "C-cmse-nonsecure-entry" fn ambient_generic(_: T, _: u32, _: u32, _: u32) -> u64 { + //~^ ERROR [E0798] + 0 + } + + extern "C-cmse-nonsecure-entry" fn ambient_generic_nested( + //~^ ERROR [E0798] + _: Wrapper, + _: u32, + _: u32, + _: u32, + ) -> u64 { + 0 + } +} + +extern "C-cmse-nonsecure-entry" fn introduced_generic( + //~^ ERROR [E0798] + _: U, + _: u32, + _: u32, + _: u32, +) -> u64 { + 0 +} + +extern "C-cmse-nonsecure-entry" fn impl_trait(_: impl Copy, _: u32, _: u32, _: u32) -> u64 { + //~^ ERROR [E0798] + 0 +} + +extern "C-cmse-nonsecure-entry" fn reference(x: &usize) -> usize { + *x +} + +trait Trait {} + +extern "C-cmse-nonsecure-entry" fn trait_object(x: &dyn Trait) -> &dyn Trait { + //~^ ERROR return value of `"C-cmse-nonsecure-entry"` function too large to pass via registers [E0798] + x +} + +extern "C-cmse-nonsecure-entry" fn static_trait_object( + x: &'static dyn Trait, +) -> &'static dyn Trait { + //~^ ERROR return value of `"C-cmse-nonsecure-entry"` function too large to pass via registers [E0798] + x +} + +#[repr(transparent)] +struct WrapperTransparent<'a>(&'a dyn Trait); + +extern "C-cmse-nonsecure-entry" fn wrapped_trait_object( + x: WrapperTransparent, +) -> WrapperTransparent { + //~^ ERROR return value of `"C-cmse-nonsecure-entry"` function too large to pass via registers [E0798] + x +} + +extern "C-cmse-nonsecure-entry" fn c_variadic(_: u32, _: ...) { + //~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg + //~| ERROR requires `va_list` lang_item +} diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/generics.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/generics.stderr new file mode 100644 index 00000000000..9e67f881f75 --- /dev/null +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/generics.stderr @@ -0,0 +1,78 @@ +error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg + --> $DIR/generics.rs:74:55 + | +LL | extern "C-cmse-nonsecure-entry" fn c_variadic(_: u32, _: ...) { + | ^^^^^^ + +error[E0798]: functions with the `"C-cmse-nonsecure-entry"` ABI cannot contain generics in their type + --> $DIR/generics.rs:31:1 + | +LL | / extern "C-cmse-nonsecure-entry" fn introduced_generic( +LL | | +LL | | _: U, +LL | | _: u32, +LL | | _: u32, +LL | | _: u32, +LL | | ) -> u64 { + | |________^ + +error[E0798]: functions with the `"C-cmse-nonsecure-entry"` ABI cannot contain generics in their type + --> $DIR/generics.rs:41:1 + | +LL | extern "C-cmse-nonsecure-entry" fn impl_trait(_: impl Copy, _: u32, _: u32, _: u32) -> u64 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0798]: functions with the `"C-cmse-nonsecure-entry"` ABI cannot contain generics in their type + --> $DIR/generics.rs:15:5 + | +LL | extern "C-cmse-nonsecure-entry" fn ambient_generic(_: T, _: u32, _: u32, _: u32) -> u64 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0798]: functions with the `"C-cmse-nonsecure-entry"` ABI cannot contain generics in their type + --> $DIR/generics.rs:20:5 + | +LL | / extern "C-cmse-nonsecure-entry" fn ambient_generic_nested( +LL | | +LL | | _: Wrapper, +LL | | _: u32, +LL | | _: u32, +LL | | _: u32, +LL | | ) -> u64 { + | |____________^ + +error[E0798]: return value of `"C-cmse-nonsecure-entry"` function too large to pass via registers + --> $DIR/generics.rs:52:67 + | +LL | extern "C-cmse-nonsecure-entry" fn trait_object(x: &dyn Trait) -> &dyn Trait { + | ^^^^^^^^^^ this type doesn't fit in the available registers + | + = note: functions with the `"C-cmse-nonsecure-entry"` ABI must pass their result via the available return registers + = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size + +error[E0798]: return value of `"C-cmse-nonsecure-entry"` function too large to pass via registers + --> $DIR/generics.rs:59:6 + | +LL | ) -> &'static dyn Trait { + | ^^^^^^^^^^^^^^^^^^ this type doesn't fit in the available registers + | + = note: functions with the `"C-cmse-nonsecure-entry"` ABI must pass their result via the available return registers + = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size + +error[E0798]: return value of `"C-cmse-nonsecure-entry"` function too large to pass via registers + --> $DIR/generics.rs:69:6 + | +LL | ) -> WrapperTransparent { + | ^^^^^^^^^^^^^^^^^^ this type doesn't fit in the available registers + | + = note: functions with the `"C-cmse-nonsecure-entry"` ABI must pass their result via the available return registers + = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size + +error: requires `va_list` lang_item + --> $DIR/generics.rs:74:55 + | +LL | extern "C-cmse-nonsecure-entry" fn c_variadic(_: u32, _: ...) { + | ^^^^^^ + +error: aborting due to 9 previous errors + +For more information about this error, try `rustc --explain E0798`. diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-registers.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-registers.rs deleted file mode 100644 index de6888fae62..00000000000 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-registers.rs +++ /dev/null @@ -1,16 +0,0 @@ -//@ build-pass -//@ compile-flags: --target thumbv8m.main-none-eabi --crate-type lib -//@ needs-llvm-components: arm -#![feature(cmse_nonsecure_entry, no_core, lang_items)] -#![no_core] -#![crate_type = "lib"] -#[lang = "sized"] -trait Sized {} -#[lang = "copy"] -trait Copy {} -impl Copy for u32 {} - -#[no_mangle] -pub extern "C-cmse-nonsecure-entry" fn entry_function(_: u32, _: u32, _: u32, d: u32) -> u32 { - d -} diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.rs deleted file mode 100644 index 4413c461c04..00000000000 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.rs +++ /dev/null @@ -1,21 +0,0 @@ -//@ build-fail -//@ compile-flags: --target thumbv8m.main-none-eabi --crate-type lib -//@ needs-llvm-components: arm -#![feature(cmse_nonsecure_entry, no_core, lang_items)] -#![no_core] -#[lang = "sized"] -trait Sized {} -#[lang = "copy"] -trait Copy {} -impl Copy for u32 {} - -#[no_mangle] -pub extern "C-cmse-nonsecure-entry" fn entry_function( - _: u32, - _: u32, - _: u32, - _: u32, - e: u32, -) -> u32 { - e -} diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.stderr deleted file mode 100644 index cfbdda509e5..00000000000 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.stderr +++ /dev/null @@ -1,4 +0,0 @@ -error: :0:0: in function entry_function i32 (i32, i32, i32, i32, i32): secure entry function requires arguments on stack - -error: aborting due to 1 previous error - diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-via-stack.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-via-stack.rs new file mode 100644 index 00000000000..572d792d5a5 --- /dev/null +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-via-stack.rs @@ -0,0 +1,26 @@ +//@ compile-flags: --target thumbv8m.main-none-eabi --crate-type lib +//@ needs-llvm-components: arm +#![feature(cmse_nonsecure_entry, no_core, lang_items)] +#![no_core] +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} +impl Copy for u32 {} + +#[repr(C, align(16))] +#[allow(unused)] +pub struct AlignRelevant(u32); + +#[no_mangle] +pub extern "C-cmse-nonsecure-entry" fn f1(_: u32, _: u32, _: u32, _: u32, _: u32, _: u32) {} //~ ERROR [E0798] +#[no_mangle] +pub extern "C-cmse-nonsecure-entry" fn f2(_: u32, _: u32, _: u32, _: u16, _: u16) {} //~ ERROR [E0798] +#[no_mangle] +pub extern "C-cmse-nonsecure-entry" fn f3(_: u32, _: u64, _: u32) {} //~ ERROR [E0798] +#[no_mangle] +pub extern "C-cmse-nonsecure-entry" fn f4(_: AlignRelevant, _: u32) {} //~ ERROR [E0798] + +#[no_mangle] +#[allow(improper_ctypes_definitions)] +pub extern "C-cmse-nonsecure-entry" fn f5(_: [u32; 5]) {} //~ ERROR [E0798] diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-via-stack.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-via-stack.stderr new file mode 100644 index 00000000000..b77e64c6bfb --- /dev/null +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-via-stack.stderr @@ -0,0 +1,43 @@ +error[E0798]: arguments for `"C-cmse-nonsecure-entry"` function too large to pass via registers + --> $DIR/params-via-stack.rs:16:78 + | +LL | pub extern "C-cmse-nonsecure-entry" fn f1(_: u32, _: u32, _: u32, _: u32, _: u32, _: u32) {} + | ^^^^^^^^^^^ these arguments don't fit in the available registers + | + = note: functions with the `"C-cmse-nonsecure-entry"` ABI must pass all their arguments via the 4 32-bit available argument registers + +error[E0798]: arguments for `"C-cmse-nonsecure-entry"` function too large to pass via registers + --> $DIR/params-via-stack.rs:18:78 + | +LL | pub extern "C-cmse-nonsecure-entry" fn f2(_: u32, _: u32, _: u32, _: u16, _: u16) {} + | ^^^ this argument doesn't fit in the available registers + | + = note: functions with the `"C-cmse-nonsecure-entry"` ABI must pass all their arguments via the 4 32-bit available argument registers + +error[E0798]: arguments for `"C-cmse-nonsecure-entry"` function too large to pass via registers + --> $DIR/params-via-stack.rs:20:62 + | +LL | pub extern "C-cmse-nonsecure-entry" fn f3(_: u32, _: u64, _: u32) {} + | ^^^ this argument doesn't fit in the available registers + | + = note: functions with the `"C-cmse-nonsecure-entry"` ABI must pass all their arguments via the 4 32-bit available argument registers + +error[E0798]: arguments for `"C-cmse-nonsecure-entry"` function too large to pass via registers + --> $DIR/params-via-stack.rs:22:64 + | +LL | pub extern "C-cmse-nonsecure-entry" fn f4(_: AlignRelevant, _: u32) {} + | ^^^ this argument doesn't fit in the available registers + | + = note: functions with the `"C-cmse-nonsecure-entry"` ABI must pass all their arguments via the 4 32-bit available argument registers + +error[E0798]: arguments for `"C-cmse-nonsecure-entry"` function too large to pass via registers + --> $DIR/params-via-stack.rs:26:46 + | +LL | pub extern "C-cmse-nonsecure-entry" fn f5(_: [u32; 5]) {} + | ^^^^^^^^ this argument doesn't fit in the available registers + | + = note: functions with the `"C-cmse-nonsecure-entry"` ABI must pass all their arguments via the 4 32-bit available argument registers + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0798`. diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/return-via-stack.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/return-via-stack.rs new file mode 100644 index 00000000000..5746d14f9b1 --- /dev/null +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/return-via-stack.rs @@ -0,0 +1,84 @@ +//@ compile-flags: --target thumbv8m.main-none-eabi --crate-type lib +//@ needs-llvm-components: arm +#![feature(cmse_nonsecure_entry, no_core, lang_items)] +#![no_core] +#[lang = "sized"] +pub trait Sized {} +#[lang = "copy"] +pub trait Copy {} +impl Copy for u32 {} +impl Copy for u8 {} + +#[repr(C)] +pub struct ReprCU64(u64); + +#[repr(C)] +pub struct ReprCBytes(u8, u8, u8, u8, u8); + +#[repr(C)] +pub struct U64Compound(u32, u32); + +#[repr(C, align(16))] +pub struct ReprCAlign16(u16); + +#[no_mangle] +pub extern "C-cmse-nonsecure-entry" fn f1() -> ReprCU64 { + //~^ ERROR [E0798] + ReprCU64(0) +} +#[no_mangle] +pub extern "C-cmse-nonsecure-entry" fn f2() -> ReprCBytes { + //~^ ERROR [E0798] + ReprCBytes(0, 1, 2, 3, 4) +} +#[no_mangle] +pub extern "C-cmse-nonsecure-entry" fn f3() -> U64Compound { + //~^ ERROR [E0798] + U64Compound(2, 3) +} +#[no_mangle] +pub extern "C-cmse-nonsecure-entry" fn f4() -> ReprCAlign16 { + //~^ ERROR [E0798] + ReprCAlign16(4) +} + +#[no_mangle] +#[allow(improper_ctypes_definitions)] +pub extern "C-cmse-nonsecure-entry" fn f5() -> [u8; 5] { + //~^ ERROR [E0798] + [0xAA; 5] +} +#[no_mangle] +#[allow(improper_ctypes_definitions)] +pub extern "C-cmse-nonsecure-entry" fn u128() -> u128 { + //~^ ERROR [E0798] + 123 +} +#[no_mangle] +#[allow(improper_ctypes_definitions)] +pub extern "C-cmse-nonsecure-entry" fn i128() -> i128 { + //~^ ERROR [E0798] + 456 +} + +#[repr(Rust)] +pub union ReprRustUnionU64 { + _unused: u64, +} + +#[repr(C)] +pub union ReprCUnionU64 { + _unused: u64, +} + +#[no_mangle] +#[allow(improper_ctypes_definitions)] +pub extern "C-cmse-nonsecure-entry" fn union_rust() -> ReprRustUnionU64 { + //~^ ERROR [E0798] + ReprRustUnionU64 { _unused: 1 } +} +#[no_mangle] +pub extern "C-cmse-nonsecure-entry" fn union_c() -> ReprCUnionU64 { + //~^ ERROR [E0798] + ReprCUnionU64 { _unused: 2 } +} diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/return-via-stack.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/return-via-stack.stderr new file mode 100644 index 00000000000..9c885d95318 --- /dev/null +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/return-via-stack.stderr @@ -0,0 +1,84 @@ +error[E0798]: return value of `"C-cmse-nonsecure-entry"` function too large to pass via registers + --> $DIR/return-via-stack.rs:25:48 + | +LL | pub extern "C-cmse-nonsecure-entry" fn f1() -> ReprCU64 { + | ^^^^^^^^ this type doesn't fit in the available registers + | + = note: functions with the `"C-cmse-nonsecure-entry"` ABI must pass their result via the available return registers + = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size + +error[E0798]: return value of `"C-cmse-nonsecure-entry"` function too large to pass via registers + --> $DIR/return-via-stack.rs:30:48 + | +LL | pub extern "C-cmse-nonsecure-entry" fn f2() -> ReprCBytes { + | ^^^^^^^^^^ this type doesn't fit in the available registers + | + = note: functions with the `"C-cmse-nonsecure-entry"` ABI must pass their result via the available return registers + = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size + +error[E0798]: return value of `"C-cmse-nonsecure-entry"` function too large to pass via registers + --> $DIR/return-via-stack.rs:35:48 + | +LL | pub extern "C-cmse-nonsecure-entry" fn f3() -> U64Compound { + | ^^^^^^^^^^^ this type doesn't fit in the available registers + | + = note: functions with the `"C-cmse-nonsecure-entry"` ABI must pass their result via the available return registers + = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size + +error[E0798]: return value of `"C-cmse-nonsecure-entry"` function too large to pass via registers + --> $DIR/return-via-stack.rs:40:48 + | +LL | pub extern "C-cmse-nonsecure-entry" fn f4() -> ReprCAlign16 { + | ^^^^^^^^^^^^ this type doesn't fit in the available registers + | + = note: functions with the `"C-cmse-nonsecure-entry"` ABI must pass their result via the available return registers + = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size + +error[E0798]: return value of `"C-cmse-nonsecure-entry"` function too large to pass via registers + --> $DIR/return-via-stack.rs:47:48 + | +LL | pub extern "C-cmse-nonsecure-entry" fn f5() -> [u8; 5] { + | ^^^^^^^ this type doesn't fit in the available registers + | + = note: functions with the `"C-cmse-nonsecure-entry"` ABI must pass their result via the available return registers + = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size + +error[E0798]: return value of `"C-cmse-nonsecure-entry"` function too large to pass via registers + --> $DIR/return-via-stack.rs:53:50 + | +LL | pub extern "C-cmse-nonsecure-entry" fn u128() -> u128 { + | ^^^^ this type doesn't fit in the available registers + | + = note: functions with the `"C-cmse-nonsecure-entry"` ABI must pass their result via the available return registers + = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size + +error[E0798]: return value of `"C-cmse-nonsecure-entry"` function too large to pass via registers + --> $DIR/return-via-stack.rs:59:50 + | +LL | pub extern "C-cmse-nonsecure-entry" fn i128() -> i128 { + | ^^^^ this type doesn't fit in the available registers + | + = note: functions with the `"C-cmse-nonsecure-entry"` ABI must pass their result via the available return registers + = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size + +error[E0798]: return value of `"C-cmse-nonsecure-entry"` function too large to pass via registers + --> $DIR/return-via-stack.rs:76:56 + | +LL | pub extern "C-cmse-nonsecure-entry" fn union_rust() -> ReprRustUnionU64 { + | ^^^^^^^^^^^^^^^^ this type doesn't fit in the available registers + | + = note: functions with the `"C-cmse-nonsecure-entry"` ABI must pass their result via the available return registers + = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size + +error[E0798]: return value of `"C-cmse-nonsecure-entry"` function too large to pass via registers + --> $DIR/return-via-stack.rs:81:53 + | +LL | pub extern "C-cmse-nonsecure-entry" fn union_c() -> ReprCUnionU64 { + | ^^^^^^^^^^^^^ this type doesn't fit in the available registers + | + = note: functions with the `"C-cmse-nonsecure-entry"` ABI must pass their result via the available return registers + = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size + +error: aborting due to 9 previous errors + +For more information about this error, try `rustc --explain E0798`. diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.stderr new file mode 100644 index 00000000000..77379f7049d --- /dev/null +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.stderr @@ -0,0 +1,9 @@ +error[E0570]: `"C-cmse-nonsecure-entry"` is not a supported ABI for the current target + --> $DIR/trustzone-only.rs:5:1 + | +LL | pub extern "C-cmse-nonsecure-entry" fn entry_function(input: u32) -> u32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0570`. diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/via-registers.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/via-registers.rs new file mode 100644 index 00000000000..8978b35d356 --- /dev/null +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/via-registers.rs @@ -0,0 +1,89 @@ +//@ build-pass +//@ compile-flags: --target thumbv8m.main-none-eabi --crate-type lib +//@ needs-llvm-components: arm +#![feature(cmse_nonsecure_entry, no_core, lang_items)] +#![no_core] +#![crate_type = "lib"] +#[lang = "sized"] +pub trait Sized {} +#[lang = "copy"] +trait Copy {} +impl Copy for u32 {} +impl Copy for u8 {} + +#[repr(transparent)] +pub struct ReprTransparentStruct { + _marker1: (), + _marker2: (), + field: T, + _marker3: (), +} + +#[repr(transparent)] +pub enum ReprTransparentEnumU64 { + A(u64), +} + +#[repr(C)] +pub struct U32Compound(u16, u16); + +#[no_mangle] +pub extern "C-cmse-nonsecure-entry" fn inputs1() {} +#[no_mangle] +pub extern "C-cmse-nonsecure-entry" fn inputs2(_: u32, _: u32, _: u32, _: u32) {} +#[no_mangle] +pub extern "C-cmse-nonsecure-entry" fn inputs3(_: u64, _: u64) {} +#[no_mangle] +#[allow(improper_ctypes_definitions)] +pub extern "C-cmse-nonsecure-entry" fn inputs4(_: u128) {} +#[no_mangle] +pub extern "C-cmse-nonsecure-entry" fn inputs5(_: f64, _: f32, _: f32) {} +#[no_mangle] +pub extern "C-cmse-nonsecure-entry" fn inputs6(_: ReprTransparentStruct, _: U32Compound) {} +#[no_mangle] +#[allow(improper_ctypes_definitions)] +pub extern "C-cmse-nonsecure-entry" fn inputs7(_: [u32; 4]) {} + +#[no_mangle] +pub extern "C-cmse-nonsecure-entry" fn outputs1() -> u32 { + 0 +} +#[no_mangle] +pub extern "C-cmse-nonsecure-entry" fn outputs2() -> u64 { + 0 +} +#[no_mangle] +pub extern "C-cmse-nonsecure-entry" fn outputs3() -> i64 { + 0 +} +#[no_mangle] +pub extern "C-cmse-nonsecure-entry" fn outputs4() -> f64 { + 0.0 +} +#[no_mangle] +#[allow(improper_ctypes_definitions)] +pub extern "C-cmse-nonsecure-entry" fn outputs5() -> [u8; 4] { + [0xAA; 4] +} +#[no_mangle] +pub extern "C-cmse-nonsecure-entry" fn outputs6() -> ReprTransparentStruct { + ReprTransparentStruct { _marker1: (), _marker2: (), field: 0xAA, _marker3: () } +} +#[no_mangle] +pub extern "C-cmse-nonsecure-entry" fn outputs7( +) -> ReprTransparentStruct> { + ReprTransparentStruct { + _marker1: (), + _marker2: (), + field: ReprTransparentStruct { _marker1: (), _marker2: (), field: 0xAA, _marker3: () }, + _marker3: (), + } +} +#[no_mangle] +pub extern "C-cmse-nonsecure-entry" fn outputs8() -> ReprTransparentEnumU64 { + ReprTransparentEnumU64::A(0) +} +#[no_mangle] +pub extern "C-cmse-nonsecure-entry" fn outputs9() -> U32Compound { + U32Compound(1, 2) +} From a802fd9c11f98c660b15bac6cec114066c786ff2 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 14 Oct 2024 22:43:41 +0200 Subject: [PATCH 304/357] ensure that a macOS os_unfair_lock that is moved while being held is not implicitly unlocked --- src/tools/miri/src/concurrency/sync.rs | 21 ++-- src/tools/miri/src/concurrency/thread.rs | 2 +- src/tools/miri/src/shims/unix/macos/sync.rs | 98 ++++++++++++++++--- src/tools/miri/src/shims/unix/sync.rs | 71 ++++++++------ src/tools/miri/src/shims/windows/sync.rs | 15 ++- .../apple_os_unfair_lock_move_deadlock.rs | 13 +++ .../apple_os_unfair_lock_move_deadlock.stderr | 13 +++ .../concurrency/apple-os-unfair-lock.rs | 4 +- 8 files changed, 178 insertions(+), 59 deletions(-) create mode 100644 src/tools/miri/tests/fail-dep/concurrency/apple_os_unfair_lock_move_deadlock.rs create mode 100644 src/tools/miri/tests/fail-dep/concurrency/apple_os_unfair_lock_move_deadlock.stderr diff --git a/src/tools/miri/src/concurrency/sync.rs b/src/tools/miri/src/concurrency/sync.rs index e7e6c100cfe..199aedfa6d2 100644 --- a/src/tools/miri/src/concurrency/sync.rs +++ b/src/tools/miri/src/concurrency/sync.rs @@ -223,13 +223,15 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } /// Helper for lazily initialized `alloc_extra.sync` data: - /// Checks if the primitive is initialized, and return its associated data if so. - /// Otherwise, calls `new_data` to initialize the primitive. + /// Checks if the primitive is initialized: + /// - If yes, fetches the data from `alloc_extra.sync`, or calls `missing_data` if that fails + /// and stores that in `alloc_extra.sync`. + /// - Otherwise, calls `new_data` to initialize the primitive. fn lazy_sync_get_data( &mut self, primitive: &MPlaceTy<'tcx>, init_offset: Size, - name: &str, + missing_data: impl FnOnce() -> InterpResult<'tcx, T>, new_data: impl FnOnce(&mut MiriInterpCx<'tcx>) -> InterpResult<'tcx, T>, ) -> InterpResult<'tcx, T> { let this = self.eval_context_mut(); @@ -254,11 +256,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // If it is initialized, it must be found in the "sync primitive" table, // or else it has been moved illegally. let (alloc, offset, _) = this.ptr_get_alloc_id(primitive.ptr(), 0)?; - let alloc_extra = this.get_alloc_extra(alloc)?; - let data = alloc_extra - .get_sync::(offset) - .ok_or_else(|| err_ub_format!("`{name}` can't be moved after first use"))?; - interp_ok(*data) + let (alloc_extra, _machine) = this.get_alloc_extra_mut(alloc)?; + if let Some(data) = alloc_extra.get_sync::(offset) { + interp_ok(*data) + } else { + let data = missing_data()?; + alloc_extra.sync.insert(offset, Box::new(data)); + interp_ok(data) + } } else { let data = new_data(this)?; this.lazy_sync_init(primitive, init_offset, data)?; diff --git a/src/tools/miri/src/concurrency/thread.rs b/src/tools/miri/src/concurrency/thread.rs index 3c5fb74fb76..3946cb5ee54 100644 --- a/src/tools/miri/src/concurrency/thread.rs +++ b/src/tools/miri/src/concurrency/thread.rs @@ -59,7 +59,7 @@ macro_rules! callback { @unblock = |$this:ident| $unblock:block ) => { callback!( - @capture<$tcx, $($lft),*> { $($name: $type),+ } + @capture<$tcx, $($lft),*> { $($name: $type),* } @unblock = |$this| $unblock @timeout = |_this| { unreachable!( diff --git a/src/tools/miri/src/shims/unix/macos/sync.rs b/src/tools/miri/src/shims/unix/macos/sync.rs index 25e1ff42fb9..1df1202442a 100644 --- a/src/tools/miri/src/shims/unix/macos/sync.rs +++ b/src/tools/miri/src/shims/unix/macos/sync.rs @@ -10,24 +10,42 @@ //! and we do not detect copying of the lock, but macOS doesn't guarantee anything //! in that case either. +use rustc_target::abi::Size; + use crate::*; -struct MacOsUnfairLock { - id: MutexId, +#[derive(Copy, Clone)] +enum MacOsUnfairLock { + Poisoned, + Active { id: MutexId }, } impl<'tcx> EvalContextExtPriv<'tcx> for crate::MiriInterpCx<'tcx> {} trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { - fn os_unfair_lock_getid(&mut self, lock_ptr: &OpTy<'tcx>) -> InterpResult<'tcx, MutexId> { + fn os_unfair_lock_get_data( + &mut self, + lock_ptr: &OpTy<'tcx>, + ) -> InterpResult<'tcx, MacOsUnfairLock> { let this = self.eval_context_mut(); let lock = this.deref_pointer(lock_ptr)?; - // We store the mutex ID in the `sync` metadata. This means that when the lock is moved, - // that's just implicitly creating a new lock at the new location. - let data = this.get_sync_or_init(lock.ptr(), |machine| { - let id = machine.sync.mutex_create(); - interp_ok(MacOsUnfairLock { id }) - })?; - interp_ok(data.id) + this.lazy_sync_get_data( + &lock, + Size::ZERO, // offset for init tracking + || { + // If we get here, due to how we reset things to zero in `os_unfair_lock_unlock`, + // this means the lock was moved while locked. This can happen with a `std` lock, + // but then any future attempt to unlock will just deadlock. In practice, terrible + // things can probably happen if you swap two locked locks, since they'd wake up + // from the wrong queue... we just won't catch all UB of this library API then (we + // would need to store some unique identifer in-memory for this, instead of a static + // LAZY_INIT_COOKIE). This can't be hit via `std::sync::Mutex`. + interp_ok(MacOsUnfairLock::Poisoned) + }, + |ecx| { + let id = ecx.machine.sync.mutex_create(); + interp_ok(MacOsUnfairLock::Active { id }) + }, + ) } } @@ -36,7 +54,21 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn os_unfair_lock_lock(&mut self, lock_op: &OpTy<'tcx>) -> InterpResult<'tcx> { let this = self.eval_context_mut(); - let id = this.os_unfair_lock_getid(lock_op)?; + let MacOsUnfairLock::Active { id } = this.os_unfair_lock_get_data(lock_op)? else { + // Trying to get a poisoned lock. Just block forever... + this.block_thread( + BlockReason::Sleep, + None, + callback!( + @capture<'tcx> {} + @unblock = |_this| { + panic!("we shouldn't wake up ever") + } + ), + ); + return interp_ok(()); + }; + if this.mutex_is_locked(id) { if this.mutex_get_owner(id) == this.active_thread() { // Matching the current macOS implementation: abort on reentrant locking. @@ -60,7 +92,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { ) -> InterpResult<'tcx> { let this = self.eval_context_mut(); - let id = this.os_unfair_lock_getid(lock_op)?; + let MacOsUnfairLock::Active { id } = this.os_unfair_lock_get_data(lock_op)? else { + // Trying to get a poisoned lock. That never works. + this.write_scalar(Scalar::from_bool(false), dest)?; + return interp_ok(()); + }; + if this.mutex_is_locked(id) { // Contrary to the blocking lock function, this does not check for // reentrancy. @@ -76,7 +113,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn os_unfair_lock_unlock(&mut self, lock_op: &OpTy<'tcx>) -> InterpResult<'tcx> { let this = self.eval_context_mut(); - let id = this.os_unfair_lock_getid(lock_op)?; + let MacOsUnfairLock::Active { id } = this.os_unfair_lock_get_data(lock_op)? else { + // The lock is poisoned, who knows who owns it... we'll pretend: someone else. + throw_machine_stop!(TerminationInfo::Abort( + "attempted to unlock an os_unfair_lock not owned by the current thread".to_owned() + )); + }; + + // Now, unlock. if this.mutex_unlock(id)?.is_none() { // Matching the current macOS implementation: abort. throw_machine_stop!(TerminationInfo::Abort( @@ -84,32 +128,56 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { )); } + // If the lock is not locked by anyone now, it went quer. + // Reset to zero so that it can be moved and initialized again for the next phase. + if !this.mutex_is_locked(id) { + let lock_place = this.deref_pointer_as(lock_op, this.machine.layouts.u32)?; + this.write_scalar_atomic(Scalar::from_u32(0), &lock_place, AtomicWriteOrd::Relaxed)?; + } + interp_ok(()) } fn os_unfair_lock_assert_owner(&mut self, lock_op: &OpTy<'tcx>) -> InterpResult<'tcx> { let this = self.eval_context_mut(); - let id = this.os_unfair_lock_getid(lock_op)?; + let MacOsUnfairLock::Active { id } = this.os_unfair_lock_get_data(lock_op)? else { + // The lock is poisoned, who knows who owns it... we'll pretend: someone else. + throw_machine_stop!(TerminationInfo::Abort( + "called os_unfair_lock_assert_owner on an os_unfair_lock not owned by the current thread".to_owned() + )); + }; if !this.mutex_is_locked(id) || this.mutex_get_owner(id) != this.active_thread() { throw_machine_stop!(TerminationInfo::Abort( "called os_unfair_lock_assert_owner on an os_unfair_lock not owned by the current thread".to_owned() )); } + // The lock is definitely not quiet since we are the owner. + interp_ok(()) } fn os_unfair_lock_assert_not_owner(&mut self, lock_op: &OpTy<'tcx>) -> InterpResult<'tcx> { let this = self.eval_context_mut(); - let id = this.os_unfair_lock_getid(lock_op)?; + let MacOsUnfairLock::Active { id } = this.os_unfair_lock_get_data(lock_op)? else { + // The lock is poisoned, who knows who owns it... we'll pretend: someone else. + return interp_ok(()); + }; if this.mutex_is_locked(id) && this.mutex_get_owner(id) == this.active_thread() { throw_machine_stop!(TerminationInfo::Abort( "called os_unfair_lock_assert_not_owner on an os_unfair_lock owned by the current thread".to_owned() )); } + // If the lock is not locked by anyone now, it went quer. + // Reset to zero so that it can be moved and initialized again for the next phase. + if !this.mutex_is_locked(id) { + let lock_place = this.deref_pointer_as(lock_op, this.machine.layouts.u32)?; + this.write_scalar_atomic(Scalar::from_u32(0), &lock_place, AtomicWriteOrd::Relaxed)?; + } + interp_ok(()) } } diff --git a/src/tools/miri/src/shims/unix/sync.rs b/src/tools/miri/src/shims/unix/sync.rs index 8eb874a4565..a4beaa47baa 100644 --- a/src/tools/miri/src/shims/unix/sync.rs +++ b/src/tools/miri/src/shims/unix/sync.rs @@ -189,11 +189,16 @@ fn mutex_get_data<'tcx, 'a>( mutex_ptr: &OpTy<'tcx>, ) -> InterpResult<'tcx, PthreadMutex> { let mutex = ecx.deref_pointer(mutex_ptr)?; - ecx.lazy_sync_get_data(&mutex, mutex_init_offset(ecx)?, "pthread_mutex_t", |ecx| { - let kind = mutex_kind_from_static_initializer(ecx, &mutex)?; - let id = ecx.machine.sync.mutex_create(); - interp_ok(PthreadMutex { id, kind }) - }) + ecx.lazy_sync_get_data( + &mutex, + mutex_init_offset(ecx)?, + || throw_ub_format!("`pthread_mutex_t` can't be moved after first use"), + |ecx| { + let kind = mutex_kind_from_static_initializer(ecx, &mutex)?; + let id = ecx.machine.sync.mutex_create(); + interp_ok(PthreadMutex { id, kind }) + }, + ) } /// Returns the kind of a static initializer. @@ -261,17 +266,22 @@ fn rwlock_get_data<'tcx>( rwlock_ptr: &OpTy<'tcx>, ) -> InterpResult<'tcx, PthreadRwLock> { let rwlock = ecx.deref_pointer(rwlock_ptr)?; - ecx.lazy_sync_get_data(&rwlock, rwlock_init_offset(ecx)?, "pthread_rwlock_t", |ecx| { - if !bytewise_equal_atomic_relaxed( - ecx, - &rwlock, - &ecx.eval_path(&["libc", "PTHREAD_RWLOCK_INITIALIZER"]), - )? { - throw_unsup_format!("unsupported static initializer used for `pthread_rwlock_t`"); - } - let id = ecx.machine.sync.rwlock_create(); - interp_ok(PthreadRwLock { id }) - }) + ecx.lazy_sync_get_data( + &rwlock, + rwlock_init_offset(ecx)?, + || throw_ub_format!("`pthread_rwlock_t` can't be moved after first use"), + |ecx| { + if !bytewise_equal_atomic_relaxed( + ecx, + &rwlock, + &ecx.eval_path(&["libc", "PTHREAD_RWLOCK_INITIALIZER"]), + )? { + throw_unsup_format!("unsupported static initializer used for `pthread_rwlock_t`"); + } + let id = ecx.machine.sync.rwlock_create(); + interp_ok(PthreadRwLock { id }) + }, + ) } // # pthread_condattr_t @@ -386,18 +396,23 @@ fn cond_get_data<'tcx>( cond_ptr: &OpTy<'tcx>, ) -> InterpResult<'tcx, PthreadCondvar> { let cond = ecx.deref_pointer(cond_ptr)?; - ecx.lazy_sync_get_data(&cond, cond_init_offset(ecx)?, "pthread_cond_t", |ecx| { - if !bytewise_equal_atomic_relaxed( - ecx, - &cond, - &ecx.eval_path(&["libc", "PTHREAD_COND_INITIALIZER"]), - )? { - throw_unsup_format!("unsupported static initializer used for `pthread_cond_t`"); - } - // This used the static initializer. The clock there is always CLOCK_REALTIME. - let id = ecx.machine.sync.condvar_create(); - interp_ok(PthreadCondvar { id, clock: ClockId::Realtime }) - }) + ecx.lazy_sync_get_data( + &cond, + cond_init_offset(ecx)?, + || throw_ub_format!("`pthread_cond_t` can't be moved after first use"), + |ecx| { + if !bytewise_equal_atomic_relaxed( + ecx, + &cond, + &ecx.eval_path(&["libc", "PTHREAD_COND_INITIALIZER"]), + )? { + throw_unsup_format!("unsupported static initializer used for `pthread_cond_t`"); + } + // This used the static initializer. The clock there is always CLOCK_REALTIME. + let id = ecx.machine.sync.condvar_create(); + interp_ok(PthreadCondvar { id, clock: ClockId::Realtime }) + }, + ) } impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} diff --git a/src/tools/miri/src/shims/windows/sync.rs b/src/tools/miri/src/shims/windows/sync.rs index 3701f479e5c..f8861085fe5 100644 --- a/src/tools/miri/src/shims/windows/sync.rs +++ b/src/tools/miri/src/shims/windows/sync.rs @@ -24,11 +24,16 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { let init_once = this.deref_pointer(init_once_ptr)?; let init_offset = Size::ZERO; - this.lazy_sync_get_data(&init_once, init_offset, "INIT_ONCE", |this| { - // TODO: check that this is still all-zero. - let id = this.machine.sync.init_once_create(); - interp_ok(WindowsInitOnce { id }) - }) + this.lazy_sync_get_data( + &init_once, + init_offset, + || throw_ub_format!("`INIT_ONCE` can't be moved after first use"), + |this| { + // TODO: check that this is still all-zero. + let id = this.machine.sync.init_once_create(); + interp_ok(WindowsInitOnce { id }) + }, + ) } /// Returns `true` if we were succssful, `false` if we would block. diff --git a/src/tools/miri/tests/fail-dep/concurrency/apple_os_unfair_lock_move_deadlock.rs b/src/tools/miri/tests/fail-dep/concurrency/apple_os_unfair_lock_move_deadlock.rs new file mode 100644 index 00000000000..84061439334 --- /dev/null +++ b/src/tools/miri/tests/fail-dep/concurrency/apple_os_unfair_lock_move_deadlock.rs @@ -0,0 +1,13 @@ +//@only-target: darwin + +use std::cell::UnsafeCell; + +fn main() { + let lock = UnsafeCell::new(libc::OS_UNFAIR_LOCK_INIT); + + unsafe { libc::os_unfair_lock_lock(lock.get()) }; + let lock = lock; + // This needs to either error or deadlock. + unsafe { libc::os_unfair_lock_lock(lock.get()) }; + //~^ error: deadlock +} diff --git a/src/tools/miri/tests/fail-dep/concurrency/apple_os_unfair_lock_move_deadlock.stderr b/src/tools/miri/tests/fail-dep/concurrency/apple_os_unfair_lock_move_deadlock.stderr new file mode 100644 index 00000000000..f043c7074f0 --- /dev/null +++ b/src/tools/miri/tests/fail-dep/concurrency/apple_os_unfair_lock_move_deadlock.stderr @@ -0,0 +1,13 @@ +error: deadlock: the evaluated program deadlocked + --> tests/fail-dep/concurrency/apple_os_unfair_lock_move_deadlock.rs:LL:CC + | +LL | unsafe { libc::os_unfair_lock_lock(lock.get()) }; + | ^ the evaluated program deadlocked + | + = note: BACKTRACE: + = note: inside `main` at tests/fail-dep/concurrency/apple_os_unfair_lock_move_deadlock.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/pass-dep/concurrency/apple-os-unfair-lock.rs b/src/tools/miri/tests/pass-dep/concurrency/apple-os-unfair-lock.rs index 0fc432f24c8..f5b64474f83 100644 --- a/src/tools/miri/tests/pass-dep/concurrency/apple-os-unfair-lock.rs +++ b/src/tools/miri/tests/pass-dep/concurrency/apple-os-unfair-lock.rs @@ -16,8 +16,8 @@ fn main() { // `os_unfair_lock`s can be moved and leaked. // In the real implementation, even moving it while locked is possible - // (and "forks" the lock, i.e. old and new location have independent wait queues); - // Miri behavior differs here and anyway none of this is documented. + // (and "forks" the lock, i.e. old and new location have independent wait queues). + // We only test the somewhat sane case of moving while unlocked that `std` plans to rely on. let lock = lock; let locked = unsafe { libc::os_unfair_lock_trylock(lock.get()) }; assert!(locked); From 373142aaa1e64f8a1e9071deaf0675c181ca3b47 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Mon, 14 Oct 2024 17:15:53 -0400 Subject: [PATCH 305/357] Mark LazyCell::into_inner unstably const Other cell `into_inner` functions are const and there shouldn't be any problem here. Make the unstable `LazyCell::into_inner` const under the same gate as its stability (`lazy_cell_into_inner`). Tracking issue: https://github.com/rust-lang/rust/issues/125623 --- library/core/src/cell/lazy.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/cell/lazy.rs b/library/core/src/cell/lazy.rs index 5bc13779af9..d323fbeac9c 100644 --- a/library/core/src/cell/lazy.rs +++ b/library/core/src/cell/lazy.rs @@ -79,7 +79,7 @@ impl T> LazyCell { /// assert_eq!(LazyCell::into_inner(lazy).ok(), Some("HELLO, WORLD!".to_string())); /// ``` #[unstable(feature = "lazy_cell_into_inner", issue = "125623")] - pub fn into_inner(this: Self) -> Result { + pub const fn into_inner(this: Self) -> Result { match this.state.into_inner() { State::Init(data) => Ok(data), State::Uninit(f) => Err(f), @@ -306,6 +306,6 @@ impl fmt::Debug for LazyCell { #[cold] #[inline(never)] -fn panic_poisoned() -> ! { +const fn panic_poisoned() -> ! { panic!("LazyCell instance has previously been poisoned") } From dda3066805ef0a0ad5f2d0d2cdb6bc0b66d8c19b Mon Sep 17 00:00:00 2001 From: Lieselotte <52315535+she3py@users.noreply.github.com> Date: Mon, 14 Oct 2024 23:22:51 +0200 Subject: [PATCH 306/357] Remove `'apostrophes'` from `rustc_parse_format` --- compiler/rustc_index_macros/Cargo.toml | 2 +- compiler/rustc_parse_format/src/lib.rs | 8 +-- .../session-diagnostic/diagnostic-derive.rs | 2 +- .../diagnostic-derive.stderr | 4 +- .../on_unimplemented/broken_format.rs | 4 +- .../on_unimplemented/broken_format.stderr | 4 +- tests/ui/fmt/closing-brace-as-fill.rs | 2 +- tests/ui/fmt/closing-brace-as-fill.stderr | 6 +- tests/ui/fmt/format-string-error-2.rs | 2 +- tests/ui/fmt/format-string-error-2.stderr | 56 +++++++++---------- tests/ui/fmt/format-string-error.rs | 6 +- tests/ui/fmt/format-string-error.stderr | 24 ++++---- tests/ui/fmt/format-string-wrong-order.rs | 4 +- tests/ui/fmt/format-string-wrong-order.stderr | 8 +-- tests/ui/fmt/ifmt-bad-arg.rs | 2 +- tests/ui/fmt/ifmt-bad-arg.stderr | 8 +-- tests/ui/fmt/issue-91556.rs | 4 +- tests/ui/fmt/issue-91556.stderr | 4 +- .../ui/fmt/respanned-literal-issue-106191.rs | 4 +- .../fmt/respanned-literal-issue-106191.stderr | 8 +-- tests/ui/macros/issue-51848.stderr | 4 +- 21 files changed, 83 insertions(+), 83 deletions(-) diff --git a/compiler/rustc_index_macros/Cargo.toml b/compiler/rustc_index_macros/Cargo.toml index 07ee81788ce..a7c2a1804dd 100644 --- a/compiler/rustc_index_macros/Cargo.toml +++ b/compiler/rustc_index_macros/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" proc-macro = true [dependencies] -syn = { version = "2.0.9", features = ["full"] } +syn = { version = "2.0.9", features = ["full", "extra-traits"] } proc-macro2 = "1" quote = "1" diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs index e7ef4385baf..1716f417969 100644 --- a/compiler/rustc_parse_format/src/lib.rs +++ b/compiler/rustc_parse_format/src/lib.rs @@ -473,19 +473,19 @@ impl<'a> Parser<'a> { } pos = peek_pos; - description = format!("expected `'}}'`, found `{maybe:?}`"); + description = format!("expected `}}`, found `{}`", maybe.escape_debug()); } else { - description = "expected `'}'` but string was terminated".to_owned(); + description = "expected `}` but string was terminated".to_owned(); // point at closing `"` pos = self.input.len() - if self.append_newline { 1 } else { 0 }; } let pos = self.to_span_index(pos); - let label = "expected `'}'`".to_owned(); + let label = "expected `}`".to_owned(); let (note, secondary_label) = if arg.format.fill == Some('}') { ( - Some("the character `'}'` is interpreted as a fill character because of the `:` that precedes it".to_owned()), + Some("the character `}` is interpreted as a fill character because of the `:` that precedes it".to_owned()), arg.format.fill_span.map(|sp| ("this is not interpreted as a formatting closing brace".to_owned(), sp)), ) } else { diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs index e8cec632177..1577b68e748 100644 --- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs +++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs @@ -178,7 +178,7 @@ struct ErrorWithNonexistentField { } #[derive(Diagnostic)] -//~^ ERROR invalid format string: expected `'}'` +//~^ ERROR invalid format string: expected `}` #[diag(no_crate_example, code = E0123)] struct ErrorMissingClosingBrace { #[suggestion(no_crate_suggestion, code = "{name")] diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr index 97f9896f3a7..ff7af388514 100644 --- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr +++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr @@ -184,11 +184,11 @@ error: `name` doesn't refer to a field on this type LL | #[suggestion(no_crate_suggestion, code = "{name}")] | ^^^^^^^^ -error: invalid format string: expected `'}'` but string was terminated +error: invalid format string: expected `}` but string was terminated --> $DIR/diagnostic-derive.rs:180:10 | LL | #[derive(Diagnostic)] - | ^^^^^^^^^^ expected `'}'` in format string + | ^^^^^^^^^^ expected `}` in format string | = note: if you intended to print `{`, you can escape it using `{{` = note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/broken_format.rs b/tests/ui/diagnostic_namespace/on_unimplemented/broken_format.rs index 8d8917fd319..3ca58b28181 100644 --- a/tests/ui/diagnostic_namespace/on_unimplemented/broken_format.rs +++ b/tests/ui/diagnostic_namespace/on_unimplemented/broken_format.rs @@ -19,8 +19,8 @@ trait ImportantTrait3 {} trait ImportantTrait4 {} #[diagnostic::on_unimplemented(message = "Test {Self:!}")] -//~^WARN expected `'}'`, found `'!'` -//~|WARN expected `'}'`, found `'!'` +//~^WARN expected `}`, found `!` +//~|WARN expected `}`, found `!` //~|WARN unmatched `}` found //~|WARN unmatched `}` found trait ImportantTrait5 {} diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/broken_format.stderr b/tests/ui/diagnostic_namespace/on_unimplemented/broken_format.stderr index 932e81ca48e..b4ed06cb63d 100644 --- a/tests/ui/diagnostic_namespace/on_unimplemented/broken_format.stderr +++ b/tests/ui/diagnostic_namespace/on_unimplemented/broken_format.stderr @@ -30,7 +30,7 @@ LL | #[diagnostic::on_unimplemented(message = "Test {Self:123}")] | = help: no format specifier are supported in this position -warning: expected `'}'`, found `'!'` +warning: expected `}`, found `!` --> $DIR/broken_format.rs:21:32 | LL | #[diagnostic::on_unimplemented(message = "Test {Self:!}")] @@ -153,7 +153,7 @@ note: required by a bound in `check_4` LL | fn check_4(_: impl ImportantTrait4) {} | ^^^^^^^^^^^^^^^ required by this bound in `check_4` -warning: expected `'}'`, found `'!'` +warning: expected `}`, found `!` --> $DIR/broken_format.rs:21:32 | LL | #[diagnostic::on_unimplemented(message = "Test {Self:!}")] diff --git a/tests/ui/fmt/closing-brace-as-fill.rs b/tests/ui/fmt/closing-brace-as-fill.rs index 6ad257f943e..5865ee31c43 100644 --- a/tests/ui/fmt/closing-brace-as-fill.rs +++ b/tests/ui/fmt/closing-brace-as-fill.rs @@ -4,5 +4,5 @@ fn main() { println!("Hello, world! {0:}<3", 2); - //~^ ERROR invalid format string: expected `'}'` but string was terminated + //~^ ERROR invalid format string: expected `}` but string was terminated } diff --git a/tests/ui/fmt/closing-brace-as-fill.stderr b/tests/ui/fmt/closing-brace-as-fill.stderr index 70068fa3aad..aa22beddf45 100644 --- a/tests/ui/fmt/closing-brace-as-fill.stderr +++ b/tests/ui/fmt/closing-brace-as-fill.stderr @@ -1,12 +1,12 @@ -error: invalid format string: expected `'}'` but string was terminated +error: invalid format string: expected `}` but string was terminated --> $DIR/closing-brace-as-fill.rs:6:35 | LL | println!("Hello, world! {0:}<3", 2); - | - ^ expected `'}'` in format string + | - ^ expected `}` in format string | | | this is not interpreted as a formatting closing brace | - = note: the character `'}'` is interpreted as a fill character because of the `:` that precedes it + = note: the character `}` is interpreted as a fill character because of the `:` that precedes it error: aborting due to 1 previous error diff --git a/tests/ui/fmt/format-string-error-2.rs b/tests/ui/fmt/format-string-error-2.rs index 1f7f0d8f6be..357dd7b10a3 100644 --- a/tests/ui/fmt/format-string-error-2.rs +++ b/tests/ui/fmt/format-string-error-2.rs @@ -72,7 +72,7 @@ raw { \n // note: `\x7B` is `{` println!("\x7B}\u{8} {", 1); - //~^ ERROR invalid format string: expected `'}'` but string was terminated + //~^ ERROR invalid format string: expected `}` but string was terminated println!("\x7B}\u8 {", 1); //~^ ERROR incorrect unicode escape sequence diff --git a/tests/ui/fmt/format-string-error-2.stderr b/tests/ui/fmt/format-string-error-2.stderr index d5fe4081ac8..a2d142e0bab 100644 --- a/tests/ui/fmt/format-string-error-2.stderr +++ b/tests/ui/fmt/format-string-error-2.stderr @@ -9,138 +9,138 @@ help: format of unicode escape sequences uses braces LL | println!("\x7B}\u{8} {", 1); | ~~~~~ -error: invalid format string: expected `'}'`, found `'a'` +error: invalid format string: expected `}`, found `a` --> $DIR/format-string-error-2.rs:5:5 | LL | format!("{ | - because of this opening brace LL | a"); - | ^ expected `'}'` in format string + | ^ expected `}` in format string | = note: if you intended to print `{`, you can escape it using `{{` -error: invalid format string: expected `'}'`, found `'b'` +error: invalid format string: expected `}`, found `b` --> $DIR/format-string-error-2.rs:9:5 | LL | format!("{ \ | - because of this opening brace LL | \ LL | b"); - | ^ expected `'}'` in format string + | ^ expected `}` in format string | = note: if you intended to print `{`, you can escape it using `{{` -error: invalid format string: expected `'}'`, found `'\'` +error: invalid format string: expected `}`, found `\` --> $DIR/format-string-error-2.rs:11:18 | LL | format!(r#"{ \ - | - ^ expected `'}'` in format string + | - ^ expected `}` in format string | | | because of this opening brace | = note: if you intended to print `{`, you can escape it using `{{` -error: invalid format string: expected `'}'`, found `'\'` +error: invalid format string: expected `}`, found `\` --> $DIR/format-string-error-2.rs:15:18 | LL | format!(r#"{ \n - | - ^ expected `'}'` in format string + | - ^ expected `}` in format string | | | because of this opening brace | = note: if you intended to print `{`, you can escape it using `{{` -error: invalid format string: expected `'}'`, found `'e'` +error: invalid format string: expected `}`, found `e` --> $DIR/format-string-error-2.rs:21:5 | LL | format!("{ \n | - because of this opening brace LL | \n LL | e"); - | ^ expected `'}'` in format string + | ^ expected `}` in format string | = note: if you intended to print `{`, you can escape it using `{{` -error: invalid format string: expected `'}'`, found `'a'` +error: invalid format string: expected `}`, found `a` --> $DIR/format-string-error-2.rs:25:5 | LL | { | - because of this opening brace LL | a"); - | ^ expected `'}'` in format string + | ^ expected `}` in format string | = note: if you intended to print `{`, you can escape it using `{{` -error: invalid format string: expected `'}'`, found `'a'` +error: invalid format string: expected `}`, found `a` --> $DIR/format-string-error-2.rs:29:5 | LL | { | - because of this opening brace LL | a - | ^ expected `'}'` in format string + | ^ expected `}` in format string | = note: if you intended to print `{`, you can escape it using `{{` -error: invalid format string: expected `'}'`, found `'b'` +error: invalid format string: expected `}`, found `b` --> $DIR/format-string-error-2.rs:35:5 | LL | { \ | - because of this opening brace LL | \ LL | b"); - | ^ expected `'}'` in format string + | ^ expected `}` in format string | = note: if you intended to print `{`, you can escape it using `{{` -error: invalid format string: expected `'}'`, found `'b'` +error: invalid format string: expected `}`, found `b` --> $DIR/format-string-error-2.rs:40:5 | LL | { \ | - because of this opening brace LL | \ LL | b \ - | ^ expected `'}'` in format string + | ^ expected `}` in format string | = note: if you intended to print `{`, you can escape it using `{{` -error: invalid format string: expected `'}'`, found `'\'` +error: invalid format string: expected `}`, found `\` --> $DIR/format-string-error-2.rs:45:8 | LL | raw { \ - | - ^ expected `'}'` in format string + | - ^ expected `}` in format string | | | because of this opening brace | = note: if you intended to print `{`, you can escape it using `{{` -error: invalid format string: expected `'}'`, found `'\'` +error: invalid format string: expected `}`, found `\` --> $DIR/format-string-error-2.rs:50:8 | LL | raw { \n - | - ^ expected `'}'` in format string + | - ^ expected `}` in format string | | | because of this opening brace | = note: if you intended to print `{`, you can escape it using `{{` -error: invalid format string: expected `'}'`, found `'e'` +error: invalid format string: expected `}`, found `e` --> $DIR/format-string-error-2.rs:57:5 | LL | { \n | - because of this opening brace LL | \n LL | e"); - | ^ expected `'}'` in format string + | ^ expected `}` in format string | = note: if you intended to print `{`, you can escape it using `{{` -error: invalid format string: expected `'}'`, found `'a'` +error: invalid format string: expected `}`, found `a` --> $DIR/format-string-error-2.rs:67:5 | LL | { | - because of this opening brace LL | asdf} - | ^ expected `'}'` in format string + | ^ expected `}` in format string | = note: if you intended to print `{`, you can escape it using `{{` @@ -150,11 +150,11 @@ error: 1 positional argument in format string, but no arguments were given LL | println!("\t{}"); | ^^ -error: invalid format string: expected `'}'` but string was terminated +error: invalid format string: expected `}` but string was terminated --> $DIR/format-string-error-2.rs:74:27 | LL | println!("\x7B}\u{8} {", 1); - | -^ expected `'}'` in format string + | -^ expected `}` in format string | | | because of this opening brace | diff --git a/tests/ui/fmt/format-string-error.rs b/tests/ui/fmt/format-string-error.rs index 9b436e2c479..cb9449be532 100644 --- a/tests/ui/fmt/format-string-error.rs +++ b/tests/ui/fmt/format-string-error.rs @@ -2,7 +2,7 @@ fn main() { println!("{"); - //~^ ERROR invalid format string: expected `'}'` but string was terminated + //~^ ERROR invalid format string: expected `}` but string was terminated println!("{{}}"); println!("}"); //~^ ERROR invalid format string: unmatched `}` found @@ -13,11 +13,11 @@ fn main() { let _ = format!("{a:._$}", a = "", _ = 0); //~^ ERROR invalid format string: invalid argument name `_` let _ = format!("{"); - //~^ ERROR invalid format string: expected `'}'` but string was terminated + //~^ ERROR invalid format string: expected `}` but string was terminated let _ = format!("}"); //~^ ERROR invalid format string: unmatched `}` found let _ = format!("{\\}"); - //~^ ERROR invalid format string: expected `'}'`, found `'\'` + //~^ ERROR invalid format string: expected `}`, found `\` let _ = format!("\n\n\n{\n\n\n"); //~^ ERROR invalid format string let _ = format!(r###" diff --git a/tests/ui/fmt/format-string-error.stderr b/tests/ui/fmt/format-string-error.stderr index 37a181e6fcb..9d6a91413d0 100644 --- a/tests/ui/fmt/format-string-error.stderr +++ b/tests/ui/fmt/format-string-error.stderr @@ -1,8 +1,8 @@ -error: invalid format string: expected `'}'` but string was terminated +error: invalid format string: expected `}` but string was terminated --> $DIR/format-string-error.rs:4:16 | LL | println!("{"); - | -^ expected `'}'` in format string + | -^ expected `}` in format string | | | because of this opening brace | @@ -40,11 +40,11 @@ LL | let _ = format!("{a:._$}", a = "", _ = 0); | = note: argument name cannot be a single underscore -error: invalid format string: expected `'}'` but string was terminated +error: invalid format string: expected `}` but string was terminated --> $DIR/format-string-error.rs:15:23 | LL | let _ = format!("{"); - | -^ expected `'}'` in format string + | -^ expected `}` in format string | | | because of this opening brace | @@ -58,44 +58,44 @@ LL | let _ = format!("}"); | = note: if you intended to print `}`, you can escape it using `}}` -error: invalid format string: expected `'}'`, found `'\'` +error: invalid format string: expected `}`, found `\` --> $DIR/format-string-error.rs:19:23 | LL | let _ = format!("{\}"); - | -^ expected `'}'` in format string + | -^ expected `}` in format string | | | because of this opening brace | = note: if you intended to print `{`, you can escape it using `{{` -error: invalid format string: expected `'}'` but string was terminated +error: invalid format string: expected `}` but string was terminated --> $DIR/format-string-error.rs:21:35 | LL | let _ = format!("\n\n\n{\n\n\n"); - | - ^ expected `'}'` in format string + | - ^ expected `}` in format string | | | because of this opening brace | = note: if you intended to print `{`, you can escape it using `{{` -error: invalid format string: expected `'}'` but string was terminated +error: invalid format string: expected `}` but string was terminated --> $DIR/format-string-error.rs:27:3 | LL | {"###); - | -^ expected `'}'` in format string + | -^ expected `}` in format string | | | because of this opening brace | = note: if you intended to print `{`, you can escape it using `{{` -error: invalid format string: expected `'}'` but string was terminated +error: invalid format string: expected `}` but string was terminated --> $DIR/format-string-error.rs:35:1 | LL | { | - because of this opening brace LL | LL | "###); - | ^ expected `'}'` in format string + | ^ expected `}` in format string | = note: if you intended to print `{`, you can escape it using `{{` diff --git a/tests/ui/fmt/format-string-wrong-order.rs b/tests/ui/fmt/format-string-wrong-order.rs index da775be3ffd..891279b97e4 100644 --- a/tests/ui/fmt/format-string-wrong-order.rs +++ b/tests/ui/fmt/format-string-wrong-order.rs @@ -7,9 +7,9 @@ fn main() { format!("{?:?}", bar); //~^ ERROR invalid format string: expected format parameter to occur after `:` format!("{??}", bar); - //~^ ERROR invalid format string: expected `'}'`, found `'?'` + //~^ ERROR invalid format string: expected `}`, found `?` format!("{?;bar}"); - //~^ ERROR invalid format string: expected `'}'`, found `'?'` + //~^ ERROR invalid format string: expected `}`, found `?` format!("{?:#?}", bar); //~^ ERROR invalid format string: expected format parameter to occur after `:` format!("Hello {<5:}!", "x"); diff --git a/tests/ui/fmt/format-string-wrong-order.stderr b/tests/ui/fmt/format-string-wrong-order.stderr index 3ef07720c15..7f017511761 100644 --- a/tests/ui/fmt/format-string-wrong-order.stderr +++ b/tests/ui/fmt/format-string-wrong-order.stderr @@ -22,21 +22,21 @@ LL | format!("{?:?}", bar); | = note: `?` comes after `:`, try `:?` instead -error: invalid format string: expected `'}'`, found `'?'` +error: invalid format string: expected `}`, found `?` --> $DIR/format-string-wrong-order.rs:9:15 | LL | format!("{??}", bar); - | -^ expected `'}'` in format string + | -^ expected `}` in format string | | | because of this opening brace | = note: if you intended to print `{`, you can escape it using `{{` -error: invalid format string: expected `'}'`, found `'?'` +error: invalid format string: expected `}`, found `?` --> $DIR/format-string-wrong-order.rs:11:15 | LL | format!("{?;bar}"); - | -^ expected `'}'` in format string + | -^ expected `}` in format string | | | because of this opening brace | diff --git a/tests/ui/fmt/ifmt-bad-arg.rs b/tests/ui/fmt/ifmt-bad-arg.rs index 68861d7bf3f..e39ffb8fe1b 100644 --- a/tests/ui/fmt/ifmt-bad-arg.rs +++ b/tests/ui/fmt/ifmt-bad-arg.rs @@ -48,7 +48,7 @@ fn main() { // bad syntax of the format string - format!("{"); //~ ERROR: expected `'}'` but string was terminated + format!("{"); //~ ERROR: expected `}` but string was terminated format!("foo } bar"); //~ ERROR: unmatched `}` found format!("foo }"); //~ ERROR: unmatched `}` found diff --git a/tests/ui/fmt/ifmt-bad-arg.stderr b/tests/ui/fmt/ifmt-bad-arg.stderr index 09ce3dca411..4344aee83c2 100644 --- a/tests/ui/fmt/ifmt-bad-arg.stderr +++ b/tests/ui/fmt/ifmt-bad-arg.stderr @@ -136,11 +136,11 @@ LL | format!("{valuea} {valueb}", valuea=5, valuec=7); | | | formatting specifier missing -error: invalid format string: expected `'}'` but string was terminated +error: invalid format string: expected `}` but string was terminated --> $DIR/ifmt-bad-arg.rs:51:15 | LL | format!("{"); - | -^ expected `'}'` in format string + | -^ expected `}` in format string | | | because of this opening brace | @@ -172,13 +172,13 @@ LL | format!("foo %s baz", "bar"); | = note: printf formatting is not supported; see the documentation for `std::fmt` -error: invalid format string: expected `'}'`, found `'t'` +error: invalid format string: expected `}`, found `t` --> $DIR/ifmt-bad-arg.rs:75:1 | LL | ninth number: { | - because of this opening brace LL | tenth number: {}", - | ^ expected `'}'` in format string + | ^ expected `}` in format string | = note: if you intended to print `{`, you can escape it using `{{` diff --git a/tests/ui/fmt/issue-91556.rs b/tests/ui/fmt/issue-91556.rs index e782e6f9076..fcf8909859c 100644 --- a/tests/ui/fmt/issue-91556.rs +++ b/tests/ui/fmt/issue-91556.rs @@ -1,8 +1,8 @@ fn main() { let _ = format!(concat!("{0}𝖳𝖾𝗌𝗍{"), i); - //~^ ERROR: invalid format string: expected `'}'` but string was terminated + //~^ ERROR: invalid format string: expected `}` but string was terminated //~| NOTE: if you intended to print `{`, you can escape it using `{{` //~| NOTE: in this expansion of concat! //~| NOTE: in this expansion of concat! - //~| NOTE: expected `'}'` in format string + //~| NOTE: expected `}` in format string } diff --git a/tests/ui/fmt/issue-91556.stderr b/tests/ui/fmt/issue-91556.stderr index beab3db0d94..52917fb8c42 100644 --- a/tests/ui/fmt/issue-91556.stderr +++ b/tests/ui/fmt/issue-91556.stderr @@ -1,8 +1,8 @@ -error: invalid format string: expected `'}'` but string was terminated +error: invalid format string: expected `}` but string was terminated --> $DIR/issue-91556.rs:2:19 | LL | let _ = format!(concat!("{0}𝖳𝖾𝗌𝗍{"), i); - | ^^^^^^^^^^^^^^^^^^^ expected `'}'` in format string + | ^^^^^^^^^^^^^^^^^^^ expected `}` in format string | = note: if you intended to print `{`, you can escape it using `{{` = note: this error originates in the macro `concat` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/fmt/respanned-literal-issue-106191.rs b/tests/ui/fmt/respanned-literal-issue-106191.rs index b0c0855a870..0a127b1a0ca 100644 --- a/tests/ui/fmt/respanned-literal-issue-106191.rs +++ b/tests/ui/fmt/respanned-literal-issue-106191.rs @@ -4,7 +4,7 @@ extern crate format_string_proc_macro; fn main() { format_string_proc_macro::respan_to_invalid_format_literal!("¡"); - //~^ ERROR invalid format string: expected `'}'` but string was terminated + //~^ ERROR invalid format string: expected `}` but string was terminated format_args!(r#concat!("¡ {")); - //~^ ERROR invalid format string: expected `'}'` but string was terminated + //~^ ERROR invalid format string: expected `}` but string was terminated } diff --git a/tests/ui/fmt/respanned-literal-issue-106191.stderr b/tests/ui/fmt/respanned-literal-issue-106191.stderr index 73a3af65a38..17ab29e799b 100644 --- a/tests/ui/fmt/respanned-literal-issue-106191.stderr +++ b/tests/ui/fmt/respanned-literal-issue-106191.stderr @@ -1,16 +1,16 @@ -error: invalid format string: expected `'}'` but string was terminated +error: invalid format string: expected `}` but string was terminated --> $DIR/respanned-literal-issue-106191.rs:6:65 | LL | format_string_proc_macro::respan_to_invalid_format_literal!("¡"); - | ^^^ expected `'}'` in format string + | ^^^ expected `}` in format string | = note: if you intended to print `{`, you can escape it using `{{` -error: invalid format string: expected `'}'` but string was terminated +error: invalid format string: expected `}` but string was terminated --> $DIR/respanned-literal-issue-106191.rs:8:18 | LL | format_args!(r#concat!("¡ {")); - | ^^^^^^^^^^^^^^^^^^^^^^^ expected `'}'` in format string + | ^^^^^^^^^^^^^^^^^^^^^^^ expected `}` in format string | = note: if you intended to print `{`, you can escape it using `{{` = note: this error originates in the macro `concat` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/macros/issue-51848.stderr b/tests/ui/macros/issue-51848.stderr index c25bedf37b7..30b64113d73 100644 --- a/tests/ui/macros/issue-51848.stderr +++ b/tests/ui/macros/issue-51848.stderr @@ -1,8 +1,8 @@ -error: invalid format string: expected `'}'` but string was terminated +error: invalid format string: expected `}` but string was terminated --> $DIR/issue-51848.rs:6:20 | LL | println!("{"); - | -^ expected `'}'` in format string + | -^ expected `}` in format string | | | because of this opening brace ... From 413ea993deebdb321db71ac8a9187e13e9990370 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 14 Oct 2024 23:37:03 +0200 Subject: [PATCH 307/357] use new check_min_arg_count helper in more places --- src/tools/miri/src/shims/backtrace.rs | 8 ++-- .../src/shims/unix/linux/foreign_items.rs | 2 +- src/tools/miri/src/shims/unix/linux/sync.rs | 42 ++++++------------- 3 files changed, 17 insertions(+), 35 deletions(-) diff --git a/src/tools/miri/src/shims/backtrace.rs b/src/tools/miri/src/shims/backtrace.rs index 25afda4edc8..ae2cdaa8d57 100644 --- a/src/tools/miri/src/shims/backtrace.rs +++ b/src/tools/miri/src/shims/backtrace.rs @@ -5,6 +5,7 @@ use rustc_span::{BytePos, Loc, Symbol, hygiene}; use rustc_target::abi::Size; use rustc_target::spec::abi::Abi; +use crate::helpers::check_min_arg_count; use crate::*; impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} @@ -39,11 +40,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let this = self.eval_context_mut(); let tcx = this.tcx; - let flags = if let Some(flags_op) = args.first() { - this.read_scalar(flags_op)?.to_u64()? - } else { - throw_ub_format!("expected at least 1 argument") - }; + let [flags] = check_min_arg_count("miri_get_backtrace", args)?; + let flags = this.read_scalar(flags)?.to_u64()?; let mut data = Vec::new(); for frame in this.active_thread_stack().iter().rev() { diff --git a/src/tools/miri/src/shims/unix/linux/foreign_items.rs b/src/tools/miri/src/shims/unix/linux/foreign_items.rs index 6c8345652c2..e73bde1ddb6 100644 --- a/src/tools/miri/src/shims/unix/linux/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/linux/foreign_items.rs @@ -150,7 +150,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } // `futex` is used by some synchronization primitives. num if num == sys_futex => { - futex(this, &args[1..], dest)?; + futex(this, args, dest)?; } num if num == sys_eventfd2 => { let [_, initval, flags] = diff --git a/src/tools/miri/src/shims/unix/linux/sync.rs b/src/tools/miri/src/shims/unix/linux/sync.rs index 5833ec64fc6..941011bfac6 100644 --- a/src/tools/miri/src/shims/unix/linux/sync.rs +++ b/src/tools/miri/src/shims/unix/linux/sync.rs @@ -1,7 +1,8 @@ +use crate::helpers::check_min_arg_count; use crate::*; /// Implementation of the SYS_futex syscall. -/// `args` is the arguments *after* the syscall number. +/// `args` is the arguments *including* the syscall number. pub fn futex<'tcx>( this: &mut MiriInterpCx<'tcx>, args: &[OpTy<'tcx>], @@ -15,12 +16,7 @@ pub fn futex<'tcx>( // may or may not be left out from the `syscall()` call. // Therefore we don't use `check_arg_count` here, but only check for the // number of arguments to fall within a range. - let [addr, op, val, ..] = args else { - throw_ub_format!( - "incorrect number of arguments for `futex` syscall: got {}, expected at least 3", - args.len() - ); - }; + let [_, addr, op, val] = check_min_arg_count("`syscall(SYS_futex, ...)`", args)?; // The first three arguments (after the syscall number itself) are the same to all futex operations: // (int *addr, int op, int val). @@ -54,24 +50,16 @@ pub fn futex<'tcx>( op if op & !futex_realtime == futex_wait || op & !futex_realtime == futex_wait_bitset => { let wait_bitset = op & !futex_realtime == futex_wait_bitset; - let bitset = if wait_bitset { - let [_, _, _, timeout, uaddr2, bitset, ..] = args else { - throw_ub_format!( - "incorrect number of arguments for `futex` syscall with `op=FUTEX_WAIT_BITSET`: got {}, expected at least 6", - args.len() - ); - }; + let (timeout, bitset) = if wait_bitset { + let [_, _, _, _, timeout, uaddr2, bitset] = + check_min_arg_count("`syscall(SYS_futex, FUTEX_WAIT_BITSET, ...)`", args)?; let _timeout = this.read_pointer(timeout)?; let _uaddr2 = this.read_pointer(uaddr2)?; - this.read_scalar(bitset)?.to_u32()? + (timeout, this.read_scalar(bitset)?.to_u32()?) } else { - if args.len() < 4 { - throw_ub_format!( - "incorrect number of arguments for `futex` syscall with `op=FUTEX_WAIT`: got {}, expected at least 4", - args.len() - ); - } - u32::MAX + let [_, _, _, _, timeout] = + check_min_arg_count("`syscall(SYS_futex, FUTEX_WAIT, ...)`", args)?; + (timeout, u32::MAX) }; if bitset == 0 { @@ -80,7 +68,7 @@ pub fn futex<'tcx>( return interp_ok(()); } - let timeout = this.deref_pointer_as(&args[3], this.libc_ty_layout("timespec"))?; + let timeout = this.deref_pointer_as(timeout, this.libc_ty_layout("timespec"))?; let timeout = if this.ptr_is_null(timeout.ptr())? { None } else { @@ -183,12 +171,8 @@ pub fn futex<'tcx>( // Same as FUTEX_WAKE, but allows you to specify a bitset to select which threads to wake up. op if op == futex_wake || op == futex_wake_bitset => { let bitset = if op == futex_wake_bitset { - let [_, _, _, timeout, uaddr2, bitset, ..] = args else { - throw_ub_format!( - "incorrect number of arguments for `futex` syscall with `op=FUTEX_WAKE_BITSET`: got {}, expected at least 6", - args.len() - ); - }; + let [_, _, _, _, timeout, uaddr2, bitset] = + check_min_arg_count("`syscall(SYS_futex, FUTEX_WAKE_BITSET, ...)`", args)?; let _timeout = this.read_pointer(timeout)?; let _uaddr2 = this.read_pointer(uaddr2)?; this.read_scalar(bitset)?.to_u32()? From 3c31729887053411226fea3013c3a8825257c928 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20Bj=C3=B8rnager=20Jensen?= Date: Wed, 9 Oct 2024 22:33:27 +0200 Subject: [PATCH 308/357] Stabilise 'const_make_ascii' --- library/core/src/char/methods.rs | 6 ++++-- library/core/src/lib.rs | 1 - library/core/src/num/mod.rs | 6 ++++-- library/core/src/slice/ascii.rs | 6 ++++-- library/core/src/str/mod.rs | 6 ++++-- 5 files changed, 16 insertions(+), 9 deletions(-) diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index 6bedb0d0dc4..04698193bba 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs @@ -1282,8 +1282,9 @@ impl char { /// /// [`to_ascii_uppercase()`]: #method.to_ascii_uppercase #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] - #[rustc_const_unstable(feature = "const_make_ascii", issue = "130698")] + #[rustc_const_stable(feature = "const_make_ascii", since = "CURRENT_RUSTC_VERSION")] #[inline] + #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn make_ascii_uppercase(&mut self) { *self = self.to_ascii_uppercase(); } @@ -1308,8 +1309,9 @@ impl char { /// /// [`to_ascii_lowercase()`]: #method.to_ascii_lowercase #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] - #[rustc_const_unstable(feature = "const_make_ascii", issue = "130698")] + #[rustc_const_stable(feature = "const_make_ascii", since = "CURRENT_RUSTC_VERSION")] #[inline] + #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn make_ascii_lowercase(&mut self) { *self = self.to_ascii_lowercase(); } diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 08c0d6e34cd..674bf075551 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -125,7 +125,6 @@ #![feature(const_heap)] #![feature(const_index_range_slice_index)] #![feature(const_likely)] -#![feature(const_make_ascii)] #![feature(const_nonnull_new)] #![feature(const_num_midpoint)] #![feature(const_option_ext)] diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index 31e35015d2d..f55d55171f2 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -624,8 +624,9 @@ impl u8 { /// /// [`to_ascii_uppercase`]: Self::to_ascii_uppercase #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] - #[rustc_const_unstable(feature = "const_make_ascii", issue = "130698")] + #[rustc_const_stable(feature = "const_make_ascii", since = "CURRENT_RUSTC_VERSION")] #[inline] + #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn make_ascii_uppercase(&mut self) { *self = self.to_ascii_uppercase(); } @@ -650,8 +651,9 @@ impl u8 { /// /// [`to_ascii_lowercase`]: Self::to_ascii_lowercase #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] - #[rustc_const_unstable(feature = "const_make_ascii", issue = "130698")] + #[rustc_const_stable(feature = "const_make_ascii", since = "CURRENT_RUSTC_VERSION")] #[inline] + #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn make_ascii_lowercase(&mut self) { *self = self.to_ascii_lowercase(); } diff --git a/library/core/src/slice/ascii.rs b/library/core/src/slice/ascii.rs index 8f8050fdc3a..8d8ac6a1d2a 100644 --- a/library/core/src/slice/ascii.rs +++ b/library/core/src/slice/ascii.rs @@ -67,8 +67,9 @@ impl [u8] { /// /// [`to_ascii_uppercase`]: #method.to_ascii_uppercase #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] - #[rustc_const_unstable(feature = "const_make_ascii", issue = "130698")] + #[rustc_const_stable(feature = "const_make_ascii", since = "CURRENT_RUSTC_VERSION")] #[inline] + #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn make_ascii_uppercase(&mut self) { // FIXME(const-hack): We would like to simply iterate using `for` loops but this isn't currently allowed in constant expressions. let mut i = 0; @@ -89,8 +90,9 @@ impl [u8] { /// /// [`to_ascii_lowercase`]: #method.to_ascii_lowercase #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] - #[rustc_const_unstable(feature = "const_make_ascii", issue = "130698")] + #[rustc_const_stable(feature = "const_make_ascii", since = "CURRENT_RUSTC_VERSION")] #[inline] + #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn make_ascii_lowercase(&mut self) { // FIXME(const-hack): We would like to simply iterate using `for` loops but this isn't currently allowed in constant expressions. let mut i = 0; diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index e93c52f2799..1d10015d75a 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -2475,8 +2475,9 @@ impl str { /// assert_eq!("GRüßE, JüRGEN ❤", s); /// ``` #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] - #[rustc_const_unstable(feature = "const_make_ascii", issue = "130698")] + #[rustc_const_stable(feature = "const_make_ascii", since = "CURRENT_RUSTC_VERSION")] #[inline] + #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn make_ascii_uppercase(&mut self) { // SAFETY: changing ASCII letters only does not invalidate UTF-8. let me = unsafe { self.as_bytes_mut() }; @@ -2503,8 +2504,9 @@ impl str { /// assert_eq!("grÜße, jÜrgen ❤", s); /// ``` #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] - #[rustc_const_unstable(feature = "const_make_ascii", issue = "130698")] + #[rustc_const_stable(feature = "const_make_ascii", since = "CURRENT_RUSTC_VERSION")] #[inline] + #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn make_ascii_lowercase(&mut self) { // SAFETY: changing ASCII letters only does not invalidate UTF-8. let me = unsafe { self.as_bytes_mut() }; From 1f501a7f09fc9a97d48585c2da68ae675b818b02 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 15 Oct 2024 07:51:50 +0200 Subject: [PATCH 309/357] update lockfile --- Cargo.lock | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b50b44bd077..701ffc0e7d1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -377,7 +377,7 @@ dependencies = [ "cargo_metadata", "directories", "rustc-build-sysroot", - "rustc_tools_util", + "rustc_tools_util 0.4.0", "rustc_version", "serde", "serde_json", @@ -552,7 +552,7 @@ dependencies = [ "parking_lot", "quote", "regex", - "rustc_tools_util", + "rustc_tools_util 0.3.0", "serde", "serde_json", "syn 2.0.79", @@ -4465,6 +4465,12 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ba09476327c4b70ccefb6180f046ef588c26a24cf5d269a9feba316eb4f029f" +[[package]] +name = "rustc_tools_util" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3316159ab19e19d1065ecc49278e87f767a9dae9fae80348d2b4d4fa4ae02d4d" + [[package]] name = "rustc_trait_selection" version = "0.0.0" From c09ed3e767a73d83673790f74c357432fa44d320 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20S=C3=A1nchez=20Mu=C3=B1oz?= Date: Mon, 14 Oct 2024 21:02:13 +0200 Subject: [PATCH 310/357] Make some float methods unstable `const fn` Some float methods are now `const fn` under the `const_float_methods` feature gate. In order to support `min`, `max`, `abs` and `copysign`, the implementation of some intrinsics had to be moved from Miri to rustc_const_eval. --- .../src/interpret/intrinsics.rs | 80 ++++ library/core/src/intrinsics.rs | 387 +++++++++++------- library/core/src/lib.rs | 1 + library/core/src/num/f128.rs | 42 +- library/core/src/num/f16.rs | 42 +- library/core/src/num/f32.rs | 33 +- library/core/src/num/f64.rs | 33 +- library/std/src/f128.rs | 9 +- library/std/src/f16.rs | 9 +- library/std/src/f32.rs | 9 +- library/std/src/f64.rs | 9 +- library/std/src/lib.rs | 1 + src/tools/miri/src/intrinsics/mod.rs | 39 -- tests/ui/consts/const-eval/float_methods.rs | 47 +++ 14 files changed, 498 insertions(+), 243 deletions(-) create mode 100644 tests/ui/consts/const-eval/float_methods.rs diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index 52780cc6a3a..540898ec645 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -4,6 +4,7 @@ use std::assert_matches::assert_matches; +use rustc_apfloat::ieee::{Double, Half, Quad, Single}; use rustc_hir::def_id::DefId; use rustc_middle::mir::{self, BinOp, ConstValue, NonDivergingIntrinsic}; use rustc_middle::ty::layout::{LayoutOf as _, TyAndLayout, ValidityRequirement}; @@ -438,6 +439,26 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { self.write_scalar(Scalar::from_target_usize(align.bytes(), self), dest)?; } + sym::minnumf16 => self.float_min_intrinsic::(args, dest)?, + sym::minnumf32 => self.float_min_intrinsic::(args, dest)?, + sym::minnumf64 => self.float_min_intrinsic::(args, dest)?, + sym::minnumf128 => self.float_min_intrinsic::(args, dest)?, + + sym::maxnumf16 => self.float_max_intrinsic::(args, dest)?, + sym::maxnumf32 => self.float_max_intrinsic::(args, dest)?, + sym::maxnumf64 => self.float_max_intrinsic::(args, dest)?, + sym::maxnumf128 => self.float_max_intrinsic::(args, dest)?, + + sym::copysignf16 => self.float_copysign_intrinsic::(args, dest)?, + sym::copysignf32 => self.float_copysign_intrinsic::(args, dest)?, + sym::copysignf64 => self.float_copysign_intrinsic::(args, dest)?, + sym::copysignf128 => self.float_copysign_intrinsic::(args, dest)?, + + sym::fabsf16 => self.float_abs_intrinsic::(args, dest)?, + sym::fabsf32 => self.float_abs_intrinsic::(args, dest)?, + sym::fabsf64 => self.float_abs_intrinsic::(args, dest)?, + sym::fabsf128 => self.float_abs_intrinsic::(args, dest)?, + // Unsupported intrinsic: skip the return_to_block below. _ => return interp_ok(false), } @@ -697,4 +718,63 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let rhs_bytes = get_bytes(self, rhs)?; interp_ok(Scalar::from_bool(lhs_bytes == rhs_bytes)) } + + fn float_min_intrinsic( + &mut self, + args: &[OpTy<'tcx, M::Provenance>], + dest: &MPlaceTy<'tcx, M::Provenance>, + ) -> InterpResult<'tcx, ()> + where + F: rustc_apfloat::Float + rustc_apfloat::FloatConvert + Into>, + { + let a: F = self.read_scalar(&args[0])?.to_float()?; + let b: F = self.read_scalar(&args[1])?.to_float()?; + let res = self.adjust_nan(a.min(b), &[a, b]); + self.write_scalar(res, dest)?; + interp_ok(()) + } + + fn float_max_intrinsic( + &mut self, + args: &[OpTy<'tcx, M::Provenance>], + dest: &MPlaceTy<'tcx, M::Provenance>, + ) -> InterpResult<'tcx, ()> + where + F: rustc_apfloat::Float + rustc_apfloat::FloatConvert + Into>, + { + let a: F = self.read_scalar(&args[0])?.to_float()?; + let b: F = self.read_scalar(&args[1])?.to_float()?; + let res = self.adjust_nan(a.max(b), &[a, b]); + self.write_scalar(res, dest)?; + interp_ok(()) + } + + fn float_copysign_intrinsic( + &mut self, + args: &[OpTy<'tcx, M::Provenance>], + dest: &MPlaceTy<'tcx, M::Provenance>, + ) -> InterpResult<'tcx, ()> + where + F: rustc_apfloat::Float + rustc_apfloat::FloatConvert + Into>, + { + let a: F = self.read_scalar(&args[0])?.to_float()?; + let b: F = self.read_scalar(&args[1])?.to_float()?; + // bitwise, no NaN adjustments + self.write_scalar(a.copy_sign(b), dest)?; + interp_ok(()) + } + + fn float_abs_intrinsic( + &mut self, + args: &[OpTy<'tcx, M::Provenance>], + dest: &MPlaceTy<'tcx, M::Provenance>, + ) -> InterpResult<'tcx, ()> + where + F: rustc_apfloat::Float + rustc_apfloat::FloatConvert + Into>, + { + let x: F = self.read_scalar(&args[0])?.to_float()?; + // bitwise, no NaN adjustments + self.write_scalar(x.abs(), dest)?; + interp_ok(()) + } } diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 061fba9a1f7..3ae729e76e1 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -1848,154 +1848,6 @@ extern "rust-intrinsic" { #[cfg(not(bootstrap))] pub fn fmuladdf128(a: f128, b: f128, c: f128) -> f128; - /// Returns the absolute value of an `f16`. - /// - /// The stabilized version of this intrinsic is - /// [`f16::abs`](../../std/primitive.f16.html#method.abs) - #[rustc_nounwind] - pub fn fabsf16(x: f16) -> f16; - /// Returns the absolute value of an `f32`. - /// - /// The stabilized version of this intrinsic is - /// [`f32::abs`](../../std/primitive.f32.html#method.abs) - #[rustc_nounwind] - pub fn fabsf32(x: f32) -> f32; - /// Returns the absolute value of an `f64`. - /// - /// The stabilized version of this intrinsic is - /// [`f64::abs`](../../std/primitive.f64.html#method.abs) - #[rustc_nounwind] - pub fn fabsf64(x: f64) -> f64; - /// Returns the absolute value of an `f128`. - /// - /// The stabilized version of this intrinsic is - /// [`f128::abs`](../../std/primitive.f128.html#method.abs) - #[rustc_nounwind] - pub fn fabsf128(x: f128) -> f128; - - /// Returns the minimum of two `f16` values. - /// - /// Note that, unlike most intrinsics, this is safe to call; - /// it does not require an `unsafe` block. - /// Therefore, implementations must not require the user to uphold - /// any safety invariants. - /// - /// The stabilized version of this intrinsic is - /// [`f16::min`] - #[rustc_safe_intrinsic] - #[rustc_nounwind] - pub fn minnumf16(x: f16, y: f16) -> f16; - /// Returns the minimum of two `f32` values. - /// - /// Note that, unlike most intrinsics, this is safe to call; - /// it does not require an `unsafe` block. - /// Therefore, implementations must not require the user to uphold - /// any safety invariants. - /// - /// The stabilized version of this intrinsic is - /// [`f32::min`] - #[rustc_safe_intrinsic] - #[rustc_nounwind] - pub fn minnumf32(x: f32, y: f32) -> f32; - /// Returns the minimum of two `f64` values. - /// - /// Note that, unlike most intrinsics, this is safe to call; - /// it does not require an `unsafe` block. - /// Therefore, implementations must not require the user to uphold - /// any safety invariants. - /// - /// The stabilized version of this intrinsic is - /// [`f64::min`] - #[rustc_safe_intrinsic] - #[rustc_nounwind] - pub fn minnumf64(x: f64, y: f64) -> f64; - /// Returns the minimum of two `f128` values. - /// - /// Note that, unlike most intrinsics, this is safe to call; - /// it does not require an `unsafe` block. - /// Therefore, implementations must not require the user to uphold - /// any safety invariants. - /// - /// The stabilized version of this intrinsic is - /// [`f128::min`] - #[rustc_safe_intrinsic] - #[rustc_nounwind] - pub fn minnumf128(x: f128, y: f128) -> f128; - - /// Returns the maximum of two `f16` values. - /// - /// Note that, unlike most intrinsics, this is safe to call; - /// it does not require an `unsafe` block. - /// Therefore, implementations must not require the user to uphold - /// any safety invariants. - /// - /// The stabilized version of this intrinsic is - /// [`f16::max`] - #[rustc_safe_intrinsic] - #[rustc_nounwind] - pub fn maxnumf16(x: f16, y: f16) -> f16; - /// Returns the maximum of two `f32` values. - /// - /// Note that, unlike most intrinsics, this is safe to call; - /// it does not require an `unsafe` block. - /// Therefore, implementations must not require the user to uphold - /// any safety invariants. - /// - /// The stabilized version of this intrinsic is - /// [`f32::max`] - #[rustc_safe_intrinsic] - #[rustc_nounwind] - pub fn maxnumf32(x: f32, y: f32) -> f32; - /// Returns the maximum of two `f64` values. - /// - /// Note that, unlike most intrinsics, this is safe to call; - /// it does not require an `unsafe` block. - /// Therefore, implementations must not require the user to uphold - /// any safety invariants. - /// - /// The stabilized version of this intrinsic is - /// [`f64::max`] - #[rustc_safe_intrinsic] - #[rustc_nounwind] - pub fn maxnumf64(x: f64, y: f64) -> f64; - /// Returns the maximum of two `f128` values. - /// - /// Note that, unlike most intrinsics, this is safe to call; - /// it does not require an `unsafe` block. - /// Therefore, implementations must not require the user to uphold - /// any safety invariants. - /// - /// The stabilized version of this intrinsic is - /// [`f128::max`] - #[rustc_safe_intrinsic] - #[rustc_nounwind] - pub fn maxnumf128(x: f128, y: f128) -> f128; - - /// Copies the sign from `y` to `x` for `f16` values. - /// - /// The stabilized version of this intrinsic is - /// [`f16::copysign`](../../std/primitive.f16.html#method.copysign) - #[rustc_nounwind] - pub fn copysignf16(x: f16, y: f16) -> f16; - /// Copies the sign from `y` to `x` for `f32` values. - /// - /// The stabilized version of this intrinsic is - /// [`f32::copysign`](../../std/primitive.f32.html#method.copysign) - #[rustc_nounwind] - pub fn copysignf32(x: f32, y: f32) -> f32; - /// Copies the sign from `y` to `x` for `f64` values. - /// - /// The stabilized version of this intrinsic is - /// [`f64::copysign`](../../std/primitive.f64.html#method.copysign) - #[rustc_nounwind] - pub fn copysignf64(x: f64, y: f64) -> f64; - /// Copies the sign from `y` to `x` for `f128` values. - /// - /// The stabilized version of this intrinsic is - /// [`f128::copysign`](../../std/primitive.f128.html#method.copysign) - #[rustc_nounwind] - pub fn copysignf128(x: f128, y: f128) -> f128; - /// Returns the largest integer less than or equal to an `f16`. /// /// The stabilized version of this intrinsic is @@ -3550,6 +3402,245 @@ pub const unsafe fn write_bytes(dst: *mut T, val: u8, count: usize) { } } +/// Returns the minimum of two `f16` values. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// The stabilized version of this intrinsic is +/// [`f16::min`] +#[rustc_nounwind] +// #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] +#[rustc_const_unstable(feature = "f16", issue = "116909")] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn minnumf16(_x: f16, _y: f16) -> f16 { + unimplemented!(); +} + +/// Returns the minimum of two `f32` values. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// The stabilized version of this intrinsic is +/// [`f32::min`] +#[rustc_nounwind] +#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn minnumf32(_x: f32, _y: f32) -> f32 { + unimplemented!(); +} + +/// Returns the minimum of two `f64` values. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// The stabilized version of this intrinsic is +/// [`f64::min`] +#[rustc_nounwind] +#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn minnumf64(_x: f64, _y: f64) -> f64 { + unimplemented!(); +} + +/// Returns the minimum of two `f128` values. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// The stabilized version of this intrinsic is +/// [`f128::min`] +#[rustc_nounwind] +// #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] +#[rustc_const_unstable(feature = "f128", issue = "116909")] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn minnumf128(_x: f128, _y: f128) -> f128 { + unimplemented!(); +} + +/// Returns the maximum of two `f16` values. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// The stabilized version of this intrinsic is +/// [`f16::max`] +#[rustc_nounwind] +// #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] +#[rustc_const_unstable(feature = "f16", issue = "116909")] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn maxnumf16(_x: f16, _y: f16) -> f16 { + unimplemented!(); +} + +/// Returns the maximum of two `f32` values. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// The stabilized version of this intrinsic is +/// [`f32::max`] +#[rustc_nounwind] +#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn maxnumf32(_x: f32, _y: f32) -> f32 { + unimplemented!(); +} + +/// Returns the maximum of two `f64` values. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// The stabilized version of this intrinsic is +/// [`f64::max`] +#[rustc_nounwind] +#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn maxnumf64(_x: f64, _y: f64) -> f64 { + unimplemented!(); +} + +/// Returns the maximum of two `f128` values. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// The stabilized version of this intrinsic is +/// [`f128::max`] +#[rustc_nounwind] +// #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] +#[rustc_const_unstable(feature = "f128", issue = "116909")] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn maxnumf128(_x: f128, _y: f128) -> f128 { + unimplemented!(); +} + +/// Returns the absolute value of an `f16`. +/// +/// The stabilized version of this intrinsic is +/// [`f16::abs`](../../std/primitive.f16.html#method.abs) +#[rustc_nounwind] +// #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] +#[rustc_const_unstable(feature = "f16", issue = "116909")] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn fabsf16(_x: f16) -> f16 { + unimplemented!(); +} + +/// Returns the absolute value of an `f32`. +/// +/// The stabilized version of this intrinsic is +/// [`f32::abs`](../../std/primitive.f32.html#method.abs) +#[rustc_nounwind] +#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn fabsf32(_x: f32) -> f32 { + unimplemented!(); +} + +/// Returns the absolute value of an `f64`. +/// +/// The stabilized version of this intrinsic is +/// [`f64::abs`](../../std/primitive.f64.html#method.abs) +#[rustc_nounwind] +#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn fabsf64(_x: f64) -> f64 { + unimplemented!(); +} + +/// Returns the absolute value of an `f128`. +/// +/// The stabilized version of this intrinsic is +/// [`f128::abs`](../../std/primitive.f128.html#method.abs) +#[rustc_nounwind] +// #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] +#[rustc_const_unstable(feature = "f128", issue = "116909")] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn fabsf128(_x: f128) -> f128 { + unimplemented!(); +} + +/// Copies the sign from `y` to `x` for `f16` values. +/// +/// The stabilized version of this intrinsic is +/// [`f16::copysign`](../../std/primitive.f16.html#method.copysign) +#[rustc_nounwind] +// #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] +#[rustc_const_unstable(feature = "f16", issue = "116909")] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn copysignf16(_x: f16, _y: f16) -> f16 { + unimplemented!(); +} + +/// Copies the sign from `y` to `x` for `f32` values. +/// +/// The stabilized version of this intrinsic is +/// [`f32::copysign`](../../std/primitive.f32.html#method.copysign) +#[rustc_nounwind] +#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn copysignf32(_x: f32, _y: f32) -> f32 { + unimplemented!(); +} +/// Copies the sign from `y` to `x` for `f64` values. +/// +/// The stabilized version of this intrinsic is +/// [`f64::copysign`](../../std/primitive.f64.html#method.copysign) +#[rustc_nounwind] +#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn copysignf64(_x: f64, _y: f64) -> f64 { + unimplemented!(); +} + +/// Copies the sign from `y` to `x` for `f128` values. +/// +/// The stabilized version of this intrinsic is +/// [`f128::copysign`](../../std/primitive.f128.html#method.copysign) +#[rustc_nounwind] +// #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] +#[rustc_const_unstable(feature = "f128", issue = "116909")] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn copysignf128(_x: f128, _y: f128) -> f128 { + unimplemented!(); +} + /// Inform Miri that a given pointer definitely has a certain alignment. #[cfg(miri)] pub(crate) const fn miri_promise_symbolic_alignment(ptr: *const (), align: usize) { diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 7f9a2152426..482e1f30b7e 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -120,6 +120,7 @@ #![feature(const_char_encode_utf16)] #![feature(const_eval_select)] #![feature(const_exact_div)] +#![feature(const_float_methods)] #![feature(const_fmt_arguments_new)] #![feature(const_hash)] #![feature(const_heap)] diff --git a/library/core/src/num/f128.rs b/library/core/src/num/f128.rs index 764df4fe4b0..5ab2ab50d7c 100644 --- a/library/core/src/num/f128.rs +++ b/library/core/src/num/f128.rs @@ -471,7 +471,7 @@ impl f128 { #[inline] #[must_use] #[unstable(feature = "f128", issue = "116909")] - pub fn is_sign_positive(self) -> bool { + pub const fn is_sign_positive(self) -> bool { !self.is_sign_negative() } @@ -497,7 +497,7 @@ impl f128 { #[inline] #[must_use] #[unstable(feature = "f128", issue = "116909")] - pub fn is_sign_negative(self) -> bool { + pub const fn is_sign_negative(self) -> bool { // IEEE754 says: isSignMinus(x) is true if and only if x has negative sign. isSignMinus // applies to zeros and NaNs as well. // SAFETY: This is just transmuting to get the sign bit, it's fine. @@ -538,7 +538,7 @@ impl f128 { #[inline] #[unstable(feature = "f128", issue = "116909")] // #[unstable(feature = "float_next_up_down", issue = "91399")] - pub fn next_up(self) -> Self { + pub const fn next_up(self) -> Self { // Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing // denormals to zero. This is in general unsound and unsupported, but here // we do our best to still produce the correct result on such targets. @@ -592,7 +592,7 @@ impl f128 { #[inline] #[unstable(feature = "f128", issue = "116909")] // #[unstable(feature = "float_next_up_down", issue = "91399")] - pub fn next_down(self) -> Self { + pub const fn next_down(self) -> Self { // Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing // denormals to zero. This is in general unsound and unsupported, but here // we do our best to still produce the correct result on such targets. @@ -627,8 +627,9 @@ impl f128 { /// ``` #[inline] #[unstable(feature = "f128", issue = "116909")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[must_use = "this returns the result of the operation, without modifying the original"] - pub fn recip(self) -> Self { + pub const fn recip(self) -> Self { 1.0 / self } @@ -647,8 +648,9 @@ impl f128 { /// ``` #[inline] #[unstable(feature = "f128", issue = "116909")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[must_use = "this returns the result of the operation, without modifying the original"] - pub fn to_degrees(self) -> Self { + pub const fn to_degrees(self) -> Self { // Use a literal for better precision. const PIS_IN_180: f128 = 57.2957795130823208767981548141051703324054724665643215491602_f128; self * PIS_IN_180 @@ -670,8 +672,9 @@ impl f128 { /// ``` #[inline] #[unstable(feature = "f128", issue = "116909")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[must_use = "this returns the result of the operation, without modifying the original"] - pub fn to_radians(self) -> f128 { + pub const fn to_radians(self) -> f128 { // Use a literal for better precision. const RADS_PER_DEG: f128 = 0.0174532925199432957692369076848861271344287188854172545609719_f128; @@ -698,8 +701,9 @@ impl f128 { /// ``` #[inline] #[unstable(feature = "f128", issue = "116909")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[must_use = "this returns the result of the comparison, without modifying either input"] - pub fn max(self, other: f128) -> f128 { + pub const fn max(self, other: f128) -> f128 { intrinsics::maxnumf128(self, other) } @@ -723,8 +727,9 @@ impl f128 { /// ``` #[inline] #[unstable(feature = "f128", issue = "116909")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[must_use = "this returns the result of the comparison, without modifying either input"] - pub fn min(self, other: f128) -> f128 { + pub const fn min(self, other: f128) -> f128 { intrinsics::minnumf128(self, other) } @@ -757,7 +762,7 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] // #[unstable(feature = "float_minimum_maximum", issue = "91079")] #[must_use = "this returns the result of the comparison, without modifying either input"] - pub fn maximum(self, other: f128) -> f128 { + pub const fn maximum(self, other: f128) -> f128 { if self > other { self } else if other > self { @@ -798,7 +803,7 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] // #[unstable(feature = "float_minimum_maximum", issue = "91079")] #[must_use = "this returns the result of the comparison, without modifying either input"] - pub fn minimum(self, other: f128) -> f128 { + pub const fn minimum(self, other: f128) -> f128 { if self < other { self } else if other < self { @@ -1269,9 +1274,20 @@ impl f128 { /// ``` #[inline] #[unstable(feature = "f128", issue = "116909")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[must_use = "method returns a new number and does not mutate the original value"] - pub fn clamp(mut self, min: f128, max: f128) -> f128 { - assert!(min <= max, "min > max, or either was NaN. min = {min:?}, max = {max:?}"); + pub const fn clamp(mut self, min: f128, max: f128) -> f128 { + #[inline] // inline to avoid LLVM crash + const fn assert_at_const(min: f128, max: f128) { + // Note that we cannot format in constant expressions. + assert!(min <= max, "min > max, or either was NaN"); + } + #[inline] // inline to avoid codegen regression + fn assert_at_rt(min: f128, max: f128) { + assert!(min <= max, "min > max, or either was NaN. min = {min:?}, max = {max:?}"); + } + // FIXME(const-hack): We would prefer to have streamlined panics when formatters become const-friendly. + intrinsics::const_eval_select((min, max), assert_at_const, assert_at_rt); if self < min { self = min; } diff --git a/library/core/src/num/f16.rs b/library/core/src/num/f16.rs index 897fc8c105d..60a88496696 100644 --- a/library/core/src/num/f16.rs +++ b/library/core/src/num/f16.rs @@ -459,7 +459,7 @@ impl f16 { #[inline] #[must_use] #[unstable(feature = "f16", issue = "116909")] - pub fn is_sign_positive(self) -> bool { + pub const fn is_sign_positive(self) -> bool { !self.is_sign_negative() } @@ -488,7 +488,7 @@ impl f16 { #[inline] #[must_use] #[unstable(feature = "f16", issue = "116909")] - pub fn is_sign_negative(self) -> bool { + pub const fn is_sign_negative(self) -> bool { // IEEE754 says: isSignMinus(x) is true if and only if x has negative sign. isSignMinus // applies to zeros and NaNs as well. // SAFETY: This is just transmuting to get the sign bit, it's fine. @@ -529,7 +529,7 @@ impl f16 { #[inline] #[unstable(feature = "f16", issue = "116909")] // #[unstable(feature = "float_next_up_down", issue = "91399")] - pub fn next_up(self) -> Self { + pub const fn next_up(self) -> Self { // Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing // denormals to zero. This is in general unsound and unsupported, but here // we do our best to still produce the correct result on such targets. @@ -583,7 +583,7 @@ impl f16 { #[inline] #[unstable(feature = "f16", issue = "116909")] // #[unstable(feature = "float_next_up_down", issue = "91399")] - pub fn next_down(self) -> Self { + pub const fn next_down(self) -> Self { // Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing // denormals to zero. This is in general unsound and unsupported, but here // we do our best to still produce the correct result on such targets. @@ -618,8 +618,9 @@ impl f16 { /// ``` #[inline] #[unstable(feature = "f16", issue = "116909")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[must_use = "this returns the result of the operation, without modifying the original"] - pub fn recip(self) -> Self { + pub const fn recip(self) -> Self { 1.0 / self } @@ -638,8 +639,9 @@ impl f16 { /// ``` #[inline] #[unstable(feature = "f16", issue = "116909")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[must_use = "this returns the result of the operation, without modifying the original"] - pub fn to_degrees(self) -> Self { + pub const fn to_degrees(self) -> Self { // Use a literal for better precision. const PIS_IN_180: f16 = 57.2957795130823208767981548141051703_f16; self * PIS_IN_180 @@ -661,8 +663,9 @@ impl f16 { /// ``` #[inline] #[unstable(feature = "f16", issue = "116909")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[must_use = "this returns the result of the operation, without modifying the original"] - pub fn to_radians(self) -> f16 { + pub const fn to_radians(self) -> f16 { // Use a literal for better precision. const RADS_PER_DEG: f16 = 0.017453292519943295769236907684886_f16; self * RADS_PER_DEG @@ -687,8 +690,9 @@ impl f16 { /// ``` #[inline] #[unstable(feature = "f16", issue = "116909")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[must_use = "this returns the result of the comparison, without modifying either input"] - pub fn max(self, other: f16) -> f16 { + pub const fn max(self, other: f16) -> f16 { intrinsics::maxnumf16(self, other) } @@ -711,8 +715,9 @@ impl f16 { /// ``` #[inline] #[unstable(feature = "f16", issue = "116909")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[must_use = "this returns the result of the comparison, without modifying either input"] - pub fn min(self, other: f16) -> f16 { + pub const fn min(self, other: f16) -> f16 { intrinsics::minnumf16(self, other) } @@ -744,7 +749,7 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] // #[unstable(feature = "float_minimum_maximum", issue = "91079")] #[must_use = "this returns the result of the comparison, without modifying either input"] - pub fn maximum(self, other: f16) -> f16 { + pub const fn maximum(self, other: f16) -> f16 { if self > other { self } else if other > self { @@ -784,7 +789,7 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] // #[unstable(feature = "float_minimum_maximum", issue = "91079")] #[must_use = "this returns the result of the comparison, without modifying either input"] - pub fn minimum(self, other: f16) -> f16 { + pub const fn minimum(self, other: f16) -> f16 { if self < other { self } else if other < self { @@ -1244,9 +1249,20 @@ impl f16 { /// ``` #[inline] #[unstable(feature = "f16", issue = "116909")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[must_use = "method returns a new number and does not mutate the original value"] - pub fn clamp(mut self, min: f16, max: f16) -> f16 { - assert!(min <= max, "min > max, or either was NaN. min = {min:?}, max = {max:?}"); + pub const fn clamp(mut self, min: f16, max: f16) -> f16 { + #[inline] // inline to avoid LLVM crash + const fn assert_at_const(min: f16, max: f16) { + // Note that we cannot format in constant expressions. + assert!(min <= max, "min > max, or either was NaN"); + } + #[inline] // inline to avoid codegen regression + fn assert_at_rt(min: f16, max: f16) { + assert!(min <= max, "min > max, or either was NaN. min = {min:?}, max = {max:?}"); + } + // FIXME(const-hack): We would prefer to have streamlined panics when formatters become const-friendly. + intrinsics::const_eval_select((min, max), assert_at_const, assert_at_rt); if self < min { self = min; } diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index a9a2595c25c..05f5a08ad0a 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -828,8 +828,9 @@ impl f32 { /// ``` #[must_use = "this returns the result of the operation, without modifying the original"] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[inline] - pub fn recip(self) -> f32 { + pub const fn recip(self) -> f32 { 1.0 / self } @@ -845,8 +846,9 @@ impl f32 { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[stable(feature = "f32_deg_rad_conversions", since = "1.7.0")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[inline] - pub fn to_degrees(self) -> f32 { + pub const fn to_degrees(self) -> f32 { // Use a constant for better precision. const PIS_IN_180: f32 = 57.2957795130823208767981548141051703_f32; self * PIS_IN_180 @@ -864,8 +866,9 @@ impl f32 { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[stable(feature = "f32_deg_rad_conversions", since = "1.7.0")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[inline] - pub fn to_radians(self) -> f32 { + pub const fn to_radians(self) -> f32 { const RADS_PER_DEG: f32 = consts::PI / 180.0; self * RADS_PER_DEG } @@ -885,8 +888,9 @@ impl f32 { /// ``` #[must_use = "this returns the result of the comparison, without modifying either input"] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[inline] - pub fn max(self, other: f32) -> f32 { + pub const fn max(self, other: f32) -> f32 { intrinsics::maxnumf32(self, other) } @@ -905,8 +909,9 @@ impl f32 { /// ``` #[must_use = "this returns the result of the comparison, without modifying either input"] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[inline] - pub fn min(self, other: f32) -> f32 { + pub const fn min(self, other: f32) -> f32 { intrinsics::minnumf32(self, other) } @@ -933,7 +938,7 @@ impl f32 { #[must_use = "this returns the result of the comparison, without modifying either input"] #[unstable(feature = "float_minimum_maximum", issue = "91079")] #[inline] - pub fn maximum(self, other: f32) -> f32 { + pub const fn maximum(self, other: f32) -> f32 { if self > other { self } else if other > self { @@ -968,7 +973,7 @@ impl f32 { #[must_use = "this returns the result of the comparison, without modifying either input"] #[unstable(feature = "float_minimum_maximum", issue = "91079")] #[inline] - pub fn minimum(self, other: f32) -> f32 { + pub const fn minimum(self, other: f32) -> f32 { if self < other { self } else if other < self { @@ -1401,9 +1406,19 @@ impl f32 { /// ``` #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "clamp", since = "1.50.0")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[inline] - pub fn clamp(mut self, min: f32, max: f32) -> f32 { - assert!(min <= max, "min > max, or either was NaN. min = {min:?}, max = {max:?}"); + pub const fn clamp(mut self, min: f32, max: f32) -> f32 { + const fn assert_at_const(min: f32, max: f32) { + // Note that we cannot format in constant expressions. + assert!(min <= max, "min > max, or either was NaN"); + } + #[inline] // inline to avoid codegen regression + fn assert_at_rt(min: f32, max: f32) { + assert!(min <= max, "min > max, or either was NaN. min = {min:?}, max = {max:?}"); + } + // FIXME(const-hack): We would prefer to have streamlined panics when formatters become const-friendly. + intrinsics::const_eval_select((min, max), assert_at_const, assert_at_rt); if self < min { self = min; } diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index aa7a54ca650..89c6726d985 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -845,8 +845,9 @@ impl f64 { /// ``` #[must_use = "this returns the result of the operation, without modifying the original"] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[inline] - pub fn recip(self) -> f64 { + pub const fn recip(self) -> f64 { 1.0 / self } @@ -862,8 +863,9 @@ impl f64 { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[inline] - pub fn to_degrees(self) -> f64 { + pub const fn to_degrees(self) -> f64 { // The division here is correctly rounded with respect to the true // value of 180/π. (This differs from f32, where a constant must be // used to ensure a correctly rounded result.) @@ -882,8 +884,9 @@ impl f64 { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[inline] - pub fn to_radians(self) -> f64 { + pub const fn to_radians(self) -> f64 { const RADS_PER_DEG: f64 = consts::PI / 180.0; self * RADS_PER_DEG } @@ -903,8 +906,9 @@ impl f64 { /// ``` #[must_use = "this returns the result of the comparison, without modifying either input"] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[inline] - pub fn max(self, other: f64) -> f64 { + pub const fn max(self, other: f64) -> f64 { intrinsics::maxnumf64(self, other) } @@ -923,8 +927,9 @@ impl f64 { /// ``` #[must_use = "this returns the result of the comparison, without modifying either input"] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[inline] - pub fn min(self, other: f64) -> f64 { + pub const fn min(self, other: f64) -> f64 { intrinsics::minnumf64(self, other) } @@ -951,7 +956,7 @@ impl f64 { #[must_use = "this returns the result of the comparison, without modifying either input"] #[unstable(feature = "float_minimum_maximum", issue = "91079")] #[inline] - pub fn maximum(self, other: f64) -> f64 { + pub const fn maximum(self, other: f64) -> f64 { if self > other { self } else if other > self { @@ -986,7 +991,7 @@ impl f64 { #[must_use = "this returns the result of the comparison, without modifying either input"] #[unstable(feature = "float_minimum_maximum", issue = "91079")] #[inline] - pub fn minimum(self, other: f64) -> f64 { + pub const fn minimum(self, other: f64) -> f64 { if self < other { self } else if other < self { @@ -1401,9 +1406,19 @@ impl f64 { /// ``` #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "clamp", since = "1.50.0")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[inline] - pub fn clamp(mut self, min: f64, max: f64) -> f64 { - assert!(min <= max, "min > max, or either was NaN. min = {min:?}, max = {max:?}"); + pub const fn clamp(mut self, min: f64, max: f64) -> f64 { + const fn assert_at_const(min: f64, max: f64) { + // Note that we cannot format in constant expressions. + assert!(min <= max, "min > max, or either was NaN"); + } + #[inline] // inline to avoid codegen regression + fn assert_at_rt(min: f64, max: f64) { + assert!(min <= max, "min > max, or either was NaN. min = {min:?}, max = {max:?}"); + } + // FIXME(const-hack): We would prefer to have streamlined panics when formatters become const-friendly. + intrinsics::const_eval_select((min, max), assert_at_const, assert_at_rt); if self < min { self = min; } diff --git a/library/std/src/f128.rs b/library/std/src/f128.rs index b436fe9929c..229f979b5b1 100644 --- a/library/std/src/f128.rs +++ b/library/std/src/f128.rs @@ -210,8 +210,9 @@ impl f128 { #[inline] #[rustc_allow_incoherent_impl] #[unstable(feature = "f128", issue = "116909")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[must_use = "method returns a new number and does not mutate the original value"] - pub fn abs(self) -> Self { + pub const fn abs(self) -> Self { // FIXME(f16_f128): replace with `intrinsics::fabsf128` when available // We don't do this now because LLVM has lowering bugs for f128 math. Self::from_bits(self.to_bits() & !(1 << 127)) @@ -240,8 +241,9 @@ impl f128 { #[inline] #[rustc_allow_incoherent_impl] #[unstable(feature = "f128", issue = "116909")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[must_use = "method returns a new number and does not mutate the original value"] - pub fn signum(self) -> f128 { + pub const fn signum(self) -> f128 { if self.is_nan() { Self::NAN } else { 1.0_f128.copysign(self) } } @@ -278,8 +280,9 @@ impl f128 { #[inline] #[rustc_allow_incoherent_impl] #[unstable(feature = "f128", issue = "116909")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[must_use = "method returns a new number and does not mutate the original value"] - pub fn copysign(self, sign: f128) -> f128 { + pub const fn copysign(self, sign: f128) -> f128 { unsafe { intrinsics::copysignf128(self, sign) } } diff --git a/library/std/src/f16.rs b/library/std/src/f16.rs index b2cd5fae9d0..bed21cda1cd 100644 --- a/library/std/src/f16.rs +++ b/library/std/src/f16.rs @@ -210,8 +210,9 @@ impl f16 { #[inline] #[rustc_allow_incoherent_impl] #[unstable(feature = "f16", issue = "116909")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[must_use = "method returns a new number and does not mutate the original value"] - pub fn abs(self) -> Self { + pub const fn abs(self) -> Self { // FIXME(f16_f128): replace with `intrinsics::fabsf16` when available Self::from_bits(self.to_bits() & !(1 << 15)) } @@ -239,8 +240,9 @@ impl f16 { #[inline] #[rustc_allow_incoherent_impl] #[unstable(feature = "f16", issue = "116909")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[must_use = "method returns a new number and does not mutate the original value"] - pub fn signum(self) -> f16 { + pub const fn signum(self) -> f16 { if self.is_nan() { Self::NAN } else { 1.0_f16.copysign(self) } } @@ -277,8 +279,9 @@ impl f16 { #[inline] #[rustc_allow_incoherent_impl] #[unstable(feature = "f16", issue = "116909")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[must_use = "method returns a new number and does not mutate the original value"] - pub fn copysign(self, sign: f16) -> f16 { + pub const fn copysign(self, sign: f16) -> f16 { unsafe { intrinsics::copysignf16(self, sign) } } diff --git a/library/std/src/f32.rs b/library/std/src/f32.rs index fa0b3ef6484..30cf4e1f756 100644 --- a/library/std/src/f32.rs +++ b/library/std/src/f32.rs @@ -194,8 +194,9 @@ impl f32 { #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[inline] - pub fn abs(self) -> f32 { + pub const fn abs(self) -> f32 { unsafe { intrinsics::fabsf32(self) } } @@ -218,8 +219,9 @@ impl f32 { #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[inline] - pub fn signum(self) -> f32 { + pub const fn signum(self) -> f32 { if self.is_nan() { Self::NAN } else { 1.0_f32.copysign(self) } } @@ -253,7 +255,8 @@ impl f32 { #[must_use = "method returns a new number and does not mutate the original value"] #[inline] #[stable(feature = "copysign", since = "1.35.0")] - pub fn copysign(self, sign: f32) -> f32 { + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] + pub const fn copysign(self, sign: f32) -> f32 { unsafe { intrinsics::copysignf32(self, sign) } } diff --git a/library/std/src/f64.rs b/library/std/src/f64.rs index 9fa43a6742e..51d5476b372 100644 --- a/library/std/src/f64.rs +++ b/library/std/src/f64.rs @@ -194,8 +194,9 @@ impl f64 { #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[inline] - pub fn abs(self) -> f64 { + pub const fn abs(self) -> f64 { unsafe { intrinsics::fabsf64(self) } } @@ -218,8 +219,9 @@ impl f64 { #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[inline] - pub fn signum(self) -> f64 { + pub const fn signum(self) -> f64 { if self.is_nan() { Self::NAN } else { 1.0_f64.copysign(self) } } @@ -252,8 +254,9 @@ impl f64 { #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "copysign", since = "1.35.0")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[inline] - pub fn copysign(self, sign: f64) -> f64 { + pub const fn copysign(self, sign: f64) -> f64 { unsafe { intrinsics::copysignf64(self, sign) } } diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 65a9aa66c7c..990d83513cf 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -288,6 +288,7 @@ #![feature(cfg_target_thread_local)] #![feature(cfi_encoding)] #![feature(concat_idents)] +#![feature(const_float_methods)] #![feature(decl_macro)] #![feature(deprecated_suggestion)] #![feature(doc_cfg)] diff --git a/src/tools/miri/src/intrinsics/mod.rs b/src/tools/miri/src/intrinsics/mod.rs index 9f772cfa982..e0d27f21dae 100644 --- a/src/tools/miri/src/intrinsics/mod.rs +++ b/src/tools/miri/src/intrinsics/mod.rs @@ -145,20 +145,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(Scalar::from_bool(branch), dest)?; } - // Floating-point operations - "fabsf32" => { - let [f] = check_arg_count(args)?; - let f = this.read_scalar(f)?.to_f32()?; - // This is a "bitwise" operation, so there's no NaN non-determinism. - this.write_scalar(Scalar::from_f32(f.abs()), dest)?; - } - "fabsf64" => { - let [f] = check_arg_count(args)?; - let f = this.read_scalar(f)?.to_f64()?; - // This is a "bitwise" operation, so there's no NaN non-determinism. - this.write_scalar(Scalar::from_f64(f.abs()), dest)?; - } - "floorf32" | "ceilf32" | "truncf32" | "roundf32" | "rintf32" => { let [f] = check_arg_count(args)?; let f = this.read_scalar(f)?.to_f32()?; @@ -249,31 +235,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(res, dest)?; } - "minnumf32" | "maxnumf32" | "copysignf32" => { - let [a, b] = check_arg_count(args)?; - let a = this.read_scalar(a)?.to_f32()?; - let b = this.read_scalar(b)?.to_f32()?; - let res = match intrinsic_name { - "minnumf32" => this.adjust_nan(a.min(b), &[a, b]), - "maxnumf32" => this.adjust_nan(a.max(b), &[a, b]), - "copysignf32" => a.copy_sign(b), // bitwise, no NaN adjustments - _ => bug!(), - }; - this.write_scalar(Scalar::from_f32(res), dest)?; - } - "minnumf64" | "maxnumf64" | "copysignf64" => { - let [a, b] = check_arg_count(args)?; - let a = this.read_scalar(a)?.to_f64()?; - let b = this.read_scalar(b)?.to_f64()?; - let res = match intrinsic_name { - "minnumf64" => this.adjust_nan(a.min(b), &[a, b]), - "maxnumf64" => this.adjust_nan(a.max(b), &[a, b]), - "copysignf64" => a.copy_sign(b), // bitwise, no NaN adjustments - _ => bug!(), - }; - this.write_scalar(Scalar::from_f64(res), dest)?; - } - "fmaf32" => { let [a, b, c] = check_arg_count(args)?; let a = this.read_scalar(a)?.to_f32()?; diff --git a/tests/ui/consts/const-eval/float_methods.rs b/tests/ui/consts/const-eval/float_methods.rs new file mode 100644 index 00000000000..49c31f68c5f --- /dev/null +++ b/tests/ui/consts/const-eval/float_methods.rs @@ -0,0 +1,47 @@ +//@ run-pass +//! Tests the float intrinsics: min, max, abs, copysign + +#![feature(const_float_methods)] +#![feature(f16, f128)] + +const F16_MIN: f16 = 1.0_f16.min(0.5_f16); +const F16_MAX: f16 = 1.0_f16.max(0.5_f16); +const F16_ABS: f16 = (-1.0_f16).abs(); +const F16_COPYSIGN: f16 = 1.0_f16.copysign(-2.0_f16); + +const F32_MIN: f32 = 1.0_f32.min(0.5_f32); +const F32_MAX: f32 = 1.0_f32.max(0.5_f32); +const F32_ABS: f32 = (-1.0_f32).abs(); +const F32_COPYSIGN: f32 = 1.0_f32.copysign(-2.0_f32); + +const F64_MIN: f64 = 1.0_f64.min(0.5_f64); +const F64_MAX: f64 = 1.0_f64.max(0.5_f64); +const F64_ABS: f64 = (-1.0_f64).abs(); +const F64_COPYSIGN: f64 = 1.0_f64.copysign(-2.0_f64); + +const F128_MIN: f128 = 1.0_f128.min(0.5_f128); +const F128_MAX: f128 = 1.0_f128.max(0.5_f128); +const F128_ABS: f128 = (-1.0_f128).abs(); +const F128_COPYSIGN: f128 = 1.0_f128.copysign(-2.0_f128); + +fn main() { + assert_eq!(F16_MIN, 0.5); + assert_eq!(F16_MAX, 1.0); + assert_eq!(F16_ABS, 1.0); + assert_eq!(F16_COPYSIGN, -1.0); + + assert_eq!(F32_MIN, 0.5); + assert_eq!(F32_MAX, 1.0); + assert_eq!(F32_ABS, 1.0); + assert_eq!(F32_COPYSIGN, -1.0); + + assert_eq!(F64_MIN, 0.5); + assert_eq!(F64_MAX, 1.0); + assert_eq!(F64_ABS, 1.0); + assert_eq!(F64_COPYSIGN, -1.0); + + assert_eq!(F128_MIN, 0.5); + assert_eq!(F128_MAX, 1.0); + assert_eq!(F128_ABS, 1.0); + assert_eq!(F128_COPYSIGN, -1.0); +} From 918dc38733985770d1cdcea76169340c620c1f32 Mon Sep 17 00:00:00 2001 From: zlfn Date: Tue, 15 Oct 2024 18:23:39 +0900 Subject: [PATCH 311/357] Combine impl_int and impl_uint Two macros are exactly the same. --- library/core/src/fmt/num.rs | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/library/core/src/fmt/num.rs b/library/core/src/fmt/num.rs index aecd725eca5..cc94c392de5 100644 --- a/library/core/src/fmt/num.rs +++ b/library/core/src/fmt/num.rs @@ -31,22 +31,11 @@ macro_rules! impl_int { })* ) } -macro_rules! impl_uint { - ($($t:ident)*) => ( - $(impl DisplayInt for $t { - fn zero() -> Self { 0 } - fn from_u8(u: u8) -> Self { u as Self } - fn to_u8(&self) -> u8 { *self as u8 } - #[cfg(not(any(target_pointer_width = "64", target_arch = "wasm32")))] - fn to_u32(&self) -> u32 { *self as u32 } - fn to_u64(&self) -> u64 { *self as u64 } - fn to_u128(&self) -> u128 { *self as u128 } - })* - ) -} -impl_int! { i8 i16 i32 i64 i128 isize } -impl_uint! { u8 u16 u32 u64 u128 usize } +impl_int! { + i8 i16 i32 i64 i128 isize + u8 u16 u32 u64 u128 usize +} /// A type that represents a specific radix /// From 0637517da6802bcdc8df9a73a75edb8c41033f11 Mon Sep 17 00:00:00 2001 From: zlfn Date: Tue, 15 Oct 2024 18:32:21 +0900 Subject: [PATCH 312/357] Rename debug! macro to impl_Debug! --- library/core/src/fmt/num.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/library/core/src/fmt/num.rs b/library/core/src/fmt/num.rs index cc94c392de5..0f33d730a68 100644 --- a/library/core/src/fmt/num.rs +++ b/library/core/src/fmt/num.rs @@ -167,7 +167,8 @@ integer! { i16, u16 } integer! { i32, u32 } integer! { i64, u64 } integer! { i128, u128 } -macro_rules! debug { + +macro_rules! impl_Debug { ($($T:ident)*) => {$( #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Debug for $T { @@ -184,10 +185,6 @@ macro_rules! debug { } )*}; } -debug! { - i8 i16 i32 i64 i128 isize - u8 u16 u32 u64 u128 usize -} // 2 digit decimal look up table static DEC_DIGITS_LUT: &[u8; 200] = b"0001020304050607080910111213141516171819\ @@ -510,6 +507,11 @@ macro_rules! impl_Exp { }; } +impl_Debug! { + i8 i16 i32 i64 i128 isize + u8 u16 u32 u64 u128 usize +} + // Include wasm32 in here since it doesn't reflect the native pointer size, and // often cares strongly about getting a smaller code size. #[cfg(any(target_pointer_width = "64", target_arch = "wasm32"))] From 1a9d2d82a5ee24d05dac2287b87ffd96f77d6d77 Mon Sep 17 00:00:00 2001 From: lcnr Date: Sat, 21 Sep 2024 07:02:51 +0000 Subject: [PATCH 313/357] stabilize `-Znext-solver=coherence` --- compiler/rustc_ast_passes/src/feature_gate.rs | 2 +- compiler/rustc_interface/src/tests.rs | 2 +- compiler/rustc_middle/src/ty/context.rs | 4 +- compiler/rustc_session/src/config.rs | 5 ++ compiler/rustc_session/src/options.rs | 31 +++---- .../src/traits/engine.rs | 4 +- .../associated-types-coherence-failure.stderr | 8 +- .../opaque_type_candidate_selection.rs | 30 ------- ...e-negative-outlives-lifetimes.stock.stderr | 2 + ...s-lifetimes.with_negative_coherence.stderr | 2 + ...overlap-negate-not-use-feature-gate.stderr | 2 + ...unnormalizable-projection-0.classic.stderr | 1 - ...unnormalizable-projection-1.classic.stderr | 2 +- ...oherence-check-placeholder-outlives.stderr | 2 + ...oherence-considering-regions.any_lt.stderr | 2 + ...constraints-on-unification.explicit.stderr | 1 + .../normalize-for-errors.current.stderr | 5 +- tests/ui/coherence/normalize-for-errors.rs | 6 +- .../ui/coherence/normalize-for-errors.stderr | 15 ++++ .../occurs-check/associated-type.old.stderr | 8 +- .../occurs-check/opaques.current.stderr | 12 +++ .../occurs-check/opaques.next.stderr | 4 +- tests/ui/coherence/occurs-check/opaques.rs | 7 +- ...reporting-if-references-err.current.stderr | 17 +--- .../skip-reporting-if-references-err.rs | 6 -- .../skip-reporting-if-references-err.stderr | 14 ++++ .../super-trait-knowable-1.current.stderr | 13 --- .../super-traits/super-trait-knowable-1.rs | 6 +- .../super-trait-knowable-3.current.stderr | 13 --- .../super-traits/super-trait-knowable-3.rs | 6 +- .../unevaluated-const-ice-119731.rs | 1 + .../unevaluated-const-ice-119731.stderr | 23 +++-- ...nown-alias-defkind-anonconst-ice-116710.rs | 1 - ...-alias-defkind-anonconst-ice-116710.stderr | 14 +--- tests/ui/error-codes/e0119/issue-23563.stderr | 2 +- ...eature-gate-with_negative_coherence.stderr | 2 + .../structually-relate-aliases.rs | 3 +- .../structually-relate-aliases.stderr | 33 +++----- .../auto-trait-coherence.old.stderr | 4 +- tests/ui/impl-trait/auto-trait-coherence.rs | 6 +- .../ui/impl-trait/auto-trait-coherence.stderr | 12 +++ .../impl-trait/coherence-treats-tait-ambig.rs | 2 +- .../coherence-treats-tait-ambig.stderr | 2 +- tests/ui/impl-trait/negative-reasoning.rs | 2 +- tests/ui/impl-trait/negative-reasoning.stderr | 6 +- tests/ui/impl-unused-tps.rs | 46 +++++----- tests/ui/impl-unused-tps.stderr | 84 ++++++++++++------- tests/ui/issues/issue-48728.rs | 8 +- .../defaultimpl/specialization-no-default.rs | 3 +- ...efault-items-drop-coherence.current.stderr | 12 +++ ...n-default-items-drop-coherence.next.stderr | 2 +- ...ialization-default-items-drop-coherence.rs | 8 +- ...lization-overlap-projection.current.stderr | 22 ++++- ...cialization-overlap-projection.next.stderr | 6 +- .../specialization-overlap-projection.rs | 13 +-- .../specialization-overlap-projection.stderr | 30 +++++++ tests/ui/traits/alias/issue-83613.rs | 2 +- tests/ui/traits/alias/issue-83613.stderr | 4 +- tests/ui/traits/issue-105231.rs | 3 +- tests/ui/traits/issue-105231.stderr | 22 ++--- .../next-solver/coherence/issue-102048.rs | 10 +-- .../next-solver/coherence/issue-102048.stderr | 16 ++++ .../cycle-via-builtin-auto-trait-impl.rs | 2 +- .../cycle-via-builtin-auto-trait-impl.stderr | 26 ++---- .../impl_trait_for_same_tait.stderr | 2 - .../implied_lifetime_wf_check.error.stderr | 4 +- .../ui/type-alias-impl-trait/issue-104817.rs | 2 +- .../issue-104817.stock.stderr | 4 +- 68 files changed, 347 insertions(+), 329 deletions(-) delete mode 100644 tests/ui/auto-traits/opaque_type_candidate_selection.rs create mode 100644 tests/ui/coherence/normalize-for-errors.stderr create mode 100644 tests/ui/coherence/occurs-check/opaques.current.stderr create mode 100644 tests/ui/coherence/skip-reporting-if-references-err.stderr delete mode 100644 tests/ui/coherence/super-traits/super-trait-knowable-1.current.stderr delete mode 100644 tests/ui/coherence/super-traits/super-trait-knowable-3.current.stderr create mode 100644 tests/ui/impl-trait/auto-trait-coherence.stderr create mode 100644 tests/ui/specialization/specialization-default-items-drop-coherence.current.stderr create mode 100644 tests/ui/specialization/specialization-overlap-projection.stderr create mode 100644 tests/ui/traits/next-solver/coherence/issue-102048.stderr diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 05850ca3260..f2773dcdc60 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -666,7 +666,7 @@ fn check_incompatible_features(sess: &Session, features: &Features) { } fn check_new_solver_banned_features(sess: &Session, features: &Features) { - if !sess.opts.unstable_opts.next_solver.is_some_and(|n| n.globally) { + if !sess.opts.unstable_opts.next_solver.globally { return; } diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 536ce154cd0..3189620e969 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -810,7 +810,7 @@ fn test_unstable_options_tracking_hash() { tracked!(mir_opt_level, Some(4)); tracked!(move_size_limit, Some(4096)); tracked!(mutable_noalias, false); - tracked!(next_solver, Some(NextSolverConfig { coherence: true, globally: false })); + tracked!(next_solver, NextSolverConfig { coherence: true, globally: true }); tracked!(no_generate_arange_section, true); tracked!(no_jump_tables, true); tracked!(no_link, true); diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 1bdcae4dfb4..c2a55060490 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -3128,11 +3128,11 @@ impl<'tcx> TyCtxt<'tcx> { } pub fn next_trait_solver_globally(self) -> bool { - self.sess.opts.unstable_opts.next_solver.map_or(false, |c| c.globally) + self.sess.opts.unstable_opts.next_solver.globally } pub fn next_trait_solver_in_coherence(self) -> bool { - self.sess.opts.unstable_opts.next_solver.map_or(false, |c| c.coherence) + self.sess.opts.unstable_opts.next_solver.coherence } pub fn is_impl_trait_in_trait(self, def_id: DefId) -> bool { diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index d2c03e588ff..d733e32f209 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -842,6 +842,11 @@ pub struct NextSolverConfig { /// This is only `true` if `coherence` is also enabled. pub globally: bool, } +impl Default for NextSolverConfig { + fn default() -> Self { + NextSolverConfig { coherence: true, globally: false } + } +} #[derive(Clone)] pub enum Input { diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index d63276db493..f9964b59a94 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -403,7 +403,7 @@ mod desc { pub(crate) const parse_unpretty: &str = "`string` or `string=string`"; pub(crate) const parse_treat_err_as_bug: &str = "either no value or a non-negative number"; pub(crate) const parse_next_solver_config: &str = - "a comma separated list of solver configurations: `globally` (default), and `coherence`"; + "either `globally` (when used without an argument), `coherence` (default) or `no`"; pub(crate) const parse_lto: &str = "either a boolean (`yes`, `no`, `on`, `off`, etc), `thin`, `fat`, or omitted"; pub(crate) const parse_linker_plugin_lto: &str = @@ -1123,27 +1123,16 @@ mod parse { } } - pub(crate) fn parse_next_solver_config( - slot: &mut Option, - v: Option<&str>, - ) -> bool { + pub(crate) fn parse_next_solver_config(slot: &mut NextSolverConfig, v: Option<&str>) -> bool { if let Some(config) = v { - let mut coherence = false; - let mut globally = true; - for c in config.split(',') { - match c { - "globally" => globally = true, - "coherence" => { - globally = false; - coherence = true; - } - _ => return false, - } - } - - *slot = Some(NextSolverConfig { coherence: coherence || globally, globally }); + *slot = match config { + "no" => NextSolverConfig { coherence: false, globally: false }, + "coherence" => NextSolverConfig { coherence: true, globally: false }, + "globally" => NextSolverConfig { coherence: true, globally: true }, + _ => return false, + }; } else { - *slot = Some(NextSolverConfig { coherence: true, globally: true }); + *slot = NextSolverConfig { coherence: true, globally: true }; } true @@ -1914,7 +1903,7 @@ options! { "the size at which the `large_assignments` lint starts to be emitted"), mutable_noalias: bool = (true, parse_bool, [TRACKED], "emit noalias metadata for mutable references (default: yes)"), - next_solver: Option = (None, parse_next_solver_config, [TRACKED], + next_solver: NextSolverConfig = (NextSolverConfig::default(), parse_next_solver_config, [TRACKED], "enable and configure the next generation trait solver used by rustc"), nll_facts: bool = (false, parse_bool, [UNTRACKED], "dump facts from NLL analysis into side files (default: no)"), diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs index d562692c1a8..7df9b6feb96 100644 --- a/compiler/rustc_trait_selection/src/traits/engine.rs +++ b/compiler/rustc_trait_selection/src/traits/engine.rs @@ -36,10 +36,8 @@ where if infcx.next_trait_solver() { Box::new(NextFulfillmentCtxt::new(infcx)) } else { - let new_solver_globally = - infcx.tcx.sess.opts.unstable_opts.next_solver.map_or(false, |c| c.globally); assert!( - !new_solver_globally, + !infcx.tcx.next_trait_solver_globally(), "using old solver even though new solver is enabled globally" ); Box::new(FulfillmentContext::new(infcx)) diff --git a/tests/ui/associated-types/associated-types-coherence-failure.stderr b/tests/ui/associated-types/associated-types-coherence-failure.stderr index 211613b3714..25c22e5f82a 100644 --- a/tests/ui/associated-types/associated-types-coherence-failure.stderr +++ b/tests/ui/associated-types/associated-types-coherence-failure.stderr @@ -1,20 +1,20 @@ -error[E0119]: conflicting implementations of trait `IntoCow<'_, _>` for type `Cow<'_, _>` +error[E0119]: conflicting implementations of trait `IntoCow<'_, _>` for type `<_ as ToOwned>::Owned` --> $DIR/associated-types-coherence-failure.rs:21:1 | LL | impl<'a, B: ?Sized> IntoCow<'a, B> for ::Owned where B: ToOwned { | ----------------------------------------------------------------------------- first implementation here ... LL | impl<'a, B: ?Sized> IntoCow<'a, B> for Cow<'a, B> where B: ToOwned { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Cow<'_, _>` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `<_ as ToOwned>::Owned` -error[E0119]: conflicting implementations of trait `IntoCow<'_, _>` for type `&_` +error[E0119]: conflicting implementations of trait `IntoCow<'_, _>` for type `<_ as ToOwned>::Owned` --> $DIR/associated-types-coherence-failure.rs:28:1 | LL | impl<'a, B: ?Sized> IntoCow<'a, B> for ::Owned where B: ToOwned { | ----------------------------------------------------------------------------- first implementation here ... LL | impl<'a, B: ?Sized> IntoCow<'a, B> for &'a B where B: ToOwned { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `&_` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `<_ as ToOwned>::Owned` error: aborting due to 2 previous errors diff --git a/tests/ui/auto-traits/opaque_type_candidate_selection.rs b/tests/ui/auto-traits/opaque_type_candidate_selection.rs deleted file mode 100644 index d6973b76a6e..00000000000 --- a/tests/ui/auto-traits/opaque_type_candidate_selection.rs +++ /dev/null @@ -1,30 +0,0 @@ -//! used to ICE: #119272 - -//@ check-pass - -#![feature(type_alias_impl_trait)] -mod defining_scope { - use super::*; - pub type Alias = impl Sized; - - pub fn cast(x: Container, T>) -> Container { - x - } -} - -struct Container, U> { - x: >::Assoc, -} - -trait Trait { - type Assoc; -} - -impl Trait for T { - type Assoc = Box; -} -impl Trait for defining_scope::Alias { - type Assoc = usize; -} - -fn main() {} diff --git a/tests/ui/coherence/coherence-negative-outlives-lifetimes.stock.stderr b/tests/ui/coherence/coherence-negative-outlives-lifetimes.stock.stderr index dbb22d8937d..1d28bb46812 100644 --- a/tests/ui/coherence/coherence-negative-outlives-lifetimes.stock.stderr +++ b/tests/ui/coherence/coherence-negative-outlives-lifetimes.stock.stderr @@ -5,6 +5,8 @@ LL | impl<'a, T: MyPredicate<'a>> MyTrait<'a> for T {} | ---------------------------------------------- first implementation here LL | impl<'a, T> MyTrait<'a> for &'a T {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `&_` + | + = note: downstream crates may implement trait `MyPredicate<'_>` for type `&_` error: aborting due to 1 previous error diff --git a/tests/ui/coherence/coherence-negative-outlives-lifetimes.with_negative_coherence.stderr b/tests/ui/coherence/coherence-negative-outlives-lifetimes.with_negative_coherence.stderr index dbb22d8937d..1d28bb46812 100644 --- a/tests/ui/coherence/coherence-negative-outlives-lifetimes.with_negative_coherence.stderr +++ b/tests/ui/coherence/coherence-negative-outlives-lifetimes.with_negative_coherence.stderr @@ -5,6 +5,8 @@ LL | impl<'a, T: MyPredicate<'a>> MyTrait<'a> for T {} | ---------------------------------------------- first implementation here LL | impl<'a, T> MyTrait<'a> for &'a T {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `&_` + | + = note: downstream crates may implement trait `MyPredicate<'_>` for type `&_` error: aborting due to 1 previous error diff --git a/tests/ui/coherence/coherence-overlap-negate-not-use-feature-gate.stderr b/tests/ui/coherence/coherence-overlap-negate-not-use-feature-gate.stderr index 21c82eedd5d..c5bb695eb18 100644 --- a/tests/ui/coherence/coherence-overlap-negate-not-use-feature-gate.stderr +++ b/tests/ui/coherence/coherence-overlap-negate-not-use-feature-gate.stderr @@ -5,6 +5,8 @@ LL | impl Foo for T {} | --------------------------- first implementation here LL | impl Foo for &U {} | ^^^^^^^^^^^^^^^^^^ conflicting implementation for `&_` + | + = note: downstream crates may implement trait `std::ops::DerefMut` for type `&_` error: aborting due to 1 previous error diff --git a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.classic.stderr b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.classic.stderr index 2ffb6000ec8..99abdf65abd 100644 --- a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.classic.stderr +++ b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.classic.stderr @@ -12,7 +12,6 @@ LL | impl Trait for Box {} | ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Box<_>` | = note: downstream crates may implement trait `WithAssoc<'a>` for type `std::boxed::Box<_>` - = note: downstream crates may implement trait `WhereBound` for type ` as WithAssoc<'a>>::Assoc` error: aborting due to 1 previous error diff --git a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.classic.stderr b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.classic.stderr index 49b236f9d2a..781ab0fcbf7 100644 --- a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.classic.stderr +++ b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.classic.stderr @@ -12,7 +12,7 @@ LL | impl Trait for Box {} | ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Box<_>` | = note: downstream crates may implement trait `WithAssoc<'a>` for type `std::boxed::Box<_>` - = note: downstream crates may implement trait `WhereBound` for type `std::boxed::Box< as WithAssoc<'a>>::Assoc>` + = note: downstream crates may implement trait `WhereBound` for type `std::boxed::Box<_>` error: aborting due to 1 previous error diff --git a/tests/ui/coherence/negative-coherence-check-placeholder-outlives.stderr b/tests/ui/coherence/negative-coherence-check-placeholder-outlives.stderr index f515c39ea8d..bf1ffcb5f00 100644 --- a/tests/ui/coherence/negative-coherence-check-placeholder-outlives.stderr +++ b/tests/ui/coherence/negative-coherence-check-placeholder-outlives.stderr @@ -5,6 +5,8 @@ LL | impl Bar for T where T: Foo {} | ------------------------------ first implementation here LL | impl Bar for Box {} | ^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Box<_>` + | + = note: downstream crates may implement trait `Foo` for type `std::boxed::Box<_>` error: aborting due to 1 previous error diff --git a/tests/ui/coherence/negative-coherence-considering-regions.any_lt.stderr b/tests/ui/coherence/negative-coherence-considering-regions.any_lt.stderr index f24de10f6ac..97e2e9759c1 100644 --- a/tests/ui/coherence/negative-coherence-considering-regions.any_lt.stderr +++ b/tests/ui/coherence/negative-coherence-considering-regions.any_lt.stderr @@ -6,6 +6,8 @@ LL | impl Bar for T where T: Foo {} ... LL | impl Bar for &T {} | ^^^^^^^^^^^^^^^^^^ conflicting implementation for `&_` + | + = note: downstream crates may implement trait `Foo` for type `&_` error: aborting due to 1 previous error diff --git a/tests/ui/coherence/negative-coherence-placeholder-region-constraints-on-unification.explicit.stderr b/tests/ui/coherence/negative-coherence-placeholder-region-constraints-on-unification.explicit.stderr index 832c56a4554..8d59cbc3466 100644 --- a/tests/ui/coherence/negative-coherence-placeholder-region-constraints-on-unification.explicit.stderr +++ b/tests/ui/coherence/negative-coherence-placeholder-region-constraints-on-unification.explicit.stderr @@ -8,6 +8,7 @@ LL | impl FnMarker for fn(&T) {} | = warning: the behavior may change in a future release = note: for more information, see issue #56105 + = note: downstream crates may implement trait `Marker` for type `&_` = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details note: the lint level is defined here --> $DIR/negative-coherence-placeholder-region-constraints-on-unification.rs:4:11 diff --git a/tests/ui/coherence/normalize-for-errors.current.stderr b/tests/ui/coherence/normalize-for-errors.current.stderr index dcbb73bd1ff..634a10b7a14 100644 --- a/tests/ui/coherence/normalize-for-errors.current.stderr +++ b/tests/ui/coherence/normalize-for-errors.current.stderr @@ -1,12 +1,13 @@ -error[E0119]: conflicting implementations of trait `MyTrait<_>` for type `(Box<(MyType,)>, _)` +error[E0119]: conflicting implementations of trait `MyTrait<_>` for type `(Box<(MyType,)>, <_ as Iterator>::Item)` --> $DIR/normalize-for-errors.rs:17:1 | LL | impl MyTrait for (T, S::Item) {} | ------------------------------------------------------ first implementation here LL | LL | impl MyTrait for (Box<<(MyType,) as Mirror>::Assoc>, S::Item) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(Box<(MyType,)>, _)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(Box<(MyType,)>, <_ as Iterator>::Item)` | + = note: upstream crates may add a new impl of trait `std::clone::Clone` for type `(MyType,)` in future versions = note: upstream crates may add a new impl of trait `std::marker::Copy` for type `std::boxed::Box<(MyType,)>` in future versions error: aborting due to 1 previous error diff --git a/tests/ui/coherence/normalize-for-errors.rs b/tests/ui/coherence/normalize-for-errors.rs index c17bb766b5b..3ef91eb0386 100644 --- a/tests/ui/coherence/normalize-for-errors.rs +++ b/tests/ui/coherence/normalize-for-errors.rs @@ -1,7 +1,3 @@ -//@ revisions: current next -//@ ignore-compare-mode-next-solver (explicit revisions) -//@[next] compile-flags: -Znext-solver - struct MyType; trait MyTrait {} @@ -18,6 +14,6 @@ impl MyTrait for (Box<<(MyType,) as Mirror>::Assoc>, S::Item) {} //~^ ERROR conflicting implementations of trait `MyTrait<_>` for type `(Box<(MyType,)>, //~| NOTE conflicting implementation for `(Box<(MyType,)>, //~| NOTE upstream crates may add a new impl of trait `std::marker::Copy` for type `std::boxed::Box<(MyType,)>` in future versions -//[next]~| NOTE upstream crates may add a new impl of trait `std::clone::Clone` for type `std::boxed::Box<(MyType,)>` in future versions +//~| NOTE upstream crates may add a new impl of trait `std::clone::Clone` for type `std::boxed::Box<(MyType,)>` in future versions fn main() {} diff --git a/tests/ui/coherence/normalize-for-errors.stderr b/tests/ui/coherence/normalize-for-errors.stderr new file mode 100644 index 00000000000..6fbcf5b0e1a --- /dev/null +++ b/tests/ui/coherence/normalize-for-errors.stderr @@ -0,0 +1,15 @@ +error[E0119]: conflicting implementations of trait `MyTrait<_>` for type `(Box<(MyType,)>, <_ as Iterator>::Item)` + --> $DIR/normalize-for-errors.rs:13:1 + | +LL | impl MyTrait for (T, S::Item) {} + | ------------------------------------------------------ first implementation here +LL | +LL | impl MyTrait for (Box<<(MyType,) as Mirror>::Assoc>, S::Item) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(Box<(MyType,)>, <_ as Iterator>::Item)` + | + = note: upstream crates may add a new impl of trait `std::clone::Clone` for type `std::boxed::Box<(MyType,)>` in future versions + = note: upstream crates may add a new impl of trait `std::marker::Copy` for type `std::boxed::Box<(MyType,)>` in future versions + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/occurs-check/associated-type.old.stderr b/tests/ui/coherence/occurs-check/associated-type.old.stderr index ccc7f30fa6f..6a4c6fe54a8 100644 --- a/tests/ui/coherence/occurs-check/associated-type.old.stderr +++ b/tests/ui/coherence/occurs-check/associated-type.old.stderr @@ -1,12 +1,8 @@ WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. } - WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, !2_0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. } WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. } - WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, !2_0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. } WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. } - WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, !2_0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. } WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. } - WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, !2_0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. } -error[E0119]: conflicting implementations of trait `Overlap fn(&'a (), _)>` for type `for<'a> fn(&'a (), _)` +error[E0119]: conflicting implementations of trait `Overlap fn(&'a (), ())>` for type `for<'a> fn(&'a (), ())` --> $DIR/associated-type.rs:31:1 | LL | impl Overlap for T { @@ -16,7 +12,7 @@ LL | / impl Overlap fn(&'a (), Assoc<'a, T>)> for T LL | | LL | | where LL | | for<'a> *const T: ToUnit<'a>, - | |_________________________________^ conflicting implementation for `for<'a> fn(&'a (), _)` + | |_________________________________^ conflicting implementation for `for<'a> fn(&'a (), ())` | = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details diff --git a/tests/ui/coherence/occurs-check/opaques.current.stderr b/tests/ui/coherence/occurs-check/opaques.current.stderr new file mode 100644 index 00000000000..96ef7cd4322 --- /dev/null +++ b/tests/ui/coherence/occurs-check/opaques.current.stderr @@ -0,0 +1,12 @@ +error[E0119]: conflicting implementations of trait `Trait<_>` + --> $DIR/opaques.rs:27:1 + | +LL | impl Trait for T { + | ---------------------- first implementation here +... +LL | impl Trait for defining_scope::Alias { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/occurs-check/opaques.next.stderr b/tests/ui/coherence/occurs-check/opaques.next.stderr index 757219398f1..2bedff25ecd 100644 --- a/tests/ui/coherence/occurs-check/opaques.next.stderr +++ b/tests/ui/coherence/occurs-check/opaques.next.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Trait<_>` - --> $DIR/opaques.rs:30:1 + --> $DIR/opaques.rs:27:1 | LL | impl Trait for T { | ---------------------- first implementation here @@ -8,7 +8,7 @@ LL | impl Trait for defining_scope::Alias { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation error[E0282]: type annotations needed - --> $DIR/opaques.rs:13:23 + --> $DIR/opaques.rs:10:23 | LL | pub fn cast(x: Container, T>) -> Container { | ^^^^^^^^^^^^^^^^^^^^^^ cannot infer type diff --git a/tests/ui/coherence/occurs-check/opaques.rs b/tests/ui/coherence/occurs-check/opaques.rs index 241a247c841..d7032dd53d9 100644 --- a/tests/ui/coherence/occurs-check/opaques.rs +++ b/tests/ui/coherence/occurs-check/opaques.rs @@ -1,10 +1,7 @@ -//@revisions: old next +//@revisions: current next //@[next] compile-flags: -Znext-solver // A regression test for #105787 - -//@[old] known-bug: #105787 -//@[old] check-pass #![feature(type_alias_impl_trait)] mod defining_scope { use super::*; @@ -28,7 +25,7 @@ impl Trait for T { type Assoc = Box; } impl Trait for defining_scope::Alias { - //[next]~^ ERROR conflicting implementations of trait + //~^ ERROR conflicting implementations of trait type Assoc = usize; } diff --git a/tests/ui/coherence/skip-reporting-if-references-err.current.stderr b/tests/ui/coherence/skip-reporting-if-references-err.current.stderr index 5eef3256b2c..5de4cf626e4 100644 --- a/tests/ui/coherence/skip-reporting-if-references-err.current.stderr +++ b/tests/ui/coherence/skip-reporting-if-references-err.current.stderr @@ -9,19 +9,6 @@ help: indicate the anonymous lifetime LL | impl ToUnit<'_> for T {} | ++++ -error[E0277]: the trait bound `for<'a> (): ToUnit<'a>` is not satisfied - --> $DIR/skip-reporting-if-references-err.rs:15:29 - | -LL | impl Overlap for for<'a> fn(<() as ToUnit<'a>>::Unit) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> ToUnit<'a>` is not implemented for `()` +error: aborting due to 1 previous error -error[E0277]: the trait bound `for<'a> (): ToUnit<'a>` is not satisfied - --> $DIR/skip-reporting-if-references-err.rs:15:18 - | -LL | impl Overlap for for<'a> fn(<() as ToUnit<'a>>::Unit) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> ToUnit<'a>` is not implemented for `()` - -error: aborting due to 3 previous errors - -Some errors have detailed explanations: E0277, E0726. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0726`. diff --git a/tests/ui/coherence/skip-reporting-if-references-err.rs b/tests/ui/coherence/skip-reporting-if-references-err.rs index f9eaa498232..dd8a71c4700 100644 --- a/tests/ui/coherence/skip-reporting-if-references-err.rs +++ b/tests/ui/coherence/skip-reporting-if-references-err.rs @@ -1,8 +1,4 @@ // Regression test for #121006. -//@ revisions: current next -//@ ignore-compare-mode-next-solver (explicit revisions) -//@[next] compile-flags: -Znext-solver - trait ToUnit<'a> { type Unit; } @@ -13,7 +9,5 @@ impl ToUnit for T {} trait Overlap {} impl Overlap for fn(U) {} impl Overlap for for<'a> fn(<() as ToUnit<'a>>::Unit) {} -//[current]~^ ERROR the trait bound `for<'a> (): ToUnit<'a>` is not satisfied -//[current]~| ERROR the trait bound `for<'a> (): ToUnit<'a>` is not satisfied fn main() {} diff --git a/tests/ui/coherence/skip-reporting-if-references-err.stderr b/tests/ui/coherence/skip-reporting-if-references-err.stderr new file mode 100644 index 00000000000..0ff3e88a0af --- /dev/null +++ b/tests/ui/coherence/skip-reporting-if-references-err.stderr @@ -0,0 +1,14 @@ +error[E0726]: implicit elided lifetime not allowed here + --> $DIR/skip-reporting-if-references-err.rs:6:9 + | +LL | impl ToUnit for T {} + | ^^^^^^ expected lifetime parameter + | +help: indicate the anonymous lifetime + | +LL | impl ToUnit<'_> for T {} + | ++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0726`. diff --git a/tests/ui/coherence/super-traits/super-trait-knowable-1.current.stderr b/tests/ui/coherence/super-traits/super-trait-knowable-1.current.stderr deleted file mode 100644 index fb01cf158d9..00000000000 --- a/tests/ui/coherence/super-traits/super-trait-knowable-1.current.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error[E0119]: conflicting implementations of trait `Overlap<_>` for type `()` - --> $DIR/super-trait-knowable-1.rs:16:1 - | -LL | impl> Overlap for U {} - | ----------------------------------- first implementation here -LL | impl Overlap for () {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()` - | - = note: downstream crates may implement trait `Sub<_>` for type `()` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/super-traits/super-trait-knowable-1.rs b/tests/ui/coherence/super-traits/super-trait-knowable-1.rs index 80df8c19ee5..77af4d0f2e3 100644 --- a/tests/ui/coherence/super-traits/super-trait-knowable-1.rs +++ b/tests/ui/coherence/super-traits/super-trait-knowable-1.rs @@ -3,10 +3,7 @@ // We therefore elaborate super trait bounds in the implicit negative // overlap check. -//@ revisions: current next -//@ ignore-compare-mode-next-solver (explicit revisions) -//@[next] compile-flags: -Znext-solver -//@[next] check-pass +//@ check-pass trait Super {} trait Sub: Super {} @@ -14,6 +11,5 @@ trait Sub: Super {} trait Overlap {} impl> Overlap for U {} impl Overlap for () {} -//[current]~^ ERROR conflicting implementations fn main() {} diff --git a/tests/ui/coherence/super-traits/super-trait-knowable-3.current.stderr b/tests/ui/coherence/super-traits/super-trait-knowable-3.current.stderr deleted file mode 100644 index 542edb8b7f6..00000000000 --- a/tests/ui/coherence/super-traits/super-trait-knowable-3.current.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error[E0119]: conflicting implementations of trait `Overlap<_>` for type `()` - --> $DIR/super-trait-knowable-3.rs:19:1 - | -LL | impl>> Overlap for U {} - | ---------------------------------------- first implementation here -LL | impl Overlap for () {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()` - | - = note: downstream crates may implement trait `Sub<_>` for type `()` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/super-traits/super-trait-knowable-3.rs b/tests/ui/coherence/super-traits/super-trait-knowable-3.rs index 295d7ac48d8..6198d3d303b 100644 --- a/tests/ui/coherence/super-traits/super-trait-knowable-3.rs +++ b/tests/ui/coherence/super-traits/super-trait-knowable-3.rs @@ -2,10 +2,7 @@ // super trait bound is in a nested goal so this would not // compile if we were to only elaborate root goals. -//@ revisions: current next -//@ ignore-compare-mode-next-solver (explicit revisions) -//@[next] compile-flags: -Znext-solver -//@[next] check-pass +//@ check-pass trait Super {} trait Sub: Super {} @@ -17,6 +14,5 @@ impl, U> Bound> for T {} trait Overlap {} impl>> Overlap for U {} impl Overlap for () {} -//[current]~^ ERROR conflicting implementations of trait `Overlap<_>` for type `()` fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.rs b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.rs index d11b457a3f6..a55be99fc0b 100644 --- a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.rs +++ b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.rs @@ -22,6 +22,7 @@ mod v20 { impl v17<512, v0> { pub const fn v21() -> v18 {} //~^ ERROR cannot find type `v18` in this scope + //~| ERROR duplicate definitions with name `v21` } impl v17 { diff --git a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr index 45be31c7ba3..30a45ce377e 100644 --- a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr +++ b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr @@ -1,5 +1,5 @@ error[E0432]: unresolved import `v20::v13` - --> $DIR/unevaluated-const-ice-119731.rs:37:15 + --> $DIR/unevaluated-const-ice-119731.rs:38:15 | LL | pub use v20::{v13, v17}; | ^^^ @@ -23,7 +23,7 @@ LL | pub const fn v21() -> v18 {} | ^^^ help: a type alias with a similar name exists: `v11` error[E0412]: cannot find type `v18` in this scope - --> $DIR/unevaluated-const-ice-119731.rs:30:31 + --> $DIR/unevaluated-const-ice-119731.rs:31:31 | LL | pub type v11 = [[usize; v4]; v4]; | --------------------------------- similarly named type alias `v11` defined here @@ -32,7 +32,7 @@ LL | pub const fn v21() -> v18 { | ^^^ help: a type alias with a similar name exists: `v11` error[E0422]: cannot find struct, variant or union type `v18` in this scope - --> $DIR/unevaluated-const-ice-119731.rs:32:13 + --> $DIR/unevaluated-const-ice-119731.rs:33:13 | LL | pub type v11 = [[usize; v4]; v4]; | --------------------------------- similarly named type alias `v11` defined here @@ -73,20 +73,29 @@ LL + #![feature(adt_const_params)] | error: maximum number of nodes exceeded in constant v20::v17::::{constant#0} - --> $DIR/unevaluated-const-ice-119731.rs:27:37 + --> $DIR/unevaluated-const-ice-119731.rs:28:37 | LL | impl v17 { | ^^ error: maximum number of nodes exceeded in constant v20::v17::::{constant#0} - --> $DIR/unevaluated-const-ice-119731.rs:27:37 + --> $DIR/unevaluated-const-ice-119731.rs:28:37 | LL | impl v17 { | ^^ | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 9 previous errors; 2 warnings emitted +error[E0592]: duplicate definitions with name `v21` + --> $DIR/unevaluated-const-ice-119731.rs:23:9 + | +LL | pub const fn v21() -> v18 {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ duplicate definitions for `v21` +... +LL | pub const fn v21() -> v18 { + | ------------------------- other definition for `v21` -Some errors have detailed explanations: E0412, E0422, E0425, E0432. +error: aborting due to 10 previous errors; 2 warnings emitted + +Some errors have detailed explanations: E0412, E0422, E0425, E0432, E0592. For more information about an error, try `rustc --explain E0412`. diff --git a/tests/ui/const-generics/generic_const_exprs/unknown-alias-defkind-anonconst-ice-116710.rs b/tests/ui/const-generics/generic_const_exprs/unknown-alias-defkind-anonconst-ice-116710.rs index dd0b1e8c9f7..81ac9979bd8 100644 --- a/tests/ui/const-generics/generic_const_exprs/unknown-alias-defkind-anonconst-ice-116710.rs +++ b/tests/ui/const-generics/generic_const_exprs/unknown-alias-defkind-anonconst-ice-116710.rs @@ -10,6 +10,5 @@ trait Trait {} impl Trait for A {} impl Trait for A {} -//~^ ERROR conflicting implementations of trait `Trait` for type `A<_>` pub fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/unknown-alias-defkind-anonconst-ice-116710.stderr b/tests/ui/const-generics/generic_const_exprs/unknown-alias-defkind-anonconst-ice-116710.stderr index 80ac96d4870..e29c49ff042 100644 --- a/tests/ui/const-generics/generic_const_exprs/unknown-alias-defkind-anonconst-ice-116710.stderr +++ b/tests/ui/const-generics/generic_const_exprs/unknown-alias-defkind-anonconst-ice-116710.stderr @@ -4,16 +4,6 @@ error[E0423]: expected value, found builtin type `u8` LL | struct A; | ^^ not a value -error[E0119]: conflicting implementations of trait `Trait` for type `A<_>` - --> $DIR/unknown-alias-defkind-anonconst-ice-116710.rs:12:1 - | -LL | impl Trait for A {} - | --------------------------------- first implementation here -LL | -LL | impl Trait for A {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `A<_>` +error: aborting due to 1 previous error -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0119, E0423. -For more information about an error, try `rustc --explain E0119`. +For more information about this error, try `rustc --explain E0423`. diff --git a/tests/ui/error-codes/e0119/issue-23563.stderr b/tests/ui/error-codes/e0119/issue-23563.stderr index 86737742f74..a308769af13 100644 --- a/tests/ui/error-codes/e0119/issue-23563.stderr +++ b/tests/ui/error-codes/e0119/issue-23563.stderr @@ -1,4 +1,4 @@ -error[E0119]: conflicting implementations of trait `LolFrom<&[_]>` for type `LocalType<_>` +error[E0119]: conflicting implementations of trait `LolFrom<&[u8]>` for type `LocalType` --> $DIR/issue-23563.rs:13:1 | LL | impl<'a, T> LolFrom<&'a [T]> for LocalType { diff --git a/tests/ui/feature-gates/feature-gate-with_negative_coherence.stderr b/tests/ui/feature-gates/feature-gate-with_negative_coherence.stderr index ba076568088..b32f54aaecf 100644 --- a/tests/ui/feature-gates/feature-gate-with_negative_coherence.stderr +++ b/tests/ui/feature-gates/feature-gate-with_negative_coherence.stderr @@ -6,6 +6,8 @@ LL | impl Foo for T { } LL | LL | impl Foo for &T { } | ^^^^^^^^^^^^^^^^^^ conflicting implementation for `&_` + | + = note: downstream crates may implement trait `std::ops::DerefMut` for type `&_` error: aborting due to 1 previous error diff --git a/tests/ui/higher-ranked/structually-relate-aliases.rs b/tests/ui/higher-ranked/structually-relate-aliases.rs index 8df24702811..69882450961 100644 --- a/tests/ui/higher-ranked/structually-relate-aliases.rs +++ b/tests/ui/higher-ranked/structually-relate-aliases.rs @@ -11,7 +11,6 @@ type Assoc<'a, T> = >::Unit; impl Overlap for T {} impl Overlap fn(&'a (), Assoc<'a, T>)> for T {} -//~^ ERROR 13:17: 13:49: the trait bound `for<'a> T: ToUnit<'a>` is not satisfied [E0277] -//~| ERROR 13:36: 13:48: the trait bound `for<'a> T: ToUnit<'a>` is not satisfied [E0277] +//~^ ERROR conflicting implementations of trait `Overlap fn(&'a (), _)>` fn main() {} diff --git a/tests/ui/higher-ranked/structually-relate-aliases.stderr b/tests/ui/higher-ranked/structually-relate-aliases.stderr index 7de30efae1c..4ecd5829bc3 100644 --- a/tests/ui/higher-ranked/structually-relate-aliases.stderr +++ b/tests/ui/higher-ranked/structually-relate-aliases.stderr @@ -1,27 +1,18 @@ WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [?1t, '^0.Named(DefId(0:15 ~ structually_relate_aliases[de75]::{impl#1}::'a), "'a")], def_id: DefId(0:5 ~ structually_relate_aliases[de75]::ToUnit::Unit), .. } - WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [?1t, !2_0.Named(DefId(0:15 ~ structually_relate_aliases[de75]::{impl#1}::'a), "'a")], def_id: DefId(0:5 ~ structually_relate_aliases[de75]::ToUnit::Unit), .. } -error[E0277]: the trait bound `for<'a> T: ToUnit<'a>` is not satisfied - --> $DIR/structually-relate-aliases.rs:13:36 + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [?1t, '^0.Named(DefId(0:15 ~ structually_relate_aliases[de75]::{impl#1}::'a), "'a")], def_id: DefId(0:5 ~ structually_relate_aliases[de75]::ToUnit::Unit), .. } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [?1t, '^0.Named(DefId(0:15 ~ structually_relate_aliases[de75]::{impl#1}::'a), "'a")], def_id: DefId(0:5 ~ structually_relate_aliases[de75]::ToUnit::Unit), .. } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [?1t, '^0.Named(DefId(0:15 ~ structually_relate_aliases[de75]::{impl#1}::'a), "'a")], def_id: DefId(0:5 ~ structually_relate_aliases[de75]::ToUnit::Unit), .. } +error[E0119]: conflicting implementations of trait `Overlap fn(&'a (), _)>` for type `for<'a> fn(&'a (), _)` + --> $DIR/structually-relate-aliases.rs:13:1 | +LL | impl Overlap for T {} + | ------------------------ first implementation here +LL | LL | impl Overlap fn(&'a (), Assoc<'a, T>)> for T {} - | ^^^^^^^^^^^^ the trait `for<'a> ToUnit<'a>` is not implemented for `T` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'a> fn(&'a (), _)` | -help: consider restricting type parameter `T` - | -LL | impl ToUnit<'a>> Overlap fn(&'a (), Assoc<'a, T>)> for T {} - | ++++++++++++++++++++ + = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details -error[E0277]: the trait bound `for<'a> T: ToUnit<'a>` is not satisfied - --> $DIR/structually-relate-aliases.rs:13:17 - | -LL | impl Overlap fn(&'a (), Assoc<'a, T>)> for T {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> ToUnit<'a>` is not implemented for `T` - | -help: consider restricting type parameter `T` - | -LL | impl ToUnit<'a>> Overlap fn(&'a (), Assoc<'a, T>)> for T {} - | ++++++++++++++++++++ +error: aborting due to 1 previous error -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/impl-trait/auto-trait-coherence.old.stderr b/tests/ui/impl-trait/auto-trait-coherence.old.stderr index 3f979d1a50b..cd91bfcb48d 100644 --- a/tests/ui/impl-trait/auto-trait-coherence.old.stderr +++ b/tests/ui/impl-trait/auto-trait-coherence.old.stderr @@ -1,11 +1,11 @@ -error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D` +error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D<_>` --> $DIR/auto-trait-coherence.rs:24:1 | LL | impl AnotherTrait for T {} | -------------------------------- first implementation here ... LL | impl AnotherTrait for D { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D<_>` error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/auto-trait-coherence.rs b/tests/ui/impl-trait/auto-trait-coherence.rs index e3036fd0fe2..0d7fef21cc9 100644 --- a/tests/ui/impl-trait/auto-trait-coherence.rs +++ b/tests/ui/impl-trait/auto-trait-coherence.rs @@ -1,6 +1,3 @@ -//@ revisions: old next -//@[next] compile-flags: -Znext-solver - // Tests that type alias impls traits do not leak auto-traits for // the purposes of coherence checking #![feature(type_alias_impl_trait)] @@ -22,8 +19,7 @@ impl AnotherTrait for T {} // (We treat opaque types as "foreign types" that could grow more impls // in the future.) impl AnotherTrait for D { - //[old]~^ ERROR conflicting implementations of trait `AnotherTrait` for type `D` - //[next]~^^ ERROR conflicting implementations of trait `AnotherTrait` for type `D<_>` + //~^ ERROR conflicting implementations of trait `AnotherTrait` for type `D<_>` } fn main() {} diff --git a/tests/ui/impl-trait/auto-trait-coherence.stderr b/tests/ui/impl-trait/auto-trait-coherence.stderr new file mode 100644 index 00000000000..e0f4c857717 --- /dev/null +++ b/tests/ui/impl-trait/auto-trait-coherence.stderr @@ -0,0 +1,12 @@ +error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D<_>` + --> $DIR/auto-trait-coherence.rs:21:1 + | +LL | impl AnotherTrait for T {} + | -------------------------------- first implementation here +... +LL | impl AnotherTrait for D { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D<_>` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/impl-trait/coherence-treats-tait-ambig.rs b/tests/ui/impl-trait/coherence-treats-tait-ambig.rs index df47208bf36..e8c1fcdd213 100644 --- a/tests/ui/impl-trait/coherence-treats-tait-ambig.rs +++ b/tests/ui/impl-trait/coherence-treats-tait-ambig.rs @@ -5,7 +5,7 @@ type T = impl Sized; struct Foo; impl Into for Foo { -//~^ ERROR conflicting implementations of trait `Into` for type `Foo` +//~^ ERROR conflicting implementations of trait `Into<_>` for type `Foo` fn into(self) -> T { Foo } diff --git a/tests/ui/impl-trait/coherence-treats-tait-ambig.stderr b/tests/ui/impl-trait/coherence-treats-tait-ambig.stderr index faaad276927..618bef1f271 100644 --- a/tests/ui/impl-trait/coherence-treats-tait-ambig.stderr +++ b/tests/ui/impl-trait/coherence-treats-tait-ambig.stderr @@ -1,4 +1,4 @@ -error[E0119]: conflicting implementations of trait `Into` for type `Foo` +error[E0119]: conflicting implementations of trait `Into<_>` for type `Foo` --> $DIR/coherence-treats-tait-ambig.rs:7:1 | LL | impl Into for Foo { diff --git a/tests/ui/impl-trait/negative-reasoning.rs b/tests/ui/impl-trait/negative-reasoning.rs index 70e24a3a9d0..0474dc0beda 100644 --- a/tests/ui/impl-trait/negative-reasoning.rs +++ b/tests/ui/impl-trait/negative-reasoning.rs @@ -17,7 +17,7 @@ impl AnotherTrait for T {} // This is in error, because we cannot assume that `OpaqueType: !Debug` impl AnotherTrait for D { - //~^ ERROR conflicting implementations of trait `AnotherTrait` for type `D` + //~^ ERROR conflicting implementations of trait `AnotherTrait` for type `D<_>` } fn main() {} diff --git a/tests/ui/impl-trait/negative-reasoning.stderr b/tests/ui/impl-trait/negative-reasoning.stderr index 3cb4be16fc3..631784c817b 100644 --- a/tests/ui/impl-trait/negative-reasoning.stderr +++ b/tests/ui/impl-trait/negative-reasoning.stderr @@ -1,13 +1,11 @@ -error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D` +error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D<_>` --> $DIR/negative-reasoning.rs:19:1 | LL | impl AnotherTrait for T {} | ------------------------------------------- first implementation here ... LL | impl AnotherTrait for D { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D` - | - = note: upstream crates may add a new impl of trait `std::marker::FnPtr` for type `OpaqueType` in future versions + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D<_>` error: aborting due to 1 previous error diff --git a/tests/ui/impl-unused-tps.rs b/tests/ui/impl-unused-tps.rs index 3eb9daedf76..a5836db3c8e 100644 --- a/tests/ui/impl-unused-tps.rs +++ b/tests/ui/impl-unused-tps.rs @@ -1,34 +1,35 @@ -//~ ERROR overflow evaluating the requirement `([isize; 0], _): Sized - trait Foo { - fn get(&self, A: &A) { } + fn get(&self, A: &A) {} } trait Bar { type Out; } -impl Foo for [isize;0] { +impl Foo for [isize; 0] { // OK, T is used in `Foo`. } -impl Foo for [isize;1] { +impl Foo for [isize; 1] { //~^ ERROR the type parameter `U` is not constrained } -impl Foo for [isize;2] where T : Bar { +impl Foo for [isize; 2] +where + T: Bar, +{ // OK, `U` is now constrained by the output type parameter. } -impl,U> Foo for [isize;3] { +impl, U> Foo for [isize; 3] { // OK, same as above but written differently. } -impl Foo for U { +impl Foo for U { //~^ ERROR conflicting implementations of trait `Foo<_>` for type `[isize; 0]` } -impl Bar for T { +impl Bar for T { //~^ ERROR the type parameter `U` is not constrained type Out = U; @@ -36,28 +37,33 @@ impl Bar for T { // Using `U` in an associated type within the impl is not good enough! } -impl Bar for T - where T : Bar +impl Bar for T +where + T: Bar, { - //~^^^ ERROR the type parameter `U` is not constrained - + //~^^^^ ERROR the type parameter `U` is not constrained by the impl trait, self type, or predicates + //~| ERROR conflicting implementations of trait `Bar` // This crafty self-referential attempt is still no good. } -impl Foo for T - where (T,U): Bar +impl Foo for T +where + (T, U): Bar, { - //~^^^ ERROR the type parameter `U` is not constrained - //~| ERROR the type parameter `V` is not constrained + //~^^^^ ERROR the type parameter `U` is not constrained + //~| ERROR the type parameter `V` is not constrained + //~| ERROR conflicting implementations of trait `Foo<[isize; 0]>` for type `[isize; 0]` // Here, `V` is bound by an output type parameter, but the inputs // are not themselves constrained. } -impl Foo<(T,U)> for T - where (T,U): Bar +impl Foo<(T, U)> for T +where + (T, U): Bar, { + //~^^^^ ERROR conflicting implementations of trait `Foo<([isize; 0], _)>` for type `[isize; 0]` // As above, but both T and U ARE constrained. } -fn main() { } +fn main() {} diff --git a/tests/ui/impl-unused-tps.stderr b/tests/ui/impl-unused-tps.stderr index af427cb5f3e..da4589dee82 100644 --- a/tests/ui/impl-unused-tps.stderr +++ b/tests/ui/impl-unused-tps.stderr @@ -1,56 +1,76 @@ error[E0119]: conflicting implementations of trait `Foo<_>` for type `[isize; 0]` - --> $DIR/impl-unused-tps.rs:27:1 + --> $DIR/impl-unused-tps.rs:28:1 | -LL | impl Foo for [isize;0] { - | ---------------------------- first implementation here +LL | impl Foo for [isize; 0] { + | ----------------------------- first implementation here ... -LL | impl Foo for U { - | ^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `[isize; 0]` +LL | impl Foo for U { + | ^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `[isize; 0]` -error[E0275]: overflow evaluating the requirement `([isize; 0], _): Sized` +error[E0119]: conflicting implementations of trait `Bar` + --> $DIR/impl-unused-tps.rs:40:1 | - = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`impl_unused_tps`) -note: required for `([isize; 0], _)` to implement `Bar` - --> $DIR/impl-unused-tps.rs:31:11 +LL | impl Bar for T { + | -------------------- first implementation here +... +LL | / impl Bar for T +LL | | where +LL | | T: Bar, + | |____________________^ conflicting implementation + +error[E0119]: conflicting implementations of trait `Foo<[isize; 0]>` for type `[isize; 0]` + --> $DIR/impl-unused-tps.rs:49:1 | -LL | impl Bar for T { - | - ^^^ ^ - | | - | unsatisfied trait bound introduced here - = note: 126 redundant requirements hidden - = note: required for `([isize; 0], _)` to implement `Bar` +LL | impl Foo for [isize; 0] { + | ----------------------------- first implementation here +... +LL | / impl Foo for T +LL | | where +LL | | (T, U): Bar, + | |_________________________^ conflicting implementation for `[isize; 0]` + +error[E0119]: conflicting implementations of trait `Foo<([isize; 0], _)>` for type `[isize; 0]` + --> $DIR/impl-unused-tps.rs:61:1 + | +LL | impl Foo for [isize; 0] { + | ----------------------------- first implementation here +... +LL | / impl Foo<(T, U)> for T +LL | | where +LL | | (T, U): Bar, + | |_________________________^ conflicting implementation for `[isize; 0]` error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates - --> $DIR/impl-unused-tps.rs:15:8 + --> $DIR/impl-unused-tps.rs:13:9 | -LL | impl Foo for [isize;1] { - | ^ unconstrained type parameter +LL | impl Foo for [isize; 1] { + | ^ unconstrained type parameter error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates - --> $DIR/impl-unused-tps.rs:31:8 + --> $DIR/impl-unused-tps.rs:32:9 | -LL | impl Bar for T { - | ^ unconstrained type parameter +LL | impl Bar for T { + | ^ unconstrained type parameter error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates - --> $DIR/impl-unused-tps.rs:39:8 + --> $DIR/impl-unused-tps.rs:40:9 | -LL | impl Bar for T - | ^ unconstrained type parameter +LL | impl Bar for T + | ^ unconstrained type parameter error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates - --> $DIR/impl-unused-tps.rs:47:8 + --> $DIR/impl-unused-tps.rs:49:9 | -LL | impl Foo for T - | ^ unconstrained type parameter +LL | impl Foo for T + | ^ unconstrained type parameter error[E0207]: the type parameter `V` is not constrained by the impl trait, self type, or predicates - --> $DIR/impl-unused-tps.rs:47:10 + --> $DIR/impl-unused-tps.rs:49:12 | -LL | impl Foo for T - | ^ unconstrained type parameter +LL | impl Foo for T + | ^ unconstrained type parameter -error: aborting due to 7 previous errors +error: aborting due to 9 previous errors -Some errors have detailed explanations: E0119, E0207, E0275. +Some errors have detailed explanations: E0119, E0207. For more information about an error, try `rustc --explain E0119`. diff --git a/tests/ui/issues/issue-48728.rs b/tests/ui/issues/issue-48728.rs index 7ef05f4277b..8ad9289c65c 100644 --- a/tests/ui/issues/issue-48728.rs +++ b/tests/ui/issues/issue-48728.rs @@ -1,12 +1,8 @@ // Regression test for #48728, an ICE that occurred computing // coherence "help" information. -//@ revisions: current next -//@ ignore-compare-mode-next-solver (explicit revisions) -//@[next] compile-flags: -Znext-solver -//@[next] check-pass - -#[derive(Clone)] //[current]~ ERROR conflicting implementations of trait `Clone` +//@ check-pass +#[derive(Clone)] struct Node(Box); impl Clone for Node<[T]> { diff --git a/tests/ui/specialization/defaultimpl/specialization-no-default.rs b/tests/ui/specialization/defaultimpl/specialization-no-default.rs index 661724eef8a..ddc32337306 100644 --- a/tests/ui/specialization/defaultimpl/specialization-no-default.rs +++ b/tests/ui/specialization/defaultimpl/specialization-no-default.rs @@ -71,7 +71,8 @@ impl Redundant for T { } default impl Redundant for i32 { - fn redundant(&self) {} //~ ERROR E0520 + fn redundant(&self) {} + //~^ ERROR `redundant` specializes an item from a parent `impl`, but that item is not marked `default` } fn main() {} diff --git a/tests/ui/specialization/specialization-default-items-drop-coherence.current.stderr b/tests/ui/specialization/specialization-default-items-drop-coherence.current.stderr new file mode 100644 index 00000000000..36df6bfd9fc --- /dev/null +++ b/tests/ui/specialization/specialization-default-items-drop-coherence.current.stderr @@ -0,0 +1,12 @@ +error[E0119]: conflicting implementations of trait `Overlap` for type `u32` + --> $DIR/specialization-default-items-drop-coherence.rs:26:1 + | +LL | impl Overlap for u32 { + | -------------------- first implementation here +... +LL | impl Overlap for ::Id { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u32` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/specialization/specialization-default-items-drop-coherence.next.stderr b/tests/ui/specialization/specialization-default-items-drop-coherence.next.stderr index e9498a00317..36df6bfd9fc 100644 --- a/tests/ui/specialization/specialization-default-items-drop-coherence.next.stderr +++ b/tests/ui/specialization/specialization-default-items-drop-coherence.next.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Overlap` for type `u32` - --> $DIR/specialization-default-items-drop-coherence.rs:29:1 + --> $DIR/specialization-default-items-drop-coherence.rs:26:1 | LL | impl Overlap for u32 { | -------------------- first implementation here diff --git a/tests/ui/specialization/specialization-default-items-drop-coherence.rs b/tests/ui/specialization/specialization-default-items-drop-coherence.rs index 6dc01277639..b3c1f72777c 100644 --- a/tests/ui/specialization/specialization-default-items-drop-coherence.rs +++ b/tests/ui/specialization/specialization-default-items-drop-coherence.rs @@ -1,8 +1,5 @@ -//@ revisions: classic coherence next +//@ revisions: current next //@[next] compile-flags: -Znext-solver -//@[coherence] compile-flags: -Znext-solver=coherence -//@[classic] check-pass -//@[classic] known-bug: #105782 // Should fail. Default items completely drop candidates instead of ambiguity, // which is unsound during coherence, since coherence requires completeness. @@ -27,8 +24,7 @@ impl Overlap for u32 { } impl Overlap for ::Id { - //[coherence]~^ ERROR conflicting implementations of trait `Overlap` for type `u32` - //[next]~^^ ERROR conflicting implementations of trait `Overlap` for type `u32` + //~^ ERROR conflicting implementations of trait `Overlap` for type `u32` type Assoc = Box; } diff --git a/tests/ui/specialization/specialization-overlap-projection.current.stderr b/tests/ui/specialization/specialization-overlap-projection.current.stderr index a69826fa96b..4e77cb17fbb 100644 --- a/tests/ui/specialization/specialization-overlap-projection.current.stderr +++ b/tests/ui/specialization/specialization-overlap-projection.current.stderr @@ -1,5 +1,5 @@ warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/specialization-overlap-projection.rs:10:12 + --> $DIR/specialization-overlap-projection.rs:4:12 | LL | #![feature(specialization)] | ^^^^^^^^^^^^^^ @@ -8,5 +8,23 @@ LL | #![feature(specialization)] = help: consider using `min_specialization` instead, which is more stable and complete = note: `#[warn(incomplete_features)]` on by default -warning: 1 warning emitted +error[E0119]: conflicting implementations of trait `Foo` for type `u32` + --> $DIR/specialization-overlap-projection.rs:19:1 + | +LL | impl Foo for u32 {} + | ---------------- first implementation here +LL | impl Foo for ::Output {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u32` +error[E0119]: conflicting implementations of trait `Foo` for type `u32` + --> $DIR/specialization-overlap-projection.rs:21:1 + | +LL | impl Foo for u32 {} + | ---------------- first implementation here +... +LL | impl Foo for ::Output {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u32` + +error: aborting due to 2 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/specialization/specialization-overlap-projection.next.stderr b/tests/ui/specialization/specialization-overlap-projection.next.stderr index 5b17696162e..4e77cb17fbb 100644 --- a/tests/ui/specialization/specialization-overlap-projection.next.stderr +++ b/tests/ui/specialization/specialization-overlap-projection.next.stderr @@ -1,5 +1,5 @@ warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/specialization-overlap-projection.rs:10:12 + --> $DIR/specialization-overlap-projection.rs:4:12 | LL | #![feature(specialization)] | ^^^^^^^^^^^^^^ @@ -9,7 +9,7 @@ LL | #![feature(specialization)] = note: `#[warn(incomplete_features)]` on by default error[E0119]: conflicting implementations of trait `Foo` for type `u32` - --> $DIR/specialization-overlap-projection.rs:25:1 + --> $DIR/specialization-overlap-projection.rs:19:1 | LL | impl Foo for u32 {} | ---------------- first implementation here @@ -17,7 +17,7 @@ LL | impl Foo for ::Output {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u32` error[E0119]: conflicting implementations of trait `Foo` for type `u32` - --> $DIR/specialization-overlap-projection.rs:27:1 + --> $DIR/specialization-overlap-projection.rs:21:1 | LL | impl Foo for u32 {} | ---------------- first implementation here diff --git a/tests/ui/specialization/specialization-overlap-projection.rs b/tests/ui/specialization/specialization-overlap-projection.rs index 16dccf82dcb..f7a2a792243 100644 --- a/tests/ui/specialization/specialization-overlap-projection.rs +++ b/tests/ui/specialization/specialization-overlap-projection.rs @@ -1,13 +1,8 @@ -//@ revisions: current next -//@ ignore-compare-mode-next-solver (explicit revisions) -//@[next] compile-flags: -Znext-solver -//@[current] check-pass - // Test that impls on projected self types can resolve overlap, even when the // projections involve specialization, so long as the associated type is // provided by the most specialized impl. - -#![feature(specialization)] //~ WARN the feature `specialization` is incomplete +#![feature(specialization)] +//~^ WARN the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes trait Assoc { type Output; @@ -23,8 +18,8 @@ impl Assoc for u16 { type Output = u16; } trait Foo {} impl Foo for u32 {} impl Foo for ::Output {} -//[next]~^ ERROR conflicting implementations of trait `Foo` for type `u32` +//~^ ERROR conflicting implementations of trait `Foo` for type `u32` impl Foo for ::Output {} -//[next]~^ ERROR conflicting implementations of trait `Foo` for type `u32` +//~^ ERROR conflicting implementations of trait `Foo` for type `u32` fn main() {} diff --git a/tests/ui/specialization/specialization-overlap-projection.stderr b/tests/ui/specialization/specialization-overlap-projection.stderr new file mode 100644 index 00000000000..5f3cd9c66cf --- /dev/null +++ b/tests/ui/specialization/specialization-overlap-projection.stderr @@ -0,0 +1,30 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-overlap-projection.rs:4:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0119]: conflicting implementations of trait `Foo` for type `u32` + --> $DIR/specialization-overlap-projection.rs:20:1 + | +LL | impl Foo for u32 {} + | ---------------- first implementation here +LL | impl Foo for ::Output {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u32` + +error[E0119]: conflicting implementations of trait `Foo` for type `u32` + --> $DIR/specialization-overlap-projection.rs:22:1 + | +LL | impl Foo for u32 {} + | ---------------- first implementation here +... +LL | impl Foo for ::Output {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u32` + +error: aborting due to 2 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/traits/alias/issue-83613.rs b/tests/ui/traits/alias/issue-83613.rs index 2462e703a71..6f0012bf089 100644 --- a/tests/ui/traits/alias/issue-83613.rs +++ b/tests/ui/traits/alias/issue-83613.rs @@ -8,5 +8,5 @@ fn mk_opaque() -> OpaqueType { trait AnotherTrait {} impl AnotherTrait for T {} impl AnotherTrait for OpaqueType {} -//~^ ERROR conflicting implementations of trait `AnotherTrait` for type `OpaqueType` +//~^ ERROR conflicting implementations of trait `AnotherTrait` fn main() {} diff --git a/tests/ui/traits/alias/issue-83613.stderr b/tests/ui/traits/alias/issue-83613.stderr index 847fda41776..47181c3f33e 100644 --- a/tests/ui/traits/alias/issue-83613.stderr +++ b/tests/ui/traits/alias/issue-83613.stderr @@ -1,10 +1,10 @@ -error[E0119]: conflicting implementations of trait `AnotherTrait` for type `OpaqueType` +error[E0119]: conflicting implementations of trait `AnotherTrait` --> $DIR/issue-83613.rs:10:1 | LL | impl AnotherTrait for T {} | -------------------------------- first implementation here LL | impl AnotherTrait for OpaqueType {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `OpaqueType` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation error: aborting due to 1 previous error diff --git a/tests/ui/traits/issue-105231.rs b/tests/ui/traits/issue-105231.rs index 7338642beef..83c3158c106 100644 --- a/tests/ui/traits/issue-105231.rs +++ b/tests/ui/traits/issue-105231.rs @@ -1,4 +1,3 @@ -//~ ERROR overflow evaluating the requirement `A>>>>>>: Send` struct A(B); //~^ ERROR recursive types `A` and `B` have infinite size //~| ERROR `T` is only used recursively @@ -7,5 +6,5 @@ struct B(A>); trait Foo {} impl Foo for T where T: Send {} impl Foo for B {} - +//~^ ERROR conflicting implementations of trait `Foo` for type `B` fn main() {} diff --git a/tests/ui/traits/issue-105231.stderr b/tests/ui/traits/issue-105231.stderr index d3014a79ad6..e113f8382b2 100644 --- a/tests/ui/traits/issue-105231.stderr +++ b/tests/ui/traits/issue-105231.stderr @@ -1,5 +1,5 @@ error[E0072]: recursive types `A` and `B` have infinite size - --> $DIR/issue-105231.rs:2:1 + --> $DIR/issue-105231.rs:1:1 | LL | struct A(B); | ^^^^^^^^^^^ ---- recursive without indirection @@ -16,7 +16,7 @@ LL ~ struct B(Box>>); | error: type parameter `T` is only used recursively - --> $DIR/issue-105231.rs:2:15 + --> $DIR/issue-105231.rs:1:15 | LL | struct A(B); | - ^ @@ -27,7 +27,7 @@ LL | struct A(B); = note: all type parameters must be used in a non-recursive way in order to constrain their variance error: type parameter `T` is only used recursively - --> $DIR/issue-105231.rs:5:17 + --> $DIR/issue-105231.rs:4:17 | LL | struct B(A>); | - ^ @@ -37,16 +37,18 @@ LL | struct B(A>); = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` = note: all type parameters must be used in a non-recursive way in order to constrain their variance -error[E0275]: overflow evaluating the requirement `A>>>>>>: Send` +error[E0119]: conflicting implementations of trait `Foo` for type `B` + --> $DIR/issue-105231.rs:8:1 | +LL | impl Foo for T where T: Send {} + | ------------------------------- first implementation here +LL | impl Foo for B {} + | ^^^^^^^^^^^^^^^^^^ conflicting implementation for `B` + | + = note: overflow evaluating the requirement `B: Send` = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_105231`) -note: required because it appears within the type `B>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` - --> $DIR/issue-105231.rs:5:8 - | -LL | struct B(A>); - | ^ error: aborting due to 4 previous errors -Some errors have detailed explanations: E0072, E0275. +Some errors have detailed explanations: E0072, E0119. For more information about an error, try `rustc --explain E0072`. diff --git a/tests/ui/traits/next-solver/coherence/issue-102048.rs b/tests/ui/traits/next-solver/coherence/issue-102048.rs index 16ae5d98488..847816eba12 100644 --- a/tests/ui/traits/next-solver/coherence/issue-102048.rs +++ b/tests/ui/traits/next-solver/coherence/issue-102048.rs @@ -1,7 +1,7 @@ // This must fail coherence. // // Getting this to pass was fairly difficult, so here's an explanation -// of what's happening: +// of what was previously happening for this to compile: // // Normalizing projections currently tries to replace them with inference variables // while emitting a nested `Projection` obligation. This cannot be done if the projection @@ -17,12 +17,6 @@ // that to `i32`. We then try to unify `i32` from `impl1` with `u32` from `impl2` which fails, // causing coherence to consider these two impls distinct. -//@ revisions: classic next -//@[next] compile-flags: -Znext-solver - -//@[classic] known-bug: #102048 -//@[classic] check-pass - pub trait Trait {} pub trait WithAssoc1<'a> { @@ -42,7 +36,7 @@ where // impl 2 impl Trait fn(>::Assoc, u32)> for (T, U) where - U: for<'a> WithAssoc1<'a> //[next]~^ ERROR conflicting implementations of trait + U: for<'a> WithAssoc1<'a> //~^ ERROR conflicting implementations of trait { } diff --git a/tests/ui/traits/next-solver/coherence/issue-102048.stderr b/tests/ui/traits/next-solver/coherence/issue-102048.stderr new file mode 100644 index 00000000000..e496517464b --- /dev/null +++ b/tests/ui/traits/next-solver/coherence/issue-102048.stderr @@ -0,0 +1,16 @@ +error[E0119]: conflicting implementations of trait `Trait fn(<_ as WithAssoc1<'a>>::Assoc, <_ as WithAssoc2<'a>>::Assoc)>` for type `(_, _)` + --> $DIR/issue-102048.rs:38:1 + | +LL | / impl Trait fn(>::Assoc, >::Assoc)> for (T, U) +LL | | where +LL | | T: for<'a> WithAssoc1<'a> + for<'a> WithAssoc2<'a, Assoc = i32>, +LL | | U: for<'a> WithAssoc2<'a>, + | |______________________________- first implementation here +... +LL | / impl Trait fn(>::Assoc, u32)> for (T, U) where +LL | | U: for<'a> WithAssoc1<'a> + | |_____________________________^ conflicting implementation for `(_, _)` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.rs b/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.rs index d37943b929a..43443be88df 100644 --- a/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.rs +++ b/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.rs @@ -1,4 +1,3 @@ -//~ ERROR overflow // A regression test for #111729 checking that we correctly // track recursion depth for obligations returned by confirmation. use std::panic::RefUnwindSafe; @@ -18,6 +17,7 @@ impl Database for T { type Storage = SalsaStorage; } impl Database for RootDatabase { + //~^ ERROR conflicting implementations of trait `Database` for type `RootDatabase` type Storage = SalsaStorage; } diff --git a/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.stderr b/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.stderr index 2ab150fc0f6..1da7671b451 100644 --- a/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.stderr +++ b/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.stderr @@ -1,24 +1,12 @@ -error[E0275]: overflow evaluating the requirement `Runtime: RefUnwindSafe` - | - = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`cycle_via_builtin_auto_trait_impl`) -note: required because it appears within the type `RootDatabase` - --> $DIR/cycle-via-builtin-auto-trait-impl.rs:13:8 - | -LL | struct RootDatabase { - | ^^^^^^^^^^^^ -note: required for `RootDatabase` to implement `Database` - --> $DIR/cycle-via-builtin-auto-trait-impl.rs:17:24 +error[E0119]: conflicting implementations of trait `Database` for type `RootDatabase` + --> $DIR/cycle-via-builtin-auto-trait-impl.rs:19:1 | LL | impl Database for T { - | ------------- ^^^^^^^^ ^ - | | - | unsatisfied trait bound introduced here -note: required because it appears within the type `Runtime` - --> $DIR/cycle-via-builtin-auto-trait-impl.rs:24:8 - | -LL | struct Runtime { - | ^^^^^^^ + | ------------------------------------- first implementation here +... +LL | impl Database for RootDatabase { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `RootDatabase` error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0275`. +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/type-alias-impl-trait/impl_trait_for_same_tait.stderr b/tests/ui/type-alias-impl-trait/impl_trait_for_same_tait.stderr index e35913be899..aaf75cc3db9 100644 --- a/tests/ui/type-alias-impl-trait/impl_trait_for_same_tait.stderr +++ b/tests/ui/type-alias-impl-trait/impl_trait_for_same_tait.stderr @@ -15,8 +15,6 @@ LL | impl Bop for Bar<()> {} ... LL | impl Bop for Barr {} | ^^^^^^^^^^^^^^^^^ conflicting implementation for `Bar<()>` - | - = note: upstream crates may add a new impl of trait `std::marker::FnPtr` for type `Barr` in future versions error[E0119]: conflicting implementations of trait `Bop` for type `Bar<()>` --> $DIR/impl_trait_for_same_tait.rs:30:1 diff --git a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check.error.stderr b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check.error.stderr index a97227e481e..49997b073c9 100644 --- a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check.error.stderr +++ b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check.error.stderr @@ -1,11 +1,11 @@ -error[E0119]: conflicting implementations of trait `Yay` for type `Alias` +error[E0119]: conflicting implementations of trait `Yay` for type `<() as HideIt>::Assoc` --> $DIR/implied_lifetime_wf_check.rs:26:1 | LL | impl Yay for <() as HideIt>::Assoc {} | ---------------------------------- first implementation here LL | #[cfg(error)] LL | impl Yay for i32 {} - | ^^^^^^^^^^^^^^^^ conflicting implementation for `Alias` + | ^^^^^^^^^^^^^^^^ conflicting implementation for `<() as HideIt>::Assoc` error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/issue-104817.rs b/tests/ui/type-alias-impl-trait/issue-104817.rs index 4679d025fce..49146321614 100644 --- a/tests/ui/type-alias-impl-trait/issue-104817.rs +++ b/tests/ui/type-alias-impl-trait/issue-104817.rs @@ -14,6 +14,6 @@ fn mk_opaque() -> OpaqueType { trait AnotherTrait {} impl AnotherTrait for T {} impl AnotherTrait for OpaqueType {} -//[stock]~^ conflicting implementations of trait `AnotherTrait` for type `OpaqueType` +//[stock]~^ conflicting implementations of trait `AnotherTrait` fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-104817.stock.stderr b/tests/ui/type-alias-impl-trait/issue-104817.stock.stderr index 41c5206d9e8..df5a6c320a8 100644 --- a/tests/ui/type-alias-impl-trait/issue-104817.stock.stderr +++ b/tests/ui/type-alias-impl-trait/issue-104817.stock.stderr @@ -1,10 +1,10 @@ -error[E0119]: conflicting implementations of trait `AnotherTrait` for type `OpaqueType` +error[E0119]: conflicting implementations of trait `AnotherTrait` --> $DIR/issue-104817.rs:16:1 | LL | impl AnotherTrait for T {} | -------------------------------- first implementation here LL | impl AnotherTrait for OpaqueType {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `OpaqueType` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation error: aborting due to 1 previous error From d3f982d46601c559c7f6ffd7155fcedfc1afc5e1 Mon Sep 17 00:00:00 2001 From: lcnr Date: Sat, 21 Sep 2024 07:04:42 +0000 Subject: [PATCH 314/357] rebase and update fixed `crashes` --- tests/crashes/118987.rs | 17 ------------ .../default-impl-normalization-ambig-2.rs} | 4 ++- .../default-impl-normalization-ambig-2.stderr | 21 +++++++++++++++ .../default-item-normalization-ambig-1.rs} | 5 ++-- .../default-item-normalization-ambig-1.stderr | 21 +++++++++++++++ .../coherence-bikeshed-intrinsic-from.rs} | 4 ++- .../coherence-bikeshed-intrinsic-from.stderr | 27 +++++++++++++++++++ 7 files changed, 78 insertions(+), 21 deletions(-) delete mode 100644 tests/crashes/118987.rs rename tests/{crashes/118987-2.rs => ui/specialization/coherence/default-impl-normalization-ambig-2.rs} (74%) create mode 100644 tests/ui/specialization/coherence/default-impl-normalization-ambig-2.stderr rename tests/{crashes/74299.rs => ui/specialization/coherence/default-item-normalization-ambig-1.rs} (56%) create mode 100644 tests/ui/specialization/coherence/default-item-normalization-ambig-1.stderr rename tests/{crashes/124207.rs => ui/transmutability/malformed-program-gracefulness/coherence-bikeshed-intrinsic-from.rs} (62%) create mode 100644 tests/ui/transmutability/malformed-program-gracefulness/coherence-bikeshed-intrinsic-from.stderr diff --git a/tests/crashes/118987.rs b/tests/crashes/118987.rs deleted file mode 100644 index 4382a7bcb63..00000000000 --- a/tests/crashes/118987.rs +++ /dev/null @@ -1,17 +0,0 @@ -//@ known-bug: #118987 -#![feature(specialization)] //~ WARN the feature `specialization` is incomplete - -trait Assoc { - type Output; -} - -default impl Assoc for T { - type Output = bool; -} - -impl Assoc for u8 {} - -trait Foo {} - -impl Foo for ::Output {} -impl Foo for ::Output {} diff --git a/tests/crashes/118987-2.rs b/tests/ui/specialization/coherence/default-impl-normalization-ambig-2.rs similarity index 74% rename from tests/crashes/118987-2.rs rename to tests/ui/specialization/coherence/default-impl-normalization-ambig-2.rs index 4382a7bcb63..1691530fa0a 100644 --- a/tests/crashes/118987-2.rs +++ b/tests/ui/specialization/coherence/default-impl-normalization-ambig-2.rs @@ -1,4 +1,4 @@ -//@ known-bug: #118987 +// regression test for #118987 #![feature(specialization)] //~ WARN the feature `specialization` is incomplete trait Assoc { @@ -15,3 +15,5 @@ trait Foo {} impl Foo for ::Output {} impl Foo for ::Output {} +//~^ ERROR the trait bound `u16: Assoc` is not satisfied +fn main() {} diff --git a/tests/ui/specialization/coherence/default-impl-normalization-ambig-2.stderr b/tests/ui/specialization/coherence/default-impl-normalization-ambig-2.stderr new file mode 100644 index 00000000000..a2fca2ef5b6 --- /dev/null +++ b/tests/ui/specialization/coherence/default-impl-normalization-ambig-2.stderr @@ -0,0 +1,21 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/default-impl-normalization-ambig-2.rs:2:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0277]: the trait bound `u16: Assoc` is not satisfied + --> $DIR/default-impl-normalization-ambig-2.rs:17:14 + | +LL | impl Foo for ::Output {} + | ^^^^^^^^^^^^^^^^^^^^^^ the trait `Assoc` is not implemented for `u16` + | + = help: the trait `Assoc` is implemented for `u8` + +error: aborting due to 1 previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/crashes/74299.rs b/tests/ui/specialization/coherence/default-item-normalization-ambig-1.rs similarity index 56% rename from tests/crashes/74299.rs rename to tests/ui/specialization/coherence/default-item-normalization-ambig-1.rs index 0e2ddce1c5b..af7cf332d5f 100644 --- a/tests/crashes/74299.rs +++ b/tests/ui/specialization/coherence/default-item-normalization-ambig-1.rs @@ -1,5 +1,5 @@ -//@ known-bug: #74299 -#![feature(specialization)] +// regression test for #73299. +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete trait X { type U; @@ -18,6 +18,7 @@ trait Y { impl Y for <() as X>::U {} impl Y for ::U {} +//~^ ERROR conflicting implementations of trait `Y` for type `<() as X>::U` fn main() { ().f().g(); diff --git a/tests/ui/specialization/coherence/default-item-normalization-ambig-1.stderr b/tests/ui/specialization/coherence/default-item-normalization-ambig-1.stderr new file mode 100644 index 00000000000..a15151cc9c4 --- /dev/null +++ b/tests/ui/specialization/coherence/default-item-normalization-ambig-1.stderr @@ -0,0 +1,21 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/default-item-normalization-ambig-1.rs:2:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0119]: conflicting implementations of trait `Y` for type `<() as X>::U` + --> $DIR/default-item-normalization-ambig-1.rs:20:1 + | +LL | impl Y for <() as X>::U {} + | ----------------------- first implementation here +LL | impl Y for ::U {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `<() as X>::U` + +error: aborting due to 1 previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/crashes/124207.rs b/tests/ui/transmutability/malformed-program-gracefulness/coherence-bikeshed-intrinsic-from.rs similarity index 62% rename from tests/crashes/124207.rs rename to tests/ui/transmutability/malformed-program-gracefulness/coherence-bikeshed-intrinsic-from.rs index a11eedb140a..0cebc99cd41 100644 --- a/tests/crashes/124207.rs +++ b/tests/ui/transmutability/malformed-program-gracefulness/coherence-bikeshed-intrinsic-from.rs @@ -1,9 +1,11 @@ -//@ known-bug: #124207 #![feature(transmutability)] #![feature(type_alias_impl_trait)] trait OpaqueTrait {} type OpaqueType = impl OpaqueTrait; +//~^ ERROR unconstrained opaque type trait AnotherTrait {} impl> AnotherTrait for T {} +//~^ ERROR type provided when a constant was expected impl AnotherTrait for OpaqueType {} +//~^ ERROR conflicting implementations of trait `AnotherTrait` pub fn main() {} diff --git a/tests/ui/transmutability/malformed-program-gracefulness/coherence-bikeshed-intrinsic-from.stderr b/tests/ui/transmutability/malformed-program-gracefulness/coherence-bikeshed-intrinsic-from.stderr new file mode 100644 index 00000000000..2424541af23 --- /dev/null +++ b/tests/ui/transmutability/malformed-program-gracefulness/coherence-bikeshed-intrinsic-from.stderr @@ -0,0 +1,27 @@ +error: unconstrained opaque type + --> $DIR/coherence-bikeshed-intrinsic-from.rs:4:19 + | +LL | type OpaqueType = impl OpaqueTrait; + | ^^^^^^^^^^^^^^^^ + | + = note: `OpaqueType` must be used in combination with a concrete type within the same module + +error[E0747]: type provided when a constant was expected + --> $DIR/coherence-bikeshed-intrinsic-from.rs:7:37 + | +LL | impl> AnotherTrait for T {} + | ^^ + +error[E0119]: conflicting implementations of trait `AnotherTrait` + --> $DIR/coherence-bikeshed-intrinsic-from.rs:9:1 + | +LL | impl> AnotherTrait for T {} + | ----------------------------------------------------------- first implementation here +LL | +LL | impl AnotherTrait for OpaqueType {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0119, E0747. +For more information about an error, try `rustc --explain E0119`. From 7aeb07a58326e9c2f1876de62877bd95a04ec35b Mon Sep 17 00:00:00 2001 From: lcnr Date: Sat, 21 Sep 2024 07:05:19 +0000 Subject: [PATCH 315/357] remove unnecessary revisions --- ...nce-overlap-downstream-inherent.old.stderr | 23 ------------------- .../coherence-overlap-downstream-inherent.rs | 3 --- ...erence-overlap-downstream-inherent.stderr} | 4 ++-- .../coherence-overlap-downstream.old.stderr | 21 ----------------- .../coherence/coherence-overlap-downstream.rs | 3 --- ...rr => coherence-overlap-downstream.stderr} | 4 ++-- ...ce-overlap-issue-23516-inherent.old.stderr | 14 ----------- .../coherence-overlap-issue-23516-inherent.rs | 3 --- ...rence-overlap-issue-23516-inherent.stderr} | 2 +- .../coherence-overlap-issue-23516.old.stderr | 13 ----------- .../coherence-overlap-issue-23516.rs | 3 --- ...r => coherence-overlap-issue-23516.stderr} | 2 +- ...ap-unnormalizable-projection-0.next.stderr | 18 --------------- ...nce-overlap-unnormalizable-projection-0.rs | 3 --- ...verlap-unnormalizable-projection-0.stderr} | 2 +- ...ap-unnormalizable-projection-1.next.stderr | 19 --------------- ...nce-overlap-unnormalizable-projection-1.rs | 3 --- ...verlap-unnormalizable-projection-1.stderr} | 2 +- tests/ui/coherence/coherent-due-to-fulfill.rs | 2 -- .../incoherent-even-though-we-fulfill.rs | 2 -- .../incoherent-even-though-we-fulfill.stderr | 2 +- ...er-crate-ambiguity-causes-notes.old.stderr | 17 -------------- .../inter-crate-ambiguity-causes-notes.rs | 3 --- ...inter-crate-ambiguity-causes-notes.stderr} | 2 +- .../normalize-for-errors.current.stderr | 15 ------------ .../normalize-for-errors.next.stderr | 15 ------------ .../occurs-check/associated-type.next.stderr | 4 ++-- .../occurs-check/associated-type.old.stderr | 2 +- .../coherence/occurs-check/associated-type.rs | 1 + .../occurs-check/opaques.current.stderr | 2 +- .../occurs-check/opaques.next.stderr | 4 ++-- tests/ui/coherence/occurs-check/opaques.rs | 3 ++- ...heck-opaque-types-not-covering.next.stderr | 21 ----------------- .../orphan-check-opaque-types-not-covering.rs | 3 --- ...an-check-opaque-types-not-covering.stderr} | 4 ++-- .../orphan-check-projections-covering.rs | 3 --- ...heck-weak-aliases-not-covering.next.stderr | 12 ---------- .../orphan-check-weak-aliases-not-covering.rs | 3 --- ...an-check-weak-aliases-not-covering.stderr} | 2 +- ...reporting-if-references-err.current.stderr | 14 ----------- ...ip-reporting-if-references-err.next.stderr | 14 ----------- .../super-traits/super-trait-knowable-2.rs | 3 --- .../coherence-bikeshed-intrinsic-from.stderr | 16 ++++++------- 43 files changed, 30 insertions(+), 281 deletions(-) delete mode 100644 tests/ui/coherence/coherence-overlap-downstream-inherent.old.stderr rename tests/ui/coherence/{coherence-overlap-downstream-inherent.next.stderr => coherence-overlap-downstream-inherent.stderr} (87%) delete mode 100644 tests/ui/coherence/coherence-overlap-downstream.old.stderr rename tests/ui/coherence/{coherence-overlap-downstream.next.stderr => coherence-overlap-downstream.stderr} (88%) delete mode 100644 tests/ui/coherence/coherence-overlap-issue-23516-inherent.old.stderr rename tests/ui/coherence/{coherence-overlap-issue-23516-inherent.next.stderr => coherence-overlap-issue-23516-inherent.stderr} (90%) delete mode 100644 tests/ui/coherence/coherence-overlap-issue-23516.old.stderr rename tests/ui/coherence/{coherence-overlap-issue-23516.next.stderr => coherence-overlap-issue-23516.stderr} (90%) delete mode 100644 tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.next.stderr rename tests/ui/coherence/{coherence-overlap-unnormalizable-projection-0.classic.stderr => coherence-overlap-unnormalizable-projection-0.stderr} (91%) delete mode 100644 tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.next.stderr rename tests/ui/coherence/{coherence-overlap-unnormalizable-projection-1.classic.stderr => coherence-overlap-unnormalizable-projection-1.stderr} (92%) delete mode 100644 tests/ui/coherence/inter-crate-ambiguity-causes-notes.old.stderr rename tests/ui/coherence/{inter-crate-ambiguity-causes-notes.next.stderr => inter-crate-ambiguity-causes-notes.stderr} (90%) delete mode 100644 tests/ui/coherence/normalize-for-errors.current.stderr delete mode 100644 tests/ui/coherence/normalize-for-errors.next.stderr delete mode 100644 tests/ui/coherence/orphan-check-opaque-types-not-covering.next.stderr rename tests/ui/coherence/{orphan-check-opaque-types-not-covering.classic.stderr => orphan-check-opaque-types-not-covering.stderr} (92%) delete mode 100644 tests/ui/coherence/orphan-check-weak-aliases-not-covering.next.stderr rename tests/ui/coherence/{orphan-check-weak-aliases-not-covering.classic.stderr => orphan-check-weak-aliases-not-covering.stderr} (92%) delete mode 100644 tests/ui/coherence/skip-reporting-if-references-err.current.stderr delete mode 100644 tests/ui/coherence/skip-reporting-if-references-err.next.stderr diff --git a/tests/ui/coherence/coherence-overlap-downstream-inherent.old.stderr b/tests/ui/coherence/coherence-overlap-downstream-inherent.old.stderr deleted file mode 100644 index 2938bc629b2..00000000000 --- a/tests/ui/coherence/coherence-overlap-downstream-inherent.old.stderr +++ /dev/null @@ -1,23 +0,0 @@ -error[E0592]: duplicate definitions with name `dummy` - --> $DIR/coherence-overlap-downstream-inherent.rs:10:26 - | -LL | impl Sweet { fn dummy(&self) { } } - | ^^^^^^^^^^^^^^^ duplicate definitions for `dummy` -LL | -LL | impl Sweet { fn dummy(&self) { } } - | --------------- other definition for `dummy` - -error[E0592]: duplicate definitions with name `f` - --> $DIR/coherence-overlap-downstream-inherent.rs:16:38 - | -LL | impl A where T: Bar { fn f(&self) {} } - | ^^^^^^^^^^^ duplicate definitions for `f` -LL | -LL | impl A { fn f(&self) {} } - | ----------- other definition for `f` - | - = note: downstream crates may implement trait `Bar<_>` for type `i32` - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0592`. diff --git a/tests/ui/coherence/coherence-overlap-downstream-inherent.rs b/tests/ui/coherence/coherence-overlap-downstream-inherent.rs index 3e90b7c7fdd..5dea33e330b 100644 --- a/tests/ui/coherence/coherence-overlap-downstream-inherent.rs +++ b/tests/ui/coherence/coherence-overlap-downstream-inherent.rs @@ -1,6 +1,3 @@ -//@ revisions: old next -//@[next] compile-flags: -Znext-solver - // Tests that we consider `T: Sugar + Fruit` to be ambiguous, even // though no impls are found. diff --git a/tests/ui/coherence/coherence-overlap-downstream-inherent.next.stderr b/tests/ui/coherence/coherence-overlap-downstream-inherent.stderr similarity index 87% rename from tests/ui/coherence/coherence-overlap-downstream-inherent.next.stderr rename to tests/ui/coherence/coherence-overlap-downstream-inherent.stderr index 2938bc629b2..bbce4b530b4 100644 --- a/tests/ui/coherence/coherence-overlap-downstream-inherent.next.stderr +++ b/tests/ui/coherence/coherence-overlap-downstream-inherent.stderr @@ -1,5 +1,5 @@ error[E0592]: duplicate definitions with name `dummy` - --> $DIR/coherence-overlap-downstream-inherent.rs:10:26 + --> $DIR/coherence-overlap-downstream-inherent.rs:7:26 | LL | impl Sweet { fn dummy(&self) { } } | ^^^^^^^^^^^^^^^ duplicate definitions for `dummy` @@ -8,7 +8,7 @@ LL | impl Sweet { fn dummy(&self) { } } | --------------- other definition for `dummy` error[E0592]: duplicate definitions with name `f` - --> $DIR/coherence-overlap-downstream-inherent.rs:16:38 + --> $DIR/coherence-overlap-downstream-inherent.rs:13:38 | LL | impl A where T: Bar { fn f(&self) {} } | ^^^^^^^^^^^ duplicate definitions for `f` diff --git a/tests/ui/coherence/coherence-overlap-downstream.old.stderr b/tests/ui/coherence/coherence-overlap-downstream.old.stderr deleted file mode 100644 index 6c2e9466b4b..00000000000 --- a/tests/ui/coherence/coherence-overlap-downstream.old.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error[E0119]: conflicting implementations of trait `Sweet` - --> $DIR/coherence-overlap-downstream.rs:11:1 - | -LL | impl Sweet for T { } - | ------------------------- first implementation here -LL | impl Sweet for T { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation - -error[E0119]: conflicting implementations of trait `Foo<_>` for type `i32` - --> $DIR/coherence-overlap-downstream.rs:17:1 - | -LL | impl Foo for T where T: Bar {} - | --------------------------------------- first implementation here -LL | impl Foo for i32 {} - | ^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `i32` - | - = note: downstream crates may implement trait `Bar<_>` for type `i32` - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-overlap-downstream.rs b/tests/ui/coherence/coherence-overlap-downstream.rs index 8b99296d12a..738ec0e3d45 100644 --- a/tests/ui/coherence/coherence-overlap-downstream.rs +++ b/tests/ui/coherence/coherence-overlap-downstream.rs @@ -1,6 +1,3 @@ -//@ revisions: old next -//@[next] compile-flags: -Znext-solver - // Tests that we consider `T: Sugar + Fruit` to be ambiguous, even // though no impls are found. diff --git a/tests/ui/coherence/coherence-overlap-downstream.next.stderr b/tests/ui/coherence/coherence-overlap-downstream.stderr similarity index 88% rename from tests/ui/coherence/coherence-overlap-downstream.next.stderr rename to tests/ui/coherence/coherence-overlap-downstream.stderr index 6c2e9466b4b..9ab099489d9 100644 --- a/tests/ui/coherence/coherence-overlap-downstream.next.stderr +++ b/tests/ui/coherence/coherence-overlap-downstream.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Sweet` - --> $DIR/coherence-overlap-downstream.rs:11:1 + --> $DIR/coherence-overlap-downstream.rs:8:1 | LL | impl Sweet for T { } | ------------------------- first implementation here @@ -7,7 +7,7 @@ LL | impl Sweet for T { } | ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation error[E0119]: conflicting implementations of trait `Foo<_>` for type `i32` - --> $DIR/coherence-overlap-downstream.rs:17:1 + --> $DIR/coherence-overlap-downstream.rs:14:1 | LL | impl Foo for T where T: Bar {} | --------------------------------------- first implementation here diff --git a/tests/ui/coherence/coherence-overlap-issue-23516-inherent.old.stderr b/tests/ui/coherence/coherence-overlap-issue-23516-inherent.old.stderr deleted file mode 100644 index 2f3ad627808..00000000000 --- a/tests/ui/coherence/coherence-overlap-issue-23516-inherent.old.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error[E0592]: duplicate definitions with name `dummy` - --> $DIR/coherence-overlap-issue-23516-inherent.rs:12:25 - | -LL | impl Cake { fn dummy(&self) { } } - | ^^^^^^^^^^^^^^^ duplicate definitions for `dummy` -LL | -LL | impl Cake> { fn dummy(&self) { } } - | --------------- other definition for `dummy` - | - = note: downstream crates may implement trait `Sugar` for type `std::boxed::Box<_>` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0592`. diff --git a/tests/ui/coherence/coherence-overlap-issue-23516-inherent.rs b/tests/ui/coherence/coherence-overlap-issue-23516-inherent.rs index 53b0a40fa66..a272e620fca 100644 --- a/tests/ui/coherence/coherence-overlap-issue-23516-inherent.rs +++ b/tests/ui/coherence/coherence-overlap-issue-23516-inherent.rs @@ -1,6 +1,3 @@ -//@ revisions: old next -//@[next] compile-flags: -Znext-solver - // Tests that we consider `Box: !Sugar` to be ambiguous, even // though we see no impl of `Sugar` for `Box`. Therefore, an overlap // error is reported for the following pair of impls (#23516). diff --git a/tests/ui/coherence/coherence-overlap-issue-23516-inherent.next.stderr b/tests/ui/coherence/coherence-overlap-issue-23516-inherent.stderr similarity index 90% rename from tests/ui/coherence/coherence-overlap-issue-23516-inherent.next.stderr rename to tests/ui/coherence/coherence-overlap-issue-23516-inherent.stderr index 2f3ad627808..aacdeb5b0f9 100644 --- a/tests/ui/coherence/coherence-overlap-issue-23516-inherent.next.stderr +++ b/tests/ui/coherence/coherence-overlap-issue-23516-inherent.stderr @@ -1,5 +1,5 @@ error[E0592]: duplicate definitions with name `dummy` - --> $DIR/coherence-overlap-issue-23516-inherent.rs:12:25 + --> $DIR/coherence-overlap-issue-23516-inherent.rs:9:25 | LL | impl Cake { fn dummy(&self) { } } | ^^^^^^^^^^^^^^^ duplicate definitions for `dummy` diff --git a/tests/ui/coherence/coherence-overlap-issue-23516.old.stderr b/tests/ui/coherence/coherence-overlap-issue-23516.old.stderr deleted file mode 100644 index b9494774025..00000000000 --- a/tests/ui/coherence/coherence-overlap-issue-23516.old.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error[E0119]: conflicting implementations of trait `Sweet` for type `Box<_>` - --> $DIR/coherence-overlap-issue-23516.rs:11:1 - | -LL | impl Sweet for T { } - | ------------------------- first implementation here -LL | impl Sweet for Box { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Box<_>` - | - = note: downstream crates may implement trait `Sugar` for type `std::boxed::Box<_>` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-overlap-issue-23516.rs b/tests/ui/coherence/coherence-overlap-issue-23516.rs index 620e00cd057..63e42e8f412 100644 --- a/tests/ui/coherence/coherence-overlap-issue-23516.rs +++ b/tests/ui/coherence/coherence-overlap-issue-23516.rs @@ -1,6 +1,3 @@ -//@ revisions: old next -//@[next] compile-flags: -Znext-solver - // Tests that we consider `Box: !Sugar` to be ambiguous, even // though we see no impl of `Sugar` for `Box`. Therefore, an overlap // error is reported for the following pair of impls (#23516). diff --git a/tests/ui/coherence/coherence-overlap-issue-23516.next.stderr b/tests/ui/coherence/coherence-overlap-issue-23516.stderr similarity index 90% rename from tests/ui/coherence/coherence-overlap-issue-23516.next.stderr rename to tests/ui/coherence/coherence-overlap-issue-23516.stderr index b9494774025..7b1b240291a 100644 --- a/tests/ui/coherence/coherence-overlap-issue-23516.next.stderr +++ b/tests/ui/coherence/coherence-overlap-issue-23516.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Sweet` for type `Box<_>` - --> $DIR/coherence-overlap-issue-23516.rs:11:1 + --> $DIR/coherence-overlap-issue-23516.rs:8:1 | LL | impl Sweet for T { } | ------------------------- first implementation here diff --git a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.next.stderr b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.next.stderr deleted file mode 100644 index 99abdf65abd..00000000000 --- a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.next.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error[E0119]: conflicting implementations of trait `Trait` for type `Box<_>` - --> $DIR/coherence-overlap-unnormalizable-projection-0.rs:27:1 - | -LL | / impl Trait for T -LL | | where -LL | | T: 'static, -LL | | for<'a> T: WithAssoc<'a>, -LL | | for<'a> >::Assoc: WhereBound, - | |____________________________________________________- first implementation here -... -LL | impl Trait for Box {} - | ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Box<_>` - | - = note: downstream crates may implement trait `WithAssoc<'a>` for type `std::boxed::Box<_>` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.rs b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.rs index b8b6d8846ef..0695076e221 100644 --- a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.rs +++ b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.rs @@ -2,9 +2,6 @@ // "Coherence incorrectly considers `unnormalizable_projection: Trait` to not hold even if it could" #![crate_type = "lib"] -//@ revisions: classic next -//@[next] compile-flags: -Znext-solver - trait WhereBound {} impl WhereBound for () {} diff --git a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.classic.stderr b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.stderr similarity index 91% rename from tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.classic.stderr rename to tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.stderr index 99abdf65abd..57befbe6e68 100644 --- a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.classic.stderr +++ b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Trait` for type `Box<_>` - --> $DIR/coherence-overlap-unnormalizable-projection-0.rs:27:1 + --> $DIR/coherence-overlap-unnormalizable-projection-0.rs:24:1 | LL | / impl Trait for T LL | | where diff --git a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.next.stderr b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.next.stderr deleted file mode 100644 index 781ab0fcbf7..00000000000 --- a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.next.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error[E0119]: conflicting implementations of trait `Trait` for type `Box<_>` - --> $DIR/coherence-overlap-unnormalizable-projection-1.rs:26:1 - | -LL | / impl Trait for T -LL | | where -LL | | T: 'static, -LL | | for<'a> T: WithAssoc<'a>, -LL | | for<'a> Box<>::Assoc>: WhereBound, - | |_________________________________________________________- first implementation here -... -LL | impl Trait for Box {} - | ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Box<_>` - | - = note: downstream crates may implement trait `WithAssoc<'a>` for type `std::boxed::Box<_>` - = note: downstream crates may implement trait `WhereBound` for type `std::boxed::Box<_>` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.rs b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.rs index 8eeadb3dc75..f5fb5aefb5c 100644 --- a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.rs +++ b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.rs @@ -2,9 +2,6 @@ // "Coherence incorrectly considers `unnormalizable_projection: Trait` to not hold even if it could" #![crate_type = "lib"] -//@ revisions: classic next -//@[next] compile-flags: -Znext-solver - pub trait WhereBound {} impl WhereBound for () {} diff --git a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.classic.stderr b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.stderr similarity index 92% rename from tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.classic.stderr rename to tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.stderr index 781ab0fcbf7..22673cef640 100644 --- a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.classic.stderr +++ b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Trait` for type `Box<_>` - --> $DIR/coherence-overlap-unnormalizable-projection-1.rs:26:1 + --> $DIR/coherence-overlap-unnormalizable-projection-1.rs:23:1 | LL | / impl Trait for T LL | | where diff --git a/tests/ui/coherence/coherent-due-to-fulfill.rs b/tests/ui/coherence/coherent-due-to-fulfill.rs index 084f9be0a8c..f4555ee5171 100644 --- a/tests/ui/coherence/coherent-due-to-fulfill.rs +++ b/tests/ui/coherence/coherent-due-to-fulfill.rs @@ -1,6 +1,4 @@ -//@ compile-flags: -Znext-solver=coherence //@ check-pass - trait Mirror { type Assoc; } diff --git a/tests/ui/coherence/incoherent-even-though-we-fulfill.rs b/tests/ui/coherence/incoherent-even-though-we-fulfill.rs index b3c9cf328c2..28e5b6d3db0 100644 --- a/tests/ui/coherence/incoherent-even-though-we-fulfill.rs +++ b/tests/ui/coherence/incoherent-even-though-we-fulfill.rs @@ -1,5 +1,3 @@ -//@ compile-flags: -Znext-solver=coherence - trait Mirror { type Assoc; } diff --git a/tests/ui/coherence/incoherent-even-though-we-fulfill.stderr b/tests/ui/coherence/incoherent-even-though-we-fulfill.stderr index b16465d2011..0b15a4e100e 100644 --- a/tests/ui/coherence/incoherent-even-though-we-fulfill.stderr +++ b/tests/ui/coherence/incoherent-even-though-we-fulfill.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Foo` for type `()` - --> $DIR/incoherent-even-though-we-fulfill.rs:17:1 + --> $DIR/incoherent-even-though-we-fulfill.rs:15:1 | LL | impl Foo for T where (): Mirror {} | --------------------------------------------- first implementation here diff --git a/tests/ui/coherence/inter-crate-ambiguity-causes-notes.old.stderr b/tests/ui/coherence/inter-crate-ambiguity-causes-notes.old.stderr deleted file mode 100644 index 74be598c44c..00000000000 --- a/tests/ui/coherence/inter-crate-ambiguity-causes-notes.old.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error[E0119]: conflicting implementations of trait `From<()>` for type `S` - --> $DIR/inter-crate-ambiguity-causes-notes.rs:12:1 - | -LL | impl From<()> for S { - | ------------------- first implementation here -... -LL | / impl From for S -LL | | -LL | | where -LL | | I: Iterator, - | |___________________________^ conflicting implementation for `S` - | - = note: upstream crates may add a new impl of trait `std::iter::Iterator` for type `()` in future versions - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/inter-crate-ambiguity-causes-notes.rs b/tests/ui/coherence/inter-crate-ambiguity-causes-notes.rs index 3dead2f0d19..5b11c78ab26 100644 --- a/tests/ui/coherence/inter-crate-ambiguity-causes-notes.rs +++ b/tests/ui/coherence/inter-crate-ambiguity-causes-notes.rs @@ -1,6 +1,3 @@ -//@ revisions: old next -//@[next] compile-flags: -Znext-solver - struct S; impl From<()> for S { diff --git a/tests/ui/coherence/inter-crate-ambiguity-causes-notes.next.stderr b/tests/ui/coherence/inter-crate-ambiguity-causes-notes.stderr similarity index 90% rename from tests/ui/coherence/inter-crate-ambiguity-causes-notes.next.stderr rename to tests/ui/coherence/inter-crate-ambiguity-causes-notes.stderr index 74be598c44c..b32283274c6 100644 --- a/tests/ui/coherence/inter-crate-ambiguity-causes-notes.next.stderr +++ b/tests/ui/coherence/inter-crate-ambiguity-causes-notes.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `From<()>` for type `S` - --> $DIR/inter-crate-ambiguity-causes-notes.rs:12:1 + --> $DIR/inter-crate-ambiguity-causes-notes.rs:9:1 | LL | impl From<()> for S { | ------------------- first implementation here diff --git a/tests/ui/coherence/normalize-for-errors.current.stderr b/tests/ui/coherence/normalize-for-errors.current.stderr deleted file mode 100644 index 634a10b7a14..00000000000 --- a/tests/ui/coherence/normalize-for-errors.current.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error[E0119]: conflicting implementations of trait `MyTrait<_>` for type `(Box<(MyType,)>, <_ as Iterator>::Item)` - --> $DIR/normalize-for-errors.rs:17:1 - | -LL | impl MyTrait for (T, S::Item) {} - | ------------------------------------------------------ first implementation here -LL | -LL | impl MyTrait for (Box<<(MyType,) as Mirror>::Assoc>, S::Item) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(Box<(MyType,)>, <_ as Iterator>::Item)` - | - = note: upstream crates may add a new impl of trait `std::clone::Clone` for type `(MyType,)` in future versions - = note: upstream crates may add a new impl of trait `std::marker::Copy` for type `std::boxed::Box<(MyType,)>` in future versions - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/normalize-for-errors.next.stderr b/tests/ui/coherence/normalize-for-errors.next.stderr deleted file mode 100644 index 44952dc1944..00000000000 --- a/tests/ui/coherence/normalize-for-errors.next.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error[E0119]: conflicting implementations of trait `MyTrait<_>` for type `(Box<(MyType,)>, <_ as Iterator>::Item)` - --> $DIR/normalize-for-errors.rs:17:1 - | -LL | impl MyTrait for (T, S::Item) {} - | ------------------------------------------------------ first implementation here -LL | -LL | impl MyTrait for (Box<<(MyType,) as Mirror>::Assoc>, S::Item) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(Box<(MyType,)>, <_ as Iterator>::Item)` - | - = note: upstream crates may add a new impl of trait `std::clone::Clone` for type `std::boxed::Box<(MyType,)>` in future versions - = note: upstream crates may add a new impl of trait `std::marker::Copy` for type `std::boxed::Box<(MyType,)>` in future versions - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/occurs-check/associated-type.next.stderr b/tests/ui/coherence/occurs-check/associated-type.next.stderr index 9544bdbb468..466b991471e 100644 --- a/tests/ui/coherence/occurs-check/associated-type.next.stderr +++ b/tests/ui/coherence/occurs-check/associated-type.next.stderr @@ -3,7 +3,7 @@ WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. } WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. } error[E0119]: conflicting implementations of trait `Overlap fn(&'a (), ())>` for type `for<'a> fn(&'a (), ())` - --> $DIR/associated-type.rs:31:1 + --> $DIR/associated-type.rs:32:1 | LL | impl Overlap for T { | ------------------------ first implementation here @@ -17,7 +17,7 @@ LL | | for<'a> *const T: ToUnit<'a>, = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details error[E0284]: type annotations needed: cannot normalize ` fn(&'a (), ()) as Overlap fn(&'a (), ())>>::Assoc` - --> $DIR/associated-type.rs:44:59 + --> $DIR/associated-type.rs:45:59 | LL | foo:: fn(&'a (), ()), for<'a> fn(&'a (), ())>(3usize); | ^^^^^^ cannot normalize ` fn(&'a (), ()) as Overlap fn(&'a (), ())>>::Assoc` diff --git a/tests/ui/coherence/occurs-check/associated-type.old.stderr b/tests/ui/coherence/occurs-check/associated-type.old.stderr index 6a4c6fe54a8..1e0345f4ec0 100644 --- a/tests/ui/coherence/occurs-check/associated-type.old.stderr +++ b/tests/ui/coherence/occurs-check/associated-type.old.stderr @@ -3,7 +3,7 @@ WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. } WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. } error[E0119]: conflicting implementations of trait `Overlap fn(&'a (), ())>` for type `for<'a> fn(&'a (), ())` - --> $DIR/associated-type.rs:31:1 + --> $DIR/associated-type.rs:32:1 | LL | impl Overlap for T { | ------------------------ first implementation here diff --git a/tests/ui/coherence/occurs-check/associated-type.rs b/tests/ui/coherence/occurs-check/associated-type.rs index 4441c38ba6d..d56ccc5b353 100644 --- a/tests/ui/coherence/occurs-check/associated-type.rs +++ b/tests/ui/coherence/occurs-check/associated-type.rs @@ -1,4 +1,5 @@ //@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver // A (partial) regression test for #105787 diff --git a/tests/ui/coherence/occurs-check/opaques.current.stderr b/tests/ui/coherence/occurs-check/opaques.current.stderr index 96ef7cd4322..f3fc22027c2 100644 --- a/tests/ui/coherence/occurs-check/opaques.current.stderr +++ b/tests/ui/coherence/occurs-check/opaques.current.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Trait<_>` - --> $DIR/opaques.rs:27:1 + --> $DIR/opaques.rs:28:1 | LL | impl Trait for T { | ---------------------- first implementation here diff --git a/tests/ui/coherence/occurs-check/opaques.next.stderr b/tests/ui/coherence/occurs-check/opaques.next.stderr index 2bedff25ecd..04fd139f901 100644 --- a/tests/ui/coherence/occurs-check/opaques.next.stderr +++ b/tests/ui/coherence/occurs-check/opaques.next.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Trait<_>` - --> $DIR/opaques.rs:27:1 + --> $DIR/opaques.rs:28:1 | LL | impl Trait for T { | ---------------------- first implementation here @@ -8,7 +8,7 @@ LL | impl Trait for defining_scope::Alias { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation error[E0282]: type annotations needed - --> $DIR/opaques.rs:10:23 + --> $DIR/opaques.rs:11:23 | LL | pub fn cast(x: Container, T>) -> Container { | ^^^^^^^^^^^^^^^^^^^^^^ cannot infer type diff --git a/tests/ui/coherence/occurs-check/opaques.rs b/tests/ui/coherence/occurs-check/opaques.rs index d7032dd53d9..e197256c78c 100644 --- a/tests/ui/coherence/occurs-check/opaques.rs +++ b/tests/ui/coherence/occurs-check/opaques.rs @@ -1,4 +1,5 @@ -//@revisions: current next +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver // A regression test for #105787 diff --git a/tests/ui/coherence/orphan-check-opaque-types-not-covering.next.stderr b/tests/ui/coherence/orphan-check-opaque-types-not-covering.next.stderr deleted file mode 100644 index 44f76f321cf..00000000000 --- a/tests/ui/coherence/orphan-check-opaque-types-not-covering.next.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`) - --> $DIR/orphan-check-opaque-types-not-covering.rs:17:6 - | -LL | impl foreign::Trait0 for Identity {} - | ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`) - | - = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type - = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait for T0`, where `T0` is the first and `Tn` is the last - -error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`) - --> $DIR/orphan-check-opaque-types-not-covering.rs:26:6 - | -LL | impl foreign::Trait1 for Opaque {} - | ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`) - | - = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type - = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait for T0`, where `T0` is the first and `Tn` is the last - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0210`. diff --git a/tests/ui/coherence/orphan-check-opaque-types-not-covering.rs b/tests/ui/coherence/orphan-check-opaque-types-not-covering.rs index 8dc02b081c5..02e9eb65570 100644 --- a/tests/ui/coherence/orphan-check-opaque-types-not-covering.rs +++ b/tests/ui/coherence/orphan-check-opaque-types-not-covering.rs @@ -1,8 +1,5 @@ // Opaque types never cover type parameters. -//@ revisions: classic next -//@[next] compile-flags: -Znext-solver - //@ aux-crate:foreign=parametrized-trait.rs //@ edition:2021 diff --git a/tests/ui/coherence/orphan-check-opaque-types-not-covering.classic.stderr b/tests/ui/coherence/orphan-check-opaque-types-not-covering.stderr similarity index 92% rename from tests/ui/coherence/orphan-check-opaque-types-not-covering.classic.stderr rename to tests/ui/coherence/orphan-check-opaque-types-not-covering.stderr index 44f76f321cf..57f5bbd2278 100644 --- a/tests/ui/coherence/orphan-check-opaque-types-not-covering.classic.stderr +++ b/tests/ui/coherence/orphan-check-opaque-types-not-covering.stderr @@ -1,5 +1,5 @@ error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`) - --> $DIR/orphan-check-opaque-types-not-covering.rs:17:6 + --> $DIR/orphan-check-opaque-types-not-covering.rs:14:6 | LL | impl foreign::Trait0 for Identity {} | ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`) @@ -8,7 +8,7 @@ LL | impl foreign::Trait0 for Identity {} = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait for T0`, where `T0` is the first and `Tn` is the last error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`) - --> $DIR/orphan-check-opaque-types-not-covering.rs:26:6 + --> $DIR/orphan-check-opaque-types-not-covering.rs:23:6 | LL | impl foreign::Trait1 for Opaque {} | ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`) diff --git a/tests/ui/coherence/orphan-check-projections-covering.rs b/tests/ui/coherence/orphan-check-projections-covering.rs index ae1917ec161..804784463a1 100644 --- a/tests/ui/coherence/orphan-check-projections-covering.rs +++ b/tests/ui/coherence/orphan-check-projections-covering.rs @@ -5,9 +5,6 @@ // first which would've lead to real-word regressions. //@ check-pass -//@ revisions: classic next -//@[next] compile-flags: -Znext-solver - //@ aux-crate:foreign=parametrized-trait.rs //@ edition:2021 diff --git a/tests/ui/coherence/orphan-check-weak-aliases-not-covering.next.stderr b/tests/ui/coherence/orphan-check-weak-aliases-not-covering.next.stderr deleted file mode 100644 index 276833fa171..00000000000 --- a/tests/ui/coherence/orphan-check-weak-aliases-not-covering.next.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`) - --> $DIR/orphan-check-weak-aliases-not-covering.rs:16:6 - | -LL | impl foreign::Trait1 for Identity {} - | ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`) - | - = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type - = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait for T0`, where `T0` is the first and `Tn` is the last - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0210`. diff --git a/tests/ui/coherence/orphan-check-weak-aliases-not-covering.rs b/tests/ui/coherence/orphan-check-weak-aliases-not-covering.rs index 9ebc45a8829..6d9bccc4c68 100644 --- a/tests/ui/coherence/orphan-check-weak-aliases-not-covering.rs +++ b/tests/ui/coherence/orphan-check-weak-aliases-not-covering.rs @@ -1,8 +1,5 @@ // Weak aliases might not cover type parameters. -//@ revisions: classic next -//@[next] compile-flags: -Znext-solver - //@ aux-crate:foreign=parametrized-trait.rs //@ edition:2021 diff --git a/tests/ui/coherence/orphan-check-weak-aliases-not-covering.classic.stderr b/tests/ui/coherence/orphan-check-weak-aliases-not-covering.stderr similarity index 92% rename from tests/ui/coherence/orphan-check-weak-aliases-not-covering.classic.stderr rename to tests/ui/coherence/orphan-check-weak-aliases-not-covering.stderr index 276833fa171..df915141a76 100644 --- a/tests/ui/coherence/orphan-check-weak-aliases-not-covering.classic.stderr +++ b/tests/ui/coherence/orphan-check-weak-aliases-not-covering.stderr @@ -1,5 +1,5 @@ error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`) - --> $DIR/orphan-check-weak-aliases-not-covering.rs:16:6 + --> $DIR/orphan-check-weak-aliases-not-covering.rs:13:6 | LL | impl foreign::Trait1 for Identity {} | ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`) diff --git a/tests/ui/coherence/skip-reporting-if-references-err.current.stderr b/tests/ui/coherence/skip-reporting-if-references-err.current.stderr deleted file mode 100644 index 5de4cf626e4..00000000000 --- a/tests/ui/coherence/skip-reporting-if-references-err.current.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error[E0726]: implicit elided lifetime not allowed here - --> $DIR/skip-reporting-if-references-err.rs:10:9 - | -LL | impl ToUnit for T {} - | ^^^^^^ expected lifetime parameter - | -help: indicate the anonymous lifetime - | -LL | impl ToUnit<'_> for T {} - | ++++ - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0726`. diff --git a/tests/ui/coherence/skip-reporting-if-references-err.next.stderr b/tests/ui/coherence/skip-reporting-if-references-err.next.stderr deleted file mode 100644 index 5de4cf626e4..00000000000 --- a/tests/ui/coherence/skip-reporting-if-references-err.next.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error[E0726]: implicit elided lifetime not allowed here - --> $DIR/skip-reporting-if-references-err.rs:10:9 - | -LL | impl ToUnit for T {} - | ^^^^^^ expected lifetime parameter - | -help: indicate the anonymous lifetime - | -LL | impl ToUnit<'_> for T {} - | ++++ - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0726`. diff --git a/tests/ui/coherence/super-traits/super-trait-knowable-2.rs b/tests/ui/coherence/super-traits/super-trait-knowable-2.rs index d1f2e8d1c1a..323ee0b10c9 100644 --- a/tests/ui/coherence/super-traits/super-trait-knowable-2.rs +++ b/tests/ui/coherence/super-traits/super-trait-knowable-2.rs @@ -9,9 +9,6 @@ // which caused the old solver to emit a `Tensor: TensorValue` goal in // `fn normalize_to_error` which then failed, causing this test to pass. -//@ revisions: current next -//@ ignore-compare-mode-next-solver (explicit revisions) -//@[next] compile-flags: -Znext-solver //@ check-pass pub trait TensorValue { diff --git a/tests/ui/transmutability/malformed-program-gracefulness/coherence-bikeshed-intrinsic-from.stderr b/tests/ui/transmutability/malformed-program-gracefulness/coherence-bikeshed-intrinsic-from.stderr index 2424541af23..cdf9deecd51 100644 --- a/tests/ui/transmutability/malformed-program-gracefulness/coherence-bikeshed-intrinsic-from.stderr +++ b/tests/ui/transmutability/malformed-program-gracefulness/coherence-bikeshed-intrinsic-from.stderr @@ -1,11 +1,3 @@ -error: unconstrained opaque type - --> $DIR/coherence-bikeshed-intrinsic-from.rs:4:19 - | -LL | type OpaqueType = impl OpaqueTrait; - | ^^^^^^^^^^^^^^^^ - | - = note: `OpaqueType` must be used in combination with a concrete type within the same module - error[E0747]: type provided when a constant was expected --> $DIR/coherence-bikeshed-intrinsic-from.rs:7:37 | @@ -21,6 +13,14 @@ LL | LL | impl AnotherTrait for OpaqueType {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation +error: unconstrained opaque type + --> $DIR/coherence-bikeshed-intrinsic-from.rs:4:19 + | +LL | type OpaqueType = impl OpaqueTrait; + | ^^^^^^^^^^^^^^^^ + | + = note: `OpaqueType` must be used in combination with a concrete type within the same module + error: aborting due to 3 previous errors Some errors have detailed explanations: E0119, E0747. From 30ec8bb5e96faeb363b6c195f60e8a76f8c92374 Mon Sep 17 00:00:00 2001 From: lcnr Date: Sat, 21 Sep 2024 07:05:51 +0000 Subject: [PATCH 316/357] update test description --- .../leak-check/leak-check-in-selection-5-ambig.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/ui/higher-ranked/leak-check/leak-check-in-selection-5-ambig.rs b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-5-ambig.rs index beda719ac20..9a44fd2e64a 100644 --- a/tests/ui/higher-ranked/leak-check/leak-check-in-selection-5-ambig.rs +++ b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-5-ambig.rs @@ -3,9 +3,9 @@ //@ check-pass // The new trait solver does not return region constraints if the goal -// is still ambiguous. This causes the following test to fail with ambiguity, -// even though `(): LeakCheckFailure<'!a, V>` would return `'!a: 'static` -// which would have caused a leak check failure. +// is still ambiguous. However, the `'!a = 'static` constraint from +// `(): LeakCheckFailure<'!a, V>` is also returned via the canonical +// var values, causing this test to compile. trait Ambig {} impl Ambig for u32 {} From d3d59055a9f8a7a34d70b581638ef8b56e68d0b4 Mon Sep 17 00:00:00 2001 From: Michal Piotrowski Date: Tue, 15 Oct 2024 13:49:07 +0200 Subject: [PATCH 317/357] Fix uninlined_format_args in stable_mir --- compiler/stable_mir/src/mir/pretty.rs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/compiler/stable_mir/src/mir/pretty.rs b/compiler/stable_mir/src/mir/pretty.rs index 74081af1d86..05d11c71bbb 100644 --- a/compiler/stable_mir/src/mir/pretty.rs +++ b/compiler/stable_mir/src/mir/pretty.rs @@ -22,7 +22,7 @@ impl Debug for Place { } pub(crate) fn function_body(writer: &mut W, body: &Body, name: &str) -> io::Result<()> { - write!(writer, "fn {}(", name)?; + write!(writer, "fn {name}(")?; body.arg_locals() .iter() .enumerate() @@ -54,7 +54,7 @@ pub(crate) fn function_body(writer: &mut W, body: &Body, name: &str) - .iter() .enumerate() .map(|(index, block)| -> io::Result<()> { - writeln!(writer, " bb{}: {{", index)?; + writeln!(writer, " bb{index}: {{")?; let _ = block .statements .iter() @@ -75,7 +75,7 @@ pub(crate) fn function_body(writer: &mut W, body: &Body, name: &str) - fn pretty_statement(writer: &mut W, statement: &StatementKind) -> io::Result<()> { match statement { StatementKind::Assign(place, rval) => { - write!(writer, " {:?} = ", place)?; + write!(writer, " {place:?} = ")?; pretty_rvalue(writer, rval)?; writeln!(writer, ";") } @@ -165,7 +165,7 @@ fn pretty_terminator_head(writer: &mut W, terminator: &TerminatorKind) Abort => write!(writer, "{INDENT}abort"), Return => write!(writer, "{INDENT}return"), Unreachable => write!(writer, "{INDENT}unreachable"), - Drop { place, .. } => write!(writer, "{INDENT}drop({:?})", place), + Drop { place, .. } => write!(writer, "{INDENT}drop({place:?})"), Call { func, args, destination, .. } => { write!(writer, "{INDENT}{:?} = {}(", destination, pretty_operand(func))?; let mut args_iter = args.iter(); @@ -304,10 +304,10 @@ fn pretty_assert_message(writer: &mut W, msg: &AssertMessage) -> io::R fn pretty_operand(operand: &Operand) -> String { match operand { Operand::Copy(copy) => { - format!("{:?}", copy) + format!("{copy:?}") } Operand::Move(mv) => { - format!("move {:?}", mv) + format!("move {mv:?}") } Operand::Constant(cnst) => pretty_mir_const(&cnst.const_), } @@ -344,13 +344,13 @@ fn pretty_rvalue(writer: &mut W, rval: &Rvalue) -> io::Result<()> { write!(writer, "Checked{:?}({}, {})", bin, pretty_operand(op1), pretty_operand(op2)) } Rvalue::CopyForDeref(deref) => { - write!(writer, "CopyForDeref({:?})", deref) + write!(writer, "CopyForDeref({deref:?})") } Rvalue::Discriminant(place) => { - write!(writer, "discriminant({:?})", place) + write!(writer, "discriminant({place:?})") } Rvalue::Len(len) => { - write!(writer, "len({:?})", len) + write!(writer, "len({len:?})") } Rvalue::Ref(_, borrowkind, place) => { let kind = match borrowkind { @@ -359,17 +359,17 @@ fn pretty_rvalue(writer: &mut W, rval: &Rvalue) -> io::Result<()> { BorrowKind::Fake(FakeBorrowKind::Shallow) => "&fake shallow ", BorrowKind::Mut { .. } => "&mut ", }; - write!(writer, "{kind}{:?}", place) + write!(writer, "{kind}{place:?}") } Rvalue::Repeat(op, cnst) => { write!(writer, "{} \" \" {}", pretty_operand(op), pretty_ty_const(cnst)) } Rvalue::ShallowInitBox(_, _) => Ok(()), Rvalue::ThreadLocalRef(item) => { - write!(writer, "thread_local_ref{:?}", item) + write!(writer, "thread_local_ref{item:?}") } Rvalue::NullaryOp(nul, ty) => { - write!(writer, "{:?} {} \" \"", nul, ty) + write!(writer, "{nul:?} {ty} \" \"") } Rvalue::UnaryOp(un, op) => { write!(writer, "{} \" \" {:?}", pretty_operand(op), un) From 4e29e454a15cbfff91174332106e09d18a7a7da0 Mon Sep 17 00:00:00 2001 From: Emmanuel Ferdman Date: Tue, 15 Oct 2024 05:12:03 -0700 Subject: [PATCH 318/357] Update arm64e-apple-tvos maintainer Signed-off-by: Emmanuel Ferdman --- src/doc/rustc/src/platform-support/arm64e-apple-tvos.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc/src/platform-support/arm64e-apple-tvos.md b/src/doc/rustc/src/platform-support/arm64e-apple-tvos.md index d49383fb853..47234809e5f 100644 --- a/src/doc/rustc/src/platform-support/arm64e-apple-tvos.md +++ b/src/doc/rustc/src/platform-support/arm64e-apple-tvos.md @@ -6,7 +6,7 @@ ARM64e tvOS (10.0+) ## Target maintainers -- Artyom Tetyukhin ([@arttet](https://github.com/https://github.com/arttet)) +- Artyom Tetyukhin ([@arttet](https://github.com/arttet)) ## Requirements From 1d6643c4f69ba31f91a385c51f46d615bd2b0d66 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Mon, 14 Oct 2024 21:16:27 +0200 Subject: [PATCH 319/357] Fix most ui tests on emscripten target To fix the linker errors, we need to set the output extension to `.js` instead of `.wasm`. Setting the output to a `.wasm` file puts Emscripten into standalone mode which is effectively a distinct target. We need to set the runner to be `node` as well. This fixes most of the ui tests. I fixed a few more tests with simple problems: - `intrinsics/intrinsic-alignment.rs` and `structs-enums/rec-align-u64.rs` -- Two `#[cfg]` macros match for Emscripten so we got a duplicate definition of `mod m`. - `issues/issue-12699.rs` -- Seems to hang so I disabled it - `process/process-sigpipe.rs` -- Not expected to work on Emscripten so I disabled it --- src/bootstrap/src/core/config/config.rs | 3 +++ src/tools/compiletest/src/runtest.rs | 4 +++- src/tools/tidy/src/issues.txt | 1 - src/tools/tidy/src/ui_tests.rs | 2 +- tests/ui/intrinsics/intrinsic-alignment.rs | 1 - tests/ui/process/process-sigpipe.rs | 8 ++------ .../ui/{issues/issue-12699.rs => std/thread-sleep-ms.rs} | 3 +++ tests/ui/structs-enums/rec-align-u64.rs | 1 - 8 files changed, 12 insertions(+), 11 deletions(-) rename tests/ui/{issues/issue-12699.rs => std/thread-sleep-ms.rs} (59%) diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index f768470c4ff..eb571f920df 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -612,6 +612,9 @@ impl Target { if triple.contains("-none") || triple.contains("nvptx") || triple.contains("switch") { target.no_std = true; } + if triple.contains("emscripten") { + target.runner = Some("node".into()); + } target } } diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 29f9925de16..69a47fcd0fb 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1643,7 +1643,9 @@ impl<'test> TestCx<'test> { // double the length. let mut f = self.output_base_dir().join("a"); // FIXME: This is using the host architecture exe suffix, not target! - if self.config.target.starts_with("wasm") { + if self.config.target.contains("emscripten") { + f = f.with_extra_extension("js"); + } else if self.config.target.starts_with("wasm") { f = f.with_extra_extension("wasm"); } else if self.config.target.contains("spirv") { f = f.with_extra_extension("spv"); diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt index 66c176c6f44..22126674c15 100644 --- a/src/tools/tidy/src/issues.txt +++ b/src/tools/tidy/src/issues.txt @@ -1520,7 +1520,6 @@ ui/issues/issue-12567.rs ui/issues/issue-12612.rs ui/issues/issue-12660.rs ui/issues/issue-12677.rs -ui/issues/issue-12699.rs ui/issues/issue-12729.rs ui/issues/issue-12744.rs ui/issues/issue-12860.rs diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index 41f7778c952..11f9d5bb03d 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -17,7 +17,7 @@ use ignore::Walk; const ENTRY_LIMIT: u32 = 901; // FIXME: The following limits should be reduced eventually. -const ISSUES_ENTRY_LIMIT: u32 = 1673; +const ISSUES_ENTRY_LIMIT: u32 = 1672; const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[ "rs", // test source files diff --git a/tests/ui/intrinsics/intrinsic-alignment.rs b/tests/ui/intrinsics/intrinsic-alignment.rs index 138273aadd2..4cb05f6a8df 100644 --- a/tests/ui/intrinsics/intrinsic-alignment.rs +++ b/tests/ui/intrinsics/intrinsic-alignment.rs @@ -13,7 +13,6 @@ mod rusti { #[cfg(any( target_os = "android", target_os = "dragonfly", - target_os = "emscripten", target_os = "freebsd", target_os = "fuchsia", target_os = "hurd", diff --git a/tests/ui/process/process-sigpipe.rs b/tests/ui/process/process-sigpipe.rs index 11f363d625f..9db130c26bd 100644 --- a/tests/ui/process/process-sigpipe.rs +++ b/tests/ui/process/process-sigpipe.rs @@ -15,11 +15,12 @@ //@ ignore-vxworks no 'sh' //@ ignore-fuchsia no 'sh' +//@ ignore-emscripten No threads +//@ only-unix SIGPIPE is a unix feature use std::process; use std::thread; -#[cfg(unix)] fn main() { // Just in case `yes` doesn't check for EPIPE... thread::spawn(|| { @@ -34,8 +35,3 @@ fn main() { assert!(output.status.success()); assert!(output.stderr.len() == 0); } - -#[cfg(not(unix))] -fn main() { - // Not worried about signal masks on other platforms -} diff --git a/tests/ui/issues/issue-12699.rs b/tests/ui/std/thread-sleep-ms.rs similarity index 59% rename from tests/ui/issues/issue-12699.rs rename to tests/ui/std/thread-sleep-ms.rs index 4fc93735c3c..0a3d0253a20 100644 --- a/tests/ui/issues/issue-12699.rs +++ b/tests/ui/std/thread-sleep-ms.rs @@ -1,6 +1,9 @@ //@ run-pass //@ ignore-sgx not supported +//@ ignore-emscripten +// FIXME: test hangs on emscripten #![allow(deprecated)] +#![allow(unused_imports)] use std::thread; diff --git a/tests/ui/structs-enums/rec-align-u64.rs b/tests/ui/structs-enums/rec-align-u64.rs index 8ea72fdf45c..313ce6d578d 100644 --- a/tests/ui/structs-enums/rec-align-u64.rs +++ b/tests/ui/structs-enums/rec-align-u64.rs @@ -33,7 +33,6 @@ struct Outer { #[cfg(any( target_os = "android", target_os = "dragonfly", - target_os = "emscripten", target_os = "freebsd", target_os = "fuchsia", target_os = "hurd", From 99af761632420b2778e2b44465a396e28adf6103 Mon Sep 17 00:00:00 2001 From: zlfn Date: Tue, 15 Oct 2024 18:39:30 +0900 Subject: [PATCH 320/357] Refactor `floating` macro and nofloat panic message --- library/core/src/fmt/float.rs | 47 ++++++++++++++++--------------- library/core/src/fmt/nofloat.rs | 21 +++++++------- library/core/src/fmt/num.rs | 50 +++++++++++++++++---------------- 3 files changed, 60 insertions(+), 58 deletions(-) diff --git a/library/core/src/fmt/float.rs b/library/core/src/fmt/float.rs index 20ea0352c2d..c70dbf54304 100644 --- a/library/core/src/fmt/float.rs +++ b/library/core/src/fmt/float.rs @@ -196,39 +196,40 @@ where } macro_rules! floating { - ($ty:ident) => { - #[stable(feature = "rust1", since = "1.0.0")] - impl Debug for $ty { - fn fmt(&self, fmt: &mut Formatter<'_>) -> Result { - float_to_general_debug(fmt, self) + ($($ty:ident)*) => { + $( + #[stable(feature = "rust1", since = "1.0.0")] + impl Debug for $ty { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result { + float_to_general_debug(fmt, self) + } } - } - #[stable(feature = "rust1", since = "1.0.0")] - impl Display for $ty { - fn fmt(&self, fmt: &mut Formatter<'_>) -> Result { - float_to_decimal_display(fmt, self) + #[stable(feature = "rust1", since = "1.0.0")] + impl Display for $ty { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result { + float_to_decimal_display(fmt, self) + } } - } - #[stable(feature = "rust1", since = "1.0.0")] - impl LowerExp for $ty { - fn fmt(&self, fmt: &mut Formatter<'_>) -> Result { - float_to_exponential_common(fmt, self, false) + #[stable(feature = "rust1", since = "1.0.0")] + impl LowerExp for $ty { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result { + float_to_exponential_common(fmt, self, false) + } } - } - #[stable(feature = "rust1", since = "1.0.0")] - impl UpperExp for $ty { - fn fmt(&self, fmt: &mut Formatter<'_>) -> Result { - float_to_exponential_common(fmt, self, true) + #[stable(feature = "rust1", since = "1.0.0")] + impl UpperExp for $ty { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result { + float_to_exponential_common(fmt, self, true) + } } - } + )* }; } -floating! { f32 } -floating! { f64 } +floating! { f32 f64 } #[stable(feature = "rust1", since = "1.0.0")] impl Debug for f16 { diff --git a/library/core/src/fmt/nofloat.rs b/library/core/src/fmt/nofloat.rs index 6b07236f1da..29aaee75d22 100644 --- a/library/core/src/fmt/nofloat.rs +++ b/library/core/src/fmt/nofloat.rs @@ -1,18 +1,17 @@ use crate::fmt::{Debug, Formatter, Result}; macro_rules! floating { - ($ty:ident) => { - #[stable(feature = "rust1", since = "1.0.0")] - impl Debug for $ty { - #[inline] - fn fmt(&self, _fmt: &mut Formatter<'_>) -> Result { - panic!("floating point support is turned off"); + ($($ty:ident)*) => { + $( + #[stable(feature = "rust1", since = "1.0.0")] + impl Debug for $ty { + #[inline] + fn fmt(&self, _fmt: &mut Formatter<'_>) -> Result { + panic!("floating point fmt support is turned off"); + } } - } + )* }; } -floating! { f16 } -floating! { f32 } -floating! { f64 } -floating! { f128 } +floating! { f16 f32 f64 f128 } diff --git a/library/core/src/fmt/num.rs b/library/core/src/fmt/num.rs index 0f33d730a68..f1540803f97 100644 --- a/library/core/src/fmt/num.rs +++ b/library/core/src/fmt/num.rs @@ -20,15 +20,15 @@ trait DisplayInt: macro_rules! impl_int { ($($t:ident)*) => ( - $(impl DisplayInt for $t { - fn zero() -> Self { 0 } - fn from_u8(u: u8) -> Self { u as Self } - fn to_u8(&self) -> u8 { *self as u8 } - #[cfg(not(any(target_pointer_width = "64", target_arch = "wasm32")))] - fn to_u32(&self) -> u32 { *self as u32 } - fn to_u64(&self) -> u64 { *self as u64 } - fn to_u128(&self) -> u128 { *self as u128 } - })* + $(impl DisplayInt for $t { + fn zero() -> Self { 0 } + fn from_u8(u: u8) -> Self { u as Self } + fn to_u8(&self) -> u8 { *self as u8 } + #[cfg(not(any(target_pointer_width = "64", target_arch = "wasm32")))] + fn to_u32(&self) -> u32 { *self as u32 } + fn to_u64(&self) -> u64 { *self as u64 } + fn to_u128(&self) -> u128 { *self as u128 } + })* ) } @@ -169,21 +169,23 @@ integer! { i64, u64 } integer! { i128, u128 } macro_rules! impl_Debug { - ($($T:ident)*) => {$( - #[stable(feature = "rust1", since = "1.0.0")] - impl fmt::Debug for $T { - #[inline] - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - if f.debug_lower_hex() { - fmt::LowerHex::fmt(self, f) - } else if f.debug_upper_hex() { - fmt::UpperHex::fmt(self, f) - } else { - fmt::Display::fmt(self, f) + ($($T:ident)*) => { + $( + #[stable(feature = "rust1", since = "1.0.0")] + impl fmt::Debug for $T { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + if f.debug_lower_hex() { + fmt::LowerHex::fmt(self, f) + } else if f.debug_upper_hex() { + fmt::UpperHex::fmt(self, f) + } else { + fmt::Display::fmt(self, f) + } } } - } - )*}; + )* + }; } // 2 digit decimal look up table @@ -508,8 +510,8 @@ macro_rules! impl_Exp { } impl_Debug! { - i8 i16 i32 i64 i128 isize - u8 u16 u32 u64 u128 usize + i8 i16 i32 i64 i128 isize + u8 u16 u32 u64 u128 usize } // Include wasm32 in here since it doesn't reflect the native pointer size, and From 2b9e41c1288a5e9f015be4f5da4c90d5a4d9c158 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 15 Oct 2024 01:58:27 +0200 Subject: [PATCH 321/357] Improve documentation for intra-doc links computation --- .../passes/collect_intra_doc_links.rs | 18 +++++++++--------- .../intra-doc/filter-out-private-2.rs | 2 +- .../intra-doc/filter-out-private-2.stderr | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 81e7bcbd7d8..10026e9f05d 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -288,14 +288,16 @@ pub(crate) struct LinkCollector<'a, 'tcx> { /// Cache the resolved links so we can avoid resolving (and emitting errors for) the same link. /// The link will be `None` if it could not be resolved (i.e. the error was cached). pub(crate) visited_links: FxHashMap)>>, - /// These links are ambiguous. We need for the cache to have its paths filled. Unfortunately, - /// if we run the `LinkCollector` pass after `Cache::populate`, a lot of items that we need - /// to go through will be removed, making a lot of intra-doc links to not be inferred. + /// According to `rustc_resolve`, these links are ambiguous. /// - /// So instead, we store the ambiguous links and we wait for cache paths to be filled before - /// inferring them (if possible). + /// However, we cannot link to an item that has been stripped from the documentation. If all + /// but one of the "possibilities" are stripped, then there is no real ambiguity. To determine + /// if an ambiguity is real, we delay resolving them until after `Cache::populate`, then filter + /// every item that doesn't have a cached path. /// - /// Key is `(item ID, path str)`. + /// We could get correct results by simply delaying everything. This would have fewer happy + /// codepaths, but we want to distinguish different kinds of error conditions, and this is easy + /// to do by resolving links as soon as possible. pub(crate) ambiguous_links: FxIndexMap<(ItemId, String), Vec>, } @@ -1187,9 +1189,7 @@ impl LinkCollector<'_, '_> { report_diagnostic( self.cx.tcx, BROKEN_INTRA_DOC_LINKS, - format!( - "all items matching `{path_str}` are either private or doc(hidden)" - ), + format!("all items matching `{path_str}` are private or doc(hidden)"), &diag_info, |diag, sp, _| { if let Some(sp) = sp { diff --git a/tests/rustdoc-ui/intra-doc/filter-out-private-2.rs b/tests/rustdoc-ui/intra-doc/filter-out-private-2.rs index 9209203c99e..9d8edbf6b5d 100644 --- a/tests/rustdoc-ui/intra-doc/filter-out-private-2.rs +++ b/tests/rustdoc-ui/intra-doc/filter-out-private-2.rs @@ -11,5 +11,5 @@ pub struct Thing {} pub fn Thing() {} /// Do stuff with [`Thing`]. -//~^ ERROR all items matching `Thing` are either private or doc(hidden) +//~^ ERROR all items matching `Thing` are private or doc(hidden) pub fn repro(_: Thing) {} diff --git a/tests/rustdoc-ui/intra-doc/filter-out-private-2.stderr b/tests/rustdoc-ui/intra-doc/filter-out-private-2.stderr index 394f919de94..1a49c90a172 100644 --- a/tests/rustdoc-ui/intra-doc/filter-out-private-2.stderr +++ b/tests/rustdoc-ui/intra-doc/filter-out-private-2.stderr @@ -1,4 +1,4 @@ -error: all items matching `Thing` are either private or doc(hidden) +error: all items matching `Thing` are private or doc(hidden) --> $DIR/filter-out-private-2.rs:13:21 | LL | /// Do stuff with [`Thing`]. From 10f2395c9ee5849e3a769ce21d3e704191ec8085 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 15 Oct 2024 15:42:47 +0200 Subject: [PATCH 322/357] Remove `AmbiguousLinks::disambiguator` --- 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 10026e9f05d..cbc6e351fac 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -302,7 +302,6 @@ pub(crate) struct LinkCollector<'a, 'tcx> { } pub(crate) struct AmbiguousLinks { - disambiguator: Option, link_text: Box, diag_info: OwnedDiagnosticInfo, resolved: Vec<(Res, Option)>, @@ -1097,7 +1096,6 @@ impl LinkCollector<'_, '_> { if resolved.len() > 1 { let links = AmbiguousLinks { - disambiguator, link_text: link_text.clone(), diag_info: diag_info.into(), resolved, @@ -1178,7 +1176,7 @@ impl LinkCollector<'_, '_> { res, fragment, path_str, - info.disambiguator, + None, diag_info, &info.link_text, ) { From dca646ab0107fd311427b7f7c4eea448e9f4ee9e Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 13 Oct 2024 10:09:42 -0400 Subject: [PATCH 323/357] Rewrite for<..> async correctly --- src/tools/rustfmt/src/types.rs | 50 +++++++++++---------- src/tools/rustfmt/tests/target/asyncness.rs | 2 + 2 files changed, 29 insertions(+), 23 deletions(-) diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs index 99b3fe60ee2..e237662f5aa 100644 --- a/src/tools/rustfmt/src/types.rs +++ b/src/tools/rustfmt/src/types.rs @@ -613,26 +613,8 @@ impl Rewrite for ast::GenericBound { ast::GenericBound::Trait(ref poly_trait_ref) => { let snippet = context.snippet(self.span()); let has_paren = snippet.starts_with('(') && snippet.ends_with(')'); - let ast::TraitBoundModifiers { - constness, - asyncness, - polarity, - } = poly_trait_ref.modifiers; - let mut constness = constness.as_str().to_string(); - if !constness.is_empty() { - constness.push(' '); - } - let mut asyncness = asyncness.as_str().to_string(); - if !asyncness.is_empty() { - asyncness.push(' '); - } - let polarity = polarity.as_str(); - let shape = shape - .offset_left(constness.len() + polarity.len()) - .max_width_error(shape.width, self.span())?; poly_trait_ref .rewrite_result(context, shape) - .map(|s| format!("{constness}{asyncness}{polarity}{s}")) .map(|s| if has_paren { format!("({})", s) } else { s }) } ast::GenericBound::Use(ref args, span) => { @@ -756,19 +738,41 @@ impl Rewrite for ast::PolyTraitRef { } fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult { - if let Some(lifetime_str) = rewrite_bound_params(context, shape, &self.bound_generic_params) + let (binder, shape) = if let Some(lifetime_str) = + rewrite_bound_params(context, shape, &self.bound_generic_params) { // 6 is "for<> ".len() let extra_offset = lifetime_str.len() + 6; let shape = shape .offset_left(extra_offset) .max_width_error(shape.width, self.span)?; - let path_str = self.trait_ref.rewrite_result(context, shape)?; - - Ok(format!("for<{lifetime_str}> {path_str}")) + (format!("for<{lifetime_str}> "), shape) } else { - self.trait_ref.rewrite_result(context, shape) + (String::new(), shape) + }; + + let ast::TraitBoundModifiers { + constness, + asyncness, + polarity, + } = self.modifiers; + let mut constness = constness.as_str().to_string(); + if !constness.is_empty() { + constness.push(' '); } + let mut asyncness = asyncness.as_str().to_string(); + if !asyncness.is_empty() { + asyncness.push(' '); + } + let polarity = polarity.as_str(); + let shape = shape + .offset_left(constness.len() + polarity.len()) + .max_width_error(shape.width, self.span)?; + + let path_str = self.trait_ref.rewrite_result(context, shape)?; + Ok(format!( + "{binder}{constness}{asyncness}{polarity}{path_str}" + )) } } diff --git a/src/tools/rustfmt/tests/target/asyncness.rs b/src/tools/rustfmt/tests/target/asyncness.rs index d91ac960499..dd651ed6a62 100644 --- a/src/tools/rustfmt/tests/target/asyncness.rs +++ b/src/tools/rustfmt/tests/target/asyncness.rs @@ -1,3 +1,5 @@ // rustfmt-edition: 2018 fn foo() -> impl async Fn() {} + +fn bar() -> impl for<'a> async Fn(&'a ()) {} From 5d178e1d4da25110e72b297caaef6489e920f04f Mon Sep 17 00:00:00 2001 From: c6c7 Date: Mon, 14 Oct 2024 12:38:49 -0400 Subject: [PATCH 324/357] Make fuchsia-test-runner.py compatible with new JSON output from llvm-readelf [A recent commit in LLVM](https://github.com/llvm/llvm-project/commit/ab930ee7cad8b8bf7968bb8d0c0d72524e2313c4) modified the JSON output of LLVM. The LLVM change renamed "Notes" to "NoteSections" and inserted a new "Notes" key nested under each "NoteSection". This change shores up exceptions around reading the JSON output of llvm-readelf and reads from "NoteSections" instead of the non-existent "Notes". --- src/ci/docker/scripts/fuchsia-test-runner.py | 42 +++++++++++++++----- 1 file changed, 31 insertions(+), 11 deletions(-) diff --git a/src/ci/docker/scripts/fuchsia-test-runner.py b/src/ci/docker/scripts/fuchsia-test-runner.py index a5458b8645d..1aa9a4a1794 100755 --- a/src/ci/docker/scripts/fuchsia-test-runner.py +++ b/src/ci/docker/scripts/fuchsia-test-runner.py @@ -193,18 +193,38 @@ class TestEnvironment: stderr=subprocess.STDOUT, ) if process.returncode: - self.env_logger.error( - f"llvm-readelf failed for binary {binary} with output {process.stdout}" + e = f"llvm-readelf failed for binary {binary} with output {process.stdout}" + self.env_logger.error(e) + raise Exception(e) + + try: + elf_output = json.loads(process.stdout) + except Exception as e: + e.add_note(f"Failed to read JSON from llvm-readelf for binary {binary}") + e.add_note(f"stdout: {process.stdout}") + raise + + try: + note_sections = elf_output[0]["NoteSections"] + except Exception as e: + e.add_note( + f'Failed to read "NoteSections" from llvm-readelf for binary {binary}' ) - raise Exception(f"Unreadable build-id for binary {binary}") - data = json.loads(process.stdout) - if len(data) != 1: - raise Exception(f"Unreadable output from llvm-readelf for binary {binary}") - notes = data[0]["Notes"] - for note in notes: - note_section = note["NoteSection"] - if note_section["Name"] == ".note.gnu.build-id": - return note_section["Note"]["Build ID"] + e.add_note(f"elf_output: {elf_output}") + raise + + for entry in note_sections: + try: + note_section = entry["NoteSection"] + if note_section["Name"] == ".note.gnu.build-id": + return note_section["Notes"][0]["Build ID"] + except Exception as e: + e.add_note( + f'Failed to read ".note.gnu.build-id" from NoteSections \ + entry in llvm-readelf for binary {binary}' + ) + e.add_note(f"NoteSections: {note_sections}") + raise raise Exception(f"Build ID not found for binary {binary}") def generate_buildid_dir( From 937d13b8efc43f3f2e93f81360565d82f243ce15 Mon Sep 17 00:00:00 2001 From: Slanterns Date: Wed, 16 Oct 2024 00:22:05 +0800 Subject: [PATCH 325/357] relax a memory order in `once_box` --- library/std/src/sys/sync/once_box.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/std/src/sys/sync/once_box.rs b/library/std/src/sys/sync/once_box.rs index 1422b5a1721..9d24db2245a 100644 --- a/library/std/src/sys/sync/once_box.rs +++ b/library/std/src/sys/sync/once_box.rs @@ -8,7 +8,7 @@ use crate::mem::replace; use crate::ptr::null_mut; use crate::sync::atomic::AtomicPtr; -use crate::sync::atomic::Ordering::{AcqRel, Acquire, Relaxed}; +use crate::sync::atomic::Ordering::{Acquire, Relaxed, Release}; pub(crate) struct OnceBox { ptr: AtomicPtr, @@ -60,7 +60,7 @@ impl OnceBox { #[cold] fn initialize(&self, f: impl FnOnce() -> Box) -> &T { let new_ptr = Box::into_raw(f()); - match self.ptr.compare_exchange(null_mut(), new_ptr, AcqRel, Acquire) { + match self.ptr.compare_exchange(null_mut(), new_ptr, Release, Acquire) { Ok(_) => unsafe { &*new_ptr }, Err(ptr) => { // Lost the race to another thread. From 2bf120de38f66631a5b2a792d76b3123ba62bcf6 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Tue, 15 Oct 2024 13:31:07 -0400 Subject: [PATCH 326/357] Update cargo --- src/tools/cargo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/cargo b/src/tools/cargo index 15fbd2f607d..8c30ce53688 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 15fbd2f607d4defc87053b8b76bf5038f2483cf4 +Subproject commit 8c30ce53688e25f7e9d860b33cc914fb2957ca9a From 4886e9a134aa7c8c9bb1fed42ebfe22d7f5b2a63 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 15 Oct 2024 14:39:49 -0400 Subject: [PATCH 327/357] Unify secondary_span and swap_secondary_and_primary --- .../src/check/compare_impl_item.rs | 9 +++------ compiler/rustc_hir_analysis/src/check/mod.rs | 1 - .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 1 - compiler/rustc_passes/src/check_attr.rs | 1 - .../src/error_reporting/infer/mod.rs | 18 +++++++----------- .../traits/fulfillment_errors.rs | 3 +-- 6 files changed, 11 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 9ca5f25447b..75956165e87 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -592,14 +592,13 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( &cause, hir.get_if_local(impl_m.def_id) .and_then(|node| node.fn_decl()) - .map(|decl| (decl.output.span(), Cow::from("return type in trait"))), + .map(|decl| (decl.output.span(), Cow::from("return type in trait"), false)), Some(infer::ValuePairs::Terms(ExpectedFound { expected: trait_return_ty.into(), found: impl_return_ty.into(), })), terr, false, - false, ); return Err(diag.emit()); } @@ -1018,14 +1017,13 @@ fn report_trait_method_mismatch<'tcx>( infcx.err_ctxt().note_type_err( &mut diag, &cause, - trait_err_span.map(|sp| (sp, Cow::from("type in trait"))), + trait_err_span.map(|sp| (sp, Cow::from("type in trait"), false)), Some(infer::ValuePairs::PolySigs(ExpectedFound { expected: ty::Binder::dummy(trait_sig), found: ty::Binder::dummy(impl_sig), })), terr, false, - false, ); diag.emit() @@ -1825,14 +1823,13 @@ fn compare_const_predicate_entailment<'tcx>( infcx.err_ctxt().note_type_err( &mut diag, &cause, - trait_c_span.map(|span| (span, Cow::from("type in trait"))), + trait_c_span.map(|span| (span, Cow::from("type in trait"), false)), Some(infer::ValuePairs::Terms(ExpectedFound { expected: trait_ty.into(), found: impl_ty.into(), })), terr, false, - false, ); return Err(diag.emit()); }; diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index 004540b2643..959b17b2d40 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -652,7 +652,6 @@ pub fn check_function_signature<'tcx>( })), err, false, - false, ); return Err(diag.emit()); } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index fa471647d02..44c0da0744a 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -1114,7 +1114,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { None, Some(trace.values), e, - false, true, ); } diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 7ce29260e36..4516ea94cad 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -2302,7 +2302,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { })), terr, false, - false, ); diag.emit(); self.abort.set(true); diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs index bd78a6ee3af..df5800ab58a 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs @@ -1127,18 +1127,14 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { /// the message in `secondary_span` as the primary label, and apply the message that would /// otherwise be used for the primary label on the `secondary_span` `Span`. This applies on /// E0271, like `tests/ui/issues/issue-39970.stderr`. - #[instrument( - level = "debug", - skip(self, diag, secondary_span, swap_secondary_and_primary, prefer_label) - )] + #[instrument(level = "debug", skip(self, diag, secondary_span, prefer_label))] pub fn note_type_err( &self, diag: &mut Diag<'_>, cause: &ObligationCause<'tcx>, - secondary_span: Option<(Span, Cow<'static, str>)>, + secondary_span: Option<(Span, Cow<'static, str>, bool)>, mut values: Option>, terr: TypeError<'tcx>, - swap_secondary_and_primary: bool, prefer_label: bool, ) { let span = cause.span(); @@ -1304,7 +1300,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { diag.span_note(span, msg); } }; - if let Some((sp, msg)) = secondary_span { + if let Some((secondary_span, secondary_msg, swap_secondary_and_primary)) = secondary_span { if swap_secondary_and_primary { let terr = if let Some(infer::ValuePairs::Terms(ExpectedFound { expected, .. @@ -1314,11 +1310,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } else { terr.to_string(self.tcx) }; - label_or_note(sp, terr); - label_or_note(span, msg); + label_or_note(secondary_span, terr); + label_or_note(span, secondary_msg); } else { label_or_note(span, terr.to_string(self.tcx)); - label_or_note(sp, msg); + label_or_note(secondary_span, secondary_msg); } } else if let Some(values) = values && let Some((e, f)) = values.ty() @@ -1788,7 +1784,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { self.type_error_additional_suggestions(&trace, terr), ); let mut diag = self.dcx().create_err(failure_code); - self.note_type_err(&mut diag, &trace.cause, None, Some(trace.values), terr, false, false); + self.note_type_err(&mut diag, &trace.cause, None, Some(trace.values), terr, false); diag } diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 824c25db07d..8a4c22fdf86 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -710,7 +710,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { None, TypeError::Sorts(ty::error::ExpectedFound::new(true, expected_ty, ct_ty)), false, - false, ); diag } @@ -1435,6 +1434,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { cx.into_buffer() } ))), + true, )), _ => None, } @@ -1452,7 +1452,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { )) }), err, - true, false, ); self.note_obligation_cause(&mut diag, obligation); From 68885216b63f6e75e50b4c0f3c7250ca4ac7afda Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 15 Oct 2024 14:58:41 -0400 Subject: [PATCH 328/357] Don't report bivariance error when nesting a struct with field errors into another struct --- .../rustc_hir_analysis/src/check/wfcheck.rs | 60 +++++++++++++++---- .../type-resolve-error-two-structs-deep.rs | 13 ++++ ...type-resolve-error-two-structs-deep.stderr | 9 +++ 3 files changed, 72 insertions(+), 10 deletions(-) create mode 100644 tests/ui/variance/type-resolve-error-two-structs-deep.rs create mode 100644 tests/ui/variance/type-resolve-error-two-structs-deep.stderr diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 607068f162a..f788456d4e9 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1875,24 +1875,15 @@ fn check_variances_for_type_defn<'tcx>( item: &'tcx hir::Item<'tcx>, hir_generics: &hir::Generics<'tcx>, ) { - let identity_args = ty::GenericArgs::identity_for_item(tcx, item.owner_id); - match item.kind { ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) => { - for field in tcx.adt_def(item.owner_id).all_fields() { - if field.ty(tcx, identity_args).references_error() { - return; - } - } + // Ok } ItemKind::TyAlias(..) => { assert!( tcx.type_alias_is_lazy(item.owner_id), "should not be computing variance of non-weak type alias" ); - if tcx.type_of(item.owner_id).skip_binder().references_error() { - return; - } } kind => span_bug!(item.span, "cannot compute the variances of {kind:?}"), } @@ -1955,6 +1946,15 @@ fn check_variances_for_type_defn<'tcx>( continue; } + // Look for `ErrorGuaranteed` deeply within this type. + if let ControlFlow::Break(ErrorGuaranteed { .. }) = tcx + .type_of(item.owner_id) + .instantiate_identity() + .visit_with(&mut HasErrorDeep { tcx, seen: Default::default() }) + { + continue; + } + match hir_param.name { hir::ParamName::Error => {} _ => { @@ -1965,6 +1965,46 @@ fn check_variances_for_type_defn<'tcx>( } } +/// Look for `ErrorGuaranteed` deeply within structs' (unsubstituted) fields. +struct HasErrorDeep<'tcx> { + tcx: TyCtxt<'tcx>, + seen: FxHashSet, +} +impl<'tcx> TypeVisitor> for HasErrorDeep<'tcx> { + type Result = ControlFlow; + + fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result { + match *ty.kind() { + ty::Adt(def, _) => { + if self.seen.insert(def.did()) { + for field in def.all_fields() { + self.tcx.type_of(field.did).instantiate_identity().visit_with(self)?; + } + } + } + ty::Error(guar) => return ControlFlow::Break(guar), + _ => {} + } + ty.super_visit_with(self) + } + + fn visit_region(&mut self, r: ty::Region<'tcx>) -> Self::Result { + if let Err(guar) = r.error_reported() { + ControlFlow::Break(guar) + } else { + ControlFlow::Continue(()) + } + } + + fn visit_const(&mut self, c: ty::Const<'tcx>) -> Self::Result { + if let Err(guar) = c.error_reported() { + ControlFlow::Break(guar) + } else { + ControlFlow::Continue(()) + } + } +} + fn report_bivariance<'tcx>( tcx: TyCtxt<'tcx>, param: &'tcx hir::GenericParam<'tcx>, diff --git a/tests/ui/variance/type-resolve-error-two-structs-deep.rs b/tests/ui/variance/type-resolve-error-two-structs-deep.rs new file mode 100644 index 00000000000..47ec532ab96 --- /dev/null +++ b/tests/ui/variance/type-resolve-error-two-structs-deep.rs @@ -0,0 +1,13 @@ +// Make sure we don't report bivariance errors when nesting structs w/ unresolved +// fields into *other* structs. + +struct Hello<'a> { + missing: Missing<'a>, + //~^ ERROR cannot find type `Missing` in this scope +} + +struct Other<'a> { + hello: Hello<'a>, +} + +fn main() {} diff --git a/tests/ui/variance/type-resolve-error-two-structs-deep.stderr b/tests/ui/variance/type-resolve-error-two-structs-deep.stderr new file mode 100644 index 00000000000..3458d924bb1 --- /dev/null +++ b/tests/ui/variance/type-resolve-error-two-structs-deep.stderr @@ -0,0 +1,9 @@ +error[E0412]: cannot find type `Missing` in this scope + --> $DIR/type-resolve-error-two-structs-deep.rs:5:14 + | +LL | missing: Missing<'a>, + | ^^^^^^^ not found in this scope + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0412`. From 50b8029ce143aa5ed67aab9d3c05533330df97d6 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 14 Oct 2024 12:40:08 -0400 Subject: [PATCH 329/357] Always recurse on predicates in BestObligation --- compiler/rustc_trait_selection/src/solve/fulfill.rs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index 081d7a6a769..0e2b081448e 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -465,13 +465,7 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> { polarity: ty::PredicatePolarity::Positive, })) } - ty::PredicateKind::Clause( - ty::ClauseKind::WellFormed(_) | ty::ClauseKind::Projection(..), - ) - | ty::PredicateKind::AliasRelate(..) => ChildMode::PassThrough, - _ => { - return ControlFlow::Break(self.obligation.clone()); - } + _ => ChildMode::PassThrough, }; let mut impl_where_bound_count = 0; From fd2038d344c3abb34a0a7812c49f1730c3cee3b2 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 14 Oct 2024 10:52:34 -0400 Subject: [PATCH 330/357] Make sure the alias is actually rigid --- .../src/solve/normalizes_to/mod.rs | 53 ++++++++++++++- .../defaults-unsound-62211-1.next.stderr | 21 ++++-- .../defaults-unsound-62211-2.next.stderr | 21 ++++-- .../associated-types/issue-54108.next.stderr | 21 ++++-- tests/ui/for/issue-20605.next.stderr | 11 +-- ...mbig-hr-projection-issue-93340.next.stderr | 12 +++- .../in-trait/alias-bounds-when-not-wf.stderr | 28 ++++++-- .../impl-trait/method-resolution4.next.stderr | 50 +++++++++++--- .../recursive-coroutine-boxed.next.stderr | 68 +++++++++++++++---- .../impl-trait/unsized_coercion.next.stderr | 35 +++++++--- .../impl-trait/unsized_coercion3.next.stderr | 43 ++++++------ .../opaque-type-unsatisfied-bound.stderr | 62 +++++++++++++++-- .../opaque-type-unsatisfied-fn-bound.stderr | 28 +++++++- .../traits/next-solver/coroutine.fail.stderr | 41 ++++++++++- .../diagnostics/projection-trait-ref.stderr | 33 ++++++++- .../next-solver/dyn-incompatibility.stderr | 15 +++- tests/ui/traits/next-solver/fn-trait.stderr | 61 ++++++++++++++++- .../issue-118950-root-region.stderr | 18 ++--- ...ution_trait_method_from_opaque.next.stderr | 19 +++++- ...hod_resolution_trait_method_from_opaque.rs | 2 + 20 files changed, 530 insertions(+), 112 deletions(-) diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs index 005b293621a..bf1d2bf08b7 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs @@ -15,7 +15,7 @@ use crate::solve::assembly::{self, Candidate}; use crate::solve::inspect::ProbeKind; use crate::solve::{ BuiltinImplSource, CandidateSource, Certainty, EvalCtxt, Goal, GoalSource, MaybeCause, - NoSolution, QueryResult, + NoSolution, QueryResult, Reveal, }; impl EvalCtxt<'_, D> @@ -39,11 +39,58 @@ where Err(NoSolution) => { let Goal { param_env, predicate: NormalizesTo { alias, term } } = goal; self.relate_rigid_alias_non_alias(param_env, alias, ty::Invariant, term)?; + self.add_rigid_constraints(param_env, alias)?; self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } } } + /// Register any obligations that are used to validate that an alias should be + /// treated as rigid. + /// + /// An alias may be considered rigid if it fails normalization, but we also don't + /// want to consider aliases that are not well-formed to be rigid simply because + /// they fail normalization. + /// + /// For example, some `::Assoc` where `T: Trait` does not hold, or an + /// opaque type whose hidden type doesn't actually satisfy the opaque item bounds. + fn add_rigid_constraints( + &mut self, + param_env: I::ParamEnv, + rigid_alias: ty::AliasTerm, + ) -> Result<(), NoSolution> { + match rigid_alias.kind(self.cx()) { + // Projections are rigid only if their trait ref holds. + ty::AliasTermKind::ProjectionTy | ty::AliasTermKind::ProjectionConst => { + let trait_ref = rigid_alias.trait_ref(self.cx()); + self.add_goal(GoalSource::Misc, Goal::new(self.cx(), param_env, trait_ref)); + Ok(()) + } + ty::AliasTermKind::OpaqueTy => { + match param_env.reveal() { + // In user-facing mode, paques are only rigid if we may not define it. + Reveal::UserFacing => { + if rigid_alias + .def_id + .as_local() + .is_some_and(|def_id| self.can_define_opaque_ty(def_id)) + { + Err(NoSolution) + } else { + Ok(()) + } + } + // Opaques are never rigid in reveal-all mode. + Reveal::All => Err(NoSolution), + } + } + // FIXME(generic_const_exprs): we would need to support generic consts here + ty::AliasTermKind::UnevaluatedConst => Err(NoSolution), + // Inherent and weak types are never rigid. This type must not be well-formed. + ty::AliasTermKind::WeakTy | ty::AliasTermKind::InherentTy => Err(NoSolution), + } + } + /// Normalize the given alias by at least one step. If the alias is rigid, this /// returns `NoSolution`. #[instrument(level = "trace", skip(self), ret)] @@ -124,6 +171,7 @@ where ecx.instantiate_normalizes_to_term(goal, assumption_projection_pred.term); // Add GAT where clauses from the trait's definition + // FIXME: We don't need these, since these are the type's own WF obligations. ecx.add_goals( GoalSource::Misc, cx.own_predicates_of(goal.predicate.def_id()) @@ -179,7 +227,8 @@ where .map(|pred| goal.with(cx, pred)); ecx.add_goals(GoalSource::ImplWhereBound, where_clause_bounds); - // Add GAT where clauses from the trait's definition + // Add GAT where clauses from the trait's definition. + // FIXME: We don't need these, since these are the type's own WF obligations. ecx.add_goals( GoalSource::Misc, cx.own_predicates_of(goal.predicate.def_id()) diff --git a/tests/ui/associated-types/defaults-unsound-62211-1.next.stderr b/tests/ui/associated-types/defaults-unsound-62211-1.next.stderr index 010f51df15a..4523fc3e037 100644 --- a/tests/ui/associated-types/defaults-unsound-62211-1.next.stderr +++ b/tests/ui/associated-types/defaults-unsound-62211-1.next.stderr @@ -31,6 +31,18 @@ help: consider further restricting `Self` LL | trait UncheckedCopy: Sized + AddAssign<&'static str> { | +++++++++++++++++++++++++ +error[E0271]: type mismatch resolving `::Target normalizes-to ::Target` + --> $DIR/defaults-unsound-62211-1.rs:24:96 + | +LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; + | ^^^^ types differ + | +note: required by a bound in `UncheckedCopy::Output` + --> $DIR/defaults-unsound-62211-1.rs:24:31 + | +LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; + | ^^^^^^^^^^^^ required by this bound in `UncheckedCopy::Output` + error[E0277]: the trait bound `Self: Deref` is not satisfied --> $DIR/defaults-unsound-62211-1.rs:24:96 | @@ -38,10 +50,10 @@ LL | type Output: Copy + Deref + AddAssign<&'static str> + Fro | ^^^^ the trait `Deref` is not implemented for `Self` | note: required by a bound in `UncheckedCopy::Output` - --> $DIR/defaults-unsound-62211-1.rs:24:31 + --> $DIR/defaults-unsound-62211-1.rs:24:25 | LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; - | ^^^^^^^^^^^^ required by this bound in `UncheckedCopy::Output` + | ^^^^^^^^^^^^^^^^^^^ required by this bound in `UncheckedCopy::Output` help: consider further restricting `Self` | LL | trait UncheckedCopy: Sized + Deref { @@ -63,6 +75,7 @@ help: consider further restricting `Self` LL | trait UncheckedCopy: Sized + Copy { | ++++++ -error: aborting due to 4 previous errors +error: aborting due to 5 previous errors -For more information about this error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0271, E0277. +For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/associated-types/defaults-unsound-62211-2.next.stderr b/tests/ui/associated-types/defaults-unsound-62211-2.next.stderr index 93478946570..7a68f1ac8cc 100644 --- a/tests/ui/associated-types/defaults-unsound-62211-2.next.stderr +++ b/tests/ui/associated-types/defaults-unsound-62211-2.next.stderr @@ -31,6 +31,18 @@ help: consider further restricting `Self` LL | trait UncheckedCopy: Sized + AddAssign<&'static str> { | +++++++++++++++++++++++++ +error[E0271]: type mismatch resolving `::Target normalizes-to ::Target` + --> $DIR/defaults-unsound-62211-2.rs:24:96 + | +LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; + | ^^^^ types differ + | +note: required by a bound in `UncheckedCopy::Output` + --> $DIR/defaults-unsound-62211-2.rs:24:31 + | +LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; + | ^^^^^^^^^^^^ required by this bound in `UncheckedCopy::Output` + error[E0277]: the trait bound `Self: Deref` is not satisfied --> $DIR/defaults-unsound-62211-2.rs:24:96 | @@ -38,10 +50,10 @@ LL | type Output: Copy + Deref + AddAssign<&'static str> + Fro | ^^^^ the trait `Deref` is not implemented for `Self` | note: required by a bound in `UncheckedCopy::Output` - --> $DIR/defaults-unsound-62211-2.rs:24:31 + --> $DIR/defaults-unsound-62211-2.rs:24:25 | LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; - | ^^^^^^^^^^^^ required by this bound in `UncheckedCopy::Output` + | ^^^^^^^^^^^^^^^^^^^ required by this bound in `UncheckedCopy::Output` help: consider further restricting `Self` | LL | trait UncheckedCopy: Sized + Deref { @@ -63,6 +75,7 @@ help: consider further restricting `Self` LL | trait UncheckedCopy: Sized + Copy { | ++++++ -error: aborting due to 4 previous errors +error: aborting due to 5 previous errors -For more information about this error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0271, E0277. +For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/associated-types/issue-54108.next.stderr b/tests/ui/associated-types/issue-54108.next.stderr index 5e2fa551afe..0866ed05451 100644 --- a/tests/ui/associated-types/issue-54108.next.stderr +++ b/tests/ui/associated-types/issue-54108.next.stderr @@ -1,3 +1,15 @@ +error[E0271]: type mismatch resolving `<::ActualSize as Add>::Output normalizes-to <::ActualSize as Add>::Output` + --> $DIR/issue-54108.rs:23:17 + | +LL | type Size = ::ActualSize; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ + | +note: required by a bound in `Encoder::Size` + --> $DIR/issue-54108.rs:8:20 + | +LL | type Size: Add; + | ^^^^^^^^^^^^^^^^^^^ required by this bound in `Encoder::Size` + error[E0277]: cannot add `::ActualSize` to `::ActualSize` --> $DIR/issue-54108.rs:23:17 | @@ -6,15 +18,16 @@ LL | type Size = ::ActualSize; | = help: the trait `Add` is not implemented for `::ActualSize` note: required by a bound in `Encoder::Size` - --> $DIR/issue-54108.rs:8:20 + --> $DIR/issue-54108.rs:8:16 | LL | type Size: Add; - | ^^^^^^^^^^^^^^^^^^^ required by this bound in `Encoder::Size` + | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Encoder::Size` help: consider further restricting the associated type | LL | T: SubEncoder, ::ActualSize: Add | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -error: aborting due to 1 previous error +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0271, E0277. +For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/for/issue-20605.next.stderr b/tests/ui/for/issue-20605.next.stderr index 98609211865..1a66cb41464 100644 --- a/tests/ui/for/issue-20605.next.stderr +++ b/tests/ui/for/issue-20605.next.stderr @@ -11,13 +11,6 @@ help: consider mutably borrowing here LL | for item in &mut *things { *item = 0 } | ++++ -error[E0614]: type ` as IntoIterator>::Item` cannot be dereferenced - --> $DIR/issue-20605.rs:6:27 - | -LL | for item in *things { *item = 0 } - | ^^^^^ +error: aborting due to 1 previous error -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0277, E0614. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.next.stderr b/tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.next.stderr index d913b2e91ca..bc57874bf85 100644 --- a/tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.next.stderr +++ b/tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.next.stderr @@ -15,6 +15,14 @@ help: consider specifying the generic arguments LL | cmp_eq:: | +++++++++++ -error: aborting due to 1 previous error +error[E0271]: type mismatch resolving `build_expression::{opaque#0} normalizes-to _` + --> $DIR/ambig-hr-projection-issue-93340.rs:14:1 + | +LL | / fn build_expression( +LL | | ) -> impl Fn(A::RefType<'_>, B::RefType<'_>) -> O { + | |_________________________________________________^ types differ -For more information about this error, try `rustc --explain E0283`. +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0271, E0283. +For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.stderr b/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.stderr index 9663fab3d8c..cab6163803a 100644 --- a/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.stderr +++ b/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.stderr @@ -7,14 +7,32 @@ LL | #![feature(lazy_type_alias)] = note: see issue #112792 for more information = note: `#[warn(incomplete_features)]` on by default -error[E0277]: the size for values of type `A` cannot be known at compilation time +error[E0271]: type mismatch resolving `A normalizes-to _` --> $DIR/alias-bounds-when-not-wf.rs:16:13 | LL | fn hello(_: W>) {} - | ^^^^^^^^^^^ doesn't have a size known at compile-time + | ^^^^^^^^^^^ types differ + +error[E0271]: type mismatch resolving `A normalizes-to _` + --> $DIR/alias-bounds-when-not-wf.rs:16:10 | - = help: the trait `Sized` is not implemented for `A` +LL | fn hello(_: W>) {} + | ^ types differ -error: aborting due to 1 previous error; 1 warning emitted +error[E0271]: type mismatch resolving `A normalizes-to _` + --> $DIR/alias-bounds-when-not-wf.rs:16:10 + | +LL | fn hello(_: W>) {} + | ^ types differ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -For more information about this error, try `rustc --explain E0277`. +error[E0271]: type mismatch resolving `A normalizes-to _` + --> $DIR/alias-bounds-when-not-wf.rs:16:1 + | +LL | fn hello(_: W>) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ types differ + +error: aborting due to 4 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/impl-trait/method-resolution4.next.stderr b/tests/ui/impl-trait/method-resolution4.next.stderr index b48de0af357..5aa6931d371 100644 --- a/tests/ui/impl-trait/method-resolution4.next.stderr +++ b/tests/ui/impl-trait/method-resolution4.next.stderr @@ -4,19 +4,51 @@ error[E0282]: type annotations needed LL | foo(false).next().unwrap(); | ^^^^^^^^^^ cannot infer type -error[E0308]: mismatched types - --> $DIR/method-resolution4.rs:16:5 +error[E0271]: type mismatch resolving `foo::{opaque#0} normalizes-to _` + --> $DIR/method-resolution4.rs:13:9 + | +LL | foo(false).next().unwrap(); + | ^^^^^^^^^^ types differ + +error[E0277]: the size for values of type `impl Iterator` cannot be known at compilation time + --> $DIR/method-resolution4.rs:11:20 | LL | fn foo(b: bool) -> impl Iterator { - | ------------------------ the expected opaque type -... + | ^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `impl Iterator` + = note: the return type of a function must have a statically known size + +error[E0271]: type mismatch resolving `foo::{opaque#0} normalizes-to _` + --> $DIR/method-resolution4.rs:16:5 + | LL | std::iter::empty() | ^^^^^^^^^^^^^^^^^^ types differ + +error[E0277]: the size for values of type `impl Iterator` cannot be known at compilation time + --> $DIR/method-resolution4.rs:13:9 | - = note: expected opaque type `impl Iterator` - found struct `std::iter::Empty<_>` +LL | foo(false).next().unwrap(); + | ^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `impl Iterator` + = note: the return type of a function must have a statically known size -error: aborting due to 2 previous errors +error[E0271]: type mismatch resolving `foo::{opaque#0} normalizes-to _` + --> $DIR/method-resolution4.rs:13:9 + | +LL | foo(false).next().unwrap(); + | ^^^^^^^^^^ types differ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -Some errors have detailed explanations: E0282, E0308. -For more information about an error, try `rustc --explain E0282`. +error[E0271]: type mismatch resolving `foo::{opaque#0} normalizes-to _` + --> $DIR/method-resolution4.rs:11:1 + | +LL | fn foo(b: bool) -> impl Iterator { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ + +error: aborting due to 7 previous errors + +Some errors have detailed explanations: E0271, E0277, E0282. +For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/impl-trait/recursive-coroutine-boxed.next.stderr b/tests/ui/impl-trait/recursive-coroutine-boxed.next.stderr index 96db2030a40..5feef0b44b5 100644 --- a/tests/ui/impl-trait/recursive-coroutine-boxed.next.stderr +++ b/tests/ui/impl-trait/recursive-coroutine-boxed.next.stderr @@ -12,15 +12,37 @@ help: consider specifying the generic argument LL | let mut gen = Box::::pin(foo()); | +++++ -error[E0308]: mismatched types +error[E0271]: type mismatch resolving `foo::{opaque#0} normalizes-to _` + --> $DIR/recursive-coroutine-boxed.rs:14:18 + | +LL | #[coroutine] || { + | __________________^ +LL | | let mut gen = Box::pin(foo()); +LL | | +LL | | let mut r = gen.as_mut().resume(()); +... | +LL | | } +LL | | } + | |_____^ types differ + +error[E0271]: type mismatch resolving `foo::{opaque#0} normalizes-to _` + --> $DIR/recursive-coroutine-boxed.rs:15:32 + | +LL | let mut gen = Box::pin(foo()); + | ^^^^^ types differ + +error[E0277]: the size for values of type `impl Coroutine` cannot be known at compilation time + --> $DIR/recursive-coroutine-boxed.rs:9:13 + | +LL | fn foo() -> impl Coroutine { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `impl Coroutine` + = note: the return type of a function must have a statically known size + +error[E0271]: type mismatch resolving `foo::{opaque#0} normalizes-to _` --> $DIR/recursive-coroutine-boxed.rs:14:18 | -LL | fn foo() -> impl Coroutine { - | --------------------------------------- - | | - | the expected opaque type - | expected `impl Coroutine` because of return type -... LL | #[coroutine] || { | __________________^ LL | | let mut gen = Box::pin(foo()); @@ -31,10 +53,32 @@ LL | | } LL | | } | |_____^ types differ | - = note: expected opaque type `impl Coroutine` - found coroutine `{coroutine@$DIR/recursive-coroutine-boxed.rs:14:18: 14:20}` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 2 previous errors +error[E0277]: the size for values of type `impl Coroutine` cannot be known at compilation time + --> $DIR/recursive-coroutine-boxed.rs:15:32 + | +LL | let mut gen = Box::pin(foo()); + | ^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `impl Coroutine` + = note: the return type of a function must have a statically known size -Some errors have detailed explanations: E0282, E0308. -For more information about an error, try `rustc --explain E0282`. +error[E0271]: type mismatch resolving `foo::{opaque#0} normalizes-to _` + --> $DIR/recursive-coroutine-boxed.rs:15:32 + | +LL | let mut gen = Box::pin(foo()); + | ^^^^^ types differ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0271]: type mismatch resolving `foo::{opaque#0} normalizes-to _` + --> $DIR/recursive-coroutine-boxed.rs:9:1 + | +LL | fn foo() -> impl Coroutine { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0271, E0277, E0282. +For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/impl-trait/unsized_coercion.next.stderr b/tests/ui/impl-trait/unsized_coercion.next.stderr index 49ac3f1845f..f31a2a80667 100644 --- a/tests/ui/impl-trait/unsized_coercion.next.stderr +++ b/tests/ui/impl-trait/unsized_coercion.next.stderr @@ -1,26 +1,39 @@ -error[E0271]: type mismatch resolving `impl Trait <: dyn Trait` +error[E0271]: type mismatch resolving `hello::{opaque#0} normalizes-to _` --> $DIR/unsized_coercion.rs:14:17 | LL | let x = hello(); | ^^^^^^^ types differ error[E0308]: mismatched types - --> $DIR/unsized_coercion.rs:18:14 + --> $DIR/unsized_coercion.rs:18:5 | LL | fn hello() -> Box { - | ---------- the expected opaque type + | --------------- + | | | + | | the expected opaque type + | expected `Box` because of return type ... LL | Box::new(1u32) - | -------- ^^^^ types differ - | | - | arguments to this function are incorrect + | ^^^^^^^^^^^^^^ types differ | - = note: expected opaque type `impl Trait` - found type `u32` -note: associated function defined here - --> $SRC_DIR/alloc/src/boxed.rs:LL:COL + = note: expected struct `Box` + found struct `Box` -error: aborting due to 2 previous errors +error[E0271]: type mismatch resolving `hello::{opaque#0} normalizes-to _` + --> $DIR/unsized_coercion.rs:14:17 + | +LL | let x = hello(); + | ^^^^^^^ types differ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0271]: type mismatch resolving `hello::{opaque#0} normalizes-to _` + --> $DIR/unsized_coercion.rs:12:1 + | +LL | fn hello() -> Box { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ + +error: aborting due to 4 previous errors Some errors have detailed explanations: E0271, E0308. For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/impl-trait/unsized_coercion3.next.stderr b/tests/ui/impl-trait/unsized_coercion3.next.stderr index 586ae076028..f5187a6256e 100644 --- a/tests/ui/impl-trait/unsized_coercion3.next.stderr +++ b/tests/ui/impl-trait/unsized_coercion3.next.stderr @@ -1,38 +1,39 @@ -error[E0271]: type mismatch resolving `impl Trait + ?Sized <: dyn Send` +error[E0271]: type mismatch resolving `hello::{opaque#0} normalizes-to _` --> $DIR/unsized_coercion3.rs:13:17 | LL | let x = hello(); | ^^^^^^^ types differ error[E0308]: mismatched types - --> $DIR/unsized_coercion3.rs:18:14 + --> $DIR/unsized_coercion3.rs:18:5 | LL | fn hello() -> Box { - | ------------------- the expected opaque type + | ------------------------ + | | | + | | the expected opaque type + | expected `Box` because of return type ... LL | Box::new(1u32) - | -------- ^^^^ types differ - | | - | arguments to this function are incorrect + | ^^^^^^^^^^^^^^ types differ | - = note: expected opaque type `impl Trait + ?Sized` - found type `u32` -note: associated function defined here - --> $SRC_DIR/alloc/src/boxed.rs:LL:COL + = note: expected struct `Box` + found struct `Box` -error[E0277]: the size for values of type `impl Trait + ?Sized` cannot be known at compilation time - --> $DIR/unsized_coercion3.rs:18:14 +error[E0271]: type mismatch resolving `hello::{opaque#0} normalizes-to _` + --> $DIR/unsized_coercion3.rs:13:17 | -LL | Box::new(1u32) - | -------- ^^^^ doesn't have a size known at compile-time - | | - | required by a bound introduced by this call +LL | let x = hello(); + | ^^^^^^^ types differ | - = help: the trait `Sized` is not implemented for `impl Trait + ?Sized` -note: required by a bound in `Box::::new` - --> $SRC_DIR/alloc/src/boxed.rs:LL:COL + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 3 previous errors +error[E0271]: type mismatch resolving `hello::{opaque#0} normalizes-to _` + --> $DIR/unsized_coercion3.rs:11:1 + | +LL | fn hello() -> Box { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ -Some errors have detailed explanations: E0271, E0277, E0308. +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0271, E0308. For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.stderr b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.stderr index 3dd2b27b55b..561bf8eee22 100644 --- a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.stderr +++ b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.stderr @@ -1,21 +1,69 @@ -error[E0271]: type mismatch resolving `impl !Sized + Sized == ()` +error[E0271]: type mismatch resolving `weird0::{opaque#0} normalizes-to _` --> $DIR/opaque-type-unsatisfied-bound.rs:15:16 | LL | fn weird0() -> impl Sized + !Sized {} | ^^^^^^^^^^^^^^^^^^^ types differ -error[E0271]: type mismatch resolving `impl !Sized + Sized == ()` +error[E0271]: type mismatch resolving `weird0::{opaque#0} normalizes-to _` + --> $DIR/opaque-type-unsatisfied-bound.rs:15:36 + | +LL | fn weird0() -> impl Sized + !Sized {} + | ^^ types differ + +error[E0277]: the size for values of type `impl !Sized + Sized` cannot be known at compilation time + --> $DIR/opaque-type-unsatisfied-bound.rs:15:16 + | +LL | fn weird0() -> impl Sized + !Sized {} + | ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `impl !Sized + Sized` + = note: the return type of a function must have a statically known size + +error[E0271]: type mismatch resolving `weird0::{opaque#0} normalizes-to _` + --> $DIR/opaque-type-unsatisfied-bound.rs:15:1 + | +LL | fn weird0() -> impl Sized + !Sized {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ + +error[E0271]: type mismatch resolving `weird1::{opaque#0} normalizes-to _` --> $DIR/opaque-type-unsatisfied-bound.rs:17:16 | LL | fn weird1() -> impl !Sized + Sized {} | ^^^^^^^^^^^^^^^^^^^ types differ -error[E0271]: type mismatch resolving `impl !Sized == ()` +error[E0271]: type mismatch resolving `weird1::{opaque#0} normalizes-to _` + --> $DIR/opaque-type-unsatisfied-bound.rs:17:36 + | +LL | fn weird1() -> impl !Sized + Sized {} + | ^^ types differ + +error[E0277]: the size for values of type `impl !Sized + Sized` cannot be known at compilation time + --> $DIR/opaque-type-unsatisfied-bound.rs:17:16 + | +LL | fn weird1() -> impl !Sized + Sized {} + | ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `impl !Sized + Sized` + = note: the return type of a function must have a statically known size + +error[E0271]: type mismatch resolving `weird1::{opaque#0} normalizes-to _` + --> $DIR/opaque-type-unsatisfied-bound.rs:17:1 + | +LL | fn weird1() -> impl !Sized + Sized {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ + +error[E0271]: type mismatch resolving `weird2::{opaque#0} normalizes-to _` --> $DIR/opaque-type-unsatisfied-bound.rs:19:16 | LL | fn weird2() -> impl !Sized {} | ^^^^^^^^^^^ types differ +error[E0271]: type mismatch resolving `weird2::{opaque#0} normalizes-to _` + --> $DIR/opaque-type-unsatisfied-bound.rs:19:28 + | +LL | fn weird2() -> impl !Sized {} + | ^^ types differ + error[E0277]: the size for values of type `impl !Sized` cannot be known at compilation time --> $DIR/opaque-type-unsatisfied-bound.rs:19:16 | @@ -25,6 +73,12 @@ LL | fn weird2() -> impl !Sized {} = help: the trait `Sized` is not implemented for `impl !Sized` = note: the return type of a function must have a statically known size +error[E0271]: type mismatch resolving `weird2::{opaque#0} normalizes-to _` + --> $DIR/opaque-type-unsatisfied-bound.rs:19:1 + | +LL | fn weird2() -> impl !Sized {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ + error[E0277]: the trait bound `impl !Trait: Trait` is not satisfied --> $DIR/opaque-type-unsatisfied-bound.rs:12:13 | @@ -39,7 +93,7 @@ note: required by a bound in `consume` LL | fn consume(_: impl Trait) {} | ^^^^^ required by this bound in `consume` -error: aborting due to 5 previous errors +error: aborting due to 13 previous errors Some errors have detailed explanations: E0271, E0277. For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.stderr b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.stderr index e1b84e0df7a..a7a83cf1d69 100644 --- a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.stderr +++ b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.stderr @@ -1,9 +1,31 @@ -error[E0271]: type mismatch resolving `impl !Fn<(u32,)> == ()` +error[E0271]: type mismatch resolving `produce::{opaque#0} normalizes-to _` --> $DIR/opaque-type-unsatisfied-fn-bound.rs:5:17 | LL | fn produce() -> impl !Fn<(u32,)> {} | ^^^^^^^^^^^^^^^^ types differ -error: aborting due to 1 previous error +error[E0271]: type mismatch resolving `produce::{opaque#0} normalizes-to _` + --> $DIR/opaque-type-unsatisfied-fn-bound.rs:5:34 + | +LL | fn produce() -> impl !Fn<(u32,)> {} + | ^^ types differ -For more information about this error, try `rustc --explain E0271`. +error[E0277]: the size for values of type `impl !Fn<(u32,)>` cannot be known at compilation time + --> $DIR/opaque-type-unsatisfied-fn-bound.rs:5:17 + | +LL | fn produce() -> impl !Fn<(u32,)> {} + | ^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `impl !Fn<(u32,)>` + = note: the return type of a function must have a statically known size + +error[E0271]: type mismatch resolving `produce::{opaque#0} normalizes-to _` + --> $DIR/opaque-type-unsatisfied-fn-bound.rs:5:1 + | +LL | fn produce() -> impl !Fn<(u32,)> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0271, E0277. +For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/traits/next-solver/coroutine.fail.stderr b/tests/ui/traits/next-solver/coroutine.fail.stderr index 8c263e8644b..b37dbc0e579 100644 --- a/tests/ui/traits/next-solver/coroutine.fail.stderr +++ b/tests/ui/traits/next-solver/coroutine.fail.stderr @@ -16,6 +16,43 @@ note: required by a bound in `needs_coroutine` LL | fn needs_coroutine(_: impl Coroutine) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `needs_coroutine` -error: aborting due to 1 previous error +error[E0271]: type mismatch resolving `<{coroutine@$DIR/coroutine.rs:20:9: 20:11} as Coroutine>::Yield normalizes-to <{coroutine@$DIR/coroutine.rs:20:9: 20:11} as Coroutine>::Yield` + --> $DIR/coroutine.rs:20:9 + | +LL | needs_coroutine( + | --------------- required by a bound introduced by this call +LL | #[coroutine] +LL | / || { +LL | | +LL | | yield (); +LL | | }, + | |_________^ types differ + | +note: required by a bound in `needs_coroutine` + --> $DIR/coroutine.rs:14:41 + | +LL | fn needs_coroutine(_: impl Coroutine) {} + | ^^^^^^^^^ required by this bound in `needs_coroutine` -For more information about this error, try `rustc --explain E0277`. +error[E0271]: type mismatch resolving `<{coroutine@$DIR/coroutine.rs:20:9: 20:11} as Coroutine>::Return normalizes-to <{coroutine@$DIR/coroutine.rs:20:9: 20:11} as Coroutine>::Return` + --> $DIR/coroutine.rs:20:9 + | +LL | needs_coroutine( + | --------------- required by a bound introduced by this call +LL | #[coroutine] +LL | / || { +LL | | +LL | | yield (); +LL | | }, + | |_________^ types differ + | +note: required by a bound in `needs_coroutine` + --> $DIR/coroutine.rs:14:52 + | +LL | fn needs_coroutine(_: impl Coroutine) {} + | ^^^^^^^^^^ required by this bound in `needs_coroutine` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0271, E0277. +For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/traits/next-solver/diagnostics/projection-trait-ref.stderr b/tests/ui/traits/next-solver/diagnostics/projection-trait-ref.stderr index cd8d8b3ffcd..dbd2880943c 100644 --- a/tests/ui/traits/next-solver/diagnostics/projection-trait-ref.stderr +++ b/tests/ui/traits/next-solver/diagnostics/projection-trait-ref.stderr @@ -9,6 +9,20 @@ help: consider restricting type parameter `T` LL | fn test_poly() { | +++++++ +error[E0271]: type mismatch resolving `::Assoc normalizes-to ::Assoc` + --> $DIR/projection-trait-ref.rs:8:12 + | +LL | let x: ::Assoc = (); + | ^^^^^^^^^^^^^^^^^^^ types differ + +error[E0271]: type mismatch resolving `::Assoc normalizes-to ::Assoc` + --> $DIR/projection-trait-ref.rs:8:12 + | +LL | let x: ::Assoc = (); + | ^^^^^^^^^^^^^^^^^^^ types differ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + error[E0277]: the trait bound `i32: Trait` is not satisfied --> $DIR/projection-trait-ref.rs:13:12 | @@ -21,6 +35,21 @@ help: this trait has no implementations, consider adding one LL | trait Trait { | ^^^^^^^^^^^ -error: aborting due to 2 previous errors +error[E0271]: type mismatch resolving `::Assoc normalizes-to ::Assoc` + --> $DIR/projection-trait-ref.rs:13:12 + | +LL | let x: ::Assoc = (); + | ^^^^^^^^^^^^^^^^^^^^^ types differ -For more information about this error, try `rustc --explain E0277`. +error[E0271]: type mismatch resolving `::Assoc normalizes-to ::Assoc` + --> $DIR/projection-trait-ref.rs:13:12 + | +LL | let x: ::Assoc = (); + | ^^^^^^^^^^^^^^^^^^^^^ types differ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0271, E0277. +For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/traits/next-solver/dyn-incompatibility.stderr b/tests/ui/traits/next-solver/dyn-incompatibility.stderr index 7f2c0646ef5..adf46686e08 100644 --- a/tests/ui/traits/next-solver/dyn-incompatibility.stderr +++ b/tests/ui/traits/next-solver/dyn-incompatibility.stderr @@ -43,7 +43,20 @@ help: consider restricting type parameter `T` LL | pub fn copy_any(t: &T) -> T { | +++++++++++++++++++ -error: aborting due to 3 previous errors +error[E0277]: the size for values of type ` as Setup>::From` cannot be known at compilation time + --> $DIR/dyn-incompatibility.rs:12:5 + | +LL | copy::>(t) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for ` as Setup>::From` + = note: the return type of a function must have a statically known size +help: consider further restricting the associated type + | +LL | pub fn copy_any(t: &T) -> T where as Setup>::From: Sized { + | +++++++++++++++++++++++++++++++++++++++++++++++++ + +error: aborting due to 4 previous errors Some errors have detailed explanations: E0277, E0308. For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/next-solver/fn-trait.stderr b/tests/ui/traits/next-solver/fn-trait.stderr index 00243fd9059..0dee26d4672 100644 --- a/tests/ui/traits/next-solver/fn-trait.stderr +++ b/tests/ui/traits/next-solver/fn-trait.stderr @@ -15,6 +15,20 @@ note: required by a bound in `require_fn` LL | fn require_fn(_: impl Fn() -> i32) {} | ^^^^^^^^^^^ required by this bound in `require_fn` +error[E0271]: type mismatch resolving ` i32 as FnOnce<()>>::Output normalizes-to i32 as FnOnce<()>>::Output` + --> $DIR/fn-trait.rs:20:16 + | +LL | require_fn(f as unsafe fn() -> i32); + | ---------- ^^^^^^^^^^^^^^^^^^^^^^^ types differ + | | + | required by a bound introduced by this call + | +note: required by a bound in `require_fn` + --> $DIR/fn-trait.rs:3:31 + | +LL | fn require_fn(_: impl Fn() -> i32) {} + | ^^^ required by this bound in `require_fn` + error[E0277]: expected a `Fn()` closure, found `extern "C" fn() -> i32 {g}` --> $DIR/fn-trait.rs:22:16 | @@ -31,6 +45,20 @@ note: required by a bound in `require_fn` LL | fn require_fn(_: impl Fn() -> i32) {} | ^^^^^^^^^^^ required by this bound in `require_fn` +error[E0271]: type mismatch resolving ` i32 {g} as FnOnce<()>>::Output normalizes-to i32 {g} as FnOnce<()>>::Output` + --> $DIR/fn-trait.rs:22:16 + | +LL | require_fn(g); + | ---------- ^ types differ + | | + | required by a bound introduced by this call + | +note: required by a bound in `require_fn` + --> $DIR/fn-trait.rs:3:31 + | +LL | fn require_fn(_: impl Fn() -> i32) {} + | ^^^ required by this bound in `require_fn` + error[E0277]: expected a `Fn()` closure, found `extern "C" fn() -> i32` --> $DIR/fn-trait.rs:24:16 | @@ -47,6 +75,20 @@ note: required by a bound in `require_fn` LL | fn require_fn(_: impl Fn() -> i32) {} | ^^^^^^^^^^^ required by this bound in `require_fn` +error[E0271]: type mismatch resolving ` i32 as FnOnce<()>>::Output normalizes-to i32 as FnOnce<()>>::Output` + --> $DIR/fn-trait.rs:24:16 + | +LL | require_fn(g as extern "C" fn() -> i32); + | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ + | | + | required by a bound introduced by this call + | +note: required by a bound in `require_fn` + --> $DIR/fn-trait.rs:3:31 + | +LL | fn require_fn(_: impl Fn() -> i32) {} + | ^^^ required by this bound in `require_fn` + error[E0277]: expected a `Fn()` closure, found `unsafe fn() -> i32 {h}` --> $DIR/fn-trait.rs:26:16 | @@ -64,6 +106,21 @@ note: required by a bound in `require_fn` LL | fn require_fn(_: impl Fn() -> i32) {} | ^^^^^^^^^^^ required by this bound in `require_fn` -error: aborting due to 4 previous errors +error[E0271]: type mismatch resolving ` i32 {h} as FnOnce<()>>::Output normalizes-to i32 {h} as FnOnce<()>>::Output` + --> $DIR/fn-trait.rs:26:16 + | +LL | require_fn(h); + | ---------- ^ types differ + | | + | required by a bound introduced by this call + | +note: required by a bound in `require_fn` + --> $DIR/fn-trait.rs:3:31 + | +LL | fn require_fn(_: impl Fn() -> i32) {} + | ^^^ required by this bound in `require_fn` -For more information about this error, try `rustc --explain E0277`. +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0271, E0277. +For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/traits/next-solver/issue-118950-root-region.stderr b/tests/ui/traits/next-solver/issue-118950-root-region.stderr index 7c3e22fb401..82ec9e3a22f 100644 --- a/tests/ui/traits/next-solver/issue-118950-root-region.stderr +++ b/tests/ui/traits/next-solver/issue-118950-root-region.stderr @@ -26,21 +26,13 @@ LL | trait ToUnit<'a> { | ^^^^^^^^^^^^^^^^ WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: ['^0.Named(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), "'a"), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc), .. } - WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: ['^0.Named(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), "'a"), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc), .. } - WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: ['^0.Named(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), "'a"), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc), .. } - WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: ['^0.Named(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), "'a"), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc), .. } -error[E0119]: conflicting implementations of trait `Overlap` for type `fn(_)` - --> $DIR/issue-118950-root-region.rs:19:1 +error[E0271]: type mismatch resolving `Assoc<'a, T> normalizes-to _` + --> $DIR/issue-118950-root-region.rs:19:17 | -LL | impl Overlap for T {} - | ------------------------ first implementation here -LL | LL | impl Overlap fn(Assoc<'a, T>)> for T where Missing: Overlap {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `fn(_)` - | - = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details + | ^^^^^^^^^^^^^^^^^^^^^^^^ types differ error: aborting due to 3 previous errors; 1 warning emitted -Some errors have detailed explanations: E0119, E0277, E0412. -For more information about an error, try `rustc --explain E0119`. +Some errors have detailed explanations: E0271, E0277, E0412. +For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.next.stderr b/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.next.stderr index 2617ce124c1..f953111aef0 100644 --- a/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.next.stderr +++ b/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.next.stderr @@ -4,6 +4,21 @@ error[E0282]: type annotations needed LL | self.bar.next().unwrap(); | ^^^^^^^^ cannot infer type -error: aborting due to 1 previous error +error[E0271]: type mismatch resolving `Tait normalizes-to _` + --> $DIR/method_resolution_trait_method_from_opaque.rs:26:9 + | +LL | self.bar.next().unwrap(); + | ^^^^^^^^ types differ -For more information about this error, try `rustc --explain E0282`. +error[E0271]: type mismatch resolving `Tait normalizes-to _` + --> $DIR/method_resolution_trait_method_from_opaque.rs:26:9 + | +LL | self.bar.next().unwrap(); + | ^^^^^^^^ types differ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0271, E0282. +For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.rs b/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.rs index b6adf08853f..5c9a3b7c2d2 100644 --- a/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.rs +++ b/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.rs @@ -25,6 +25,8 @@ impl Foo { //[current]~^ ERROR: item does not constrain self.bar.next().unwrap(); //[next]~^ ERROR: type annotations needed + //[next]~| ERROR type mismatch resolving `Tait normalizes-to _` + //[next]~| ERROR type mismatch resolving `Tait normalizes-to _` } } From 8528387743709360f1cb2d3b5538342ec71bd03a Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 14 Oct 2024 13:04:10 -0400 Subject: [PATCH 331/357] Be better at reporting alias errors --- .../src/solve/eval_ctxt/mod.rs | 2 +- .../src/solve/normalizes_to/mod.rs | 20 +++-- .../src/solve/fulfill.rs | 17 ++++- .../src/solve/inspect/analyse.rs | 6 +- .../rustc_trait_selection/src/solve/select.rs | 3 +- compiler/rustc_type_ir/src/solve/inspect.rs | 2 + compiler/rustc_type_ir/src/solve/mod.rs | 4 + .../defaults-unsound-62211-1.next.stderr | 21 +----- .../defaults-unsound-62211-2.next.stderr | 21 +----- .../associated-types/issue-54108.next.stderr | 21 +----- tests/ui/for/issue-20605.rs | 7 +- ...mbig-hr-projection-issue-93340.next.stderr | 12 +-- ...ambig-hr-projection-issue-93340.old.stderr | 2 +- .../ambig-hr-projection-issue-93340.rs | 1 + .../in-trait/alias-bounds-when-not-wf.rs | 4 +- .../in-trait/alias-bounds-when-not-wf.stderr | 38 ++++++---- .../impl-trait/method-resolution4.next.stderr | 36 ++------- tests/ui/impl-trait/method-resolution4.rs | 3 +- .../recursive-coroutine-boxed.next.stderr | 60 ++------------- .../impl-trait/recursive-coroutine-boxed.rs | 6 +- .../impl-trait/unsized_coercion.next.stderr | 30 ++++---- tests/ui/impl-trait/unsized_coercion.rs | 3 +- .../impl-trait/unsized_coercion3.next.stderr | 30 ++++---- .../impl-trait/unsized_coercion3.old.stderr | 2 +- tests/ui/impl-trait/unsized_coercion3.rs | 4 +- .../opaque-type-unsatisfied-bound.rs | 16 +++- .../opaque-type-unsatisfied-bound.stderr | 73 ++++++++++++------- .../opaque-type-unsatisfied-fn-bound.rs | 5 +- .../opaque-type-unsatisfied-fn-bound.stderr | 21 ++++-- .../traits/next-solver/coroutine.fail.stderr | 41 +---------- .../diagnostics/projection-trait-ref.stderr | 33 +-------- .../traits/next-solver/dyn-incompatibility.rs | 1 + tests/ui/traits/next-solver/fn-trait.stderr | 61 +--------------- .../next-solver/issue-118950-root-region.rs | 4 +- .../issue-118950-root-region.stderr | 14 +++- .../normalize/normalize-region-obligations.rs | 2 +- ...ution_trait_method_from_opaque.next.stderr | 19 +---- ...hod_resolution_trait_method_from_opaque.rs | 2 - tests/ui/typeck/issue-103899.rs | 10 +-- 39 files changed, 237 insertions(+), 420 deletions(-) diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index daacc669118..0f8b796d602 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -983,7 +983,7 @@ where hidden_ty, &mut goals, ); - self.add_goals(GoalSource::Misc, goals); + self.add_goals(GoalSource::AliasWellFormed, goals); } // Do something for each opaque/hidden pair defined with `def_id` in the diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs index bf1d2bf08b7..4d8b193ee49 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs @@ -37,10 +37,12 @@ where match normalize_result { Ok(res) => Ok(res), Err(NoSolution) => { - let Goal { param_env, predicate: NormalizesTo { alias, term } } = goal; - self.relate_rigid_alias_non_alias(param_env, alias, ty::Invariant, term)?; - self.add_rigid_constraints(param_env, alias)?; - self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + self.probe(|&result| ProbeKind::RigidAlias { result }).enter(|this| { + let Goal { param_env, predicate: NormalizesTo { alias, term } } = goal; + this.add_rigid_constraints(param_env, alias)?; + this.relate_rigid_alias_non_alias(param_env, alias, ty::Invariant, term)?; + this.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + }) } } } @@ -59,11 +61,13 @@ where param_env: I::ParamEnv, rigid_alias: ty::AliasTerm, ) -> Result<(), NoSolution> { - match rigid_alias.kind(self.cx()) { - // Projections are rigid only if their trait ref holds. + let cx = self.cx(); + match rigid_alias.kind(cx) { + // Projections are rigid only if their trait ref holds, + // and the GAT where-clauses hold. ty::AliasTermKind::ProjectionTy | ty::AliasTermKind::ProjectionConst => { - let trait_ref = rigid_alias.trait_ref(self.cx()); - self.add_goal(GoalSource::Misc, Goal::new(self.cx(), param_env, trait_ref)); + let trait_ref = rigid_alias.trait_ref(cx); + self.add_goal(GoalSource::AliasWellFormed, Goal::new(cx, param_env, trait_ref)); Ok(()) } ty::AliasTermKind::OpaqueTy => { diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index 0e2b081448e..0f977beb85a 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -13,7 +13,7 @@ use rustc_middle::bug; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::{self, TyCtxt}; use rustc_next_trait_solver::solve::{GenerateProofTree, HasChanged, SolverDelegateEvalExt as _}; -use tracing::instrument; +use tracing::{instrument, trace}; use super::Certainty; use super::delegate::SolverDelegate; @@ -402,6 +402,7 @@ impl<'tcx> BestObligation<'tcx> { nested_goal.source(), GoalSource::ImplWhereBound | GoalSource::InstantiateHigherRanked + | GoalSource::AliasWellFormed ) && match self.consider_ambiguities { true => { matches!( @@ -416,6 +417,13 @@ impl<'tcx> BestObligation<'tcx> { }) }); } + + // Prefer a non-rigid candidate if there is one. + if candidates.len() > 1 { + candidates.retain(|candidate| { + !matches!(candidate.kind(), inspect::ProbeKind::RigidAlias { .. }) + }); + } } } @@ -430,8 +438,11 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> { self.obligation.cause.span } + #[instrument(level = "trace", skip(self, goal), fields(goal = ?goal.goal()))] fn visit_goal(&mut self, goal: &inspect::InspectGoal<'_, 'tcx>) -> Self::Result { let candidates = self.non_trivial_candidates(goal); + trace!(candidates = ?candidates.iter().map(|c| c.kind()).collect::>()); + let [candidate] = candidates.as_slice() else { return ControlFlow::Break(self.obligation.clone()); }; @@ -470,6 +481,8 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> { let mut impl_where_bound_count = 0; for nested_goal in candidate.instantiate_nested_goals(self.span()) { + trace!(nested_goal = ?(nested_goal.goal(), nested_goal.source(), nested_goal.result())); + let make_obligation = |cause| Obligation { cause, param_env: nested_goal.goal().param_env, @@ -496,7 +509,7 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> { (_, GoalSource::InstantiateHigherRanked) => { obligation = self.obligation.clone(); } - (ChildMode::PassThrough, _) => { + (ChildMode::PassThrough, _) | (_, GoalSource::AliasWellFormed) => { obligation = make_obligation(self.obligation.cause.clone()); } } diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs index 254620e0b59..4975a9ce0c7 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs @@ -292,7 +292,8 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> { | inspect::ProbeKind::Root { .. } | inspect::ProbeKind::TryNormalizeNonRigid { .. } | inspect::ProbeKind::TraitCandidate { .. } - | inspect::ProbeKind::OpaqueTypeStorageLookup { .. } => { + | inspect::ProbeKind::OpaqueTypeStorageLookup { .. } + | inspect::ProbeKind::RigidAlias { .. } => { // Nested probes have to prove goals added in their parent // but do not leak them, so we truncate the added goals // afterwards. @@ -316,7 +317,8 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> { inspect::ProbeKind::Root { result } | inspect::ProbeKind::TryNormalizeNonRigid { result } | inspect::ProbeKind::TraitCandidate { source: _, result } - | inspect::ProbeKind::OpaqueTypeStorageLookup { result } => { + | inspect::ProbeKind::OpaqueTypeStorageLookup { result } + | inspect::ProbeKind::RigidAlias { result } => { // We only add a candidate if `shallow_certainty` was set, which means // that we ended up calling `evaluate_added_goals_and_make_canonical_response`. if let Some(shallow_certainty) = shallow_certainty { diff --git a/compiler/rustc_trait_selection/src/solve/select.rs b/compiler/rustc_trait_selection/src/solve/select.rs index 257fd263b94..1661852903c 100644 --- a/compiler/rustc_trait_selection/src/solve/select.rs +++ b/compiler/rustc_trait_selection/src/solve/select.rs @@ -177,7 +177,8 @@ fn to_selection<'tcx>( | ProbeKind::UpcastProjectionCompatibility | ProbeKind::OpaqueTypeStorageLookup { result: _ } | ProbeKind::Root { result: _ } - | ProbeKind::ShadowedEnvProbing => { + | ProbeKind::ShadowedEnvProbing + | ProbeKind::RigidAlias { result: _ } => { span_bug!(span, "didn't expect to assemble trait candidate from {:#?}", cand.kind()) } }) diff --git a/compiler/rustc_type_ir/src/solve/inspect.rs b/compiler/rustc_type_ir/src/solve/inspect.rs index 099c66f6bdc..138ba8bac88 100644 --- a/compiler/rustc_type_ir/src/solve/inspect.rs +++ b/compiler/rustc_type_ir/src/solve/inspect.rs @@ -135,4 +135,6 @@ pub enum ProbeKind { ShadowedEnvProbing, /// Try to unify an opaque type with an existing key in the storage. OpaqueTypeStorageLookup { result: QueryResult }, + /// Checking that a rigid alias is well-formed. + RigidAlias { result: QueryResult }, } diff --git a/compiler/rustc_type_ir/src/solve/mod.rs b/compiler/rustc_type_ir/src/solve/mod.rs index a0f7658212f..f02c7a32071 100644 --- a/compiler/rustc_type_ir/src/solve/mod.rs +++ b/compiler/rustc_type_ir/src/solve/mod.rs @@ -130,6 +130,10 @@ pub enum GoalSource { ImplWhereBound, /// Instantiating a higher-ranked goal and re-proving it. InstantiateHigherRanked, + /// Predicate required for an alias projection to be well-formed. + /// This is used in two places: projecting to an opaque whose hidden type + /// is already registered in the opaque type storage, and for rigid projections. + AliasWellFormed, } #[derive_where(Clone; I: Interner, Goal: Clone)] diff --git a/tests/ui/associated-types/defaults-unsound-62211-1.next.stderr b/tests/ui/associated-types/defaults-unsound-62211-1.next.stderr index 4523fc3e037..010f51df15a 100644 --- a/tests/ui/associated-types/defaults-unsound-62211-1.next.stderr +++ b/tests/ui/associated-types/defaults-unsound-62211-1.next.stderr @@ -31,18 +31,6 @@ help: consider further restricting `Self` LL | trait UncheckedCopy: Sized + AddAssign<&'static str> { | +++++++++++++++++++++++++ -error[E0271]: type mismatch resolving `::Target normalizes-to ::Target` - --> $DIR/defaults-unsound-62211-1.rs:24:96 - | -LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; - | ^^^^ types differ - | -note: required by a bound in `UncheckedCopy::Output` - --> $DIR/defaults-unsound-62211-1.rs:24:31 - | -LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; - | ^^^^^^^^^^^^ required by this bound in `UncheckedCopy::Output` - error[E0277]: the trait bound `Self: Deref` is not satisfied --> $DIR/defaults-unsound-62211-1.rs:24:96 | @@ -50,10 +38,10 @@ LL | type Output: Copy + Deref + AddAssign<&'static str> + Fro | ^^^^ the trait `Deref` is not implemented for `Self` | note: required by a bound in `UncheckedCopy::Output` - --> $DIR/defaults-unsound-62211-1.rs:24:25 + --> $DIR/defaults-unsound-62211-1.rs:24:31 | LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; - | ^^^^^^^^^^^^^^^^^^^ required by this bound in `UncheckedCopy::Output` + | ^^^^^^^^^^^^ required by this bound in `UncheckedCopy::Output` help: consider further restricting `Self` | LL | trait UncheckedCopy: Sized + Deref { @@ -75,7 +63,6 @@ help: consider further restricting `Self` LL | trait UncheckedCopy: Sized + Copy { | ++++++ -error: aborting due to 5 previous errors +error: aborting due to 4 previous errors -Some errors have detailed explanations: E0271, E0277. -For more information about an error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/defaults-unsound-62211-2.next.stderr b/tests/ui/associated-types/defaults-unsound-62211-2.next.stderr index 7a68f1ac8cc..93478946570 100644 --- a/tests/ui/associated-types/defaults-unsound-62211-2.next.stderr +++ b/tests/ui/associated-types/defaults-unsound-62211-2.next.stderr @@ -31,18 +31,6 @@ help: consider further restricting `Self` LL | trait UncheckedCopy: Sized + AddAssign<&'static str> { | +++++++++++++++++++++++++ -error[E0271]: type mismatch resolving `::Target normalizes-to ::Target` - --> $DIR/defaults-unsound-62211-2.rs:24:96 - | -LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; - | ^^^^ types differ - | -note: required by a bound in `UncheckedCopy::Output` - --> $DIR/defaults-unsound-62211-2.rs:24:31 - | -LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; - | ^^^^^^^^^^^^ required by this bound in `UncheckedCopy::Output` - error[E0277]: the trait bound `Self: Deref` is not satisfied --> $DIR/defaults-unsound-62211-2.rs:24:96 | @@ -50,10 +38,10 @@ LL | type Output: Copy + Deref + AddAssign<&'static str> + Fro | ^^^^ the trait `Deref` is not implemented for `Self` | note: required by a bound in `UncheckedCopy::Output` - --> $DIR/defaults-unsound-62211-2.rs:24:25 + --> $DIR/defaults-unsound-62211-2.rs:24:31 | LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; - | ^^^^^^^^^^^^^^^^^^^ required by this bound in `UncheckedCopy::Output` + | ^^^^^^^^^^^^ required by this bound in `UncheckedCopy::Output` help: consider further restricting `Self` | LL | trait UncheckedCopy: Sized + Deref { @@ -75,7 +63,6 @@ help: consider further restricting `Self` LL | trait UncheckedCopy: Sized + Copy { | ++++++ -error: aborting due to 5 previous errors +error: aborting due to 4 previous errors -Some errors have detailed explanations: E0271, E0277. -For more information about an error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/issue-54108.next.stderr b/tests/ui/associated-types/issue-54108.next.stderr index 0866ed05451..5e2fa551afe 100644 --- a/tests/ui/associated-types/issue-54108.next.stderr +++ b/tests/ui/associated-types/issue-54108.next.stderr @@ -1,15 +1,3 @@ -error[E0271]: type mismatch resolving `<::ActualSize as Add>::Output normalizes-to <::ActualSize as Add>::Output` - --> $DIR/issue-54108.rs:23:17 - | -LL | type Size = ::ActualSize; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ - | -note: required by a bound in `Encoder::Size` - --> $DIR/issue-54108.rs:8:20 - | -LL | type Size: Add; - | ^^^^^^^^^^^^^^^^^^^ required by this bound in `Encoder::Size` - error[E0277]: cannot add `::ActualSize` to `::ActualSize` --> $DIR/issue-54108.rs:23:17 | @@ -18,16 +6,15 @@ LL | type Size = ::ActualSize; | = help: the trait `Add` is not implemented for `::ActualSize` note: required by a bound in `Encoder::Size` - --> $DIR/issue-54108.rs:8:16 + --> $DIR/issue-54108.rs:8:20 | LL | type Size: Add; - | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Encoder::Size` + | ^^^^^^^^^^^^^^^^^^^ required by this bound in `Encoder::Size` help: consider further restricting the associated type | LL | T: SubEncoder, ::ActualSize: Add | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0271, E0277. -For more information about an error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/for/issue-20605.rs b/tests/ui/for/issue-20605.rs index 647dc84028c..5c56e64a017 100644 --- a/tests/ui/for/issue-20605.rs +++ b/tests/ui/for/issue-20605.rs @@ -4,12 +4,7 @@ fn changer<'a>(mut things: Box>) { for item in *things { *item = 0 } - //[current]~^ ERROR `dyn Iterator` is not an iterator - //[next]~^^ ERROR `dyn Iterator` is not an iterator - //[next]~| ERROR type ` as IntoIterator>::Item` cannot be dereferenced - - // FIXME(-Znext-solver): these error messages are horrible and have to be - // improved before we stabilize the new solver. + //~^ ERROR `dyn Iterator` is not an iterator } fn main() {} diff --git a/tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.next.stderr b/tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.next.stderr index bc57874bf85..d624fb1e42b 100644 --- a/tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.next.stderr +++ b/tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.next.stderr @@ -1,5 +1,5 @@ error[E0283]: type annotations needed - --> $DIR/ambig-hr-projection-issue-93340.rs:16:5 + --> $DIR/ambig-hr-projection-issue-93340.rs:17:5 | LL | cmp_eq | ^^^^^^ cannot infer type of the type parameter `A` declared on the function `cmp_eq` @@ -15,14 +15,16 @@ help: consider specifying the generic arguments LL | cmp_eq:: | +++++++++++ -error[E0271]: type mismatch resolving `build_expression::{opaque#0} normalizes-to _` +error[E0277]: expected a `Fn(::RefType<'_>, ::RefType<'_>)` closure, found `for<'a, 'b> fn(::RefType<'a>, <_ as Scalar>::RefType<'b>) -> O {cmp_eq::}` --> $DIR/ambig-hr-projection-issue-93340.rs:14:1 | LL | / fn build_expression( LL | | ) -> impl Fn(A::RefType<'_>, B::RefType<'_>) -> O { - | |_________________________________________________^ types differ + | |_________________________________________________^ expected an `Fn(::RefType<'_>, ::RefType<'_>)` closure, found `for<'a, 'b> fn(::RefType<'a>, <_ as Scalar>::RefType<'b>) -> O {cmp_eq::}` + | + = help: the trait `for<'a, 'b> Fn(::RefType<'a>, ::RefType<'b>)` is not implemented for fn item `for<'a, 'b> fn(::RefType<'a>, <_ as Scalar>::RefType<'b>) -> O {cmp_eq::}` error: aborting due to 2 previous errors -Some errors have detailed explanations: E0271, E0283. -For more information about an error, try `rustc --explain E0271`. +Some errors have detailed explanations: E0277, E0283. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.old.stderr b/tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.old.stderr index d913b2e91ca..4a293d44e0e 100644 --- a/tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.old.stderr +++ b/tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.old.stderr @@ -1,5 +1,5 @@ error[E0283]: type annotations needed - --> $DIR/ambig-hr-projection-issue-93340.rs:16:5 + --> $DIR/ambig-hr-projection-issue-93340.rs:17:5 | LL | cmp_eq | ^^^^^^ cannot infer type of the type parameter `A` declared on the function `cmp_eq` diff --git a/tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.rs b/tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.rs index acfebad38db..5f2e134109e 100644 --- a/tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.rs +++ b/tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.rs @@ -13,6 +13,7 @@ fn cmp_eq<'a, 'b, A: Scalar, B: Scalar, O: Scalar>(a: A::RefType<'a>, b: B::RefT fn build_expression( ) -> impl Fn(A::RefType<'_>, B::RefType<'_>) -> O { + //[next]~^^ expected a `Fn(::RefType<'_>, ::RefType<'_>)` closure cmp_eq //~^ ERROR type annotations needed } diff --git a/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.rs b/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.rs index 5a6bf9bfaef..351cdad4ee1 100644 --- a/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.rs +++ b/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.rs @@ -14,6 +14,8 @@ struct W(T); // `usize: Foo` doesn't hold. Therefore we ICE, because we don't expect to still // encounter weak types in `assemble_alias_bound_candidates_recur`. fn hello(_: W>) {} -//~^ ERROR the size for values of type `A` cannot be known at compilation time +//~^ ERROR the trait bound `usize: Foo` is not satisfied +//~| ERROR the trait bound `usize: Foo` is not satisfied +//~| ERROR the trait bound `usize: Foo` is not satisfied fn main() {} diff --git a/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.stderr b/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.stderr index cab6163803a..79581066a3a 100644 --- a/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.stderr +++ b/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.stderr @@ -7,32 +7,42 @@ LL | #![feature(lazy_type_alias)] = note: see issue #112792 for more information = note: `#[warn(incomplete_features)]` on by default -error[E0271]: type mismatch resolving `A normalizes-to _` +error[E0277]: the trait bound `usize: Foo` is not satisfied --> $DIR/alias-bounds-when-not-wf.rs:16:13 | LL | fn hello(_: W>) {} - | ^^^^^^^^^^^ types differ + | ^^^^^^^^^^^ the trait `Foo` is not implemented for `usize` + | +help: this trait has no implementations, consider adding one + --> $DIR/alias-bounds-when-not-wf.rs:6:1 + | +LL | trait Foo {} + | ^^^^^^^^^ -error[E0271]: type mismatch resolving `A normalizes-to _` +error[E0277]: the trait bound `usize: Foo` is not satisfied --> $DIR/alias-bounds-when-not-wf.rs:16:10 | LL | fn hello(_: W>) {} - | ^ types differ - -error[E0271]: type mismatch resolving `A normalizes-to _` - --> $DIR/alias-bounds-when-not-wf.rs:16:10 + | ^ the trait `Foo` is not implemented for `usize` | -LL | fn hello(_: W>) {} - | ^ types differ +help: this trait has no implementations, consider adding one + --> $DIR/alias-bounds-when-not-wf.rs:6:1 | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +LL | trait Foo {} + | ^^^^^^^^^ -error[E0271]: type mismatch resolving `A normalizes-to _` +error[E0277]: the trait bound `usize: Foo` is not satisfied --> $DIR/alias-bounds-when-not-wf.rs:16:1 | LL | fn hello(_: W>) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^ types differ + | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `usize` + | +help: this trait has no implementations, consider adding one + --> $DIR/alias-bounds-when-not-wf.rs:6:1 + | +LL | trait Foo {} + | ^^^^^^^^^ -error: aborting due to 4 previous errors; 1 warning emitted +error: aborting due to 3 previous errors; 1 warning emitted -For more information about this error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/method-resolution4.next.stderr b/tests/ui/impl-trait/method-resolution4.next.stderr index 5aa6931d371..8eacfd3e44d 100644 --- a/tests/ui/impl-trait/method-resolution4.next.stderr +++ b/tests/ui/impl-trait/method-resolution4.next.stderr @@ -1,15 +1,9 @@ error[E0282]: type annotations needed - --> $DIR/method-resolution4.rs:13:9 + --> $DIR/method-resolution4.rs:14:9 | LL | foo(false).next().unwrap(); | ^^^^^^^^^^ cannot infer type -error[E0271]: type mismatch resolving `foo::{opaque#0} normalizes-to _` - --> $DIR/method-resolution4.rs:13:9 - | -LL | foo(false).next().unwrap(); - | ^^^^^^^^^^ types differ - error[E0277]: the size for values of type `impl Iterator` cannot be known at compilation time --> $DIR/method-resolution4.rs:11:20 | @@ -19,14 +13,8 @@ LL | fn foo(b: bool) -> impl Iterator { = help: the trait `Sized` is not implemented for `impl Iterator` = note: the return type of a function must have a statically known size -error[E0271]: type mismatch resolving `foo::{opaque#0} normalizes-to _` - --> $DIR/method-resolution4.rs:16:5 - | -LL | std::iter::empty() - | ^^^^^^^^^^^^^^^^^^ types differ - error[E0277]: the size for values of type `impl Iterator` cannot be known at compilation time - --> $DIR/method-resolution4.rs:13:9 + --> $DIR/method-resolution4.rs:14:9 | LL | foo(false).next().unwrap(); | ^^^^^^^^^^ doesn't have a size known at compile-time @@ -34,21 +22,7 @@ LL | foo(false).next().unwrap(); = help: the trait `Sized` is not implemented for `impl Iterator` = note: the return type of a function must have a statically known size -error[E0271]: type mismatch resolving `foo::{opaque#0} normalizes-to _` - --> $DIR/method-resolution4.rs:13:9 - | -LL | foo(false).next().unwrap(); - | ^^^^^^^^^^ types differ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +error: aborting due to 3 previous errors -error[E0271]: type mismatch resolving `foo::{opaque#0} normalizes-to _` - --> $DIR/method-resolution4.rs:11:1 - | -LL | fn foo(b: bool) -> impl Iterator { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ - -error: aborting due to 7 previous errors - -Some errors have detailed explanations: E0271, E0277, E0282. -For more information about an error, try `rustc --explain E0271`. +Some errors have detailed explanations: E0277, E0282. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/method-resolution4.rs b/tests/ui/impl-trait/method-resolution4.rs index 91884eb59fd..8eeedf04cbe 100644 --- a/tests/ui/impl-trait/method-resolution4.rs +++ b/tests/ui/impl-trait/method-resolution4.rs @@ -9,12 +9,13 @@ //@[current] check-pass fn foo(b: bool) -> impl Iterator { + //[next]~^ ERROR the size for values of type `impl Iterator` cannot be known at compilation time if b { foo(false).next().unwrap(); //[next]~^ type annotations needed + //[next]~| ERROR the size for values of type `impl Iterator` cannot be known at compilation time } std::iter::empty() - //[next]~^ mismatched types } fn main() {} diff --git a/tests/ui/impl-trait/recursive-coroutine-boxed.next.stderr b/tests/ui/impl-trait/recursive-coroutine-boxed.next.stderr index 5feef0b44b5..b38850c9214 100644 --- a/tests/ui/impl-trait/recursive-coroutine-boxed.next.stderr +++ b/tests/ui/impl-trait/recursive-coroutine-boxed.next.stderr @@ -1,9 +1,9 @@ error[E0282]: type annotations needed - --> $DIR/recursive-coroutine-boxed.rs:15:23 + --> $DIR/recursive-coroutine-boxed.rs:16:23 | LL | let mut gen = Box::pin(foo()); | ^^^^^^^^ cannot infer type of the type parameter `T` declared on the struct `Box` -LL | +... LL | let mut r = gen.as_mut().resume(()); | ------ type must be known at this point | @@ -12,25 +12,6 @@ help: consider specifying the generic argument LL | let mut gen = Box::::pin(foo()); | +++++ -error[E0271]: type mismatch resolving `foo::{opaque#0} normalizes-to _` - --> $DIR/recursive-coroutine-boxed.rs:14:18 - | -LL | #[coroutine] || { - | __________________^ -LL | | let mut gen = Box::pin(foo()); -LL | | -LL | | let mut r = gen.as_mut().resume(()); -... | -LL | | } -LL | | } - | |_____^ types differ - -error[E0271]: type mismatch resolving `foo::{opaque#0} normalizes-to _` - --> $DIR/recursive-coroutine-boxed.rs:15:32 - | -LL | let mut gen = Box::pin(foo()); - | ^^^^^ types differ - error[E0277]: the size for values of type `impl Coroutine` cannot be known at compilation time --> $DIR/recursive-coroutine-boxed.rs:9:13 | @@ -40,23 +21,8 @@ LL | fn foo() -> impl Coroutine { = help: the trait `Sized` is not implemented for `impl Coroutine` = note: the return type of a function must have a statically known size -error[E0271]: type mismatch resolving `foo::{opaque#0} normalizes-to _` - --> $DIR/recursive-coroutine-boxed.rs:14:18 - | -LL | #[coroutine] || { - | __________________^ -LL | | let mut gen = Box::pin(foo()); -LL | | -LL | | let mut r = gen.as_mut().resume(()); -... | -LL | | } -LL | | } - | |_____^ types differ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - error[E0277]: the size for values of type `impl Coroutine` cannot be known at compilation time - --> $DIR/recursive-coroutine-boxed.rs:15:32 + --> $DIR/recursive-coroutine-boxed.rs:16:32 | LL | let mut gen = Box::pin(foo()); | ^^^^^ doesn't have a size known at compile-time @@ -64,21 +30,7 @@ LL | let mut gen = Box::pin(foo()); = help: the trait `Sized` is not implemented for `impl Coroutine` = note: the return type of a function must have a statically known size -error[E0271]: type mismatch resolving `foo::{opaque#0} normalizes-to _` - --> $DIR/recursive-coroutine-boxed.rs:15:32 - | -LL | let mut gen = Box::pin(foo()); - | ^^^^^ types differ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +error: aborting due to 3 previous errors -error[E0271]: type mismatch resolving `foo::{opaque#0} normalizes-to _` - --> $DIR/recursive-coroutine-boxed.rs:9:1 - | -LL | fn foo() -> impl Coroutine { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ - -error: aborting due to 8 previous errors - -Some errors have detailed explanations: E0271, E0277, E0282. -For more information about an error, try `rustc --explain E0271`. +Some errors have detailed explanations: E0277, E0282. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/recursive-coroutine-boxed.rs b/tests/ui/impl-trait/recursive-coroutine-boxed.rs index 24a77d73114..8e670dd78ec 100644 --- a/tests/ui/impl-trait/recursive-coroutine-boxed.rs +++ b/tests/ui/impl-trait/recursive-coroutine-boxed.rs @@ -7,13 +7,15 @@ use std::ops::{Coroutine, CoroutineState}; fn foo() -> impl Coroutine { + //[next]~^ ERROR the size for values of type `impl Coroutine` cannot be known at compilation time + // FIXME(-Znext-solver): this fails with a mismatched types as the // hidden type of the opaque ends up as {type error}. We should not // emit errors for such goals. - - #[coroutine] || { //[next]~ ERROR mismatched types + #[coroutine] || { let mut gen = Box::pin(foo()); //[next]~^ ERROR type annotations needed + //[next]~| ERROR the size for values of type `impl Coroutine` cannot be known at compilation time let mut r = gen.as_mut().resume(()); while let CoroutineState::Yielded(v) = r { yield v; diff --git a/tests/ui/impl-trait/unsized_coercion.next.stderr b/tests/ui/impl-trait/unsized_coercion.next.stderr index f31a2a80667..4cebd26a5be 100644 --- a/tests/ui/impl-trait/unsized_coercion.next.stderr +++ b/tests/ui/impl-trait/unsized_coercion.next.stderr @@ -1,11 +1,13 @@ -error[E0271]: type mismatch resolving `hello::{opaque#0} normalizes-to _` - --> $DIR/unsized_coercion.rs:14:17 +error[E0277]: the size for values of type `dyn Trait` cannot be known at compilation time + --> $DIR/unsized_coercion.rs:15:17 | LL | let x = hello(); - | ^^^^^^^ types differ + | ^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `dyn Trait` error[E0308]: mismatched types - --> $DIR/unsized_coercion.rs:18:5 + --> $DIR/unsized_coercion.rs:19:5 | LL | fn hello() -> Box { | --------------- @@ -19,21 +21,15 @@ LL | Box::new(1u32) = note: expected struct `Box` found struct `Box` -error[E0271]: type mismatch resolving `hello::{opaque#0} normalizes-to _` - --> $DIR/unsized_coercion.rs:14:17 - | -LL | let x = hello(); - | ^^^^^^^ types differ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error[E0271]: type mismatch resolving `hello::{opaque#0} normalizes-to _` +error[E0277]: the size for values of type `dyn Trait` cannot be known at compilation time --> $DIR/unsized_coercion.rs:12:1 | LL | fn hello() -> Box { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `dyn Trait` -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0271, E0308. -For more information about an error, try `rustc --explain E0271`. +Some errors have detailed explanations: E0277, E0308. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/unsized_coercion.rs b/tests/ui/impl-trait/unsized_coercion.rs index 46e040c1428..b3791b38abc 100644 --- a/tests/ui/impl-trait/unsized_coercion.rs +++ b/tests/ui/impl-trait/unsized_coercion.rs @@ -10,9 +10,10 @@ trait Trait {} impl Trait for u32 {} fn hello() -> Box { + //[next]~^ ERROR the size for values of type `dyn Trait` cannot be known at compilation time if true { let x = hello(); - //[next]~^ ERROR: type mismatch resolving `impl Trait <: dyn Trait` + //[next]~^ ERROR: the size for values of type `dyn Trait` cannot be known at compilation time let y: Box = x; } Box::new(1u32) //[next]~ ERROR: mismatched types diff --git a/tests/ui/impl-trait/unsized_coercion3.next.stderr b/tests/ui/impl-trait/unsized_coercion3.next.stderr index f5187a6256e..d1e1809cf16 100644 --- a/tests/ui/impl-trait/unsized_coercion3.next.stderr +++ b/tests/ui/impl-trait/unsized_coercion3.next.stderr @@ -1,11 +1,13 @@ -error[E0271]: type mismatch resolving `hello::{opaque#0} normalizes-to _` - --> $DIR/unsized_coercion3.rs:13:17 +error[E0277]: the trait bound `dyn Send: Trait` is not satisfied + --> $DIR/unsized_coercion3.rs:14:17 | LL | let x = hello(); - | ^^^^^^^ types differ + | ^^^^^^^ the trait `Trait` is not implemented for `dyn Send` + | + = help: the trait `Trait` is implemented for `u32` error[E0308]: mismatched types - --> $DIR/unsized_coercion3.rs:18:5 + --> $DIR/unsized_coercion3.rs:19:5 | LL | fn hello() -> Box { | ------------------------ @@ -19,21 +21,15 @@ LL | Box::new(1u32) = note: expected struct `Box` found struct `Box` -error[E0271]: type mismatch resolving `hello::{opaque#0} normalizes-to _` - --> $DIR/unsized_coercion3.rs:13:17 - | -LL | let x = hello(); - | ^^^^^^^ types differ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error[E0271]: type mismatch resolving `hello::{opaque#0} normalizes-to _` +error[E0277]: the trait bound `dyn Send: Trait` is not satisfied --> $DIR/unsized_coercion3.rs:11:1 | LL | fn hello() -> Box { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `dyn Send` + | + = help: the trait `Trait` is implemented for `u32` -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0271, E0308. -For more information about an error, try `rustc --explain E0271`. +Some errors have detailed explanations: E0277, E0308. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/unsized_coercion3.old.stderr b/tests/ui/impl-trait/unsized_coercion3.old.stderr index 52a72b84a8d..3bb9f9c2095 100644 --- a/tests/ui/impl-trait/unsized_coercion3.old.stderr +++ b/tests/ui/impl-trait/unsized_coercion3.old.stderr @@ -1,5 +1,5 @@ error[E0277]: the size for values of type `impl Trait + ?Sized` cannot be known at compilation time - --> $DIR/unsized_coercion3.rs:15:32 + --> $DIR/unsized_coercion3.rs:16:32 | LL | let y: Box = x; | ^ doesn't have a size known at compile-time diff --git a/tests/ui/impl-trait/unsized_coercion3.rs b/tests/ui/impl-trait/unsized_coercion3.rs index 7e862de2157..c1dd5350e22 100644 --- a/tests/ui/impl-trait/unsized_coercion3.rs +++ b/tests/ui/impl-trait/unsized_coercion3.rs @@ -9,15 +9,15 @@ trait Trait {} impl Trait for u32 {} fn hello() -> Box { + //[next]~^ ERROR: the trait bound `dyn Send: Trait` is not satisfied if true { let x = hello(); - //[next]~^ ERROR: type mismatch resolving `impl Trait + ?Sized <: dyn Send` + //[next]~^ ERROR: the trait bound `dyn Send: Trait` is not satisfied let y: Box = x; //[old]~^ ERROR: the size for values of type `impl Trait + ?Sized` cannot be know } Box::new(1u32) //[next]~^ ERROR: mismatched types - //[next]~| ERROR: the size for values of type `impl Trait + ?Sized` cannot be know } fn main() {} diff --git a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.rs b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.rs index 35757f2339d..70cc47bb022 100644 --- a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.rs +++ b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.rs @@ -13,9 +13,17 @@ fn main() { } fn weird0() -> impl Sized + !Sized {} -//~^ ERROR type mismatch resolving `impl !Sized + Sized == ()` +//~^ ERROR the size for values of type `()` cannot be known at compilation time [E0277] +//~| ERROR the size for values of type `()` cannot be known at compilation time [E0277] +//~| ERROR the size for values of type `impl !Sized + Sized` cannot be known at compilation time [E0277] +//~| ERROR the size for values of type `()` cannot be known at compilation time [E0277] fn weird1() -> impl !Sized + Sized {} -//~^ ERROR type mismatch resolving `impl !Sized + Sized == ()` +//~^ ERROR the size for values of type `()` cannot be known at compilation time [E0277] +//~| ERROR the size for values of type `()` cannot be known at compilation time [E0277] +//~| ERROR the size for values of type `impl !Sized + Sized` cannot be known at compilation time [E0277] +//~| ERROR the size for values of type `()` cannot be known at compilation time [E0277] fn weird2() -> impl !Sized {} -//~^ ERROR type mismatch resolving `impl !Sized == ()` -//~| ERROR the size for values of type `impl !Sized` cannot be known at compilation time +//~^ ERROR the size for values of type `()` cannot be known at compilation time [E0277] +//~| ERROR the size for values of type `()` cannot be known at compilation time [E0277] +//~| ERROR the size for values of type `impl !Sized` cannot be known at compilation time [E0277] +//~| ERROR the size for values of type `()` cannot be known at compilation time [E0277] diff --git a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.stderr b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.stderr index 561bf8eee22..366baf26dea 100644 --- a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.stderr +++ b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.stderr @@ -1,14 +1,18 @@ -error[E0271]: type mismatch resolving `weird0::{opaque#0} normalizes-to _` +error[E0277]: the size for values of type `()` cannot be known at compilation time --> $DIR/opaque-type-unsatisfied-bound.rs:15:16 | LL | fn weird0() -> impl Sized + !Sized {} - | ^^^^^^^^^^^^^^^^^^^ types differ + | ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait bound `(): !Sized` is not satisfied -error[E0271]: type mismatch resolving `weird0::{opaque#0} normalizes-to _` +error[E0277]: the size for values of type `()` cannot be known at compilation time --> $DIR/opaque-type-unsatisfied-bound.rs:15:36 | LL | fn weird0() -> impl Sized + !Sized {} - | ^^ types differ + | ^^ doesn't have a size known at compile-time + | + = help: the trait bound `(): !Sized` is not satisfied error[E0277]: the size for values of type `impl !Sized + Sized` cannot be known at compilation time --> $DIR/opaque-type-unsatisfied-bound.rs:15:16 @@ -19,26 +23,32 @@ LL | fn weird0() -> impl Sized + !Sized {} = help: the trait `Sized` is not implemented for `impl !Sized + Sized` = note: the return type of a function must have a statically known size -error[E0271]: type mismatch resolving `weird0::{opaque#0} normalizes-to _` +error[E0277]: the size for values of type `()` cannot be known at compilation time --> $DIR/opaque-type-unsatisfied-bound.rs:15:1 | LL | fn weird0() -> impl Sized + !Sized {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait bound `(): !Sized` is not satisfied -error[E0271]: type mismatch resolving `weird1::{opaque#0} normalizes-to _` - --> $DIR/opaque-type-unsatisfied-bound.rs:17:16 +error[E0277]: the size for values of type `()` cannot be known at compilation time + --> $DIR/opaque-type-unsatisfied-bound.rs:20:16 | LL | fn weird1() -> impl !Sized + Sized {} - | ^^^^^^^^^^^^^^^^^^^ types differ + | ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait bound `(): !Sized` is not satisfied -error[E0271]: type mismatch resolving `weird1::{opaque#0} normalizes-to _` - --> $DIR/opaque-type-unsatisfied-bound.rs:17:36 +error[E0277]: the size for values of type `()` cannot be known at compilation time + --> $DIR/opaque-type-unsatisfied-bound.rs:20:36 | LL | fn weird1() -> impl !Sized + Sized {} - | ^^ types differ + | ^^ doesn't have a size known at compile-time + | + = help: the trait bound `(): !Sized` is not satisfied error[E0277]: the size for values of type `impl !Sized + Sized` cannot be known at compilation time - --> $DIR/opaque-type-unsatisfied-bound.rs:17:16 + --> $DIR/opaque-type-unsatisfied-bound.rs:20:16 | LL | fn weird1() -> impl !Sized + Sized {} | ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time @@ -46,26 +56,32 @@ LL | fn weird1() -> impl !Sized + Sized {} = help: the trait `Sized` is not implemented for `impl !Sized + Sized` = note: the return type of a function must have a statically known size -error[E0271]: type mismatch resolving `weird1::{opaque#0} normalizes-to _` - --> $DIR/opaque-type-unsatisfied-bound.rs:17:1 +error[E0277]: the size for values of type `()` cannot be known at compilation time + --> $DIR/opaque-type-unsatisfied-bound.rs:20:1 | LL | fn weird1() -> impl !Sized + Sized {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait bound `(): !Sized` is not satisfied -error[E0271]: type mismatch resolving `weird2::{opaque#0} normalizes-to _` - --> $DIR/opaque-type-unsatisfied-bound.rs:19:16 +error[E0277]: the size for values of type `()` cannot be known at compilation time + --> $DIR/opaque-type-unsatisfied-bound.rs:25:16 | LL | fn weird2() -> impl !Sized {} - | ^^^^^^^^^^^ types differ + | ^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait bound `(): !Sized` is not satisfied -error[E0271]: type mismatch resolving `weird2::{opaque#0} normalizes-to _` - --> $DIR/opaque-type-unsatisfied-bound.rs:19:28 +error[E0277]: the size for values of type `()` cannot be known at compilation time + --> $DIR/opaque-type-unsatisfied-bound.rs:25:28 | LL | fn weird2() -> impl !Sized {} - | ^^ types differ + | ^^ doesn't have a size known at compile-time + | + = help: the trait bound `(): !Sized` is not satisfied error[E0277]: the size for values of type `impl !Sized` cannot be known at compilation time - --> $DIR/opaque-type-unsatisfied-bound.rs:19:16 + --> $DIR/opaque-type-unsatisfied-bound.rs:25:16 | LL | fn weird2() -> impl !Sized {} | ^^^^^^^^^^^ doesn't have a size known at compile-time @@ -73,11 +89,13 @@ LL | fn weird2() -> impl !Sized {} = help: the trait `Sized` is not implemented for `impl !Sized` = note: the return type of a function must have a statically known size -error[E0271]: type mismatch resolving `weird2::{opaque#0} normalizes-to _` - --> $DIR/opaque-type-unsatisfied-bound.rs:19:1 +error[E0277]: the size for values of type `()` cannot be known at compilation time + --> $DIR/opaque-type-unsatisfied-bound.rs:25:1 | LL | fn weird2() -> impl !Sized {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait bound `(): !Sized` is not satisfied error[E0277]: the trait bound `impl !Trait: Trait` is not satisfied --> $DIR/opaque-type-unsatisfied-bound.rs:12:13 @@ -95,5 +113,4 @@ LL | fn consume(_: impl Trait) {} error: aborting due to 13 previous errors -Some errors have detailed explanations: E0271, E0277. -For more information about an error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.rs b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.rs index 9951826a846..3633e9f3f48 100644 --- a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.rs +++ b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.rs @@ -3,6 +3,9 @@ #![feature(negative_bounds, unboxed_closures)] fn produce() -> impl !Fn<(u32,)> {} -//~^ ERROR type mismatch resolving `impl !Fn<(u32,)> == ()` +//~^ ERROR expected a `Fn(u32)` closure, found `()` +//~| ERROR expected a `Fn(u32)` closure, found `()` +//~| ERROR the size for values of type `impl !Fn<(u32,)>` cannot be known at compilation time +//~| ERROR expected a `Fn(u32)` closure, found `()` fn main() {} diff --git a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.stderr b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.stderr index a7a83cf1d69..cdd89de0d88 100644 --- a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.stderr +++ b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.stderr @@ -1,14 +1,18 @@ -error[E0271]: type mismatch resolving `produce::{opaque#0} normalizes-to _` +error[E0277]: expected a `Fn(u32)` closure, found `()` --> $DIR/opaque-type-unsatisfied-fn-bound.rs:5:17 | LL | fn produce() -> impl !Fn<(u32,)> {} - | ^^^^^^^^^^^^^^^^ types differ + | ^^^^^^^^^^^^^^^^ expected an `Fn(u32)` closure, found `()` + | + = help: the trait bound `(): !Fn(u32)` is not satisfied -error[E0271]: type mismatch resolving `produce::{opaque#0} normalizes-to _` +error[E0277]: expected a `Fn(u32)` closure, found `()` --> $DIR/opaque-type-unsatisfied-fn-bound.rs:5:34 | LL | fn produce() -> impl !Fn<(u32,)> {} - | ^^ types differ + | ^^ expected an `Fn(u32)` closure, found `()` + | + = help: the trait bound `(): !Fn(u32)` is not satisfied error[E0277]: the size for values of type `impl !Fn<(u32,)>` cannot be known at compilation time --> $DIR/opaque-type-unsatisfied-fn-bound.rs:5:17 @@ -19,13 +23,14 @@ LL | fn produce() -> impl !Fn<(u32,)> {} = help: the trait `Sized` is not implemented for `impl !Fn<(u32,)>` = note: the return type of a function must have a statically known size -error[E0271]: type mismatch resolving `produce::{opaque#0} normalizes-to _` +error[E0277]: expected a `Fn(u32)` closure, found `()` --> $DIR/opaque-type-unsatisfied-fn-bound.rs:5:1 | LL | fn produce() -> impl !Fn<(u32,)> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an `Fn(u32)` closure, found `()` + | + = help: the trait bound `(): !Fn(u32)` is not satisfied error: aborting due to 4 previous errors -Some errors have detailed explanations: E0271, E0277. -For more information about an error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/next-solver/coroutine.fail.stderr b/tests/ui/traits/next-solver/coroutine.fail.stderr index b37dbc0e579..8c263e8644b 100644 --- a/tests/ui/traits/next-solver/coroutine.fail.stderr +++ b/tests/ui/traits/next-solver/coroutine.fail.stderr @@ -16,43 +16,6 @@ note: required by a bound in `needs_coroutine` LL | fn needs_coroutine(_: impl Coroutine) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `needs_coroutine` -error[E0271]: type mismatch resolving `<{coroutine@$DIR/coroutine.rs:20:9: 20:11} as Coroutine>::Yield normalizes-to <{coroutine@$DIR/coroutine.rs:20:9: 20:11} as Coroutine>::Yield` - --> $DIR/coroutine.rs:20:9 - | -LL | needs_coroutine( - | --------------- required by a bound introduced by this call -LL | #[coroutine] -LL | / || { -LL | | -LL | | yield (); -LL | | }, - | |_________^ types differ - | -note: required by a bound in `needs_coroutine` - --> $DIR/coroutine.rs:14:41 - | -LL | fn needs_coroutine(_: impl Coroutine) {} - | ^^^^^^^^^ required by this bound in `needs_coroutine` +error: aborting due to 1 previous error -error[E0271]: type mismatch resolving `<{coroutine@$DIR/coroutine.rs:20:9: 20:11} as Coroutine>::Return normalizes-to <{coroutine@$DIR/coroutine.rs:20:9: 20:11} as Coroutine>::Return` - --> $DIR/coroutine.rs:20:9 - | -LL | needs_coroutine( - | --------------- required by a bound introduced by this call -LL | #[coroutine] -LL | / || { -LL | | -LL | | yield (); -LL | | }, - | |_________^ types differ - | -note: required by a bound in `needs_coroutine` - --> $DIR/coroutine.rs:14:52 - | -LL | fn needs_coroutine(_: impl Coroutine) {} - | ^^^^^^^^^^ required by this bound in `needs_coroutine` - -error: aborting due to 3 previous errors - -Some errors have detailed explanations: E0271, E0277. -For more information about an error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/next-solver/diagnostics/projection-trait-ref.stderr b/tests/ui/traits/next-solver/diagnostics/projection-trait-ref.stderr index dbd2880943c..cd8d8b3ffcd 100644 --- a/tests/ui/traits/next-solver/diagnostics/projection-trait-ref.stderr +++ b/tests/ui/traits/next-solver/diagnostics/projection-trait-ref.stderr @@ -9,20 +9,6 @@ help: consider restricting type parameter `T` LL | fn test_poly() { | +++++++ -error[E0271]: type mismatch resolving `::Assoc normalizes-to ::Assoc` - --> $DIR/projection-trait-ref.rs:8:12 - | -LL | let x: ::Assoc = (); - | ^^^^^^^^^^^^^^^^^^^ types differ - -error[E0271]: type mismatch resolving `::Assoc normalizes-to ::Assoc` - --> $DIR/projection-trait-ref.rs:8:12 - | -LL | let x: ::Assoc = (); - | ^^^^^^^^^^^^^^^^^^^ types differ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - error[E0277]: the trait bound `i32: Trait` is not satisfied --> $DIR/projection-trait-ref.rs:13:12 | @@ -35,21 +21,6 @@ help: this trait has no implementations, consider adding one LL | trait Trait { | ^^^^^^^^^^^ -error[E0271]: type mismatch resolving `::Assoc normalizes-to ::Assoc` - --> $DIR/projection-trait-ref.rs:13:12 - | -LL | let x: ::Assoc = (); - | ^^^^^^^^^^^^^^^^^^^^^ types differ +error: aborting due to 2 previous errors -error[E0271]: type mismatch resolving `::Assoc normalizes-to ::Assoc` - --> $DIR/projection-trait-ref.rs:13:12 - | -LL | let x: ::Assoc = (); - | ^^^^^^^^^^^^^^^^^^^^^ types differ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 6 previous errors - -Some errors have detailed explanations: E0271, E0277. -For more information about an error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/next-solver/dyn-incompatibility.rs b/tests/ui/traits/next-solver/dyn-incompatibility.rs index a347984daf6..b53a6543c90 100644 --- a/tests/ui/traits/next-solver/dyn-incompatibility.rs +++ b/tests/ui/traits/next-solver/dyn-incompatibility.rs @@ -13,6 +13,7 @@ pub fn copy_any(t: &T) -> T { //~^ ERROR the trait bound `T: Copy` is not satisfied in `dyn Setup` //~| ERROR mismatched types //~| ERROR the trait bound `T: Copy` is not satisfied + //~| ERROR the size for values of type ` as Setup>::From` cannot be known at compilation time // FIXME(-Znext-solver): These error messages are horrible and some of them // are even simple fallout from previous error. diff --git a/tests/ui/traits/next-solver/fn-trait.stderr b/tests/ui/traits/next-solver/fn-trait.stderr index 0dee26d4672..00243fd9059 100644 --- a/tests/ui/traits/next-solver/fn-trait.stderr +++ b/tests/ui/traits/next-solver/fn-trait.stderr @@ -15,20 +15,6 @@ note: required by a bound in `require_fn` LL | fn require_fn(_: impl Fn() -> i32) {} | ^^^^^^^^^^^ required by this bound in `require_fn` -error[E0271]: type mismatch resolving ` i32 as FnOnce<()>>::Output normalizes-to i32 as FnOnce<()>>::Output` - --> $DIR/fn-trait.rs:20:16 - | -LL | require_fn(f as unsafe fn() -> i32); - | ---------- ^^^^^^^^^^^^^^^^^^^^^^^ types differ - | | - | required by a bound introduced by this call - | -note: required by a bound in `require_fn` - --> $DIR/fn-trait.rs:3:31 - | -LL | fn require_fn(_: impl Fn() -> i32) {} - | ^^^ required by this bound in `require_fn` - error[E0277]: expected a `Fn()` closure, found `extern "C" fn() -> i32 {g}` --> $DIR/fn-trait.rs:22:16 | @@ -45,20 +31,6 @@ note: required by a bound in `require_fn` LL | fn require_fn(_: impl Fn() -> i32) {} | ^^^^^^^^^^^ required by this bound in `require_fn` -error[E0271]: type mismatch resolving ` i32 {g} as FnOnce<()>>::Output normalizes-to i32 {g} as FnOnce<()>>::Output` - --> $DIR/fn-trait.rs:22:16 - | -LL | require_fn(g); - | ---------- ^ types differ - | | - | required by a bound introduced by this call - | -note: required by a bound in `require_fn` - --> $DIR/fn-trait.rs:3:31 - | -LL | fn require_fn(_: impl Fn() -> i32) {} - | ^^^ required by this bound in `require_fn` - error[E0277]: expected a `Fn()` closure, found `extern "C" fn() -> i32` --> $DIR/fn-trait.rs:24:16 | @@ -75,20 +47,6 @@ note: required by a bound in `require_fn` LL | fn require_fn(_: impl Fn() -> i32) {} | ^^^^^^^^^^^ required by this bound in `require_fn` -error[E0271]: type mismatch resolving ` i32 as FnOnce<()>>::Output normalizes-to i32 as FnOnce<()>>::Output` - --> $DIR/fn-trait.rs:24:16 - | -LL | require_fn(g as extern "C" fn() -> i32); - | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ - | | - | required by a bound introduced by this call - | -note: required by a bound in `require_fn` - --> $DIR/fn-trait.rs:3:31 - | -LL | fn require_fn(_: impl Fn() -> i32) {} - | ^^^ required by this bound in `require_fn` - error[E0277]: expected a `Fn()` closure, found `unsafe fn() -> i32 {h}` --> $DIR/fn-trait.rs:26:16 | @@ -106,21 +64,6 @@ note: required by a bound in `require_fn` LL | fn require_fn(_: impl Fn() -> i32) {} | ^^^^^^^^^^^ required by this bound in `require_fn` -error[E0271]: type mismatch resolving ` i32 {h} as FnOnce<()>>::Output normalizes-to i32 {h} as FnOnce<()>>::Output` - --> $DIR/fn-trait.rs:26:16 - | -LL | require_fn(h); - | ---------- ^ types differ - | | - | required by a bound introduced by this call - | -note: required by a bound in `require_fn` - --> $DIR/fn-trait.rs:3:31 - | -LL | fn require_fn(_: impl Fn() -> i32) {} - | ^^^ required by this bound in `require_fn` +error: aborting due to 4 previous errors -error: aborting due to 8 previous errors - -Some errors have detailed explanations: E0271, E0277. -For more information about an error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/next-solver/issue-118950-root-region.rs b/tests/ui/traits/next-solver/issue-118950-root-region.rs index 9f6dea5d5bf..e1bd234a275 100644 --- a/tests/ui/traits/next-solver/issue-118950-root-region.rs +++ b/tests/ui/traits/next-solver/issue-118950-root-region.rs @@ -17,7 +17,7 @@ type Assoc<'a, T> = <*const T as ToUnit<'a>>::Unit; impl Overlap for T {} impl Overlap fn(Assoc<'a, T>)> for T where Missing: Overlap {} -//~^ ERROR conflicting implementations of trait `Overlap` for type `fn(_)` -//~| ERROR cannot find type `Missing` in this scope +//~^ ERROR cannot find type `Missing` in this scope +//~| ERROR the trait bound `for<'a> *const T: ToUnit<'a>` is not satisfied fn main() {} diff --git a/tests/ui/traits/next-solver/issue-118950-root-region.stderr b/tests/ui/traits/next-solver/issue-118950-root-region.stderr index 82ec9e3a22f..f6545c6ebf9 100644 --- a/tests/ui/traits/next-solver/issue-118950-root-region.stderr +++ b/tests/ui/traits/next-solver/issue-118950-root-region.stderr @@ -26,13 +26,19 @@ LL | trait ToUnit<'a> { | ^^^^^^^^^^^^^^^^ WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: ['^0.Named(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), "'a"), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc), .. } -error[E0271]: type mismatch resolving `Assoc<'a, T> normalizes-to _` +error[E0277]: the trait bound `for<'a> *const T: ToUnit<'a>` is not satisfied --> $DIR/issue-118950-root-region.rs:19:17 | LL | impl Overlap fn(Assoc<'a, T>)> for T where Missing: Overlap {} - | ^^^^^^^^^^^^^^^^^^^^^^^^ types differ + | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> ToUnit<'a>` is not implemented for `*const T` + | +help: this trait has no implementations, consider adding one + --> $DIR/issue-118950-root-region.rs:8:1 + | +LL | trait ToUnit<'a> { + | ^^^^^^^^^^^^^^^^ error: aborting due to 3 previous errors; 1 warning emitted -Some errors have detailed explanations: E0271, E0277, E0412. -For more information about an error, try `rustc --explain E0271`. +Some errors have detailed explanations: E0277, E0412. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/next-solver/normalize/normalize-region-obligations.rs b/tests/ui/traits/next-solver/normalize/normalize-region-obligations.rs index 7bf3274f9c6..c4c2e695a1d 100644 --- a/tests/ui/traits/next-solver/normalize/normalize-region-obligations.rs +++ b/tests/ui/traits/next-solver/normalize/normalize-region-obligations.rs @@ -15,7 +15,7 @@ trait Mirror { type Assoc: ?Sized; } impl Mirror for T { type Assoc = T; } trait MirrorRegion<'a> { type Assoc: ?Sized; } -impl<'a, T> MirrorRegion<'a> for T { type Assoc = T; } +impl<'a, T: ?Sized> MirrorRegion<'a> for T { type Assoc = T; } impl Foo for T { #[cfg(normalize_param_env)] diff --git a/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.next.stderr b/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.next.stderr index f953111aef0..2617ce124c1 100644 --- a/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.next.stderr +++ b/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.next.stderr @@ -4,21 +4,6 @@ error[E0282]: type annotations needed LL | self.bar.next().unwrap(); | ^^^^^^^^ cannot infer type -error[E0271]: type mismatch resolving `Tait normalizes-to _` - --> $DIR/method_resolution_trait_method_from_opaque.rs:26:9 - | -LL | self.bar.next().unwrap(); - | ^^^^^^^^ types differ +error: aborting due to 1 previous error -error[E0271]: type mismatch resolving `Tait normalizes-to _` - --> $DIR/method_resolution_trait_method_from_opaque.rs:26:9 - | -LL | self.bar.next().unwrap(); - | ^^^^^^^^ types differ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 3 previous errors - -Some errors have detailed explanations: E0271, E0282. -For more information about an error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.rs b/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.rs index 5c9a3b7c2d2..b6adf08853f 100644 --- a/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.rs +++ b/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.rs @@ -25,8 +25,6 @@ impl Foo { //[current]~^ ERROR: item does not constrain self.bar.next().unwrap(); //[next]~^ ERROR: type annotations needed - //[next]~| ERROR type mismatch resolving `Tait normalizes-to _` - //[next]~| ERROR type mismatch resolving `Tait normalizes-to _` } } diff --git a/tests/ui/typeck/issue-103899.rs b/tests/ui/typeck/issue-103899.rs index 38882e9dc54..81ab92a8994 100644 --- a/tests/ui/typeck/issue-103899.rs +++ b/tests/ui/typeck/issue-103899.rs @@ -1,11 +1,9 @@ //@ revisions: current next -//@[next] compile-flags: -Znext-solver -//@[next] check-pass //@ ignore-compare-mode-next-solver (explicit revisions) -//@[current] check-fail -//@[current] failure-status: 101 -//@[current] dont-check-compiler-stderr -//@[current] known-bug: #103899 +//@ check-fail +//@ failure-status: 101 +//@ dont-check-compiler-stderr +//@ known-bug: #103899 trait BaseWithAssoc { type Assoc; From 0ead25c4a99242a526ef1076c52fa420c65b667a Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 14 Oct 2024 13:49:31 -0400 Subject: [PATCH 332/357] Register a dummy candidate for failed structural normalization during candiate assembly --- .../src/solve/assembly/mod.rs | 20 +++++++++ .../impl-trait/method-resolution4.next.stderr | 25 ++--------- tests/ui/impl-trait/method-resolution4.rs | 2 - .../recursive-coroutine-boxed.next.stderr | 27 ++---------- .../impl-trait/recursive-coroutine-boxed.rs | 3 -- .../opaque-type-unsatisfied-bound.rs | 3 -- .../opaque-type-unsatisfied-bound.stderr | 41 ++++--------------- .../opaque-type-unsatisfied-fn-bound.rs | 1 - .../opaque-type-unsatisfied-fn-bound.stderr | 11 +---- .../traits/next-solver/dyn-incompatibility.rs | 1 - .../next-solver/dyn-incompatibility.stderr | 15 +------ 11 files changed, 36 insertions(+), 113 deletions(-) diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs index cebeef76bfc..c9c0d6391fc 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -6,6 +6,7 @@ use derive_where::derive_where; use rustc_type_ir::fold::TypeFoldable; use rustc_type_ir::inherent::*; use rustc_type_ir::lang_items::TraitSolverLangItem; +use rustc_type_ir::solve::inspect; use rustc_type_ir::visit::TypeVisitableExt as _; use rustc_type_ir::{self as ty, Interner, Upcast as _, elaborate}; use tracing::{debug, instrument}; @@ -288,6 +289,25 @@ where let Ok(normalized_self_ty) = self.structurally_normalize_ty(goal.param_env, goal.predicate.self_ty()) else { + // FIXME: We register a fake candidate when normalization fails so that + // we can point at the reason for *why*. I'm tempted to say that this + // is the wrong way to do this, though. + let result = + self.probe(|&result| inspect::ProbeKind::RigidAlias { result }).enter(|this| { + let normalized_ty = this.next_ty_infer(); + let alias_relate_goal = Goal::new( + this.cx(), + goal.param_env, + ty::PredicateKind::AliasRelate( + goal.predicate.self_ty().into(), + normalized_ty.into(), + ty::AliasRelationDirection::Equate, + ), + ); + this.add_goal(GoalSource::AliasWellFormed, alias_relate_goal); + this.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS) + }); + assert_eq!(result, Err(NoSolution)); return vec![]; }; diff --git a/tests/ui/impl-trait/method-resolution4.next.stderr b/tests/ui/impl-trait/method-resolution4.next.stderr index 8eacfd3e44d..0524f49f98e 100644 --- a/tests/ui/impl-trait/method-resolution4.next.stderr +++ b/tests/ui/impl-trait/method-resolution4.next.stderr @@ -1,28 +1,9 @@ error[E0282]: type annotations needed - --> $DIR/method-resolution4.rs:14:9 + --> $DIR/method-resolution4.rs:13:9 | LL | foo(false).next().unwrap(); | ^^^^^^^^^^ cannot infer type -error[E0277]: the size for values of type `impl Iterator` cannot be known at compilation time - --> $DIR/method-resolution4.rs:11:20 - | -LL | fn foo(b: bool) -> impl Iterator { - | ^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time - | - = help: the trait `Sized` is not implemented for `impl Iterator` - = note: the return type of a function must have a statically known size +error: aborting due to 1 previous error -error[E0277]: the size for values of type `impl Iterator` cannot be known at compilation time - --> $DIR/method-resolution4.rs:14:9 - | -LL | foo(false).next().unwrap(); - | ^^^^^^^^^^ doesn't have a size known at compile-time - | - = help: the trait `Sized` is not implemented for `impl Iterator` - = note: the return type of a function must have a statically known size - -error: aborting due to 3 previous errors - -Some errors have detailed explanations: E0277, E0282. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/impl-trait/method-resolution4.rs b/tests/ui/impl-trait/method-resolution4.rs index 8eeedf04cbe..5c8813ed792 100644 --- a/tests/ui/impl-trait/method-resolution4.rs +++ b/tests/ui/impl-trait/method-resolution4.rs @@ -9,11 +9,9 @@ //@[current] check-pass fn foo(b: bool) -> impl Iterator { - //[next]~^ ERROR the size for values of type `impl Iterator` cannot be known at compilation time if b { foo(false).next().unwrap(); //[next]~^ type annotations needed - //[next]~| ERROR the size for values of type `impl Iterator` cannot be known at compilation time } std::iter::empty() } diff --git a/tests/ui/impl-trait/recursive-coroutine-boxed.next.stderr b/tests/ui/impl-trait/recursive-coroutine-boxed.next.stderr index b38850c9214..132f7de4ef2 100644 --- a/tests/ui/impl-trait/recursive-coroutine-boxed.next.stderr +++ b/tests/ui/impl-trait/recursive-coroutine-boxed.next.stderr @@ -1,9 +1,9 @@ error[E0282]: type annotations needed - --> $DIR/recursive-coroutine-boxed.rs:16:23 + --> $DIR/recursive-coroutine-boxed.rs:14:23 | LL | let mut gen = Box::pin(foo()); | ^^^^^^^^ cannot infer type of the type parameter `T` declared on the struct `Box` -... +LL | LL | let mut r = gen.as_mut().resume(()); | ------ type must be known at this point | @@ -12,25 +12,6 @@ help: consider specifying the generic argument LL | let mut gen = Box::::pin(foo()); | +++++ -error[E0277]: the size for values of type `impl Coroutine` cannot be known at compilation time - --> $DIR/recursive-coroutine-boxed.rs:9:13 - | -LL | fn foo() -> impl Coroutine { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time - | - = help: the trait `Sized` is not implemented for `impl Coroutine` - = note: the return type of a function must have a statically known size +error: aborting due to 1 previous error -error[E0277]: the size for values of type `impl Coroutine` cannot be known at compilation time - --> $DIR/recursive-coroutine-boxed.rs:16:32 - | -LL | let mut gen = Box::pin(foo()); - | ^^^^^ doesn't have a size known at compile-time - | - = help: the trait `Sized` is not implemented for `impl Coroutine` - = note: the return type of a function must have a statically known size - -error: aborting due to 3 previous errors - -Some errors have detailed explanations: E0277, E0282. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/impl-trait/recursive-coroutine-boxed.rs b/tests/ui/impl-trait/recursive-coroutine-boxed.rs index 8e670dd78ec..8d38e6aed12 100644 --- a/tests/ui/impl-trait/recursive-coroutine-boxed.rs +++ b/tests/ui/impl-trait/recursive-coroutine-boxed.rs @@ -7,15 +7,12 @@ use std::ops::{Coroutine, CoroutineState}; fn foo() -> impl Coroutine { - //[next]~^ ERROR the size for values of type `impl Coroutine` cannot be known at compilation time - // FIXME(-Znext-solver): this fails with a mismatched types as the // hidden type of the opaque ends up as {type error}. We should not // emit errors for such goals. #[coroutine] || { let mut gen = Box::pin(foo()); //[next]~^ ERROR type annotations needed - //[next]~| ERROR the size for values of type `impl Coroutine` cannot be known at compilation time let mut r = gen.as_mut().resume(()); while let CoroutineState::Yielded(v) = r { yield v; diff --git a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.rs b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.rs index 70cc47bb022..25034b67e35 100644 --- a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.rs +++ b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.rs @@ -15,15 +15,12 @@ fn main() { fn weird0() -> impl Sized + !Sized {} //~^ ERROR the size for values of type `()` cannot be known at compilation time [E0277] //~| ERROR the size for values of type `()` cannot be known at compilation time [E0277] -//~| ERROR the size for values of type `impl !Sized + Sized` cannot be known at compilation time [E0277] //~| ERROR the size for values of type `()` cannot be known at compilation time [E0277] fn weird1() -> impl !Sized + Sized {} //~^ ERROR the size for values of type `()` cannot be known at compilation time [E0277] //~| ERROR the size for values of type `()` cannot be known at compilation time [E0277] -//~| ERROR the size for values of type `impl !Sized + Sized` cannot be known at compilation time [E0277] //~| ERROR the size for values of type `()` cannot be known at compilation time [E0277] fn weird2() -> impl !Sized {} //~^ ERROR the size for values of type `()` cannot be known at compilation time [E0277] //~| ERROR the size for values of type `()` cannot be known at compilation time [E0277] -//~| ERROR the size for values of type `impl !Sized` cannot be known at compilation time [E0277] //~| ERROR the size for values of type `()` cannot be known at compilation time [E0277] diff --git a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.stderr b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.stderr index 366baf26dea..3e803a1c24f 100644 --- a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.stderr +++ b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.stderr @@ -14,15 +14,6 @@ LL | fn weird0() -> impl Sized + !Sized {} | = help: the trait bound `(): !Sized` is not satisfied -error[E0277]: the size for values of type `impl !Sized + Sized` cannot be known at compilation time - --> $DIR/opaque-type-unsatisfied-bound.rs:15:16 - | -LL | fn weird0() -> impl Sized + !Sized {} - | ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time - | - = help: the trait `Sized` is not implemented for `impl !Sized + Sized` - = note: the return type of a function must have a statically known size - error[E0277]: the size for values of type `()` cannot be known at compilation time --> $DIR/opaque-type-unsatisfied-bound.rs:15:1 | @@ -32,7 +23,7 @@ LL | fn weird0() -> impl Sized + !Sized {} = help: the trait bound `(): !Sized` is not satisfied error[E0277]: the size for values of type `()` cannot be known at compilation time - --> $DIR/opaque-type-unsatisfied-bound.rs:20:16 + --> $DIR/opaque-type-unsatisfied-bound.rs:19:16 | LL | fn weird1() -> impl !Sized + Sized {} | ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time @@ -40,24 +31,15 @@ LL | fn weird1() -> impl !Sized + Sized {} = help: the trait bound `(): !Sized` is not satisfied error[E0277]: the size for values of type `()` cannot be known at compilation time - --> $DIR/opaque-type-unsatisfied-bound.rs:20:36 + --> $DIR/opaque-type-unsatisfied-bound.rs:19:36 | LL | fn weird1() -> impl !Sized + Sized {} | ^^ doesn't have a size known at compile-time | = help: the trait bound `(): !Sized` is not satisfied -error[E0277]: the size for values of type `impl !Sized + Sized` cannot be known at compilation time - --> $DIR/opaque-type-unsatisfied-bound.rs:20:16 - | -LL | fn weird1() -> impl !Sized + Sized {} - | ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time - | - = help: the trait `Sized` is not implemented for `impl !Sized + Sized` - = note: the return type of a function must have a statically known size - error[E0277]: the size for values of type `()` cannot be known at compilation time - --> $DIR/opaque-type-unsatisfied-bound.rs:20:1 + --> $DIR/opaque-type-unsatisfied-bound.rs:19:1 | LL | fn weird1() -> impl !Sized + Sized {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time @@ -65,7 +47,7 @@ LL | fn weird1() -> impl !Sized + Sized {} = help: the trait bound `(): !Sized` is not satisfied error[E0277]: the size for values of type `()` cannot be known at compilation time - --> $DIR/opaque-type-unsatisfied-bound.rs:25:16 + --> $DIR/opaque-type-unsatisfied-bound.rs:23:16 | LL | fn weird2() -> impl !Sized {} | ^^^^^^^^^^^ doesn't have a size known at compile-time @@ -73,24 +55,15 @@ LL | fn weird2() -> impl !Sized {} = help: the trait bound `(): !Sized` is not satisfied error[E0277]: the size for values of type `()` cannot be known at compilation time - --> $DIR/opaque-type-unsatisfied-bound.rs:25:28 + --> $DIR/opaque-type-unsatisfied-bound.rs:23:28 | LL | fn weird2() -> impl !Sized {} | ^^ doesn't have a size known at compile-time | = help: the trait bound `(): !Sized` is not satisfied -error[E0277]: the size for values of type `impl !Sized` cannot be known at compilation time - --> $DIR/opaque-type-unsatisfied-bound.rs:25:16 - | -LL | fn weird2() -> impl !Sized {} - | ^^^^^^^^^^^ doesn't have a size known at compile-time - | - = help: the trait `Sized` is not implemented for `impl !Sized` - = note: the return type of a function must have a statically known size - error[E0277]: the size for values of type `()` cannot be known at compilation time - --> $DIR/opaque-type-unsatisfied-bound.rs:25:1 + --> $DIR/opaque-type-unsatisfied-bound.rs:23:1 | LL | fn weird2() -> impl !Sized {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time @@ -111,6 +84,6 @@ note: required by a bound in `consume` LL | fn consume(_: impl Trait) {} | ^^^^^ required by this bound in `consume` -error: aborting due to 13 previous errors +error: aborting due to 10 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.rs b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.rs index 3633e9f3f48..7538e3c0d2b 100644 --- a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.rs +++ b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.rs @@ -5,7 +5,6 @@ fn produce() -> impl !Fn<(u32,)> {} //~^ ERROR expected a `Fn(u32)` closure, found `()` //~| ERROR expected a `Fn(u32)` closure, found `()` -//~| ERROR the size for values of type `impl !Fn<(u32,)>` cannot be known at compilation time //~| ERROR expected a `Fn(u32)` closure, found `()` fn main() {} diff --git a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.stderr b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.stderr index cdd89de0d88..57a423741b3 100644 --- a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.stderr +++ b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.stderr @@ -14,15 +14,6 @@ LL | fn produce() -> impl !Fn<(u32,)> {} | = help: the trait bound `(): !Fn(u32)` is not satisfied -error[E0277]: the size for values of type `impl !Fn<(u32,)>` cannot be known at compilation time - --> $DIR/opaque-type-unsatisfied-fn-bound.rs:5:17 - | -LL | fn produce() -> impl !Fn<(u32,)> {} - | ^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time - | - = help: the trait `Sized` is not implemented for `impl !Fn<(u32,)>` - = note: the return type of a function must have a statically known size - error[E0277]: expected a `Fn(u32)` closure, found `()` --> $DIR/opaque-type-unsatisfied-fn-bound.rs:5:1 | @@ -31,6 +22,6 @@ LL | fn produce() -> impl !Fn<(u32,)> {} | = help: the trait bound `(): !Fn(u32)` is not satisfied -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/next-solver/dyn-incompatibility.rs b/tests/ui/traits/next-solver/dyn-incompatibility.rs index b53a6543c90..a347984daf6 100644 --- a/tests/ui/traits/next-solver/dyn-incompatibility.rs +++ b/tests/ui/traits/next-solver/dyn-incompatibility.rs @@ -13,7 +13,6 @@ pub fn copy_any(t: &T) -> T { //~^ ERROR the trait bound `T: Copy` is not satisfied in `dyn Setup` //~| ERROR mismatched types //~| ERROR the trait bound `T: Copy` is not satisfied - //~| ERROR the size for values of type ` as Setup>::From` cannot be known at compilation time // FIXME(-Znext-solver): These error messages are horrible and some of them // are even simple fallout from previous error. diff --git a/tests/ui/traits/next-solver/dyn-incompatibility.stderr b/tests/ui/traits/next-solver/dyn-incompatibility.stderr index adf46686e08..7f2c0646ef5 100644 --- a/tests/ui/traits/next-solver/dyn-incompatibility.stderr +++ b/tests/ui/traits/next-solver/dyn-incompatibility.stderr @@ -43,20 +43,7 @@ help: consider restricting type parameter `T` LL | pub fn copy_any(t: &T) -> T { | +++++++++++++++++++ -error[E0277]: the size for values of type ` as Setup>::From` cannot be known at compilation time - --> $DIR/dyn-incompatibility.rs:12:5 - | -LL | copy::>(t) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time - | - = help: the trait `Sized` is not implemented for ` as Setup>::From` - = note: the return type of a function must have a statically known size -help: consider further restricting the associated type - | -LL | pub fn copy_any(t: &T) -> T where as Setup>::From: Sized { - | +++++++++++++++++++++++++++++++++++++++++++++++++ - -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors Some errors have detailed explanations: E0277, E0308. For more information about an error, try `rustc --explain E0277`. From f956dc2e779ae5ca14c882998d308609648025e9 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 15 Oct 2024 20:38:43 -0400 Subject: [PATCH 333/357] Bless tests --- .../structually-relate-aliases.rs | 3 +- .../structually-relate-aliases.stderr | 32 ++++++----- .../opaque-type-unsatisfied-bound.rs | 18 +++---- .../opaque-type-unsatisfied-bound.stderr | 54 +++++++------------ .../opaque-type-unsatisfied-fn-bound.rs | 6 +-- .../opaque-type-unsatisfied-fn-bound.stderr | 18 +++---- 6 files changed, 58 insertions(+), 73 deletions(-) diff --git a/tests/ui/higher-ranked/structually-relate-aliases.rs b/tests/ui/higher-ranked/structually-relate-aliases.rs index 69882450961..73c2cd23d86 100644 --- a/tests/ui/higher-ranked/structually-relate-aliases.rs +++ b/tests/ui/higher-ranked/structually-relate-aliases.rs @@ -11,6 +11,7 @@ type Assoc<'a, T> = >::Unit; impl Overlap for T {} impl Overlap fn(&'a (), Assoc<'a, T>)> for T {} -//~^ ERROR conflicting implementations of trait `Overlap fn(&'a (), _)>` +//~^ ERROR the trait bound `for<'a> T: ToUnit<'a>` is not satisfied +//~| ERROR the trait bound `for<'a> T: ToUnit<'a>` is not satisfied fn main() {} diff --git a/tests/ui/higher-ranked/structually-relate-aliases.stderr b/tests/ui/higher-ranked/structually-relate-aliases.stderr index 4ecd5829bc3..e9d91e45e21 100644 --- a/tests/ui/higher-ranked/structually-relate-aliases.stderr +++ b/tests/ui/higher-ranked/structually-relate-aliases.stderr @@ -1,18 +1,26 @@ WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [?1t, '^0.Named(DefId(0:15 ~ structually_relate_aliases[de75]::{impl#1}::'a), "'a")], def_id: DefId(0:5 ~ structually_relate_aliases[de75]::ToUnit::Unit), .. } - WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [?1t, '^0.Named(DefId(0:15 ~ structually_relate_aliases[de75]::{impl#1}::'a), "'a")], def_id: DefId(0:5 ~ structually_relate_aliases[de75]::ToUnit::Unit), .. } - WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [?1t, '^0.Named(DefId(0:15 ~ structually_relate_aliases[de75]::{impl#1}::'a), "'a")], def_id: DefId(0:5 ~ structually_relate_aliases[de75]::ToUnit::Unit), .. } - WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [?1t, '^0.Named(DefId(0:15 ~ structually_relate_aliases[de75]::{impl#1}::'a), "'a")], def_id: DefId(0:5 ~ structually_relate_aliases[de75]::ToUnit::Unit), .. } -error[E0119]: conflicting implementations of trait `Overlap fn(&'a (), _)>` for type `for<'a> fn(&'a (), _)` - --> $DIR/structually-relate-aliases.rs:13:1 +error[E0277]: the trait bound `for<'a> T: ToUnit<'a>` is not satisfied + --> $DIR/structually-relate-aliases.rs:13:36 | -LL | impl Overlap for T {} - | ------------------------ first implementation here -LL | LL | impl Overlap fn(&'a (), Assoc<'a, T>)> for T {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'a> fn(&'a (), _)` + | ^^^^^^^^^^^^ the trait `for<'a> ToUnit<'a>` is not implemented for `T` | - = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details +help: consider restricting type parameter `T` + | +LL | impl ToUnit<'a>> Overlap fn(&'a (), Assoc<'a, T>)> for T {} + | ++++++++++++++++++++ -error: aborting due to 1 previous error +error[E0277]: the trait bound `for<'a> T: ToUnit<'a>` is not satisfied + --> $DIR/structually-relate-aliases.rs:13:17 + | +LL | impl Overlap fn(&'a (), Assoc<'a, T>)> for T {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> ToUnit<'a>` is not implemented for `T` + | +help: consider restricting type parameter `T` + | +LL | impl ToUnit<'a>> Overlap fn(&'a (), Assoc<'a, T>)> for T {} + | ++++++++++++++++++++ -For more information about this error, try `rustc --explain E0119`. +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.rs b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.rs index 25034b67e35..1260cca5106 100644 --- a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.rs +++ b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.rs @@ -13,14 +13,14 @@ fn main() { } fn weird0() -> impl Sized + !Sized {} -//~^ ERROR the size for values of type `()` cannot be known at compilation time [E0277] -//~| ERROR the size for values of type `()` cannot be known at compilation time [E0277] -//~| ERROR the size for values of type `()` cannot be known at compilation time [E0277] +//~^ ERROR the trait bound `(): !Sized` is not satisfied +//~| ERROR the trait bound `(): !Sized` is not satisfied +//~| ERROR the trait bound `(): !Sized` is not satisfied fn weird1() -> impl !Sized + Sized {} -//~^ ERROR the size for values of type `()` cannot be known at compilation time [E0277] -//~| ERROR the size for values of type `()` cannot be known at compilation time [E0277] -//~| ERROR the size for values of type `()` cannot be known at compilation time [E0277] +//~^ ERROR the trait bound `(): !Sized` is not satisfied +//~| ERROR the trait bound `(): !Sized` is not satisfied +//~| ERROR the trait bound `(): !Sized` is not satisfied fn weird2() -> impl !Sized {} -//~^ ERROR the size for values of type `()` cannot be known at compilation time [E0277] -//~| ERROR the size for values of type `()` cannot be known at compilation time [E0277] -//~| ERROR the size for values of type `()` cannot be known at compilation time [E0277] +//~^ ERROR the trait bound `(): !Sized` is not satisfied +//~| ERROR the trait bound `(): !Sized` is not satisfied +//~| ERROR the trait bound `(): !Sized` is not satisfied diff --git a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.stderr b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.stderr index 3e803a1c24f..4ec578a3b7b 100644 --- a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.stderr +++ b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.stderr @@ -1,74 +1,56 @@ -error[E0277]: the size for values of type `()` cannot be known at compilation time +error[E0277]: the trait bound `(): !Sized` is not satisfied --> $DIR/opaque-type-unsatisfied-bound.rs:15:16 | LL | fn weird0() -> impl Sized + !Sized {} - | ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time - | - = help: the trait bound `(): !Sized` is not satisfied + | ^^^^^^^^^^^^^^^^^^^ the trait bound `(): !Sized` is not satisfied -error[E0277]: the size for values of type `()` cannot be known at compilation time +error[E0277]: the trait bound `(): !Sized` is not satisfied --> $DIR/opaque-type-unsatisfied-bound.rs:15:36 | LL | fn weird0() -> impl Sized + !Sized {} - | ^^ doesn't have a size known at compile-time - | - = help: the trait bound `(): !Sized` is not satisfied + | ^^ the trait bound `(): !Sized` is not satisfied -error[E0277]: the size for values of type `()` cannot be known at compilation time +error[E0277]: the trait bound `(): !Sized` is not satisfied --> $DIR/opaque-type-unsatisfied-bound.rs:15:1 | LL | fn weird0() -> impl Sized + !Sized {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time - | - = help: the trait bound `(): !Sized` is not satisfied + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait bound `(): !Sized` is not satisfied -error[E0277]: the size for values of type `()` cannot be known at compilation time +error[E0277]: the trait bound `(): !Sized` is not satisfied --> $DIR/opaque-type-unsatisfied-bound.rs:19:16 | LL | fn weird1() -> impl !Sized + Sized {} - | ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time - | - = help: the trait bound `(): !Sized` is not satisfied + | ^^^^^^^^^^^^^^^^^^^ the trait bound `(): !Sized` is not satisfied -error[E0277]: the size for values of type `()` cannot be known at compilation time +error[E0277]: the trait bound `(): !Sized` is not satisfied --> $DIR/opaque-type-unsatisfied-bound.rs:19:36 | LL | fn weird1() -> impl !Sized + Sized {} - | ^^ doesn't have a size known at compile-time - | - = help: the trait bound `(): !Sized` is not satisfied + | ^^ the trait bound `(): !Sized` is not satisfied -error[E0277]: the size for values of type `()` cannot be known at compilation time +error[E0277]: the trait bound `(): !Sized` is not satisfied --> $DIR/opaque-type-unsatisfied-bound.rs:19:1 | LL | fn weird1() -> impl !Sized + Sized {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time - | - = help: the trait bound `(): !Sized` is not satisfied + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait bound `(): !Sized` is not satisfied -error[E0277]: the size for values of type `()` cannot be known at compilation time +error[E0277]: the trait bound `(): !Sized` is not satisfied --> $DIR/opaque-type-unsatisfied-bound.rs:23:16 | LL | fn weird2() -> impl !Sized {} - | ^^^^^^^^^^^ doesn't have a size known at compile-time - | - = help: the trait bound `(): !Sized` is not satisfied + | ^^^^^^^^^^^ the trait bound `(): !Sized` is not satisfied -error[E0277]: the size for values of type `()` cannot be known at compilation time +error[E0277]: the trait bound `(): !Sized` is not satisfied --> $DIR/opaque-type-unsatisfied-bound.rs:23:28 | LL | fn weird2() -> impl !Sized {} - | ^^ doesn't have a size known at compile-time - | - = help: the trait bound `(): !Sized` is not satisfied + | ^^ the trait bound `(): !Sized` is not satisfied -error[E0277]: the size for values of type `()` cannot be known at compilation time +error[E0277]: the trait bound `(): !Sized` is not satisfied --> $DIR/opaque-type-unsatisfied-bound.rs:23:1 | LL | fn weird2() -> impl !Sized {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time - | - = help: the trait bound `(): !Sized` is not satisfied + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait bound `(): !Sized` is not satisfied error[E0277]: the trait bound `impl !Trait: Trait` is not satisfied --> $DIR/opaque-type-unsatisfied-bound.rs:12:13 diff --git a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.rs b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.rs index 7538e3c0d2b..c6826578658 100644 --- a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.rs +++ b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.rs @@ -3,8 +3,8 @@ #![feature(negative_bounds, unboxed_closures)] fn produce() -> impl !Fn<(u32,)> {} -//~^ ERROR expected a `Fn(u32)` closure, found `()` -//~| ERROR expected a `Fn(u32)` closure, found `()` -//~| ERROR expected a `Fn(u32)` closure, found `()` +//~^ ERROR the trait bound `(): !Fn(u32)` is not satisfied +//~| ERROR the trait bound `(): !Fn(u32)` is not satisfied +//~| ERROR the trait bound `(): !Fn(u32)` is not satisfied fn main() {} diff --git a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.stderr b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.stderr index 57a423741b3..f81f0a23ac3 100644 --- a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.stderr +++ b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.stderr @@ -1,26 +1,20 @@ -error[E0277]: expected a `Fn(u32)` closure, found `()` +error[E0277]: the trait bound `(): !Fn(u32)` is not satisfied --> $DIR/opaque-type-unsatisfied-fn-bound.rs:5:17 | LL | fn produce() -> impl !Fn<(u32,)> {} - | ^^^^^^^^^^^^^^^^ expected an `Fn(u32)` closure, found `()` - | - = help: the trait bound `(): !Fn(u32)` is not satisfied + | ^^^^^^^^^^^^^^^^ the trait bound `(): !Fn(u32)` is not satisfied -error[E0277]: expected a `Fn(u32)` closure, found `()` +error[E0277]: the trait bound `(): !Fn(u32)` is not satisfied --> $DIR/opaque-type-unsatisfied-fn-bound.rs:5:34 | LL | fn produce() -> impl !Fn<(u32,)> {} - | ^^ expected an `Fn(u32)` closure, found `()` - | - = help: the trait bound `(): !Fn(u32)` is not satisfied + | ^^ the trait bound `(): !Fn(u32)` is not satisfied -error[E0277]: expected a `Fn(u32)` closure, found `()` +error[E0277]: the trait bound `(): !Fn(u32)` is not satisfied --> $DIR/opaque-type-unsatisfied-fn-bound.rs:5:1 | LL | fn produce() -> impl !Fn<(u32,)> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an `Fn(u32)` closure, found `()` - | - = help: the trait bound `(): !Fn(u32)` is not satisfied + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait bound `(): !Fn(u32)` is not satisfied error: aborting due to 3 previous errors From b4e9aad137800936b4fbc3c36da6ff2819b385b5 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 15 Oct 2024 13:20:41 -0400 Subject: [PATCH 334/357] Rename can_coerce to may_coerce --- compiler/rustc_hir_typeck/src/_match.rs | 4 +-- compiler/rustc_hir_typeck/src/cast.rs | 8 ++--- compiler/rustc_hir_typeck/src/coercion.rs | 17 ++++++---- compiler/rustc_hir_typeck/src/expr.rs | 10 +++--- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 10 +++--- .../src/fn_ctxt/suggestions.rs | 34 +++++++++---------- .../rustc_hir_typeck/src/method/suggest.rs | 4 +-- compiler/rustc_hir_typeck/src/pat.rs | 2 +- 8 files changed, 46 insertions(+), 43 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs index 0d9d1910ae0..e68caa3e2e3 100644 --- a/compiler/rustc_hir_typeck/src/_match.rs +++ b/compiler/rustc_hir_typeck/src/_match.rs @@ -235,8 +235,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Some(ret_coercion) => { let ret_ty = ret_coercion.borrow().expected_ty(); let ret_ty = self.infcx.shallow_resolve(ret_ty); - self.can_coerce(arm_ty, ret_ty) - && prior_arm.is_none_or(|(_, ty, _)| self.can_coerce(ty, ret_ty)) + self.may_coerce(arm_ty, ret_ty) + && prior_arm.is_none_or(|(_, ty, _)| self.may_coerce(ty, ret_ty)) // The match arms need to unify for the case of `impl Trait`. && !matches!(ret_ty.kind(), ty::Alias(ty::Opaque, ..)) } diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index 407191661a4..8fa6ab8503d 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -409,7 +409,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { let mut sugg_mutref = false; if let ty::Ref(reg, cast_ty, mutbl) = *self.cast_ty.kind() { if let ty::RawPtr(expr_ty, _) = *self.expr_ty.kind() - && fcx.can_coerce( + && fcx.may_coerce( Ty::new_ref(fcx.tcx, fcx.tcx.lifetimes.re_erased, expr_ty, mutbl), self.cast_ty, ) @@ -418,14 +418,14 @@ impl<'a, 'tcx> CastCheck<'tcx> { } else if let ty::Ref(expr_reg, expr_ty, expr_mutbl) = *self.expr_ty.kind() && expr_mutbl == Mutability::Not && mutbl == Mutability::Mut - && fcx.can_coerce(Ty::new_mut_ref(fcx.tcx, expr_reg, expr_ty), self.cast_ty) + && fcx.may_coerce(Ty::new_mut_ref(fcx.tcx, expr_reg, expr_ty), self.cast_ty) { sugg_mutref = true; } if !sugg_mutref && sugg == None - && fcx.can_coerce( + && fcx.may_coerce( Ty::new_ref(fcx.tcx, reg, self.expr_ty, mutbl), self.cast_ty, ) @@ -433,7 +433,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { sugg = Some((format!("&{}", mutbl.prefix_str()), false)); } } else if let ty::RawPtr(_, mutbl) = *self.cast_ty.kind() - && fcx.can_coerce( + && fcx.may_coerce( Ty::new_ref(fcx.tcx, fcx.tcx.lifetimes.re_erased, self.expr_ty, mutbl), self.cast_ty, ) diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index bd0b9870298..a6df9e45db5 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -1083,21 +1083,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }) } - /// Same as `coerce()`, but without side-effects. + /// Probe whether `expr_ty` can be coerced to `target_ty`. This has no side-effects, + /// and may return false positives if types are not yet fully constrained by inference. /// - /// Returns false if the coercion creates any obligations that result in - /// errors. - pub(crate) fn can_coerce(&self, expr_ty: Ty<'tcx>, target: Ty<'tcx>) -> bool { + /// Returns false if the coercion is not possible, or if the coercion creates any + /// sub-obligations that result in errors. + /// + /// This should only be used for diagnostics. + pub(crate) fn may_coerce(&self, expr_ty: Ty<'tcx>, target_ty: Ty<'tcx>) -> bool { // FIXME(-Znext-solver): We need to structurally resolve both types here. let source = self.resolve_vars_with_obligations(expr_ty); - debug!("coercion::can_with_predicates({:?} -> {:?})", source, target); + debug!("coercion::can_with_predicates({:?} -> {:?})", source, target_ty); let cause = self.cause(DUMMY_SP, ObligationCauseCode::ExprAssignable); // We don't ever need two-phase here since we throw out the result of the coercion. // We also just always set `coerce_never` to true, since this is a heuristic. let coerce = Coerce::new(self, cause, AllowTwoPhase::No, true); self.probe(|_| { - let Ok(ok) = coerce.coerce(source, target) else { + let Ok(ok) = coerce.coerce(source, target_ty) else { return false; }; let ocx = ObligationCtxt::new(self); @@ -1369,7 +1372,7 @@ pub fn can_coerce<'tcx>( ) -> bool { let root_ctxt = crate::typeck_root_ctxt::TypeckRootCtxt::new(tcx, body_id); let fn_ctxt = FnCtxt::new(&root_ctxt, param_env, body_id); - fn_ctxt.can_coerce(ty, output_ty) + fn_ctxt.may_coerce(ty, output_ty) } /// CoerceMany encapsulates the pattern you should use when you have diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index b310398a0f1..7bdd3c95ad1 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -1330,9 +1330,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let refs_can_coerce = |lhs: Ty<'tcx>, rhs: Ty<'tcx>| { let lhs = Ty::new_imm_ref(self.tcx, self.tcx.lifetimes.re_erased, lhs.peel_refs()); let rhs = Ty::new_imm_ref(self.tcx, self.tcx.lifetimes.re_erased, rhs.peel_refs()); - self.can_coerce(rhs, lhs) + self.may_coerce(rhs, lhs) }; - let (applicability, eq) = if self.can_coerce(rhs_ty, lhs_ty) { + let (applicability, eq) = if self.may_coerce(rhs_ty, lhs_ty) { (Applicability::MachineApplicable, true) } else if refs_can_coerce(rhs_ty, lhs_ty) { // The lhs and rhs are likely missing some references in either side. Subsequent @@ -1349,7 +1349,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let actual_lhs_ty = self.check_expr(rhs_expr); ( Applicability::MaybeIncorrect, - self.can_coerce(rhs_ty, actual_lhs_ty) + self.may_coerce(rhs_ty, actual_lhs_ty) || refs_can_coerce(rhs_ty, actual_lhs_ty), ) } else if let ExprKind::Binary( @@ -1363,7 +1363,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let actual_rhs_ty = self.check_expr(lhs_expr); ( Applicability::MaybeIncorrect, - self.can_coerce(actual_rhs_ty, lhs_ty) + self.may_coerce(actual_rhs_ty, lhs_ty) || refs_can_coerce(actual_rhs_ty, lhs_ty), ) } else { @@ -1414,7 +1414,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.param_env, ) .may_apply(); - if lhs_deref_ty_is_sized && self.can_coerce(rhs_ty, lhs_deref_ty) { + if lhs_deref_ty_is_sized && self.may_coerce(rhs_ty, lhs_deref_ty) { err.span_suggestion_verbose( lhs.span.shrink_to_lo(), "consider dereferencing here to assign to the mutably borrowed value", diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index fa471647d02..660cbc29d4c 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -658,7 +658,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { && fn_sig.inputs()[1..] .iter() .zip(input_types.iter()) - .all(|(expected, found)| self.can_coerce(*expected, *found)) + .all(|(expected, found)| self.may_coerce(*expected, *found)) && fn_sig.inputs()[1..].len() == input_types.len() { err.span_suggestion_verbose( @@ -722,7 +722,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let expectation = Expectation::rvalue_hint(self, expected_input_ty); let coerced_ty = expectation.only_has_type(self).unwrap_or(formal_input_ty); - let can_coerce = self.can_coerce(arg_ty, coerced_ty); + let can_coerce = self.may_coerce(arg_ty, coerced_ty); if !can_coerce { return Compatibility::Incompatible(Some(ty::error::TypeError::Sorts( ty::error::ExpectedFound::new(true, coerced_ty, arg_ty), @@ -802,7 +802,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { provided_arg_tys.iter().map(|(ty, _)| *ty).skip(mismatch_idx + tys.len()), ), ) { - if !self.can_coerce(provided_ty, *expected_ty) { + if !self.may_coerce(provided_ty, *expected_ty) { satisfied = false; break; } @@ -1023,7 +1023,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { std::iter::zip(formal_and_expected_inputs.iter(), removed_arg_tys.iter()).all( |((expected_ty, _), (provided_ty, _))| { !provided_ty.references_error() - && self.can_coerce(*provided_ty, *expected_ty) + && self.may_coerce(*provided_ty, *expected_ty) }, ) }; @@ -2124,7 +2124,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let expr_ty = self.typeck_results.borrow().expr_ty(expr); let return_ty = fn_sig.output(); if !matches!(expr.kind, hir::ExprKind::Ret(..)) - && self.can_coerce(expr_ty, return_ty) + && self.may_coerce(expr_ty, return_ty) { found_semi = true; } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 3e9e5326156..3f703c2fcf6 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -261,7 +261,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let hir::ExprKind::MethodCall(hir::PathSegment { ident: method, .. }, recv_expr, &[], _) = expr.kind && let Some(recv_ty) = self.typeck_results.borrow().expr_ty_opt(recv_expr) - && self.can_coerce(recv_ty, expected) + && self.may_coerce(recv_ty, expected) && let name = method.name.as_str() && (name.starts_with("to_") || name.starts_with("as_") || name == "into") { @@ -349,7 +349,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return true; } - if self.suggest_fn_call(err, expr, found, |output| self.can_coerce(output, expected)) + if self.suggest_fn_call(err, expr, found, |output| self.may_coerce(output, expected)) && let ty::FnDef(def_id, ..) = *found.kind() && let Some(sp) = self.tcx.hir().span_if_local(def_id) { @@ -568,7 +568,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if self.tcx.hir().is_inside_const_context(hir_id) || !expected.is_box() || found.is_box() { return false; } - if self.can_coerce(Ty::new_box(self.tcx, found), expected) { + if self.may_coerce(Ty::new_box(self.tcx, found), expected) { let suggest_boxing = match found.kind() { ty::Tuple(tuple) if tuple.is_empty() => { errors::SuggestBoxing::Unit { start: span.shrink_to_lo(), end: span } @@ -663,7 +663,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; match expected.kind() { ty::Adt(def, _) if Some(def.did()) == pin_did => { - if self.can_coerce(pin_box_found, expected) { + if self.may_coerce(pin_box_found, expected) { debug!("can coerce {:?} to {:?}, suggesting Box::pin", pin_box_found, expected); match found.kind() { ty::Adt(def, _) if def.is_box() => { @@ -689,7 +689,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } true - } else if self.can_coerce(pin_found, expected) { + } else if self.may_coerce(pin_found, expected) { match found.kind() { ty::Adt(def, _) if def.is_box() => { err.help("use `Box::pin`"); @@ -701,7 +701,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { false } } - ty::Adt(def, _) if def.is_box() && self.can_coerce(box_found, expected) => { + ty::Adt(def, _) if def.is_box() && self.may_coerce(box_found, expected) => { // Check if the parent expression is a call to Pin::new. If it // is and we were expecting a Box, ergo Pin>, we // can suggest Box::pin. @@ -884,7 +884,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let ty = Binder::bind_with_vars(ty, bound_vars); let ty = self.normalize(hir_ty.span, ty); let ty = self.tcx.instantiate_bound_regions_with_erased(ty); - if self.can_coerce(expected, ty) { + if self.may_coerce(expected, ty) { err.subdiagnostic(errors::ExpectedReturnTypeLabel::Other { span: hir_ty.span, expected, @@ -1141,12 +1141,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty::Asyncness::No => ty, }; let ty = self.normalize(expr.span, ty); - self.can_coerce(found, ty) + self.may_coerce(found, ty) } hir::FnRetTy::DefaultReturn(_) if in_closure => { self.ret_coercion.as_ref().map_or(false, |ret| { let ret_ty = ret.borrow().expected_ty(); - self.can_coerce(found, ret_ty) + self.may_coerce(found, ret_ty) }) } _ => false, @@ -1510,7 +1510,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { provided_ty }; - if !self.can_coerce(expected_ty, dummy_ty) { + if !self.may_coerce(expected_ty, dummy_ty) { return; } let msg = format!("use `{adt_name}::map_or` to deref inner value of `{adt_name}`"); @@ -1534,7 +1534,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected_ty: Ty<'tcx>, ) { if let ty::Slice(elem_ty) | ty::Array(elem_ty, _) = expected_ty.kind() { - if self.can_coerce(blk_ty, *elem_ty) + if self.may_coerce(blk_ty, *elem_ty) && blk.stmts.is_empty() && blk.rules == hir::BlockCheckMode::DefaultBlock { @@ -1744,7 +1744,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if item_ty.has_param() { return false; } - if self.can_coerce(item_ty, expected_ty) { + if self.may_coerce(item_ty, expected_ty) { err.span_suggestion_verbose( segment.ident.span, format!("try referring to the associated const `{capitalized_name}` instead",), @@ -1804,7 +1804,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // diagnostic in cases where we have `(&&T).clone()` and we expect `T`). && !results.expr_adjustments(callee_expr).iter().any(|adj| matches!(adj.kind, ty::adjustment::Adjust::Deref(..))) // Check that we're in fact trying to clone into the expected type - && self.can_coerce(*pointee_ty, expected_ty) + && self.may_coerce(*pointee_ty, expected_ty) && let trait_ref = ty::TraitRef::new(self.tcx, clone_trait_did, [expected_ty]) // And the expected type doesn't implement `Clone` && !self.predicate_must_hold_considering_regions(&traits::Obligation::new( @@ -2022,7 +2022,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else { return false; }; - if is_ctor || !self.can_coerce(args.type_at(0), expected) { + if is_ctor || !self.may_coerce(args.type_at(0), expected) { return false; } @@ -2293,7 +2293,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .then(|| " (its field is private, but it's local to this crate and its privacy can be changed)".to_string()); let sole_field_ty = sole_field.ty(self.tcx, args); - if self.can_coerce(expr_ty, sole_field_ty) { + if self.may_coerce(expr_ty, sole_field_ty) { let variant_path = with_no_trimmed_paths!(self.tcx.def_path_str(variant.def_id)); // FIXME #56861: DRYer prelude filtering @@ -2401,7 +2401,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } let int_type = args.type_at(0); - if !self.can_coerce(expr_ty, int_type) { + if !self.may_coerce(expr_ty, int_type) { return false; } @@ -2585,7 +2585,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Ty::new_imm_ref(self.tcx, self.tcx.lifetimes.re_static, checked_ty) } }; - if self.can_coerce(ref_ty, expected) { + if self.may_coerce(ref_ty, expected) { let mut sugg_sp = sp; if let hir::ExprKind::MethodCall(segment, receiver, args, _) = expr.kind { let clone_trait = diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 7f68e19a313..9dd59541148 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -1934,7 +1934,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { && fn_sig.inputs()[1..] .iter() .zip(args.into_iter()) - .all(|(expected, found)| self.can_coerce(*expected, *found)) + .all(|(expected, found)| self.may_coerce(*expected, *found)) && fn_sig.inputs()[1..].len() == args.len() { err.span_suggestion_verbose( @@ -4148,7 +4148,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return false; }; - if !self.can_coerce(output, expected) { + if !self.may_coerce(output, expected) { return false; } diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index fb78da0a86c..5ce9bae81c1 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -1767,7 +1767,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else if inexistent_fields.len() == 1 { match pat_field.pat.kind { PatKind::Lit(expr) - if !self.can_coerce( + if !self.may_coerce( self.typeck_results.borrow().expr_ty(expr), self.field_ty(field.span, field_def, args), ) => {} From e3eba2d9204e9af2ac7a089f61996b25cfecf2d8 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 15 Oct 2024 13:26:56 -0400 Subject: [PATCH 335/357] Don't structurally resolve in may_coerce --- compiler/rustc_hir_typeck/src/coercion.rs | 6 +---- .../lazy_subtyping_of_opaques.stderr | 24 ++++++++++++------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index a6df9e45db5..bb2f1f0493a 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -1091,16 +1091,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// /// This should only be used for diagnostics. pub(crate) fn may_coerce(&self, expr_ty: Ty<'tcx>, target_ty: Ty<'tcx>) -> bool { - // FIXME(-Znext-solver): We need to structurally resolve both types here. - let source = self.resolve_vars_with_obligations(expr_ty); - debug!("coercion::can_with_predicates({:?} -> {:?})", source, target_ty); - let cause = self.cause(DUMMY_SP, ObligationCauseCode::ExprAssignable); // We don't ever need two-phase here since we throw out the result of the coercion. // We also just always set `coerce_never` to true, since this is a heuristic. let coerce = Coerce::new(self, cause, AllowTwoPhase::No, true); self.probe(|_| { - let Ok(ok) = coerce.coerce(source, target_ty) else { + let Ok(ok) = coerce.coerce(expr_ty, target_ty) else { return false; }; let ocx = ObligationCtxt::new(self); diff --git a/tests/ui/type-alias-impl-trait/lazy_subtyping_of_opaques.stderr b/tests/ui/type-alias-impl-trait/lazy_subtyping_of_opaques.stderr index 7bc2fa1b09e..921667f577b 100644 --- a/tests/ui/type-alias-impl-trait/lazy_subtyping_of_opaques.stderr +++ b/tests/ui/type-alias-impl-trait/lazy_subtyping_of_opaques.stderr @@ -1,3 +1,15 @@ +error[E0308]: mismatched types + --> $DIR/lazy_subtyping_of_opaques.rs:11:5 + | +LL | fn reify_as_tait() -> Thunk { + | ----------- expected `Thunk<_>` because of return type +LL | +LL | Thunk::new(|cont| cont) + | ^^^^^^^^^^^^^^^^^^^^^^^ expected `Thunk<_>`, found `()` + | + = note: expected struct `Thunk<_>` + found unit type `()` + error[E0277]: expected a `FnOnce()` closure, found `()` --> $DIR/lazy_subtyping_of_opaques.rs:11:23 | @@ -12,19 +24,13 @@ error[E0277]: expected a `FnOnce()` closure, found `()` | LL | fn reify_as_tait() -> Thunk { | ^^^^^^^^^^^ expected an `FnOnce()` closure, found `()` +LL | +LL | Thunk::new(|cont| cont) + | ----------------------- return type was inferred to be `{type error}` here | = help: the trait `FnOnce()` is not implemented for `()` = note: wrap the `()` in a closure with no arguments: `|| { /* code */ }` -error[E0308]: mismatched types - --> $DIR/lazy_subtyping_of_opaques.rs:11:5 - | -LL | Thunk::new(|cont| cont) - | ^^^^^^^^^^^^^^^^^^^^^^^ expected `Thunk<_>`, found `()` - | - = note: expected struct `Thunk<_>` - found unit type `()` - error: aborting due to 3 previous errors Some errors have detailed explanations: E0277, E0308. From 9070abab4b6862e42a8ce25eeb4a810301b76dd7 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 15 Oct 2024 13:47:43 -0400 Subject: [PATCH 336/357] Structurally resolve in may_coerce --- compiler/rustc_hir_typeck/src/coercion.rs | 23 +++++++++++++++++-- .../diagnostics/coerce-in-may-coerce.rs | 19 +++++++++++++++ .../diagnostics/coerce-in-may-coerce.stderr | 21 +++++++++++++++++ 3 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 tests/ui/traits/next-solver/diagnostics/coerce-in-may-coerce.rs create mode 100644 tests/ui/traits/next-solver/diagnostics/coerce-in-may-coerce.stderr diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index bb2f1f0493a..fb9262a59b9 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -1094,12 +1094,31 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let cause = self.cause(DUMMY_SP, ObligationCauseCode::ExprAssignable); // We don't ever need two-phase here since we throw out the result of the coercion. // We also just always set `coerce_never` to true, since this is a heuristic. - let coerce = Coerce::new(self, cause, AllowTwoPhase::No, true); + let coerce = Coerce::new(self, cause.clone(), AllowTwoPhase::No, true); self.probe(|_| { + // Make sure to structurally resolve the types, since we use + // the `TyKind`s heavily in coercion. + let ocx = ObligationCtxt::new(self); + let structurally_resolve = |ty| { + let ty = self.shallow_resolve(ty); + if self.next_trait_solver() + && let ty::Alias(..) = ty.kind() + { + ocx.structurally_normalize(&cause, self.param_env, ty) + } else { + Ok(ty) + } + }; + let Ok(expr_ty) = structurally_resolve(expr_ty) else { + return false; + }; + let Ok(target_ty) = structurally_resolve(target_ty) else { + return false; + }; + let Ok(ok) = coerce.coerce(expr_ty, target_ty) else { return false; }; - let ocx = ObligationCtxt::new(self); ocx.register_obligations(ok.obligations); ocx.select_where_possible().is_empty() }) diff --git a/tests/ui/traits/next-solver/diagnostics/coerce-in-may-coerce.rs b/tests/ui/traits/next-solver/diagnostics/coerce-in-may-coerce.rs new file mode 100644 index 00000000000..bd3dccad152 --- /dev/null +++ b/tests/ui/traits/next-solver/diagnostics/coerce-in-may-coerce.rs @@ -0,0 +1,19 @@ +//@ compile-flags: -Znext-solver + +trait Mirror { + type Assoc; +} +impl Mirror for T { + type Assoc = T; +} + +fn arg() -> &'static [i32; 1] { todo!() } + +fn arg_error(x: ::Assoc, y: ()) { todo!() } + +fn main() { + // Should suggest to reverse the args... + // but if we don't normalize the expected, then we don't. + arg_error((), || ()); + //~^ ERROR arguments to this function are incorrect +} diff --git a/tests/ui/traits/next-solver/diagnostics/coerce-in-may-coerce.stderr b/tests/ui/traits/next-solver/diagnostics/coerce-in-may-coerce.stderr new file mode 100644 index 00000000000..1938b3375a5 --- /dev/null +++ b/tests/ui/traits/next-solver/diagnostics/coerce-in-may-coerce.stderr @@ -0,0 +1,21 @@ +error[E0308]: arguments to this function are incorrect + --> $DIR/coerce-in-may-coerce.rs:17:5 + | +LL | arg_error((), || ()); + | ^^^^^^^^^ -- ----- expected `()`, found `{closure@$DIR/coerce-in-may-coerce.rs:17:19: 17:21}` + | | + | expected `::Assoc`, found `()` + | +note: function defined here + --> $DIR/coerce-in-may-coerce.rs:12:4 + | +LL | fn arg_error(x: ::Assoc, y: ()) { todo!() } + | ^^^^^^^^^ -------------------------- ----- +help: swap these arguments + | +LL | arg_error(|| (), ()); + | ~~~~~~~~~~~ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. From c7730989de17b0cbdc1d48481062745d31d5c5a0 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 28 Sep 2024 13:21:39 -0400 Subject: [PATCH 337/357] Don't check unsize goal in MIR validation when opaques remain --- compiler/rustc_mir_transform/src/validate.rs | 11 +++++++++++ tests/crashes/130921.rs | 10 ---------- tests/ui/impl-trait/unsize-cast-validation-rpit.rs | 12 ++++++++++++ 3 files changed, 23 insertions(+), 10 deletions(-) delete mode 100644 tests/crashes/130921.rs create mode 100644 tests/ui/impl-trait/unsize-cast-validation-rpit.rs diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index e353be6a105..25e68f44456 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -595,6 +595,17 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { &self, pred: impl Upcast, ty::Predicate<'tcx>>, ) -> bool { + let pred: ty::Predicate<'tcx> = pred.upcast(self.tcx); + + // We sometimes have to use `defining_opaque_types` for predicates + // to succeed here and figuring out how exactly that should work + // is annoying. It is harmless enough to just not validate anything + // in that case. We still check this after analysis as all opaque + // types have been revealed at this point. + if pred.has_opaque_types() { + return true; + } + let infcx = self.tcx.infer_ctxt().build(); let ocx = ObligationCtxt::new(&infcx); ocx.register_obligation(Obligation::new( diff --git a/tests/crashes/130921.rs b/tests/crashes/130921.rs deleted file mode 100644 index b7cb1303937..00000000000 --- a/tests/crashes/130921.rs +++ /dev/null @@ -1,10 +0,0 @@ -//@ known-bug: #130921 -//@ compile-flags: -Zvalidate-mir -Copt-level=0 --crate-type lib - -pub fn hello() -> [impl Sized; 2] { - if false { - let x = hello(); - let _: &[i32] = &x; - } - todo!() -} diff --git a/tests/ui/impl-trait/unsize-cast-validation-rpit.rs b/tests/ui/impl-trait/unsize-cast-validation-rpit.rs new file mode 100644 index 00000000000..cace30aca8a --- /dev/null +++ b/tests/ui/impl-trait/unsize-cast-validation-rpit.rs @@ -0,0 +1,12 @@ +//@ check-pass +//@ compile-flags: -Zvalidate-mir + +fn hello() -> &'static [impl Sized; 0] { + if false { + let x = hello(); + let _: &[i32] = x; + } + &[] +} + +fn main() {} From e9853961452b56997cc127b51308879b9cd09482 Mon Sep 17 00:00:00 2001 From: Matthew Maurer Date: Tue, 15 Oct 2024 20:56:20 +0000 Subject: [PATCH 338/357] llvm: Match aarch64 data layout to new LLVM layout LLVM has added 3 new address spaces to support special Windows use cases. These shouldn't trouble us for now, but LLVM requires matching data layouts. See llvm/llvm-project#111879 for details --- compiler/rustc_codegen_llvm/src/context.rs | 10 ++++++++++ .../src/spec/targets/aarch64_apple_darwin.rs | 3 ++- .../rustc_target/src/spec/targets/aarch64_apple_ios.rs | 3 ++- .../src/spec/targets/aarch64_apple_ios_macabi.rs | 3 ++- .../src/spec/targets/aarch64_apple_ios_sim.rs | 3 ++- .../src/spec/targets/aarch64_apple_tvos.rs | 3 ++- .../src/spec/targets/aarch64_apple_tvos_sim.rs | 3 ++- .../src/spec/targets/aarch64_apple_visionos.rs | 3 ++- .../src/spec/targets/aarch64_apple_visionos_sim.rs | 3 ++- .../src/spec/targets/aarch64_apple_watchos.rs | 3 ++- .../src/spec/targets/aarch64_apple_watchos_sim.rs | 3 ++- .../src/spec/targets/aarch64_kmc_solid_asp3.rs | 2 +- .../src/spec/targets/aarch64_linux_android.rs | 2 +- .../targets/aarch64_nintendo_switch_freestanding.rs | 2 +- .../src/spec/targets/aarch64_pc_windows_gnullvm.rs | 4 +++- .../src/spec/targets/aarch64_pc_windows_msvc.rs | 4 +++- .../src/spec/targets/aarch64_unknown_freebsd.rs | 2 +- .../src/spec/targets/aarch64_unknown_fuchsia.rs | 2 +- .../src/spec/targets/aarch64_unknown_hermit.rs | 2 +- .../src/spec/targets/aarch64_unknown_illumos.rs | 2 +- .../src/spec/targets/aarch64_unknown_linux_gnu.rs | 2 +- .../src/spec/targets/aarch64_unknown_linux_musl.rs | 2 +- .../src/spec/targets/aarch64_unknown_linux_ohos.rs | 2 +- .../src/spec/targets/aarch64_unknown_netbsd.rs | 2 +- .../src/spec/targets/aarch64_unknown_none.rs | 2 +- .../src/spec/targets/aarch64_unknown_none_softfloat.rs | 2 +- .../src/spec/targets/aarch64_unknown_nto_qnx700.rs | 2 +- .../src/spec/targets/aarch64_unknown_openbsd.rs | 2 +- .../src/spec/targets/aarch64_unknown_redox.rs | 2 +- .../src/spec/targets/aarch64_unknown_teeos.rs | 2 +- .../src/spec/targets/aarch64_unknown_trusty.rs | 2 +- .../src/spec/targets/aarch64_unknown_uefi.rs | 4 +++- .../src/spec/targets/aarch64_uwp_windows_msvc.rs | 4 +++- .../src/spec/targets/aarch64_wrs_vxworks.rs | 2 +- .../src/spec/targets/arm64_32_apple_watchos.rs | 3 ++- .../src/spec/targets/arm64e_apple_darwin.rs | 3 ++- .../rustc_target/src/spec/targets/arm64e_apple_ios.rs | 3 ++- .../rustc_target/src/spec/targets/arm64e_apple_tvos.rs | 3 ++- .../src/spec/targets/arm64ec_pc_windows_msvc.rs | 4 +++- 39 files changed, 72 insertions(+), 38 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index c836dd5473f..2f830d6f941 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -138,6 +138,16 @@ pub(crate) unsafe fn create_module<'ll>( } } + if llvm_version < (20, 0, 0) { + if sess.target.arch == "aarch64" || sess.target.arch.starts_with("arm64") { + // LLVM 20 defines three additional address spaces for alternate + // pointer kinds used in Windows. + // See https://github.com/llvm/llvm-project/pull/111879 + target_data_layout = + target_data_layout.replace("-p270:32:32-p271:32:32-p272:64:64", ""); + } + } + // Ensure the data-layout values hardcoded remain the defaults. { let tm = crate::back::write::create_informational_target_machine(tcx.sess, false); diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs index e6ce50a005f..adee6f5fe99 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs @@ -12,7 +12,8 @@ pub(crate) fn target() -> Target { std: Some(true), }, pointer_width: 64, - data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(), + data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32" + .into(), arch, options: TargetOptions { mcount: "\u{1}mcount".into(), diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs index 78441ede333..efc42b909e4 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs @@ -12,7 +12,8 @@ pub(crate) fn target() -> Target { std: Some(true), }, pointer_width: 64, - data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(), + data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32" + .into(), arch, options: TargetOptions { features: "+neon,+fp-armv8,+apple-a7".into(), diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs index 857abd21faf..be503d18bf1 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs @@ -12,7 +12,8 @@ pub(crate) fn target() -> Target { std: Some(true), }, pointer_width: 64, - data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(), + data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32" + .into(), arch, options: TargetOptions { features: "+neon,+fp-armv8,+apple-a12".into(), diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs index cbc8b7cd95e..04bbee45cd3 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs @@ -12,7 +12,8 @@ pub(crate) fn target() -> Target { std: Some(true), }, pointer_width: 64, - data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(), + data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32" + .into(), arch, options: TargetOptions { features: "+neon,+fp-armv8,+apple-a7".into(), diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs index f5176d35f80..fa0bc130e1c 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs @@ -12,7 +12,8 @@ pub(crate) fn target() -> Target { std: Some(true), }, pointer_width: 64, - data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(), + data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32" + .into(), arch, options: TargetOptions { features: "+neon,+fp-armv8,+apple-a7".into(), diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs index d6738514145..428045da493 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs @@ -12,7 +12,8 @@ pub(crate) fn target() -> Target { std: Some(true), }, pointer_width: 64, - data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(), + data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32" + .into(), arch, options: TargetOptions { features: "+neon,+fp-armv8,+apple-a7".into(), diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs index dc5dac4fd8f..62d6ffbd34f 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs @@ -12,7 +12,8 @@ pub(crate) fn target() -> Target { std: Some(false), }, pointer_width: 64, - data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(), + data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32" + .into(), arch, options: TargetOptions { features: "+neon,+fp-armv8,+apple-a16".into(), diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs index e9fe786f65e..a66c4f6e96b 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs @@ -12,7 +12,8 @@ pub(crate) fn target() -> Target { std: Some(false), }, pointer_width: 64, - data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(), + data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32" + .into(), arch, options: TargetOptions { features: "+neon,+fp-armv8,+apple-a16".into(), diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs index 4f5ce2f12e7..abd924b5934 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs @@ -12,7 +12,8 @@ pub(crate) fn target() -> Target { std: Some(true), }, pointer_width: 64, - data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(), + data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32" + .into(), arch, options: TargetOptions { features: "+v8a,+neon,+fp-armv8,+apple-a7".into(), diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs index 952c98c324f..ba85647fddc 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs @@ -12,7 +12,8 @@ pub(crate) fn target() -> Target { std: Some(true), }, pointer_width: 64, - data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(), + data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32" + .into(), arch, options: TargetOptions { features: "+neon,+fp-armv8,+apple-a7".into(), diff --git a/compiler/rustc_target/src/spec/targets/aarch64_kmc_solid_asp3.rs b/compiler/rustc_target/src/spec/targets/aarch64_kmc_solid_asp3.rs index 97ce53b2d8f..58fc703946e 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_kmc_solid_asp3.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_kmc_solid_asp3.rs @@ -11,7 +11,7 @@ pub(crate) fn target() -> Target { std: Some(true), }, pointer_width: 64, - data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), + data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), arch: "aarch64".into(), options: TargetOptions { linker: Some("aarch64-kmc-elf-gcc".into()), diff --git a/compiler/rustc_target/src/spec/targets/aarch64_linux_android.rs b/compiler/rustc_target/src/spec/targets/aarch64_linux_android.rs index a8ef5544a24..a021d317cc8 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_linux_android.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_linux_android.rs @@ -13,7 +13,7 @@ pub(crate) fn target() -> Target { std: Some(true), }, pointer_width: 64, - data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), + data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), arch: "aarch64".into(), options: TargetOptions { max_atomic_width: Some(128), diff --git a/compiler/rustc_target/src/spec/targets/aarch64_nintendo_switch_freestanding.rs b/compiler/rustc_target/src/spec/targets/aarch64_nintendo_switch_freestanding.rs index 1f1cd966326..6ac69e0f57f 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_nintendo_switch_freestanding.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_nintendo_switch_freestanding.rs @@ -15,7 +15,7 @@ pub(crate) fn target() -> Target { std: Some(false), }, pointer_width: 64, - data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), + data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), arch: "aarch64".into(), options: TargetOptions { features: "+v8a".into(), diff --git a/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_gnullvm.rs b/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_gnullvm.rs index 7a56809dcfc..8b96f589c74 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_gnullvm.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_gnullvm.rs @@ -15,7 +15,9 @@ pub(crate) fn target() -> Target { std: Some(true), }, pointer_width: 64, - data_layout: "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128-Fn32".into(), + data_layout: + "e-m:w-p270:32:32-p271:32:32-p272:64:64-p:64:64-i32:32-i64:64-i128:128-n32:64-S128-Fn32" + .into(), arch: "aarch64".into(), options: base, } diff --git a/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs index e1133a4ce05..14ce5edd2f3 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs @@ -14,7 +14,9 @@ pub(crate) fn target() -> Target { std: Some(true), }, pointer_width: 64, - data_layout: "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128-Fn32".into(), + data_layout: + "e-m:w-p270:32:32-p271:32:32-p272:64:64-p:64:64-i32:32-i64:64-i128:128-n32:64-S128-Fn32" + .into(), arch: "aarch64".into(), options: base, } diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_freebsd.rs index 2ca2f403e17..dd90161f440 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_freebsd.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_freebsd.rs @@ -10,7 +10,7 @@ pub(crate) fn target() -> Target { std: Some(true), }, pointer_width: 64, - data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), + data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), arch: "aarch64".into(), options: TargetOptions { features: "+v8a".into(), diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_fuchsia.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_fuchsia.rs index 26a736a2712..df13d52a223 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_fuchsia.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_fuchsia.rs @@ -10,7 +10,7 @@ pub(crate) fn target() -> Target { std: Some(true), }, pointer_width: 64, - data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), + data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), arch: "aarch64".into(), options: TargetOptions { features: "+v8a".into(), diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_hermit.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_hermit.rs index 3989cc13fba..459e888eb94 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_hermit.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_hermit.rs @@ -11,7 +11,7 @@ pub(crate) fn target() -> Target { }, pointer_width: 64, arch: "aarch64".into(), - data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), + data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), options: TargetOptions { features: "+v8a,+strict-align,+neon,+fp-armv8".into(), max_atomic_width: Some(128), diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_illumos.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_illumos.rs index b76f10b8efd..699376a7928 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_illumos.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_illumos.rs @@ -18,7 +18,7 @@ pub(crate) fn target() -> Target { std: Some(true), }, pointer_width: 64, - data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), + data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), arch: "aarch64".into(), options: base, } diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu.rs index 96c25af0a7f..18711cb399d 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu.rs @@ -10,7 +10,7 @@ pub(crate) fn target() -> Target { std: Some(true), }, pointer_width: 64, - data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), + data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), arch: "aarch64".into(), options: TargetOptions { features: "+v8a,+outline-atomics".into(), diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_musl.rs index 197ff2d74e5..bb65048a56d 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_musl.rs @@ -21,7 +21,7 @@ pub(crate) fn target() -> Target { std: Some(true), }, pointer_width: 64, - data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), + data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), arch: "aarch64".into(), options: TargetOptions { mcount: "\u{1}_mcount".into(), ..base }, } diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_ohos.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_ohos.rs index 9d5bce05350..22b3a5f8842 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_ohos.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_ohos.rs @@ -13,7 +13,7 @@ pub(crate) fn target() -> Target { std: Some(true), }, pointer_width: 64, - data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), + data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), arch: "aarch64".into(), options: TargetOptions { features: "+reserve-x18".into(), diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_netbsd.rs index d1769d1476c..0ec76e4b42f 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_netbsd.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_netbsd.rs @@ -10,7 +10,7 @@ pub(crate) fn target() -> Target { std: Some(true), }, pointer_width: 64, - data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), + data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), arch: "aarch64".into(), options: TargetOptions { features: "+v8a".into(), diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_none.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_none.rs index d124f8a3d29..05fe32734a7 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_none.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_none.rs @@ -37,7 +37,7 @@ pub(crate) fn target() -> Target { std: Some(false), }, pointer_width: 64, - data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), + data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), arch: "aarch64".into(), options: opts, } diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_none_softfloat.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_none_softfloat.rs index 7933041b584..d6b77ffd091 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_none_softfloat.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_none_softfloat.rs @@ -32,7 +32,7 @@ pub(crate) fn target() -> Target { std: Some(false), }, pointer_width: 64, - data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), + data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), arch: "aarch64".into(), options: opts, } diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx700.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx700.rs index 6c061112b16..441ed7cf153 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx700.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx700.rs @@ -22,7 +22,7 @@ pub(crate) fn target() -> Target { // i128:128 = 128-bit-integer, minimum_alignment=128, preferred_alignment=128 // n32:64 = 32 and 64 are native integer widths; Elements of this set are considered to support most general arithmetic operations efficiently. // S128 = 128 bits are the natural alignment of the stack in bits. - data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), + data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), arch: "aarch64".into(), options: TargetOptions { features: "+v8a".into(), diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_openbsd.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_openbsd.rs index 31c8daa98b0..0fcf5c34bb0 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_openbsd.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_openbsd.rs @@ -10,7 +10,7 @@ pub(crate) fn target() -> Target { std: Some(true), }, pointer_width: 64, - data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), + data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), arch: "aarch64".into(), options: TargetOptions { features: "+v8a".into(), diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_redox.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_redox.rs index 6bd8c306abb..7ff99c574ad 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_redox.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_redox.rs @@ -15,7 +15,7 @@ pub(crate) fn target() -> Target { std: None, // ? }, pointer_width: 64, - data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), + data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), arch: "aarch64".into(), options: base, } diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_teeos.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_teeos.rs index 4bffef4758d..fb8b59f7729 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_teeos.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_teeos.rs @@ -15,7 +15,7 @@ pub(crate) fn target() -> Target { std: None, // ? }, pointer_width: 64, - data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), + data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), arch: "aarch64".into(), options: base, } diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_trusty.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_trusty.rs index 69ab992e12c..cebd8ff2f68 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_trusty.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_trusty.rs @@ -12,7 +12,7 @@ pub(crate) fn target() -> Target { std: Some(false), }, pointer_width: 64, - data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), + data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), arch: "aarch64".into(), options: TargetOptions { features: "+neon,+fp-armv8,+reserve-x18".into(), diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_uefi.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_uefi.rs index bde1ce95b3f..9656024ddaa 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_uefi.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_uefi.rs @@ -19,7 +19,9 @@ pub(crate) fn target() -> Target { std: None, // ? }, pointer_width: 64, - data_layout: "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128-Fn32".into(), + data_layout: + "e-m:w-p270:32:32-p271:32:32-p272:64:64-p:64:64-i32:32-i64:64-i128:128-n32:64-S128-Fn32" + .into(), arch: "aarch64".into(), options: base, } diff --git a/compiler/rustc_target/src/spec/targets/aarch64_uwp_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/aarch64_uwp_windows_msvc.rs index c916aa6b23c..3d7c0269808 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_uwp_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_uwp_windows_msvc.rs @@ -14,7 +14,9 @@ pub(crate) fn target() -> Target { std: None, // ? }, pointer_width: 64, - data_layout: "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128-Fn32".into(), + data_layout: + "e-m:w-p270:32:32-p271:32:32-p272:64:64-p:64:64-i32:32-i64:64-i128:128-n32:64-S128-Fn32" + .into(), arch: "aarch64".into(), options: base, } diff --git a/compiler/rustc_target/src/spec/targets/aarch64_wrs_vxworks.rs b/compiler/rustc_target/src/spec/targets/aarch64_wrs_vxworks.rs index dd5298944e0..d5e78d03076 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_wrs_vxworks.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_wrs_vxworks.rs @@ -10,7 +10,7 @@ pub(crate) fn target() -> Target { std: Some(true), }, pointer_width: 64, - data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), + data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), arch: "aarch64".into(), options: TargetOptions { features: "+v8a".into(), diff --git a/compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs b/compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs index 4f7a1857e76..a5a6f772ac8 100644 --- a/compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs +++ b/compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs @@ -12,7 +12,8 @@ pub(crate) fn target() -> Target { std: Some(true), }, pointer_width: 32, - data_layout: "e-m:o-p:32:32-i64:64-i128:128-n32:64-S128-Fn32".into(), + data_layout: + "e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32".into(), arch, options: TargetOptions { features: "+v8a,+neon,+fp-armv8,+apple-a7".into(), diff --git a/compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs index 04906fb0460..744d95445b8 100644 --- a/compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs @@ -12,7 +12,8 @@ pub(crate) fn target() -> Target { std: Some(true), }, pointer_width: 64, - data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(), + data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32" + .into(), arch, options: TargetOptions { mcount: "\u{1}mcount".into(), diff --git a/compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs b/compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs index 3264669c169..dace11dae24 100644 --- a/compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs +++ b/compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs @@ -12,7 +12,8 @@ pub(crate) fn target() -> Target { std: Some(true), }, pointer_width: 64, - data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(), + data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32" + .into(), arch, options: TargetOptions { features: "+neon,+fp-armv8,+apple-a12,+v8.3a,+pauth".into(), diff --git a/compiler/rustc_target/src/spec/targets/arm64e_apple_tvos.rs b/compiler/rustc_target/src/spec/targets/arm64e_apple_tvos.rs index 4c231cb519c..2ccdc76c52e 100644 --- a/compiler/rustc_target/src/spec/targets/arm64e_apple_tvos.rs +++ b/compiler/rustc_target/src/spec/targets/arm64e_apple_tvos.rs @@ -12,7 +12,8 @@ pub(crate) fn target() -> Target { std: Some(true), }, pointer_width: 64, - data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(), + data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32" + .into(), arch, options: TargetOptions { features: "+neon,+fp-armv8,+apple-a12,+v8.3a,+pauth".into(), diff --git a/compiler/rustc_target/src/spec/targets/arm64ec_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/arm64ec_pc_windows_msvc.rs index a6744b95a3e..03c96fbfdb0 100644 --- a/compiler/rustc_target/src/spec/targets/arm64ec_pc_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/arm64ec_pc_windows_msvc.rs @@ -18,7 +18,9 @@ pub(crate) fn target() -> Target { std: None, // ? }, pointer_width: 64, - data_layout: "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128-Fn32".into(), + data_layout: + "e-m:w-p270:32:32-p271:32:32-p272:64:64-p:64:64-i32:32-i64:64-i128:128-n32:64-S128-Fn32" + .into(), arch: "arm64ec".into(), options: base, } From 4cf0475eeb6fb3aca3b67cd16127d825709a0bb4 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Wed, 16 Oct 2024 12:16:17 +1100 Subject: [PATCH 339/357] Fix unnecessary nesting in run-make test output directories --- src/tools/compiletest/src/runtest/run_make.rs | 6 +++++- tests/run-make/README.md | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/tools/compiletest/src/runtest/run_make.rs b/src/tools/compiletest/src/runtest/run_make.rs index 75fe6a6baaf..f8ffd0fbe3f 100644 --- a/src/tools/compiletest/src/runtest/run_make.rs +++ b/src/tools/compiletest/src/runtest/run_make.rs @@ -22,6 +22,10 @@ impl TestCx<'_> { let src_root = self.config.src_base.parent().unwrap().parent().unwrap(); let src_root = cwd.join(&src_root); + // FIXME(Zalathar): This should probably be `output_base_dir` to avoid + // an unnecessary extra subdirectory, but since legacy Makefile tests + // are hopefully going away, it seems safer to leave this perilous code + // as-is until it can all be deleted. let tmpdir = cwd.join(self.output_base_name()); if tmpdir.exists() { self.aggressive_rm_rf(&tmpdir).unwrap(); @@ -213,7 +217,7 @@ impl TestCx<'_> { // `rmake_out/` directory. // // This setup intentionally diverges from legacy Makefile run-make tests. - let base_dir = self.output_base_name(); + let base_dir = self.output_base_dir(); if base_dir.exists() { self.aggressive_rm_rf(&base_dir).unwrap(); } diff --git a/tests/run-make/README.md b/tests/run-make/README.md index 9e1eaa881c9..40359903473 100644 --- a/tests/run-make/README.md +++ b/tests/run-make/README.md @@ -29,7 +29,7 @@ The setup for the `rmake.rs` version is a 3-stage process: structure within `build//test/run-make/` ``` - // + / rmake.exe # recipe binary rmake_out/ # sources from test sources copied over ``` From 69faeafd0cac0f503f75a994f68f3e42af568046 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= <39484203+jieyouxu@users.noreply.github.com> Date: Wed, 16 Oct 2024 10:40:29 +0800 Subject: [PATCH 340/357] mailmap: add entry for my dev-desktop setup --- .mailmap | 1 + 1 file changed, 1 insertion(+) diff --git a/.mailmap b/.mailmap index dc5bfe6d5fc..bdc34c52aa7 100644 --- a/.mailmap +++ b/.mailmap @@ -280,6 +280,7 @@ Jerry Hardee Jesús Rubio Jethro Beekman Jian Zeng +Jieyou Xu <39484203+jieyouxu@users.noreply.github.com> Jihyun Yu Jihyun Yu jihyun Jihyun Yu Jihyun Yu From f204e2c23b20f3052acaec7e0e231deb4ee23e50 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Mon, 14 Oct 2024 10:22:50 -0700 Subject: [PATCH 341/357] replace placeholder version (cherry picked from commit 567fd9610cbfd220844443487059335d7e1ff021) --- compiler/rustc_feature/src/accepted.rs | 10 ++++---- compiler/rustc_feature/src/removed.rs | 4 ++-- compiler/rustc_feature/src/unstable.rs | 14 +++++------ library/core/src/array/mod.rs | 2 +- library/core/src/cell.rs | 8 +++---- library/core/src/cell/once.rs | 2 +- library/core/src/char/methods.rs | 6 ++--- library/core/src/fmt/builders.rs | 8 +++---- library/core/src/intrinsics.rs | 20 ++++++++-------- library/core/src/mem/maybe_uninit.rs | 5 +--- library/core/src/mem/mod.rs | 2 +- library/core/src/num/f32.rs | 32 ++++++++++++------------- library/core/src/num/f64.rs | 32 ++++++++++++------------- library/core/src/ops/control_flow.rs | 8 +++---- library/core/src/option.rs | 22 ++++++++--------- library/core/src/ptr/const_ptr.rs | 6 ++--- library/core/src/ptr/metadata.rs | 6 ++--- library/core/src/ptr/mod.rs | 8 +++---- library/core/src/ptr/mut_ptr.rs | 16 ++++++------- library/core/src/ptr/non_null.rs | 21 +++++++--------- library/core/src/result.rs | 8 +++---- library/core/src/slice/mod.rs | 22 ++++++++--------- library/core/src/slice/raw.rs | 4 ++-- library/core/src/str/converts.rs | 5 +--- library/core/src/str/mod.rs | 4 ++-- library/core/src/task/wake.rs | 8 +++---- library/core/src/time.rs | 8 +++---- library/std/src/collections/hash/map.rs | 20 ++++++++-------- library/std/src/collections/hash/set.rs | 4 ++-- library/std/src/io/error.rs | 32 ++++++++++++------------- library/std/src/io/mod.rs | 2 +- 31 files changed, 170 insertions(+), 179 deletions(-) diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index a850eb95620..0c5fe6e8d8b 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -116,7 +116,7 @@ declare_features! ( /// Allows calling constructor functions in `const fn`. (accepted, const_constructor, "1.40.0", Some(61456)), /// Allows the definition of `const extern fn` and `const unsafe extern fn`. - (accepted, const_extern_fn, "CURRENT_RUSTC_VERSION", Some(64926)), + (accepted, const_extern_fn, "1.83.0", Some(64926)), /// Allows basic arithmetic on floating point types in a `const fn`. (accepted, const_fn_floating_point_arithmetic, "1.82.0", Some(57241)), /// Allows using and casting function pointers in a `const fn`. @@ -144,15 +144,15 @@ declare_features! ( /// Allows the use of `loop` and `while` in constants. (accepted, const_loop, "1.46.0", Some(52000)), /// Allows using `&mut` in constant functions. - (accepted, const_mut_refs, "CURRENT_RUSTC_VERSION", Some(57349)), + (accepted, const_mut_refs, "1.83.0", Some(57349)), /// Allows panicking during const eval (producing compile-time errors). (accepted, const_panic, "1.57.0", Some(51999)), /// Allows dereferencing raw pointers during const eval. (accepted, const_raw_ptr_deref, "1.58.0", Some(51911)), /// Allows references to types with interior mutability within constants - (accepted, const_refs_to_cell, "CURRENT_RUSTC_VERSION", Some(80384)), + (accepted, const_refs_to_cell, "1.83.0", Some(80384)), /// Allows creating pointers and references to `static` items in constants. - (accepted, const_refs_to_static, "CURRENT_RUSTC_VERSION", Some(119618)), + (accepted, const_refs_to_static, "1.83.0", Some(119618)), /// Allows implementing `Copy` for closures where possible (RFC 2132). (accepted, copy_closures, "1.26.0", Some(44490)), /// Allows `crate` in paths. @@ -190,7 +190,7 @@ declare_features! ( /// Allows explicit generic arguments specification with `impl Trait` present. (accepted, explicit_generic_args_with_impl_trait, "1.63.0", Some(83701)), /// Uses 2024 rules for matching `expr` fragments in macros. Also enables `expr_2021` fragment. - (accepted, expr_fragment_specifier_2024, "CURRENT_RUSTC_VERSION", Some(123742)), + (accepted, expr_fragment_specifier_2024, "1.83.0", Some(123742)), /// Allows arbitrary expressions in key-value attributes at parse time. (accepted, extended_key_value_attributes, "1.54.0", Some(78835)), /// Allows resolving absolute paths as paths from other crates. diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs index cba4535156b..d797fee000d 100644 --- a/compiler/rustc_feature/src/removed.rs +++ b/compiler/rustc_feature/src/removed.rs @@ -156,7 +156,7 @@ declare_features! ( (removed, no_stack_check, "1.0.0", None, None), /// Allows making `dyn Trait` well-formed even if `Trait` is not dyn-compatible (object safe). /// Renamed to `dyn_compatible_for_dispatch`. - (removed, object_safe_for_dispatch, "CURRENT_RUSTC_VERSION", Some(43561), + (removed, object_safe_for_dispatch, "1.83.0", Some(43561), Some("renamed to `dyn_compatible_for_dispatch`")), /// Allows using `#[on_unimplemented(..)]` on traits. /// (Moved to `rustc_attrs`.) @@ -221,7 +221,7 @@ declare_features! ( /// Allows using items which are missing stability attributes (removed, unmarked_api, "1.0.0", None, None), /// Allows unnamed fields of struct and union type - (removed, unnamed_fields, "CURRENT_RUSTC_VERSION", Some(49804), Some("feature needs redesign")), + (removed, unnamed_fields, "1.83.0", Some(49804), Some("feature needs redesign")), (removed, unsafe_no_drop_flag, "1.0.0", None, None), /// Allows `union` fields that don't implement `Copy` as long as they don't have any drop glue. (removed, untagged_unions, "1.13.0", Some(55149), diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index c0398db9c10..1067156958d 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -228,7 +228,7 @@ declare_features! ( /// Added for testing unstable lints; perma-unstable. (internal, test_unstable_lint, "1.60.0", None), /// Helps with formatting for `group_imports = "StdExternalCrate"`. - (unstable, unqualified_local_imports, "CURRENT_RUSTC_VERSION", None), + (unstable, unqualified_local_imports, "1.83.0", None), /// Use for stable + negative coherence and strict coherence depending on trait's /// rustc_strict_coherence value. (unstable, with_negative_coherence, "1.60.0", None), @@ -266,7 +266,7 @@ declare_features! ( /// Renamed from `object_safe_for_dispatch`. /// /// [^1]: Formerly known as "object safe". - (unstable, dyn_compatible_for_dispatch, "CURRENT_RUSTC_VERSION", Some(43561)), + (unstable, dyn_compatible_for_dispatch, "1.83.0", Some(43561)), /// Allows using the `#[fundamental]` attribute. (unstable, fundamental, "1.0.0", Some(29635)), /// Allows using `#[link_name="llvm.*"]`. @@ -360,7 +360,7 @@ declare_features! ( /// Allows inherent and trait methods with arbitrary self types. (unstable, arbitrary_self_types, "1.23.0", Some(44874)), /// Allows inherent and trait methods with arbitrary self types that are raw pointers. - (unstable, arbitrary_self_types_pointers, "CURRENT_RUSTC_VERSION", Some(44874)), + (unstable, arbitrary_self_types_pointers, "1.83.0", Some(44874)), /// Enables experimental inline assembly support for additional architectures. (unstable, asm_experimental_arch, "1.58.0", Some(93335)), /// Allows using `label` operands in inline assembly. @@ -380,7 +380,7 @@ declare_features! ( /// Allows using C-variadics. (unstable, c_variadic, "1.34.0", Some(44930)), /// Allows the use of `#[cfg()]`. - (unstable, cfg_boolean_literals, "CURRENT_RUSTC_VERSION", Some(131204)), + (unstable, cfg_boolean_literals, "1.83.0", Some(131204)), /// Allows the use of `#[cfg(overflow_checks)` to check if integer overflow behaviour. (unstable, cfg_overflow_checks, "1.71.0", Some(111466)), /// Provides the relocation model information as cfg entry @@ -498,7 +498,7 @@ declare_features! ( /// Allows `if let` guard in match arms. (unstable, if_let_guard, "1.47.0", Some(51114)), /// Rescoping temporaries in `if let` to align with Rust 2024. - (unstable, if_let_rescope, "CURRENT_RUSTC_VERSION", Some(124085)), + (unstable, if_let_rescope, "1.83.0", Some(124085)), /// Allows `impl Trait` to be used inside associated types (RFC 2515). (unstable, impl_trait_in_assoc_type, "1.70.0", Some(63063)), /// Allows `impl Trait` as output type in `Fn` traits in return position of functions. @@ -563,11 +563,11 @@ declare_features! ( /// Allows specifying nop padding on functions for dynamic patching. (unstable, patchable_function_entry, "1.81.0", Some(123115)), /// Experimental features that make `Pin` more ergonomic. - (incomplete, pin_ergonomics, "CURRENT_RUSTC_VERSION", Some(130494)), + (incomplete, pin_ergonomics, "1.83.0", Some(130494)), /// Allows postfix match `expr.match { ... }` (unstable, postfix_match, "1.79.0", Some(121618)), /// Allows `use<..>` precise capturign on impl Trait in traits. - (unstable, precise_capturing_in_traits, "CURRENT_RUSTC_VERSION", Some(130044)), + (unstable, precise_capturing_in_traits, "1.83.0", Some(130044)), /// Allows macro attributes on expressions, statements and non-inline modules. (unstable, proc_macro_hygiene, "1.30.0", Some(54727)), /// Makes `&` and `&mut` patterns eat only one layer of references in Rust 2024. diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index a95046162d2..72f48878904 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -146,7 +146,7 @@ pub const fn from_ref(s: &T) -> &[T; 1] { /// Converts a mutable reference to `T` into a mutable reference to an array of length 1 (without copying). #[stable(feature = "array_from_ref", since = "1.53.0")] -#[rustc_const_stable(feature = "const_array_from_ref", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "const_array_from_ref", since = "1.83.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn from_mut(s: &mut T) -> &mut [T; 1] { // SAFETY: Converting `&mut T` to `&mut [T; 1]` is sound. diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index 513b9cbcefc..0945845021e 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -515,7 +515,7 @@ impl Cell { /// assert_eq!(five, 5); /// ``` #[stable(feature = "move_cell", since = "1.17.0")] - #[rustc_const_stable(feature = "const_cell_into_inner", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_cell_into_inner", since = "1.83.0")] #[rustc_allow_const_fn_unstable(const_precise_live_drops)] pub const fn into_inner(self) -> T { self.value.into_inner() @@ -864,7 +864,7 @@ impl RefCell { /// let five = c.into_inner(); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_cell_into_inner", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_cell_into_inner", since = "1.83.0")] #[rustc_allow_const_fn_unstable(const_precise_live_drops)] #[inline] pub const fn into_inner(self) -> T { @@ -2108,7 +2108,7 @@ impl UnsafeCell { /// ``` #[inline(always)] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_cell_into_inner", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_cell_into_inner", since = "1.83.0")] #[rustc_allow_const_fn_unstable(const_precise_live_drops)] pub const fn into_inner(self) -> T { self.value @@ -2182,7 +2182,7 @@ impl UnsafeCell { #[inline(always)] #[stable(feature = "unsafe_cell_get_mut", since = "1.50.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] - #[rustc_const_stable(feature = "const_unsafecell_get_mut", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_unsafecell_get_mut", since = "1.83.0")] pub const fn get_mut(&mut self) -> &mut T { &mut self.value } diff --git a/library/core/src/cell/once.rs b/library/core/src/cell/once.rs index 14c587e0c48..c14afe0f476 100644 --- a/library/core/src/cell/once.rs +++ b/library/core/src/cell/once.rs @@ -309,7 +309,7 @@ impl OnceCell { /// ``` #[inline] #[stable(feature = "once_cell", since = "1.70.0")] - #[rustc_const_stable(feature = "const_cell_into_inner", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_cell_into_inner", since = "1.83.0")] #[rustc_allow_const_fn_unstable(const_precise_live_drops)] pub const fn into_inner(self) -> Option { // Because `into_inner` takes `self` by value, the compiler statically verifies diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index 04698193bba..1abfaa46ec6 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs @@ -36,7 +36,7 @@ impl char { /// let value_at_min = u32::from(char::MIN); /// assert_eq!(char::from_u32(value_at_min), Some('\0')); /// ``` - #[stable(feature = "char_min", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "char_min", since = "1.83.0")] pub const MIN: char = '\0'; /// The highest valid code point a `char` can have, `'\u{10FFFF}'`. @@ -674,7 +674,7 @@ impl char { /// 'ß'.encode_utf8(&mut b); /// ``` #[stable(feature = "unicode_encode_char", since = "1.15.0")] - #[rustc_const_stable(feature = "const_char_encode_utf8", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_char_encode_utf8", since = "1.83.0")] #[inline] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn encode_utf8(self, dst: &mut [u8]) -> &mut str { @@ -1773,7 +1773,7 @@ const fn len_utf16(code: u32) -> usize { /// Panics if the buffer is not large enough. /// A buffer of length four is large enough to encode any `char`. #[unstable(feature = "char_internals", reason = "exposed only for libstd", issue = "none")] -#[rustc_const_stable(feature = "const_char_encode_utf8", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "const_char_encode_utf8", since = "1.83.0")] #[doc(hidden)] #[inline] #[rustc_allow_const_fn_unstable(const_eval_select)] diff --git a/library/core/src/fmt/builders.rs b/library/core/src/fmt/builders.rs index 3d0c9f7c964..1862be0e86c 100644 --- a/library/core/src/fmt/builders.rs +++ b/library/core/src/fmt/builders.rs @@ -383,7 +383,7 @@ impl<'a, 'b: 'a> DebugTuple<'a, 'b> { /// "Foo(10, ..)", /// ); /// ``` - #[stable(feature = "debug_more_non_exhaustive", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "debug_more_non_exhaustive", since = "1.83.0")] pub fn finish_non_exhaustive(&mut self) -> fmt::Result { self.result = self.result.and_then(|_| { if self.fields > 0 { @@ -626,7 +626,7 @@ impl<'a, 'b: 'a> DebugSet<'a, 'b> { /// "{1, 2, ..}", /// ); /// ``` - #[stable(feature = "debug_more_non_exhaustive", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "debug_more_non_exhaustive", since = "1.83.0")] pub fn finish_non_exhaustive(&mut self) -> fmt::Result { self.inner.result = self.inner.result.and_then(|_| { if self.inner.has_fields { @@ -818,7 +818,7 @@ impl<'a, 'b: 'a> DebugList<'a, 'b> { /// "[1, 2, ..]", /// ); /// ``` - #[stable(feature = "debug_more_non_exhaustive", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "debug_more_non_exhaustive", since = "1.83.0")] pub fn finish_non_exhaustive(&mut self) -> fmt::Result { self.inner.result.and_then(|_| { if self.inner.has_fields { @@ -1146,7 +1146,7 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { /// r#"{"A": 10, "B": 11, ..}"#, /// ); /// ``` - #[stable(feature = "debug_more_non_exhaustive", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "debug_more_non_exhaustive", since = "1.83.0")] pub fn finish_non_exhaustive(&mut self) -> fmt::Result { self.result = self.result.and_then(|_| { assert!(!self.has_key, "attempted to finish a map with a partial entry"); diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index e8f5af863c1..ca5b9fc98b9 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -1085,7 +1085,7 @@ extern "rust-intrinsic" { /// it does not require an `unsafe` block. /// Therefore, implementations must not require the user to uphold /// any safety invariants. - #[rustc_const_stable(feature = "const_intrinsic_forget", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_intrinsic_forget", since = "1.83.0")] #[rustc_safe_intrinsic] #[rustc_nounwind] pub fn forget(_: T); @@ -2541,7 +2541,7 @@ extern "rust-intrinsic" { /// This intrinsic can *only* be called where the pointer is a local without /// projections (`write_via_move(ptr, x)`, not `write_via_move(*ptr, x)`) so /// that it trivially obeys runtime-MIR rules about derefs in operands. - #[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_ptr_write", since = "1.83.0")] #[rustc_nounwind] pub fn write_via_move(ptr: *mut T, value: T); @@ -3070,7 +3070,7 @@ pub const fn type_id() -> u128 { /// change the possible layouts of pointers. #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] -#[rustc_const_stable(feature = "ptr_metadata_const", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "ptr_metadata_const", since = "1.83.0")] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn aggregate_raw_ptr, D, M>(_data: D, _meta: M) -> P { @@ -3095,7 +3095,7 @@ impl AggregateRawPtr<*mut T> for *mut P { /// This is used to implement functions like `ptr::metadata`. #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] -#[rustc_const_stable(feature = "ptr_metadata_const", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "ptr_metadata_const", since = "1.83.0")] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn ptr_metadata + ?Sized, M>(_ptr: *const P) -> M { @@ -3196,13 +3196,13 @@ pub const fn ptr_metadata + ?Sized, M>(_ptr: *cons #[doc(alias = "memcpy")] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_allowed_through_unstable_modules] -#[rustc_const_stable(feature = "const_intrinsic_copy", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_diagnostic_item = "ptr_copy_nonoverlapping"] pub const unsafe fn copy_nonoverlapping(src: *const T, dst: *mut T, count: usize) { extern "rust-intrinsic" { - #[rustc_const_stable(feature = "const_intrinsic_copy", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] #[rustc_nounwind] pub fn copy_nonoverlapping(src: *const T, dst: *mut T, count: usize); } @@ -3300,13 +3300,13 @@ pub const unsafe fn copy_nonoverlapping(src: *const T, dst: *mut T, count: us #[doc(alias = "memmove")] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_allowed_through_unstable_modules] -#[rustc_const_stable(feature = "const_intrinsic_copy", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_diagnostic_item = "ptr_copy"] pub const unsafe fn copy(src: *const T, dst: *mut T, count: usize) { extern "rust-intrinsic" { - #[rustc_const_stable(feature = "const_intrinsic_copy", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] #[rustc_nounwind] fn copy(src: *const T, dst: *mut T, count: usize); } @@ -3381,13 +3381,13 @@ pub const unsafe fn copy(src: *const T, dst: *mut T, count: usize) { #[doc(alias = "memset")] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_allowed_through_unstable_modules] -#[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "const_ptr_write", since = "1.83.0")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_diagnostic_item = "ptr_write_bytes"] pub const unsafe fn write_bytes(dst: *mut T, val: u8, count: usize) { extern "rust-intrinsic" { - #[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_ptr_write", since = "1.83.0")] #[rustc_nounwind] fn write_bytes(dst: *mut T, val: u8, count: usize); } diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index f992785c43b..bb01d4e642c 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -569,10 +569,7 @@ impl MaybeUninit { /// (Notice that the rules around references to uninitialized data are not finalized yet, but /// until they are, it is advisable to avoid them.) #[stable(feature = "maybe_uninit", since = "1.36.0")] - #[rustc_const_stable( - feature = "const_maybe_uninit_as_mut_ptr", - since = "CURRENT_RUSTC_VERSION" - )] + #[rustc_const_stable(feature = "const_maybe_uninit_as_mut_ptr", since = "1.83.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[inline(always)] pub const fn as_mut_ptr(&mut self) -> *mut T { diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index 9bf2aa594c0..ada80463306 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -858,7 +858,7 @@ pub fn take(dest: &mut T) -> T { #[stable(feature = "rust1", since = "1.0.0")] #[must_use = "if you don't need the old value, you can just assign the new value directly"] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] -#[rustc_const_stable(feature = "const_replace", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "const_replace", since = "1.83.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "mem_replace")] pub const fn replace(dest: &mut T, src: T) -> T { // It may be tempting to use `swap` to avoid `unsafe` here. Don't! diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index 05f5a08ad0a..a01761ee5d4 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -517,7 +517,7 @@ impl f32 { /// ``` #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")] #[inline] #[allow(clippy::eq_op)] // > if you intended to check if the operand is NaN, use `.is_nan()` instead :) pub const fn is_nan(self) -> bool { @@ -550,7 +550,7 @@ impl f32 { /// ``` #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")] #[inline] pub const fn is_infinite(self) -> bool { // Getting clever with transmutation can result in incorrect answers on some FPUs @@ -575,7 +575,7 @@ impl f32 { /// ``` #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")] #[inline] pub const fn is_finite(self) -> bool { // There's no need to handle NaN separately: if self is NaN, @@ -603,7 +603,7 @@ impl f32 { /// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number #[must_use] #[stable(feature = "is_subnormal", since = "1.53.0")] - #[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")] #[inline] pub const fn is_subnormal(self) -> bool { matches!(self.classify(), FpCategory::Subnormal) @@ -630,7 +630,7 @@ impl f32 { /// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")] #[inline] pub const fn is_normal(self) -> bool { matches!(self.classify(), FpCategory::Normal) @@ -650,7 +650,7 @@ impl f32 { /// assert_eq!(inf.classify(), FpCategory::Infinite); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")] pub const fn classify(self) -> FpCategory { // We used to have complicated logic here that avoids the simple bit-based tests to work // around buggy codegen for x87 targets (see @@ -686,7 +686,7 @@ impl f32 { /// ``` #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")] #[inline] pub const fn is_sign_positive(self) -> bool { !self.is_sign_negative() @@ -711,7 +711,7 @@ impl f32 { /// ``` #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")] #[inline] pub const fn is_sign_negative(self) -> bool { // IEEE754 says: isSignMinus(x) is true if and only if x has negative sign. isSignMinus @@ -1093,7 +1093,7 @@ impl f32 { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[stable(feature = "float_bits_conv", since = "1.20.0")] - #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")] #[inline] pub const fn to_bits(self) -> u32 { // SAFETY: `u32` is a plain old datatype so we can always transmute to it. @@ -1137,7 +1137,7 @@ impl f32 { /// assert_eq!(v, 12.5); /// ``` #[stable(feature = "float_bits_conv", since = "1.20.0")] - #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")] #[must_use] #[inline] pub const fn from_bits(v: u32) -> Self { @@ -1161,7 +1161,7 @@ impl f32 { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[stable(feature = "float_to_from_bytes", since = "1.40.0")] - #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")] #[inline] pub const fn to_be_bytes(self) -> [u8; 4] { self.to_bits().to_be_bytes() @@ -1182,7 +1182,7 @@ impl f32 { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[stable(feature = "float_to_from_bytes", since = "1.40.0")] - #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")] #[inline] pub const fn to_le_bytes(self) -> [u8; 4] { self.to_bits().to_le_bytes() @@ -1216,7 +1216,7 @@ impl f32 { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[stable(feature = "float_to_from_bytes", since = "1.40.0")] - #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")] #[inline] pub const fn to_ne_bytes(self) -> [u8; 4] { self.to_bits().to_ne_bytes() @@ -1234,7 +1234,7 @@ impl f32 { /// assert_eq!(value, 12.5); /// ``` #[stable(feature = "float_to_from_bytes", since = "1.40.0")] - #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")] #[must_use] #[inline] pub const fn from_be_bytes(bytes: [u8; 4]) -> Self { @@ -1253,7 +1253,7 @@ impl f32 { /// assert_eq!(value, 12.5); /// ``` #[stable(feature = "float_to_from_bytes", since = "1.40.0")] - #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")] #[must_use] #[inline] pub const fn from_le_bytes(bytes: [u8; 4]) -> Self { @@ -1283,7 +1283,7 @@ impl f32 { /// assert_eq!(value, 12.5); /// ``` #[stable(feature = "float_to_from_bytes", since = "1.40.0")] - #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")] #[must_use] #[inline] pub const fn from_ne_bytes(bytes: [u8; 4]) -> Self { diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index 89c6726d985..2995e41cd6e 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -516,7 +516,7 @@ impl f64 { /// ``` #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")] #[inline] #[allow(clippy::eq_op)] // > if you intended to check if the operand is NaN, use `.is_nan()` instead :) pub const fn is_nan(self) -> bool { @@ -549,7 +549,7 @@ impl f64 { /// ``` #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")] #[inline] pub const fn is_infinite(self) -> bool { // Getting clever with transmutation can result in incorrect answers on some FPUs @@ -574,7 +574,7 @@ impl f64 { /// ``` #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")] #[inline] pub const fn is_finite(self) -> bool { // There's no need to handle NaN separately: if self is NaN, @@ -602,7 +602,7 @@ impl f64 { /// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number #[must_use] #[stable(feature = "is_subnormal", since = "1.53.0")] - #[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")] #[inline] pub const fn is_subnormal(self) -> bool { matches!(self.classify(), FpCategory::Subnormal) @@ -629,7 +629,7 @@ impl f64 { /// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")] #[inline] pub const fn is_normal(self) -> bool { matches!(self.classify(), FpCategory::Normal) @@ -649,7 +649,7 @@ impl f64 { /// assert_eq!(inf.classify(), FpCategory::Infinite); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")] pub const fn classify(self) -> FpCategory { // We used to have complicated logic here that avoids the simple bit-based tests to work // around buggy codegen for x87 targets (see @@ -685,7 +685,7 @@ impl f64 { /// ``` #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")] #[inline] pub const fn is_sign_positive(self) -> bool { !self.is_sign_negative() @@ -719,7 +719,7 @@ impl f64 { /// ``` #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")] #[inline] pub const fn is_sign_negative(self) -> bool { // IEEE754 says: isSignMinus(x) is true if and only if x has negative sign. isSignMinus @@ -1093,7 +1093,7 @@ impl f64 { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[stable(feature = "float_bits_conv", since = "1.20.0")] - #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")] #[inline] pub const fn to_bits(self) -> u64 { // SAFETY: `u64` is a plain old datatype so we can always transmute to it. @@ -1137,7 +1137,7 @@ impl f64 { /// assert_eq!(v, 12.5); /// ``` #[stable(feature = "float_bits_conv", since = "1.20.0")] - #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")] #[must_use] #[inline] pub const fn from_bits(v: u64) -> Self { @@ -1161,7 +1161,7 @@ impl f64 { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[stable(feature = "float_to_from_bytes", since = "1.40.0")] - #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")] #[inline] pub const fn to_be_bytes(self) -> [u8; 8] { self.to_bits().to_be_bytes() @@ -1182,7 +1182,7 @@ impl f64 { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[stable(feature = "float_to_from_bytes", since = "1.40.0")] - #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")] #[inline] pub const fn to_le_bytes(self) -> [u8; 8] { self.to_bits().to_le_bytes() @@ -1216,7 +1216,7 @@ impl f64 { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[stable(feature = "float_to_from_bytes", since = "1.40.0")] - #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")] #[inline] pub const fn to_ne_bytes(self) -> [u8; 8] { self.to_bits().to_ne_bytes() @@ -1234,7 +1234,7 @@ impl f64 { /// assert_eq!(value, 12.5); /// ``` #[stable(feature = "float_to_from_bytes", since = "1.40.0")] - #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")] #[must_use] #[inline] pub const fn from_be_bytes(bytes: [u8; 8]) -> Self { @@ -1253,7 +1253,7 @@ impl f64 { /// assert_eq!(value, 12.5); /// ``` #[stable(feature = "float_to_from_bytes", since = "1.40.0")] - #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")] #[must_use] #[inline] pub const fn from_le_bytes(bytes: [u8; 8]) -> Self { @@ -1283,7 +1283,7 @@ impl f64 { /// assert_eq!(value, 12.5); /// ``` #[stable(feature = "float_to_from_bytes", since = "1.40.0")] - #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")] #[must_use] #[inline] pub const fn from_ne_bytes(bytes: [u8; 8]) -> Self { diff --git a/library/core/src/ops/control_flow.rs b/library/core/src/ops/control_flow.rs index 7a8158b8231..55deabbee8f 100644 --- a/library/core/src/ops/control_flow.rs +++ b/library/core/src/ops/control_flow.rs @@ -177,7 +177,7 @@ impl ControlFlow { /// assert_eq!(ControlFlow::::Continue(3).break_value(), None); /// ``` #[inline] - #[stable(feature = "control_flow_enum", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "control_flow_enum", since = "1.83.0")] pub fn break_value(self) -> Option { match self { ControlFlow::Continue(..) => None, @@ -188,7 +188,7 @@ impl ControlFlow { /// Maps `ControlFlow` to `ControlFlow` by applying a function /// to the break value in case it exists. #[inline] - #[stable(feature = "control_flow_enum", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "control_flow_enum", since = "1.83.0")] pub fn map_break(self, f: impl FnOnce(B) -> T) -> ControlFlow { match self { ControlFlow::Continue(x) => ControlFlow::Continue(x), @@ -208,7 +208,7 @@ impl ControlFlow { /// assert_eq!(ControlFlow::::Continue(3).continue_value(), Some(3)); /// ``` #[inline] - #[stable(feature = "control_flow_enum", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "control_flow_enum", since = "1.83.0")] pub fn continue_value(self) -> Option { match self { ControlFlow::Continue(x) => Some(x), @@ -219,7 +219,7 @@ impl ControlFlow { /// Maps `ControlFlow` to `ControlFlow` by applying a function /// to the continue value in case it exists. #[inline] - #[stable(feature = "control_flow_enum", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "control_flow_enum", since = "1.83.0")] pub fn map_continue(self, f: impl FnOnce(C) -> T) -> ControlFlow { match self { ControlFlow::Continue(x) => ControlFlow::Continue(f(x)), diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 84ccb7a1f66..661176ce9fc 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -724,7 +724,7 @@ impl Option { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] - #[rustc_const_stable(feature = "const_option", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_option", since = "1.83.0")] pub const fn as_mut(&mut self) -> Option<&mut T> { match *self { Some(ref mut x) => Some(x), @@ -926,7 +926,7 @@ impl Option { #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "option_expect")] #[rustc_allow_const_fn_unstable(const_precise_live_drops)] - #[rustc_const_stable(feature = "const_option", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_option", since = "1.83.0")] pub const fn expect(self, msg: &str) -> T { match self { Some(val) => val, @@ -965,7 +965,7 @@ impl Option { #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "option_unwrap")] #[rustc_allow_const_fn_unstable(const_precise_live_drops)] - #[rustc_const_stable(feature = "const_option", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_option", since = "1.83.0")] pub const fn unwrap(self) -> T { match self { Some(val) => val, @@ -1073,7 +1073,7 @@ impl Option { #[track_caller] #[stable(feature = "option_result_unwrap_unchecked", since = "1.58.0")] #[rustc_allow_const_fn_unstable(const_precise_live_drops)] - #[rustc_const_stable(feature = "const_option", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_option", since = "1.83.0")] pub const unsafe fn unwrap_unchecked(self) -> T { match self { Some(val) => val, @@ -1655,7 +1655,7 @@ impl Option { /// assert_eq!(x, Some(7)); /// ``` #[inline] - #[stable(feature = "option_get_or_insert_default", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "option_get_or_insert_default", since = "1.83.0")] pub fn get_or_insert_default(&mut self) -> &mut T where T: Default, @@ -1717,7 +1717,7 @@ impl Option { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] - #[rustc_const_stable(feature = "const_option", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_option", since = "1.83.0")] pub const fn take(&mut self) -> Option { // FIXME(const-hack) replace `mem::replace` by `mem::take` when the latter is const ready mem::replace(self, None) @@ -1776,7 +1776,7 @@ impl Option { #[inline] #[stable(feature = "option_replace", since = "1.31.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] - #[rustc_const_stable(feature = "const_option", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_option", since = "1.83.0")] pub const fn replace(&mut self, value: T) -> Option { mem::replace(self, Some(value)) } @@ -1884,7 +1884,7 @@ impl Option<&T> { /// ``` #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "copied", since = "1.35.0")] - #[rustc_const_stable(feature = "const_option", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_option", since = "1.83.0")] pub const fn copied(self) -> Option where T: Copy, @@ -1938,7 +1938,7 @@ impl Option<&mut T> { #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "copied", since = "1.35.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] - #[rustc_const_stable(feature = "const_option", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_option", since = "1.83.0")] pub const fn copied(self) -> Option where T: Copy, @@ -1994,7 +1994,7 @@ impl Option> { #[inline] #[stable(feature = "transpose_result", since = "1.33.0")] #[rustc_allow_const_fn_unstable(const_precise_live_drops)] - #[rustc_const_stable(feature = "const_option", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_option", since = "1.83.0")] pub const fn transpose(self) -> Result, E> { match self { Some(Ok(x)) => Ok(Some(x)), @@ -2542,7 +2542,7 @@ impl Option> { #[inline] #[stable(feature = "option_flattening", since = "1.40.0")] #[rustc_allow_const_fn_unstable(const_precise_live_drops)] - #[rustc_const_stable(feature = "const_option", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_option", since = "1.83.0")] pub const fn flatten(self) -> Option { // FIXME(const-hack): could be written with `and_then` match self { diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 0b0449d6174..72f4bc2c9da 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -113,7 +113,7 @@ impl *const T { /// println!("{:?}", unsafe { &*bad }); /// ``` #[unstable(feature = "set_ptr_value", issue = "75091")] - #[rustc_const_stable(feature = "ptr_metadata_const", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "ptr_metadata_const", since = "1.83.0")] #[must_use = "returns a new pointer rather than modifying its argument"] #[inline] pub const fn with_metadata_of(self, meta: *const U) -> *const U @@ -1299,7 +1299,7 @@ impl *const T { /// See [`ptr::copy`] for safety concerns and examples. /// /// [`ptr::copy`]: crate::ptr::copy() - #[rustc_const_stable(feature = "const_intrinsic_copy", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces @@ -1319,7 +1319,7 @@ impl *const T { /// See [`ptr::copy_nonoverlapping`] for safety concerns and examples. /// /// [`ptr::copy_nonoverlapping`]: crate::ptr::copy_nonoverlapping() - #[rustc_const_stable(feature = "const_intrinsic_copy", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces diff --git a/library/core/src/ptr/metadata.rs b/library/core/src/ptr/metadata.rs index feeaf78d3e7..09c4002dbc7 100644 --- a/library/core/src/ptr/metadata.rs +++ b/library/core/src/ptr/metadata.rs @@ -92,7 +92,7 @@ pub trait Thin = Pointee; /// /// assert_eq!(std::ptr::metadata("foo"), 3_usize); /// ``` -#[rustc_const_stable(feature = "ptr_metadata_const", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "ptr_metadata_const", since = "1.83.0")] #[inline] pub const fn metadata(ptr: *const T) -> ::Metadata { ptr_metadata(ptr) @@ -106,7 +106,7 @@ pub const fn metadata(ptr: *const T) -> ::Metadata { /// /// [`slice::from_raw_parts`]: crate::slice::from_raw_parts #[unstable(feature = "ptr_metadata", issue = "81513")] -#[rustc_const_stable(feature = "ptr_metadata_const", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "ptr_metadata_const", since = "1.83.0")] #[inline] pub const fn from_raw_parts( data_pointer: *const impl Thin, @@ -120,7 +120,7 @@ pub const fn from_raw_parts( /// /// See the documentation of [`from_raw_parts`] for more details. #[unstable(feature = "ptr_metadata", issue = "81513")] -#[rustc_const_stable(feature = "ptr_metadata_const", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "ptr_metadata_const", since = "1.83.0")] #[inline] pub const fn from_raw_parts_mut( data_pointer: *mut impl Thin, diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index dd93f919c92..61b48e312cf 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -992,7 +992,7 @@ pub const fn slice_from_raw_parts(data: *const T, len: usize) -> *const [T] { /// ``` #[inline] #[stable(feature = "slice_from_raw_parts", since = "1.42.0")] -#[rustc_const_stable(feature = "const_slice_from_raw_parts_mut", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "const_slice_from_raw_parts_mut", since = "1.83.0")] #[rustc_diagnostic_item = "ptr_slice_from_raw_parts_mut"] pub const fn slice_from_raw_parts_mut(data: *mut T, len: usize) -> *mut [T] { from_raw_parts_mut(data, len) @@ -1266,7 +1266,7 @@ const unsafe fn swap_nonoverlapping_simple_untyped(x: *mut T, y: *mut T, coun #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] -#[rustc_const_stable(feature = "const_replace", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "const_replace", since = "1.83.0")] #[rustc_diagnostic_item = "ptr_replace"] pub const unsafe fn replace(dst: *mut T, src: T) -> T { // SAFETY: the caller must guarantee that `dst` is valid to be @@ -1616,7 +1616,7 @@ pub const unsafe fn read_unaligned(src: *const T) -> T { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "const_ptr_write", since = "1.83.0")] #[rustc_diagnostic_item = "ptr_write"] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn write(dst: *mut T, src: T) { @@ -1726,7 +1726,7 @@ pub const unsafe fn write(dst: *mut T, src: T) { #[inline] #[stable(feature = "ptr_unaligned", since = "1.17.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_refs_to_cell))] -#[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "const_ptr_write", since = "1.83.0")] #[rustc_diagnostic_item = "ptr_write_unaligned"] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn write_unaligned(dst: *mut T, src: T) { diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 8b61da74d02..d7ce197848b 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -94,7 +94,7 @@ impl *mut T { /// // This dereference is UB. The pointer only has provenance for `x` but points to `y`. /// println!("{:?}", unsafe { &*bad }); #[unstable(feature = "set_ptr_value", issue = "75091")] - #[rustc_const_stable(feature = "ptr_metadata_const", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "ptr_metadata_const", since = "1.83.0")] #[must_use = "returns a new pointer rather than modifying its argument"] #[inline] pub const fn with_metadata_of(self, meta: *const U) -> *mut U @@ -1378,7 +1378,7 @@ impl *mut T { /// See [`ptr::copy`] for safety concerns and examples. /// /// [`ptr::copy`]: crate::ptr::copy() - #[rustc_const_stable(feature = "const_intrinsic_copy", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces @@ -1398,7 +1398,7 @@ impl *mut T { /// See [`ptr::copy_nonoverlapping`] for safety concerns and examples. /// /// [`ptr::copy_nonoverlapping`]: crate::ptr::copy_nonoverlapping() - #[rustc_const_stable(feature = "const_intrinsic_copy", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces @@ -1418,7 +1418,7 @@ impl *mut T { /// See [`ptr::copy`] for safety concerns and examples. /// /// [`ptr::copy`]: crate::ptr::copy() - #[rustc_const_stable(feature = "const_intrinsic_copy", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces @@ -1438,7 +1438,7 @@ impl *mut T { /// See [`ptr::copy_nonoverlapping`] for safety concerns and examples. /// /// [`ptr::copy_nonoverlapping`]: crate::ptr::copy_nonoverlapping() - #[rustc_const_stable(feature = "const_intrinsic_copy", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces @@ -1469,7 +1469,7 @@ impl *mut T { /// /// [`ptr::write`]: crate::ptr::write() #[stable(feature = "pointer_methods", since = "1.26.0")] - #[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_ptr_write", since = "1.83.0")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn write(self, val: T) @@ -1488,7 +1488,7 @@ impl *mut T { /// [`ptr::write_bytes`]: crate::ptr::write_bytes() #[doc(alias = "memset")] #[stable(feature = "pointer_methods", since = "1.26.0")] - #[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_ptr_write", since = "1.83.0")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn write_bytes(self, val: u8, count: usize) @@ -1529,7 +1529,7 @@ impl *mut T { /// /// [`ptr::write_unaligned`]: crate::ptr::write_unaligned() #[stable(feature = "pointer_methods", since = "1.26.0")] - #[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_ptr_write", since = "1.83.0")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn write_unaligned(self, val: T) diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index 980d4a3cf6c..c6839136348 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -395,7 +395,7 @@ impl NonNull { /// [the module documentation]: crate::ptr#safety #[stable(feature = "nonnull", since = "1.25.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] - #[rustc_const_stable(feature = "const_ptr_as_ref", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_ptr_as_ref", since = "1.83.0")] #[must_use] #[inline(always)] pub const unsafe fn as_mut<'a>(&mut self) -> &'a mut T { @@ -923,7 +923,7 @@ impl NonNull { #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[stable(feature = "non_null_convenience", since = "1.80.0")] - #[rustc_const_stable(feature = "const_intrinsic_copy", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] pub const unsafe fn copy_to(self, dest: NonNull, count: usize) where T: Sized, @@ -943,7 +943,7 @@ impl NonNull { #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[stable(feature = "non_null_convenience", since = "1.80.0")] - #[rustc_const_stable(feature = "const_intrinsic_copy", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] pub const unsafe fn copy_to_nonoverlapping(self, dest: NonNull, count: usize) where T: Sized, @@ -963,7 +963,7 @@ impl NonNull { #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[stable(feature = "non_null_convenience", since = "1.80.0")] - #[rustc_const_stable(feature = "const_intrinsic_copy", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] pub const unsafe fn copy_from(self, src: NonNull, count: usize) where T: Sized, @@ -983,7 +983,7 @@ impl NonNull { #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[stable(feature = "non_null_convenience", since = "1.80.0")] - #[rustc_const_stable(feature = "const_intrinsic_copy", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] pub const unsafe fn copy_from_nonoverlapping(self, src: NonNull, count: usize) where T: Sized, @@ -1013,7 +1013,7 @@ impl NonNull { #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[stable(feature = "non_null_convenience", since = "1.80.0")] - #[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_ptr_write", since = "1.83.0")] pub const unsafe fn write(self, val: T) where T: Sized, @@ -1032,7 +1032,7 @@ impl NonNull { #[doc(alias = "memset")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[stable(feature = "non_null_convenience", since = "1.80.0")] - #[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_ptr_write", since = "1.83.0")] pub const unsafe fn write_bytes(self, val: u8, count: usize) where T: Sized, @@ -1073,7 +1073,7 @@ impl NonNull { #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[stable(feature = "non_null_convenience", since = "1.80.0")] - #[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_ptr_write", since = "1.83.0")] pub const unsafe fn write_unaligned(self, val: T) where T: Sized, @@ -1432,10 +1432,7 @@ impl NonNull<[T]> { /// (Note that this example artificially demonstrates a use of this method, /// but `let slice = NonNull::from(&x[..]);` would be a better way to write code like this.) #[stable(feature = "nonnull_slice_from_raw_parts", since = "1.70.0")] - #[rustc_const_stable( - feature = "const_slice_from_raw_parts_mut", - since = "CURRENT_RUSTC_VERSION" - )] + #[rustc_const_stable(feature = "const_slice_from_raw_parts_mut", since = "1.83.0")] #[must_use] #[inline] pub const fn slice_from_raw_parts(data: NonNull, len: usize) -> Self { diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 95faacbf96d..e84c4e3a239 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -734,7 +734,7 @@ impl Result { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_result", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_result", since = "1.83.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn as_mut(&mut self) -> Result<&mut T, &mut E> { match *self { @@ -1537,7 +1537,7 @@ impl Result<&T, E> { /// ``` #[inline] #[stable(feature = "result_copied", since = "1.59.0")] - #[rustc_const_stable(feature = "const_result", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_result", since = "1.83.0")] #[rustc_allow_const_fn_unstable(const_precise_live_drops)] pub const fn copied(self) -> Result where @@ -1588,7 +1588,7 @@ impl Result<&mut T, E> { /// ``` #[inline] #[stable(feature = "result_copied", since = "1.59.0")] - #[rustc_const_stable(feature = "const_result", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_result", since = "1.83.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[rustc_allow_const_fn_unstable(const_precise_live_drops)] pub const fn copied(self) -> Result @@ -1643,7 +1643,7 @@ impl Result, E> { /// ``` #[inline] #[stable(feature = "transpose_result", since = "1.33.0")] - #[rustc_const_stable(feature = "const_result", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_result", since = "1.83.0")] #[rustc_allow_const_fn_unstable(const_precise_live_drops)] pub const fn transpose(self) -> Option> { match self { diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 90ddc9c1d85..9fdcea1f7b7 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -172,7 +172,7 @@ impl [T] { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] - #[rustc_const_stable(feature = "const_slice_first_last", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_slice_first_last", since = "1.83.0")] #[inline] #[must_use] pub const fn first_mut(&mut self) -> Option<&mut T> { @@ -215,7 +215,7 @@ impl [T] { /// ``` #[stable(feature = "slice_splits", since = "1.5.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] - #[rustc_const_stable(feature = "const_slice_first_last", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_slice_first_last", since = "1.83.0")] #[inline] #[must_use] pub const fn split_first_mut(&mut self) -> Option<(&mut T, &mut [T])> { @@ -258,7 +258,7 @@ impl [T] { /// ``` #[stable(feature = "slice_splits", since = "1.5.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] - #[rustc_const_stable(feature = "const_slice_first_last", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_slice_first_last", since = "1.83.0")] #[inline] #[must_use] pub const fn split_last_mut(&mut self) -> Option<(&mut T, &mut [T])> { @@ -301,7 +301,7 @@ impl [T] { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] - #[rustc_const_stable(feature = "const_slice_first_last", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_slice_first_last", since = "1.83.0")] #[inline] #[must_use] pub const fn last_mut(&mut self) -> Option<&mut T> { @@ -356,7 +356,7 @@ impl [T] { /// ``` #[inline] #[stable(feature = "slice_first_last_chunk", since = "1.77.0")] - #[rustc_const_stable(feature = "const_slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_slice_first_last_chunk", since = "1.83.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn first_chunk_mut(&mut self) -> Option<&mut [T; N]> { if self.len() < N { @@ -422,7 +422,7 @@ impl [T] { /// ``` #[inline] #[stable(feature = "slice_first_last_chunk", since = "1.77.0")] - #[rustc_const_stable(feature = "const_slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_slice_first_last_chunk", since = "1.83.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn split_first_chunk_mut( &mut self, @@ -493,7 +493,7 @@ impl [T] { /// ``` #[inline] #[stable(feature = "slice_first_last_chunk", since = "1.77.0")] - #[rustc_const_stable(feature = "const_slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_slice_first_last_chunk", since = "1.83.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn split_last_chunk_mut( &mut self, @@ -563,7 +563,7 @@ impl [T] { /// ``` #[inline] #[stable(feature = "slice_first_last_chunk", since = "1.77.0")] - #[rustc_const_stable(feature = "const_slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_slice_first_last_chunk", since = "1.83.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn last_chunk_mut(&mut self) -> Option<&mut [T; N]> { if self.len() < N { @@ -1907,7 +1907,7 @@ impl [T] { #[inline] #[track_caller] #[must_use] - #[rustc_const_stable(feature = "const_slice_split_at_mut", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_slice_split_at_mut", since = "1.83.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) { match self.split_at_mut_checked(mid) { @@ -2010,7 +2010,7 @@ impl [T] { /// assert_eq!(v, [1, 2, 3, 4, 5, 6]); /// ``` #[stable(feature = "slice_split_at_unchecked", since = "1.79.0")] - #[rustc_const_stable(feature = "const_slice_split_at_mut", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_slice_split_at_mut", since = "1.83.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[inline] #[must_use] @@ -2111,7 +2111,7 @@ impl [T] { /// assert_eq!(None, v.split_at_mut_checked(7)); /// ``` #[stable(feature = "split_at_checked", since = "1.80.0")] - #[rustc_const_stable(feature = "const_slice_split_at_mut", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_slice_split_at_mut", since = "1.83.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[inline] #[must_use] diff --git a/library/core/src/slice/raw.rs b/library/core/src/slice/raw.rs index 20c5e026946..976749cc148 100644 --- a/library/core/src/slice/raw.rs +++ b/library/core/src/slice/raw.rs @@ -171,7 +171,7 @@ pub const unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] /// [`NonNull::dangling()`]: ptr::NonNull::dangling #[inline] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_stable(feature = "const_slice_from_raw_parts_mut", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "const_slice_from_raw_parts_mut", since = "1.83.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[must_use] #[rustc_diagnostic_item = "slice_from_raw_parts_mut"] @@ -204,7 +204,7 @@ pub const fn from_ref(s: &T) -> &[T] { /// Converts a reference to T into a slice of length 1 (without copying). #[stable(feature = "from_ref", since = "1.28.0")] -#[rustc_const_stable(feature = "const_slice_from_ref", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "const_slice_from_ref", since = "1.83.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[must_use] pub const fn from_mut(s: &mut T) -> &mut [T] { diff --git a/library/core/src/str/converts.rs b/library/core/src/str/converts.rs index 194db56fdaf..b61ed454cd9 100644 --- a/library/core/src/str/converts.rs +++ b/library/core/src/str/converts.rs @@ -196,10 +196,7 @@ pub const unsafe fn from_utf8_unchecked(v: &[u8]) -> &str { #[must_use] #[stable(feature = "str_mut_extras", since = "1.20.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] -#[rustc_const_stable( - feature = "const_str_from_utf8_unchecked_mut", - since = "CURRENT_RUSTC_VERSION" -)] +#[rustc_const_stable(feature = "const_str_from_utf8_unchecked_mut", since = "1.83.0")] #[rustc_diagnostic_item = "str_from_utf8_unchecked_mut"] pub const unsafe fn from_utf8_unchecked_mut(v: &mut [u8]) -> &mut str { // SAFETY: the caller must guarantee that the bytes `v` diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index 1d10015d75a..09938dda262 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -340,7 +340,7 @@ impl str { /// ``` #[stable(feature = "str_mut_extras", since = "1.20.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] - #[rustc_const_stable(feature = "const_str_as_mut", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_str_as_mut", since = "1.83.0")] #[must_use] #[inline(always)] pub const unsafe fn as_bytes_mut(&mut self) -> &mut [u8] { @@ -387,7 +387,7 @@ impl str { /// modified in a way that it remains valid UTF-8. #[stable(feature = "str_as_mut_ptr", since = "1.36.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] - #[rustc_const_stable(feature = "const_str_as_mut", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_str_as_mut", since = "1.83.0")] #[rustc_never_returns_null_ptr] #[must_use] #[inline(always)] diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs index fc549abd433..3e795e7b5e3 100644 --- a/library/core/src/task/wake.rs +++ b/library/core/src/task/wake.rs @@ -519,8 +519,8 @@ impl Waker { /// [`Wake`]: ../../alloc/task/trait.Wake.html #[inline] #[must_use] - #[stable(feature = "waker_getters", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "waker_getters", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "waker_getters", since = "1.83.0")] + #[rustc_const_stable(feature = "waker_getters", since = "1.83.0")] pub const unsafe fn new(data: *const (), vtable: &'static RawWakerVTable) -> Self { Waker { waker: RawWaker { data, vtable } } } @@ -584,7 +584,7 @@ impl Waker { /// Gets the `data` pointer used to create this `Waker`. #[inline] #[must_use] - #[stable(feature = "waker_getters", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "waker_getters", since = "1.83.0")] pub fn data(&self) -> *const () { self.waker.data } @@ -592,7 +592,7 @@ impl Waker { /// Gets the `vtable` pointer used to create this `Waker`. #[inline] #[must_use] - #[stable(feature = "waker_getters", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "waker_getters", since = "1.83.0")] pub fn vtable(&self) -> &'static RawWakerVTable { self.waker.vtable } diff --git a/library/core/src/time.rs b/library/core/src/time.rs index 51005ff795c..5081e777af4 100644 --- a/library/core/src/time.rs +++ b/library/core/src/time.rs @@ -844,7 +844,7 @@ impl Duration { #[stable(feature = "duration_float", since = "1.38.0")] #[must_use] #[inline] - #[rustc_const_stable(feature = "duration_consts_float", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "duration_consts_float", since = "1.83.0")] pub const fn as_secs_f64(&self) -> f64 { (self.secs as f64) + (self.nanos.0 as f64) / (NANOS_PER_SEC as f64) } @@ -863,7 +863,7 @@ impl Duration { #[stable(feature = "duration_float", since = "1.38.0")] #[must_use] #[inline] - #[rustc_const_stable(feature = "duration_consts_float", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "duration_consts_float", since = "1.83.0")] pub const fn as_secs_f32(&self) -> f32 { (self.secs as f32) + (self.nanos.0 as f32) / (NANOS_PER_SEC as f32) } @@ -1084,7 +1084,7 @@ impl Duration { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - #[rustc_const_stable(feature = "duration_consts_float", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "duration_consts_float", since = "1.83.0")] pub const fn div_duration_f64(self, rhs: Duration) -> f64 { let self_nanos = (self.secs as f64) * (NANOS_PER_SEC as f64) + (self.nanos.0 as f64); let rhs_nanos = (rhs.secs as f64) * (NANOS_PER_SEC as f64) + (rhs.nanos.0 as f64); @@ -1105,7 +1105,7 @@ impl Duration { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - #[rustc_const_stable(feature = "duration_consts_float", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "duration_consts_float", since = "1.83.0")] pub const fn div_duration_f32(self, rhs: Duration) -> f32 { let self_nanos = (self.secs as f32) * (NANOS_PER_SEC as f32) + (self.nanos.0 as f32); let rhs_nanos = (rhs.secs as f32) * (NANOS_PER_SEC as f32) + (rhs.nanos.0 as f32); diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index f2e523dca77..ded4f404d78 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -1438,7 +1438,7 @@ impl Clone for Iter<'_, K, V> { } } -#[stable(feature = "default_iters_hash", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "default_iters_hash", since = "1.83.0")] impl Default for Iter<'_, K, V> { #[inline] fn default() -> Self { @@ -1484,7 +1484,7 @@ impl<'a, K, V> IterMut<'a, K, V> { } } -#[stable(feature = "default_iters_hash", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "default_iters_hash", since = "1.83.0")] impl Default for IterMut<'_, K, V> { #[inline] fn default() -> Self { @@ -1522,7 +1522,7 @@ impl IntoIter { } } -#[stable(feature = "default_iters_hash", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "default_iters_hash", since = "1.83.0")] impl Default for IntoIter { #[inline] fn default() -> Self { @@ -1562,7 +1562,7 @@ impl Clone for Keys<'_, K, V> { } } -#[stable(feature = "default_iters_hash", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "default_iters_hash", since = "1.83.0")] impl Default for Keys<'_, K, V> { #[inline] fn default() -> Self { @@ -1609,7 +1609,7 @@ impl Clone for Values<'_, K, V> { } } -#[stable(feature = "default_iters_hash", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "default_iters_hash", since = "1.83.0")] impl Default for Values<'_, K, V> { #[inline] fn default() -> Self { @@ -1705,7 +1705,7 @@ pub struct ValuesMut<'a, K: 'a, V: 'a> { inner: IterMut<'a, K, V>, } -#[stable(feature = "default_iters_hash", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "default_iters_hash", since = "1.83.0")] impl Default for ValuesMut<'_, K, V> { #[inline] fn default() -> Self { @@ -1735,7 +1735,7 @@ pub struct IntoKeys { inner: IntoIter, } -#[stable(feature = "default_iters_hash", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "default_iters_hash", since = "1.83.0")] impl Default for IntoKeys { #[inline] fn default() -> Self { @@ -1765,7 +1765,7 @@ pub struct IntoValues { inner: IntoIter, } -#[stable(feature = "default_iters_hash", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "default_iters_hash", since = "1.83.0")] impl Default for IntoValues { #[inline] fn default() -> Self { @@ -2865,7 +2865,7 @@ impl<'a, K, V> Entry<'a, K, V> { /// assert_eq!(entry.key(), &"poneyland"); /// ``` #[inline] - #[stable(feature = "entry_insert", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "entry_insert", since = "1.83.0")] pub fn insert_entry(self, value: V) -> OccupiedEntry<'a, K, V> { match self { Occupied(mut entry) => { @@ -3152,7 +3152,7 @@ impl<'a, K: 'a, V: 'a> VacantEntry<'a, K, V> { /// assert_eq!(map["poneyland"], 37); /// ``` #[inline] - #[stable(feature = "entry_insert", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "entry_insert", since = "1.83.0")] pub fn insert_entry(self, value: V) -> OccupiedEntry<'a, K, V> { let base = self.base.insert_entry(value); OccupiedEntry { base } diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs index 210f5715225..e1e0eb36d23 100644 --- a/library/std/src/collections/hash/set.rs +++ b/library/std/src/collections/hash/set.rs @@ -1244,7 +1244,7 @@ pub struct Iter<'a, K: 'a> { base: base::Iter<'a, K>, } -#[stable(feature = "default_iters_hash", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "default_iters_hash", since = "1.83.0")] impl Default for Iter<'_, K> { #[inline] fn default() -> Self { @@ -1273,7 +1273,7 @@ pub struct IntoIter { base: base::IntoIter, } -#[stable(feature = "default_iters_hash", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "default_iters_hash", since = "1.83.0")] impl Default for IntoIter { #[inline] fn default() -> Self { diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs index f20814dd95c..adf103e9430 100644 --- a/library/std/src/io/error.rs +++ b/library/std/src/io/error.rs @@ -223,10 +223,10 @@ pub enum ErrorKind { #[stable(feature = "rust1", since = "1.0.0")] ConnectionReset, /// The remote host is not reachable. - #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] HostUnreachable, /// The network containing the remote host is not reachable. - #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] NetworkUnreachable, /// The connection was aborted (terminated) by the remote server. #[stable(feature = "rust1", since = "1.0.0")] @@ -243,7 +243,7 @@ pub enum ErrorKind { #[stable(feature = "rust1", since = "1.0.0")] AddrNotAvailable, /// The system's networking is down. - #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] NetworkDown, /// The operation failed because a pipe was closed. #[stable(feature = "rust1", since = "1.0.0")] @@ -259,18 +259,18 @@ pub enum ErrorKind { /// /// For example, a filesystem path was specified where one of the intermediate directory /// components was, in fact, a plain file. - #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] NotADirectory, /// The filesystem object is, unexpectedly, a directory. /// /// A directory was specified when a non-directory was expected. - #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] IsADirectory, /// A non-empty directory was specified where an empty directory was expected. - #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] DirectoryNotEmpty, /// The filesystem or storage medium is read-only, but a write operation was attempted. - #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] ReadOnlyFilesystem, /// Loop in the filesystem or IO subsystem; often, too many levels of symbolic links. /// @@ -285,7 +285,7 @@ pub enum ErrorKind { /// /// With some network filesystems, notably NFS, an open file (or directory) can be invalidated /// by problems with the network or server. - #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] StaleNetworkFileHandle, /// A parameter was incorrect. #[stable(feature = "rust1", since = "1.0.0")] @@ -319,13 +319,13 @@ pub enum ErrorKind { /// The underlying storage (typically, a filesystem) is full. /// /// This does not include out of quota errors. - #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] StorageFull, /// Seek on unseekable file. /// /// Seeking was attempted on an open file handle which is not suitable for seeking - for /// example, on Unix, a named pipe opened with `File::open`. - #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] NotSeekable, /// Filesystem quota was exceeded. #[unstable(feature = "io_error_more", issue = "86442")] @@ -335,22 +335,22 @@ pub enum ErrorKind { /// This might arise from a hard limit of the underlying filesystem or file access API, or from /// an administratively imposed resource limitation. Simple disk full, and out of quota, have /// their own errors. - #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] FileTooLarge, /// Resource is busy. - #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] ResourceBusy, /// Executable file is busy. /// /// An attempt was made to write to a file which is also in use as a running program. (Not all /// operating systems detect this situation.) - #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] ExecutableFileBusy, /// Deadlock (avoided). /// /// A file locking operation would result in deadlock. This situation is typically detected, if /// at all, on a best-effort basis. - #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] Deadlock, /// Cross-device or cross-filesystem (hard) link or rename. #[unstable(feature = "io_error_more", issue = "86442")] @@ -358,7 +358,7 @@ pub enum ErrorKind { /// Too many (hard) links to the same filesystem object. /// /// The filesystem does not support making so many hardlinks to the same file. - #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] TooManyLinks, /// A filename was invalid. /// @@ -369,7 +369,7 @@ pub enum ErrorKind { /// /// When trying to run an external program, a system or process limit on the size of the /// arguments would have been exceeded. - #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] ArgumentListTooLong, /// This operation was interrupted. /// diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 8fedcb241d0..71dfd0676c9 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -2405,7 +2405,7 @@ pub trait BufRead: Read { /// assert_eq!(num_bytes, 11); /// assert_eq!(animal, b"Crustacean\0"); /// ``` - #[stable(feature = "bufread_skip_until", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "bufread_skip_until", since = "1.83.0")] fn skip_until(&mut self, byte: u8) -> Result { skip_until(self, byte) } From 6134f9f636422abeda9fbc1563f6aa9a5b0b3fdf Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Tue, 15 Oct 2024 20:13:29 -0700 Subject: [PATCH 342/357] bump stage0 to 1.83.0-beta.1 --- src/stage0 | 900 ++++++++++++++++++++++++++--------------------------- 1 file changed, 450 insertions(+), 450 deletions(-) diff --git a/src/stage0 b/src/stage0 index 0d6542d2dd7..57a01edb6fd 100644 --- a/src/stage0 +++ b/src/stage0 @@ -14,456 +14,456 @@ nightly_branch=master # All changes below this comment will be overridden the next time the # tool is executed. -compiler_date=2024-09-22 +compiler_date=2024-10-16 compiler_version=beta -rustfmt_date=2024-09-22 +rustfmt_date=2024-10-16 rustfmt_version=nightly -dist/2024-09-22/rustc-beta-aarch64-apple-darwin.tar.gz=59b70ccc04680e74bbd1e13368bbf5639679fb8e1e7ba39ae4a235f9a96522f6 -dist/2024-09-22/rustc-beta-aarch64-apple-darwin.tar.xz=d4b18e0a269e7b66dbbdf03d7da6b478c6cff9cd52ef34f110b68a9ff0111d0f -dist/2024-09-22/rustc-beta-aarch64-pc-windows-msvc.tar.gz=7cc2e8511801c27360e17cc0380e30e5eb6cc185224aba94bf9ed852e5ff2ce0 -dist/2024-09-22/rustc-beta-aarch64-pc-windows-msvc.tar.xz=a9f8f8e691b9a307ddc4468cc34964063253292f18869d21dc91ca437bbc08fd -dist/2024-09-22/rustc-beta-aarch64-unknown-linux-gnu.tar.gz=5940e8c99d329fae3cc4b1d5709e9481e8f2b1dc799363ae0a1429ea4df4ad41 -dist/2024-09-22/rustc-beta-aarch64-unknown-linux-gnu.tar.xz=c7c36aada972ea10e50e0904530d06b2df074f9981dec4dcc66efeaa16499c1b -dist/2024-09-22/rustc-beta-aarch64-unknown-linux-musl.tar.gz=2ae2b1e2d90c130be5274806db1e4dcdfe0b588fe72f967e58b128aa1d28a7eb -dist/2024-09-22/rustc-beta-aarch64-unknown-linux-musl.tar.xz=d8297b214d4ef841bb5963e71353ce08a4d3aead47a2cdf234e0846ad0b1ccbb -dist/2024-09-22/rustc-beta-arm-unknown-linux-gnueabi.tar.gz=256b62cd5f1bc17c081277752a49d38104ce438e83342e6bbb467442e9250563 -dist/2024-09-22/rustc-beta-arm-unknown-linux-gnueabi.tar.xz=457ea31587b8ff8c9fcc7a9ed4bf958625c7b9e55d640329ccdf432309a6583f -dist/2024-09-22/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz=4cc8f851eff833100fe4d7c421c25e65d4779d8cdbb9b5e2cb3c8f5ebf9f8e98 -dist/2024-09-22/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz=6ab386aaab687a253b3d28b12307ad5c8df2ea1a0af281a8fab6fe6d24ee6130 -dist/2024-09-22/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz=0b548c45c2ec840942b29a68ad38debd8a2ec7c920d3be7cda91365e0a8fce80 -dist/2024-09-22/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz=bc1ce3524199c62230fc08b9dab1282d2f31d3cd1a892cbc8bfab0257e0ff5dc -dist/2024-09-22/rustc-beta-i686-pc-windows-gnu.tar.gz=a407a4dda4c24e8e9d510843aa9e8f06291622d240538a14c1d924d8b7d84e33 -dist/2024-09-22/rustc-beta-i686-pc-windows-gnu.tar.xz=fe3b235ed043d14856f47babf433ae214d9b64480b1824053fee8b99ca69cc69 -dist/2024-09-22/rustc-beta-i686-pc-windows-msvc.tar.gz=a156aa0fb17b5edf476f97b8e839f9fe550ed3edd63a2fe2936a7fe0f388ece4 -dist/2024-09-22/rustc-beta-i686-pc-windows-msvc.tar.xz=0e46e75722b10bbbd2631c2676089665f92ce092408ed63aa14c99b1fc385369 -dist/2024-09-22/rustc-beta-i686-unknown-linux-gnu.tar.gz=5523e67362db0840d6f0ab6a1deec99c1b64c32fae94362792b0aa031bfd39d6 -dist/2024-09-22/rustc-beta-i686-unknown-linux-gnu.tar.xz=45a820f2ebd182ec3237436a567960d2bd0f92e9e603aa394b1a6eafbd9ba0fa -dist/2024-09-22/rustc-beta-loongarch64-unknown-linux-gnu.tar.gz=bdbe165ffd50974b32f4b570da7908c125739c0321f700d12cc481f32ab76eaa -dist/2024-09-22/rustc-beta-loongarch64-unknown-linux-gnu.tar.xz=997a8387989676848355e30dea1b131fa96945e62cef8f011025c52351db1269 -dist/2024-09-22/rustc-beta-loongarch64-unknown-linux-musl.tar.gz=a49f46df49a9aa974ff10361ae29267d2c86c10486399803a5a6879e638212f2 -dist/2024-09-22/rustc-beta-loongarch64-unknown-linux-musl.tar.xz=ee236f4dab4a06d23b6040a47afdf73496bc9093b3b29fae896f5f5bbe87c222 -dist/2024-09-22/rustc-beta-powerpc-unknown-linux-gnu.tar.gz=e83c1253643c4ff70301bab198db731ac65c6d3b0ec847d7aa68bd6afef6ee93 -dist/2024-09-22/rustc-beta-powerpc-unknown-linux-gnu.tar.xz=f7f09a5028ca3f45475cedec7518ead06b2e305554292462d82b2032e5d83f73 -dist/2024-09-22/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz=9ef2829f5b2bc9666bba319875eecbda37840d204f7c1493dce2a4f2f45d45c5 -dist/2024-09-22/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz=140489beedcf46e02931ce8f69e9008ea4c7e3c332d0a3482d4495d7fff21b81 -dist/2024-09-22/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz=63a34f34425d6c11d62768a3cdfc4602d96ae0f11d82344412a69a3b1ec550b9 -dist/2024-09-22/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz=108d429397a5cef93151439646b684109d1b619c1a6f11544062e407258f4897 -dist/2024-09-22/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz=77cb4dea8b55779e0f3de1f48e74de966d3a2dc27946228b42b0eae654d53e5a -dist/2024-09-22/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz=93b7dc39c3da7560cbabef5a35dddec111a4d9c0ec0e2b0648925975c5042b31 -dist/2024-09-22/rustc-beta-s390x-unknown-linux-gnu.tar.gz=58b1eed6046552703f8993b36d2a571d12db806ca9665d276c338fc89f79b980 -dist/2024-09-22/rustc-beta-s390x-unknown-linux-gnu.tar.xz=39ad5c20dd703e5949f008ed21e671b1438a1160b4aece5ba434ae03f32004cf -dist/2024-09-22/rustc-beta-x86_64-apple-darwin.tar.gz=c5082f7773f1573a1f60148ed744f148169b3c58ca38539e72688cb31221003e -dist/2024-09-22/rustc-beta-x86_64-apple-darwin.tar.xz=a797564192dc84184d5af88ecb4d295ab266cde4a1c4407b06c56f656800e336 -dist/2024-09-22/rustc-beta-x86_64-pc-windows-gnu.tar.gz=0f29dc08756a36f42e9937cf9e2f8c5cc7771fab5b791b58dd7b038dcb20e2ca -dist/2024-09-22/rustc-beta-x86_64-pc-windows-gnu.tar.xz=9a9f6178208f01487a132ab91ffb1251722df3f6e3ccc7f4b3e79dc389b7217a -dist/2024-09-22/rustc-beta-x86_64-pc-windows-msvc.tar.gz=2f2b828b46dea57c9896149a5ffc5cc6db368d90067c498f554b9ea75de0990f -dist/2024-09-22/rustc-beta-x86_64-pc-windows-msvc.tar.xz=42c64410633bf748134ba004ef397f2319556e44fc2862a4f3a5e847e334fdbf -dist/2024-09-22/rustc-beta-x86_64-unknown-freebsd.tar.gz=9ba0fdecbd343606bbdf2d4b401d64ed5de82e4bd508c0e6b6bcc21365c4b840 -dist/2024-09-22/rustc-beta-x86_64-unknown-freebsd.tar.xz=aeabedce922b315fb872127a6102a76e9fe5e1932b14a7210f31191f9a85488b -dist/2024-09-22/rustc-beta-x86_64-unknown-illumos.tar.gz=4d5348b0ef100a1691f655acee54447866d76b46f88e23ee641eb5e4b4318b4c -dist/2024-09-22/rustc-beta-x86_64-unknown-illumos.tar.xz=046b8d0139b97d78a741251ef7094629394f67cbb817a7239de704b4ff3a8963 -dist/2024-09-22/rustc-beta-x86_64-unknown-linux-gnu.tar.gz=81ba8a28534746a9c33c98a98aeeea89f6c057333827d919b2f404991e0ded45 -dist/2024-09-22/rustc-beta-x86_64-unknown-linux-gnu.tar.xz=358bbda124aa68416d55d8ed6c9a184f8ea7ae166f3f0427e8c9ac40900bd4b6 -dist/2024-09-22/rustc-beta-x86_64-unknown-linux-musl.tar.gz=8594ed15236342879b4c486e4d5e2440891e9dec52302e1bb6393008eaf876e7 -dist/2024-09-22/rustc-beta-x86_64-unknown-linux-musl.tar.xz=e45cdb771899998e42bf3f9e965a4b4557199b1632843c0472731d48ea664834 -dist/2024-09-22/rustc-beta-x86_64-unknown-netbsd.tar.gz=ba1d8b89c65441cfe6fa1341c6a7e21dc596df13cef8e8038d8d7ac376bd91fc -dist/2024-09-22/rustc-beta-x86_64-unknown-netbsd.tar.xz=95fb21a9730eaf815ba6da5f42b997accca0b578870207912a2ea359b588421e -dist/2024-09-22/rust-std-beta-aarch64-apple-darwin.tar.gz=60127b21a176a56664e537a8e6d81c18c5406706f12e3a406ebad8c86f5fc442 -dist/2024-09-22/rust-std-beta-aarch64-apple-darwin.tar.xz=04d163b5bb40aa4ed7e712006155549eb5ca094e71b89b4a3e5142c40d0b2102 -dist/2024-09-22/rust-std-beta-aarch64-apple-ios.tar.gz=1463a6f3a55b1c7795c0417040423f2dc1d9a3df343ee4bd2d9c96b2de5c84e8 -dist/2024-09-22/rust-std-beta-aarch64-apple-ios.tar.xz=74a06570dd6bd8b501ccdcdf25b9b5ccac25936b883b37be6a0296d5e59394b6 -dist/2024-09-22/rust-std-beta-aarch64-apple-ios-macabi.tar.gz=ccdf0df40f435ca4c5f8d6b67cf06b48c1792d5b1592cb129e7e40e7690c3c5b -dist/2024-09-22/rust-std-beta-aarch64-apple-ios-macabi.tar.xz=4388b9b3ab0e048b6c8349a3ceae6afc078bdc217172d7ef0271afb5e181fb6f -dist/2024-09-22/rust-std-beta-aarch64-apple-ios-sim.tar.gz=4428d02fe8e43b5d082149991e88a4c9d342157fa1c2cd91903812240fb5bb08 -dist/2024-09-22/rust-std-beta-aarch64-apple-ios-sim.tar.xz=21f9c521dc8203584ce0c56536818431ec19f259f86b8d8cab5a33f7e44165cf -dist/2024-09-22/rust-std-beta-aarch64-linux-android.tar.gz=d9d238db60d1e54366cfb4f20e2a6c6b8bc055f83716837970261b074cc93218 -dist/2024-09-22/rust-std-beta-aarch64-linux-android.tar.xz=aab44af6a7f1dc483c943be9fd0b2ade0c938a844acc8deab76843e3dc514355 -dist/2024-09-22/rust-std-beta-aarch64-pc-windows-gnullvm.tar.gz=fccf8f5199da8c0fe2d1dec6ee384c9761f2e6334e5dce28add413f29207e902 -dist/2024-09-22/rust-std-beta-aarch64-pc-windows-gnullvm.tar.xz=d6373d38a862120c08afa569ea9941945b43ce1676f45ca995fb3b30c34500ec -dist/2024-09-22/rust-std-beta-aarch64-pc-windows-msvc.tar.gz=e0b31c36068626fbf2133a352002cbd8f4c2b6a1b5379a0ab0fd3bc640576e9d -dist/2024-09-22/rust-std-beta-aarch64-pc-windows-msvc.tar.xz=d10defe0175f8872ebb68d2dd331fa9bbbeb1fa892188371665547567f7f2738 -dist/2024-09-22/rust-std-beta-aarch64-unknown-fuchsia.tar.gz=dda6f7b74035c963dd89a2e003d6c7baca2e2db9bfdd3007f95743e44bd08cb0 -dist/2024-09-22/rust-std-beta-aarch64-unknown-fuchsia.tar.xz=23944ba7752e89e860f19f3c18d2951bb5c7c6b707bd6e06914f7d48aafee40c -dist/2024-09-22/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz=b00fa5fea66b2af7d173d6405a59c529a1dd0b793d735c2d97fcab7775693ed4 -dist/2024-09-22/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz=34bd748cc5bc0a6b6d8e6d8ea23693d7628bed11ebcd886860cd5c0b31ac3c0d -dist/2024-09-22/rust-std-beta-aarch64-unknown-linux-musl.tar.gz=ecb1b709c48556fabc527d976e6cc69b8b69384cb4c45e691195a12b9cdba383 -dist/2024-09-22/rust-std-beta-aarch64-unknown-linux-musl.tar.xz=2c90df930935dcf9f9725588ed6579100fdf676267305f715f03e413a04c3032 -dist/2024-09-22/rust-std-beta-aarch64-unknown-linux-ohos.tar.gz=56782db097cca16a0d6e8466b83b35bfd7334d5f48b9ac5c500767eeba30c122 -dist/2024-09-22/rust-std-beta-aarch64-unknown-linux-ohos.tar.xz=9b41b551b5f88dfa3fdcc1d22102f102627c5c88e42353edaceda6da3b76d97b -dist/2024-09-22/rust-std-beta-aarch64-unknown-none.tar.gz=087fccd0b40fe73a545885a58758eafb86e9bb7b9588d047c9536e5bd8c201b6 -dist/2024-09-22/rust-std-beta-aarch64-unknown-none.tar.xz=60039451dc07ada83944606e67363ca32b22879293bc41a6d66f6545e7e3f1aa -dist/2024-09-22/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz=0e1f73720beaecff935d0a90272448f5dfb0c912b2e366239c46c6ab3b854cfc -dist/2024-09-22/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz=c2670b262833415d43b22485c2734d87d8748315e6471a2a384249b2cba6e581 -dist/2024-09-22/rust-std-beta-aarch64-unknown-uefi.tar.gz=edfd391f36b6aa6758649ca6f9706d671956f078e572ea9ce5f9423a1310e817 -dist/2024-09-22/rust-std-beta-aarch64-unknown-uefi.tar.xz=59b09f6cef1d97b273262d3ccdd95d9c46766b82e935cb46538514292cd04a39 -dist/2024-09-22/rust-std-beta-arm-linux-androideabi.tar.gz=f84267d71217b79a5e622a281ce926c1a54ee9122e19b2647d1aa85afa9132be -dist/2024-09-22/rust-std-beta-arm-linux-androideabi.tar.xz=57e80fea8463416012339fc6f74e9ae4da7d92042d05311bc8a9620fec3541b2 -dist/2024-09-22/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz=556ff5b6947ed37f5215953fbcbe3e82313e7deb9d32d5b86feabe46c8328e56 -dist/2024-09-22/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz=3f0721bc56fa232ca4203dcb43f1ef8f453373d9a0fa4720d89c51b827407a91 -dist/2024-09-22/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz=57b81555f7d7695e985e1538795c97b9f0573cd84d6fda25a09d49ac54bd1a24 -dist/2024-09-22/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz=66d5af25be1dfc99fbeb1aa0c7eee30dc2d3e5766affb73e6e7c0e7b9a78abff -dist/2024-09-22/rust-std-beta-arm-unknown-linux-musleabi.tar.gz=23cfcb1cde1e95f55442ebb8ba155a0e13ec932cd7a8ab20a2ad09596a79b3a4 -dist/2024-09-22/rust-std-beta-arm-unknown-linux-musleabi.tar.xz=660d3f7b05da3d5b01775989546a687fe40090d193289c3ad24317c07c5eb445 -dist/2024-09-22/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz=ee453c78eacca64fd0a6f1c066a6728ddca0ecbd6e184b63a4b4455f77183f07 -dist/2024-09-22/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz=b003790997ebe0bfa095b0fe38db67db179a2f9e93f4b49852f5ec04828337f4 -dist/2024-09-22/rust-std-beta-arm64ec-pc-windows-msvc.tar.gz=60f03912a464169464800a603606e2cb8a302c998bd59f582cdd3b9bf39ecc82 -dist/2024-09-22/rust-std-beta-arm64ec-pc-windows-msvc.tar.xz=6d1858acf2f2cfb3daac89ae21cfc7a7df3e1f57dac0aaa3ee70057b1974c0f2 -dist/2024-09-22/rust-std-beta-armebv7r-none-eabi.tar.gz=b23fd4380d20e289e58b86afaad1df0636004c74a03d7f3ff861f26c6ca308f8 -dist/2024-09-22/rust-std-beta-armebv7r-none-eabi.tar.xz=beac209cec83a56315c109fc3a0e3b6b16f8044de270e23cdd9dc3e2b5db3af3 -dist/2024-09-22/rust-std-beta-armebv7r-none-eabihf.tar.gz=731064c4b9b35d420f740ff5fbc4f6dd1f038e3225db19ca861af6db5f283ea7 -dist/2024-09-22/rust-std-beta-armebv7r-none-eabihf.tar.xz=04b406b44da8aee6a077f9f971b5ba62bc98fb09413fe47fd892c67798381d5b -dist/2024-09-22/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz=26dc6030f28453478e790879547f22a63ae810572cac790d4ed944eb68c96d87 -dist/2024-09-22/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz=2aa9589c9512388e75c3c93e53b6a90ce5c973d98830a64388b0ec22618504c5 -dist/2024-09-22/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz=0020c2142cef0ab6bd62c4212f01dce2675104e0da5e701cbf03ee7c45a0fb2c -dist/2024-09-22/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz=b891ccdcbd8abf7d56d31b84800a17cbe1f6d4242584598433e38eff5a9a16c0 -dist/2024-09-22/rust-std-beta-armv7-linux-androideabi.tar.gz=128b86795a07b47088fbc51a251f6b112379454940878150547b54ffb95890e9 -dist/2024-09-22/rust-std-beta-armv7-linux-androideabi.tar.xz=26497ef07fb7f42198b4fc02b122497fc09bd215eb7e3e01c789b481bd2d86ae -dist/2024-09-22/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz=933f22ab901b9de042b17548e0218de699275a8553b8056d2d85430858f4e1bc -dist/2024-09-22/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz=495f8186e0c589882d1e1f1cf21ab28ea5531bad327b6d5ae1ca83d26c77944e -dist/2024-09-22/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz=53c87859857618a011e94c14c5641927503c5543831acd16498d7fb244eb00b8 -dist/2024-09-22/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz=7ee039186087e320396e56cdd9e5a6b7993c44783e3a80fd86e74e41be646a57 -dist/2024-09-22/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz=fa9f256a201c4fe5cd95363c2cb02d87565a321e27554e83d63f1d61ed55dfda -dist/2024-09-22/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz=fd3eced91b52924bb6d4acb3cc6c3bd7b45a1879e353f22442cb1e76ed5a7f28 -dist/2024-09-22/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz=b683d929fd6a6b60a786ec154970338158cc2b7bce28601b70966b898017b131 -dist/2024-09-22/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz=518fa28ee0292b95322bea4c0b714146a1b94c730e49bb6a84038520c91a668b -dist/2024-09-22/rust-std-beta-armv7-unknown-linux-ohos.tar.gz=d0f8659cddfc6da0b0dd815794f86ec1ffa0a243020dc9190c4358c6cdc03fdf -dist/2024-09-22/rust-std-beta-armv7-unknown-linux-ohos.tar.xz=89f39595aa42f23efa2b3853c466cddd6a932043bae3373193c25b788c15efd6 -dist/2024-09-22/rust-std-beta-armv7a-none-eabi.tar.gz=c1fc1973cc683c313e50542f1a6b69f1b5a5b4ac558b45954f79ef4dff9d5f75 -dist/2024-09-22/rust-std-beta-armv7a-none-eabi.tar.xz=00c45dfc370ea40d8993519bdb5cce8f5167401434f0b7553b6fdf7c5b49da87 -dist/2024-09-22/rust-std-beta-armv7r-none-eabi.tar.gz=ef54f8762f1d190b822e58b845889ac9c2dba4250cf0d693a3b1cbf64e2cf8a2 -dist/2024-09-22/rust-std-beta-armv7r-none-eabi.tar.xz=9375a15e96f7b3da4394bcda8ce34c452417f4278f07926830d5b00b155cb338 -dist/2024-09-22/rust-std-beta-armv7r-none-eabihf.tar.gz=85a5ae26f11c47872649699eaf01557aac746831b4c30de7b892438cc736b679 -dist/2024-09-22/rust-std-beta-armv7r-none-eabihf.tar.xz=e9dde209b4e0de6ae76b316c5e3aa2923f208bd9aa7858fef5177ba2e3b06119 -dist/2024-09-22/rust-std-beta-i586-pc-windows-msvc.tar.gz=652bc4cbf176d0780a81cff637684fd8f1cdc99c7a58d68325f54564942d46dc -dist/2024-09-22/rust-std-beta-i586-pc-windows-msvc.tar.xz=367eca53e9c4be297454751d2d8b7f5503caf669962a44ea92290b0772969fb6 -dist/2024-09-22/rust-std-beta-i586-unknown-linux-gnu.tar.gz=7c48fb48b02628358ae3572c92d5cc112734e99606c78d04b29e665ee03f36ec -dist/2024-09-22/rust-std-beta-i586-unknown-linux-gnu.tar.xz=4ac829df3b8b5e7864b883713a90ed18a9b08f45a3da2af2c6b3f700c8d7c27c -dist/2024-09-22/rust-std-beta-i586-unknown-linux-musl.tar.gz=7786d5b5e0cb8489df5456854cbbdfefbb8b4a3755f61e62747abc224e48dfc6 -dist/2024-09-22/rust-std-beta-i586-unknown-linux-musl.tar.xz=e2ec9458a99a159480a45b8107041b3b4054316ba15adaf802690d2bf66b2f22 -dist/2024-09-22/rust-std-beta-i686-linux-android.tar.gz=54edc2ca229e1a5aad5077800c492cf5038da341555eda11fc4b77d1a3896def -dist/2024-09-22/rust-std-beta-i686-linux-android.tar.xz=a75135f1e04b716855fce5b830797ea87bd428d54c06190cc8067ba5952d7215 -dist/2024-09-22/rust-std-beta-i686-pc-windows-gnu.tar.gz=4c5b54eecd6efbb03a3a01f57c265d47c49df49dd584e67b493205fcec92a59b -dist/2024-09-22/rust-std-beta-i686-pc-windows-gnu.tar.xz=7ec6292ac497b450277c17cca3ca87321d5b6bd545bd479b37698ceebdcbf719 -dist/2024-09-22/rust-std-beta-i686-pc-windows-gnullvm.tar.gz=0deb2de1b9830099bb6de1bb99e4658c8e4e3438e555f239c85309b771293e6b -dist/2024-09-22/rust-std-beta-i686-pc-windows-gnullvm.tar.xz=f35566df72b302dd446d449ffc8a775015b30970911c5284a3d4c1866e004a6b -dist/2024-09-22/rust-std-beta-i686-pc-windows-msvc.tar.gz=17e505c8ece5c89988896b1c14400b203e2588bc7777189bef89335cc868fb1d -dist/2024-09-22/rust-std-beta-i686-pc-windows-msvc.tar.xz=197fe430d6fce984ca397ba664beb25d4a0216180cd8fc2797710a8c541573a8 -dist/2024-09-22/rust-std-beta-i686-unknown-freebsd.tar.gz=9d7ff528d75e80ebb8255c9b6ef3f5ec6db579524e03dc3aad540690401fb7b8 -dist/2024-09-22/rust-std-beta-i686-unknown-freebsd.tar.xz=81152e616efe27a4ae80d2ffc86b79211c31ab324faa7847606f6ed839a3d470 -dist/2024-09-22/rust-std-beta-i686-unknown-linux-gnu.tar.gz=b1913a26f2258531596e1ef31fc42d720f807f04b068802ea3a0164d877d694c -dist/2024-09-22/rust-std-beta-i686-unknown-linux-gnu.tar.xz=3be89fd0c0f0a5b6d5cea23feffd32573be29ec1ce6c96b88ac35e04cf1eaa46 -dist/2024-09-22/rust-std-beta-i686-unknown-linux-musl.tar.gz=e446e4cbb904f89fbaf7bd48be6975671db2cc2ad018fc03e967dff2bbce0e3d -dist/2024-09-22/rust-std-beta-i686-unknown-linux-musl.tar.xz=453d6a6b1872e884aeae40936e950b7c2d0ce291c9f5882fc9c15a6b3e9c86fe -dist/2024-09-22/rust-std-beta-i686-unknown-uefi.tar.gz=a330462d4b0ade7028d2c2bd8764b1225cc9eac90b014c8899f971fadf002cba -dist/2024-09-22/rust-std-beta-i686-unknown-uefi.tar.xz=8fdb9e12d0cf92e0c4fcbcdc57daceb2cf17b21786e1252904ec0faba4b90a9d -dist/2024-09-22/rust-std-beta-loongarch64-unknown-linux-gnu.tar.gz=82859d2feb163fa7ac068db184e8c76261771dc47838bd952301ffd8037d885a -dist/2024-09-22/rust-std-beta-loongarch64-unknown-linux-gnu.tar.xz=1fa1ae996cd7010b4ab9006bfcb69098fcadbfc7a8f6988bdd34c62d2d6309f3 -dist/2024-09-22/rust-std-beta-loongarch64-unknown-linux-musl.tar.gz=e4200a2c1eb5a1420071fde891266849da5d46aaf46031129ae329175a3708f8 -dist/2024-09-22/rust-std-beta-loongarch64-unknown-linux-musl.tar.xz=15fc279f0c1370d05543af48c493d91687e3de2dc25123a1b657919494a0653c -dist/2024-09-22/rust-std-beta-loongarch64-unknown-none.tar.gz=4cc49f8231bca8c19e4d449cf3b3cd84d5db9e4665394ebada29ea626cee4dc4 -dist/2024-09-22/rust-std-beta-loongarch64-unknown-none.tar.xz=b3b7959a696c75575edb3676520f64178151df1d523128c6ed6e28cd0c8051b9 -dist/2024-09-22/rust-std-beta-loongarch64-unknown-none-softfloat.tar.gz=7b15fd753967116653b4372e10796ae2ea35910872f517a2d1c6dd3539717915 -dist/2024-09-22/rust-std-beta-loongarch64-unknown-none-softfloat.tar.xz=87f88922e5c3a17af392bade5af1ce94f03aac275e6ed3dbadc9d6c720223c7f -dist/2024-09-22/rust-std-beta-nvptx64-nvidia-cuda.tar.gz=f1d4f6887d12f1316bcf515bd07f9474bb9e036dfe78171720d72e98de580791 -dist/2024-09-22/rust-std-beta-nvptx64-nvidia-cuda.tar.xz=2dcaa78854d5b619e9609db70fa805cdf1e5baf2fac35f3eefb66ae854e78891 -dist/2024-09-22/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz=c4ae30e180d94550da74b09f6005a6224136d8b5d752e9cdb1b44081a95b8c9f -dist/2024-09-22/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz=c6438a341e8008b3c475e3250d52df2cb0a505862a14ed70e89884086a56e54f -dist/2024-09-22/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz=8ff723f008f1ff81541f2f14d68ad1e77a2842577dcbe4f5109f6c54fdc42726 -dist/2024-09-22/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz=c5704ef9d690721790d127ca341e4747d572bd34f636894fe897d23660a11467 -dist/2024-09-22/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz=13d46982612f710d7aacf1a9636502418fdc673dde21641e1c52d2c55c8c35a1 -dist/2024-09-22/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz=9e33e5c0ffd8511705258a741b448e167fdb13229d1d8bb36ef0b41a1f9c49ec -dist/2024-09-22/rust-std-beta-riscv32i-unknown-none-elf.tar.gz=f7e0cc15730cfcd05ac904a3fb6012a99310c15402db19e915860fc4bc1f55ce -dist/2024-09-22/rust-std-beta-riscv32i-unknown-none-elf.tar.xz=af179ee477d53727d01feeb704776370482f8aa6f6bd51d7dcbcf90010d36b74 -dist/2024-09-22/rust-std-beta-riscv32im-unknown-none-elf.tar.gz=9673565000aebce56cddf905d27ec651d2c2845e9a2768ec38d10e18443924d8 -dist/2024-09-22/rust-std-beta-riscv32im-unknown-none-elf.tar.xz=38a5d0812838d5596a7a4804ee46e97bc5f4814056f93ad0988b7f2f34a90325 -dist/2024-09-22/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz=cb397f91bf2c66a0f7d704c320964885aaeacec90a0f562358e8678e749c1e64 -dist/2024-09-22/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz=ff95fa7f5598ed1f25e2aa0be9fb89ef0a7b145ffa9bcba7479bb3c0d83808b5 -dist/2024-09-22/rust-std-beta-riscv32imafc-unknown-none-elf.tar.gz=9049a87a4bea3319c7bf8162d5289ce252897e3ee637a0b6bca841c3507b98c4 -dist/2024-09-22/rust-std-beta-riscv32imafc-unknown-none-elf.tar.xz=e24970b400b30728a9ee5202b0fdb9734c115e015178817629220390badb7e50 -dist/2024-09-22/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz=aa06101ff7386aac69a1dafeb39645344fae3c0ca02537078029c4ba073aa1af -dist/2024-09-22/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz=13e358d57a5bfe3e4ca2c8ca5e6c8d026cfac417b3c050ebd9bcd5d24f3a5f6c -dist/2024-09-22/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz=5d880502cba47ed72006ef6e60fe004885c0f215d589a20456d41dcec8238503 -dist/2024-09-22/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz=a242f39d05716b72aeebdf83357835bae0d2386feca6759f343721148b7a0d4d -dist/2024-09-22/rust-std-beta-riscv64gc-unknown-linux-musl.tar.gz=117ec2433159f057fcd7fbae9d85042979340ab00f8d1b940c3adc5d3c791803 -dist/2024-09-22/rust-std-beta-riscv64gc-unknown-linux-musl.tar.xz=be0f262d8ed5122fee6b67abd4b78e419839e4005cfff1db9813ae655fbea23f -dist/2024-09-22/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz=78e28d3d341cedd0fe5ef0036b3b3c246b9f86e5e61d3bfd7e03e95d03920985 -dist/2024-09-22/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz=43bb14df9b4947f111c1e4ba9c4092b73a895c9431a299e4b076d387477f5687 -dist/2024-09-22/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz=e325c2ad8623b87456c12e17b29aa7f52ad243971002b4763677052f9b305eff -dist/2024-09-22/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz=ca02e01254defcfbf0a48ab574dc4b5aecd6a6be2ddc835704986284916019d8 -dist/2024-09-22/rust-std-beta-s390x-unknown-linux-gnu.tar.gz=79044a23a910bfd8488c382a3d2eab0c6a7ba9677165878b02f28a6c75d3a0b5 -dist/2024-09-22/rust-std-beta-s390x-unknown-linux-gnu.tar.xz=6a1196d2b2f30e22497a739e3b1ee302339ed442e0b807c707d1c4eb7c53ff3b -dist/2024-09-22/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz=fa3ad826bcf924094ad5cf19779fbfa70f656c1d2e66f4aee5dcf51792af74f4 -dist/2024-09-22/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz=d5f701446546c6cb64b413be37f3c4a0739010f25616b6a295adfcefb16e8642 -dist/2024-09-22/rust-std-beta-sparcv9-sun-solaris.tar.gz=1ac5c327d5a0d0256d16968aab3bf35828c995c818ba73788421da56404f165e -dist/2024-09-22/rust-std-beta-sparcv9-sun-solaris.tar.xz=fd6c7f163d2d6006eb85cc68e2794850f82dfe09f9173390cd0c167d90622d8d -dist/2024-09-22/rust-std-beta-thumbv6m-none-eabi.tar.gz=8f082a38dfe968d8f987bfec0822e221d0ab8ab73dfd451b63de7644ccaeb239 -dist/2024-09-22/rust-std-beta-thumbv6m-none-eabi.tar.xz=044bca675ac6b621ced7f2bc9a9909814c0b0818505ca1bfcd765c1859a9ed7f -dist/2024-09-22/rust-std-beta-thumbv7em-none-eabi.tar.gz=f3e1789a409b58b9769db8587ddbd21352e6634ff5a508b6ad82237cc85409be -dist/2024-09-22/rust-std-beta-thumbv7em-none-eabi.tar.xz=5f36d0504401bf6cbd2eed78e4575a190300ae26c581ee8599ab8d6e32dfafaf -dist/2024-09-22/rust-std-beta-thumbv7em-none-eabihf.tar.gz=a0ed6b4c71570e900e1605302ef865f7df9405e19245ed45ff5f7654eb3cbea7 -dist/2024-09-22/rust-std-beta-thumbv7em-none-eabihf.tar.xz=6fd7fac23460b49ca5246a6471de4f39d92764231ef2eac5f51d177c9d14ce2a -dist/2024-09-22/rust-std-beta-thumbv7m-none-eabi.tar.gz=21e1983e3f9c481677db7c839d5b2b301bae748ef52e1d0b5c3fbf9347732c66 -dist/2024-09-22/rust-std-beta-thumbv7m-none-eabi.tar.xz=ade8b1a2c128c298ba1d20ea7c7585af2a2b3a17b55a8dc6d39f0eebf0f01e66 -dist/2024-09-22/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz=29c7c493c9fee6afa8aea0f337da66118216ee21b373303432ccfb6375cd8428 -dist/2024-09-22/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz=d63e1c8cf97c0834a3825d9a552ed0ce744b2471028f49cbad6f7df1f7bfad7c -dist/2024-09-22/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz=0cec39208ae369c146d49dbc98984edb993c318a5dcbff205d3fa6b651400bc0 -dist/2024-09-22/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz=158f249f6446503ad5c558dba966ca69f57161aa90fa995a9e9b68fb3e38e732 -dist/2024-09-22/rust-std-beta-thumbv8m.base-none-eabi.tar.gz=8df09685f21eb9285adff2493ea6a9b3a04ce2e24b0761a47b44f0257b3485ff -dist/2024-09-22/rust-std-beta-thumbv8m.base-none-eabi.tar.xz=0a119d100a6bddf66047e98d453b8c54ab0952712c38b1e396bbef81114d4423 -dist/2024-09-22/rust-std-beta-thumbv8m.main-none-eabi.tar.gz=e7e234a7a8f687f0649654f562b12e09d332229dfd9e8d81a780afd9d8eac8ea -dist/2024-09-22/rust-std-beta-thumbv8m.main-none-eabi.tar.xz=a3c6c68ad6c24d080af8034168b36bbb24edc30e1fce2ac91bc3fa09ac34a678 -dist/2024-09-22/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz=1662be2b7ec3db6331ef545ac59c844733c3d1cdc728aef78049fecf37a416c5 -dist/2024-09-22/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz=b19dd77e7582da1785f78e85e39a9d966c7a747641e6772dd18cbd489b4940b8 -dist/2024-09-22/rust-std-beta-wasm32-unknown-emscripten.tar.gz=a7ae18e142b5b7a3fbab372bbf4e829626b52a67a10496f2cdecc89aab029310 -dist/2024-09-22/rust-std-beta-wasm32-unknown-emscripten.tar.xz=75a9a2dae5117b714a08024588cb4f5e5a6f07f28af55013f49fbe7cc8e2a690 -dist/2024-09-22/rust-std-beta-wasm32-unknown-unknown.tar.gz=25bf0342788e03ad52ee4835f280f3d92bf2324db3acfcf2654c5f5d37d43431 -dist/2024-09-22/rust-std-beta-wasm32-unknown-unknown.tar.xz=21798a2663b6d0e7347404666d5341b51c5d5de108cd68efbd1466b7c4002a62 -dist/2024-09-22/rust-std-beta-wasm32-wasi.tar.gz=02c1fcc01d28005432f6e53b6f8cecda2b555d482f713ec70ac92b1507121ec7 -dist/2024-09-22/rust-std-beta-wasm32-wasi.tar.xz=f2b4ae22141d39202bddd45e3373a8520684dd71460ceb3cdc9bc7d09aedd774 -dist/2024-09-22/rust-std-beta-wasm32-wasip1.tar.gz=f59a67c3acc927e72278f66553cd10bb3d81e16045c76671d38d09c8a462c78f -dist/2024-09-22/rust-std-beta-wasm32-wasip1.tar.xz=0f4eea80dcd13008f55d7120f2239aed87a6dcf693f70983caffc36a4be72ffb -dist/2024-09-22/rust-std-beta-wasm32-wasip1-threads.tar.gz=2581846fe64f1d9547ec293875be715251174c5b163a7c533dcae81fd55ea6d6 -dist/2024-09-22/rust-std-beta-wasm32-wasip1-threads.tar.xz=ad6d869148eea87192f786fca0302983094b25a1afec2813012ba3133e8994c8 -dist/2024-09-22/rust-std-beta-wasm32-wasip2.tar.gz=091057da389eb1d464353acca41e158130f969ad20f90827a4dc38bd363a68fa -dist/2024-09-22/rust-std-beta-wasm32-wasip2.tar.xz=c91b4440326443a4987758ac161b79f5aa30d23662a5c99a3c0adfedc0eb8e51 -dist/2024-09-22/rust-std-beta-x86_64-apple-darwin.tar.gz=180a9b1d5fb71ec3e88dd4e3a88f6f1da433a191125ecdf98c0169bd7b0511b3 -dist/2024-09-22/rust-std-beta-x86_64-apple-darwin.tar.xz=7d066c7b394c5b15027472fa388b9379ae8a7d4a990e02c0785f63a6f1b7f0c7 -dist/2024-09-22/rust-std-beta-x86_64-apple-ios.tar.gz=4ebdf9f16075859830e76e40547d1d56230ed8715e57f254c82d467634aa63e5 -dist/2024-09-22/rust-std-beta-x86_64-apple-ios.tar.xz=0bdcf11914a169b86b945df232a30c69f991393e3871956b55ca88a0ad65bf79 -dist/2024-09-22/rust-std-beta-x86_64-apple-ios-macabi.tar.gz=45ea8961f12b31e8404ebd178586711f7e4d4729d96ee298623240d8163766aa -dist/2024-09-22/rust-std-beta-x86_64-apple-ios-macabi.tar.xz=a36a3ed36c0224edaa5161b1c2cb7acb2736d0c2845d56064bde1c94af4e2db1 -dist/2024-09-22/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz=8d217487118140549fdc2223954d38a7932a2e9004a07924f853139395f8d88d -dist/2024-09-22/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz=66d7b8cc0b92af4f0458eab631faee6069c3bdf8e35200fa3d573177b1b354c8 -dist/2024-09-22/rust-std-beta-x86_64-linux-android.tar.gz=7efbe112fdf33d55ada19f3803b2552796d1027281b6c652a19465e4902a22bf -dist/2024-09-22/rust-std-beta-x86_64-linux-android.tar.xz=cacbf59cc9bad0a212d9fb86c81434350fb0b4842918bf7dc51fe978d21402b6 -dist/2024-09-22/rust-std-beta-x86_64-pc-solaris.tar.gz=073833d7b60d396be6890552f7068e885dc0fd4536e5049e88d97c71df31f126 -dist/2024-09-22/rust-std-beta-x86_64-pc-solaris.tar.xz=c6cbc8c41eb2e071cad032ae7587c5ae2e841f1d074c328229e3b7f271fe9330 -dist/2024-09-22/rust-std-beta-x86_64-pc-windows-gnu.tar.gz=0b5c7c007faa77fb28fe7cf275846f23adf0aa3fa1338dc93f86c05f7c605ded -dist/2024-09-22/rust-std-beta-x86_64-pc-windows-gnu.tar.xz=c1ec0ad342ec630f2ed909c54b0ca7f9073a85977da3a86eb5ef68d5c13ad4b9 -dist/2024-09-22/rust-std-beta-x86_64-pc-windows-gnullvm.tar.gz=5cf9a1daad4b60f7946adbdc9bde0d0d3ce438902f0a158f5f4f423f10960886 -dist/2024-09-22/rust-std-beta-x86_64-pc-windows-gnullvm.tar.xz=d8cfeec61cbbf6bb1b4234bd53a777ad2157def8dc232ba4b5f16bc81f4f1524 -dist/2024-09-22/rust-std-beta-x86_64-pc-windows-msvc.tar.gz=795ac3edcb9f0f10f36a19be14641918b5b0d647d5cc38e8652040437e409538 -dist/2024-09-22/rust-std-beta-x86_64-pc-windows-msvc.tar.xz=dacb5baf49d2b3dd8727a159f8fd348967f987a95162e587c8e5add57dd6d31e -dist/2024-09-22/rust-std-beta-x86_64-unknown-freebsd.tar.gz=089f99e1cbeab86b5d7ba9d582c5771c8d229ece1f81ad110716618823692deb -dist/2024-09-22/rust-std-beta-x86_64-unknown-freebsd.tar.xz=8749c2ae47644c16f62a310500ab91e5403a25c3e023a2c6e25cfa16217c98e9 -dist/2024-09-22/rust-std-beta-x86_64-unknown-fuchsia.tar.gz=becef9619e8ad1d4de66796c5877fd9798e5c943fb93a893aacd7819465f8a15 -dist/2024-09-22/rust-std-beta-x86_64-unknown-fuchsia.tar.xz=3801cc566789ae0313a5d10159cd0c94cbbcd8636409ba69ace73fae972ce2eb -dist/2024-09-22/rust-std-beta-x86_64-unknown-illumos.tar.gz=ba74cfa20f8c53865d96d26b9aaaa7abebf2269d1c3fe2bcd70e3cd7bd4e78d1 -dist/2024-09-22/rust-std-beta-x86_64-unknown-illumos.tar.xz=8f0a00cb53e21c90d60eb02853412d4cf671a1667bbbf7fe9a64183d966a9e48 -dist/2024-09-22/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz=1188997812bfef02c93a13a7d31a9df560383a875bb6a3cbdbb03eaf5fa0d649 -dist/2024-09-22/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz=12583cfd10835abf0f340fe8e141683cdce3e4df5a00998a04361b59203321e6 -dist/2024-09-22/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz=854f01a511c01b003facf4beb89a511395f0efcdc2284ad279b92837349eaa95 -dist/2024-09-22/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz=b016d4584a44064feee64de50963ccfbfaaecb792c88c97a079f279a0c1df955 -dist/2024-09-22/rust-std-beta-x86_64-unknown-linux-musl.tar.gz=912eea9c27b6fd251c5b92ae24d6321d5effe9586dbbd473e16a8dee2b758291 -dist/2024-09-22/rust-std-beta-x86_64-unknown-linux-musl.tar.xz=96bf10ef8fee6f8571b6601ab89e65562a91312502630c139d986b6e1ec9fbac -dist/2024-09-22/rust-std-beta-x86_64-unknown-linux-ohos.tar.gz=09e42b412f0891d608a9d4030203fe09645fc763ecad4be5ae790122a5d01f4a -dist/2024-09-22/rust-std-beta-x86_64-unknown-linux-ohos.tar.xz=dd84077f22ac4abea1c143d5d293425a85fad62ac65a4b31f18b9100c4e1076e -dist/2024-09-22/rust-std-beta-x86_64-unknown-netbsd.tar.gz=9aa5fa7bf57fbb95c3a6f718c0a2b62f32c6d1c9ccf93b392d4e166d311e0833 -dist/2024-09-22/rust-std-beta-x86_64-unknown-netbsd.tar.xz=765cf1a81b03ce210a88e87404a64d5b378f6615e428c385fac7a33b646f1276 -dist/2024-09-22/rust-std-beta-x86_64-unknown-none.tar.gz=e00c50362ffc95a1704912ea35c7b1792ead7906d98937fd73b9fa9fe31a520c -dist/2024-09-22/rust-std-beta-x86_64-unknown-none.tar.xz=280cf203356db9c32898197a3b5954901897a5b3059547f67c59cf5780c46386 -dist/2024-09-22/rust-std-beta-x86_64-unknown-redox.tar.gz=77069fcc33bc481ac8e18697884c1f3e3004a5fe5b265acb419b5f60c03fd2c9 -dist/2024-09-22/rust-std-beta-x86_64-unknown-redox.tar.xz=254dba227a76cb476fbc2a897169713969bf00f691ef77e03d303473db130523 -dist/2024-09-22/rust-std-beta-x86_64-unknown-uefi.tar.gz=4f1fb25ef423ab3cd5577f3e081771494978998acb8c04dda9de8a7d56cce985 -dist/2024-09-22/rust-std-beta-x86_64-unknown-uefi.tar.xz=fc21de2770ff0d0eb44d0939db5b274b0f408eb1a904c9eaf4db4c9463b5ff8d -dist/2024-09-22/cargo-beta-aarch64-apple-darwin.tar.gz=489c1b6aef3a7275e2e7a644677dde933a738534966089fe28c52c61dff04f2c -dist/2024-09-22/cargo-beta-aarch64-apple-darwin.tar.xz=5fe4d6a15e4f51f0575f2aee12eb644a95e548a4f03a80835296c44b1daf18a6 -dist/2024-09-22/cargo-beta-aarch64-pc-windows-msvc.tar.gz=5c5c408b026e0332c4e5d816c7a6a961ae5af0174f02b793edd613e56c672494 -dist/2024-09-22/cargo-beta-aarch64-pc-windows-msvc.tar.xz=4e060bccd78dc8abba7c7006585103b6bfa473a0f1cdd9e2c6b10d4fb8294f8c -dist/2024-09-22/cargo-beta-aarch64-unknown-linux-gnu.tar.gz=45cee09ecd3655b3a822b9c85e3f61f8e40b3fb510728503a3691f56ce415274 -dist/2024-09-22/cargo-beta-aarch64-unknown-linux-gnu.tar.xz=d8902eb0c3a725ef6345d325907ac10a7eb81e274c59aa589bf05aedea5958cb -dist/2024-09-22/cargo-beta-aarch64-unknown-linux-musl.tar.gz=67e6658e39c0381554ac025c26564888804eb9d8a3e1178726652fff03bc21b4 -dist/2024-09-22/cargo-beta-aarch64-unknown-linux-musl.tar.xz=427e7a4781dcdd2e316eb0c2751257597b4af58da8a5fd8407a8402814b65148 -dist/2024-09-22/cargo-beta-arm-unknown-linux-gnueabi.tar.gz=735d1b824d3a375a6b9c5a5d22fb5e607d3ad06ff70cebe81b84007967c6a5c7 -dist/2024-09-22/cargo-beta-arm-unknown-linux-gnueabi.tar.xz=749c017f8c25d0df23a160e02a765bb5e967f7657fdf3105d0d7ce64afe83524 -dist/2024-09-22/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz=050ae56d0398150212a75493562e6654cc14b7a1ebd6051bde146b5d408d24c8 -dist/2024-09-22/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz=1088b61e20981dabe406ff52965f48ab1542dd84d9673f7d56b21145d0b604b3 -dist/2024-09-22/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz=43dfb8491dcb64b91e6786366300a0ee3fd00f1815cd84f3bb4247e6b723a6d6 -dist/2024-09-22/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz=90266fcba10bd88e1f8f5d8420ee6835fe3e337dad1cc43ab7ef79edbe1a1b98 -dist/2024-09-22/cargo-beta-i686-pc-windows-gnu.tar.gz=6dca2e273600ee0f92a416901a7713ffd6db420b953e62d51d95bc85c1dbe27b -dist/2024-09-22/cargo-beta-i686-pc-windows-gnu.tar.xz=36fa46c7edcfc881568435f366e76f1989479356d93b8982981658fd44b80f4d -dist/2024-09-22/cargo-beta-i686-pc-windows-msvc.tar.gz=bd99a9cf662fbe90b79711776f972d2d574fcd6f0053bb672e4cdb35fc67ddf3 -dist/2024-09-22/cargo-beta-i686-pc-windows-msvc.tar.xz=8a995e56a96217cd999e786b16a69de1ec6e9db6412cd2c9c6ce090ed21a84bf -dist/2024-09-22/cargo-beta-i686-unknown-linux-gnu.tar.gz=ae115caa9516a96f144db9751b185503e1c648ea9b7e8b0a6aa10200315e6458 -dist/2024-09-22/cargo-beta-i686-unknown-linux-gnu.tar.xz=54b125ce0c00afa7bdebf5cb592249c37ac21d78479129a46d0b70d86fe6bf17 -dist/2024-09-22/cargo-beta-loongarch64-unknown-linux-gnu.tar.gz=21d2ca9f6d715e44fae058b7c26abc873930ac2823e72c9f8c983f7d089bd91a -dist/2024-09-22/cargo-beta-loongarch64-unknown-linux-gnu.tar.xz=b9b395041d328a09643b7e727705aa7705bf67c08edb3d26b78405ce454c6798 -dist/2024-09-22/cargo-beta-loongarch64-unknown-linux-musl.tar.gz=da7853da9096b6ddebc3b3da948b90ac448663dc9a5d2940cad420360d5934a2 -dist/2024-09-22/cargo-beta-loongarch64-unknown-linux-musl.tar.xz=9997e251abe606e390e3d2c280233f435f8ab46a6a3d24ce95d7a700ec049664 -dist/2024-09-22/cargo-beta-powerpc-unknown-linux-gnu.tar.gz=1715eabf3860f2fa7e1e27f2163a5243c8000b6216c0e7ac8dec993061ff479b -dist/2024-09-22/cargo-beta-powerpc-unknown-linux-gnu.tar.xz=f4e0f364c4ca68dc7b40b40bf13e28284a9bf6e6075b10504b9e6979d4a1a375 -dist/2024-09-22/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz=70cb2337910933f0ce22ef57e8dec4ab5732855d0657e56ed237e3e483aa07d2 -dist/2024-09-22/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz=1e9e383a093b54b8f7bff8dbf2f38590c148d0c9e18399bc128a09a6c67565bd -dist/2024-09-22/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz=6e01a5a6cf68b8385d2a2eaa07984ba62ef4df6811be2ade5dd7b22ba7d4bd69 -dist/2024-09-22/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz=70d0e45fba27db3322c3e4d802cdcd37503d2a848b9c0c2b9b759d48611c19ab -dist/2024-09-22/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz=baabb56c3670a0dab62fc7c0e5cb07474de795e81a6be42c57a91c2249e9b960 -dist/2024-09-22/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz=fd87e580bd0d4b47340b797fb52aeda83854556328869ebd1ce7136bcf8ead78 -dist/2024-09-22/cargo-beta-s390x-unknown-linux-gnu.tar.gz=dbf01fb97c1aa9db57b68fa863dca5df81e1f83c1686bdbc01c702b0148bba7a -dist/2024-09-22/cargo-beta-s390x-unknown-linux-gnu.tar.xz=f2eaf49ad1a05b5acf3050159aeb7351544c5aa14a46b381b0e2659eb857bce8 -dist/2024-09-22/cargo-beta-x86_64-apple-darwin.tar.gz=cdd90fe77bff57d0acae21499c0188fac2ddf7aa24dba07dcbf900444ceb1295 -dist/2024-09-22/cargo-beta-x86_64-apple-darwin.tar.xz=2c8acbf6eb4076ad876993f09714a2b1664031a41a12ff395c1f9c4bd0283640 -dist/2024-09-22/cargo-beta-x86_64-pc-windows-gnu.tar.gz=f16189ad7a0d311b17b6bb6ced913cde0115ac07e9a950b85d4336c488456c6c -dist/2024-09-22/cargo-beta-x86_64-pc-windows-gnu.tar.xz=1d4bf171c84def4110ee3f4e4798ab3ee52d0323bc2fc4abd564f229a23846da -dist/2024-09-22/cargo-beta-x86_64-pc-windows-msvc.tar.gz=c3e27d6a38eb46fca153ef17cea76b11664e8171e0aa76af594e67ed9dffbef5 -dist/2024-09-22/cargo-beta-x86_64-pc-windows-msvc.tar.xz=b64792d6ec70ee083dac929343ab45f4a52039c7fbc6cb223b02663591c8f544 -dist/2024-09-22/cargo-beta-x86_64-unknown-freebsd.tar.gz=40bf96a087dc1d57ba495733975ff34a4e75e51d7ddffc025561f0951adb57ca -dist/2024-09-22/cargo-beta-x86_64-unknown-freebsd.tar.xz=7912a49f7a181145b71a197014e3de6594b216959cd7c95a003fcd13854cb056 -dist/2024-09-22/cargo-beta-x86_64-unknown-illumos.tar.gz=1c3dfd5dcb8e7c8ba947b67f5bc466bae26ca1518a74798cfe5a21997bfcf71d -dist/2024-09-22/cargo-beta-x86_64-unknown-illumos.tar.xz=6f620a91c2bc145f894f5736a9818f7b54583a93e7eb2d0ac202f46a38040b99 -dist/2024-09-22/cargo-beta-x86_64-unknown-linux-gnu.tar.gz=c6c20977054f56fc279e666cf02da65acb376c1b08bbbc998cf34d0cc2b5bb7b -dist/2024-09-22/cargo-beta-x86_64-unknown-linux-gnu.tar.xz=9cca7e46ad35f0f69d8fe628a95e44388ed5cb62c1b77f2bab03dab28a05a650 -dist/2024-09-22/cargo-beta-x86_64-unknown-linux-musl.tar.gz=74005a4511ca2087ebb92db7e19a2e31e3ddcdef93e27da544bbc444df01dc32 -dist/2024-09-22/cargo-beta-x86_64-unknown-linux-musl.tar.xz=94215716623cadc8bf4a119612ad7482661905748d4e43ddff1855d4746f3972 -dist/2024-09-22/cargo-beta-x86_64-unknown-netbsd.tar.gz=fd9b2dd77b76b2ac44dbeb80e46371669223fe8ca57e4d480deeb162168c38d5 -dist/2024-09-22/cargo-beta-x86_64-unknown-netbsd.tar.xz=d419dbb9d1c905eb841c6870ddc8afe946b7618d3a0c6f39f8feeba6ecc74f0d -dist/2024-09-22/clippy-beta-aarch64-apple-darwin.tar.gz=60aba239287116d7e0f58fc71e510fdb7582003efdb3011765f732b1e494c7e1 -dist/2024-09-22/clippy-beta-aarch64-apple-darwin.tar.xz=00ef2da71c8e3f5be8401128509ff99130eebd5c0b90b5b5c16dc0465c2a18f8 -dist/2024-09-22/clippy-beta-aarch64-pc-windows-msvc.tar.gz=7ff2952e057849ec69a7d1147920c2b6ecb99fe7984afe627c5514c8c6a8811c -dist/2024-09-22/clippy-beta-aarch64-pc-windows-msvc.tar.xz=cc3e145daaf3674c1436d4380171ce5e26b075975121dac5c1d5c5d6cfa1a6e6 -dist/2024-09-22/clippy-beta-aarch64-unknown-linux-gnu.tar.gz=430c6d5ded52d04bfe93fce17f8fef57ce3ab05715767b85d6c9b59e521671b2 -dist/2024-09-22/clippy-beta-aarch64-unknown-linux-gnu.tar.xz=df4b9444dd435133bcfe386955b1d4b63c13e4acd766dc3bb9742c21431926d4 -dist/2024-09-22/clippy-beta-aarch64-unknown-linux-musl.tar.gz=7064208f59db897b1107072a3cc1a516d53888ea1c549bdf3cfd8479c65ec0c3 -dist/2024-09-22/clippy-beta-aarch64-unknown-linux-musl.tar.xz=1d33c3e2b4daa1ba7f1a6399790d1b76fdfe1ac9d293859983412d5e1e3663a1 -dist/2024-09-22/clippy-beta-arm-unknown-linux-gnueabi.tar.gz=b851cb5bcb31a2105039b55a613d937113fd45f5c1fbd4e3d24eecbed85a0bb0 -dist/2024-09-22/clippy-beta-arm-unknown-linux-gnueabi.tar.xz=a17f46c82fa28bfa9e3c9ff99cd25a888b6ff0c08a887ef4056b8ae29437a67a -dist/2024-09-22/clippy-beta-arm-unknown-linux-gnueabihf.tar.gz=784a1a0134d54cff72c9bf59ee1e750d0493fef5bde06bf778bc98321d833031 -dist/2024-09-22/clippy-beta-arm-unknown-linux-gnueabihf.tar.xz=c11461066103bf92f21298e5cb3b009cf4ac07bde5d99ce9ab97c1cbdf7c73f5 -dist/2024-09-22/clippy-beta-armv7-unknown-linux-gnueabihf.tar.gz=98c74f6a0692482355045bb4b0977887b419a8aa3c4654b9b59cd0d867f261ac -dist/2024-09-22/clippy-beta-armv7-unknown-linux-gnueabihf.tar.xz=20c82e6bbefdbaca22911a63a41d0aa05ed0ffad4571090c053cb354b49acd23 -dist/2024-09-22/clippy-beta-i686-pc-windows-gnu.tar.gz=3da558108df227ceb0ff7a2837d1bd2f5a75a0c7167f0b3c380d1aa5b2fa3e77 -dist/2024-09-22/clippy-beta-i686-pc-windows-gnu.tar.xz=f657f1cdc9f91243112834afbe5fe60f8b43e914504c8aed1994a13ac98bc575 -dist/2024-09-22/clippy-beta-i686-pc-windows-msvc.tar.gz=cf27f06843f5e0706aace4be4b9973fd164b57697b44d00852a9545d336c6fd2 -dist/2024-09-22/clippy-beta-i686-pc-windows-msvc.tar.xz=74dd229cdf65ce19ded1ed27cf5fb31c20f6a45879b277ad43aedc818eed514c -dist/2024-09-22/clippy-beta-i686-unknown-linux-gnu.tar.gz=4d22b439675ec118d021a85dc75540d7a3331364395e21bc1a2d76c26aabe9d3 -dist/2024-09-22/clippy-beta-i686-unknown-linux-gnu.tar.xz=bfc60e9fe1dbed050904efc71e8d0e5c90dae7f949fc7c81312de0c129f4d058 -dist/2024-09-22/clippy-beta-loongarch64-unknown-linux-gnu.tar.gz=25df67e21543e3a3b71500f55da1abe6182a24aabe1f5bb1e57fe99821a22d97 -dist/2024-09-22/clippy-beta-loongarch64-unknown-linux-gnu.tar.xz=7b56b6f7704742821f42396f5c517adda129b68f05da258d371cc8a3bc7356f3 -dist/2024-09-22/clippy-beta-loongarch64-unknown-linux-musl.tar.gz=f7305d23b8b850b4169a2ae6816c9db721a989ffbb642a4645ed95068a6553fe -dist/2024-09-22/clippy-beta-loongarch64-unknown-linux-musl.tar.xz=9576586590c11c86e8b029c32f17916ebd13d27d8750e30a927a4a986dd47aea -dist/2024-09-22/clippy-beta-powerpc-unknown-linux-gnu.tar.gz=1eb483594b3ca3ab8e0eac99e7699be151791fcdf0349714b0da923ea33b92bc -dist/2024-09-22/clippy-beta-powerpc-unknown-linux-gnu.tar.xz=42b9373a18ebf76394513cb75f8072ca094efbdfd8c60cc2249b04fad344f677 -dist/2024-09-22/clippy-beta-powerpc64-unknown-linux-gnu.tar.gz=fa6438d40613bb99062118bfb293f6f252a21c927d222c7cdfe4cee865d30d16 -dist/2024-09-22/clippy-beta-powerpc64-unknown-linux-gnu.tar.xz=7cfba858f149b327cbd9bf292080a2ae20404018228ab556eeefc3776f429785 -dist/2024-09-22/clippy-beta-powerpc64le-unknown-linux-gnu.tar.gz=5f6d94333400f99bbb0762be18fa9390885c13f4fe0ad7ea05b57808b26653e4 -dist/2024-09-22/clippy-beta-powerpc64le-unknown-linux-gnu.tar.xz=38042ee6161d8e8b04faf58a4bca98cf7940ece6ec42eb44ce29bdb9aedb6c89 -dist/2024-09-22/clippy-beta-riscv64gc-unknown-linux-gnu.tar.gz=b5056a3d8a8b3bbd888647117b316404b2701803bff09737cca18e16611ed3cd -dist/2024-09-22/clippy-beta-riscv64gc-unknown-linux-gnu.tar.xz=9322024609e563bb0d1f342bae2deab1d0c0ae951c2e94fe74ddc22fe2c7d3f2 -dist/2024-09-22/clippy-beta-s390x-unknown-linux-gnu.tar.gz=8b52721fc1df5cd158e12ae80a2936929f64a7b2506c55793b4a7d28522f0e3e -dist/2024-09-22/clippy-beta-s390x-unknown-linux-gnu.tar.xz=66dedbc154a11588a03616b92823c63502276123e66e9ff110c2e63cc7ed3529 -dist/2024-09-22/clippy-beta-x86_64-apple-darwin.tar.gz=66ba82b5e5097a2e35053fcb5db9ca44a152c1172f75d689688454561c8b3712 -dist/2024-09-22/clippy-beta-x86_64-apple-darwin.tar.xz=cfaa2e71b847103660336ad58025fff26f2928a4d7bcc5907fef91e70b63e1fc -dist/2024-09-22/clippy-beta-x86_64-pc-windows-gnu.tar.gz=fef4e4f2c68294908e170c78efb657c02166fbfbc45b6ce65fbfb5c76ce6d20c -dist/2024-09-22/clippy-beta-x86_64-pc-windows-gnu.tar.xz=0eec7155f78dfd0cc2e6ac996053492d7ba8a4fa5203f779a92b04ad42e8f651 -dist/2024-09-22/clippy-beta-x86_64-pc-windows-msvc.tar.gz=4dc7b6c972ed13417fa831ee20b9e4cc0a3895c39d4f059d1a14ebe51f7430e3 -dist/2024-09-22/clippy-beta-x86_64-pc-windows-msvc.tar.xz=c9f3fb89a31cbba2b575cbb7fc74c09c087940b138b34015239c8938ed6d6f14 -dist/2024-09-22/clippy-beta-x86_64-unknown-freebsd.tar.gz=cd7e5a9ee6be58a627b13d2e85c05aebd64414f854229aca917f3334acbe2352 -dist/2024-09-22/clippy-beta-x86_64-unknown-freebsd.tar.xz=7d81d8fd02506935f289e22c6a8f3433bc2c78ea02bbfa4950a31f49eb95344b -dist/2024-09-22/clippy-beta-x86_64-unknown-illumos.tar.gz=d38eda29de151d13b0fb1f58b090b63e049e095a326e26b76055383ba13285a0 -dist/2024-09-22/clippy-beta-x86_64-unknown-illumos.tar.xz=3100a9e357e6ded30499d4a60a6ff64f26d99e1cbd1eea11ca7fcf92a9c1f293 -dist/2024-09-22/clippy-beta-x86_64-unknown-linux-gnu.tar.gz=c09c9e00e653ffdb51c4edca6aa1e23572092c45a1cb81235f05bc75331d68c3 -dist/2024-09-22/clippy-beta-x86_64-unknown-linux-gnu.tar.xz=1e2fa4de890d7bc6c2828df95a729a55cb2b255a25d96194ccca0c3e06a580ba -dist/2024-09-22/clippy-beta-x86_64-unknown-linux-musl.tar.gz=ac80d0b1b7f3e451c3bd00fd882b547a9b87e95c3fc0d332050859ff827782a9 -dist/2024-09-22/clippy-beta-x86_64-unknown-linux-musl.tar.xz=1178ff5a580bd131ecb9a7b0ad2894c09f2882bcfc483ca14e1fd780925e97ed -dist/2024-09-22/clippy-beta-x86_64-unknown-netbsd.tar.gz=b69d92c035e456d4d1dd8a09032a92f8226c9f39579966e86c2e202ac9995d29 -dist/2024-09-22/clippy-beta-x86_64-unknown-netbsd.tar.xz=a0e827a24ffe8d2b38efff5da0972eee15e098f790b49035b21a72ebf1cb17ef -dist/2024-09-22/rustfmt-nightly-aarch64-apple-darwin.tar.gz=4e632df4953f955b24414d929c352ce1f6e196c50cedde3da4d8663f5f1dd77e -dist/2024-09-22/rustfmt-nightly-aarch64-apple-darwin.tar.xz=d7f8d8442b25053e767ec85e50aa2a6f9bb01e45a2ec3fdec56ef1c305a91ba2 -dist/2024-09-22/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz=eaee820d549347d15f1b96e3c85517a65e2a5655b86e27927eb6646a7c1d7b67 -dist/2024-09-22/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz=5fb16519d2acb68df963800c9a5036f1ee38b6ea02a115c40b6622338cf7052c -dist/2024-09-22/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz=037999e2fed25ae76b70960133a811a29707712d2141fc74a1db312cfe6020e1 -dist/2024-09-22/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz=b10d1947baafc6160ce8d5902936c2b3469a1558b71263671e581ac5b1c14f0e -dist/2024-09-22/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz=eb33ec39c232a6ddeab1b8038222f96407b9671052f995e0a60ada332a1ccb3f -dist/2024-09-22/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz=396775133e37dac5de8e71e5d8fea26c19dbfc7841244a35c3529f5dfec93163 -dist/2024-09-22/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz=4885a99dbab8f33288501532b287c20f981bdcd10ea4d9ccffe585d5338c43d3 -dist/2024-09-22/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz=af165d8090fd3c32efc7e5f58dd57d4a2c228cc6a9939c40024d896c35119bf6 -dist/2024-09-22/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz=150086cbd94e084b30faaebabc809cff11eca87a4aa4ff2b2b89286e0af6760e -dist/2024-09-22/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz=49ab34e495e893037431851e65a35ea7e9d0b46ba651f7d73591bd659c031bd7 -dist/2024-09-22/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz=c61c6bb8a96c19a848155a38560e0a6dac91ec5f1ee2c602a060cd6039324839 -dist/2024-09-22/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz=81b7ae3c5e27830fa10a17e062c56bcfe66413b994b27951b63f67faabd296d4 -dist/2024-09-22/rustfmt-nightly-i686-pc-windows-gnu.tar.gz=585896ee3c2b1644ebcba6a81b2f2dabc47da151f6100b5660e208c3a2967952 -dist/2024-09-22/rustfmt-nightly-i686-pc-windows-gnu.tar.xz=ca875f395d33249cbfd657cfab1b4c596de1453c4451c7bb4466ebec639ad016 -dist/2024-09-22/rustfmt-nightly-i686-pc-windows-msvc.tar.gz=4dbce4c329cac38785408eb1a8b2ff5358fd18b59276435695324a03a7018fa9 -dist/2024-09-22/rustfmt-nightly-i686-pc-windows-msvc.tar.xz=10aea1e2abaae9d098afff8d080cc9d84bfb3f77e2e72ec0a639d61dc5900fd8 -dist/2024-09-22/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz=140897d538c0f7df473c3f704ec7e9198c9e903b5882688f0494166647dbd91e -dist/2024-09-22/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz=06e85fa8391eb7d82902ef55af8ee89a16f07b32e4839a848ac09b506f4227e3 -dist/2024-09-22/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.gz=4103e5daf242f72c0c7875044ea2ee5f2c88bc5c87ba1e685eee526038663e7d -dist/2024-09-22/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.xz=fe424f1c13eb8257036db3e843d4c6b7b0e3bbf310f1d42719046f86dd635c95 -dist/2024-09-22/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.gz=86304bb8673decae3d6e8b923765b410948277ea00d0cc5b14bb448da149aa8d -dist/2024-09-22/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.xz=743abf4d3ea8b3e1e8dbed6d9f75ee84680b0636e8e7c536b13bd69a41c8a0d9 -dist/2024-09-22/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz=db68cf7bfaa00b8f6c544b615eabdea998540ae70ec23af6b7370153a6706a64 -dist/2024-09-22/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz=fe1abd02ed36a3720c41c46c77136c89c5addc2c8e5e2cbe25331a34082f4b7a -dist/2024-09-22/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz=c6bb214d68fe7d631398a8684df49f4d1faeb42f9d422c247328e508bdaee830 -dist/2024-09-22/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz=230e19228f80fa4da3036d4eac5b9f9dde02b47d32c43278190da4d322461fd1 -dist/2024-09-22/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz=b21b569a1831a2ea621c35e19a1820f236fdfc54d38a387789b7750b1af26043 -dist/2024-09-22/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz=28f8c4aa4cf00561d6c9dfddc13fdf5fba7b936f9f510b9ecc84160385d590d0 -dist/2024-09-22/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz=5cd81cb8c792abb3c31da225424ef5d1f6006163d3ddee06a95bb4286a29123e -dist/2024-09-22/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz=58eedfc8cda153ea5ee92278bf08a0625d129d3e208b3e0244e2b90819c7cc2e -dist/2024-09-22/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz=17a0c073de3c6e3769a86d0438b1132762456153f3739c6652f94fca270e3a4b -dist/2024-09-22/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz=d7001fc75844be6859a57d2263075ff1b7ac2d88c62452bd42fef97b0afe03d7 -dist/2024-09-22/rustfmt-nightly-x86_64-apple-darwin.tar.gz=7bc303ca8b36c782f2034441cbb6d3dc3ea891114895d2027cce9d8cd25ce348 -dist/2024-09-22/rustfmt-nightly-x86_64-apple-darwin.tar.xz=119dcbdeda0fc6cb80d18e6e908646cbaedd615f5a501922344c795ffd1dc7d8 -dist/2024-09-22/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz=b14962a790a48b609eda7e1a847c85759cd7dc7f9d0ac9914f126f458b4ae268 -dist/2024-09-22/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz=3a710fdf3d35c0a42f5c43341aa00390644d82e76c52aa59f4d652a6ab980b3d -dist/2024-09-22/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz=946233868c179df3c133fa04bde2c863028a69776c7416aa4a33adb102d63783 -dist/2024-09-22/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz=1db1094ee7c9cad7a16b227de6763b835bc33c0650ba2eb9b380c430a766b81c -dist/2024-09-22/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz=68bc0322c947af0d98f63fc3e41322c12ce8be2bd185091b14407792d407f59b -dist/2024-09-22/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz=66e380f40e18c8a1ce91a9eaf7f662cacd580fc2b276cc854c03d795a5b9d547 -dist/2024-09-22/rustfmt-nightly-x86_64-unknown-illumos.tar.gz=5048bd14d07ed54f5120b0488925f69ff92d2fe00f1e19ae3a8a39a56201c09b -dist/2024-09-22/rustfmt-nightly-x86_64-unknown-illumos.tar.xz=d2f903f996c265b4d70bb88d47e85dd7382b3298f9ff02ad4502f32d6f9919dd -dist/2024-09-22/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz=f0c150cb2fcbb7cfc4982426be6760093aa6cf854d84ed3c793f766fba6a0cc8 -dist/2024-09-22/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz=5d5cc741435c63b162417f425f7cf9445a13c109687cc85f28424fc51192e333 -dist/2024-09-22/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz=a3252a997f60b086ea8c9c32665277f33cf574fdefee859ee448dc0b7eed5be9 -dist/2024-09-22/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz=b888f58dce3689e75ea6c23904481f7fec110f0aea45b75a9390d2160e0d3151 -dist/2024-09-22/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz=4663adcc009bd376b0787760854fb694eaa0edff88f72b4cf486f7180f6a1c2b -dist/2024-09-22/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz=bfc83277d2217b3a908c3f9153db1336b63270c70c6cd83a2628cf18c41db47f -dist/2024-09-22/rustc-nightly-aarch64-apple-darwin.tar.gz=ade996e00dd338a86cdcb25961d07c936edec1392526d78dd5de156ba012fe55 -dist/2024-09-22/rustc-nightly-aarch64-apple-darwin.tar.xz=147d0cfe57be988564d30fcba7fc0c69979b5fbdd91e4a08ac8e580be8a1cc6f -dist/2024-09-22/rustc-nightly-aarch64-pc-windows-msvc.tar.gz=e6a59a0303abbabb3b373fda7fb697ad2cfd31011f231fbdfd45c1cbd64e8bd7 -dist/2024-09-22/rustc-nightly-aarch64-pc-windows-msvc.tar.xz=9ee27bc608470ef29a51272656d0ed5e03946dcc3411412ef8b05cc70f97f8b9 -dist/2024-09-22/rustc-nightly-aarch64-unknown-linux-gnu.tar.gz=3ec6f8cee20883195c102bdcffee31d695698bb6eaf45502720edbc16b02f471 -dist/2024-09-22/rustc-nightly-aarch64-unknown-linux-gnu.tar.xz=7f8fabd6433acb752131071c5bee76752fcc88e08ffff4684a7badb9ed4bc50e -dist/2024-09-22/rustc-nightly-aarch64-unknown-linux-musl.tar.gz=7a8756afcd643b78aa6834497935d7bc0ede1ae74150fa83fff85243deb5e554 -dist/2024-09-22/rustc-nightly-aarch64-unknown-linux-musl.tar.xz=de39081dbeeb0715d433e0cd56e62db45c3bb5bf04d1e7dc3fa097e7b3ca97dc -dist/2024-09-22/rustc-nightly-arm-unknown-linux-gnueabi.tar.gz=ea6bd6b337d24a7c9995fa95d8884e66755d016fb1d50fea063129a410bec22a -dist/2024-09-22/rustc-nightly-arm-unknown-linux-gnueabi.tar.xz=fa195b2588675831274ca21c0d2420e5729d1c21c4c245f2fd1d2c044d7ede1c -dist/2024-09-22/rustc-nightly-arm-unknown-linux-gnueabihf.tar.gz=6f0719613ec54221e978e7136baa00eb25b8b3d627e5de5ee3488c9d9e869b97 -dist/2024-09-22/rustc-nightly-arm-unknown-linux-gnueabihf.tar.xz=9e0bbd283a0377f881f1c048660c54700561762e220ff2713566d3fb6eb56cce -dist/2024-09-22/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.gz=c8f88bb948119a9ff218571eb3ff0144915b2ce4a404d445db9f8f9c25044aa3 -dist/2024-09-22/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.xz=1c41588099d929a7e9dd56cba22782f5202fac2829b924b1aa7dab3e03c52960 -dist/2024-09-22/rustc-nightly-i686-pc-windows-gnu.tar.gz=af2d30b4925e786ace64d4a11bb05ac6f7df1636989a3656d1aa9fe56cdc330f -dist/2024-09-22/rustc-nightly-i686-pc-windows-gnu.tar.xz=4bfe618c3702ea805b63beac19cbf0561d262e67d87765a4e10ea9defded53c4 -dist/2024-09-22/rustc-nightly-i686-pc-windows-msvc.tar.gz=c4e57fe6fec40d874c8fb54227b310072dc98f35f99b8cc741e6818a67941f6d -dist/2024-09-22/rustc-nightly-i686-pc-windows-msvc.tar.xz=ed10535a830e2e1ab22767a24b82b3314b7ef4ac3c318954ee8f2384b287d8e7 -dist/2024-09-22/rustc-nightly-i686-unknown-linux-gnu.tar.gz=da5e36f6bb3d9f00b8e5db5aceefcf8ad38552b85a1a4f60f7b700148cd49152 -dist/2024-09-22/rustc-nightly-i686-unknown-linux-gnu.tar.xz=5831b0209eb64a44b6bfc8aa4b092faaae85101f58f79c4e869bffec22361f1b -dist/2024-09-22/rustc-nightly-loongarch64-unknown-linux-gnu.tar.gz=f31871890aa6249528b43119d0f050d27c5f404b560d48660cd4c9e7a3a80b76 -dist/2024-09-22/rustc-nightly-loongarch64-unknown-linux-gnu.tar.xz=19dc59393d25edef8a341bb137ad1f4ca20741038b0111dc81d6e61c0a7a1975 -dist/2024-09-22/rustc-nightly-loongarch64-unknown-linux-musl.tar.gz=8ebea352863ef014e4dafbafe5a28ddfff6a26f3e4cf728fb4099ecd3444a3ec -dist/2024-09-22/rustc-nightly-loongarch64-unknown-linux-musl.tar.xz=97196b586f44022d2c24b7378830f716abceb451244035f74c40b6c1587f6c50 -dist/2024-09-22/rustc-nightly-powerpc-unknown-linux-gnu.tar.gz=6f4d2428ec7a4d5e1540b53e35904b9f9ff5b8fcd05cf3311b005dbfd426d65b -dist/2024-09-22/rustc-nightly-powerpc-unknown-linux-gnu.tar.xz=c2bc66d7d763c1d4c5752b60ab563fe5b870dd35533712046acd40f258f7a337 -dist/2024-09-22/rustc-nightly-powerpc64-unknown-linux-gnu.tar.gz=d0e6f42aafc8d8b289b55c1ba4a34039c747a7445b347f05017606801a7d81a4 -dist/2024-09-22/rustc-nightly-powerpc64-unknown-linux-gnu.tar.xz=9612777e56955ab5446e3ef20e0d579fbeceedc3bdc4d0053367be2191551fd7 -dist/2024-09-22/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.gz=811099c8b6adc017678c4e43c8f7b02b2bde267eac1bbc023b1f22c184894231 -dist/2024-09-22/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.xz=f766dab0fa46122c26e5a7736da65e8a2df9c2c6578093b6532dbd88a162d1a5 -dist/2024-09-22/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.gz=21e9896e5184d797445a19ce5788d8dabe86302d5f63bf8c07105b52a237c13b -dist/2024-09-22/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.xz=002da974c9606726cc7e6f68cda012ef305e420cf6f7a0de84bf791c007fecd6 -dist/2024-09-22/rustc-nightly-s390x-unknown-linux-gnu.tar.gz=adfa4248f4ad883a04d67f923325c28b7400853063f2d8017cca8f4100ec1125 -dist/2024-09-22/rustc-nightly-s390x-unknown-linux-gnu.tar.xz=8334aa8a99d2a8034267394d44b0e5036d053c247812dbd5bc90bdb2344e4713 -dist/2024-09-22/rustc-nightly-x86_64-apple-darwin.tar.gz=385aa935fb1762423d1a11c0928597e502adbab9809a86c17d98096c31f65775 -dist/2024-09-22/rustc-nightly-x86_64-apple-darwin.tar.xz=f2bb16e1618dbcc7dda85e0ff4460ee270a99871477380a6412f575bd02f4cf5 -dist/2024-09-22/rustc-nightly-x86_64-pc-windows-gnu.tar.gz=6e3894c7651bfb48c741aba516ee99690616431643db82cd186fe408675d07b4 -dist/2024-09-22/rustc-nightly-x86_64-pc-windows-gnu.tar.xz=5661b5ba3a496106f4b0019d4ce81dbcb4b4a0db68a90bac64a95a0bd9201514 -dist/2024-09-22/rustc-nightly-x86_64-pc-windows-msvc.tar.gz=564f7a0582f3b900201cda4fe502e191b651a845210d21a40a119b94e2e51133 -dist/2024-09-22/rustc-nightly-x86_64-pc-windows-msvc.tar.xz=1804ebc7ade5c49ec4b82cac2261cf159b8c852a7e06f3faafbf990214936d2b -dist/2024-09-22/rustc-nightly-x86_64-unknown-freebsd.tar.gz=7455de95ddb8e565ddeaf2da7d80d890c60bc653f52afcab5244476d35305e0b -dist/2024-09-22/rustc-nightly-x86_64-unknown-freebsd.tar.xz=36a7cf6e8245c3879c08d5e3acfb0155ebcdc6c5b06edc51d43376c44d9ed0b4 -dist/2024-09-22/rustc-nightly-x86_64-unknown-illumos.tar.gz=143f5ce723a8f5e54af64a3b31d83243a808355705b1402be5de821759187066 -dist/2024-09-22/rustc-nightly-x86_64-unknown-illumos.tar.xz=c88c8d2ae8f221fe1db978802c98368472381b443bed9501371c03617865785d -dist/2024-09-22/rustc-nightly-x86_64-unknown-linux-gnu.tar.gz=0ea098f78927d9fdf4ec075a04e989b6ac83bc1f1225aca5960281cd65046a3b -dist/2024-09-22/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz=33e5e1e0b758de383281ae704d3dd1ee337d8e28515d6b4584dd2691587c7f0e -dist/2024-09-22/rustc-nightly-x86_64-unknown-linux-musl.tar.gz=723f5eaceef968b05286a17b7868c7e0cf222ac33d23a9ac3f761fc274b87c38 -dist/2024-09-22/rustc-nightly-x86_64-unknown-linux-musl.tar.xz=1b00b14a57b6f3b7edbf9adc05d3ed28ed1e2b8ced921a444d13dd1ef577e715 -dist/2024-09-22/rustc-nightly-x86_64-unknown-netbsd.tar.gz=6cd2651e4e8aedd8aef8d325a72cf18694ee7a14077c7331d96e2e7c03b9c57a -dist/2024-09-22/rustc-nightly-x86_64-unknown-netbsd.tar.xz=0c6144559f040a209183d6f02f61caf485f0174190e643870d1d6c9744bfede3 \ No newline at end of file +dist/2024-10-16/rustc-beta-aarch64-apple-darwin.tar.gz=24719797bf50fb494c61cf4711d6bb238ea9e789a1b10d957abb23f9849a06cd +dist/2024-10-16/rustc-beta-aarch64-apple-darwin.tar.xz=5eed456f0034e2b31ed4f6089163dd5e86ecb04630371e408aca741c32d845c5 +dist/2024-10-16/rustc-beta-aarch64-pc-windows-msvc.tar.gz=f337d992f4a730d39ae571d602f15d2c66ed0b6abf1b2c63112b570e855ac409 +dist/2024-10-16/rustc-beta-aarch64-pc-windows-msvc.tar.xz=d22b4f26ba8b82e32114311c1f0386d0126eecffa2accab8ca9ecd6a7aa38400 +dist/2024-10-16/rustc-beta-aarch64-unknown-linux-gnu.tar.gz=047735b5c90fca9f26e5eca2a1d24dcac6fdddfddcb89c9d1e2f6d0af0199946 +dist/2024-10-16/rustc-beta-aarch64-unknown-linux-gnu.tar.xz=c70bce1fa2a6e98577683d94473ca7046e8add65b85792e9887fee4edb8bdcb7 +dist/2024-10-16/rustc-beta-aarch64-unknown-linux-musl.tar.gz=4c75417b640557b35172ea384fa34a3e8da1960efdf4a40cf8d1fdbdd50ee997 +dist/2024-10-16/rustc-beta-aarch64-unknown-linux-musl.tar.xz=f7f5e67b831af5fdb28266fadd7cfd9f092c066f7e7322b058d6fb2bc7f6ff77 +dist/2024-10-16/rustc-beta-arm-unknown-linux-gnueabi.tar.gz=5d94f4e51767b02ddcdafdcaba3404a3133d308fe98c7bf5145a41bde8146319 +dist/2024-10-16/rustc-beta-arm-unknown-linux-gnueabi.tar.xz=49166b4eb2e18e009ebde1e4c133adcacc3d5257fbd63b07418642d5c841957a +dist/2024-10-16/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz=9e51ecc782cf9738adafd70c055ed793ab895c9616619c525cb52d7412cdf884 +dist/2024-10-16/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz=d60502f25273c2552997de281727b0f5914a2a97f32310f921ea714c5a1080d7 +dist/2024-10-16/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz=5796a33eda8d7b47c8982d3a2e425728cf681043151a291fea107b3aca9ff1a7 +dist/2024-10-16/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz=71fb2132822aa284cae878a76f9996092316942f84dc5a674fb8be17eb391cb0 +dist/2024-10-16/rustc-beta-i686-pc-windows-gnu.tar.gz=d089cdb87961d00e7dc51c767993342a2fa704756a94c421be7f195dfa6c5293 +dist/2024-10-16/rustc-beta-i686-pc-windows-gnu.tar.xz=42865105f308f7e0cf9af250b54086eaa20da8ef13e9cbf82380340a9db4ce90 +dist/2024-10-16/rustc-beta-i686-pc-windows-msvc.tar.gz=5753e00d74de3ceb1af0dc533496d7db6295d673eb05aea779734a519b5f789f +dist/2024-10-16/rustc-beta-i686-pc-windows-msvc.tar.xz=dff93d0c39e8653f01248f0db05123018c63c92a1d3861935b12ad1818b00864 +dist/2024-10-16/rustc-beta-i686-unknown-linux-gnu.tar.gz=4e2e06e503be7d15211dad18911ce951491d2596cef466ae8282af840184427c +dist/2024-10-16/rustc-beta-i686-unknown-linux-gnu.tar.xz=77d0d69f3e0c2b32bd1ccb73f12b5b770a1a720e7928859d454f42e611f77d67 +dist/2024-10-16/rustc-beta-loongarch64-unknown-linux-gnu.tar.gz=5faa3516ecfe77f8fb21ba80e78c21a1b039f5fffae508cceffd04c8c329f152 +dist/2024-10-16/rustc-beta-loongarch64-unknown-linux-gnu.tar.xz=8f086e53b3abffd7c947f5b0784f9977ed4559e654805bc3877ada99072d38e4 +dist/2024-10-16/rustc-beta-loongarch64-unknown-linux-musl.tar.gz=2147f76d151c513aaef63cb2365bb2c9a8d0eb21a6b1c7c2ff535dab0882c46a +dist/2024-10-16/rustc-beta-loongarch64-unknown-linux-musl.tar.xz=db2c17f1f3e0af9ad56982e1396a031df07939aa04c73795f541b16161fc3bdf +dist/2024-10-16/rustc-beta-powerpc-unknown-linux-gnu.tar.gz=e5d3fabc7902695ccf85171dd16cfe772a480dce203004da0853170450e57b1c +dist/2024-10-16/rustc-beta-powerpc-unknown-linux-gnu.tar.xz=db2f03a41470e60a0070b4d96590ae049c23d2c0f8c07a5778023a4ecf3e52eb +dist/2024-10-16/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz=49610d2df0b6ece6b2afc583db707eed0a6a12ef99a8ba0a82f9acb7c1e15fca +dist/2024-10-16/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz=801a92eebf0c068c88a48129b054c4ecea143f38468ff5d53e28fd00a0fad6de +dist/2024-10-16/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz=db8a9c4bc9313627d5ad2ed2ebe91b6129958254a32862aec67edee10cdf9bca +dist/2024-10-16/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz=fb2f2f2acb7516d98a6abf17e84e8b36beb7179c69776d69465f1c981466321d +dist/2024-10-16/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz=87effe21c4b4333769fa7b4b0fc4bd43edaabc1c8ba33e75480cb4da0d59dae9 +dist/2024-10-16/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz=71701db843d0974b4fc09afb65e3872faaaf66bfda258c9627576efe8f998f96 +dist/2024-10-16/rustc-beta-s390x-unknown-linux-gnu.tar.gz=6485ed4c99deffdde4eee34e46b8be2eeb65a3f8f4b4eb032a4ccd9c6f4e29e7 +dist/2024-10-16/rustc-beta-s390x-unknown-linux-gnu.tar.xz=e8ee8b61386d490c8e59e0c2ccb30fb7758ea0ff0b1448d5f946d9fc58496a11 +dist/2024-10-16/rustc-beta-x86_64-apple-darwin.tar.gz=23e36a4892e948a6dc231d15913562f1f95f798a62a38315a6b19244aaf78385 +dist/2024-10-16/rustc-beta-x86_64-apple-darwin.tar.xz=2db43b3b599eab832a13c784d3a1bc60c3222f5bfce8e112688e1478837b8c25 +dist/2024-10-16/rustc-beta-x86_64-pc-windows-gnu.tar.gz=099c529cc84219ae3ed9a33dbc5265c46a01c8cffb8989e66e367078bc981eec +dist/2024-10-16/rustc-beta-x86_64-pc-windows-gnu.tar.xz=efef4dd4a40d4f96d151293031783688c84b088a5f2cdde84d931bd44aee923a +dist/2024-10-16/rustc-beta-x86_64-pc-windows-msvc.tar.gz=28633202a502121e9369e93a8cc66bcb52b2cc959d7598f9bbb8e4c840381baa +dist/2024-10-16/rustc-beta-x86_64-pc-windows-msvc.tar.xz=c7b879d2e7d7c21eafc7b8e9f18f009d2d38f91a2eafa51d25d38e3b51e17ef3 +dist/2024-10-16/rustc-beta-x86_64-unknown-freebsd.tar.gz=69bdb56ac4f47fa614fa9e8be5218a492d31a423454c192ed5850f49357687e5 +dist/2024-10-16/rustc-beta-x86_64-unknown-freebsd.tar.xz=36c995c1dd55ab4501f250a77f27cce34330daa2a3e74129ce389aa23b4e3a05 +dist/2024-10-16/rustc-beta-x86_64-unknown-illumos.tar.gz=84bb641a5576ef0e93c7b5bae7417eae344f32271a0ebc31bb987d15316815a3 +dist/2024-10-16/rustc-beta-x86_64-unknown-illumos.tar.xz=a7311a345dddc9f8cf1eab6b3e82658fadb485bd755a115d4d6ffdfb42a5625e +dist/2024-10-16/rustc-beta-x86_64-unknown-linux-gnu.tar.gz=9def7618829111d1014e21fb0bc10abc26459e59ce61fdac5fb3b63583f472c6 +dist/2024-10-16/rustc-beta-x86_64-unknown-linux-gnu.tar.xz=97d124a65a7d7e5610901521b565ff031313685cc37a1caf89de58d952065c3c +dist/2024-10-16/rustc-beta-x86_64-unknown-linux-musl.tar.gz=101a440c383011cb4621825481582a81bfbad0ac03439542bd8d05ccb5aaf2c4 +dist/2024-10-16/rustc-beta-x86_64-unknown-linux-musl.tar.xz=4148b4311ce8e1cc5dae86d5f27e207496b85e5c23a53c7bc5b05ba18918f717 +dist/2024-10-16/rustc-beta-x86_64-unknown-netbsd.tar.gz=25c5c35f2acd37a7c72eb8dc546cb6e9f62b3e76e1569d188bbe2aa9b31ea3e1 +dist/2024-10-16/rustc-beta-x86_64-unknown-netbsd.tar.xz=9b84ce176d4015ed8f6946ef2d42f2f601cf419d1a6477f44bd6b7c7d27c95fc +dist/2024-10-16/rust-std-beta-aarch64-apple-darwin.tar.gz=ebdf49b8d4fab00c7fb4d396c54caf5cb234389b7353856734b960f908c3cff9 +dist/2024-10-16/rust-std-beta-aarch64-apple-darwin.tar.xz=4d0d5fbc235d8cc78e9997302c45916008e203ba7f02edcd061290fb9639ee8f +dist/2024-10-16/rust-std-beta-aarch64-apple-ios.tar.gz=6693f5a06df0ea5929df18b633ad6373d098db4454d0e1d35e4c19b6dd7fa4ed +dist/2024-10-16/rust-std-beta-aarch64-apple-ios.tar.xz=351a1a2a13316161edcf97238d868cf4b1b5216bdf28ca0aff5a1dba2a1258f4 +dist/2024-10-16/rust-std-beta-aarch64-apple-ios-macabi.tar.gz=f0e13e1700a1cbc1489c0a5728ce6c0f5ba1432a75ca2c0c0573b9fcf130ae9b +dist/2024-10-16/rust-std-beta-aarch64-apple-ios-macabi.tar.xz=825550e3a2afbe15130dcf7b702ea62b3b90f8a1e0b850cd6e9a5b5dd180e72d +dist/2024-10-16/rust-std-beta-aarch64-apple-ios-sim.tar.gz=f77a6c24301c5c7165de3bf51b5b6d45e7d37a82d00446d1abbe5a5c591ca616 +dist/2024-10-16/rust-std-beta-aarch64-apple-ios-sim.tar.xz=5a9507e0c06b252196203b01319355e4d246eddead60993262bd680b6a1d2315 +dist/2024-10-16/rust-std-beta-aarch64-linux-android.tar.gz=eca36ae4253e5f1b51c065631a650135b71797b452a7fbf6dfa17c49a01f71d9 +dist/2024-10-16/rust-std-beta-aarch64-linux-android.tar.xz=1da17cca8397bedda8b5403ddcc9f7686d7ad207daa7389a6cf80f922bac8140 +dist/2024-10-16/rust-std-beta-aarch64-pc-windows-gnullvm.tar.gz=1a4eea434371a7d95b473410a42d8409995119c85954f94a75b8b0a69aa3095b +dist/2024-10-16/rust-std-beta-aarch64-pc-windows-gnullvm.tar.xz=cea3d7d9568d2ed86ab11d28f5a02cf36210971b798c4d61e133357c24108f6f +dist/2024-10-16/rust-std-beta-aarch64-pc-windows-msvc.tar.gz=355fa0988a68a1a331a2794a573cd065e6fbbe8b312e187dfff59f4f4245cc5f +dist/2024-10-16/rust-std-beta-aarch64-pc-windows-msvc.tar.xz=c93347602b0133e0da072243ba9419c95179f9f548b6284612967d7b80a42144 +dist/2024-10-16/rust-std-beta-aarch64-unknown-fuchsia.tar.gz=c4305667ed2a77764c729fe236491b239cea7c2605039c2bc28a926d21f343cc +dist/2024-10-16/rust-std-beta-aarch64-unknown-fuchsia.tar.xz=02b6b621a1b3b91e25482400680cd38be806d7de541cf364d0ed181a92fdcbf5 +dist/2024-10-16/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz=830e1b90ea156eee05b0c5fab514d82558e2473eb5f6bddfeafa51e7417315c2 +dist/2024-10-16/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz=c5910437177f607439a6b18bd05b93c3965f915a0d372fb540deecf044b21880 +dist/2024-10-16/rust-std-beta-aarch64-unknown-linux-musl.tar.gz=7a0f343b5fa50168a3edd0770dee148c82e43e7b2b82e2149ca22badeade3218 +dist/2024-10-16/rust-std-beta-aarch64-unknown-linux-musl.tar.xz=dc4d7b3cb830451044726e72b848e529e92ec0330e610f06b07f8ed37415c3cd +dist/2024-10-16/rust-std-beta-aarch64-unknown-linux-ohos.tar.gz=8a9e341e6f208d5036e4c774f68b75802c64c53c4a9381ffd5a62e9b3c486cdd +dist/2024-10-16/rust-std-beta-aarch64-unknown-linux-ohos.tar.xz=fd24b56cc9891d9a1246e62eb33f6de8385acb265ca875af79f2593ff4bd323d +dist/2024-10-16/rust-std-beta-aarch64-unknown-none.tar.gz=51a58a9f663de787ca58da8e4ed705a1099bfeca945eaab3bbce01edd45aff4b +dist/2024-10-16/rust-std-beta-aarch64-unknown-none.tar.xz=47fcf0fcdabaddde929e4828c1de1db3986af1d32a752c057ec69aee9c8f6162 +dist/2024-10-16/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz=207281137a1b6ec8c1df21c581c23a6db7bfdd11c550749203bbe24b9ae80019 +dist/2024-10-16/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz=217625e68479d09d8e63f931983e030ea9f0829cdd559ba88bf657e711c96aa6 +dist/2024-10-16/rust-std-beta-aarch64-unknown-uefi.tar.gz=4c5fa8fc4e18723c4522a1e93e9e343e35f02e74fc82e6fc44951bf7e1849371 +dist/2024-10-16/rust-std-beta-aarch64-unknown-uefi.tar.xz=f4440f97ebab6a79d50683169994cef569a427cb1811b85ee196432d4e2d0b38 +dist/2024-10-16/rust-std-beta-arm-linux-androideabi.tar.gz=ab7dfa2b8aff6bb7514798d11970e4c09c8a4844d7408e295c547f1a87c23ea0 +dist/2024-10-16/rust-std-beta-arm-linux-androideabi.tar.xz=fb9ce70893a8c89bc3e66dd6ded2e0c4813c96bd0781b6c3b420a278c53ba4cd +dist/2024-10-16/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz=4650f832189a221337fc172c2ffa113ff209774949ae12e7ef159117a02e984e +dist/2024-10-16/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz=f6bb5528b914311802fdb9816260e8a57531fedc5f68bef2dc6ba83d59d5ce4c +dist/2024-10-16/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz=2fff203abd959498321680582bb969de89c9de4718b38e06cc91a789d7fd415e +dist/2024-10-16/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz=df5cadfd5895ee1552bbcfebc40b34826481932bdde309ecb2c13f55541ca2c0 +dist/2024-10-16/rust-std-beta-arm-unknown-linux-musleabi.tar.gz=e29900d97e62c7568395191e1230fa6f98f971c1593303810f05d4db5c68592e +dist/2024-10-16/rust-std-beta-arm-unknown-linux-musleabi.tar.xz=4455ff5a1de11281aca0df4f3f6d33d245314ce4276bda9d161bf850eda24ad6 +dist/2024-10-16/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz=26fcafd19aee4fcba45875d0f35aeceed7cb0a0fa070e6a2447b3d9b86170c8a +dist/2024-10-16/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz=cc43780fa58e7fa1d23a3b5e2695dfd3f4ac3c02398756516c395f4546e2042d +dist/2024-10-16/rust-std-beta-arm64ec-pc-windows-msvc.tar.gz=a67a25cdaa3fabdd2b619434e3b98f05acc13f25cc7ebf8f936e7f3d1761e272 +dist/2024-10-16/rust-std-beta-arm64ec-pc-windows-msvc.tar.xz=e8ee762127e02a73614e636b77d34d927f34e967cadd79158ca6ea27687c679a +dist/2024-10-16/rust-std-beta-armebv7r-none-eabi.tar.gz=7343489518ad6d354f9bfcbbc884d1c0e4fc88c4650cc68d9b9b84ee12b750b2 +dist/2024-10-16/rust-std-beta-armebv7r-none-eabi.tar.xz=eef35d9c016fdb67b9825104558ca0fc1aec3af8a738636a0f24797ad270b8e6 +dist/2024-10-16/rust-std-beta-armebv7r-none-eabihf.tar.gz=ed36702bbf1d45c263b8b52a06f2b4a9783c6ec78db28e00d317acd09a549977 +dist/2024-10-16/rust-std-beta-armebv7r-none-eabihf.tar.xz=e4fbf4007af9858e1bebffef6bdb4c66f419b035c8fb385dc70d46ce2e312e2e +dist/2024-10-16/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz=1eebca6a4ed9b04a1cd3fc57f8f75bda14cc03c8909385586c8a084e46aa96fd +dist/2024-10-16/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz=0bf68ccaa22a4782f23a34b8a52ca250b183e265f12bffde7cda9ddac515040c +dist/2024-10-16/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz=6f7b932bb0176fefbcc1de700a36da7c60dac609ec91e6bf351e4c42ea6fb119 +dist/2024-10-16/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz=a0d9397caf812fa479da6b389b653fcff451f8d54fa0545e5c908e73391b6dee +dist/2024-10-16/rust-std-beta-armv7-linux-androideabi.tar.gz=5be2ca5bd0340fa2e7ffe435081d1848ab883e46a9c0f07eee69f7dd9d08e0f6 +dist/2024-10-16/rust-std-beta-armv7-linux-androideabi.tar.xz=ed563b78d4201ce29ba79cf6ebf5a3b7d8020611309e39b8790c59edcdd05b29 +dist/2024-10-16/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz=53f7928406a1a14dfc6774fb2704bfa9c68091b135b750c5e46e3610e00e8c72 +dist/2024-10-16/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz=d71cf98a8b6dfa2cc1682819d1bc5bbfe0eae819f63bb91d64e4f52bbee4158f +dist/2024-10-16/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz=f65eccc2a47e34d96faa94954c738813d9b5acae351936b07df6ee2ee8592296 +dist/2024-10-16/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz=4f44230338a6b6bc17a8a2a80125ba18a9dedb6f9347c6e93b7f7b88c87e4468 +dist/2024-10-16/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz=80eae216bc5c3f77817d244f0d81cc13704894c1c7bde30c89b4f58b6049767f +dist/2024-10-16/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz=b8036aee8615786593f83c3e7808eac2a59ad44ae9f5959b9719fd475b3197b0 +dist/2024-10-16/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz=95ca16bf6931261a62f4a3637495c02450d34fd0a0ee8abe350881b9aa0bc773 +dist/2024-10-16/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz=df92b9f5ec3ea09c2cc48e4c91d41ecb1fa82db87180458b1e051bbceeb4efc2 +dist/2024-10-16/rust-std-beta-armv7-unknown-linux-ohos.tar.gz=26a4426464874411bf51cf0148569c9a110681632d228dc9c9d57fbe24292e93 +dist/2024-10-16/rust-std-beta-armv7-unknown-linux-ohos.tar.xz=70ee4948185aec3b556c963ba030abbb6424e09190e31afb11d063bc2ba21664 +dist/2024-10-16/rust-std-beta-armv7a-none-eabi.tar.gz=50c5b3d721cb5d83ab5f277c24eecbdbde32bdbc208bc0597830329fd19bf786 +dist/2024-10-16/rust-std-beta-armv7a-none-eabi.tar.xz=9add40fc1a971f135796a8020e3ecbc6ccfa657714cee2535866f2af38fcde97 +dist/2024-10-16/rust-std-beta-armv7r-none-eabi.tar.gz=d9e4695576a9f34e67804a636de6164fa7d381ac2193095cd2daa74fe148b748 +dist/2024-10-16/rust-std-beta-armv7r-none-eabi.tar.xz=6592a61388b53c3d3040245b8634715026f1e2a020a118edaf43f98839537aa3 +dist/2024-10-16/rust-std-beta-armv7r-none-eabihf.tar.gz=da24db2c8642e8273ef7d0e74fd32a1045ec99f5201b35d0116ba1818ab330d3 +dist/2024-10-16/rust-std-beta-armv7r-none-eabihf.tar.xz=75574d203e5e15973ce1e6e12a43d6b26825844382ef76b05c4dd568912fd16b +dist/2024-10-16/rust-std-beta-i586-pc-windows-msvc.tar.gz=2e4bab4042bac836ac40e07c36c6057273d6bffaf97b1b22a64cd0876d48895d +dist/2024-10-16/rust-std-beta-i586-pc-windows-msvc.tar.xz=f335988ba2ae2853c4c8928562fa6ed81a2bbd2bd5d09dbcebd7e64cbc7d458e +dist/2024-10-16/rust-std-beta-i586-unknown-linux-gnu.tar.gz=e96921c51d49ae28871286147d589bb59eec596826d1e0eeddd928f57ed4499f +dist/2024-10-16/rust-std-beta-i586-unknown-linux-gnu.tar.xz=c17d7cbbc6bb30899a1a94f74f380bb54878b927ebe58b31592f7adb64d7b5fb +dist/2024-10-16/rust-std-beta-i586-unknown-linux-musl.tar.gz=f9030f5b2ae0411349f1f4fabd00efa3e1117ca5dc5ba60fe87f33f94e51787b +dist/2024-10-16/rust-std-beta-i586-unknown-linux-musl.tar.xz=d45b9c7c6f8de53f99b550a6d673bf8ff29e507c60ef63271d7d5ac73c765e07 +dist/2024-10-16/rust-std-beta-i686-linux-android.tar.gz=2a6b9c893d2d8bbdb5900c4105fe54a988101c7d69f504e4d2983ba7aaadbbd4 +dist/2024-10-16/rust-std-beta-i686-linux-android.tar.xz=94c884a0cd03fe092bdfb6fe718fd335921a82c9c2887e0e68a13fe6a183a877 +dist/2024-10-16/rust-std-beta-i686-pc-windows-gnu.tar.gz=2d4a8b299987ab046536db276f3c4ea97413be5915189b9af085e4a4ba7b28ab +dist/2024-10-16/rust-std-beta-i686-pc-windows-gnu.tar.xz=eb60bf4d73fa45fe61730427287585939ff1a14efa8910877546818167b343cc +dist/2024-10-16/rust-std-beta-i686-pc-windows-gnullvm.tar.gz=ec0f11f5cce47e6ad288393dafaa69b27fc5207194e886f0a00b4e6c3a006164 +dist/2024-10-16/rust-std-beta-i686-pc-windows-gnullvm.tar.xz=10a5c127538bc9b951c62692ca4d626cd669919d5bb2236ef6112da28db028a5 +dist/2024-10-16/rust-std-beta-i686-pc-windows-msvc.tar.gz=7c9afcae592f5494ffd2baa95947b4fa5483c795e516852b463170e4797984cc +dist/2024-10-16/rust-std-beta-i686-pc-windows-msvc.tar.xz=ad9381999c1846c188d7264992c79faf413d675fdd70f22f25afcf84ed6e3b22 +dist/2024-10-16/rust-std-beta-i686-unknown-freebsd.tar.gz=9b4ea3de244aaf14b6759807444bb983ec5732b119faad1c9437eb2c02d407ed +dist/2024-10-16/rust-std-beta-i686-unknown-freebsd.tar.xz=88f975eff5146af6ae548e2d7be8d402ca3d6f470b6760b75e27dedcac9f70fb +dist/2024-10-16/rust-std-beta-i686-unknown-linux-gnu.tar.gz=8a8a255695d36a86ab32abe9f37f9f6f3e9b75eee75953486d82f186d8342180 +dist/2024-10-16/rust-std-beta-i686-unknown-linux-gnu.tar.xz=00a55b220767f3b692286bea728208bf665ea9a54869f82b31805b40ff56f763 +dist/2024-10-16/rust-std-beta-i686-unknown-linux-musl.tar.gz=96e838064bfdace0fcd5596c50714585a221a5116e2825aba448cc1f188d0edf +dist/2024-10-16/rust-std-beta-i686-unknown-linux-musl.tar.xz=78c5be28afda04d536a634a049c175b38d46309eb4b02126ba2cda3102b92d45 +dist/2024-10-16/rust-std-beta-i686-unknown-uefi.tar.gz=41a11092091b1f3b508f606978c0ac026e94614fe4b2207522b4f5f3d6c3262b +dist/2024-10-16/rust-std-beta-i686-unknown-uefi.tar.xz=a2250a5bb179549426ead55edaf3eba7626ee57a5e2c578057c3166348a47523 +dist/2024-10-16/rust-std-beta-loongarch64-unknown-linux-gnu.tar.gz=782998317c6c9cca107e84538ee166a37490b287efb437e5da9bf799178084b1 +dist/2024-10-16/rust-std-beta-loongarch64-unknown-linux-gnu.tar.xz=75b15b6d6db6f801a74419aa294b9537aa6e92b4d9d4c482e66aa6e319accee5 +dist/2024-10-16/rust-std-beta-loongarch64-unknown-linux-musl.tar.gz=003a9949067435194f6a9bc6ea742876d5894ade67b5831c111826aa8ba5c2d5 +dist/2024-10-16/rust-std-beta-loongarch64-unknown-linux-musl.tar.xz=5f1a4b6acfc1c82049c13ee2553ac20df016062feb368a54e44aead601105987 +dist/2024-10-16/rust-std-beta-loongarch64-unknown-none.tar.gz=f5e851d27f7017832de64c134727b7cd045495ed93fece21101c1e32b4c4c5e2 +dist/2024-10-16/rust-std-beta-loongarch64-unknown-none.tar.xz=289a56a0ee6087fbebed28a8d2110961c08889724d1a776a41094d5589cd112d +dist/2024-10-16/rust-std-beta-loongarch64-unknown-none-softfloat.tar.gz=86cc3aa69dd4b18fc8435b6f6c1c73a24dc0b031cd79f942f6bc20a11f093f67 +dist/2024-10-16/rust-std-beta-loongarch64-unknown-none-softfloat.tar.xz=3e29c510424862fbd96cf61e89b6f9d64cef3c0274dea125f4af2c2a84816f5d +dist/2024-10-16/rust-std-beta-nvptx64-nvidia-cuda.tar.gz=7506febb3ffaf1e763084d06a8dc9da096155c6a609a5c4c26feb993688f45f4 +dist/2024-10-16/rust-std-beta-nvptx64-nvidia-cuda.tar.xz=9c7e50509abfe5f0faa41eb526effa915e0799f59e5404e5a667c5f674a1ed18 +dist/2024-10-16/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz=6070daa8b4fc8bfb6c392767ac669a80067520c0fa85c923cb435c03a5ba6b9b +dist/2024-10-16/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz=32e4064ed11bc521f26e222897ca651704e41bd42df214eb618b6fffcb909b56 +dist/2024-10-16/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz=51a092e812baf52f5eb7100e433fc1d5ac7cd984f8062b7d960711b9b88f1431 +dist/2024-10-16/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz=444bcbf145d1aff19d8e2474191ee4ff0be738c7c3b1ded12e1a9bb35d700c2f +dist/2024-10-16/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz=9a4968669cb034ebdd0623f57f86a674df513abf6c01cbffce0d104447f0aacf +dist/2024-10-16/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz=11e478ed0cf115eaed256e9f0f64ab9f879ea0fb26b2f520a6388d3efe705422 +dist/2024-10-16/rust-std-beta-riscv32i-unknown-none-elf.tar.gz=0476e97436699b50ce459b3c38b55425b81864162639997bc14bce33fd7ea429 +dist/2024-10-16/rust-std-beta-riscv32i-unknown-none-elf.tar.xz=f76163c6963a7f1e29cc6a348b68e3c0659b739383273029eefac4d292280a3f +dist/2024-10-16/rust-std-beta-riscv32im-unknown-none-elf.tar.gz=f922ff15e927c047bed29d64534218d392bb584e12abdba09d9d9243613de3b4 +dist/2024-10-16/rust-std-beta-riscv32im-unknown-none-elf.tar.xz=0131845949fe27479123189bca11f2ff13aa14e0349c0901407cf65723271fad +dist/2024-10-16/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz=a7898b83bf49203172e6191cc720b6b184aca6cdbe44386278fab0e6c8ca4bca +dist/2024-10-16/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz=d5a4a03dfa52f732af211ae3ed3220fd76c5a2a6babada0bf94de3817e71cca9 +dist/2024-10-16/rust-std-beta-riscv32imafc-unknown-none-elf.tar.gz=c074043d065a85860d2f99b657035b87a1ee7fdcea53c557035a8da6fbba96ad +dist/2024-10-16/rust-std-beta-riscv32imafc-unknown-none-elf.tar.xz=9a02c6c4c5cf7c57942a89da30869d7bbe2b0f5bf7374b7dec868bb5f84e00f6 +dist/2024-10-16/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz=1c016db6ffad0ecc552025777b2d2df5a54d6ec3a215eb2b4af0f1ccc6e45f14 +dist/2024-10-16/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz=399d56e3525aeb354a0c9250f070a43a7426e185960db6d8b57484f47ad11a4d +dist/2024-10-16/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz=64f01a83583f4d025c95b3b2c09b86c4bae123c72a66a6a0995994d4226d34fa +dist/2024-10-16/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz=794cb971242dedc2926a6b56badeffd1b4aa4f1753a22a1228eda8f336c2a5c5 +dist/2024-10-16/rust-std-beta-riscv64gc-unknown-linux-musl.tar.gz=1eaa20562af0921066ae04c8e1d9191ecfc4f9816a721ad2797c47b58a343084 +dist/2024-10-16/rust-std-beta-riscv64gc-unknown-linux-musl.tar.xz=423b35248c797ea494e6462b4a9c16e49649f0105b06b16c6137799a82f0a401 +dist/2024-10-16/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz=38a31b095b74cb4b678ecd797ed768f4f9f967a201b79f21b059ef8a39fbd4f9 +dist/2024-10-16/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz=d7a53419a2f604102bda0d0b8ee9aba790082ccb0d63c31ff28be15f37ee87d6 +dist/2024-10-16/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz=0cbccec64f57ca0951fe678299cf17a7aec8bb2a8d71aa7fea1a26cd720b38ca +dist/2024-10-16/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz=aed7bcbb60aa5444ed8a8e1ccc7b74cc978b7e1646eb618a1899ebe61adf2c34 +dist/2024-10-16/rust-std-beta-s390x-unknown-linux-gnu.tar.gz=0cd68dad85a5cc084d8a0cddc275cd5e932e50cea18d3d622d03ecca068008e4 +dist/2024-10-16/rust-std-beta-s390x-unknown-linux-gnu.tar.xz=0873ae093594ae2d93f19003ded34d1d6d4884757e0a5a790d4766be4bd7622a +dist/2024-10-16/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz=ae70c9e9edd7d83776cdd0013e081d3b16dadb2a2504037b245acc82f104112f +dist/2024-10-16/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz=810c1346632064535769e8fb15ac207de45f06700e8cc9875b3971c44725a3df +dist/2024-10-16/rust-std-beta-sparcv9-sun-solaris.tar.gz=0538ccf4739439c52d6c7d99b573e7d8163a834a6163720829816d291e067217 +dist/2024-10-16/rust-std-beta-sparcv9-sun-solaris.tar.xz=8064bfdddb99ba6ff202ab92e3492bd2191ea11387b930a35fcde5ac7e341c29 +dist/2024-10-16/rust-std-beta-thumbv6m-none-eabi.tar.gz=a988938091594f39015783e78a334d72d41f5a3646a3da09fe7a7a0db7ec2662 +dist/2024-10-16/rust-std-beta-thumbv6m-none-eabi.tar.xz=0dbf287df801225c52d4dcbfd7afdfd5c1bb8410d9342885c092a4982a0d038b +dist/2024-10-16/rust-std-beta-thumbv7em-none-eabi.tar.gz=d5b46640810193ee163ef6cf3bb8d506b6844104c3d00c033d436d79ee790dcf +dist/2024-10-16/rust-std-beta-thumbv7em-none-eabi.tar.xz=f4e7ee83d5392e2496b9d3fc1e42b45d73be3b67e723a2e62f931c11a61480af +dist/2024-10-16/rust-std-beta-thumbv7em-none-eabihf.tar.gz=0fa0ba0ca7c4e73f8b9ff2800919484cad7d902cc5e704e5aa3adb742cf6a6a0 +dist/2024-10-16/rust-std-beta-thumbv7em-none-eabihf.tar.xz=ce3f3f3bc51cf79449df550b8c3fbcac588444b3234f379b93076034be6a40e7 +dist/2024-10-16/rust-std-beta-thumbv7m-none-eabi.tar.gz=3b2aee46d16f38cf43cdd3f3fab78df181bab6438cb012c2caa56fa097ad1402 +dist/2024-10-16/rust-std-beta-thumbv7m-none-eabi.tar.xz=3ee398b8497b7920f5d3cb18be2334ce440ec61b11e80c3ffb9eb1d898be45cc +dist/2024-10-16/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz=26a67116e52dc1fcf179dd226fc28e3e21f2d2b482330d254b5882502573ee6b +dist/2024-10-16/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz=d051ae1bc98060db4a2ca7fa3c3dfc6c3107632631edac41d553e4b192ccc2d3 +dist/2024-10-16/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz=dc34a8335b1a9dc077e38b4e4a8222d84340de604a6af547fa17bb142cd0c4da +dist/2024-10-16/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz=2d5c375d09bcaad6f983d4c4e0762532feb1d3706beacbf3a8d2e4fd75bf0c71 +dist/2024-10-16/rust-std-beta-thumbv8m.base-none-eabi.tar.gz=30c73a59d9138a542337fbb2be848a152172be272a25a1ad9a28f37510e35e94 +dist/2024-10-16/rust-std-beta-thumbv8m.base-none-eabi.tar.xz=467775974be97da92015790d49cb4f89d967ed1fd7846456b4b30e20f9585501 +dist/2024-10-16/rust-std-beta-thumbv8m.main-none-eabi.tar.gz=06db2989a00b1913822cec211225b0d37143dfe1e62d394c18c04954f7396ac0 +dist/2024-10-16/rust-std-beta-thumbv8m.main-none-eabi.tar.xz=65de9bf3cfc8ac6910953b2d3b2e9de532220f692519875e7da50a6493500fe5 +dist/2024-10-16/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz=26a6aec0f92b238c4d75c9eda3ecbb8bf0f1628ea5bdf52941e7b5ca398ec03a +dist/2024-10-16/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz=7a4b72ba1d507f418b30d7a110eb5e9025872e2398f0aa68abbef150f4c49ef1 +dist/2024-10-16/rust-std-beta-wasm32-unknown-emscripten.tar.gz=cf04dc8f1df723dbca4fa3a1155dc3bced6b3c96588bf41f6bcc196b74ae19cf +dist/2024-10-16/rust-std-beta-wasm32-unknown-emscripten.tar.xz=4fd17a62d10d27c13818cc3dbe1c62aa85d9c7123b88310d12cc40939010ec97 +dist/2024-10-16/rust-std-beta-wasm32-unknown-unknown.tar.gz=64ddae5e3e08ede16960f50595c4205de9962e0f5b8de9de5df1e9a8946bf66a +dist/2024-10-16/rust-std-beta-wasm32-unknown-unknown.tar.xz=0d6449807c02e1ef817fa2d378e77d9becd3a1560192bc9fdfad84cdee5cc8b3 +dist/2024-10-16/rust-std-beta-wasm32-wasi.tar.gz=c4ba753891162f604effac480ded4c536f294e39768f41d7b4fea1ab28c71be3 +dist/2024-10-16/rust-std-beta-wasm32-wasi.tar.xz=46a6f680f19ee2ddeb41e7aa13bb91a893ae27ae89ec41c36094f6e4db4a3e0d +dist/2024-10-16/rust-std-beta-wasm32-wasip1.tar.gz=3f89ca539044a79abd2b25f12d08ae954a7fcdcdf0288239c57d241b225776f9 +dist/2024-10-16/rust-std-beta-wasm32-wasip1.tar.xz=18a922eb41f5c907bfb624d18ca882dfd569f6775105dcdc29e7c7eb49187859 +dist/2024-10-16/rust-std-beta-wasm32-wasip1-threads.tar.gz=6dec5910a96e7a8e0713c109c993df44094e03fc8ac90b1a99f72dfdf84798f7 +dist/2024-10-16/rust-std-beta-wasm32-wasip1-threads.tar.xz=00e21ba70b0ee2760dcd51bf68f6be74c5cf38fc301476f406bf1f1d21ae7503 +dist/2024-10-16/rust-std-beta-wasm32-wasip2.tar.gz=c0b620ffb0debcd0f20155b1be250627450f14b4f62b32d9d9e4ee4c4e57cca7 +dist/2024-10-16/rust-std-beta-wasm32-wasip2.tar.xz=4d14c5de2f92b67c99e6fd2342d4ee968805d9eb68d4f9d1f549bb27e866f3b0 +dist/2024-10-16/rust-std-beta-x86_64-apple-darwin.tar.gz=b3ffba3cdef26174462e65847414458eba1c6aea63a78f6087497a04b427295b +dist/2024-10-16/rust-std-beta-x86_64-apple-darwin.tar.xz=1923ee9008ca30677642d1e66463555ba6fcee88dc0ed947e0ece7e4ce4efdd4 +dist/2024-10-16/rust-std-beta-x86_64-apple-ios.tar.gz=e8f1cd196c5e3b10a58f640cc8bdf3d015e1b23d49724112aaa7e4019cf01107 +dist/2024-10-16/rust-std-beta-x86_64-apple-ios.tar.xz=5fec3b22adc67fc6e4ef2cb873d446cb1520cfcee2ef4248e3dcc2816ada683e +dist/2024-10-16/rust-std-beta-x86_64-apple-ios-macabi.tar.gz=852e5067d47ac896c18e424cedcb984b0b4724b7fcd05e550151de2781603737 +dist/2024-10-16/rust-std-beta-x86_64-apple-ios-macabi.tar.xz=2333f02b870c6e7b673f5e8e166bf9166c3f6d1586daafa4eeb626d8de5b305e +dist/2024-10-16/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz=5c2bfde266aefa83ef9e65448900f4aa73e1d91de3719ada2512230a69090e2c +dist/2024-10-16/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz=218f4a4861812e38992bf261e390e95fbe67402f89827e6ac1b68fa42c705166 +dist/2024-10-16/rust-std-beta-x86_64-linux-android.tar.gz=5cd9859a22f77dffae58fb6573a8f5e23dc75bf030f54c152714777e5a01eef3 +dist/2024-10-16/rust-std-beta-x86_64-linux-android.tar.xz=be754bee393794ac427718b687f5e4aaf61aa1544795ed0da0b9d20e77e45803 +dist/2024-10-16/rust-std-beta-x86_64-pc-solaris.tar.gz=556f48c0ee8276bc847f3519dc0dfb72bd11cf27add709815da47f5cbb48716d +dist/2024-10-16/rust-std-beta-x86_64-pc-solaris.tar.xz=aa185610d66b606913d1102f62b62c5bbf9c5baf2e091d14d37c30b1526fb583 +dist/2024-10-16/rust-std-beta-x86_64-pc-windows-gnu.tar.gz=1a7dd15c91fb1597593b27dc0b72bc0b1a6e758935efae3c9db714cd624d7639 +dist/2024-10-16/rust-std-beta-x86_64-pc-windows-gnu.tar.xz=be18c0a1f2d0a1852c81ac1619a01d04d0c8c22472655710f643d86cb559508d +dist/2024-10-16/rust-std-beta-x86_64-pc-windows-gnullvm.tar.gz=e18f210cfe890af8285da5f99cc476770daa78cddb7f8213f7f26f66111e17ef +dist/2024-10-16/rust-std-beta-x86_64-pc-windows-gnullvm.tar.xz=b207877400dbfad09b6a3c2917516b63faa159f922ad03911736634ff46898d1 +dist/2024-10-16/rust-std-beta-x86_64-pc-windows-msvc.tar.gz=6f277d2e2e9a9057e2a2c8045c3949ab36ee8ed58b64829b10470e0c6b111671 +dist/2024-10-16/rust-std-beta-x86_64-pc-windows-msvc.tar.xz=51a102726ddf492dbc530437047fcb4d5e542dc4ace0e64da21c7ec79ebc001c +dist/2024-10-16/rust-std-beta-x86_64-unknown-freebsd.tar.gz=eeb6a46dd78fe3b477454c256ba8486b906e7a7ed044e686bd4f8c868265bd90 +dist/2024-10-16/rust-std-beta-x86_64-unknown-freebsd.tar.xz=67e103b9742ebf2798fe8e2647a6755a1d253301fea13a5193ced5bc394b9a0c +dist/2024-10-16/rust-std-beta-x86_64-unknown-fuchsia.tar.gz=b42fcd18458cff0ffa0902a0797e9b42cdf9475f5e84279972e4010608a14ba3 +dist/2024-10-16/rust-std-beta-x86_64-unknown-fuchsia.tar.xz=878e3950e0aefbd5c5c155f1ba2a4e8abebab10e3e77311403fc2c475e6da9df +dist/2024-10-16/rust-std-beta-x86_64-unknown-illumos.tar.gz=d72be5ca5fde3ac33da483058b8132707c93647652245864c988158e6dd70ca1 +dist/2024-10-16/rust-std-beta-x86_64-unknown-illumos.tar.xz=270959bb47366b7276717b677c5303ba0d579c9fd1f98fcf3774ce033caf0015 +dist/2024-10-16/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz=33370d376f3ecd80ddb5f614eef222c601e2df5dd18ae98ec034922790f56218 +dist/2024-10-16/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz=061a262fe98e6e1b41df6f9f60367259d44215f528938574098ede8698985c94 +dist/2024-10-16/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz=70328a15c8e29be07f248bb073336f06eba613c377ea4e98a1e0a4abe5e2eb6e +dist/2024-10-16/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz=ac389ebe5ca69cb382fd104161c9068bd8aa4d28960d578f2d925faafffb61da +dist/2024-10-16/rust-std-beta-x86_64-unknown-linux-musl.tar.gz=22d350bc0718b999d88e715cba73ef1860e1b1b8efac026f46d9050952d739b3 +dist/2024-10-16/rust-std-beta-x86_64-unknown-linux-musl.tar.xz=0761b9cb94210ee40fd0dbde38cd049a9e727a73da4ebc2cf10e5db92e6860de +dist/2024-10-16/rust-std-beta-x86_64-unknown-linux-ohos.tar.gz=35f975847adac17d19abba5385b951ce2015dd8b62ce4b0a716ac612808cc9d7 +dist/2024-10-16/rust-std-beta-x86_64-unknown-linux-ohos.tar.xz=5a9679805c1bdfa835aee94ed0d3ed4d2b4d0b6a8e2ec4471fcbcefd331cb200 +dist/2024-10-16/rust-std-beta-x86_64-unknown-netbsd.tar.gz=e4269be360d9823bccf6f7d71e4f51feeb8e955c7851d5bb6527055d709b68b7 +dist/2024-10-16/rust-std-beta-x86_64-unknown-netbsd.tar.xz=58880cc63fb93bbbb78fa4268eb69b37464b429de2f007abf05f5fd7c53aec8a +dist/2024-10-16/rust-std-beta-x86_64-unknown-none.tar.gz=42c77c14c433f43a092bef5ea0cfa60aea747301a9499c66bdd81d7998a74143 +dist/2024-10-16/rust-std-beta-x86_64-unknown-none.tar.xz=0cdfb3cf58d8f6db3bd65f4848aec8a431ffb4e1a5f79e56ceafe09849a96ac3 +dist/2024-10-16/rust-std-beta-x86_64-unknown-redox.tar.gz=35ba471138c115ac3e1ac3560fe8590038cb6002d22a45dd92f09a868270d223 +dist/2024-10-16/rust-std-beta-x86_64-unknown-redox.tar.xz=f250b60b52e2f84864406a0ef7e2f8896e1373f4f14f555a47a2019fd370f553 +dist/2024-10-16/rust-std-beta-x86_64-unknown-uefi.tar.gz=7332cbab92c48611604eb13ac025b845fd0dc0bfe838a4edb02f8266a5245aeb +dist/2024-10-16/rust-std-beta-x86_64-unknown-uefi.tar.xz=7cbef4955ee702d845116c59742194b1019d67f564145cf809ecec67245ca8af +dist/2024-10-16/cargo-beta-aarch64-apple-darwin.tar.gz=59321dd2f962c7b14514fdf1ec96907c16735a03a799479055f40f17883b8b6e +dist/2024-10-16/cargo-beta-aarch64-apple-darwin.tar.xz=336c7dff9f3a1d9de819a32f62eb518dd94d45ee591afb01d329127a2146c3fb +dist/2024-10-16/cargo-beta-aarch64-pc-windows-msvc.tar.gz=00c53e3a327909882282a32850c82e4aa18508a5e355532951d380e985b75c79 +dist/2024-10-16/cargo-beta-aarch64-pc-windows-msvc.tar.xz=39d09b49740b0512a84fd5351d473c5802de30721f621cf99ccd0178d8eebd60 +dist/2024-10-16/cargo-beta-aarch64-unknown-linux-gnu.tar.gz=dcb522627c49811d2e6eb133725e301089a4942da1347721ea28f2cdd670685a +dist/2024-10-16/cargo-beta-aarch64-unknown-linux-gnu.tar.xz=b9ce402bb130d35e482ee360f8f142726ff51bac3954aeed14800eef0bd96f6d +dist/2024-10-16/cargo-beta-aarch64-unknown-linux-musl.tar.gz=670c0b78cd5c985e6bacb2bb2cc3a5a2478c2623992c4cc35d0d4c624e1b4b16 +dist/2024-10-16/cargo-beta-aarch64-unknown-linux-musl.tar.xz=8a936c0c457a1d5c659611e7a69fe9934313d9ceea04c0a0eb393e28544ce7b1 +dist/2024-10-16/cargo-beta-arm-unknown-linux-gnueabi.tar.gz=10150caa2130a73443942f1dde7c849172b57b7b9e07e8939cd6c126c701d7d7 +dist/2024-10-16/cargo-beta-arm-unknown-linux-gnueabi.tar.xz=4dc0ffb898e66661a1b9844b965a0b0ca115bd6d9bb25fd5c5df022fdbeb56bf +dist/2024-10-16/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz=6db24d0a3eb7de6e3d40dceccf6a92ed86e170e0c4dd2ebc9702652655ad664b +dist/2024-10-16/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz=c5699a6a4ad49c34a77c94a4982b1a0ea7f6dea84d2771c24fdc05dfe9d4cdb4 +dist/2024-10-16/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz=f5621b39e7608e8461b559f3c3e57969e7eadce82798b395ba41e6302b2e0283 +dist/2024-10-16/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz=d7f62c0ac375f56d9ebbd0edbfaee4684d7d47ed8ad38bf7d25fb75a5770bdb1 +dist/2024-10-16/cargo-beta-i686-pc-windows-gnu.tar.gz=b895fa9240c3a6c089cde6b08a21408b5a6f38818c4a9cf25394b17e9610da96 +dist/2024-10-16/cargo-beta-i686-pc-windows-gnu.tar.xz=e26de92566339b932cdf4a4ee90464f1f3863d89534c03a3c9f9a632a278993d +dist/2024-10-16/cargo-beta-i686-pc-windows-msvc.tar.gz=ba64512c0732f5821ac4d1eb7fb53c0f340847c0cbc7dd5f88f67e03bc3f58ee +dist/2024-10-16/cargo-beta-i686-pc-windows-msvc.tar.xz=cf9872ad8ce5621faf517c2796620f24c1a99bccff7f328b7e7650e89e604b22 +dist/2024-10-16/cargo-beta-i686-unknown-linux-gnu.tar.gz=23496080baad6b976f8680b7f6c856461a410a4dce5c66a41cfa220d9479cd95 +dist/2024-10-16/cargo-beta-i686-unknown-linux-gnu.tar.xz=9799594bddbe1e04e1d625a6ead04efdd4749d4f0773585d21ba2be6636f0bee +dist/2024-10-16/cargo-beta-loongarch64-unknown-linux-gnu.tar.gz=5a1b95969f002c25717751337951aed39e6f6256ee58acce150d5ffaf0046300 +dist/2024-10-16/cargo-beta-loongarch64-unknown-linux-gnu.tar.xz=36bab05ec8b39c7e230ed78f64b2680ea21fa9f7997c980c22edde61c0799b5a +dist/2024-10-16/cargo-beta-loongarch64-unknown-linux-musl.tar.gz=19bfbd70b98c0bbbf29a0a796572d1661b8902132087173ca0e6aaadb4d51d09 +dist/2024-10-16/cargo-beta-loongarch64-unknown-linux-musl.tar.xz=629e42e188447a392bfc7cef5fe04c31380ee30523dc0bc33b0f3c02bd2fd82c +dist/2024-10-16/cargo-beta-powerpc-unknown-linux-gnu.tar.gz=5d8b1daa253ebe0750e6f073b8367b053de09b4f209327d4114bfa60b2bb5602 +dist/2024-10-16/cargo-beta-powerpc-unknown-linux-gnu.tar.xz=545d7ad3b7b0b5d2ec0b4bb70b7e31dd823048d6087d6c3fa2139f307ea35fbb +dist/2024-10-16/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz=2111cbc7586a1e58dc7e6e54a63157f9606f5586c7bb72ffa15f1a94284d4c97 +dist/2024-10-16/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz=0d6702d3ec5a6aa9dfb06d565e4e16b27cd3d445871bf2344c876d7ffe2f8a32 +dist/2024-10-16/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz=0f750831b518b452a2ac17c9bab3a02f30f58bba6ffcd962eed06012102c7b31 +dist/2024-10-16/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz=6d476e16109e9bc5dd055c537a9382ce154d2837a32bc2c165a1aec76ba1ba43 +dist/2024-10-16/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz=850bbca95670afa1262b5d46bb02f0bb367c83f851bc2a9817f8bf2eda9bd2ef +dist/2024-10-16/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz=f42b3b5cb506886bcfc92c0a7f3dd3d0668bdda0f2db657b98becb4c0e99bfd1 +dist/2024-10-16/cargo-beta-s390x-unknown-linux-gnu.tar.gz=f3a8541b3e6c12f350fcfbf43a8efb2a8bb48a62e055d9dc522d568b94476f43 +dist/2024-10-16/cargo-beta-s390x-unknown-linux-gnu.tar.xz=12c5411791c715562c99dd211095c9924142053d510e17e6ec50b7b8b927eda1 +dist/2024-10-16/cargo-beta-x86_64-apple-darwin.tar.gz=95885bfcf5fc1de80d0f9b5415dd261136d5577b7d61716c184a6c6379acca21 +dist/2024-10-16/cargo-beta-x86_64-apple-darwin.tar.xz=881c9d88bf2a848f5b5cd61d18068e2dda3542a65e93ab373e3a047cc30369d2 +dist/2024-10-16/cargo-beta-x86_64-pc-windows-gnu.tar.gz=c04ca1768c5925d5c7e19d5f232adbda355469974b19a2a130a6967db94b56c3 +dist/2024-10-16/cargo-beta-x86_64-pc-windows-gnu.tar.xz=bc02593e98f5393ce2032fb605ec2bc053a1a19311a5a80d27c3a552ec8b968b +dist/2024-10-16/cargo-beta-x86_64-pc-windows-msvc.tar.gz=8ffb930c33ad454806f2f61a10949a3fa5b92b9313454927dbd76928955ed7f2 +dist/2024-10-16/cargo-beta-x86_64-pc-windows-msvc.tar.xz=ef0bbe8512b3dc9bdc9f3a47abf2834bcde1fd7f59e319f7c7040b7100ba1f8a +dist/2024-10-16/cargo-beta-x86_64-unknown-freebsd.tar.gz=eb21f7739dbd7c120dc9552360e8aa6e1e0eee14d80ea16e3dcecb9e94efe7c0 +dist/2024-10-16/cargo-beta-x86_64-unknown-freebsd.tar.xz=9e287f3d0c7e402dbc121cd737fd2360dfcd97fa886770aae93c07474494bb77 +dist/2024-10-16/cargo-beta-x86_64-unknown-illumos.tar.gz=1cb86b6953ec99e95d92d61ead263021d16921cfe6152b6331efb838c46be85c +dist/2024-10-16/cargo-beta-x86_64-unknown-illumos.tar.xz=c356e671ca97dcb4d945567e33f06911d5269fdebc19fe83a9313f574d446576 +dist/2024-10-16/cargo-beta-x86_64-unknown-linux-gnu.tar.gz=7613e679837e2769b9e8df5b8785fdb7e51665379e64547bae9d6015eb8e45c0 +dist/2024-10-16/cargo-beta-x86_64-unknown-linux-gnu.tar.xz=39ae7207f84ee3da16ee11271070e8b82d2991cde29771d5154bb2957d9beccc +dist/2024-10-16/cargo-beta-x86_64-unknown-linux-musl.tar.gz=4dfaa69f4377bb724eb7d1990aea7ac219a960b690601769f8e06b72f59f86b4 +dist/2024-10-16/cargo-beta-x86_64-unknown-linux-musl.tar.xz=4cf72f3f0048e8cfb2b05566cbc1d76e9730cf1f71f9d0f3a71bd9379f30b08c +dist/2024-10-16/cargo-beta-x86_64-unknown-netbsd.tar.gz=e1d3ff748dcf1777bc2d999ec82f0b8a67295f91a9cb07a9c1123cd5424928c3 +dist/2024-10-16/cargo-beta-x86_64-unknown-netbsd.tar.xz=7e21e89e218118d536d489d16e77e667df7ba7c809135ba179e7097a2243df5d +dist/2024-10-16/clippy-beta-aarch64-apple-darwin.tar.gz=244ed83cac923e00647cdd3aab9d0479cf420991e9e06eee5ffd8acc9e5a199e +dist/2024-10-16/clippy-beta-aarch64-apple-darwin.tar.xz=6dd93a671fca0efb2d3b8cc461aba66483624327a382fd714a526832034c8438 +dist/2024-10-16/clippy-beta-aarch64-pc-windows-msvc.tar.gz=56710fa9c7d46fb881903e08e407c258e3ffc75ce3de0226dcdc3709dc59180e +dist/2024-10-16/clippy-beta-aarch64-pc-windows-msvc.tar.xz=6ee782709786c310fb1e887cc576e7e61b0a4b120f6a46c7dea1e2f2bf7dad1d +dist/2024-10-16/clippy-beta-aarch64-unknown-linux-gnu.tar.gz=06f0ee2195349921d1ae791fa1628fceaa7adb377968fa09dbe17aa77c762a47 +dist/2024-10-16/clippy-beta-aarch64-unknown-linux-gnu.tar.xz=6e792e91db8b54e0cfb9eaed8187b5202ac5d5735ed0f73080a6a73bf15ce683 +dist/2024-10-16/clippy-beta-aarch64-unknown-linux-musl.tar.gz=bde52962b121472cd1b755c506b9362ff88ec582cb3fe9d307948c51f4d96f1c +dist/2024-10-16/clippy-beta-aarch64-unknown-linux-musl.tar.xz=70a06d5b8175d078bd246adf45f3058d362f0b128f1dc11d3797840b28692bf5 +dist/2024-10-16/clippy-beta-arm-unknown-linux-gnueabi.tar.gz=ab8b54d8436dbc6af279a048d2b75eea9eabfa369f23c51fc1c47388f642a755 +dist/2024-10-16/clippy-beta-arm-unknown-linux-gnueabi.tar.xz=a2715009144defc9aea3ff0d6a15485d8feedd37b333658470d479600fe87ffd +dist/2024-10-16/clippy-beta-arm-unknown-linux-gnueabihf.tar.gz=a1863b47208051a231f9571bdac3628d8afdfca7eac3b1cb7a04a843c176ae80 +dist/2024-10-16/clippy-beta-arm-unknown-linux-gnueabihf.tar.xz=a5926e8e3e2867a8fa87db77dc26bd18734f84a4a685374dda07d50d21068f62 +dist/2024-10-16/clippy-beta-armv7-unknown-linux-gnueabihf.tar.gz=f70eabd386aac93c676485bd42845e62b34c034b8710bf0db24a440c03b15bce +dist/2024-10-16/clippy-beta-armv7-unknown-linux-gnueabihf.tar.xz=cfde41ebe7398d0858bf507b9322c5f4959becd5a3a4624027b4bf3321730a29 +dist/2024-10-16/clippy-beta-i686-pc-windows-gnu.tar.gz=3d988126d6a0ed9133b73b8aea3b16d6355db8ad83254a7499f7dc3b414d62f8 +dist/2024-10-16/clippy-beta-i686-pc-windows-gnu.tar.xz=6efe88aab2daa0c7df17bbb449c2b815e085ca7e859b17bb578978d18ca2ea04 +dist/2024-10-16/clippy-beta-i686-pc-windows-msvc.tar.gz=2c2eb32ebe3ec89a985c07ce87cc1dbc627f5f8588aeac72fd381c6e19034095 +dist/2024-10-16/clippy-beta-i686-pc-windows-msvc.tar.xz=fe2d2ae70e0ce102794450d4259b706d3bda2c5b05bd21a863b2ecd8ed54274b +dist/2024-10-16/clippy-beta-i686-unknown-linux-gnu.tar.gz=0d633381b174f04523f13cc574e79af5041a231aa61b0befc406c7e3ccb0ebf3 +dist/2024-10-16/clippy-beta-i686-unknown-linux-gnu.tar.xz=029558aecdd4862dc74ce9726a462f1d34a7e2a6eda5bf791995dfd6933096e7 +dist/2024-10-16/clippy-beta-loongarch64-unknown-linux-gnu.tar.gz=2bdaa7f730f30db62ed0661f135227c54249786a78a8022428ead03766c9e29b +dist/2024-10-16/clippy-beta-loongarch64-unknown-linux-gnu.tar.xz=2a4f5982eac9cb5e8372d35c13a7832d532a31e5c38d13b0643d16832e1e341e +dist/2024-10-16/clippy-beta-loongarch64-unknown-linux-musl.tar.gz=a9a1fc5b74e19a567c45ce1789c7bfd50b28774bca8320886108e4a18a1d7765 +dist/2024-10-16/clippy-beta-loongarch64-unknown-linux-musl.tar.xz=9e957652f80b2de14c5a8f5faaa5662d0ebd26e18b2bc5d248587d72413e483b +dist/2024-10-16/clippy-beta-powerpc-unknown-linux-gnu.tar.gz=a9fa9caea0f784ed096b3ff204a8261126102e05456c52d544c7036f9ee30c41 +dist/2024-10-16/clippy-beta-powerpc-unknown-linux-gnu.tar.xz=0e3d3472e3e73b02aca8797ecaa2471e472d361b0c44126e4bfc2d25a8fad96c +dist/2024-10-16/clippy-beta-powerpc64-unknown-linux-gnu.tar.gz=211c52eed69942aed1e6b1fb4799232ea4fd3f898a44a4bb6343336e89dfec74 +dist/2024-10-16/clippy-beta-powerpc64-unknown-linux-gnu.tar.xz=8c07b34223e465e17094b7e20efdbf8ec6ef5aa042485d3cfbc6ef58dbca0be9 +dist/2024-10-16/clippy-beta-powerpc64le-unknown-linux-gnu.tar.gz=b3fc3cc6e81ef118eada3c01fc3535dfc622b92377d8e735f80d7661b4b847fb +dist/2024-10-16/clippy-beta-powerpc64le-unknown-linux-gnu.tar.xz=e885c534589fac79046bb31b92aefe7674dee13c8df1a456e91ca63e9d92c6d5 +dist/2024-10-16/clippy-beta-riscv64gc-unknown-linux-gnu.tar.gz=fcfbf29d105ade4a6d7537dc44d01c6de2de70d066afd8ac3af58bf3bcb6f7d0 +dist/2024-10-16/clippy-beta-riscv64gc-unknown-linux-gnu.tar.xz=a5425df8cd724fd992de26434090e157e9d148d063161bfb43789d6b4234ad02 +dist/2024-10-16/clippy-beta-s390x-unknown-linux-gnu.tar.gz=ab96fc1c538a9a526124bc2cf3e97edd655f29f8d6d310b3b5f017cfbe6311e3 +dist/2024-10-16/clippy-beta-s390x-unknown-linux-gnu.tar.xz=096de4e9f80f40a294dfd1ba32e9de038c3449b2760189a5c9e46cf8e36dc0d6 +dist/2024-10-16/clippy-beta-x86_64-apple-darwin.tar.gz=5614651ef2acd5ce1d43cc2504d353e471d9c8c425c16e3649f81e1cef44b86f +dist/2024-10-16/clippy-beta-x86_64-apple-darwin.tar.xz=26e39442af2251c52bcd275c7ae25a88211ec2f582bbe7a29724f816768c9781 +dist/2024-10-16/clippy-beta-x86_64-pc-windows-gnu.tar.gz=b2626513cbcd9b1456dce8543c2b11458eb052434f9ca84a6e926a77e5be2362 +dist/2024-10-16/clippy-beta-x86_64-pc-windows-gnu.tar.xz=87403c11e1b92bbbc2651183b2b480c41d9c7e0fa6f08551702c6ab308fbbf5e +dist/2024-10-16/clippy-beta-x86_64-pc-windows-msvc.tar.gz=929029e67d34bc813061c524490b8f0030d31097fc1fd439acd4d8c3545589a1 +dist/2024-10-16/clippy-beta-x86_64-pc-windows-msvc.tar.xz=1584df60f086c6af01f06023236f612bf59be9d5b991bd09ed66f4c505737533 +dist/2024-10-16/clippy-beta-x86_64-unknown-freebsd.tar.gz=d5ee8cfefbf164d33529f1a777437f49216e93173a2ac04b605e74fea89fc6a3 +dist/2024-10-16/clippy-beta-x86_64-unknown-freebsd.tar.xz=9469aead14fc03ebe984e51bbee0db6d1cd8e877b67ca361c44939e2464a95fe +dist/2024-10-16/clippy-beta-x86_64-unknown-illumos.tar.gz=79bd918b2a391cbeb885b7075b1e0534054c81784c332a2aa8539d0e1cd15f69 +dist/2024-10-16/clippy-beta-x86_64-unknown-illumos.tar.xz=16b808026a4fdfaa85a4ac01b01b4fc79c4824a651bd4e412e4ee9b0011eca4c +dist/2024-10-16/clippy-beta-x86_64-unknown-linux-gnu.tar.gz=62224af7a1831140fc3f06e7e918191e9443751549ec5c96afdcb3ffb5b18e06 +dist/2024-10-16/clippy-beta-x86_64-unknown-linux-gnu.tar.xz=78bab115fa696fc95d911655575032fc9af324c8b6df136044f11681239e5c41 +dist/2024-10-16/clippy-beta-x86_64-unknown-linux-musl.tar.gz=1a76ea2b1596acd396585d78d01be5d3b795641d7b20f84379cd2c344e7536e9 +dist/2024-10-16/clippy-beta-x86_64-unknown-linux-musl.tar.xz=63ac980b41b0a3b744d94727af6ee1679b8bc4c50db4ef68402d0253b1852ffb +dist/2024-10-16/clippy-beta-x86_64-unknown-netbsd.tar.gz=eba61354aecfea64815a68b569122e029501d85876d37f5ea4119f36f932e146 +dist/2024-10-16/clippy-beta-x86_64-unknown-netbsd.tar.xz=37f9395e78a2bf2977b38929b9511e9668f26e23705d025609f028b282aeaee2 +dist/2024-10-16/rustfmt-nightly-aarch64-apple-darwin.tar.gz=05cc308cd0c35063b43a45dab3e84001e2d580b10431c74899a86cd8971e5b36 +dist/2024-10-16/rustfmt-nightly-aarch64-apple-darwin.tar.xz=aede50889786bc1e902162b9347cf59ee67b15e902b0ed78d7187d3c24a7c4a0 +dist/2024-10-16/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz=1c25ee283dbc720b471d435ed952e6d794ecacafd4c889a2ad8d43725cba8ded +dist/2024-10-16/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz=67602978481a53b0b4681523d94bf79ad731a369cc088c3b0adf8e7d54b1fbce +dist/2024-10-16/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz=ed7c9c38071f9d1e632104ff1d9a9407efec99d74eabd127db795c56e84b9d73 +dist/2024-10-16/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz=65ee60bfefa1334cece9f5da72789d90b4b5918e7afea2b47aa4d1450d9a1237 +dist/2024-10-16/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz=e92d5ddf80c94bdc34697bec4d7a1b1ea677e5fc6c68c41059a7829e53e95505 +dist/2024-10-16/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz=2f1737178817318d1543deabd865aa83a1f395a36cc83e3717157b4dad827f22 +dist/2024-10-16/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz=a4be0eb92a011ed940db67973d5fb62c4b5d3fdd52a08981223c5fa5278826b5 +dist/2024-10-16/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz=a47b2dab4f20f53e6c29fbce06383144a67ece61a63f33c3fb86beaabfe4bce5 +dist/2024-10-16/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz=7bfef0a8b7cb4a905ad145311c320a8ccb2048e806ef68688a1423009770b35a +dist/2024-10-16/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz=d944161b92bdd74f3ba533b94b67a3a361a01b82fa5c156710608f00c46913ec +dist/2024-10-16/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz=46a46ad32e2829550e301a84212f057faf21bf67ff6862f77f11cb0e13f80453 +dist/2024-10-16/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz=d917336a949ad5a5f0fcfe1ef261d87d4dcbde22b467258543c50715a9041d64 +dist/2024-10-16/rustfmt-nightly-i686-pc-windows-gnu.tar.gz=38a9cd401774ff1d832e536ed0aca9a3f0d5593814bd6db9ba4f8341a5545fd3 +dist/2024-10-16/rustfmt-nightly-i686-pc-windows-gnu.tar.xz=fa2194663d11d517bbd67c157fc40cf67149246c391e9b8adf0a46c2eb96c860 +dist/2024-10-16/rustfmt-nightly-i686-pc-windows-msvc.tar.gz=c5271c244d8055401d3d3a97873064b93915dbcc52108cb9b61381af1ebe99ad +dist/2024-10-16/rustfmt-nightly-i686-pc-windows-msvc.tar.xz=56c6a0cedf3ec4667d65a209477cfe0d395e534654b49e28efbd3836e8a0dae7 +dist/2024-10-16/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz=c4325b80bfc63dc58c4632ede188efdc94aa4cad49abfa4e57d81faad673a35c +dist/2024-10-16/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz=35b4fba91cad3bf9e627d59baf1f1864e30d002b05696c61498e73fd0e0f299f +dist/2024-10-16/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.gz=b2f856cc81be2c6f2c4250ec88cbab0a51c3d59e73fefd66cae9b1a91a32b0bb +dist/2024-10-16/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.xz=1b1a40377a8a13b74f62f5bb382cb8056930c543b97261d32613c53826c758da +dist/2024-10-16/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.gz=98b1f0fc4f45eae47a6cae7e7d4d9734979d8f860c7c96da281fa1d9ed3ca39f +dist/2024-10-16/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.xz=bae7dbd1342d5aa89c335f1dcdac0d93f5cd8198ce9f869ef4c32dba8bc6c0d7 +dist/2024-10-16/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz=cb5dc166002aba8a95f7e10d2d9e93a66d51483540c7e733b528bfccdbc74d9f +dist/2024-10-16/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz=c070a48d0aad7ce42cfe5eba9477a0f54a9e04c9ec5c770e91bd2db55d0d764a +dist/2024-10-16/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz=424c0d9a047ac228cfed286d0a2936b857e1c575ddebd931ca634e0501c125da +dist/2024-10-16/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz=b067b3d095a5b53191ff148d0e89baed0b53c2099142d885961220548b904c52 +dist/2024-10-16/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz=01acab58a327ee34d100e67a4a40a9efb66a64d478d6bcaaf94ce35874296c42 +dist/2024-10-16/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz=c1a715f7502ef54a236d4ebe15488ec4c1c5cc5b1c50eea416a5b9c57de66f53 +dist/2024-10-16/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz=cb014573a52f2d6776e47f3f728ae1e8b05feac2274c5916b1545675e658fc15 +dist/2024-10-16/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz=5abf6bf36bcb57c0492e9bb4953ef78a61acf347d20ab788b4b31da44ae3bd39 +dist/2024-10-16/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz=0bee2c4ea3f8ba07c189f7e2e0df1b2627b7bb638823fde2839d46a353e0480a +dist/2024-10-16/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz=df352612d69dff13b59da185581a48062e54ee07161b1fe205b92d0687a4e896 +dist/2024-10-16/rustfmt-nightly-x86_64-apple-darwin.tar.gz=b7b44f5fb37fac58a83c2220a68c251513fcca96c51a71b189152a78cf095cf9 +dist/2024-10-16/rustfmt-nightly-x86_64-apple-darwin.tar.xz=f5876f1d8181880e4ecb71eaa2477b0431dd0bbb45e6a4da8f20bc31426cb43d +dist/2024-10-16/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz=cae33e30d7b2e5589a6fe681345f6edbf406aa803d0d521ea182a575ee32dca2 +dist/2024-10-16/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz=21324d7c6949bd12c841db8904d9485dd709f8c324e7aea31f2a9eb2a32844c0 +dist/2024-10-16/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz=cfccffb90721492cc79212ba49dd88361c6d38eab24ca4fbfd8110c2eefea001 +dist/2024-10-16/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz=05c528e683c40467ed3911ec5f852914e117fd71e8a0826f17d91295d4f1b047 +dist/2024-10-16/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz=97cd5e773bfebd3e1d78dc3d486a75b969e30f1dd0311d07c337440d275d0443 +dist/2024-10-16/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz=19989c6e9ce4d67e068d449b92dfedd8e07bd1a287cee0410f43aa43432346f9 +dist/2024-10-16/rustfmt-nightly-x86_64-unknown-illumos.tar.gz=c3d8ed4650b4f7902a8643bfee849926892aea2e664400b858f61000966042cd +dist/2024-10-16/rustfmt-nightly-x86_64-unknown-illumos.tar.xz=6b0dce2bb77036d154d15ffb2495480ed8c8cc441dc8979b4fd767af80e0736d +dist/2024-10-16/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz=de7b427a783d588a778a2301a1bf8e4fec076ede2006e275f45d82a87e965feb +dist/2024-10-16/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz=43fdb72c7e74c86eedbb01631ec357c2cf469512c0c591d15f35f747bcfbbd30 +dist/2024-10-16/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz=3fccaaf7106f47302eb3c489dd722a91727e25351278a17f81d06fbb4cd4041d +dist/2024-10-16/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz=988d6c342a4561790d1024455be643e17525ae07e02fe5238fc61d00c91d3cd6 +dist/2024-10-16/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz=71c10377a84b3bd612a83cd2822bc6c0eb4a540c681114d63be368da84ef3766 +dist/2024-10-16/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz=1e6a3c7080334663ef6fe246eae3482a05446b83c8a0c659084ca8186b9cab01 +dist/2024-10-16/rustc-nightly-aarch64-apple-darwin.tar.gz=e68c96b5d6fc204944cd1bfd80e2c6a8332dedede98a968e170fa657e012ec1f +dist/2024-10-16/rustc-nightly-aarch64-apple-darwin.tar.xz=9f7138fecf991a17483e0359c7a5a0b4292cffeafdd4b52b7c1021cbf993ec5c +dist/2024-10-16/rustc-nightly-aarch64-pc-windows-msvc.tar.gz=0f31c36e6b6b765e9814dd193861e2ae2a176160f22aaff6211a6da3efbc1fd0 +dist/2024-10-16/rustc-nightly-aarch64-pc-windows-msvc.tar.xz=ab4cbc70a6002bdba2955fbbdd99f03d3e54d14d32bd2f7250be6a323f39dfd9 +dist/2024-10-16/rustc-nightly-aarch64-unknown-linux-gnu.tar.gz=e088594f42b88494401df68cc60b8d94a4c1199e3549aa6dffd513b0c5f7508a +dist/2024-10-16/rustc-nightly-aarch64-unknown-linux-gnu.tar.xz=a204d11814dfb6a3283ed84abf8b88492283eb6cfbec018a0f249d496e2db5f1 +dist/2024-10-16/rustc-nightly-aarch64-unknown-linux-musl.tar.gz=802ae62e1023c460739670a12b8a331637cec02aec14769bf0bbdbad44217555 +dist/2024-10-16/rustc-nightly-aarch64-unknown-linux-musl.tar.xz=9ab24e33a80a442a540720377855710c2b33617531daa625dff537d1251bb9b4 +dist/2024-10-16/rustc-nightly-arm-unknown-linux-gnueabi.tar.gz=08a139d7e1ad8559d3add81416581984d24eb997f5d03f2ea85a76eac62df57e +dist/2024-10-16/rustc-nightly-arm-unknown-linux-gnueabi.tar.xz=dc9dface28b81a1b241a6ad034cd910221866cff7188d94929bd80e3d2dc1598 +dist/2024-10-16/rustc-nightly-arm-unknown-linux-gnueabihf.tar.gz=ecfb3225d805cb7faeb185e43471b35decc735c1330bcb45d54cbb93fac0db4f +dist/2024-10-16/rustc-nightly-arm-unknown-linux-gnueabihf.tar.xz=60437f2b7cd51cebff36687bc904c7493ef834e39033c08e35883b3de03ed15f +dist/2024-10-16/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.gz=aab495b49ad218fbaf6f36e0dc82ae76dd867ca77411568f15039e494154d890 +dist/2024-10-16/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.xz=51648f6d14e8684c3f258ede3e97371c1530be584b5bc47a92b7bce84d70b397 +dist/2024-10-16/rustc-nightly-i686-pc-windows-gnu.tar.gz=6bf818c20105a30461336053b40b9b298388b341766536137a3fd6039e7885ad +dist/2024-10-16/rustc-nightly-i686-pc-windows-gnu.tar.xz=60346687b8359a3df7bc4d7beb5532be716bb699fe8aec76664b5b5b4d7cacfc +dist/2024-10-16/rustc-nightly-i686-pc-windows-msvc.tar.gz=48b542959792f1cb4c316ee417fec68ccab0ee76a68accbe667fc56ca9d5a367 +dist/2024-10-16/rustc-nightly-i686-pc-windows-msvc.tar.xz=b83ebe192f8e2d82fdb0765952e69e4234f11fd6a0a4a69d089b2df42a3c637f +dist/2024-10-16/rustc-nightly-i686-unknown-linux-gnu.tar.gz=03b36beaf28462424b3b70e6a944d24a22a551c4fd9c245cfd5eef464047ec30 +dist/2024-10-16/rustc-nightly-i686-unknown-linux-gnu.tar.xz=e00e81bfca624087f97ae2ff675adf08a72519240e31cfaf0f4da238d7be8050 +dist/2024-10-16/rustc-nightly-loongarch64-unknown-linux-gnu.tar.gz=f71e27157be06043624ebb769cffc92593d4db6d2a9edabec6815d0f9be64b9f +dist/2024-10-16/rustc-nightly-loongarch64-unknown-linux-gnu.tar.xz=5bd77608b891be20b38739d2b1cd4319feeb13f92214e550a01c599349fd6ce2 +dist/2024-10-16/rustc-nightly-loongarch64-unknown-linux-musl.tar.gz=0cda1b3a287843431991468cf8dea7a34221d42153e9421ed89a8f58d048e01b +dist/2024-10-16/rustc-nightly-loongarch64-unknown-linux-musl.tar.xz=57f3a4d73a40ffe0dad530334f2e584c1279ce3b81458023f034bf8c35dc6641 +dist/2024-10-16/rustc-nightly-powerpc-unknown-linux-gnu.tar.gz=5d7c5164b12ad921f1d8461d0edeb17566bf4d5861d6b0f18f66ac1a91b7306d +dist/2024-10-16/rustc-nightly-powerpc-unknown-linux-gnu.tar.xz=8ba849b777182977ad9b87c002bff49ff9ad2007932abab98509e96274b9c7d9 +dist/2024-10-16/rustc-nightly-powerpc64-unknown-linux-gnu.tar.gz=03c12e5d01a6f0b66dfd728610fc0df2f3bef8d5cf418a4d5a385b11f35ecd81 +dist/2024-10-16/rustc-nightly-powerpc64-unknown-linux-gnu.tar.xz=db0b2d5a9a12c9c8aa0d5d3a320ef8f815ea2ac84718e1bbe94514e7480db6b5 +dist/2024-10-16/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.gz=2e3a85da6e7a74b079a5bbbbcd433e0271b89b873aec22c19537669bd908a98c +dist/2024-10-16/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.xz=2b19af7ec21a9e442975b073455e4b3a2711832f6f4a521335034f47dd7725e3 +dist/2024-10-16/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.gz=c293489afe56e4ab984bab7c0ea8db292464b1b0a83b3efac3d38079f71303b2 +dist/2024-10-16/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.xz=fad8d9fce164461c81c5fca56c3557e76635f70ad755cfdb1a448faf161a6b02 +dist/2024-10-16/rustc-nightly-s390x-unknown-linux-gnu.tar.gz=1a4d7fb7e5d74649270e79fcdd5b7686bf3db6985d3a781ebb1f069404639884 +dist/2024-10-16/rustc-nightly-s390x-unknown-linux-gnu.tar.xz=cb1ca19ca8a99b68a1665937c2bfde2a275ff2746cd8b50e097202352a0f7cba +dist/2024-10-16/rustc-nightly-x86_64-apple-darwin.tar.gz=32d6c59ee1bb8d1449393b37ae9399d24ecbfcaa6dc5831ad2bdfb3a586c8ab9 +dist/2024-10-16/rustc-nightly-x86_64-apple-darwin.tar.xz=5a9237c1b359da2c6aac0d6c9202f527d5982310477c414c3c03c6eee50feaf3 +dist/2024-10-16/rustc-nightly-x86_64-pc-windows-gnu.tar.gz=9b03ad10b3e5de01a813fd9be676135de072de0d3fe6db63e82ff881b9d81c51 +dist/2024-10-16/rustc-nightly-x86_64-pc-windows-gnu.tar.xz=1e7b91da95fa7fba74c4f8937fc9e02b592c4a66260aab1a4feca24e136501e3 +dist/2024-10-16/rustc-nightly-x86_64-pc-windows-msvc.tar.gz=59efe9285d460cf8080d3aaed31742cc7ae5dffebb9bdd3410be22a061fa8dc0 +dist/2024-10-16/rustc-nightly-x86_64-pc-windows-msvc.tar.xz=e64edab835454e2024081b9c447798075cc2df3703a8b627d9661c32233c8540 +dist/2024-10-16/rustc-nightly-x86_64-unknown-freebsd.tar.gz=c1ceabe8ad4f89b401a72a6a02843a5f31267cb9762d1a8c30dbcb51c1967488 +dist/2024-10-16/rustc-nightly-x86_64-unknown-freebsd.tar.xz=456708749343846153490593eebc55d78ae347d0a1096d0fdbea19c99aa24d9e +dist/2024-10-16/rustc-nightly-x86_64-unknown-illumos.tar.gz=e01be583da5371501755ca0f6d44cd2abef40543d7d97448933e27ba0de78c8e +dist/2024-10-16/rustc-nightly-x86_64-unknown-illumos.tar.xz=42dca4d9e7d76109a3c963b5783554d6ce0171001d744f3fa6b5001bc6ad66a1 +dist/2024-10-16/rustc-nightly-x86_64-unknown-linux-gnu.tar.gz=4464cc28f6a15d5a2a1de098f28224848d0b91779bb70ace3106f3a6208d25dd +dist/2024-10-16/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz=5f9b9cf42730255c27bef5187241736693b5e39de9fde935da25c9f33deb4325 +dist/2024-10-16/rustc-nightly-x86_64-unknown-linux-musl.tar.gz=d6c2b41d4fff28d12b254d3cdab480ac4a81054e50794b6cfb7ed30065cad5a1 +dist/2024-10-16/rustc-nightly-x86_64-unknown-linux-musl.tar.xz=1acfe2f78ff7aa747e5b307b40ff5a8be5e8076897b78b2fb5828d1bb1d74cf1 +dist/2024-10-16/rustc-nightly-x86_64-unknown-netbsd.tar.gz=9d5bfab5bfb9e6d627a5acd1f54fb164538e84c449aa3ea15841636257ec7ab4 +dist/2024-10-16/rustc-nightly-x86_64-unknown-netbsd.tar.xz=dddd1663a821d99ea19864435e1c7daed6bcb4fd914e6b79c94d644836bc8d1a \ No newline at end of file From acb09bf741ba439356e824dd10a07054c6656fb6 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Mon, 14 Oct 2024 14:46:44 -0700 Subject: [PATCH 343/357] update bootstrap configs --- compiler/rustc_const_eval/src/lib.rs | 4 +-- compiler/rustc_data_structures/src/steal.rs | 2 +- compiler/rustc_lint/src/if_let_rescope.rs | 2 +- compiler/rustc_lint_defs/src/builtin.rs | 1 - compiler/rustc_next_trait_solver/src/lib.rs | 2 +- compiler/rustc_type_ir/src/lib.rs | 2 +- library/alloc/src/lib.rs | 2 -- library/alloc/tests/lib.rs | 1 - library/alloc/tests/vec.rs | 2 +- library/core/src/arch.rs | 35 ------------------- library/core/src/array/mod.rs | 1 - library/core/src/cell.rs | 1 - library/core/src/char/methods.rs | 4 --- library/core/src/intrinsics.rs | 4 --- library/core/src/lib.rs | 3 -- library/core/src/mem/maybe_uninit.rs | 3 -- library/core/src/mem/mod.rs | 1 - library/core/src/num/mod.rs | 2 -- library/core/src/option.rs | 4 --- library/core/src/ptr/mod.rs | 5 +-- library/core/src/ptr/mut_ptr.rs | 2 -- library/core/src/ptr/non_null.rs | 1 - library/core/src/result.rs | 2 -- library/core/src/slice/ascii.rs | 2 -- library/core/src/slice/mod.rs | 12 ------- library/core/src/slice/raw.rs | 2 -- library/core/src/str/converts.rs | 1 - library/core/src/str/mod.rs | 4 --- library/core/tests/atomic.rs | 2 +- library/core/tests/lib.rs | 1 - library/std/src/lib.rs | 1 - src/tools/miri/src/lib.rs | 4 +-- .../import-of-type-ir-inherent.rs | 3 -- .../import-of-type-ir-inherent.stderr | 8 ++--- .../internal-lints/query_completeness.rs | 2 -- .../internal-lints/query_completeness.stderr | 4 +-- 36 files changed, 17 insertions(+), 115 deletions(-) diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs index cbe8a043fba..39e2d3b4ebb 100644 --- a/compiler/rustc_const_eval/src/lib.rs +++ b/compiler/rustc_const_eval/src/lib.rs @@ -1,8 +1,6 @@ // tidy-alphabetical-start #![allow(internal_features)] #![allow(rustc::diagnostic_outside_of_impl)] -#![cfg_attr(not(bootstrap), feature(unqualified_local_imports))] -#![cfg_attr(not(bootstrap), warn(unqualified_local_imports))] #![doc(rust_logo)] #![feature(assert_matches)] #![feature(box_patterns)] @@ -15,7 +13,9 @@ #![feature(strict_provenance)] #![feature(trait_alias)] #![feature(try_blocks)] +#![feature(unqualified_local_imports)] #![feature(yeet_expr)] +#![warn(unqualified_local_imports)] #![warn(unreachable_pub)] // tidy-alphabetical-end diff --git a/compiler/rustc_data_structures/src/steal.rs b/compiler/rustc_data_structures/src/steal.rs index aaa95f6b7f1..0d79d98b5d9 100644 --- a/compiler/rustc_data_structures/src/steal.rs +++ b/compiler/rustc_data_structures/src/steal.rs @@ -57,7 +57,7 @@ impl Steal { /// /// This should not be used within rustc as it leaks information not tracked /// by the query system, breaking incremental compilation. - #[cfg_attr(not(bootstrap), rustc_lint_untracked_query_information)] + #[rustc_lint_untracked_query_information] pub fn is_stolen(&self) -> bool { self.value.borrow().is_none() } diff --git a/compiler/rustc_lint/src/if_let_rescope.rs b/compiler/rustc_lint/src/if_let_rescope.rs index cdd0e80c458..58fd11fcc29 100644 --- a/compiler/rustc_lint/src/if_let_rescope.rs +++ b/compiler/rustc_lint/src/if_let_rescope.rs @@ -24,7 +24,7 @@ declare_lint! { /// ### Example /// /// ```rust,edition2021 - /// #![cfg_attr(not(bootstrap), feature(if_let_rescope))] // Simplify this in bootstrap bump. + /// #![feature(if_let_rescope)] /// #![warn(if_let_rescope)] /// #![allow(unused_variables)] /// diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index da603df9a9a..f532b9b153b 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -1871,7 +1871,6 @@ declare_lint! { /// ### Example /// /// ```rust,compile_fail - /// # #[cfg_attr(bootstrap)] compile_error!(); // Remove this in bootstrap bump. /// #![deny(elided_named_lifetimes)] /// struct Foo; /// impl Foo { diff --git a/compiler/rustc_next_trait_solver/src/lib.rs b/compiler/rustc_next_trait_solver/src/lib.rs index de74ac32804..d67ae2550d9 100644 --- a/compiler/rustc_next_trait_solver/src/lib.rs +++ b/compiler/rustc_next_trait_solver/src/lib.rs @@ -5,7 +5,7 @@ //! So if you got to this crate from the old solver, it's totally normal. // tidy-alphabetical-start -#![cfg_attr(not(bootstrap), allow(rustc::usage_of_type_ir_inherent))] +#![allow(rustc::usage_of_type_ir_inherent)] #![warn(unreachable_pub)] // tidy-alphabetical-end diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index 51c887fc4da..9e6d1f424ba 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -1,11 +1,11 @@ // tidy-alphabetical-start #![allow(rustc::usage_of_ty_tykind)] +#![allow(rustc::usage_of_type_ir_inherent)] #![cfg_attr( feature = "nightly", feature(associated_type_defaults, never_type, rustc_attrs, negative_impls) )] #![cfg_attr(feature = "nightly", allow(internal_features))] -#![cfg_attr(not(bootstrap), allow(rustc::usage_of_type_ir_inherent))] #![warn(unreachable_pub)] // tidy-alphabetical-end diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 50bf385d671..12512f0dd8c 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -162,8 +162,6 @@ // // Language features: // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(const_mut_refs))] -#![cfg_attr(bootstrap, feature(const_refs_to_cell))] #![cfg_attr(not(test), feature(coroutine_trait))] #![cfg_attr(test, feature(panic_update_hook))] #![cfg_attr(test, feature(test))] diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs index 3ec4332c71b..301126b5d4d 100644 --- a/library/alloc/tests/lib.rs +++ b/library/alloc/tests/lib.rs @@ -5,7 +5,6 @@ #![feature(btree_extract_if)] #![feature(cow_is_borrowed)] #![feature(const_heap)] -#![cfg_attr(bootstrap, feature(const_mut_refs))] #![feature(const_try)] #![feature(core_intrinsics)] #![feature(extract_if)] diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs index f508a3e4c22..0f27fdff3e1 100644 --- a/library/alloc/tests/vec.rs +++ b/library/alloc/tests/vec.rs @@ -1288,7 +1288,7 @@ fn test_from_iter_specialization_panic_during_iteration_drops() { #[test] #[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] // FIXME(static_mut_refs): Do not allow `static_mut_refs` lint -#[cfg_attr(not(bootstrap), allow(static_mut_refs))] +#[allow(static_mut_refs)] fn test_from_iter_specialization_panic_during_drop_doesnt_leak() { static mut DROP_COUNTER_OLD: [usize; 5] = [0; 5]; static mut DROP_COUNTER_NEW: [usize; 2] = [0; 2]; diff --git a/library/core/src/arch.rs b/library/core/src/arch.rs index 4945c045bc6..57f456c98b3 100644 --- a/library/core/src/arch.rs +++ b/library/core/src/arch.rs @@ -3,9 +3,6 @@ #[allow(unused_imports)] #[stable(feature = "simd_arch", since = "1.27.0")] pub use crate::core_arch::arch::*; -#[unstable(feature = "naked_functions", issue = "90957")] -#[cfg(bootstrap)] -pub use crate::naked_asm; /// Inline assembly. /// @@ -20,37 +17,6 @@ pub macro asm("assembly template", $(operands,)* $(options($(option),*))?) { /* compiler built-in */ } -/// Inline assembly used in combination with `#[naked]` functions. -/// -/// Refer to [Rust By Example] for a usage guide and the [reference] for -/// detailed information about the syntax and available options. -/// -/// [Rust By Example]: https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html -/// [reference]: https://doc.rust-lang.org/nightly/reference/inline-assembly.html -#[unstable(feature = "naked_functions", issue = "90957")] -#[macro_export] -#[cfg(bootstrap)] -macro_rules! naked_asm { - ([$last:expr], [$($pushed:expr),*]) => { - #[cfg(any(target_arch = "x86_64", target_arch = "x86"))] - { - core::arch::asm!($($pushed),*, options(att_syntax, noreturn)) - } - #[cfg(not(any(target_arch = "x86_64", target_arch = "x86")))] - { - core::arch::asm!($($pushed),* , $last, options(noreturn)) - } - }; - - ([$first:expr $(, $rest:expr)*], [$($pushed:expr),*]) => { - naked_asm!([$($rest),*], [$($pushed,)* $first]); - }; - - ($($expr:expr),* $(,)?) => { - naked_asm!([$($expr),*], []); - }; -} - /// Inline assembly used in combination with `#[naked]` functions. /// /// Refer to [Rust By Example] for a usage guide and the [reference] for @@ -60,7 +26,6 @@ macro_rules! naked_asm { /// [reference]: https://doc.rust-lang.org/nightly/reference/inline-assembly.html #[unstable(feature = "naked_functions", issue = "90957")] #[rustc_builtin_macro] -#[cfg(not(bootstrap))] pub macro naked_asm("assembly template", $(operands,)* $(options($(option),*))?) { /* compiler built-in */ } diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 72f48878904..9b28b8b613e 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -147,7 +147,6 @@ pub const fn from_ref(s: &T) -> &[T; 1] { /// Converts a mutable reference to `T` into a mutable reference to an array of length 1 (without copying). #[stable(feature = "array_from_ref", since = "1.53.0")] #[rustc_const_stable(feature = "const_array_from_ref", since = "1.83.0")] -#[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn from_mut(s: &mut T) -> &mut [T; 1] { // SAFETY: Converting `&mut T` to `&mut [T; 1]` is sound. unsafe { &mut *(s as *mut T).cast::<[T; 1]>() } diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index 0945845021e..e1fa43296d0 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -2181,7 +2181,6 @@ impl UnsafeCell { /// ``` #[inline(always)] #[stable(feature = "unsafe_cell_get_mut", since = "1.50.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[rustc_const_stable(feature = "const_unsafecell_get_mut", since = "1.83.0")] pub const fn get_mut(&mut self) -> &mut T { &mut self.value diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index 1abfaa46ec6..30c0fff3104 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs @@ -676,7 +676,6 @@ impl char { #[stable(feature = "unicode_encode_char", since = "1.15.0")] #[rustc_const_stable(feature = "const_char_encode_utf8", since = "1.83.0")] #[inline] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn encode_utf8(self, dst: &mut [u8]) -> &mut str { // SAFETY: `char` is not a surrogate, so this is valid UTF-8. unsafe { from_utf8_unchecked_mut(encode_utf8_raw(self as u32, dst)) } @@ -1284,7 +1283,6 @@ impl char { #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[rustc_const_stable(feature = "const_make_ascii", since = "CURRENT_RUSTC_VERSION")] #[inline] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn make_ascii_uppercase(&mut self) { *self = self.to_ascii_uppercase(); } @@ -1311,7 +1309,6 @@ impl char { #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[rustc_const_stable(feature = "const_make_ascii", since = "CURRENT_RUSTC_VERSION")] #[inline] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn make_ascii_lowercase(&mut self) { *self = self.to_ascii_lowercase(); } @@ -1777,7 +1774,6 @@ const fn len_utf16(code: u32) -> usize { #[doc(hidden)] #[inline] #[rustc_allow_const_fn_unstable(const_eval_select)] -#[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn encode_utf8_raw(code: u32, dst: &mut [u8]) -> &mut [u8] { const fn panic_at_const(_code: u32, _len: usize, _dst_len: usize) { // Note that we cannot format in constant expressions. diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index ca5b9fc98b9..69ad4f41519 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -1807,7 +1807,6 @@ extern "rust-intrinsic" { /// is selected, and that may depend on optimization level and context, for /// example. #[rustc_nounwind] - #[cfg(not(bootstrap))] pub fn fmuladdf16(a: f16, b: f16, c: f16) -> f16; /// Returns `a * b + c` for `f32` values, non-deterministically executing /// either a fused multiply-add or two operations with rounding of the @@ -1820,7 +1819,6 @@ extern "rust-intrinsic" { /// is selected, and that may depend on optimization level and context, for /// example. #[rustc_nounwind] - #[cfg(not(bootstrap))] pub fn fmuladdf32(a: f32, b: f32, c: f32) -> f32; /// Returns `a * b + c` for `f64` values, non-deterministically executing /// either a fused multiply-add or two operations with rounding of the @@ -1833,7 +1831,6 @@ extern "rust-intrinsic" { /// is selected, and that may depend on optimization level and context, for /// example. #[rustc_nounwind] - #[cfg(not(bootstrap))] pub fn fmuladdf64(a: f64, b: f64, c: f64) -> f64; /// Returns `a * b + c` for `f128` values, non-deterministically executing /// either a fused multiply-add or two operations with rounding of the @@ -1846,7 +1843,6 @@ extern "rust-intrinsic" { /// is selected, and that may depend on optimization level and context, for /// example. #[rustc_nounwind] - #[cfg(not(bootstrap))] pub fn fmuladdf128(a: f128, b: f128, c: f128) -> f128; /// Returns the largest integer less than or equal to an `f16`. diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index ccd6534de9b..7060da172f3 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -173,9 +173,6 @@ // // Language features: // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(const_mut_refs))] -#![cfg_attr(bootstrap, feature(const_refs_to_cell))] -#![cfg_attr(bootstrap, feature(const_refs_to_static))] #![feature(abi_unadjusted)] #![feature(adt_const_params)] #![feature(allow_internal_unsafe)] diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index bb01d4e642c..ea73cfc3781 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -570,7 +570,6 @@ impl MaybeUninit { /// until they are, it is advisable to avoid them.) #[stable(feature = "maybe_uninit", since = "1.36.0")] #[rustc_const_stable(feature = "const_maybe_uninit_as_mut_ptr", since = "1.83.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[inline(always)] pub const fn as_mut_ptr(&mut self) -> *mut T { // `MaybeUninit` and `ManuallyDrop` are both `repr(transparent)` so we can cast the pointer. @@ -910,7 +909,6 @@ impl MaybeUninit { /// }; /// ``` #[stable(feature = "maybe_uninit_ref", since = "1.55.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[rustc_const_stable( feature = "const_maybe_uninit_assume_init", since = "CURRENT_RUSTC_VERSION" @@ -1000,7 +998,6 @@ impl MaybeUninit { /// /// [`assume_init_mut`]: MaybeUninit::assume_init_mut #[unstable(feature = "maybe_uninit_slice", issue = "63569")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[rustc_const_unstable(feature = "maybe_uninit_slice", issue = "63569")] #[inline(always)] pub const unsafe fn slice_assume_init_mut(slice: &mut [Self]) -> &mut [T] { diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index ada80463306..74b198c4fdd 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -857,7 +857,6 @@ pub fn take(dest: &mut T) -> T { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[must_use = "if you don't need the old value, you can just assign the new value directly"] -#[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[rustc_const_stable(feature = "const_replace", since = "1.83.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "mem_replace")] pub const fn replace(dest: &mut T, src: T) -> T { diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index f55d55171f2..5e2f45884dd 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -626,7 +626,6 @@ impl u8 { #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[rustc_const_stable(feature = "const_make_ascii", since = "CURRENT_RUSTC_VERSION")] #[inline] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn make_ascii_uppercase(&mut self) { *self = self.to_ascii_uppercase(); } @@ -653,7 +652,6 @@ impl u8 { #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[rustc_const_stable(feature = "const_make_ascii", since = "CURRENT_RUSTC_VERSION")] #[inline] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn make_ascii_lowercase(&mut self) { *self = self.to_ascii_lowercase(); } diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 661176ce9fc..0b996c40c04 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -723,7 +723,6 @@ impl Option { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[rustc_const_stable(feature = "const_option", since = "1.83.0")] pub const fn as_mut(&mut self) -> Option<&mut T> { match *self { @@ -1716,7 +1715,6 @@ impl Option { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[rustc_const_stable(feature = "const_option", since = "1.83.0")] pub const fn take(&mut self) -> Option { // FIXME(const-hack) replace `mem::replace` by `mem::take` when the latter is const ready @@ -1775,7 +1773,6 @@ impl Option { /// ``` #[inline] #[stable(feature = "option_replace", since = "1.31.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[rustc_const_stable(feature = "const_option", since = "1.83.0")] pub const fn replace(&mut self, value: T) -> Option { mem::replace(self, Some(value)) @@ -1937,7 +1934,6 @@ impl Option<&mut T> { /// ``` #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "copied", since = "1.35.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[rustc_const_stable(feature = "const_option", since = "1.83.0")] pub const fn copied(self) -> Option where diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 61b48e312cf..09ff7f8cab1 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -1265,7 +1265,6 @@ const unsafe fn swap_nonoverlapping_simple_untyped(x: *mut T, y: *mut T, coun /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[rustc_const_stable(feature = "const_replace", since = "1.83.0")] #[rustc_diagnostic_item = "ptr_replace"] pub const unsafe fn replace(dst: *mut T, src: T) -> T { @@ -1518,7 +1517,6 @@ pub const unsafe fn read(src: *const T) -> T { #[inline] #[stable(feature = "ptr_unaligned", since = "1.17.0")] #[rustc_const_stable(feature = "const_ptr_read", since = "1.71.0")] -#[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_diagnostic_item = "ptr_read_unaligned"] pub const unsafe fn read_unaligned(src: *const T) -> T { @@ -1725,7 +1723,6 @@ pub const unsafe fn write(dst: *mut T, src: T) { /// ``` #[inline] #[stable(feature = "ptr_unaligned", since = "1.17.0")] -#[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_refs_to_cell))] #[rustc_const_stable(feature = "const_ptr_write", since = "1.83.0")] #[rustc_diagnostic_item = "ptr_write_unaligned"] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces @@ -1918,7 +1915,7 @@ pub unsafe fn write_volatile(dst: *mut T, src: T) { /// than trying to adapt this to accommodate that change. /// /// Any questions go to @nagisa. -#[cfg_attr(not(bootstrap), allow(ptr_to_integer_transmute_in_consts))] +#[allow(ptr_to_integer_transmute_in_consts)] #[lang = "align_offset"] pub(crate) const unsafe fn align_offset(p: *const T, a: usize) -> usize { // FIXME(#75598): Direct use of these intrinsics improves codegen significantly at opt-level <= diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index d7ce197848b..613d2c91ac6 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -1678,7 +1678,6 @@ impl *mut T { /// /// ``` /// #![feature(const_pointer_is_aligned)] - /// # #![cfg_attr(bootstrap, feature(const_mut_refs))] /// /// // On some platforms, the alignment of primitives is less than their size. /// #[repr(align(4))] @@ -1804,7 +1803,6 @@ impl *mut T { /// ``` /// #![feature(pointer_is_aligned_to)] /// #![feature(const_pointer_is_aligned)] - /// # #![cfg_attr(bootstrap, feature(const_mut_refs))] /// /// // On some platforms, the alignment of i32 is less than 4. /// #[repr(align(4))] diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index c6839136348..dfd0bd8fd1e 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -394,7 +394,6 @@ impl NonNull { /// /// [the module documentation]: crate::ptr#safety #[stable(feature = "nonnull", since = "1.25.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[rustc_const_stable(feature = "const_ptr_as_ref", since = "1.83.0")] #[must_use] #[inline(always)] diff --git a/library/core/src/result.rs b/library/core/src/result.rs index e84c4e3a239..330d1eb14ed 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -735,7 +735,6 @@ impl Result { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_result", since = "1.83.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn as_mut(&mut self) -> Result<&mut T, &mut E> { match *self { Ok(ref mut x) => Ok(x), @@ -1589,7 +1588,6 @@ impl Result<&mut T, E> { #[inline] #[stable(feature = "result_copied", since = "1.59.0")] #[rustc_const_stable(feature = "const_result", since = "1.83.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[rustc_allow_const_fn_unstable(const_precise_live_drops)] pub const fn copied(self) -> Result where diff --git a/library/core/src/slice/ascii.rs b/library/core/src/slice/ascii.rs index 8d8ac6a1d2a..a03e9fbae11 100644 --- a/library/core/src/slice/ascii.rs +++ b/library/core/src/slice/ascii.rs @@ -69,7 +69,6 @@ impl [u8] { #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[rustc_const_stable(feature = "const_make_ascii", since = "CURRENT_RUSTC_VERSION")] #[inline] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn make_ascii_uppercase(&mut self) { // FIXME(const-hack): We would like to simply iterate using `for` loops but this isn't currently allowed in constant expressions. let mut i = 0; @@ -92,7 +91,6 @@ impl [u8] { #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[rustc_const_stable(feature = "const_make_ascii", since = "CURRENT_RUSTC_VERSION")] #[inline] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn make_ascii_lowercase(&mut self) { // FIXME(const-hack): We would like to simply iterate using `for` loops but this isn't currently allowed in constant expressions. let mut i = 0; diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 9fdcea1f7b7..dbcfe946440 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -171,7 +171,6 @@ impl [T] { /// assert_eq!(None, y.first_mut()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[rustc_const_stable(feature = "const_slice_first_last", since = "1.83.0")] #[inline] #[must_use] @@ -214,7 +213,6 @@ impl [T] { /// assert_eq!(x, &[3, 4, 5]); /// ``` #[stable(feature = "slice_splits", since = "1.5.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[rustc_const_stable(feature = "const_slice_first_last", since = "1.83.0")] #[inline] #[must_use] @@ -257,7 +255,6 @@ impl [T] { /// assert_eq!(x, &[4, 5, 3]); /// ``` #[stable(feature = "slice_splits", since = "1.5.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[rustc_const_stable(feature = "const_slice_first_last", since = "1.83.0")] #[inline] #[must_use] @@ -300,7 +297,6 @@ impl [T] { /// assert_eq!(None, y.last_mut()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[rustc_const_stable(feature = "const_slice_first_last", since = "1.83.0")] #[inline] #[must_use] @@ -357,7 +353,6 @@ impl [T] { #[inline] #[stable(feature = "slice_first_last_chunk", since = "1.77.0")] #[rustc_const_stable(feature = "const_slice_first_last_chunk", since = "1.83.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn first_chunk_mut(&mut self) -> Option<&mut [T; N]> { if self.len() < N { None @@ -423,7 +418,6 @@ impl [T] { #[inline] #[stable(feature = "slice_first_last_chunk", since = "1.77.0")] #[rustc_const_stable(feature = "const_slice_first_last_chunk", since = "1.83.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn split_first_chunk_mut( &mut self, ) -> Option<(&mut [T; N], &mut [T])> { @@ -494,7 +488,6 @@ impl [T] { #[inline] #[stable(feature = "slice_first_last_chunk", since = "1.77.0")] #[rustc_const_stable(feature = "const_slice_first_last_chunk", since = "1.83.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn split_last_chunk_mut( &mut self, ) -> Option<(&mut [T], &mut [T; N])> { @@ -564,7 +557,6 @@ impl [T] { #[inline] #[stable(feature = "slice_first_last_chunk", since = "1.77.0")] #[rustc_const_stable(feature = "const_slice_first_last_chunk", since = "1.83.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn last_chunk_mut(&mut self) -> Option<&mut [T; N]> { if self.len() < N { None @@ -853,7 +845,6 @@ impl [T] { /// [`as_mut_ptr`]: slice::as_mut_ptr #[stable(feature = "slice_ptr_range", since = "1.48.0")] #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs, const_refs_to_cell))] #[inline] #[must_use] pub const fn as_mut_ptr_range(&mut self) -> Range<*mut T> { @@ -1908,7 +1899,6 @@ impl [T] { #[track_caller] #[must_use] #[rustc_const_stable(feature = "const_slice_split_at_mut", since = "1.83.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) { match self.split_at_mut_checked(mid) { Some(pair) => pair, @@ -2011,7 +2001,6 @@ impl [T] { /// ``` #[stable(feature = "slice_split_at_unchecked", since = "1.79.0")] #[rustc_const_stable(feature = "const_slice_split_at_mut", since = "1.83.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[inline] #[must_use] pub const unsafe fn split_at_mut_unchecked(&mut self, mid: usize) -> (&mut [T], &mut [T]) { @@ -2112,7 +2101,6 @@ impl [T] { /// ``` #[stable(feature = "split_at_checked", since = "1.80.0")] #[rustc_const_stable(feature = "const_slice_split_at_mut", since = "1.83.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[inline] #[must_use] pub const fn split_at_mut_checked(&mut self, mid: usize) -> Option<(&mut [T], &mut [T])> { diff --git a/library/core/src/slice/raw.rs b/library/core/src/slice/raw.rs index 976749cc148..89840881c4d 100644 --- a/library/core/src/slice/raw.rs +++ b/library/core/src/slice/raw.rs @@ -172,7 +172,6 @@ pub const unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_slice_from_raw_parts_mut", since = "1.83.0")] -#[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[must_use] #[rustc_diagnostic_item = "slice_from_raw_parts_mut"] pub const unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T] { @@ -205,7 +204,6 @@ pub const fn from_ref(s: &T) -> &[T] { /// Converts a reference to T into a slice of length 1 (without copying). #[stable(feature = "from_ref", since = "1.28.0")] #[rustc_const_stable(feature = "const_slice_from_ref", since = "1.83.0")] -#[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[must_use] pub const fn from_mut(s: &mut T) -> &mut [T] { array::from_mut(s) diff --git a/library/core/src/str/converts.rs b/library/core/src/str/converts.rs index b61ed454cd9..c997e5e443d 100644 --- a/library/core/src/str/converts.rs +++ b/library/core/src/str/converts.rs @@ -195,7 +195,6 @@ pub const unsafe fn from_utf8_unchecked(v: &[u8]) -> &str { #[inline] #[must_use] #[stable(feature = "str_mut_extras", since = "1.20.0")] -#[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[rustc_const_stable(feature = "const_str_from_utf8_unchecked_mut", since = "1.83.0")] #[rustc_diagnostic_item = "str_from_utf8_unchecked_mut"] pub const unsafe fn from_utf8_unchecked_mut(v: &mut [u8]) -> &mut str { diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index 09938dda262..89addc4cb74 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -339,7 +339,6 @@ impl str { /// assert_eq!("🍔∈🌏", s); /// ``` #[stable(feature = "str_mut_extras", since = "1.20.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[rustc_const_stable(feature = "const_str_as_mut", since = "1.83.0")] #[must_use] #[inline(always)] @@ -386,7 +385,6 @@ impl str { /// It is your responsibility to make sure that the string slice only gets /// modified in a way that it remains valid UTF-8. #[stable(feature = "str_as_mut_ptr", since = "1.36.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[rustc_const_stable(feature = "const_str_as_mut", since = "1.83.0")] #[rustc_never_returns_null_ptr] #[must_use] @@ -2477,7 +2475,6 @@ impl str { #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[rustc_const_stable(feature = "const_make_ascii", since = "CURRENT_RUSTC_VERSION")] #[inline] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn make_ascii_uppercase(&mut self) { // SAFETY: changing ASCII letters only does not invalidate UTF-8. let me = unsafe { self.as_bytes_mut() }; @@ -2506,7 +2503,6 @@ impl str { #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[rustc_const_stable(feature = "const_make_ascii", since = "CURRENT_RUSTC_VERSION")] #[inline] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn make_ascii_lowercase(&mut self) { // SAFETY: changing ASCII letters only does not invalidate UTF-8. let me = unsafe { self.as_bytes_mut() }; diff --git a/library/core/tests/atomic.rs b/library/core/tests/atomic.rs index 2bdaeb3845a..0ffba538b20 100644 --- a/library/core/tests/atomic.rs +++ b/library/core/tests/atomic.rs @@ -229,7 +229,7 @@ fn static_init() { #[test] // FIXME(static_mut_refs): Do not allow `static_mut_refs` lint -#[cfg_attr(not(bootstrap), allow(static_mut_refs))] +#[allow(static_mut_refs)] fn atomic_access_bool() { static mut ATOMIC: AtomicBool = AtomicBool::new(false); diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 37e7db1157c..bfc0b638b7e 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -1,5 +1,4 @@ // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(const_mut_refs))] #![cfg_attr(target_has_atomic = "128", feature(integer_atomics))] #![cfg_attr(test, feature(cfg_match))] #![feature(alloc_layout_extra)] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index ed448e50e60..3ab65238368 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -279,7 +279,6 @@ // // Language features: // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(const_mut_refs))] #![feature(alloc_error_handler)] #![feature(allocator_internals)] #![feature(allow_internal_unsafe)] diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs index f089d1e1bcc..9814858beaa 100644 --- a/src/tools/miri/src/lib.rs +++ b/src/tools/miri/src/lib.rs @@ -14,6 +14,7 @@ #![feature(strict_provenance)] #![feature(exposed_provenance)] #![feature(pointer_is_aligned_to)] +#![feature(unqualified_local_imports)] // Configure clippy and other lints #![allow( clippy::collapsible_else_if, @@ -42,13 +43,12 @@ )] #![warn( rust_2018_idioms, + unqualified_local_imports, clippy::cast_possible_wrap, // unsigned -> signed clippy::cast_sign_loss, // signed -> unsigned clippy::cast_lossless, clippy::cast_possible_truncation, )] -#![cfg_attr(not(bootstrap), feature(unqualified_local_imports))] -#![cfg_attr(not(bootstrap), warn(unqualified_local_imports))] // Needed for rustdoc from bootstrap (with `-Znormalize-docs`). #![recursion_limit = "256"] diff --git a/tests/ui-fulldeps/internal-lints/import-of-type-ir-inherent.rs b/tests/ui-fulldeps/internal-lints/import-of-type-ir-inherent.rs index 08d86606a6b..a26d00b77ac 100644 --- a/tests/ui-fulldeps/internal-lints/import-of-type-ir-inherent.rs +++ b/tests/ui-fulldeps/internal-lints/import-of-type-ir-inherent.rs @@ -1,8 +1,5 @@ //@ compile-flags: -Z unstable-options -// #[cfg(bootstrap)]: We can stop ignoring next beta bump; afterward this ALWAYS should run. -//@ ignore-stage1 - #![feature(rustc_private)] #![deny(rustc::usage_of_type_ir_inherent)] diff --git a/tests/ui-fulldeps/internal-lints/import-of-type-ir-inherent.stderr b/tests/ui-fulldeps/internal-lints/import-of-type-ir-inherent.stderr index cc6cb9170c0..3326b1047ac 100644 --- a/tests/ui-fulldeps/internal-lints/import-of-type-ir-inherent.stderr +++ b/tests/ui-fulldeps/internal-lints/import-of-type-ir-inherent.stderr @@ -1,18 +1,18 @@ error: do not use `rustc_type_ir::inherent` unless you're inside of the trait solver - --> $DIR/import-of-type-ir-inherent.rs:11:20 + --> $DIR/import-of-type-ir-inherent.rs:8:20 | LL | use rustc_type_ir::inherent::*; | ^^^^^^^^ | = note: the method or struct you're looking for is likely defined somewhere else downstream in the compiler note: the lint level is defined here - --> $DIR/import-of-type-ir-inherent.rs:7:9 + --> $DIR/import-of-type-ir-inherent.rs:4:9 | LL | #![deny(rustc::usage_of_type_ir_inherent)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: do not use `rustc_type_ir::inherent` unless you're inside of the trait solver - --> $DIR/import-of-type-ir-inherent.rs:13:20 + --> $DIR/import-of-type-ir-inherent.rs:10:20 | LL | use rustc_type_ir::inherent; | ^^^^^^^^ @@ -20,7 +20,7 @@ LL | use rustc_type_ir::inherent; = note: the method or struct you're looking for is likely defined somewhere else downstream in the compiler error: do not use `rustc_type_ir::inherent` unless you're inside of the trait solver - --> $DIR/import-of-type-ir-inherent.rs:15:20 + --> $DIR/import-of-type-ir-inherent.rs:12:20 | LL | use rustc_type_ir::inherent::Predicate; | ^^^^^^^^ diff --git a/tests/ui-fulldeps/internal-lints/query_completeness.rs b/tests/ui-fulldeps/internal-lints/query_completeness.rs index 50b0fb4c3fc..791f4599273 100644 --- a/tests/ui-fulldeps/internal-lints/query_completeness.rs +++ b/tests/ui-fulldeps/internal-lints/query_completeness.rs @@ -1,6 +1,4 @@ //@ compile-flags: -Z unstable-options -// #[cfg(bootstrap)]: We can stop ignoring next beta bump; afterward this ALWAYS should run. -//@ ignore-stage1 (requires matching sysroot built with in-tree compiler) #![feature(rustc_private)] #![deny(rustc::untracked_query_information)] diff --git a/tests/ui-fulldeps/internal-lints/query_completeness.stderr b/tests/ui-fulldeps/internal-lints/query_completeness.stderr index 35bb867f40e..e17c2a891cf 100644 --- a/tests/ui-fulldeps/internal-lints/query_completeness.stderr +++ b/tests/ui-fulldeps/internal-lints/query_completeness.stderr @@ -1,12 +1,12 @@ error: `is_stolen` accesses information that is not tracked by the query system - --> $DIR/query_completeness.rs:12:15 + --> $DIR/query_completeness.rs:10:15 | LL | let _ = x.is_stolen(); | ^^^^^^^^^ | = note: if you believe this case to be fine, allow this lint and add a comment explaining your rationale note: the lint level is defined here - --> $DIR/query_completeness.rs:5:9 + --> $DIR/query_completeness.rs:3:9 | LL | #![deny(rustc::untracked_query_information)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From 618b0cb0469fe219bd5e668bb5a63d3ee1568abc Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Tue, 15 Oct 2024 20:16:16 -0700 Subject: [PATCH 344/357] update STAGE0_MISSING_TARGETS --- src/bootstrap/src/core/sanity.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs index 6fbdd76ed5b..fabb4f2b13b 100644 --- a/src/bootstrap/src/core/sanity.rs +++ b/src/bootstrap/src/core/sanity.rs @@ -34,10 +34,6 @@ pub struct Finder { // Targets can be removed from this list once they are present in the stage0 compiler (usually by updating the beta compiler of the bootstrap). const STAGE0_MISSING_TARGETS: &[&str] = &[ // just a dummy comment so the list doesn't get onelined - "armv7-rtems-eabihf", - "riscv32e-unknown-none-elf", - "riscv32em-unknown-none-elf", - "riscv32emc-unknown-none-elf", ]; /// Minimum version threshold for libstdc++ required when using prebuilt LLVM From cd60224af72a380dad27f01afc08c7374105525b Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Tue, 15 Oct 2024 20:53:26 -0700 Subject: [PATCH 345/357] Fix `clippy::needless-lifetimes` in bootstrap --- src/bootstrap/src/core/build_steps/tool.rs | 2 +- src/bootstrap/src/core/builder.rs | 2 +- src/bootstrap/src/core/config/config.rs | 4 ++-- src/bootstrap/src/utils/cache.rs | 6 +++--- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs index a01497c2bb9..f1a10c3296e 100644 --- a/src/bootstrap/src/core/build_steps/tool.rs +++ b/src/bootstrap/src/core/build_steps/tool.rs @@ -1096,7 +1096,7 @@ tool_extended!((self, builder), Rustfmt, "src/tools/rustfmt", "rustfmt", stable=true, add_bins_to_sysroot = ["rustfmt", "cargo-fmt"]; ); -impl<'a> Builder<'a> { +impl Builder<'_> { /// Gets a `BootstrapCommand` which is ready to run `tool` in `stage` built for /// `host`. pub fn tool_cmd(&self, tool: Tool) -> BootstrapCommand { diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs index 9ac0b0a01f7..15c6f303f94 100644 --- a/src/bootstrap/src/core/builder.rs +++ b/src/bootstrap/src/core/builder.rs @@ -63,7 +63,7 @@ pub struct Builder<'a> { pub paths: Vec, } -impl<'a> Deref for Builder<'a> { +impl Deref for Builder<'_> { type Target = Build; fn deref(&self) -> &Self::Target { diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index eb571f920df..c2ab439891e 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -996,7 +996,7 @@ impl<'de> Deserialize<'de> for RustOptimize { struct OptimizeVisitor; -impl<'de> serde::de::Visitor<'de> for OptimizeVisitor { +impl serde::de::Visitor<'_> for OptimizeVisitor { type Value = RustOptimize; fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { @@ -1071,7 +1071,7 @@ impl<'de> Deserialize<'de> for LldMode { { struct LldModeVisitor; - impl<'de> serde::de::Visitor<'de> for LldModeVisitor { + impl serde::de::Visitor<'_> for LldModeVisitor { type Value = LldMode; fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { diff --git a/src/bootstrap/src/utils/cache.rs b/src/bootstrap/src/utils/cache.rs index 3f78b04d44a..29342cc5a2c 100644 --- a/src/bootstrap/src/utils/cache.rs +++ b/src/bootstrap/src/utils/cache.rs @@ -39,17 +39,17 @@ impl PartialEq for Interned { *self == other } } -impl<'a> PartialEq<&'a str> for Interned { +impl PartialEq<&str> for Interned { fn eq(&self, other: &&str) -> bool { **self == **other } } -impl<'a, T> PartialEq<&'a Interned> for Interned { +impl PartialEq<&Interned> for Interned { fn eq(&self, other: &&Self) -> bool { self.0 == other.0 } } -impl<'a, T> PartialEq> for &'a Interned { +impl PartialEq> for &Interned { fn eq(&self, other: &Interned) -> bool { self.0 == other.0 } From 0804d1bc27bd9b64c1302851f047316f086a0d1a Mon Sep 17 00:00:00 2001 From: Juniper Tyree <50025784+juntyr@users.noreply.github.com> Date: Sat, 12 Oct 2024 08:03:02 +0300 Subject: [PATCH 346/357] Add wasm32-unknown-emscripten platform support document Co-authored-by: Hood Chatham Co-authored-by: Alex Crichton Co-authored-by: Kleis Auke Wolthuizen --- src/doc/rustc/src/SUMMARY.md | 1 + src/doc/rustc/src/platform-support.md | 2 +- .../wasm32-unknown-emscripten.md | 168 ++++++++++++++++++ .../wasm32-unknown-unknown.md | 4 +- 4 files changed, 172 insertions(+), 3 deletions(-) create mode 100644 src/doc/rustc/src/platform-support/wasm32-unknown-emscripten.md diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index b1a5bd604eb..795908b32c0 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -84,6 +84,7 @@ - [wasm32-wasip1](platform-support/wasm32-wasip1.md) - [wasm32-wasip1-threads](platform-support/wasm32-wasip1-threads.md) - [wasm32-wasip2](platform-support/wasm32-wasip2.md) + - [wasm32-unknown-emscripten](platform-support/wasm32-unknown-emscripten.md) - [wasm32-unknown-unknown](platform-support/wasm32-unknown-unknown.md) - [wasm64-unknown-unknown](platform-support/wasm64-unknown-unknown.md) - [\*-win7-windows-msvc](platform-support/win7-windows-msvc.md) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 0ef95ba64a1..022fc9da7e0 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -190,7 +190,7 @@ target | std | notes [`thumbv8m.base-none-eabi`](platform-support/thumbv8m.base-none-eabi.md) | * | Bare Armv8-M Baseline [`thumbv8m.main-none-eabi`](platform-support/thumbv8m.main-none-eabi.md) | * | Bare Armv8-M Mainline [`thumbv8m.main-none-eabihf`](platform-support/thumbv8m.main-none-eabi.md) | * | Bare Armv8-M Mainline, hardfloat -`wasm32-unknown-emscripten` | ✓ | WebAssembly via Emscripten +[`wasm32-unknown-emscripten`](platform-support/wasm32-unknown-emscripten.md) | ✓ | WebAssembly via Emscripten [`wasm32-unknown-unknown`](platform-support/wasm32-unknown-unknown.md) | ✓ | WebAssembly `wasm32-wasi` | ✓ | WebAssembly with WASI (undergoing a [rename to `wasm32-wasip1`][wasi-rename]) [`wasm32-wasip1`](platform-support/wasm32-wasip1.md) | ✓ | WebAssembly with WASI diff --git a/src/doc/rustc/src/platform-support/wasm32-unknown-emscripten.md b/src/doc/rustc/src/platform-support/wasm32-unknown-emscripten.md new file mode 100644 index 00000000000..7a9cd4b522b --- /dev/null +++ b/src/doc/rustc/src/platform-support/wasm32-unknown-emscripten.md @@ -0,0 +1,168 @@ +# `wasm32-unknown-emscripten` + +**Tier: 2** + +The `wasm32-unknown-emscripten` target is a WebAssembly compilation target which +uses the [Emscripten](https://emscripten.org/) compiler toolchain. Emscripten is +a C/C++ toolchain designed to make it as easy as possible to port C/C++ code +written for Linux to run on the web or in other JavaScript runtimes such as Node. +It thus provides POSIX-compatible (musl) `libc` and `libstd` implementations and +many Linux APIs, access to the OpenGL and SDL APIs, and the ability to run arbitrary +JavaScript code, all based on web APIs using JS glue code. With the +`wasm32-unknown-emscripten` target, Rust code can interoperate with Emscripten's +ecosystem, C/C++ and JS code, and web APIs. + +One existing user of this target is the +[`pyodide` project](https://pyodide.org/) which provides a Python runtime in +WebAssembly using Emscripten and compiles Python extension modules written in Rust +to the `wasm32-unknown-emscripten` target. + +If you want to generate a standalone WebAssembly binary that does not require +access to the web APIs or the Rust standard library, the +[`wasm32-unknown-unknown`](./wasm32-unknown-unknown.md) target may be better +suited for you. However, [`wasm32-unknown-unknown`](./wasm32-unknown-unknown.md) +does not (easily) support interop with C/C++ code. Please refer to the +[wasm-bindgen](https://crates.io/crates/wasm-bindgen) crate in case you want to +interoperate with JavaScript with this target. + +Like Emscripten, the WASI targets [`wasm32-wasip1`](./wasm32-wasip1.md) and +[`wasm32-wasip2`](./wasm32-wasip2.md) also provide access to the host environment, +support interop with C/C++ (and other languages), and support most of the Rust +standard library. While the WASI targets are portable across different hosts +(web and non-web), WASI has no standard way of accessing web APIs, whereas +Emscripten has the ability to run arbitrary JS from WASM and access many web APIs. +If you are only targeting the web and need to access web APIs, the +`wasm32-unknown-emscripten` target may be preferable. + +## Target maintainers + +- Hood Chatham, https://github.com/hoodmane +- Juniper Tyree, https://github.com/juntyr + +## Requirements + +This target is cross-compiled. The Emscripten compiler toolchain `emcc` must be +installed to link WASM binaries for this target. You can install `emcc` using: + +```sh +git clone https://github.com/emscripten-core/emsdk.git --depth 1 +./emsdk/emsdk install 3.1.68 +./emsdk/emsdk activate 3.1.68 +source ./emsdk/emsdk_env.sh +``` + +Please refer to for +further details and instructions. + +## Building the target + +Building this target can be done by: + +* Configure the `wasm32-unknown-emscripten` target to get built. +* Ensure the `WebAssembly` target backend is not disabled in LLVM. + +These are all controlled through `config.toml` options. It should be possible +to build this target on any platform. A minimal example configuration would be: + +```toml +[llvm] +targets = "WebAssembly" + +[build] +build-stage = 1 +target = ["wasm32-unknown-emscripten"] +``` + +## Building Rust programs + +Rust programs can be compiled by adding this target via rustup: + +```sh +$ rustup target add wasm32-unknown-emscripten +``` + +and then compiling with the target: + +```sh +$ rustc foo.rs --target wasm32-unknown-emscripten +$ file foo.wasm +``` + +## Cross-compilation + +This target can be cross-compiled from any host. + +## Emscripten ABI Compatibility + +The Emscripten compiler toolchain does not follow a semantic versioning scheme +that clearly indicates when breaking changes to the ABI can be made. Additionally, +Emscripten offers many different ABIs even for a single version of Emscripten +depending on the linker flags used, e.g. `-fexceptions` and `-sWASM_BIGINT`. If +the ABIs mismatch, your code may exhibit undefined behaviour. + +To ensure that the ABIs of your Rust code, of the Rust standard library, and of +other code compiled for Emscripten all match, you should rebuild the Rust standard +library with your local Emscripten version and settings using: + +```sh +cargo +nightly -Zbuild-std build +``` + +If you still want to use the pre-compiled `std` from rustup, you should ensure +that your local Emscripten matches the version used by Rust and be careful about +any `-C link-arg`s that you compiled your Rust code with. + +## Testing + +This target is not extensively tested in CI for the rust-lang/rust repository. It +can be tested locally, for example, with: + +```sh +./x.py test --target wasm32-unknown-emscripten --skip src/tools/linkchecker +``` + +To run these tests, both `emcc` and `node` need to be in your `$PATH`. You can +install `node`, for example, using `nvm` by following the instructions at +. + +If you need to test WebAssembly compatibility *in general*, it is recommended +to test the [`wasm32-wasip1`](./wasm32-wasip1.md) target instead. + +## Conditionally compiling code + +It's recommended to conditionally compile code for this target with: + +```text +#[cfg(target_os = "emscripten")] +``` + +It may sometimes be necessary to conditionally compile code for WASM targets +which do *not* use emscripten, which can be achieved with: + +```text +#[cfg(all(target_family = "wasm", not(target_os = "emscripten)))] +``` + +## Enabled WebAssembly features + +WebAssembly is an evolving standard which adds new features such as new +instructions over time. This target's default set of supported WebAssembly +features will additionally change over time. The `wasm32-unknown-emscripten` target +inherits the default settings of LLVM which typically, but not necessarily, matches +the default settings of Emscripten as well. At link time, `emcc` configures the +linker to use Emscripten's settings. + +Please refer to the [`wasm32-unknown-unknown`](./wasm32-unknown-unknown.md) +target's documentation on which WebAssembly features Rust enables by default, how +features can be disabled, and how Rust code can be conditionally compiled based on +which features are enabled. + +Note that Rust code compiled for `wasm32-unknown-emscripten` currently enables +`-fexceptions` (JS exceptions) by default unless the Rust code is compiled with +`-Cpanic=abort`. `-fwasm-exceptions` (WASM exceptions) is not yet currently supported, +see . + +Please refer to the [Emscripten ABI compatibility](#emscripten-abi-compatibility) +section to ensure that the features that are enabled do not cause an ABI mismatch +between your Rust code, the pre-compiled Rust standard library, and other code compiled +for Emscripten. diff --git a/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md b/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md index 0e06a820a22..48a8df0c4a8 100644 --- a/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md +++ b/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md @@ -46,8 +46,8 @@ This target currently has no equivalent in C/C++. There is no C/C++ toolchain for this target. While interop is theoretically possible it's recommended to instead use one of: -* `wasm32-unknown-emscripten` - for web-based use cases the Emscripten - toolchain is typically chosen for running C/C++. +* [`wasm32-unknown-emscripten`](./wasm32-unknown-emscripten.md) - for web-based + use cases the Emscripten toolchain is typically chosen for running C/C++. * [`wasm32-wasip1`](./wasm32-wasip1.md) - the wasi-sdk toolchain is used to compile C/C++ on this target and can interop with Rust code. WASI works on the web so far as there's no blocker, but an implementation of WASI APIs From 5eb863698964b026149f4ed9f958639eb290f5b3 Mon Sep 17 00:00:00 2001 From: Urgau Date: Wed, 16 Oct 2024 09:41:49 +0200 Subject: [PATCH 347/357] Handle gracefully true/false in `cfg(target(..))` compact --- compiler/rustc_attr/src/builtin.rs | 8 +++++++- tests/ui/cfg/cfg-target-compact-errors.rs | 4 ++++ tests/ui/cfg/cfg-target-compact-errors.stderr | 8 +++++++- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index c1db4d07dfc..bbb17497684 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -723,7 +723,13 @@ pub fn eval_condition( } mis.iter().fold(true, |res, mi| { - let mut mi = mi.meta_item().unwrap().clone(); + let Some(mut mi) = mi.meta_item().cloned() else { + dcx.emit_err(session_diagnostics::CfgPredicateIdentifier { + span: mi.span(), + }); + return false; + }; + if let [seg, ..] = &mut mi.path.segments[..] { seg.ident.name = Symbol::intern(&format!("target_{}", seg.ident.name)); } diff --git a/tests/ui/cfg/cfg-target-compact-errors.rs b/tests/ui/cfg/cfg-target-compact-errors.rs index daacbb2851d..e00d42fe4d9 100644 --- a/tests/ui/cfg/cfg-target-compact-errors.rs +++ b/tests/ui/cfg/cfg-target-compact-errors.rs @@ -14,4 +14,8 @@ fn two() {} //~^ ERROR invalid predicate `target_pointer` fn three() {} +#[cfg(target(true))] +//~^ ERROR `cfg` predicate key must be an identifier +fn four() {} + fn main() {} diff --git a/tests/ui/cfg/cfg-target-compact-errors.stderr b/tests/ui/cfg/cfg-target-compact-errors.stderr index bb858301eb5..219d9732c32 100644 --- a/tests/ui/cfg/cfg-target-compact-errors.stderr +++ b/tests/ui/cfg/cfg-target-compact-errors.stderr @@ -16,7 +16,13 @@ error[E0537]: invalid predicate `target_pointer` LL | #[cfg(target(os = "linux", pointer(width = "64")))] | ^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 3 previous errors +error: `cfg` predicate key must be an identifier + --> $DIR/cfg-target-compact-errors.rs:17:14 + | +LL | #[cfg(target(true))] + | ^^^^ + +error: aborting due to 4 previous errors Some errors have detailed explanations: E0537, E0565. For more information about an error, try `rustc --explain E0537`. From 476ea45c68223e4b2f9674d20f1aff8dd52fe1fb Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Wed, 16 Oct 2024 12:22:14 +0200 Subject: [PATCH 348/357] Emscripten: Xfail backtrace ui tests It is possible to link libunwind and use the normal backtrace code, but it fails to symbolize stack traces. I investigated and could get the list of instruction pointers and symbol names, but I'm not sure how to use the dwarf info to map from instruction pointer to source location. In any case, fixing this is probably not a high priority. See https://github.com/rust-lang/rust/issues/131738 --- tests/ui/backtrace/dylib-dep.rs | 1 + tests/ui/backtrace/line-tables-only.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/tests/ui/backtrace/dylib-dep.rs b/tests/ui/backtrace/dylib-dep.rs index fcd1f92e28e..a41931ad548 100644 --- a/tests/ui/backtrace/dylib-dep.rs +++ b/tests/ui/backtrace/dylib-dep.rs @@ -9,6 +9,7 @@ //@ ignore-musl musl doesn't support dynamic libraries (at least when the original test was written). //@ needs-unwind //@ compile-flags: -g -Copt-level=0 -Cstrip=none -Cforce-frame-pointers=yes +//@ ignore-emscripten Requires custom symbolization code //@ aux-crate: dylib_dep_helper=dylib-dep-helper.rs //@ aux-crate: auxiliary=dylib-dep-helper-aux.rs //@ run-pass diff --git a/tests/ui/backtrace/line-tables-only.rs b/tests/ui/backtrace/line-tables-only.rs index 044f59e483a..6624c71e184 100644 --- a/tests/ui/backtrace/line-tables-only.rs +++ b/tests/ui/backtrace/line-tables-only.rs @@ -10,6 +10,7 @@ //@ compile-flags: -Cstrip=none -Cdebuginfo=line-tables-only //@ ignore-android FIXME #17520 //@ ignore-fuchsia Backtraces not symbolized +//@ ignore-emscripten Requires custom symbolization code //@ needs-unwind //@ aux-build: line-tables-only-helper.rs From 89ea9e44f073a67a2b92de2ede5985acb1f810ec Mon Sep 17 00:00:00 2001 From: Michal Piotrowski Date: Wed, 16 Oct 2024 12:36:44 +0200 Subject: [PATCH 349/357] Fix trivially_copy_pass_by_ref in stable_mir --- compiler/stable_mir/src/mir/body.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/stable_mir/src/mir/body.rs b/compiler/stable_mir/src/mir/body.rs index 742469a1c93..f96487cc53c 100644 --- a/compiler/stable_mir/src/mir/body.rs +++ b/compiler/stable_mir/src/mir/body.rs @@ -1028,7 +1028,7 @@ impl ProjectionElem { ProjectionElem::Field(_idx, fty) => Ok(*fty), ProjectionElem::Index(_) | ProjectionElem::ConstantIndex { .. } => Self::index_ty(ty), ProjectionElem::Subslice { from, to, from_end } => { - Self::subslice_ty(ty, from, to, from_end) + Self::subslice_ty(ty, *from, *to, *from_end) } ProjectionElem::Downcast(_) => Ok(ty), ProjectionElem::OpaqueCast(ty) | ProjectionElem::Subtype(ty) => Ok(*ty), @@ -1039,13 +1039,13 @@ impl ProjectionElem { ty.kind().builtin_index().ok_or_else(|| error!("Cannot index non-array type: {ty:?}")) } - fn subslice_ty(ty: Ty, from: &u64, to: &u64, from_end: &bool) -> Result { + fn subslice_ty(ty: Ty, from: u64, to: u64, from_end: bool) -> Result { let ty_kind = ty.kind(); match ty_kind { TyKind::RigidTy(RigidTy::Slice(..)) => Ok(ty), TyKind::RigidTy(RigidTy::Array(inner, _)) if !from_end => Ty::try_new_array( inner, - to.checked_sub(*from).ok_or_else(|| error!("Subslice overflow: {from}..{to}"))?, + to.checked_sub(from).ok_or_else(|| error!("Subslice overflow: {from}..{to}"))?, ), TyKind::RigidTy(RigidTy::Array(inner, size)) => { let size = size.eval_target_usize()?; From a10a44956e4efddf4fdf0f7a8b10796b9ae965ea Mon Sep 17 00:00:00 2001 From: Michal Piotrowski Date: Wed, 16 Oct 2024 13:31:23 +0200 Subject: [PATCH 350/357] Fix needless_lifetimes in stable_mir --- compiler/stable_mir/src/mir/visit.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/stable_mir/src/mir/visit.rs b/compiler/stable_mir/src/mir/visit.rs index e2d1ff7fdd3..85205528979 100644 --- a/compiler/stable_mir/src/mir/visit.rs +++ b/compiler/stable_mir/src/mir/visit.rs @@ -487,7 +487,7 @@ pub struct PlaceRef<'a> { pub projection: &'a [ProjectionElem], } -impl<'a> PlaceRef<'a> { +impl PlaceRef<'_> { /// Get the type of this place. pub fn ty(&self, locals: &[LocalDecl]) -> Result { self.projection.iter().fold(Ok(locals[self.local].ty), |place_ty, elem| elem.ty(place_ty?)) From b2b4ad4cc94077eba1331acc534b5e36ae3e2603 Mon Sep 17 00:00:00 2001 From: Michal Piotrowski Date: Wed, 16 Oct 2024 15:44:16 +0200 Subject: [PATCH 351/357] Fix explicit_iter_loop in rustc_serialize --- compiler/rustc_serialize/src/serialize.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_serialize/src/serialize.rs b/compiler/rustc_serialize/src/serialize.rs index bae5f259fcc..db8555edd0f 100644 --- a/compiler/rustc_serialize/src/serialize.rs +++ b/compiler/rustc_serialize/src/serialize.rs @@ -288,7 +288,7 @@ impl> Decodable for Rc { impl> Encodable for [T] { default fn encode(&self, s: &mut S) { s.emit_usize(self.len()); - for e in self.iter() { + for e in self { e.encode(s); } } @@ -527,7 +527,7 @@ impl> Decodable for ThinVec { impl> Encodable for VecDeque { fn encode(&self, s: &mut S) { s.emit_usize(self.len()); - for e in self.iter() { + for e in self { e.encode(s); } } @@ -547,7 +547,7 @@ where { fn encode(&self, e: &mut S) { e.emit_usize(self.len()); - for (key, val) in self.iter() { + for (key, val) in self { key.encode(e); val.encode(e); } @@ -571,7 +571,7 @@ where { fn encode(&self, s: &mut S) { s.emit_usize(self.len()); - for e in self.iter() { + for e in self { e.encode(s); } } @@ -595,7 +595,7 @@ where { fn encode(&self, e: &mut E) { e.emit_usize(self.len()); - for (key, val) in self.iter() { + for (key, val) in self { key.encode(e); val.encode(e); } @@ -621,7 +621,7 @@ where { fn encode(&self, s: &mut E) { s.emit_usize(self.len()); - for e in self.iter() { + for e in self { e.encode(s); } } @@ -646,7 +646,7 @@ where { fn encode(&self, e: &mut E) { e.emit_usize(self.len()); - for (key, val) in self.iter() { + for (key, val) in self { key.encode(e); val.encode(e); } @@ -672,7 +672,7 @@ where { fn encode(&self, s: &mut E) { s.emit_usize(self.len()); - for e in self.iter() { + for e in self { e.encode(s); } } From 6d82559bc1d5e02705cec0726a25704882c79365 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Sat, 12 Oct 2024 12:34:58 +0200 Subject: [PATCH 352/357] rustdoc: Rename "object safe" to "dyn compatible" --- src/librustdoc/clean/types.rs | 2 +- src/librustdoc/html/markdown.rs | 2 +- src/librustdoc/html/render/print_item.rs | 14 ++++++------ src/librustdoc/html/render/sidebar.rs | 6 +++--- src/librustdoc/json/conversions.rs | 2 +- tests/rustdoc/dyn-compatibility.rs | 27 ++++++++++++++++++++++++ tests/rustdoc/sidebar/sidebar-items.rs | 6 +++--- tests/rustdoc/trait-object-safe.rs | 27 ------------------------ 8 files changed, 44 insertions(+), 42 deletions(-) create mode 100644 tests/rustdoc/dyn-compatibility.rs delete mode 100644 tests/rustdoc/trait-object-safe.rs diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index bc5bf4c0583..44295fa0cd9 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1450,7 +1450,7 @@ impl Trait { pub(crate) fn safety(&self, tcx: TyCtxt<'_>) -> hir::Safety { tcx.trait_def(self.def_id).safety } - pub(crate) fn is_object_safe(&self, tcx: TyCtxt<'_>) -> bool { + pub(crate) fn is_dyn_compatible(&self, tcx: TyCtxt<'_>) -> bool { tcx.is_dyn_compatible(self.def_id) } } diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 5dacabd031e..315b7742a4c 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -2002,7 +2002,7 @@ fn init_id_map() -> FxHashMap, usize> { map.insert("required-associated-consts".into(), 1); map.insert("required-methods".into(), 1); map.insert("provided-methods".into(), 1); - map.insert("object-safety".into(), 1); + map.insert("dyn-compatibility".into(), 1); map.insert("implementors".into(), 1); map.insert("synthetic-implementors".into(), 1); map.insert("implementations-list".into(), 1); diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 3c96f873681..5e9cbef99a9 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -934,16 +934,18 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: let cache = &cloned_shared.cache; let mut extern_crates = FxIndexSet::default(); - if !t.is_object_safe(cx.tcx()) { + if !t.is_dyn_compatible(cx.tcx()) { + // FIXME(dyn_compat_renaming): Update the URL once the Reference is updated. write_section_heading( w, - "Object Safety", - "object-safety", + "Dyn Compatibility", + "dyn-compatibility", None, &format!( - "

", + "

This trait is not \ + dyn compatible.

\ +

In older versions of Rust, dyn compatibility was called \"object safety\", \ + so this trait is not object safe.

", base = crate::clean::utils::DOC_RUST_LANG_ORG_CHANNEL ), ); diff --git a/src/librustdoc/html/render/sidebar.rs b/src/librustdoc/html/render/sidebar.rs index e7706e7fdea..6df9486e658 100644 --- a/src/librustdoc/html/render/sidebar.rs +++ b/src/librustdoc/html/render/sidebar.rs @@ -315,10 +315,10 @@ fn sidebar_trait<'a>( ); sidebar_assoc_items(cx, it, blocks); - if !t.is_object_safe(cx.tcx()) { + if !t.is_dyn_compatible(cx.tcx()) { blocks.push(LinkBlock::forced( - Link::new("object-safety", "Object Safety"), - "object-safety-note", + Link::new("dyn-compatibility", "Dyn Compatibility"), + "dyn-compatibility-note", )); } diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index b8791c9918b..77e7d83090b 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -672,7 +672,7 @@ impl FromClean for Trait { let tcx = renderer.tcx; let is_auto = trait_.is_auto(tcx); let is_unsafe = trait_.safety(tcx) == rustc_hir::Safety::Unsafe; - let is_object_safe = trait_.is_object_safe(tcx); + let is_object_safe = trait_.is_dyn_compatible(tcx); let clean::Trait { items, generics, bounds, .. } = trait_; Trait { is_auto, diff --git a/tests/rustdoc/dyn-compatibility.rs b/tests/rustdoc/dyn-compatibility.rs new file mode 100644 index 00000000000..9115f93bc3b --- /dev/null +++ b/tests/rustdoc/dyn-compatibility.rs @@ -0,0 +1,27 @@ +#![crate_name = "foo"] + +//@ has 'foo/trait.DynIncompatible.html' +//@ has - '//*[@class="dyn-compatibility-info"]' 'This trait is not dyn compatible.' +//@ has - '//*[@id="dyn-compatibility"]' 'Dyn Compatibility' +pub trait DynIncompatible { + fn foo() -> Self; +} + +//@ has 'foo/trait.DynIncompatible2.html' +//@ has - '//*[@class="dyn-compatibility-info"]' 'This trait is not dyn compatible.' +//@ has - '//*[@id="dyn-compatibility"]' 'Dyn Compatibility' +pub trait DynIncompatible2 { + fn foo(i: T); +} + +//@ has 'foo/trait.DynCompatible.html' +//@ !has - '//*[@class="dyn-compatibility-info"]' '' +//@ !has - '//*[@id="dyn-compatibility"]' '' +pub trait DynCompatible { + fn foo(&self); +} + +//@ has 'foo/struct.Foo.html' +//@ count - '//*[@class="dyn-compatibility-info"]' 0 +//@ count - '//*[@id="dyn-compatibility"]' 0 +pub struct Foo; diff --git a/tests/rustdoc/sidebar/sidebar-items.rs b/tests/rustdoc/sidebar/sidebar-items.rs index f3812143a7d..57c2eee91a9 100644 --- a/tests/rustdoc/sidebar/sidebar-items.rs +++ b/tests/rustdoc/sidebar/sidebar-items.rs @@ -14,7 +14,7 @@ //@ has - '//*[@class="sidebar-elems"]//section//a' 'Output' //@ has - '//div[@class="sidebar-elems"]//h3/a[@href="#provided-associated-types"]' 'Provided Associated Types' //@ has - '//*[@class="sidebar-elems"]//section//a' 'Extra' -//@ has - '//div[@class="sidebar-elems"]//h3/a[@href="#object-safety"]' 'Object Safety' +//@ has - '//div[@class="sidebar-elems"]//h3/a[@href="#dyn-compatibility"]' 'Dyn Compatibility' pub trait Foo { const FOO: usize; const BAR: u32 = 0; @@ -25,9 +25,9 @@ pub trait Foo { fn bar() -> Self::Output; } -//@ has foo/trait.Safe.html +//@ has foo/trait.DynCompatible.html //@ !has - '//div[@class="sidebar-elems"]//h3/a[@href="#object-safety"]' '' -pub trait Safe { +pub trait DynCompatible { fn access(&self); } diff --git a/tests/rustdoc/trait-object-safe.rs b/tests/rustdoc/trait-object-safe.rs deleted file mode 100644 index b4e986c8f69..00000000000 --- a/tests/rustdoc/trait-object-safe.rs +++ /dev/null @@ -1,27 +0,0 @@ -#![crate_name = "foo"] - -//@ has 'foo/trait.Unsafe.html' -//@ has - '//*[@class="object-safety-info"]' 'This trait is not object safe.' -//@ has - '//*[@id="object-safety"]' 'Object Safety' -pub trait Unsafe { - fn foo() -> Self; -} - -//@ has 'foo/trait.Unsafe2.html' -//@ has - '//*[@class="object-safety-info"]' 'This trait is not object safe.' -//@ has - '//*[@id="object-safety"]' 'Object Safety' -pub trait Unsafe2 { - fn foo(i: T); -} - -//@ has 'foo/trait.Safe.html' -//@ !has - '//*[@class="object-safety-info"]' '' -//@ !has - '//*[@id="object-safety"]' '' -pub trait Safe { - fn foo(&self); -} - -//@ has 'foo/struct.Foo.html' -//@ count - '//*[@class="object-safety-info"]' 0 -//@ count - '//*[@id="object-safety"]' 0 -pub struct Foo; From 8991fd4bed6583757c5df3f37b7c17fd58963f09 Mon Sep 17 00:00:00 2001 From: Charles Celerier Date: Tue, 15 Oct 2024 15:47:10 -0400 Subject: [PATCH 353/357] Ignore lint-non-snake-case-crate#proc_macro_ on targets without unwind The lint-non-snake-case-crate test may emit a warning in stderr if the target does not support unwinding ``` warning: building proc macro crate with `panic=abort` may crash the compiler should the proc-macro panic ``` Consequently, the test will fail on targets that don't support unwinding as written. This change prevents lint-non-snake-case-crate#proc_macro_ from running on targets that don't support unwind by using the needs-unwind directive. --- .../non-snake-case/lint-non-snake-case-crate.cdylib_.stderr | 4 ++-- .../non-snake-case/lint-non-snake-case-crate.dylib_.stderr | 4 ++-- .../lint/non-snake-case/lint-non-snake-case-crate.lib_.stderr | 4 ++-- .../lint-non-snake-case-crate.proc_macro_.stderr | 4 ++-- .../non-snake-case/lint-non-snake-case-crate.rlib_.stderr | 4 ++-- tests/ui/lint/non-snake-case/lint-non-snake-case-crate.rs | 4 ++++ .../lint-non-snake-case-crate.staticlib_.stderr | 4 ++-- 7 files changed, 16 insertions(+), 12 deletions(-) diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.cdylib_.stderr b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.cdylib_.stderr index 9bccb270627..140d72b9742 100644 --- a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.cdylib_.stderr +++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.cdylib_.stderr @@ -1,11 +1,11 @@ error: crate `NonSnakeCase` should have a snake case name - --> $DIR/lint-non-snake-case-crate.rs:25:18 + --> $DIR/lint-non-snake-case-crate.rs:29:18 | LL | #![crate_name = "NonSnakeCase"] | ^^^^^^^^^^^^ help: convert the identifier to snake case: `non_snake_case` | note: the lint level is defined here - --> $DIR/lint-non-snake-case-crate.rs:27:9 + --> $DIR/lint-non-snake-case-crate.rs:31:9 | LL | #![deny(non_snake_case)] | ^^^^^^^^^^^^^^ diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.dylib_.stderr b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.dylib_.stderr index 9bccb270627..140d72b9742 100644 --- a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.dylib_.stderr +++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.dylib_.stderr @@ -1,11 +1,11 @@ error: crate `NonSnakeCase` should have a snake case name - --> $DIR/lint-non-snake-case-crate.rs:25:18 + --> $DIR/lint-non-snake-case-crate.rs:29:18 | LL | #![crate_name = "NonSnakeCase"] | ^^^^^^^^^^^^ help: convert the identifier to snake case: `non_snake_case` | note: the lint level is defined here - --> $DIR/lint-non-snake-case-crate.rs:27:9 + --> $DIR/lint-non-snake-case-crate.rs:31:9 | LL | #![deny(non_snake_case)] | ^^^^^^^^^^^^^^ diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.lib_.stderr b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.lib_.stderr index 9bccb270627..140d72b9742 100644 --- a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.lib_.stderr +++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.lib_.stderr @@ -1,11 +1,11 @@ error: crate `NonSnakeCase` should have a snake case name - --> $DIR/lint-non-snake-case-crate.rs:25:18 + --> $DIR/lint-non-snake-case-crate.rs:29:18 | LL | #![crate_name = "NonSnakeCase"] | ^^^^^^^^^^^^ help: convert the identifier to snake case: `non_snake_case` | note: the lint level is defined here - --> $DIR/lint-non-snake-case-crate.rs:27:9 + --> $DIR/lint-non-snake-case-crate.rs:31:9 | LL | #![deny(non_snake_case)] | ^^^^^^^^^^^^^^ diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.proc_macro_.stderr b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.proc_macro_.stderr index 9bccb270627..140d72b9742 100644 --- a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.proc_macro_.stderr +++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.proc_macro_.stderr @@ -1,11 +1,11 @@ error: crate `NonSnakeCase` should have a snake case name - --> $DIR/lint-non-snake-case-crate.rs:25:18 + --> $DIR/lint-non-snake-case-crate.rs:29:18 | LL | #![crate_name = "NonSnakeCase"] | ^^^^^^^^^^^^ help: convert the identifier to snake case: `non_snake_case` | note: the lint level is defined here - --> $DIR/lint-non-snake-case-crate.rs:27:9 + --> $DIR/lint-non-snake-case-crate.rs:31:9 | LL | #![deny(non_snake_case)] | ^^^^^^^^^^^^^^ diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.rlib_.stderr b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.rlib_.stderr index 9bccb270627..140d72b9742 100644 --- a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.rlib_.stderr +++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.rlib_.stderr @@ -1,11 +1,11 @@ error: crate `NonSnakeCase` should have a snake case name - --> $DIR/lint-non-snake-case-crate.rs:25:18 + --> $DIR/lint-non-snake-case-crate.rs:29:18 | LL | #![crate_name = "NonSnakeCase"] | ^^^^^^^^^^^^ help: convert the identifier to snake case: `non_snake_case` | note: the lint level is defined here - --> $DIR/lint-non-snake-case-crate.rs:27:9 + --> $DIR/lint-non-snake-case-crate.rs:31:9 | LL | #![deny(non_snake_case)] | ^^^^^^^^^^^^^^ diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.rs b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.rs index 57604d99a07..097b246c165 100644 --- a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.rs +++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.rs @@ -22,6 +22,10 @@ //@[rlib_] compile-flags: --crate-type=rlib //@[staticlib_] compile-flags: --crate-type=staticlib +// The compiler may emit a warning that causes stderr output +// that contains a warning this test does not wish to check. +//@[proc_macro_] needs-unwind + #![crate_name = "NonSnakeCase"] //[cdylib_,dylib_,lib_,proc_macro_,rlib_,staticlib_]~^ ERROR crate `NonSnakeCase` should have a snake case name #![deny(non_snake_case)] diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.staticlib_.stderr b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.staticlib_.stderr index 9bccb270627..140d72b9742 100644 --- a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.staticlib_.stderr +++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.staticlib_.stderr @@ -1,11 +1,11 @@ error: crate `NonSnakeCase` should have a snake case name - --> $DIR/lint-non-snake-case-crate.rs:25:18 + --> $DIR/lint-non-snake-case-crate.rs:29:18 | LL | #![crate_name = "NonSnakeCase"] | ^^^^^^^^^^^^ help: convert the identifier to snake case: `non_snake_case` | note: the lint level is defined here - --> $DIR/lint-non-snake-case-crate.rs:27:9 + --> $DIR/lint-non-snake-case-crate.rs:31:9 | LL | #![deny(non_snake_case)] | ^^^^^^^^^^^^^^ From 682bca30ccbfe1dc94e8c1abbd458d7f7be18077 Mon Sep 17 00:00:00 2001 From: dufucun Date: Thu, 17 Oct 2024 00:16:19 +0800 Subject: [PATCH 354/357] Fix mismatched quotation mark --- tests/ui/mir/mir-inlining/always-encode-mirs.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ui/mir/mir-inlining/always-encode-mirs.rs b/tests/ui/mir/mir-inlining/always-encode-mirs.rs index 9029ff6499b..4553560baaa 100644 --- a/tests/ui/mir/mir-inlining/always-encode-mirs.rs +++ b/tests/ui/mir/mir-inlining/always-encode-mirs.rs @@ -1,6 +1,6 @@ // Regression test for MIR inlining with -Zalways-encode-mir enabled in the auxiliary crate. // Previously we inlined function not eligible for inlining which lead to linking error: -// undefined reference to `internal::S' +// undefined reference to `internal::S` // //@ aux-build:internal.rs //@ build-pass From e0e2c4534a55713520d6cd00e19d585852bc432d Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 16 Oct 2024 11:12:55 -0700 Subject: [PATCH 355/357] Remove `Waker::waker` from 1.82 relnotes --- RELEASES.md | 1 - 1 file changed, 1 deletion(-) diff --git a/RELEASES.md b/RELEASES.md index 1213a596024..ac72a1d885c 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -123,7 +123,6 @@ Stabilized APIs These APIs are now stable in const contexts: - [`std::task::Waker::from_raw`](https://doc.rust-lang.org/nightly/std/task/struct.Waker.html#method.from_raw) -- [`std::task::Waker::waker`](https://doc.rust-lang.org/nightly/std/task/struct.Waker.html#method.from_raw) - [`std::task::Context::from_waker`](https://doc.rust-lang.org/nightly/std/task/struct.Context.html#method.from_waker) - [`std::task::Context::waker`](https://doc.rust-lang.org/nightly/std/task/struct.Context.html#method.waker) - [`$integer::from_str_radix`](https://doc.rust-lang.org/nightly/std/primitive.u32.html#method.from_str_radix) From aff69ccfb2b7da9374dd47f13e626a980ce8338a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Thu, 17 Oct 2024 10:04:47 +0300 Subject: [PATCH 356/357] Preparing for merge from rust-lang/rust --- src/tools/rust-analyzer/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer/rust-version b/src/tools/rust-analyzer/rust-version index f217c6a19cb..d0f9fa7ac42 100644 --- a/src/tools/rust-analyzer/rust-version +++ b/src/tools/rust-analyzer/rust-version @@ -1 +1 @@ -cf24c73141a77db730f4b7fda69dcd7e8b113b51 +dd5127615ad626741a1116d022cf784637ac05df From 6e4f8fea36cd04f623c46d99adc3c370b1879883 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Thu, 17 Oct 2024 10:10:01 +0300 Subject: [PATCH 357/357] Bump rustc crates --- src/tools/rust-analyzer/Cargo.lock | 24 +++++++++---------- src/tools/rust-analyzer/Cargo.toml | 10 ++++---- .../crates/parser/src/lexed_str.rs | 5 ++-- 3 files changed, 20 insertions(+), 19 deletions(-) diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock index d09315d9061..4a6da47a47d 100644 --- a/src/tools/rust-analyzer/Cargo.lock +++ b/src/tools/rust-analyzer/Cargo.lock @@ -1497,9 +1497,9 @@ dependencies = [ [[package]] name = "ra-ap-rustc_abi" -version = "0.68.0" +version = "0.71.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a8cb51bb4534ac3e9c74f1d9bd90e607e60f94f734b1cf1a66f753ad2af6ed7" +checksum = "c6999d098000b98415939f13158dac78cb3eeeb7b0c073847f3e4b623866e27c" dependencies = [ "bitflags 2.6.0", "ra-ap-rustc_index", @@ -1508,9 +1508,9 @@ dependencies = [ [[package]] name = "ra-ap-rustc_index" -version = "0.68.0" +version = "0.71.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b640fba2b7ef4f875459e2e76daeb846ef341d1d376fa758962ac0eba79bce6" +checksum = "ae9fb312d942817dab10790881f555928c1f6a11a85186e8e573ad4a86c7d3be" dependencies = [ "arrayvec", "ra-ap-rustc_index_macros", @@ -1519,9 +1519,9 @@ dependencies = [ [[package]] name = "ra-ap-rustc_index_macros" -version = "0.68.0" +version = "0.71.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "faef502419ba5ac9d3079b1a835c6e5b4e605388254bbe55eb5683936f541be9" +checksum = "766e3990eb1066a06deefc561b5a01b32ca5c9211feea31cbf4ed50611519872" dependencies = [ "proc-macro2", "quote", @@ -1530,9 +1530,9 @@ dependencies = [ [[package]] name = "ra-ap-rustc_lexer" -version = "0.68.0" +version = "0.71.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5da7f9d533b8d5be6704558da741ff20b982ad4647b1e9e08632853e4fecf9d5" +checksum = "f4afa98eb7889c137d5a3f1cd189089e16da04d1e4837d358a67aa3dab10ffbe" dependencies = [ "unicode-properties", "unicode-xid", @@ -1540,9 +1540,9 @@ dependencies = [ [[package]] name = "ra-ap-rustc_parse_format" -version = "0.68.0" +version = "0.71.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94389cf81c651b1bda9ac45d3de6a2d851bb6fd4cb893875daa44e419c94205f" +checksum = "d9234c96ffb0565286790407fb7eb7f55ebf69267de4db382fdec0a17f14b0e2" dependencies = [ "ra-ap-rustc_index", "ra-ap-rustc_lexer", @@ -1550,9 +1550,9 @@ dependencies = [ [[package]] name = "ra-ap-rustc_pattern_analysis" -version = "0.68.0" +version = "0.71.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3679d8dd0114ed6000918309f843782738e51c99d8e4baec0d0f706e4d948819" +checksum = "273d5f72926a58c7eea27aebc898d1d5b32d23d2342f692a94a2cf8746aa4a2f" dependencies = [ "ra-ap-rustc_index", "rustc-hash", diff --git a/src/tools/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/Cargo.toml index d97d4d4d368..8c099f324b4 100644 --- a/src/tools/rust-analyzer/Cargo.toml +++ b/src/tools/rust-analyzer/Cargo.toml @@ -85,11 +85,11 @@ tt = { path = "./crates/tt", version = "0.0.0" } vfs-notify = { path = "./crates/vfs-notify", version = "0.0.0" } vfs = { path = "./crates/vfs", version = "0.0.0" } -ra-ap-rustc_lexer = { version = "0.68.0", default-features = false } -ra-ap-rustc_parse_format = { version = "0.68.0", default-features = false } -ra-ap-rustc_index = { version = "0.68.0", default-features = false } -ra-ap-rustc_abi = { version = "0.68.0", default-features = false } -ra-ap-rustc_pattern_analysis = { version = "0.68.0", default-features = false } +ra-ap-rustc_lexer = { version = "0.71.0", default-features = false } +ra-ap-rustc_parse_format = { version = "0.71.0", default-features = false } +ra-ap-rustc_index = { version = "0.71.0", default-features = false } +ra-ap-rustc_abi = { version = "0.71.0", default-features = false } +ra-ap-rustc_pattern_analysis = { version = "0.71.0", default-features = false } # local crates that aren't published to crates.io. These should not have versions. test-fixture = { path = "./crates/test-fixture" } diff --git a/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs b/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs index 7ea23b4f752..5322463a713 100644 --- a/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs +++ b/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs @@ -188,10 +188,11 @@ impl<'a> Converter<'a> { rustc_lexer::TokenKind::RawIdent => IDENT, - rustc_lexer::TokenKind::GuardedStrPrefix => { + rustc_lexer::TokenKind::GuardedStrPrefix if self.edition.at_least_2024() => { err = "Invalid string literal (reserved syntax)"; ERROR - }, + } + rustc_lexer::TokenKind::GuardedStrPrefix => POUND, rustc_lexer::TokenKind::Literal { kind, .. } => { self.extend_literal(token_text.len(), kind);

, _: F) -> Parser> + { loop {} } + +fn main() { + if_impl().0; +} diff --git a/tests/crashes/130967.rs b/tests/crashes/130967.rs new file mode 100644 index 00000000000..8a3aae72c20 --- /dev/null +++ b/tests/crashes/130967.rs @@ -0,0 +1,13 @@ +//@ known-bug: #130967 + +trait Producer { + type Produced; + fn make_one() -> Self::Produced; +} + +impl Producer for () { + type Produced = Option; + fn make_one() -> Self::Produced { + loop {} + } +} diff --git a/tests/crashes/131046.rs b/tests/crashes/131046.rs new file mode 100644 index 00000000000..2638705ae18 --- /dev/null +++ b/tests/crashes/131046.rs @@ -0,0 +1,15 @@ +//@ known-bug: #131046 + +trait Owner { + const C: u32; +} + +impl Owner for () { + const C: u32 = N; +} + +fn take0(_: impl Owner = { N }>) {} + +fn main() { + take0::<128>(()); +} diff --git a/tests/crashes/131048.rs b/tests/crashes/131048.rs new file mode 100644 index 00000000000..d57e9921a8a --- /dev/null +++ b/tests/crashes/131048.rs @@ -0,0 +1,7 @@ +//@ known-bug: #131048 + +impl std::ops::CoerceUnsized for A {} + +fn main() { + format_args!("Hello, world!"); +} diff --git a/tests/crashes/131050.rs b/tests/crashes/131050.rs new file mode 100644 index 00000000000..07f8662d016 --- /dev/null +++ b/tests/crashes/131050.rs @@ -0,0 +1,27 @@ +//@ known-bug: #131050 +//@ compile-flags: --edition=2021 + +fn query_as() {} + +async fn create_user() { + query_as(); +} + +async fn post_user_filter() -> impl Filter { + AndThen(&(), || async { create_user().await }) +} + +async fn get_app() -> impl Send { + post_user_filter().await +} + +trait Filter {} + +struct AndThen(T, F); + +impl Filter for AndThen +where + F: Fn() -> R, + R: Send, +{ +} diff --git a/tests/crashes/131052.rs b/tests/crashes/131052.rs new file mode 100644 index 00000000000..7ae3ec08f3e --- /dev/null +++ b/tests/crashes/131052.rs @@ -0,0 +1,8 @@ +//@ known-bug: #131052 +#![feature(adt_const_params)] + +struct ConstBytes; + +pub fn main() { + let _: ConstBytes = ConstBytes::; +} diff --git a/tests/crashes/131101.rs b/tests/crashes/131101.rs new file mode 100644 index 00000000000..3ec441101b7 --- /dev/null +++ b/tests/crashes/131101.rs @@ -0,0 +1,12 @@ +//@ known-bug: #131101 +trait Foo { + fn do_x(&self) -> [u8; N]; +} + +struct Bar; + +impl Foo for Bar { + fn do_x(&self) -> [u8; 3] { + [0u8; 3] + } +} diff --git a/tests/crashes/131102.rs b/tests/crashes/131102.rs new file mode 100644 index 00000000000..12b35f8d1b2 --- /dev/null +++ b/tests/crashes/131102.rs @@ -0,0 +1,4 @@ +//@ known-bug: #131102 +pub struct Blorb([String; N]); +pub struct Wrap(Blorb<0>); +pub const fn i(_: Wrap) {} diff --git a/tests/crashes/131103.rs b/tests/crashes/131103.rs new file mode 100644 index 00000000000..70193e8b3bd --- /dev/null +++ b/tests/crashes/131103.rs @@ -0,0 +1,6 @@ +//@ known-bug: #131103 +struct Struct(pub [u8; N]); + +pub fn function(value: Struct<3>) -> u8 { + value.0[0] +} diff --git a/tests/crashes/131190.rs b/tests/crashes/131190.rs new file mode 100644 index 00000000000..3a0e64c69d5 --- /dev/null +++ b/tests/crashes/131190.rs @@ -0,0 +1,19 @@ +//@ known-bug: #131190 +//@ compile-flags: -Cinstrument-coverage --edition=2018 + +use std::future::Future; + +pub fn block_on(fut: impl Future) -> T {} + +async fn call_once(f: impl async FnOnce(DropMe)) { + f(DropMe("world")).await; +} + +struct DropMe(&'static str); + +pub fn main() { + block_on(async { + let async_closure = async move |a: DropMe| {}; + call_once(async_closure).await; + }); +} diff --git a/tests/crashes/131227.rs b/tests/crashes/131227.rs new file mode 100644 index 00000000000..f46185b5b4a --- /dev/null +++ b/tests/crashes/131227.rs @@ -0,0 +1,16 @@ +//@ known-bug: #131227 +//@ compile-flags: -Zmir-opt-level=3 + +static mut G: () = (); + +fn myfunc() -> i32 { + let var = &raw mut G; + if var.is_null() { + return 0; + } + 0 +} + +fn main() { + myfunc(); +} diff --git a/tests/crashes/131292.rs b/tests/crashes/131292.rs new file mode 100644 index 00000000000..01e0eca0bd6 --- /dev/null +++ b/tests/crashes/131292.rs @@ -0,0 +1,7 @@ +//@ known-bug: #131292 +//@ only-x86_64 +use std::arch::asm; + +unsafe fn f6() { + asm!(concat!(r#"lJ𐏿Æ�.𐏿�"#, "{}/day{:02}.txt")); +} diff --git a/tests/crashes/131294-2.rs b/tests/crashes/131294-2.rs new file mode 100644 index 00000000000..130a8b10fb7 --- /dev/null +++ b/tests/crashes/131294-2.rs @@ -0,0 +1,25 @@ +//@ known-bug: #131294 +//@ compile-flags: -Zmir-opt-level=5 -Zvalidate-mir -Zcross-crate-inline-threshold=always + +// https://github.com/rust-lang/rust/issues/131294#issuecomment-2395088049 second comment +struct Rows; + +impl Iterator for Rows { + type Item = String; + + fn next() -> Option { + let args = format_args!("Hello world"); + + { + match args.as_str() { + Some(t) => t.to_owned(), + None => String::new(), + } + } + .into() + } +} + +fn main() { + Rows.next(); +} diff --git a/tests/crashes/131294.rs b/tests/crashes/131294.rs new file mode 100644 index 00000000000..ec6c9567467 --- /dev/null +++ b/tests/crashes/131294.rs @@ -0,0 +1,16 @@ +//@ known-bug: #131294 +//@ compile-flags: -Zmir-opt-level=5 -Zvalidate-mir -Zcross-crate-inline-threshold=always + +struct Rows; + +impl Iterator for Rows { + type Item = String; + + fn next() -> Option { + std::fmt::format(format_args!("Hello world")).into() + } +} + +fn main() { + Rows.next(); +} diff --git a/tests/crashes/131295.rs b/tests/crashes/131295.rs new file mode 100644 index 00000000000..f31d6bc324a --- /dev/null +++ b/tests/crashes/131295.rs @@ -0,0 +1,9 @@ +//@ known-bug: #131295 + +#![feature(generic_const_exprs)] + +async fn foo<'a>() -> [(); { + let _y: &'a (); + 4 + }] { +} diff --git a/tests/crashes/131298.rs b/tests/crashes/131298.rs new file mode 100644 index 00000000000..833f1b04ffa --- /dev/null +++ b/tests/crashes/131298.rs @@ -0,0 +1,12 @@ +//@ known-bug: #131298 + +fn dyn_hoops() -> *const dyn Iterator { + loop {} +} + +mod typeck { + type Opaque = impl Sized; + fn define() -> Opaque { + let _: Opaque = super::dyn_hoops::(); + } +} diff --git a/tests/crashes/131342-2.rs b/tests/crashes/131342-2.rs new file mode 100644 index 00000000000..79b6a837a49 --- /dev/null +++ b/tests/crashes/131342-2.rs @@ -0,0 +1,40 @@ +//@ known-bug: #131342 +// see also: 131342.rs + +fn main() { + problem_thingy(Once); +} + +struct Once; + +impl Iterator for Once { + type Item = (); +} + +fn problem_thingy(items: impl Iterator) { + let peeker = items.peekable(); + problem_thingy(&peeker); +} + +trait Iterator { + type Item; + + fn peekable(self) -> Peekable + where + Self: Sized, + { + loop {} + } +} + +struct Peekable { + _peeked: I::Item, +} + +impl Iterator for Peekable { + type Item = I::Item; +} + +impl Iterator for &I { + type Item = I::Item; +} diff --git a/tests/crashes/131342.rs b/tests/crashes/131342.rs new file mode 100644 index 00000000000..7f7ee9c9ac1 --- /dev/null +++ b/tests/crashes/131342.rs @@ -0,0 +1,16 @@ +//@ known-bug: #131342 +// see also: 131342-2.rs + +fn main() { + let mut items = vec![1, 2, 3, 4, 5].into_iter(); + problem_thingy(&mut items); +} + +fn problem_thingy(items: &mut impl Iterator) { + let mut peeker = items.peekable(); + match peeker.peek() { + Some(_) => (), + None => return (), + } + problem_thingy(&mut peeker); +} diff --git a/tests/crashes/131347.rs b/tests/crashes/131347.rs new file mode 100644 index 00000000000..15f367d79e2 --- /dev/null +++ b/tests/crashes/131347.rs @@ -0,0 +1,9 @@ +//@ known-bug: #131347 +//@ compile-flags: -Zmir-opt-level=5 -Zvalidate-mir + +struct S; +static STUFF: [i8] = [0; S::N]; + +fn main() { + assert_eq!(STUFF, [0; 63]); +} diff --git a/tests/crashes/131373.rs b/tests/crashes/131373.rs new file mode 100644 index 00000000000..661fecd7620 --- /dev/null +++ b/tests/crashes/131373.rs @@ -0,0 +1,33 @@ +//@ known-bug: #131373 + +trait LockReference: 'static { + type Ref<'a>; +} + +struct SliceRef<'a, T: ?Sized> { + _x: &'a T, +} + +impl<'a, T: ?Sized, SR: LockReference> IntoIterator for SliceRef<'a, T> +where + &'a T: IntoIterator, +{ + type Item = SR::Ref<'a>; + type IntoIter = std::iter::Map<<&'a T as IntoIterator>::IntoIter, + for<'c> fn(&'c SR) -> SR::Ref<'c>>; + fn into_iter(self) -> Self::IntoIter { + loop {} + } +} + +impl LockReference for () { + type Ref<'a> = (); +} + +fn locked() -> SliceRef<'static, [()]> { + loop {} +} + +fn main() { + let _ = locked().into_iter(); +} diff --git a/tests/crashes/131406.rs b/tests/crashes/131406.rs new file mode 100644 index 00000000000..ea642f94928 --- /dev/null +++ b/tests/crashes/131406.rs @@ -0,0 +1,12 @@ +//@ known-bug: #131406 + +trait Owner { + const C: u32 = N; +} + +impl Owner for () {} +fn take0(_: impl Owner = { N }>) {} + +fn main() { + take0::<128>(()); +} From 7a9a9cba3f02445e2e1f3d34b31a588405cf68a9 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 9 Oct 2024 16:20:39 +0200 Subject: [PATCH 120/357] epoll: rename blocking_epoll_callback since it is not just called after unblocking --- src/tools/miri/src/shims/unix/linux/epoll.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/tools/miri/src/shims/unix/linux/epoll.rs b/src/tools/miri/src/shims/unix/linux/epoll.rs index 81a6739728b..b3c66c1b578 100644 --- a/src/tools/miri/src/shims/unix/linux/epoll.rs +++ b/src/tools/miri/src/shims/unix/linux/epoll.rs @@ -480,7 +480,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } if timeout == 0 || !ready_list_empty { // If the ready list is not empty, or the timeout is 0, we can return immediately. - blocking_epoll_callback(epfd_value, weak_epfd, dest, &event, this)?; + return_ready_list(epfd_value, weak_epfd, dest, &event, this)?; } else { // Blocking let timeout = match timeout { @@ -508,7 +508,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { event: MPlaceTy<'tcx>, } @unblock = |this| { - blocking_epoll_callback(epfd_value, weak_epfd, &dest, &event, this)?; + return_ready_list(epfd_value, weak_epfd, &dest, &event, this)?; interp_ok(()) } @timeout = |this| { @@ -636,8 +636,9 @@ fn check_and_update_one_event_interest<'tcx>( } } -/// Callback function after epoll_wait unblocks -fn blocking_epoll_callback<'tcx>( +/// Stores the ready list of the `epfd` epoll instance into `events` (which must be an array), +/// and the number of returned events into `dest`. +fn return_ready_list<'tcx>( epfd_value: i32, weak_epfd: WeakFileDescriptionRef, dest: &MPlaceTy<'tcx>, From f64c9c64164664bcd7ccad4a68ccd97f11684a22 Mon Sep 17 00:00:00 2001 From: Yoh Deadfall Date: Tue, 8 Oct 2024 23:26:55 +0300 Subject: [PATCH 121/357] Fixed pthread_getname_np impl for glibc --- .../src/shims/unix/linux/foreign_items.rs | 26 +++++-- .../tests/pass-dep/libc/pthread-threadname.rs | 78 +++++++++++++++---- 2 files changed, 80 insertions(+), 24 deletions(-) diff --git a/src/tools/miri/src/shims/unix/linux/foreign_items.rs b/src/tools/miri/src/shims/unix/linux/foreign_items.rs index 4b5f3b6c81b..3722cc2f3ca 100644 --- a/src/tools/miri/src/shims/unix/linux/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/linux/foreign_items.rs @@ -9,6 +9,11 @@ use crate::machine::{SIGRTMAX, SIGRTMIN}; use crate::shims::unix::*; use crate::*; +// The documentation of glibc complains that the kernel never exposes +// TASK_COMM_LEN through the headers, so it's assumed to always be 16 bytes +// long including a null terminator. +const TASK_COMM_LEN: usize = 16; + pub fn is_dyn_sym(name: &str) -> bool { matches!(name, "statx") } @@ -74,22 +79,29 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "pthread_setname_np" => { let [thread, name] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let max_len = 16; let res = this.pthread_setname_np( this.read_scalar(thread)?, this.read_scalar(name)?, - max_len, + TASK_COMM_LEN, )?; this.write_scalar(res, dest)?; } "pthread_getname_np" => { let [thread, name, len] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let res = this.pthread_getname_np( - this.read_scalar(thread)?, - this.read_scalar(name)?, - this.read_scalar(len)?, - )?; + // The function's behavior isn't portable between platforms. + // In case of glibc, the length of the output buffer must + // be not shorter than TASK_COMM_LEN. + let len = this.read_scalar(len)?; + let res = if len.to_target_usize(this)? < TASK_COMM_LEN as u64 { + this.eval_libc("ERANGE") + } else { + this.pthread_getname_np( + this.read_scalar(thread)?, + this.read_scalar(name)?, + len, + )? + }; this.write_scalar(res, dest)?; } "gettid" => { diff --git a/src/tools/miri/tests/pass-dep/libc/pthread-threadname.rs b/src/tools/miri/tests/pass-dep/libc/pthread-threadname.rs index a94f960f442..a2cc7bfbe46 100644 --- a/src/tools/miri/tests/pass-dep/libc/pthread-threadname.rs +++ b/src/tools/miri/tests/pass-dep/libc/pthread-threadname.rs @@ -5,6 +5,9 @@ use std::ffi::CString; use std::thread; fn main() { + // The short name should be shorter than 16 bytes which POSIX promises + // for thread names. The length includes a null terminator. + let short_name = "test_named".to_owned(); let long_name = std::iter::once("test_named_thread_truncation") .chain(std::iter::repeat(" yada").take(100)) .collect::(); @@ -48,23 +51,64 @@ fn main() { } } - let result = thread::Builder::new().name(long_name.clone()).spawn(move || { - // Rust remembers the full thread name itself. - assert_eq!(thread::current().name(), Some(long_name.as_str())); + thread::Builder::new() + .name(short_name.clone()) + .spawn(move || { + // Rust remembers the full thread name itself. + assert_eq!(thread::current().name(), Some(short_name.as_str())); - // But the system is limited -- make sure we successfully set a truncation. - let mut buf = vec![0u8; long_name.len() + 1]; - assert_eq!(get_thread_name(&mut buf), 0); - let cstr = CStr::from_bytes_until_nul(&buf).unwrap(); - assert!(cstr.to_bytes().len() >= 15, "name is too short: len={}", cstr.to_bytes().len()); // POSIX seems to promise at least 15 chars - assert!(long_name.as_bytes().starts_with(cstr.to_bytes())); + // Note that glibc requires 15 bytes long buffer exculding a null terminator. + // Otherwise, `pthread_getname_np` returns an error. + let mut buf = vec![0u8; short_name.len().max(15) + 1]; + assert_eq!(get_thread_name(&mut buf), 0); - // Also test directly calling pthread_setname to check its return value. - assert_eq!(set_thread_name(&cstr), 0); - // But with a too long name it should fail (except on FreeBSD where the - // function has no return, hence cannot indicate failure). - #[cfg(not(target_os = "freebsd"))] - assert_ne!(set_thread_name(&CString::new(long_name).unwrap()), 0); - }); - result.unwrap().join().unwrap(); + let cstr = CStr::from_bytes_until_nul(&buf).unwrap(); + // POSIX seems to promise at least 15 chars excluding a null terminator. + assert_eq!(short_name.as_bytes(), cstr.to_bytes()); + + // Also test directly calling pthread_setname to check its return value. + assert_eq!(set_thread_name(&cstr), 0); + + // For glibc used by linux-gnu there should be a failue, + // if a shorter than 16 bytes buffer is provided, even if that would be + // large enough for the thread name. + #[cfg(target_os = "linux")] + assert_eq!(get_thread_name(&mut buf[..15]), libc::ERANGE); + }) + .unwrap() + .join() + .unwrap(); + + thread::Builder::new() + .name(long_name.clone()) + .spawn(move || { + // Rust remembers the full thread name itself. + assert_eq!(thread::current().name(), Some(long_name.as_str())); + + // But the system is limited -- make sure we successfully set a truncation. + // Note that there's no specific to glibc buffer requirement, since the value + // `long_name` is longer than 16 bytes including a null terminator. + let mut buf = vec![0u8; long_name.len() + 1]; + assert_eq!(get_thread_name(&mut buf), 0); + + let cstr = CStr::from_bytes_until_nul(&buf).unwrap(); + // POSIX seems to promise at least 15 chars excluding a null terminator. + assert!( + cstr.to_bytes().len() >= 15, + "name is too short: len={}", + cstr.to_bytes().len() + ); + assert!(long_name.as_bytes().starts_with(cstr.to_bytes())); + + // Also test directly calling pthread_setname to check its return value. + assert_eq!(set_thread_name(&cstr), 0); + + // But with a too long name it should fail (except on FreeBSD where the + // function has no return, hence cannot indicate failure). + #[cfg(not(target_os = "freebsd"))] + assert_ne!(set_thread_name(&CString::new(long_name).unwrap()), 0); + }) + .unwrap() + .join() + .unwrap(); } From 45606066029ece21e5df869c52419df7a6c3990a Mon Sep 17 00:00:00 2001 From: Frank Rehwinkel Date: Tue, 8 Oct 2024 19:12:31 -0400 Subject: [PATCH 122/357] epoll: change clock to be per event --- src/tools/miri/src/shims/unix/linux/epoll.rs | 22 +++++++-------- .../libc/libc-epoll-data-race.rs} | 27 +++++++------------ .../fail-dep/libc/libc-epoll-data-race.stderr | 20 ++++++++++++++ 3 files changed, 41 insertions(+), 28 deletions(-) rename src/tools/miri/tests/{pass-dep/libc/libc-epoll-clock-sync.rs => fail-dep/libc/libc-epoll-data-race.rs} (82%) create mode 100644 src/tools/miri/tests/fail-dep/libc/libc-epoll-data-race.stderr diff --git a/src/tools/miri/src/shims/unix/linux/epoll.rs b/src/tools/miri/src/shims/unix/linux/epoll.rs index 81a6739728b..cc6b9e94f36 100644 --- a/src/tools/miri/src/shims/unix/linux/epoll.rs +++ b/src/tools/miri/src/shims/unix/linux/epoll.rs @@ -32,11 +32,13 @@ pub struct EpollEventInstance { events: u32, /// Original data retrieved from `epoll_event` during `epoll_ctl`. data: u64, + /// The release clock associated with this event. + clock: VClock, } impl EpollEventInstance { pub fn new(events: u32, data: u64) -> EpollEventInstance { - EpollEventInstance { events, data } + EpollEventInstance { events, data, clock: Default::default() } } } @@ -92,7 +94,6 @@ pub struct EpollReadyEvents { #[derive(Debug, Default)] struct ReadyList { mapping: RefCell>, - clock: RefCell, } impl EpollReadyEvents { @@ -567,11 +568,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let epoll = epfd.downcast::().unwrap(); - // Synchronize running thread to the epoll ready list. - this.release_clock(|clock| { - epoll.ready_list.clock.borrow_mut().join(clock); - }); - if let Some(thread_id) = epoll.thread_id.borrow_mut().pop() { waiter.push(thread_id); }; @@ -627,7 +623,11 @@ fn check_and_update_one_event_interest<'tcx>( if flags != 0 { let epoll_key = (id, epoll_event_interest.fd_num); let ready_list = &mut epoll_event_interest.ready_list.mapping.borrow_mut(); - let event_instance = EpollEventInstance::new(flags, epoll_event_interest.data); + let mut event_instance = EpollEventInstance::new(flags, epoll_event_interest.data); + // If we are tracking data races, remember the current clock so we can sync with it later. + ecx.release_clock(|clock| { + event_instance.clock.join(clock); + }); // Triggers the notification by inserting it to the ready list. ready_list.insert(epoll_key, event_instance); interp_ok(true) @@ -654,9 +654,6 @@ fn blocking_epoll_callback<'tcx>( let ready_list = epoll_file_description.get_ready_list(); - // Synchronize waking thread from the epoll ready list. - ecx.acquire_clock(&ready_list.clock.borrow()); - let mut ready_list = ready_list.mapping.borrow_mut(); let mut num_of_events: i32 = 0; let mut array_iter = ecx.project_array_fields(events)?; @@ -670,6 +667,9 @@ fn blocking_epoll_callback<'tcx>( ], &des.1, )?; + // Synchronize waking thread with the event of interest. + ecx.acquire_clock(&epoll_event_instance.clock); + num_of_events = num_of_events.strict_add(1); } else { break; diff --git a/src/tools/miri/tests/pass-dep/libc/libc-epoll-clock-sync.rs b/src/tools/miri/tests/fail-dep/libc/libc-epoll-data-race.rs similarity index 82% rename from src/tools/miri/tests/pass-dep/libc/libc-epoll-clock-sync.rs rename to src/tools/miri/tests/fail-dep/libc/libc-epoll-data-race.rs index 56c2615b8a7..398bc92b392 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-epoll-clock-sync.rs +++ b/src/tools/miri/tests/fail-dep/libc/libc-epoll-data-race.rs @@ -1,5 +1,9 @@ +//! This ensures that when an epoll_wait wakes up and there are multiple events, +//! and we only read one of them, we do not synchronize with the other events +//! and therefore still report a data race for things that need to see the second event +//! to be considered synchronized. //@only-target: linux -// ensure single way to order the thread tests +// ensure deterministic schedule //@compile-flags: -Zmiri-preemption-rate=0 use std::convert::TryInto; @@ -30,7 +34,7 @@ fn check_epoll_wait(epfd: i32, expected_notifications: &[(u32, u } } -fn common_setup() -> (i32, [i32; 2], [i32; 2]) { +fn main() { // Create an epoll instance. let epfd = unsafe { libc::epoll_create1(0) }; assert_ne!(epfd, -1); @@ -59,17 +63,6 @@ fn common_setup() -> (i32, [i32; 2], [i32; 2]) { let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fds_b[1], &mut ev) }; assert_eq!(res, 0); - (epfd, fds_a, fds_b) -} - -// Test that the clock sync that happens through an epoll_wait only synchronizes with the clock(s) -// that were reported. It is possible more events had become ready but the epoll_wait didn't -// provide room for them all. -// -// Well before the fix, this fails to report UB. -fn main() { - let (epfd, fds_a, fds_b) = common_setup(); - static mut VAL_ONE: u8 = 40; // This one will be read soundly. static mut VAL_TWO: u8 = 50; // This one will be read unsoundly. let thread1 = spawn(move || { @@ -91,13 +84,13 @@ fn main() { let expected_value = u64::try_from(fds_a[1]).unwrap(); check_epoll_wait::<1>(epfd, &[(expected_event, expected_value)]); - #[allow(static_mut_refs)] + // Since we only received one event, we have synchronized with + // the write to VAL_ONE but not with the one to VAL_TWO. unsafe { - assert_eq!(VAL_ONE, 41) // This one is not UB + assert_eq!({ VAL_ONE }, 41) // This one is not UB }; - #[allow(static_mut_refs)] unsafe { - assert_eq!(VAL_TWO, 51) // This one should be UB but isn't (yet). + assert_eq!({ VAL_TWO }, 51) //~ERROR: Data race detected }; thread1.join().unwrap(); diff --git a/src/tools/miri/tests/fail-dep/libc/libc-epoll-data-race.stderr b/src/tools/miri/tests/fail-dep/libc/libc-epoll-data-race.stderr new file mode 100644 index 00000000000..a16c86f90ed --- /dev/null +++ b/src/tools/miri/tests/fail-dep/libc/libc-epoll-data-race.stderr @@ -0,0 +1,20 @@ +error: Undefined Behavior: Data race detected between (1) non-atomic write on thread `unnamed-ID` and (2) non-atomic read on thread `main` at ALLOC. (2) just happened here + --> tests/fail-dep/libc/libc-epoll-data-race.rs:LL:CC + | +LL | assert_eq!({ VAL_TWO }, 51) + | ^^^^^^^ Data race detected between (1) non-atomic write on thread `unnamed-ID` and (2) non-atomic read on thread `main` at ALLOC. (2) just happened here + | +help: and (1) occurred earlier here + --> tests/fail-dep/libc/libc-epoll-data-race.rs:LL:CC + | +LL | unsafe { VAL_TWO = 51 }; + | ^^^^^^^^^^^^ + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE (of the first span): + = note: inside `main` at tests/fail-dep/libc/libc-epoll-data-race.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + From e08dc0491a9069681b123bbe27eb388a7861a351 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Wed, 25 Sep 2024 13:17:58 +0200 Subject: [PATCH 123/357] Library: Rename "object safe" to "dyn compatible" --- library/core/src/cell.rs | 6 +++--- library/core/src/error.rs | 21 +++++++++++---------- library/core/src/iter/traits/iterator.rs | 2 +- library/core/src/marker.rs | 3 ++- library/core/src/ops/unsize.rs | 8 +++++--- library/core/tests/hash/mod.rs | 2 +- library/std/src/keyword_docs.rs | 4 +++- 7 files changed, 26 insertions(+), 20 deletions(-) diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index a3e91bc0670..df32c83f645 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -661,7 +661,7 @@ impl Cell { impl, U> CoerceUnsized> for Cell {} // Allow types that wrap `Cell` to also implement `DispatchFromDyn` -// and become object safe method receivers. +// and become dyn-compatible method receivers. // Note that currently `Cell` itself cannot be a method receiver // because it does not implement Deref. // In other words: @@ -2236,7 +2236,7 @@ impl From for UnsafeCell { impl, U> CoerceUnsized> for UnsafeCell {} // Allow types that wrap `UnsafeCell` to also implement `DispatchFromDyn` -// and become object safe method receivers. +// and become dyn-compatible method receivers. // Note that currently `UnsafeCell` itself cannot be a method receiver // because it does not implement Deref. // In other words: @@ -2379,7 +2379,7 @@ impl From for SyncUnsafeCell { impl, U> CoerceUnsized> for SyncUnsafeCell {} // Allow types that wrap `SyncUnsafeCell` to also implement `DispatchFromDyn` -// and become object safe method receivers. +// and become dyn-compatible method receivers. // Note that currently `SyncUnsafeCell` itself cannot be a method receiver // because it does not implement Deref. // In other words: diff --git a/library/core/src/error.rs b/library/core/src/error.rs index cac00b37d1f..95a39cc3aed 100644 --- a/library/core/src/error.rs +++ b/library/core/src/error.rs @@ -335,16 +335,17 @@ impl dyn Error { #[unstable(feature = "error_iter", issue = "58520")] #[inline] pub fn sources(&self) -> Source<'_> { - // You may think this method would be better in the Error trait, and you'd be right. - // Unfortunately that doesn't work, not because of the object safety rules but because we - // save a reference to self in Sources below as a trait object. If this method was - // declared in Error, then self would have the type &T where T is some concrete type which - // implements Error. We would need to coerce self to have type &dyn Error, but that requires - // that Self has a known size (i.e., Self: Sized). We can't put that bound on Error - // since that would forbid Error trait objects, and we can't put that bound on the method - // because that means the method can't be called on trait objects (we'd also need the - // 'static bound, but that isn't allowed because methods with bounds on Self other than - // Sized are not object-safe). Requiring an Unsize bound is not backwards compatible. + // You may think this method would be better in the `Error` trait, and you'd be right. + // Unfortunately that doesn't work, not because of the dyn-incompatibility rules but + // because we save a reference to `self` in `Source`s below as a trait object. + // If this method was declared in `Error`, then `self` would have the type `&T` where + // `T` is some concrete type which implements `Error`. We would need to coerce `self` + // to have type `&dyn Error`, but that requires that `Self` has a known size + // (i.e., `Self: Sized`). We can't put that bound on `Error` since that would forbid + // `Error` trait objects, and we can't put that bound on the method because that means + // the method can't be called on trait objects (we'd also need the `'static` bound, + // but that isn't allowed because methods with bounds on `Self` other than `Sized` are + // dyn-incompatible). Requiring an `Unsize` bound is not backwards compatible. Source { current: Some(self) } } diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 7963459bfb5..302720eddef 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -9,7 +9,7 @@ use crate::cmp::{self, Ordering}; use crate::num::NonZero; use crate::ops::{ChangeOutputType, ControlFlow, FromResidual, Residual, Try}; -fn _assert_is_object_safe(_: &dyn Iterator) {} +fn _assert_is_dyn_compatible(_: &dyn Iterator) {} /// A trait for dealing with iterators. /// diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index fd41b80cdbd..aed6be4c627 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -158,7 +158,7 @@ pub trait Sized { /// - Arrays `[T; N]` implement `Unsize<[T]>`. /// - A type implements `Unsize` if all of these conditions are met: /// - The type implements `Trait`. -/// - `Trait` is object safe. +/// - `Trait` is dyn-compatible[^1]. /// - The type is sized. /// - The type outlives `'a`. /// - Structs `Foo<..., T1, ..., Tn, ...>` implement `Unsize>` @@ -178,6 +178,7 @@ pub trait Sized { /// [`Rc`]: ../../std/rc/struct.Rc.html /// [RFC982]: https://github.com/rust-lang/rfcs/blob/master/text/0982-dst-coercion.md /// [nomicon-coerce]: ../../nomicon/coercions.html +/// [^1]: Formerly known as *object safe*. #[unstable(feature = "unsize", issue = "18598")] #[lang = "unsize"] #[rustc_deny_explicit_impl(implement_via_object = false)] diff --git a/library/core/src/ops/unsize.rs b/library/core/src/ops/unsize.rs index b51f12580ea..d2a07197f6f 100644 --- a/library/core/src/ops/unsize.rs +++ b/library/core/src/ops/unsize.rs @@ -68,8 +68,8 @@ impl, U: ?Sized> CoerceUnsized<*const U> for *mut T {} #[unstable(feature = "coerce_unsized", issue = "18598")] impl, U: ?Sized> CoerceUnsized<*const U> for *const T {} -/// `DispatchFromDyn` is used in the implementation of object safety checks (specifically allowing -/// arbitrary self types), to guarantee that a method's receiver type can be dispatched on. +/// `DispatchFromDyn` is used in the implementation of dyn-compatibility[^1] checks (specifically +/// allowing arbitrary self types), to guarantee that a method's receiver type can be dispatched on. /// /// Note: `DispatchFromDyn` was briefly named `CoerceSized` (and had a slightly different /// interpretation). @@ -80,7 +80,7 @@ impl, U: ?Sized> CoerceUnsized<*const U> for *const T {} /// type). The compiler must generate an implicit conversion from the trait object/wide pointer to /// the concrete reference/narrow pointer. Implementing `DispatchFromDyn` indicates that that /// conversion is allowed and thus that the type implementing `DispatchFromDyn` is safe to use as -/// the self type in an object-safe method. (in the above example, the compiler will require +/// the self type in an dyn-compatible method. (in the above example, the compiler will require /// `DispatchFromDyn` is implemented for `&'a U`). /// /// `DispatchFromDyn` does not specify the conversion from wide pointer to narrow pointer; the @@ -112,6 +112,8 @@ impl, U: ?Sized> CoerceUnsized<*const U> for *const T {} /// T: Unsize, /// {} /// ``` +/// +/// [^1]: Formerly known as *object safety*. #[unstable(feature = "dispatch_from_dyn", issue = "none")] #[lang = "dispatch_from_dyn"] pub trait DispatchFromDyn { diff --git a/library/core/tests/hash/mod.rs b/library/core/tests/hash/mod.rs index 03826fc4c92..bf91e9e5df0 100644 --- a/library/core/tests/hash/mod.rs +++ b/library/core/tests/hash/mod.rs @@ -164,7 +164,7 @@ fn test_indirect_hasher() { } #[test] -fn test_build_hasher_object_safe() { +fn test_build_hasher_dyn_compatible() { use std::hash::{DefaultHasher, RandomState}; let _: &dyn BuildHasher = &RandomState::new(); diff --git a/library/std/src/keyword_docs.rs b/library/std/src/keyword_docs.rs index 9f4d244b547..453b2708daa 100644 --- a/library/std/src/keyword_docs.rs +++ b/library/std/src/keyword_docs.rs @@ -2349,12 +2349,13 @@ mod async_keyword {} /// [`async`]: ../std/keyword.async.html mod await_keyword {} +// FIXME(dyn_compat_renaming): Update URL and link text. #[doc(keyword = "dyn")] // /// `dyn` is a prefix of a [trait object]'s type. /// /// The `dyn` keyword is used to highlight that calls to methods on the associated `Trait` -/// are [dynamically dispatched]. To use the trait this way, it must be 'object safe'. +/// are [dynamically dispatched]. To use the trait this way, it must be 'dyn-compatible'[^1]. /// /// Unlike generic parameters or `impl Trait`, the compiler does not know the concrete type that /// is being passed. That is, the type has been [erased]. @@ -2382,6 +2383,7 @@ mod await_keyword {} /// [ref-trait-obj]: ../reference/types/trait-object.html /// [ref-obj-safety]: ../reference/items/traits.html#object-safety /// [erased]: https://en.wikipedia.org/wiki/Type_erasure +/// [^1]: Formerly known as 'object safe'. mod dyn_keyword {} #[doc(keyword = "union")] From 12ce6f656428b420b8cd01f56d85dc2c5955492c Mon Sep 17 00:00:00 2001 From: Alyssa Haroldsen Date: Wed, 9 Oct 2024 10:28:16 -0700 Subject: [PATCH 124/357] Fix typo in E0793 --- compiler/rustc_error_codes/src/error_codes/E0793.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0793.md b/compiler/rustc_error_codes/src/error_codes/E0793.md index b2e51e24e14..ccd1b43bd19 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0793.md +++ b/compiler/rustc_error_codes/src/error_codes/E0793.md @@ -1,4 +1,4 @@ -An unaligned references to a field of a [packed] struct got created. +An unaligned reference to a field of a [packed] struct got created. Erroneous code example: From 16844e24850700386b6a7fc482738400a2f115c9 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 8 Oct 2024 20:53:11 +0200 Subject: [PATCH 125/357] Fix methods alignment on mobile --- src/librustdoc/html/static/css/rustdoc.css | 2 +- tests/rustdoc-gui/notable-trait.goml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 5f6f3c65c7f..3fee73d6e5d 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -2435,7 +2435,7 @@ in src-script.js and main.js } /* Position of the "[-]" element. */ - details.toggle:not(.top-doc) > summary { + details.toggle:not(.top-doc) > summary, .impl-items > section { margin-left: 10px; } .impl-items > details.toggle > summary:not(.hideme)::before, diff --git a/tests/rustdoc-gui/notable-trait.goml b/tests/rustdoc-gui/notable-trait.goml index b8fa26b17f6..43a7e8a8f51 100644 --- a/tests/rustdoc-gui/notable-trait.goml +++ b/tests/rustdoc-gui/notable-trait.goml @@ -85,8 +85,8 @@ call-function: ("check-notable-tooltip-position", { // Checking on mobile now. set-window-size: (650, 600) call-function: ("check-notable-tooltip-position-complete", { - "x": 15, - "i_x": 293, + "x": 25, + "i_x": 303, "popover_x": 0, }) From 12d5f0aa2cdd3d53d3d273c360773cd5a1a3c821 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 8 Oct 2024 21:14:13 +0200 Subject: [PATCH 126/357] Add GUI regression test for methods left margin on mobile --- tests/rustdoc-gui/methods-left-margin.goml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 tests/rustdoc-gui/methods-left-margin.goml diff --git a/tests/rustdoc-gui/methods-left-margin.goml b/tests/rustdoc-gui/methods-left-margin.goml new file mode 100644 index 00000000000..af88bbaefc5 --- /dev/null +++ b/tests/rustdoc-gui/methods-left-margin.goml @@ -0,0 +1,17 @@ +// This test is to ensure that methods are correctly aligned on the left side. + +go-to: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html" + +// First we ensure that we have methods with and without documentation. +assert: ".impl-items > details.method-toggle > summary > section.method" +assert: ".impl-items > section.method" + +// Checking on desktop. +set-window-size: (900, 600) +store-position: (".impl-items section.method", {"x": x}) +assert-position: (".impl-items section.method", {"x": |x|}, ALL) + +// Checking on mobile. +set-window-size: (600, 600) +store-position: (".impl-items section.method", {"x": x}) +assert-position: (".impl-items section.method", {"x": |x|}, ALL) From 5e6033ea8b25d42a56eca04eba5bb33a530bc381 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 9 Oct 2024 21:23:20 +0200 Subject: [PATCH 127/357] Strengthen some GUI tests --- tests/rustdoc-gui/methods-left-margin.goml | 2 ++ tests/rustdoc-gui/notable-trait.goml | 1 + 2 files changed, 3 insertions(+) diff --git a/tests/rustdoc-gui/methods-left-margin.goml b/tests/rustdoc-gui/methods-left-margin.goml index af88bbaefc5..1003cec33f9 100644 --- a/tests/rustdoc-gui/methods-left-margin.goml +++ b/tests/rustdoc-gui/methods-left-margin.goml @@ -8,10 +8,12 @@ assert: ".impl-items > section.method" // Checking on desktop. set-window-size: (900, 600) +wait-for-size: ("body", {"width": 900}) store-position: (".impl-items section.method", {"x": x}) assert-position: (".impl-items section.method", {"x": |x|}, ALL) // Checking on mobile. set-window-size: (600, 600) +wait-for-size: ("body", {"width": 600}) store-position: (".impl-items section.method", {"x": x}) assert-position: (".impl-items section.method", {"x": |x|}, ALL) diff --git a/tests/rustdoc-gui/notable-trait.goml b/tests/rustdoc-gui/notable-trait.goml index 43a7e8a8f51..e02974e6082 100644 --- a/tests/rustdoc-gui/notable-trait.goml +++ b/tests/rustdoc-gui/notable-trait.goml @@ -84,6 +84,7 @@ call-function: ("check-notable-tooltip-position", { // Checking on mobile now. set-window-size: (650, 600) +wait-for-size: ("body", {"width": 650}) call-function: ("check-notable-tooltip-position-complete", { "x": 25, "i_x": 303, From f04d1f64e27dd16c773c0ff353cc825e08f3a8a2 Mon Sep 17 00:00:00 2001 From: Frank Rehwinkel Date: Thu, 3 Oct 2024 12:35:53 -0400 Subject: [PATCH 128/357] syscall/eventfd2: add failing test The shim syscall logic doesn't support ID 290, SYS_eventfd2. --- .../tests/fail-dep/libc/libc_syscall_eventfd2.rs | 14 ++++++++++++++ .../fail-dep/libc/libc_syscall_eventfd2.stderr | 15 +++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 src/tools/miri/tests/fail-dep/libc/libc_syscall_eventfd2.rs create mode 100644 src/tools/miri/tests/fail-dep/libc/libc_syscall_eventfd2.stderr diff --git a/src/tools/miri/tests/fail-dep/libc/libc_syscall_eventfd2.rs b/src/tools/miri/tests/fail-dep/libc/libc_syscall_eventfd2.rs new file mode 100644 index 00000000000..fc5a6b37cc0 --- /dev/null +++ b/src/tools/miri/tests/fail-dep/libc/libc_syscall_eventfd2.rs @@ -0,0 +1,14 @@ +//@only-target: linux + +// This is a test for calling eventfd2 through a syscall. +// But we do not support this. +fn main() { + let initval = 0 as libc::c_uint; + let flags = (libc::EFD_CLOEXEC | libc::EFD_NONBLOCK) as libc::c_int; + + let result = unsafe { + libc::syscall(libc::SYS_eventfd2, initval, flags) //~ERROR: unsupported operation + }; + + assert_eq!(result, 3); // The first FD provided would be 3. +} diff --git a/src/tools/miri/tests/fail-dep/libc/libc_syscall_eventfd2.stderr b/src/tools/miri/tests/fail-dep/libc/libc_syscall_eventfd2.stderr new file mode 100644 index 00000000000..d39cea564d6 --- /dev/null +++ b/src/tools/miri/tests/fail-dep/libc/libc_syscall_eventfd2.stderr @@ -0,0 +1,15 @@ +error: unsupported operation: can't execute syscall with ID 290 + --> tests/fail-dep/libc/libc_syscall_eventfd2.rs:LL:CC + | +LL | libc::syscall(libc::SYS_eventfd2, initval, flags) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't execute syscall with ID 290 + | + = help: if this is a basic API commonly used on this target, please report an issue with Miri + = help: however, note that Miri does not aim to support every FFI function out there; for instance, we will not support APIs for things such as GUIs, scripting languages, or databases + = note: BACKTRACE: + = note: inside `main` at tests/fail-dep/libc/libc_syscall_eventfd2.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + From 7b52e6bc479bcefc531fde4947c00cc725d8813d Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 9 Oct 2024 12:43:23 -0700 Subject: [PATCH 129/357] Mention allocation errors for `open_buffered` --- library/std/src/fs.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 124ef121b18..675140ff18f 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -394,7 +394,8 @@ impl File { /// /// # Errors /// - /// This function will return an error if `path` does not already exist. + /// This function will return an error if `path` does not already exist, + /// or if memory allocation fails for the new buffer. /// Other errors may also be returned according to [`OpenOptions::open`]. /// /// # Examples From 118f7a6b88a2627aba161d7a6e695350329d20e7 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Wed, 9 Oct 2024 22:11:37 +0300 Subject: [PATCH 130/357] ignore `ci_rustc_if_unchanged_logic` test Signed-off-by: onur-ozkan --- src/bootstrap/src/core/builder/tests.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index ab36193f8b6..4ab1ef1ad0f 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -214,6 +214,8 @@ fn alias_and_path_for_library() { assert_eq!(first(cache.all::()), &[doc_std!(A => A, stage = 0)]); } +// FIXME: This is failing in various runners in merge CI. +#[ignore] #[test] fn ci_rustc_if_unchanged_logic() { let config = Config::parse_inner( From 2675f14bef6464eeb107c8a30deec5bdf4ef7b75 Mon Sep 17 00:00:00 2001 From: Frank Rehwinkel Date: Thu, 3 Oct 2024 16:07:40 -0400 Subject: [PATCH 131/357] syscall/eventfd2: add support --- .../miri/src/shims/unix/linux/foreign_items.rs | 12 ++++++++++++ .../tests/fail-dep/libc/libc_syscall_eventfd2.rs | 14 -------------- .../fail-dep/libc/libc_syscall_eventfd2.stderr | 15 --------------- .../miri/tests/pass-dep/libc/libc-eventfd.rs | 9 +++++++++ 4 files changed, 21 insertions(+), 29 deletions(-) delete mode 100644 src/tools/miri/tests/fail-dep/libc/libc_syscall_eventfd2.rs delete mode 100644 src/tools/miri/tests/fail-dep/libc/libc_syscall_eventfd2.stderr diff --git a/src/tools/miri/src/shims/unix/linux/foreign_items.rs b/src/tools/miri/src/shims/unix/linux/foreign_items.rs index 3722cc2f3ca..2a72004378e 100644 --- a/src/tools/miri/src/shims/unix/linux/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/linux/foreign_items.rs @@ -122,6 +122,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let sys_getrandom = this.eval_libc("SYS_getrandom").to_target_usize(this)?; let sys_futex = this.eval_libc("SYS_futex").to_target_usize(this)?; + let sys_eventfd2 = this.eval_libc("SYS_eventfd2").to_target_usize(this)?; if args.is_empty() { throw_ub_format!( @@ -155,6 +156,17 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { id if id == sys_futex => { futex(this, &args[1..], dest)?; } + id if id == sys_eventfd2 => { + let [_, initval, flags, ..] = args else { + throw_ub_format!( + "incorrect number of arguments for `eventfd2` syscall: got {}, expected at least 3", + args.len() + ); + }; + + let result = this.eventfd(initval, flags)?; + this.write_int(result.to_i32()?, dest)?; + } id => { this.handle_unsupported_foreign_item(format!( "can't execute syscall with ID {id}" diff --git a/src/tools/miri/tests/fail-dep/libc/libc_syscall_eventfd2.rs b/src/tools/miri/tests/fail-dep/libc/libc_syscall_eventfd2.rs deleted file mode 100644 index fc5a6b37cc0..00000000000 --- a/src/tools/miri/tests/fail-dep/libc/libc_syscall_eventfd2.rs +++ /dev/null @@ -1,14 +0,0 @@ -//@only-target: linux - -// This is a test for calling eventfd2 through a syscall. -// But we do not support this. -fn main() { - let initval = 0 as libc::c_uint; - let flags = (libc::EFD_CLOEXEC | libc::EFD_NONBLOCK) as libc::c_int; - - let result = unsafe { - libc::syscall(libc::SYS_eventfd2, initval, flags) //~ERROR: unsupported operation - }; - - assert_eq!(result, 3); // The first FD provided would be 3. -} diff --git a/src/tools/miri/tests/fail-dep/libc/libc_syscall_eventfd2.stderr b/src/tools/miri/tests/fail-dep/libc/libc_syscall_eventfd2.stderr deleted file mode 100644 index d39cea564d6..00000000000 --- a/src/tools/miri/tests/fail-dep/libc/libc_syscall_eventfd2.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error: unsupported operation: can't execute syscall with ID 290 - --> tests/fail-dep/libc/libc_syscall_eventfd2.rs:LL:CC - | -LL | libc::syscall(libc::SYS_eventfd2, initval, flags) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't execute syscall with ID 290 - | - = help: if this is a basic API commonly used on this target, please report an issue with Miri - = help: however, note that Miri does not aim to support every FFI function out there; for instance, we will not support APIs for things such as GUIs, scripting languages, or databases - = note: BACKTRACE: - = note: inside `main` at tests/fail-dep/libc/libc_syscall_eventfd2.rs:LL:CC - -note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace - -error: aborting due to 1 previous error - diff --git a/src/tools/miri/tests/pass-dep/libc/libc-eventfd.rs b/src/tools/miri/tests/pass-dep/libc/libc-eventfd.rs index 1d084194658..c92d9c3fe70 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-eventfd.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-eventfd.rs @@ -10,6 +10,7 @@ use std::thread; fn main() { test_read_write(); test_race(); + test_syscall(); } fn read_bytes(fd: i32, buf: &mut [u8; N]) -> i32 { @@ -109,3 +110,11 @@ fn test_race() { thread::yield_now(); thread1.join().unwrap(); } + +// This is a test for calling eventfd2 through a syscall. +fn test_syscall() { + let initval = 0 as libc::c_uint; + let flags = (libc::EFD_CLOEXEC | libc::EFD_NONBLOCK) as libc::c_int; + let fd = unsafe { libc::syscall(libc::SYS_eventfd2, initval, flags) }; + assert_ne!(fd, -1); +} From 9c9d3c85bbed439d4b3d8eb2354c4d0e62d7d315 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 9 Oct 2024 09:45:59 -0700 Subject: [PATCH 132/357] Update wasm-component-ld to 0.5.10 This pulls in a bug fix relative to the 0.5.9 release which was updated-to recently. --- Cargo.lock | 48 +++++++++++++------------- src/tools/wasm-component-ld/Cargo.toml | 2 +- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 502920350d5..a11144f1cf4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5798,16 +5798,16 @@ checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" [[package]] name = "wasm-component-ld" -version = "0.5.9" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fde17bc96539700198e12516230c76095cc215c84ef39ad206e1af3f84243e0f" +checksum = "4d4aa6bd7fbe7cffbed29fe3e236fda74419def1bdef6f80f989ec51137edf44" dependencies = [ "anyhow", "clap", "lexopt", "tempfile", "wasi-preview1-component-adapter-provider", - "wasmparser 0.218.0", + "wasmparser 0.219.0", "wat", "wit-component", "wit-parser", @@ -5831,19 +5831,19 @@ dependencies = [ [[package]] name = "wasm-encoder" -version = "0.218.0" +version = "0.219.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22b896fa8ceb71091ace9bcb81e853f54043183a1c9667cf93422c40252ffa0a" +checksum = "e2b1b95711b3ad655656a341e301cc64e33cbee94de9a99a1c5a2ab88efab79d" dependencies = [ "leb128", - "wasmparser 0.218.0", + "wasmparser 0.219.0", ] [[package]] name = "wasm-metadata" -version = "0.218.0" +version = "0.219.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa5eeb071abe8a2132fdd5565dabffee70775ee8c24fc7e300ac43f51f4a8a91" +checksum = "96132fe00dd17d092d2be289eeed5a0a68ad3cf30b68e8875bc953b96f55f0be" dependencies = [ "anyhow", "indexmap", @@ -5851,8 +5851,8 @@ dependencies = [ "serde_derive", "serde_json", "spdx", - "wasm-encoder 0.218.0", - "wasmparser 0.218.0", + "wasm-encoder 0.219.0", + "wasmparser 0.219.0", ] [[package]] @@ -5867,9 +5867,9 @@ dependencies = [ [[package]] name = "wasmparser" -version = "0.218.0" +version = "0.219.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b09e46c7fceceaa72b2dd1a8a137ea7fd8f93dfaa69806010a709918e496c5dc" +checksum = "324b4e56d24439495b88cd81439dad5e97f3c7b1eedc3c7e10455ed1e045e9a2" dependencies = [ "ahash", "bitflags 2.6.0", @@ -5881,22 +5881,22 @@ dependencies = [ [[package]] name = "wast" -version = "218.0.0" +version = "219.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a53cd1f0fa505df97557e36a58bddb8296e2fcdcd089529545ebfdb18a1b9d7" +checksum = "06880ecb25662bc21db6a83f4fcc27c41f71fbcba4f1980b650c88ada92728e1" dependencies = [ "bumpalo", "leb128", "memchr", "unicode-width", - "wasm-encoder 0.218.0", + "wasm-encoder 0.219.0", ] [[package]] name = "wat" -version = "1.218.0" +version = "1.219.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f87f8e14e776762e07927c27c2054d2cf678aab9aae2d431a79b3e31e4dd391" +checksum = "11e56dbf9fc89111b0d97c91e683d7895b1a6e5633a729f2ccad2303724005b6" dependencies = [ "wast", ] @@ -6173,9 +6173,9 @@ dependencies = [ [[package]] name = "wit-component" -version = "0.218.0" +version = "0.219.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa53aa7e6bf2b3e8ccaffbcc963fbdb672a603dc0af393a481b6cec24c266406" +checksum = "99a76111c20444a814019de20499d30940ecd219b9512ee296f034a5edb18a2d" dependencies = [ "anyhow", "bitflags 2.6.0", @@ -6184,17 +6184,17 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "wasm-encoder 0.218.0", + "wasm-encoder 0.219.0", "wasm-metadata", - "wasmparser 0.218.0", + "wasmparser 0.219.0", "wit-parser", ] [[package]] name = "wit-parser" -version = "0.218.0" +version = "0.219.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d3d1066ab761b115f97fef2b191090faabcb0f37b555b758d3caf42d4ed9e55" +checksum = "23102e180c0c464f36e293d31a27b524e3ece930d7b5527d2f33f9d2c963de64" dependencies = [ "anyhow", "id-arena", @@ -6205,7 +6205,7 @@ dependencies = [ "serde_derive", "serde_json", "unicode-xid", - "wasmparser 0.218.0", + "wasmparser 0.219.0", ] [[package]] diff --git a/src/tools/wasm-component-ld/Cargo.toml b/src/tools/wasm-component-ld/Cargo.toml index 49f4e59650e..acdb1aa1ab7 100644 --- a/src/tools/wasm-component-ld/Cargo.toml +++ b/src/tools/wasm-component-ld/Cargo.toml @@ -10,4 +10,4 @@ name = "wasm-component-ld" path = "src/main.rs" [dependencies] -wasm-component-ld = "0.5.9" +wasm-component-ld = "0.5.10" From 6524acf04bd10c1459bba2db18f1a34100c0b241 Mon Sep 17 00:00:00 2001 From: ltdk Date: Tue, 28 May 2024 14:27:25 -0400 Subject: [PATCH 133/357] Optimize escape_ascii --- library/core/src/escape.rs | 112 +++++++++++++++++++++++++++++------- library/core/tests/ascii.rs | 22 ++++++- 2 files changed, 109 insertions(+), 25 deletions(-) diff --git a/library/core/src/escape.rs b/library/core/src/escape.rs index b213cc2b916..0685f525dca 100644 --- a/library/core/src/escape.rs +++ b/library/core/src/escape.rs @@ -18,38 +18,106 @@ const fn backslash(a: ascii::Char) -> ([ascii::Char; N], Range(byte: u8) -> ([ascii::Char; N], Range) { + const { assert!(N >= 4) }; + + let mut output = [ascii::Char::Null; N]; + + let hi = HEX_DIGITS[(byte >> 4) as usize]; + let lo = HEX_DIGITS[(byte & 0xf) as usize]; + + output[0] = ascii::Char::ReverseSolidus; + output[1] = ascii::Char::SmallX; + output[2] = hi; + output[3] = lo; + + (output, 0..4) +} + +#[inline] +const fn verbatim(a: ascii::Char) -> ([ascii::Char; N], Range) { + const { assert!(N >= 1) }; + + let mut output = [ascii::Char::Null; N]; + + output[0] = a; + + (output, 0..1) +} + /// Escapes an ASCII character. /// /// Returns a buffer and the length of the escaped representation. const fn escape_ascii(byte: u8) -> ([ascii::Char; N], Range) { const { assert!(N >= 4) }; - match byte { - b'\t' => backslash(ascii::Char::SmallT), - b'\r' => backslash(ascii::Char::SmallR), - b'\n' => backslash(ascii::Char::SmallN), - b'\\' => backslash(ascii::Char::ReverseSolidus), - b'\'' => backslash(ascii::Char::Apostrophe), - b'\"' => backslash(ascii::Char::QuotationMark), - byte => { - let mut output = [ascii::Char::Null; N]; + #[cfg(feature = "optimize_for_size")] + { + match byte { + b'\t' => backslash(ascii::Char::SmallT), + b'\r' => backslash(ascii::Char::SmallR), + b'\n' => backslash(ascii::Char::SmallN), + b'\\' => backslash(ascii::Char::ReverseSolidus), + b'\'' => backslash(ascii::Char::Apostrophe), + b'"' => backslash(ascii::Char::QuotationMark), + 0x00..=0x1F | 0x7F => hex_escape(byte), + _ => match ascii::Char::from_u8(byte) { + Some(a) => verbatim(a), + None => hex_escape(byte), + }, + } + } - if let Some(c) = byte.as_ascii() - && !byte.is_ascii_control() - { - output[0] = c; - (output, 0..1) - } else { - let hi = HEX_DIGITS[(byte >> 4) as usize]; - let lo = HEX_DIGITS[(byte & 0xf) as usize]; + #[cfg(not(feature = "optimize_for_size"))] + { + /// Lookup table helps us determine how to display character. + /// + /// Since ASCII characters will always be 7 bits, we can exploit this to store the 8th bit to + /// indicate whether the result is escaped or unescaped. + /// + /// We additionally use 0x80 (escaped NUL character) to indicate hex-escaped bytes, since + /// escaped NUL will not occur. + const LOOKUP: [u8; 256] = { + let mut arr = [0; 256]; + let mut idx = 0; + while idx <= 255 { + arr[idx] = match idx as u8 { + // use 8th bit to indicate escaped + b'\t' => 0x80 | b't', + b'\r' => 0x80 | b'r', + b'\n' => 0x80 | b'n', + b'\\' => 0x80 | b'\\', + b'\'' => 0x80 | b'\'', + b'"' => 0x80 | b'"', - output[0] = ascii::Char::ReverseSolidus; - output[1] = ascii::Char::SmallX; - output[2] = hi; - output[3] = lo; + // use NUL to indicate hex-escaped + 0x00..=0x1F | 0x7F..=0xFF => 0x80 | b'\0', - (output, 0..4) + idx => idx, + }; + idx += 1; } + arr + }; + + let lookup = LOOKUP[byte as usize]; + + // 8th bit indicates escape + let lookup_escaped = lookup & 0x80 != 0; + + // SAFETY: We explicitly mask out the eighth bit to get a 7-bit ASCII character. + let lookup_ascii = unsafe { ascii::Char::from_u8_unchecked(lookup & 0x7F) }; + + if lookup_escaped { + // NUL indicates hex-escaped + if matches!(lookup_ascii, ascii::Char::Null) { + hex_escape(byte) + } else { + backslash(lookup_ascii) + } + } else { + verbatim(lookup_ascii) } } } diff --git a/library/core/tests/ascii.rs b/library/core/tests/ascii.rs index 3d3f8ac10c6..ce09ee507f1 100644 --- a/library/core/tests/ascii.rs +++ b/library/core/tests/ascii.rs @@ -481,9 +481,25 @@ fn ascii_ctype_const() { } #[test] -fn test_ascii_display() { - assert_eq!(b"foo'bar".escape_ascii().to_string(), r#"foo\'bar"#); - assert_eq!(b"\0\xff".escape_ascii().to_string(), r#"\x00\xff"#); +fn test_escape_ascii() { + let mut buf = [0u8; 0x1F + 7]; // 0..=0x1F plus two quotes, slash, \x7F, \x80, \xFF + for idx in 0..=0x1F { + buf[idx] = idx as u8; + } + buf[0x20] = b'\''; + buf[0x21] = b'"'; + buf[0x22] = b'\\'; + buf[0x23] = 0x7F; + buf[0x24] = 0x80; + buf[0x25] = 0xff; + assert_eq!( + buf.escape_ascii().to_string(), + r#"\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\'\"\\\x7f\x80\xff"# + ); +} + +#[test] +fn test_escape_ascii_iter() { let mut it = b"\0fastpath\xffremainder\xff".escape_ascii(); let _ = it.advance_by(4); let _ = it.advance_back_by(4); From 62b24ea7c53aec6f8176fed05d0acee926b76bdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Wed, 9 Oct 2024 20:19:36 +0200 Subject: [PATCH 134/357] Compiler: Replace remaining occurrences of "object safe" with "dyn compatible" --- .../src/traits/dyn_compatibility.rs | 20 ++++++++----------- 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs index d5d7681a8d6..191eda4d347 100644 --- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs +++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs @@ -1,12 +1,8 @@ -//! "Object safety" refers to the ability for a trait to be converted -//! to an object. In general, traits may only be converted to an -//! object if all of their methods meet certain criteria. In particular, -//! they must: +//! "Dyn-compatibility"[^1] refers to the ability for a trait to be converted +//! to a trait object. In general, traits may only be converted to a trait +//! object if certain criteria are met. //! -//! - have a suitable receiver from which we can extract a vtable and coerce to a "thin" version -//! that doesn't contain the vtable; -//! - not reference the erased type `Self` except for in this receiver; -//! - not have generic type parameters. +//! [^1]: Formerly known as "object safety". use std::iter; use std::ops::ControlFlow; @@ -506,8 +502,8 @@ fn virtual_call_violations_for_method<'tcx>( /// This code checks that `receiver_is_dispatchable` is correctly implemented. /// -/// This check is outlined from the object safety check to avoid cycles with -/// layout computation, which relies on knowing whether methods are object safe. +/// This check is outlined from the dyn-compatibility check to avoid cycles with +/// layout computation, which relies on knowing whether methods are dyn-compatible. fn check_receiver_correct<'tcx>(tcx: TyCtxt<'tcx>, trait_def_id: DefId, method: ty::AssocItem) { if !is_vtable_safe_method(tcx, trait_def_id, method) { return; @@ -644,7 +640,7 @@ fn object_ty_for_trait<'tcx>( /// a pointer. /// /// In practice, we cannot use `dyn Trait` explicitly in the obligation because it would result -/// in a new check that `Trait` is object safe, creating a cycle (until object_safe_for_dispatch +/// in a new check that `Trait` is dyn-compatible, creating a cycle (until object_safe_for_dispatch /// is stabilized, see tracking issue ). /// Instead, we fudge a little by introducing a new type parameter `U` such that /// `Self: Unsize` and `U: Trait + ?Sized`, and use `U` in place of `dyn Trait`. @@ -865,7 +861,7 @@ impl<'tcx> TypeVisitor> for IllegalSelfTypeVisitor<'tcx> { } fn visit_const(&mut self, ct: ty::Const<'tcx>) -> Self::Result { - // Constants can only influence object safety if they are generic and reference `Self`. + // Constants can only influence dyn-compatibility if they are generic and reference `Self`. // This is only possible for unevaluated constants, so we walk these here. self.tcx.expand_abstract_consts(ct).super_visit_with(self) } From 2e7a52b22fe222316a48093547f6312252c20f0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Wed, 9 Oct 2024 18:37:30 +0200 Subject: [PATCH 135/357] Rename feature object_safe_for_dispatch to dyn_compatible_for_dispatch --- compiler/rustc_feature/src/removed.rs | 4 ++ compiler/rustc_feature/src/unstable.rs | 15 ++-- .../rustc_hir_analysis/src/coherence/mod.rs | 2 +- compiler/rustc_span/src/symbol.rs | 1 + .../src/traits/dyn_compatibility.rs | 6 +- .../src/traits/select/candidate_assembly.rs | 2 +- .../rustc_trait_selection/src/traits/wf.rs | 2 +- tests/crashes/120241-2.rs | 2 +- tests/crashes/120241.rs | 2 +- tests/crashes/120482.rs | 2 +- tests/crashes/125512.rs | 2 +- tests/crashes/128176.rs | 2 +- tests/crashes/130521.rs | 2 +- .../coherence-unsafe-trait-object-impl.rs | 2 +- ...eature-gate-dyn_compatible_for_dispatch.rs | 41 +++++++++++ ...e-gate-dyn_compatible_for_dispatch.stderr} | 70 +++++++++---------- .../feature-gate-object_safe_for_dispatch.rs | 41 ----------- ...-bound.dyn_compatible_for_dispatch.stderr} | 0 .../ui/kindck/kindck-inherited-copy-bound.rs | 8 +-- ...consts.dyn_compatible_for_dispatch.stderr} | 0 .../object-safety-associated-consts.rs | 4 +- ...nerics.dyn_compatible_for_dispatch.stderr} | 0 .../object-safety/object-safety-generics.rs | 8 +-- ...s-Self.dyn_compatible_for_dispatch.stderr} | 0 .../object-safety-mentions-Self.rs | 4 +- ...static.dyn_compatible_for_dispatch.stderr} | 0 .../object-safety/object-safety-no-static.rs | 4 +- ...ized-2.dyn_compatible_for_dispatch.stderr} | 0 .../ui/object-safety/object-safety-sized-2.rs | 4 +- ...-sized.dyn_compatible_for_dispatch.stderr} | 0 tests/ui/object-safety/object-safety-sized.rs | 4 +- .../downcast-unsafe-trait-objects.rs | 2 +- ...al-self-impl-for-unsafe-obj.current.stderr | 0 ...anual-self-impl-for-unsafe-obj.next.stderr | 0 .../manual-self-impl-for-unsafe-obj.rs | 2 +- .../static-dispatch-unsafe-object.rs | 2 +- ...t-safe.dyn_compatible_for_dispatch.stderr} | 0 .../arbitrary-self-types-not-object-safe.rs | 6 +- tests/ui/suggestions/issue-104328.rs | 2 +- .../ui/wf/wf-convert-unsafe-trait-obj-box.rs | 2 +- tests/ui/wf/wf-convert-unsafe-trait-obj.rs | 2 +- tests/ui/wf/wf-unsafe-trait-obj-match.rs | 2 +- 42 files changed, 130 insertions(+), 124 deletions(-) create mode 100644 tests/ui/feature-gates/feature-gate-dyn_compatible_for_dispatch.rs rename tests/ui/feature-gates/{feature-gate-object_safe_for_dispatch.stderr => feature-gate-dyn_compatible_for_dispatch.stderr} (50%) delete mode 100644 tests/ui/feature-gates/feature-gate-object_safe_for_dispatch.rs rename tests/ui/kindck/{kindck-inherited-copy-bound.object_safe_for_dispatch.stderr => kindck-inherited-copy-bound.dyn_compatible_for_dispatch.stderr} (100%) rename tests/ui/object-safety/{object-safety-associated-consts.object_safe_for_dispatch.stderr => object-safety-associated-consts.dyn_compatible_for_dispatch.stderr} (100%) rename tests/ui/object-safety/{object-safety-generics.object_safe_for_dispatch.stderr => object-safety-generics.dyn_compatible_for_dispatch.stderr} (100%) rename tests/ui/object-safety/{object-safety-mentions-Self.object_safe_for_dispatch.stderr => object-safety-mentions-Self.dyn_compatible_for_dispatch.stderr} (100%) rename tests/ui/object-safety/{object-safety-no-static.object_safe_for_dispatch.stderr => object-safety-no-static.dyn_compatible_for_dispatch.stderr} (100%) rename tests/ui/object-safety/{object-safety-sized-2.object_safe_for_dispatch.stderr => object-safety-sized-2.dyn_compatible_for_dispatch.stderr} (100%) rename tests/ui/object-safety/{object-safety-sized.object_safe_for_dispatch.stderr => object-safety-sized.dyn_compatible_for_dispatch.stderr} (100%) rename tests/ui/rfcs/{rfc-2027-object-safe-for-dispatch => rfc-2027-dyn-compatible-for-dispatch}/downcast-unsafe-trait-objects.rs (90%) rename tests/ui/rfcs/{rfc-2027-object-safe-for-dispatch => rfc-2027-dyn-compatible-for-dispatch}/manual-self-impl-for-unsafe-obj.current.stderr (100%) rename tests/ui/rfcs/{rfc-2027-object-safe-for-dispatch => rfc-2027-dyn-compatible-for-dispatch}/manual-self-impl-for-unsafe-obj.next.stderr (100%) rename tests/ui/rfcs/{rfc-2027-object-safe-for-dispatch => rfc-2027-dyn-compatible-for-dispatch}/manual-self-impl-for-unsafe-obj.rs (97%) rename tests/ui/rfcs/{rfc-2027-object-safe-for-dispatch => rfc-2027-dyn-compatible-for-dispatch}/static-dispatch-unsafe-object.rs (94%) rename tests/ui/self/{arbitrary-self-types-not-object-safe.object_safe_for_dispatch.stderr => arbitrary-self-types-not-object-safe.dyn_compatible_for_dispatch.stderr} (100%) diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs index 0cd0963d4e3..c275ad31b87 100644 --- a/compiler/rustc_feature/src/removed.rs +++ b/compiler/rustc_feature/src/removed.rs @@ -154,6 +154,10 @@ declare_features! ( /// then removed. But there was no utility storing it separately, so now /// it's in this list. (removed, no_stack_check, "1.0.0", None, None), + /// Allows making `dyn Trait` well-formed even if `Trait` is not dyn-compatible (object safe). + /// Renamed to `dyn_compatible_for_dispatch`. + (removed, object_safe_for_dispatch, "CURRENT_RUSTC_VERSION", Some(43561), + Some("renamed to `dyn_compatible_for_dispatch`")), /// Allows using `#[on_unimplemented(..)]` on traits. /// (Moved to `rustc_attrs`.) (removed, on_unimplemented, "1.40.0", None, None), diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index c5530097e96..110ffa75b05 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -259,6 +259,14 @@ declare_features! ( (unstable, doc_notable_trait, "1.52.0", Some(45040)), /// Allows using the `may_dangle` attribute (RFC 1327). (unstable, dropck_eyepatch, "1.10.0", Some(34761)), + /// Allows making `dyn Trait` well-formed even if `Trait` is not dyn-compatible[^1]. + /// In that case, `dyn Trait: Trait` does not hold. Moreover, coercions and + /// casts in safe Rust to `dyn Trait` for such a `Trait` is also forbidden. + /// + /// Renamed from `object_safe_for_dispatch`. + /// + /// [^1]: Formerly known as "object safe". + (unstable, dyn_compatible_for_dispatch, "CURRENT_RUSTC_VERSION", Some(43561)), /// Allows using the `#[fundamental]` attribute. (unstable, fundamental, "1.0.0", Some(29635)), /// Allows using `#[link_name="llvm.*"]`. @@ -544,13 +552,6 @@ declare_features! ( (unstable, non_exhaustive_omitted_patterns_lint, "1.57.0", Some(89554)), /// Allows `for` binders in where-clauses (incomplete, non_lifetime_binders, "1.69.0", Some(108185)), - /// Allows making `dyn Trait` well-formed even if `Trait` is not dyn-compatible[^1]. - /// In that case, `dyn Trait: Trait` does not hold. Moreover, coercions and - /// casts in safe Rust to `dyn Trait` for such a `Trait` is also forbidden. - /// - /// [^1]: Formerly known as "object safe". - // FIXME(dyn_compat_renaming): Rename feature. - (unstable, object_safe_for_dispatch, "1.40.0", Some(43561)), /// Allows using enums in offset_of! (unstable, offset_of_enum, "1.75.0", Some(120141)), /// Allows using fields with slice type in offset_of! diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs index 69d36426447..eea5a16ac6f 100644 --- a/compiler/rustc_hir_analysis/src/coherence/mod.rs +++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs @@ -199,7 +199,7 @@ fn check_object_overlap<'tcx>( for component_def_id in component_def_ids { if !tcx.is_dyn_compatible(component_def_id) { // FIXME(dyn_compat_renaming): Rename test and update comment. - // Without the 'object_safe_for_dispatch' feature this is an error + // Without the 'dyn_compatible_for_dispatch' feature this is an error // which will be reported by wfcheck. Ignore it here. // This is tested by `coherence-impl-trait-for-trait-object-safe.rs`. // With the feature enabled, the trait is not implemented automatically, diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index e8aa129c6cd..9e2df848309 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -776,6 +776,7 @@ symbols! { dropck_eyepatch, dropck_parametricity, dylib, + dyn_compatible_for_dispatch, dyn_metadata, dyn_star, dyn_trait, diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs index 191eda4d347..45e7de942fb 100644 --- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs +++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs @@ -639,8 +639,8 @@ fn object_ty_for_trait<'tcx>( /// contained by the trait object, because the object that needs to be coerced is behind /// a pointer. /// -/// In practice, we cannot use `dyn Trait` explicitly in the obligation because it would result -/// in a new check that `Trait` is dyn-compatible, creating a cycle (until object_safe_for_dispatch +/// In practice, we cannot use `dyn Trait` explicitly in the obligation because it would result in +/// a new check that `Trait` is dyn-compatible, creating a cycle (until dyn_compatible_for_dispatch /// is stabilized, see tracking issue ). /// Instead, we fudge a little by introducing a new type parameter `U` such that /// `Self: Unsize` and `U: Trait + ?Sized`, and use `U` in place of `dyn Trait`. @@ -674,7 +674,7 @@ fn receiver_is_dispatchable<'tcx>( // the type `U` in the query // use a bogus type parameter to mimic a forall(U) query using u32::MAX for now. - // FIXME(mikeyhew) this is a total hack. Once object_safe_for_dispatch is stabilized, we can + // FIXME(mikeyhew) this is a total hack. Once dyn_compatible_for_dispatch is stabilized, we can // replace this with `dyn Trait` let unsized_self_ty: Ty<'tcx> = Ty::new_param(tcx, u32::MAX, Symbol::intern("RustaceansAreAwesome")); diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 084b61115db..20adda6f0de 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -881,7 +881,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } if let Some(principal) = data.principal() { - if !self.infcx.tcx.features().object_safe_for_dispatch { + if !self.infcx.tcx.features().dyn_compatible_for_dispatch { principal.with_self_ty(self.tcx(), self_ty) } else if self.tcx().is_dyn_compatible(principal.def_id()) { principal.with_self_ty(self.tcx(), self_ty) diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 7e140ecfee0..a849cdfe125 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -829,7 +829,7 @@ impl<'a, 'tcx> TypeVisitor> for WfPredicates<'a, 'tcx> { // obligations that don't refer to Self and // checking those - let defer_to_coercion = tcx.features().object_safe_for_dispatch; + let defer_to_coercion = tcx.features().dyn_compatible_for_dispatch; if !defer_to_coercion { if let Some(principal) = data.principal_def_id() { diff --git a/tests/crashes/120241-2.rs b/tests/crashes/120241-2.rs index 9c4a3a50293..91ec3362090 100644 --- a/tests/crashes/120241-2.rs +++ b/tests/crashes/120241-2.rs @@ -1,6 +1,6 @@ //@ known-bug: #120241 //@ edition:2021 -#![feature(object_safe_for_dispatch)] +#![feature(dyn_compatible_for_dispatch)] #![feature(unsized_fn_params)] fn guard(_s: Copy) -> bool { diff --git a/tests/crashes/120241.rs b/tests/crashes/120241.rs index f18347a006c..b4fcb903714 100644 --- a/tests/crashes/120241.rs +++ b/tests/crashes/120241.rs @@ -1,6 +1,6 @@ //@ known-bug: #120241 //@ edition:2021 -#![feature(object_safe_for_dispatch)] +#![feature(dyn_compatible_for_dispatch)] trait B { fn f(a: A) -> A; diff --git a/tests/crashes/120482.rs b/tests/crashes/120482.rs index 6cbc2009c5f..a395855d796 100644 --- a/tests/crashes/120482.rs +++ b/tests/crashes/120482.rs @@ -1,6 +1,6 @@ //@ known-bug: #120482 //@ edition:2021 -#![feature(object_safe_for_dispatch)] +#![feature(dyn_compatible_for_dispatch)] trait B { fn bar(&self, x: &Self); diff --git a/tests/crashes/125512.rs b/tests/crashes/125512.rs index 1672b24a114..37dbdf2f32f 100644 --- a/tests/crashes/125512.rs +++ b/tests/crashes/125512.rs @@ -1,6 +1,6 @@ //@ known-bug: rust-lang/rust#125512 //@ edition:2021 -#![feature(object_safe_for_dispatch)] +#![feature(dyn_compatible_for_dispatch)] trait B { fn f(a: A) -> A; } diff --git a/tests/crashes/128176.rs b/tests/crashes/128176.rs index 70fada4f0fe..970ad9ff2cd 100644 --- a/tests/crashes/128176.rs +++ b/tests/crashes/128176.rs @@ -1,7 +1,7 @@ //@ known-bug: rust-lang/rust#128176 #![feature(generic_const_exprs)] -#![feature(object_safe_for_dispatch)] +#![feature(dyn_compatible_for_dispatch)] trait X { type Y; } diff --git a/tests/crashes/130521.rs b/tests/crashes/130521.rs index 2d30b658024..7c078ab5790 100644 --- a/tests/crashes/130521.rs +++ b/tests/crashes/130521.rs @@ -1,6 +1,6 @@ //@ known-bug: #130521 -#![feature(object_safe_for_dispatch)] +#![feature(dyn_compatible_for_dispatch)] struct Vtable(dyn Cap); trait Cap<'a> {} diff --git a/tests/ui/coherence/coherence-unsafe-trait-object-impl.rs b/tests/ui/coherence/coherence-unsafe-trait-object-impl.rs index 9859a226efd..16baf0958a6 100644 --- a/tests/ui/coherence/coherence-unsafe-trait-object-impl.rs +++ b/tests/ui/coherence/coherence-unsafe-trait-object-impl.rs @@ -1,7 +1,7 @@ // Check that unsafe trait object do not implement themselves // automatically -#![feature(object_safe_for_dispatch)] +#![feature(dyn_compatible_for_dispatch)] trait Trait: Sized { fn call(&self); diff --git a/tests/ui/feature-gates/feature-gate-dyn_compatible_for_dispatch.rs b/tests/ui/feature-gates/feature-gate-dyn_compatible_for_dispatch.rs new file mode 100644 index 00000000000..2dbba370a51 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-dyn_compatible_for_dispatch.rs @@ -0,0 +1,41 @@ +// Test that the use of the dyn-incompatible trait objects +// are gated by the `dyn_compatible_for_dispatch` feature gate. + +trait DynIncompatible1: Sized {} + +trait DynIncompatible2 { + fn static_fn() {} +} + +trait DynIncompatible3 { + fn foo(&self); +} + +trait DynIncompatible4 { + fn foo(&self, s: &Self); +} + +fn takes_non_object_safe_ref(obj: &dyn DynIncompatible1) { + //~^ ERROR E0038 +} + +fn return_non_object_safe_ref() -> &'static dyn DynIncompatible2 { + //~^ ERROR E0038 + loop {} +} + +fn takes_non_object_safe_box(obj: Box) { + //~^ ERROR E0038 +} + +fn return_non_object_safe_rc() -> std::rc::Rc { + //~^ ERROR E0038 + loop {} +} + +trait Trait {} + +impl Trait for dyn DynIncompatible1 {} +//~^ ERROR E0038 + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr b/tests/ui/feature-gates/feature-gate-dyn_compatible_for_dispatch.stderr similarity index 50% rename from tests/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr rename to tests/ui/feature-gates/feature-gate-dyn_compatible_for_dispatch.stderr index fd5ed9c40f7..3cb73dfd52c 100644 --- a/tests/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr +++ b/tests/ui/feature-gates/feature-gate-dyn_compatible_for_dispatch.stderr @@ -1,28 +1,28 @@ -error[E0038]: the trait `NonObjectSafe1` cannot be made into an object - --> $DIR/feature-gate-object_safe_for_dispatch.rs:18:39 +error[E0038]: the trait `DynIncompatible1` cannot be made into an object + --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:18:39 | -LL | fn takes_non_object_safe_ref(obj: &dyn NonObjectSafe1) { - | ^^^^^^^^^^^^^^^^^^ `NonObjectSafe1` cannot be made into an object +LL | fn takes_non_object_safe_ref(obj: &dyn DynIncompatible1) { + | ^^^^^^^^^^^^^^^^^^^^ `DynIncompatible1` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/feature-gate-object_safe_for_dispatch.rs:4:23 + --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:4:25 | -LL | trait NonObjectSafe1: Sized {} - | -------------- ^^^^^ ...because it requires `Self: Sized` +LL | trait DynIncompatible1: Sized {} + | ---------------- ^^^^^ ...because it requires `Self: Sized` | | | this trait cannot be made into an object... -error[E0038]: the trait `NonObjectSafe2` cannot be made into an object - --> $DIR/feature-gate-object_safe_for_dispatch.rs:22:45 +error[E0038]: the trait `DynIncompatible2` cannot be made into an object + --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:22:45 | -LL | fn return_non_object_safe_ref() -> &'static dyn NonObjectSafe2 { - | ^^^^^^^^^^^^^^^^^^ `NonObjectSafe2` cannot be made into an object +LL | fn return_non_object_safe_ref() -> &'static dyn DynIncompatible2 { + | ^^^^^^^^^^^^^^^^^^^^ `DynIncompatible2` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/feature-gate-object_safe_for_dispatch.rs:7:8 + --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:7:8 | -LL | trait NonObjectSafe2 { - | -------------- this trait cannot be made into an object... +LL | trait DynIncompatible2 { + | ---------------- this trait cannot be made into an object... LL | fn static_fn() {} | ^^^^^^^^^ ...because associated function `static_fn` has no `self` parameter help: consider turning `static_fn` into a method by giving it a `&self` argument @@ -34,47 +34,47 @@ help: alternatively, consider constraining `static_fn` so it does not apply to t LL | fn static_fn() where Self: Sized {} | +++++++++++++++++ -error[E0038]: the trait `NonObjectSafe3` cannot be made into an object - --> $DIR/feature-gate-object_safe_for_dispatch.rs:27:39 +error[E0038]: the trait `DynIncompatible3` cannot be made into an object + --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:27:39 | -LL | fn takes_non_object_safe_box(obj: Box) { - | ^^^^^^^^^^^^^^^^^^ `NonObjectSafe3` cannot be made into an object +LL | fn takes_non_object_safe_box(obj: Box) { + | ^^^^^^^^^^^^^^^^^^^^ `DynIncompatible3` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/feature-gate-object_safe_for_dispatch.rs:11:8 + --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:11:8 | -LL | trait NonObjectSafe3 { - | -------------- this trait cannot be made into an object... +LL | trait DynIncompatible3 { + | ---------------- this trait cannot be made into an object... LL | fn foo(&self); | ^^^ ...because method `foo` has generic type parameters = help: consider moving `foo` to another trait -error[E0038]: the trait `NonObjectSafe4` cannot be made into an object - --> $DIR/feature-gate-object_safe_for_dispatch.rs:31:47 +error[E0038]: the trait `DynIncompatible4` cannot be made into an object + --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:31:47 | -LL | fn return_non_object_safe_rc() -> std::rc::Rc { - | ^^^^^^^^^^^^^^^^^^ `NonObjectSafe4` cannot be made into an object +LL | fn return_non_object_safe_rc() -> std::rc::Rc { + | ^^^^^^^^^^^^^^^^^^^^ `DynIncompatible4` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/feature-gate-object_safe_for_dispatch.rs:15:22 + --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:15:22 | -LL | trait NonObjectSafe4 { - | -------------- this trait cannot be made into an object... +LL | trait DynIncompatible4 { + | ---------------- this trait cannot be made into an object... LL | fn foo(&self, s: &Self); | ^^^^^ ...because method `foo` references the `Self` type in this parameter = help: consider moving `foo` to another trait -error[E0038]: the trait `NonObjectSafe1` cannot be made into an object - --> $DIR/feature-gate-object_safe_for_dispatch.rs:38:16 +error[E0038]: the trait `DynIncompatible1` cannot be made into an object + --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:38:16 | -LL | impl Trait for dyn NonObjectSafe1 {} - | ^^^^^^^^^^^^^^^^^^ `NonObjectSafe1` cannot be made into an object +LL | impl Trait for dyn DynIncompatible1 {} + | ^^^^^^^^^^^^^^^^^^^^ `DynIncompatible1` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/feature-gate-object_safe_for_dispatch.rs:4:23 + --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:4:25 | -LL | trait NonObjectSafe1: Sized {} - | -------------- ^^^^^ ...because it requires `Self: Sized` +LL | trait DynIncompatible1: Sized {} + | ---------------- ^^^^^ ...because it requires `Self: Sized` | | | this trait cannot be made into an object... diff --git a/tests/ui/feature-gates/feature-gate-object_safe_for_dispatch.rs b/tests/ui/feature-gates/feature-gate-object_safe_for_dispatch.rs deleted file mode 100644 index 37348e476d4..00000000000 --- a/tests/ui/feature-gates/feature-gate-object_safe_for_dispatch.rs +++ /dev/null @@ -1,41 +0,0 @@ -// Test that the use of the non object-safe trait objects -// are gated by `object_safe_for_dispatch` feature gate. - -trait NonObjectSafe1: Sized {} - -trait NonObjectSafe2 { - fn static_fn() {} -} - -trait NonObjectSafe3 { - fn foo(&self); -} - -trait NonObjectSafe4 { - fn foo(&self, s: &Self); -} - -fn takes_non_object_safe_ref(obj: &dyn NonObjectSafe1) { - //~^ ERROR E0038 -} - -fn return_non_object_safe_ref() -> &'static dyn NonObjectSafe2 { - //~^ ERROR E0038 - loop {} -} - -fn takes_non_object_safe_box(obj: Box) { - //~^ ERROR E0038 -} - -fn return_non_object_safe_rc() -> std::rc::Rc { - //~^ ERROR E0038 - loop {} -} - -trait Trait {} - -impl Trait for dyn NonObjectSafe1 {} -//~^ ERROR E0038 - -fn main() {} diff --git a/tests/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr b/tests/ui/kindck/kindck-inherited-copy-bound.dyn_compatible_for_dispatch.stderr similarity index 100% rename from tests/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr rename to tests/ui/kindck/kindck-inherited-copy-bound.dyn_compatible_for_dispatch.stderr diff --git a/tests/ui/kindck/kindck-inherited-copy-bound.rs b/tests/ui/kindck/kindck-inherited-copy-bound.rs index c785736f42e..dda95229ddf 100644 --- a/tests/ui/kindck/kindck-inherited-copy-bound.rs +++ b/tests/ui/kindck/kindck-inherited-copy-bound.rs @@ -1,8 +1,8 @@ // Test that Copy bounds inherited by trait are checked. // -//@ revisions: curr object_safe_for_dispatch +//@ revisions: curr dyn_compatible_for_dispatch -#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))] +#![cfg_attr(dyn_compatible_for_dispatch, feature(dyn_compatible_for_dispatch))] use std::any::Any; @@ -19,7 +19,7 @@ fn take_param(foo: &T) { } fn a() { let x: Box<_> = Box::new(3); take_param(&x); //[curr]~ ERROR E0277 - //[object_safe_for_dispatch]~^ ERROR E0277 + //[dyn_compatible_for_dispatch]~^ ERROR E0277 } fn b() { @@ -28,7 +28,7 @@ fn b() { let z = &x as &dyn Foo; //[curr]~^ ERROR E0038 //[curr]~| ERROR E0038 - //[object_safe_for_dispatch]~^^^ ERROR E0038 + //[dyn_compatible_for_dispatch]~^^^ ERROR E0038 } fn main() { } diff --git a/tests/ui/object-safety/object-safety-associated-consts.object_safe_for_dispatch.stderr b/tests/ui/object-safety/object-safety-associated-consts.dyn_compatible_for_dispatch.stderr similarity index 100% rename from tests/ui/object-safety/object-safety-associated-consts.object_safe_for_dispatch.stderr rename to tests/ui/object-safety/object-safety-associated-consts.dyn_compatible_for_dispatch.stderr diff --git a/tests/ui/object-safety/object-safety-associated-consts.rs b/tests/ui/object-safety/object-safety-associated-consts.rs index a090214bbb4..fc7b372b782 100644 --- a/tests/ui/object-safety/object-safety-associated-consts.rs +++ b/tests/ui/object-safety/object-safety-associated-consts.rs @@ -1,9 +1,9 @@ // Check that we correctly prevent users from making trait objects // from traits with associated consts. // -//@ revisions: curr object_safe_for_dispatch +//@ revisions: curr dyn_compatible_for_dispatch -#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))] +#![cfg_attr(dyn_compatible_for_dispatch, feature(dyn_compatible_for_dispatch))] trait Bar { const X: usize; diff --git a/tests/ui/object-safety/object-safety-generics.object_safe_for_dispatch.stderr b/tests/ui/object-safety/object-safety-generics.dyn_compatible_for_dispatch.stderr similarity index 100% rename from tests/ui/object-safety/object-safety-generics.object_safe_for_dispatch.stderr rename to tests/ui/object-safety/object-safety-generics.dyn_compatible_for_dispatch.stderr diff --git a/tests/ui/object-safety/object-safety-generics.rs b/tests/ui/object-safety/object-safety-generics.rs index f005a689ac4..b51555aa500 100644 --- a/tests/ui/object-safety/object-safety-generics.rs +++ b/tests/ui/object-safety/object-safety-generics.rs @@ -1,9 +1,9 @@ // Check that we correctly prevent users from making trait objects // from traits with generic methods, unless `where Self : Sized` is // present. -//@ revisions: curr object_safe_for_dispatch +//@ revisions: curr dyn_compatible_for_dispatch -#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))] +#![cfg_attr(dyn_compatible_for_dispatch, feature(dyn_compatible_for_dispatch))] trait Bar { @@ -18,14 +18,14 @@ trait Quux { fn make_bar(t: &T) -> &dyn Bar { //[curr]~^ ERROR E0038 t - //[object_safe_for_dispatch]~^ ERROR E0038 + //[dyn_compatible_for_dispatch]~^ ERROR E0038 //[curr]~^^ ERROR E0038 } fn make_bar_explicit(t: &T) -> &dyn Bar { //[curr]~^ ERROR E0038 t as &dyn Bar - //[object_safe_for_dispatch]~^ ERROR E0038 + //[dyn_compatible_for_dispatch]~^ ERROR E0038 //[curr]~^^ ERROR E0038 //[curr]~| ERROR E0038 } diff --git a/tests/ui/object-safety/object-safety-mentions-Self.object_safe_for_dispatch.stderr b/tests/ui/object-safety/object-safety-mentions-Self.dyn_compatible_for_dispatch.stderr similarity index 100% rename from tests/ui/object-safety/object-safety-mentions-Self.object_safe_for_dispatch.stderr rename to tests/ui/object-safety/object-safety-mentions-Self.dyn_compatible_for_dispatch.stderr diff --git a/tests/ui/object-safety/object-safety-mentions-Self.rs b/tests/ui/object-safety/object-safety-mentions-Self.rs index 1311faf97bc..84c229e252d 100644 --- a/tests/ui/object-safety/object-safety-mentions-Self.rs +++ b/tests/ui/object-safety/object-safety-mentions-Self.rs @@ -2,9 +2,9 @@ // form traits that make use of `Self` in an argument or return // position, unless `where Self : Sized` is present.. // -//@ revisions: curr object_safe_for_dispatch +//@ revisions: curr dyn_compatible_for_dispatch -#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))] +#![cfg_attr(dyn_compatible_for_dispatch, feature(dyn_compatible_for_dispatch))] trait Bar { diff --git a/tests/ui/object-safety/object-safety-no-static.object_safe_for_dispatch.stderr b/tests/ui/object-safety/object-safety-no-static.dyn_compatible_for_dispatch.stderr similarity index 100% rename from tests/ui/object-safety/object-safety-no-static.object_safe_for_dispatch.stderr rename to tests/ui/object-safety/object-safety-no-static.dyn_compatible_for_dispatch.stderr diff --git a/tests/ui/object-safety/object-safety-no-static.rs b/tests/ui/object-safety/object-safety-no-static.rs index 4f4e03d734e..54af16fe18e 100644 --- a/tests/ui/object-safety/object-safety-no-static.rs +++ b/tests/ui/object-safety/object-safety-no-static.rs @@ -1,9 +1,9 @@ // Check that we correctly prevent users from making trait objects // from traits with static methods. // -//@ revisions: curr object_safe_for_dispatch +//@ revisions: curr dyn_compatible_for_dispatch -#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))] +#![cfg_attr(dyn_compatible_for_dispatch, feature(dyn_compatible_for_dispatch))] trait Foo { fn foo() {} diff --git a/tests/ui/object-safety/object-safety-sized-2.object_safe_for_dispatch.stderr b/tests/ui/object-safety/object-safety-sized-2.dyn_compatible_for_dispatch.stderr similarity index 100% rename from tests/ui/object-safety/object-safety-sized-2.object_safe_for_dispatch.stderr rename to tests/ui/object-safety/object-safety-sized-2.dyn_compatible_for_dispatch.stderr diff --git a/tests/ui/object-safety/object-safety-sized-2.rs b/tests/ui/object-safety/object-safety-sized-2.rs index cfb5d588d70..f5edd287f24 100644 --- a/tests/ui/object-safety/object-safety-sized-2.rs +++ b/tests/ui/object-safety/object-safety-sized-2.rs @@ -1,9 +1,9 @@ // Check that we correctly prevent users from making trait objects // from traits where `Self : Sized`. // -//@ revisions: curr object_safe_for_dispatch +//@ revisions: curr dyn_compatible_for_dispatch -#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))] +#![cfg_attr(dyn_compatible_for_dispatch, feature(dyn_compatible_for_dispatch))] trait Bar where Self : Sized diff --git a/tests/ui/object-safety/object-safety-sized.object_safe_for_dispatch.stderr b/tests/ui/object-safety/object-safety-sized.dyn_compatible_for_dispatch.stderr similarity index 100% rename from tests/ui/object-safety/object-safety-sized.object_safe_for_dispatch.stderr rename to tests/ui/object-safety/object-safety-sized.dyn_compatible_for_dispatch.stderr diff --git a/tests/ui/object-safety/object-safety-sized.rs b/tests/ui/object-safety/object-safety-sized.rs index f4d6c945b33..4c4fe3f8f25 100644 --- a/tests/ui/object-safety/object-safety-sized.rs +++ b/tests/ui/object-safety/object-safety-sized.rs @@ -1,9 +1,9 @@ // Check that we correctly prevent users from making trait objects // from traits where `Self : Sized`. // -//@ revisions: curr object_safe_for_dispatch +//@ revisions: curr dyn_compatible_for_dispatch -#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))] +#![cfg_attr(dyn_compatible_for_dispatch, feature(dyn_compatible_for_dispatch))] trait Bar: Sized { fn bar(&self, t: T); diff --git a/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/downcast-unsafe-trait-objects.rs b/tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/downcast-unsafe-trait-objects.rs similarity index 90% rename from tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/downcast-unsafe-trait-objects.rs rename to tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/downcast-unsafe-trait-objects.rs index d4337dcb165..e9206789756 100644 --- a/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/downcast-unsafe-trait-objects.rs +++ b/tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/downcast-unsafe-trait-objects.rs @@ -3,7 +3,7 @@ // //@ check-pass -#![feature(object_safe_for_dispatch)] +#![feature(dyn_compatible_for_dispatch)] trait Trait: Sized {} diff --git a/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.current.stderr b/tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/manual-self-impl-for-unsafe-obj.current.stderr similarity index 100% rename from tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.current.stderr rename to tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/manual-self-impl-for-unsafe-obj.current.stderr diff --git a/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.next.stderr b/tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/manual-self-impl-for-unsafe-obj.next.stderr similarity index 100% rename from tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.next.stderr rename to tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/manual-self-impl-for-unsafe-obj.next.stderr diff --git a/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.rs b/tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/manual-self-impl-for-unsafe-obj.rs similarity index 97% rename from tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.rs rename to tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/manual-self-impl-for-unsafe-obj.rs index a020d91fb14..37e6f948ad1 100644 --- a/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.rs +++ b/tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/manual-self-impl-for-unsafe-obj.rs @@ -5,7 +5,7 @@ //@[next] compile-flags: -Znext-solver //@ run-pass -#![feature(object_safe_for_dispatch)] +#![feature(dyn_compatible_for_dispatch)] trait Bad { fn stat() -> char { diff --git a/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/static-dispatch-unsafe-object.rs b/tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/static-dispatch-unsafe-object.rs similarity index 94% rename from tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/static-dispatch-unsafe-object.rs rename to tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/static-dispatch-unsafe-object.rs index cbf76a6830b..c38928a9f44 100644 --- a/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/static-dispatch-unsafe-object.rs +++ b/tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/static-dispatch-unsafe-object.rs @@ -3,7 +3,7 @@ // //@ check-pass -#![feature(object_safe_for_dispatch)] +#![feature(dyn_compatible_for_dispatch)] trait Statics { fn plain() {} diff --git a/tests/ui/self/arbitrary-self-types-not-object-safe.object_safe_for_dispatch.stderr b/tests/ui/self/arbitrary-self-types-not-object-safe.dyn_compatible_for_dispatch.stderr similarity index 100% rename from tests/ui/self/arbitrary-self-types-not-object-safe.object_safe_for_dispatch.stderr rename to tests/ui/self/arbitrary-self-types-not-object-safe.dyn_compatible_for_dispatch.stderr diff --git a/tests/ui/self/arbitrary-self-types-not-object-safe.rs b/tests/ui/self/arbitrary-self-types-not-object-safe.rs index 0053eb5f739..940b2f1e8e2 100644 --- a/tests/ui/self/arbitrary-self-types-not-object-safe.rs +++ b/tests/ui/self/arbitrary-self-types-not-object-safe.rs @@ -1,6 +1,6 @@ -//@ revisions: curr object_safe_for_dispatch +//@ revisions: curr dyn_compatible_for_dispatch -#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))] +#![cfg_attr(dyn_compatible_for_dispatch, feature(dyn_compatible_for_dispatch))] use std::rc::Rc; @@ -33,7 +33,7 @@ fn make_foo() { let x = Rc::new(5usize) as Rc; //[curr]~^ ERROR E0038 //[curr]~| ERROR E0038 - //[object_safe_for_dispatch]~^^^ ERROR E0038 + //[dyn_compatible_for_dispatch]~^^^ ERROR E0038 } fn make_bar() { diff --git a/tests/ui/suggestions/issue-104328.rs b/tests/ui/suggestions/issue-104328.rs index c3707baf79f..2b0fbdb8d35 100644 --- a/tests/ui/suggestions/issue-104328.rs +++ b/tests/ui/suggestions/issue-104328.rs @@ -1,4 +1,4 @@ -#![feature(object_safe_for_dispatch)] +#![feature(dyn_compatible_for_dispatch)] trait Foo { fn f() {} diff --git a/tests/ui/wf/wf-convert-unsafe-trait-obj-box.rs b/tests/ui/wf/wf-convert-unsafe-trait-obj-box.rs index ffdb49a3be5..e32b04c4715 100644 --- a/tests/ui/wf/wf-convert-unsafe-trait-obj-box.rs +++ b/tests/ui/wf/wf-convert-unsafe-trait-obj-box.rs @@ -1,7 +1,7 @@ // Check that we do not allow casts or coercions // to object unsafe trait objects inside a Box -#![feature(object_safe_for_dispatch)] +#![feature(dyn_compatible_for_dispatch)] trait Trait: Sized {} diff --git a/tests/ui/wf/wf-convert-unsafe-trait-obj.rs b/tests/ui/wf/wf-convert-unsafe-trait-obj.rs index 143b854ed6b..6f386352819 100644 --- a/tests/ui/wf/wf-convert-unsafe-trait-obj.rs +++ b/tests/ui/wf/wf-convert-unsafe-trait-obj.rs @@ -1,7 +1,7 @@ // Check that we do not allow casts or coercions // to object unsafe trait objects by ref -#![feature(object_safe_for_dispatch)] +#![feature(dyn_compatible_for_dispatch)] trait Trait: Sized {} diff --git a/tests/ui/wf/wf-unsafe-trait-obj-match.rs b/tests/ui/wf/wf-unsafe-trait-obj-match.rs index c8731a8ecaf..07e90538b85 100644 --- a/tests/ui/wf/wf-unsafe-trait-obj-match.rs +++ b/tests/ui/wf/wf-unsafe-trait-obj-match.rs @@ -1,7 +1,7 @@ // Check that we do not allow coercions to object // unsafe trait objects in match arms -#![feature(object_safe_for_dispatch)] +#![feature(dyn_compatible_for_dispatch)] trait Trait: Sized {} From 20cebae31203a9781f99081b075abe0dc2504a98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Wed, 9 Oct 2024 23:31:01 +0200 Subject: [PATCH 136/357] UI tests: Rename "object safe" to "dyn compatible" --- src/tools/tidy/src/issues.txt | 4 -- tests/ui/allocator/dyn-compatible.rs | 13 ++++ tests/ui/allocator/object-safe.rs | 13 ---- ....rs => entails-sized-dyn-compatibility.rs} | 12 ++-- ...{object-safety.rs => dyn-compatibility.rs} | 0 ...safety.stderr => dyn-compatibility.stderr} | 4 +- ...ce-impl-trait-for-trait-dyn-compatible.rs} | 6 +- ...impl-trait-for-trait-dyn-compatible.stderr | 27 +++++++ ...ce-impl-trait-for-trait-object-safe.stderr | 27 ------- ...rs => const_param_ty_dyn_compatibility.rs} | 0 ...> const_param_ty_dyn_compatibility.stderr} | 4 +- ...rr-ret.rs => dyn-compatibility-err-ret.rs} | 0 ...tderr => dyn-compatibility-err-ret.stderr} | 8 +-- ... => dyn-compatibility-err-where-bounds.rs} | 0 ...dyn-compatibility-err-where-bounds.stderr} | 8 +-- ...r.rs => dyn-compatibility-ok-infer-err.rs} | 0 ... => dyn-compatibility-ok-infer-err.stderr} | 8 +-- ...t-safety-ok.rs => dyn-compatibility-ok.rs} | 0 .../almost-supertrait-associated-type.rs | 2 +- .../almost-supertrait-associated-type.stderr | 0 .../assoc_const_bounds.rs | 0 .../assoc_const_bounds_sized.rs | 0 .../assoc_type_bounds.rs | 0 .../assoc_type_bounds.stderr | 0 .../assoc_type_bounds2.rs | 0 .../assoc_type_bounds2.stderr | 0 .../assoc_type_bounds_implicit_sized.fixed | 0 .../assoc_type_bounds_implicit_sized.rs | 0 .../assoc_type_bounds_implicit_sized.stderr | 0 .../assoc_type_bounds_sized.rs | 0 .../assoc_type_bounds_sized_others.rs | 0 .../assoc_type_bounds_sized_others.stderr | 0 .../assoc_type_bounds_sized_unnecessary.rs | 0 ...assoc_type_bounds_sized_unnecessary.stderr | 0 .../assoc_type_bounds_sized_used.rs | 0 .../assoc_type_bounds_sized_used.stderr | 0 .../associated-consts.curr.stderr} | 8 +-- ...consts.dyn_compatible_for_dispatch.stderr} | 4 +- .../associated-consts.rs} | 0 .../avoid-ice-on-warning-2.new.stderr | 0 .../avoid-ice-on-warning-2.old.stderr | 0 .../avoid-ice-on-warning-2.rs | 0 .../avoid-ice-on-warning-3.new.stderr | 0 .../avoid-ice-on-warning-3.old.stderr | 0 .../avoid-ice-on-warning-3.rs | 0 .../avoid-ice-on-warning.new.stderr | 0 .../avoid-ice-on-warning.old.stderr | 0 .../avoid-ice-on-warning.rs | 0 .../bare-trait-dont-suggest-dyn.new.fixed | 0 .../bare-trait-dont-suggest-dyn.new.stderr | 0 .../bare-trait-dont-suggest-dyn.old.stderr | 0 .../bare-trait-dont-suggest-dyn.rs | 0 .../bounds.rs} | 2 +- .../bounds.stderr} | 4 +- .../by-value-self-use.rs} | 2 +- .../by-value-self-use.stderr} | 2 +- .../by-value-self.rs} | 2 +- .../call-when-assoc-ty-is-sized.rs | 0 .../elaborated-predicates-ordering.rs} | 1 + .../erroneous_signature.rs | 0 .../erroneous_signature.stderr | 0 .../generics.curr.stderr} | 20 +++--- ...nerics.dyn_compatible_for_dispatch.stderr} | 8 +-- .../generics.rs} | 0 ...s-multiple_supertrait_upcastable-check.rs} | 1 + .../item-bounds-can-reference-self.rs | 0 ...mention-correct-dyn-incompatible-trait.rs} | 2 + ...ion-correct-dyn-incompatible-trait.stderr} | 8 +-- .../mentions-Self-in-super-predicates.rs} | 0 .../mentions-Self-in-super-predicates.stderr} | 12 ++-- .../mentions-Self.curr.stderr} | 16 ++--- ...s-Self.dyn_compatible_for_dispatch.stderr} | 8 +-- .../mentions-Self.rs} | 0 .../missing-assoc-type.rs} | 0 .../missing-assoc-type.stderr} | 16 ++--- .../no-static.curr.stderr} | 12 ++-- ...static.dyn_compatible_for_dispatch.stderr} | 4 +- .../no-static.rs} | 0 .../phantom-fn.rs} | 2 +- ...t-in-fn-inputs-and-outputs-issue-125139.rs | 0 ...-fn-inputs-and-outputs-issue-125139.stderr | 0 .../sized-2.curr.stderr} | 8 +-- ...ized-2.dyn_compatible_for_dispatch.stderr} | 4 +- .../sized-2.rs} | 0 .../sized.curr.stderr} | 8 +-- .../sized.dyn_compatible_for_dispatch.stderr} | 4 +- .../sized.rs} | 0 .../supertrait-mentions-GAT.rs} | 0 .../supertrait-mentions-GAT.stderr} | 8 +-- .../supertrait-mentions-Self.rs} | 0 .../supertrait-mentions-Self.stderr} | 8 +-- ...chable-receiver-and-wc-references-Self.rs} | 5 +- ...le-receiver-and-wc-references-Self.stderr} | 12 ++-- ...ure-gate-dispatch-from-dyn-missing-impl.rs | 2 +- ...eature-gate-dyn_compatible_for_dispatch.rs | 8 +-- ...re-gate-dyn_compatible_for_dispatch.stderr | 24 +++---- .../generic-associated-types/trait-objects.rs | 2 +- ...ble-trait-in-return-position-dyn-trait.rs} | 11 +-- ...trait-in-return-position-dyn-trait.stderr} | 72 +++++++++---------- ...le-trait-in-return-position-impl-trait.rs} | 16 ++--- ...rait-in-return-position-impl-trait.stderr} | 12 ++-- ...ilities-during-dyn-compatibility-check.rs} | 0 ...ies-during-dyn-compatibility-check.stderr} | 16 ++--- ...ty-sized.rs => dyn-compatibility-sized.rs} | 0 ...{object-safety.rs => dyn-compatibility.rs} | 0 ...safety.stderr => dyn-compatibility.stderr} | 16 ++--- tests/ui/issues/issue-58734.rs | 8 +-- .../downcast-unsafe-trait-objects.rs | 2 +- .../manual-self-impl-for-unsafe-obj.rs | 2 +- tests/ui/sanitizer/cfi/async-closures.rs | 2 +- ...y-self-types-dyn-incompatible.curr.stderr} | 8 +-- ...atible.dyn_compatible_for_dispatch.stderr} | 4 +- ... arbitrary-self-types-dyn-incompatible.rs} | 0 ...itrary_self_types_pointers_and_wrappers.rs | 6 +- ...compatibility-sized-self-by-value-self.rs} | 2 +- ...ompatibility-sized-self-generic-method.rs} | 2 +- ...n-compatibility-sized-self-return-Self.rs} | 2 +- tests/ui/specialization/issue-44861.rs | 8 +-- ...not-object-safe.rs => dyn-incompatible.rs} | 0 ...dyn-incompatible-trait-references-self.rs} | 0 ...incompatible-trait-references-self.stderr} | 14 ++-- ...trait-should-use-self-2021-without-dyn.rs} | 0 ...t-should-use-self-2021-without-dyn.stderr} | 30 ++++---- ...ncompatible-trait-should-use-self-2021.rs} | 0 ...patible-trait-should-use-self-2021.stderr} | 12 ++-- ...dyn-incompatible-trait-should-use-self.rs} | 0 ...incompatible-trait-should-use-self.stderr} | 12 ++-- ...atible-trait-should-use-where-sized.fixed} | 0 ...ompatible-trait-should-use-where-sized.rs} | 0 ...tible-trait-should-use-where-sized.stderr} | 6 +- tests/ui/suggestions/issue-98500.rs | 6 +- tests/ui/suggestions/issue-98500.stderr | 2 +- tests/ui/traits/alias/no-duplicates.rs | 4 +- tests/ui/traits/alias/no-extra-traits.rs | 2 +- tests/ui/traits/alias/object-wf.rs | 4 +- ...ect-unsafety.rs => dyn-incompatibility.rs} | 0 ...fety.stderr => dyn-incompatibility.stderr} | 10 +-- ...ety.rs => supertrait-dyn-compatibility.rs} | 0 ...rr => supertrait-dyn-compatibility.stderr} | 14 ++-- tests/ui/traits/object/print_vtable_sizes.rs | 2 +- tests/ui/traits/object/safety.rs | 2 +- ...ect-safe.rs => vtable-dyn-incompatible.rs} | 2 +- ....stderr => vtable-dyn-incompatible.stderr} | 2 +- tests/ui/traits/wf-object/no-duplicates.rs | 4 +- tests/ui/traits/wf-object/reverse-order.rs | 2 +- ...by-value-trait-dyn-compatibility-rpass.rs} | 0 ...e-trait-dyn-compatibility-with-default.rs} | 0 ...rs => by-value-trait-dyn-compatibility.rs} | 0 ...> by-value-trait-dyn-compatibility.stderr} | 4 +- ... wf-convert-dyn-incompat-trait-obj-box.rs} | 2 +- ...convert-dyn-incompat-trait-obj-box.stderr} | 12 ++-- ...s => wf-convert-dyn-incompat-trait-obj.rs} | 2 +- ... wf-convert-dyn-incompat-trait-obj.stderr} | 12 ++-- ....rs => wf-dyn-incompat-trait-obj-match.rs} | 0 ...=> wf-dyn-incompat-trait-obj-match.stderr} | 10 +-- ...-object-safe.rs => wf-dyn-incompatible.rs} | 2 +- ...safe.stderr => wf-dyn-incompatible.stderr} | 4 +- 157 files changed, 366 insertions(+), 364 deletions(-) create mode 100644 tests/ui/allocator/dyn-compatible.rs delete mode 100644 tests/ui/allocator/object-safe.rs rename tests/ui/associated-type-bounds/{entails-sized-object-safety.rs => entails-sized-dyn-compatibility.rs} (67%) rename tests/ui/async-await/in-trait/{object-safety.rs => dyn-compatibility.rs} (100%) rename tests/ui/async-await/in-trait/{object-safety.stderr => dyn-compatibility.stderr} (90%) rename tests/ui/coherence/{coherence-impl-trait-for-trait-object-safe.rs => coherence-impl-trait-for-trait-dyn-compatible.rs} (54%) create mode 100644 tests/ui/coherence/coherence-impl-trait-for-trait-dyn-compatible.stderr delete mode 100644 tests/ui/coherence/coherence-impl-trait-for-trait-object-safe.stderr rename tests/ui/const-generics/adt_const_params/{const_param_ty_object_safety.rs => const_param_ty_dyn_compatibility.rs} (100%) rename tests/ui/const-generics/adt_const_params/{const_param_ty_object_safety.stderr => const_param_ty_dyn_compatibility.stderr} (93%) rename tests/ui/const-generics/generic_const_exprs/{object-safety-err-ret.rs => dyn-compatibility-err-ret.rs} (100%) rename tests/ui/const-generics/generic_const_exprs/{object-safety-err-ret.stderr => dyn-compatibility-err-ret.stderr} (91%) rename tests/ui/const-generics/generic_const_exprs/{object-safety-err-where-bounds.rs => dyn-compatibility-err-where-bounds.rs} (100%) rename tests/ui/const-generics/generic_const_exprs/{object-safety-err-where-bounds.stderr => dyn-compatibility-err-where-bounds.stderr} (88%) rename tests/ui/const-generics/generic_const_exprs/{object-safety-ok-infer-err.rs => dyn-compatibility-ok-infer-err.rs} (100%) rename tests/ui/const-generics/generic_const_exprs/{object-safety-ok-infer-err.stderr => dyn-compatibility-ok-infer-err.stderr} (85%) rename tests/ui/const-generics/generic_const_exprs/{object-safety-ok.rs => dyn-compatibility-ok.rs} (100%) rename tests/ui/{object-safety => dyn-compatibility}/almost-supertrait-associated-type.rs (95%) rename tests/ui/{object-safety => dyn-compatibility}/almost-supertrait-associated-type.stderr (100%) rename tests/ui/{object-safety => dyn-compatibility}/assoc_const_bounds.rs (100%) rename tests/ui/{object-safety => dyn-compatibility}/assoc_const_bounds_sized.rs (100%) rename tests/ui/{object-safety => dyn-compatibility}/assoc_type_bounds.rs (100%) rename tests/ui/{object-safety => dyn-compatibility}/assoc_type_bounds.stderr (100%) rename tests/ui/{object-safety => dyn-compatibility}/assoc_type_bounds2.rs (100%) rename tests/ui/{object-safety => dyn-compatibility}/assoc_type_bounds2.stderr (100%) rename tests/ui/{object-safety => dyn-compatibility}/assoc_type_bounds_implicit_sized.fixed (100%) rename tests/ui/{object-safety => dyn-compatibility}/assoc_type_bounds_implicit_sized.rs (100%) rename tests/ui/{object-safety => dyn-compatibility}/assoc_type_bounds_implicit_sized.stderr (100%) rename tests/ui/{object-safety => dyn-compatibility}/assoc_type_bounds_sized.rs (100%) rename tests/ui/{object-safety => dyn-compatibility}/assoc_type_bounds_sized_others.rs (100%) rename tests/ui/{object-safety => dyn-compatibility}/assoc_type_bounds_sized_others.stderr (100%) rename tests/ui/{object-safety => dyn-compatibility}/assoc_type_bounds_sized_unnecessary.rs (100%) rename tests/ui/{object-safety => dyn-compatibility}/assoc_type_bounds_sized_unnecessary.stderr (100%) rename tests/ui/{object-safety => dyn-compatibility}/assoc_type_bounds_sized_used.rs (100%) rename tests/ui/{object-safety => dyn-compatibility}/assoc_type_bounds_sized_used.stderr (100%) rename tests/ui/{object-safety/object-safety-associated-consts.curr.stderr => dyn-compatibility/associated-consts.curr.stderr} (86%) rename tests/ui/{object-safety/object-safety-associated-consts.dyn_compatible_for_dispatch.stderr => dyn-compatibility/associated-consts.dyn_compatible_for_dispatch.stderr} (87%) rename tests/ui/{object-safety/object-safety-associated-consts.rs => dyn-compatibility/associated-consts.rs} (100%) rename tests/ui/{object-safety => dyn-compatibility}/avoid-ice-on-warning-2.new.stderr (100%) rename tests/ui/{object-safety => dyn-compatibility}/avoid-ice-on-warning-2.old.stderr (100%) rename tests/ui/{object-safety => dyn-compatibility}/avoid-ice-on-warning-2.rs (100%) rename tests/ui/{object-safety => dyn-compatibility}/avoid-ice-on-warning-3.new.stderr (100%) rename tests/ui/{object-safety => dyn-compatibility}/avoid-ice-on-warning-3.old.stderr (100%) rename tests/ui/{object-safety => dyn-compatibility}/avoid-ice-on-warning-3.rs (100%) rename tests/ui/{object-safety => dyn-compatibility}/avoid-ice-on-warning.new.stderr (100%) rename tests/ui/{object-safety => dyn-compatibility}/avoid-ice-on-warning.old.stderr (100%) rename tests/ui/{object-safety => dyn-compatibility}/avoid-ice-on-warning.rs (100%) rename tests/ui/{object-safety => dyn-compatibility}/bare-trait-dont-suggest-dyn.new.fixed (100%) rename tests/ui/{object-safety => dyn-compatibility}/bare-trait-dont-suggest-dyn.new.stderr (100%) rename tests/ui/{object-safety => dyn-compatibility}/bare-trait-dont-suggest-dyn.old.stderr (100%) rename tests/ui/{object-safety => dyn-compatibility}/bare-trait-dont-suggest-dyn.rs (100%) rename tests/ui/{object-safety/object-safety-bounds.rs => dyn-compatibility/bounds.rs} (72%) rename tests/ui/{object-safety/object-safety-bounds.stderr => dyn-compatibility/bounds.stderr} (89%) rename tests/ui/{object-safety/object-safety-by-value-self-use.rs => dyn-compatibility/by-value-self-use.rs} (79%) rename tests/ui/{object-safety/object-safety-by-value-self-use.stderr => dyn-compatibility/by-value-self-use.stderr} (83%) rename tests/ui/{object-safety/object-safety-by-value-self.rs => dyn-compatibility/by-value-self.rs} (90%) rename tests/ui/{object-safety => dyn-compatibility}/call-when-assoc-ty-is-sized.rs (100%) rename tests/ui/{object-safety/issue-102933.rs => dyn-compatibility/elaborated-predicates-ordering.rs} (93%) rename tests/ui/{object-safety => dyn-compatibility}/erroneous_signature.rs (100%) rename tests/ui/{object-safety => dyn-compatibility}/erroneous_signature.stderr (100%) rename tests/ui/{object-safety/object-safety-generics.curr.stderr => dyn-compatibility/generics.curr.stderr} (88%) rename tests/ui/{object-safety/object-safety-generics.dyn_compatible_for_dispatch.stderr => dyn-compatibility/generics.dyn_compatible_for_dispatch.stderr} (89%) rename tests/ui/{object-safety/object-safety-generics.rs => dyn-compatibility/generics.rs} (100%) rename tests/ui/{object-safety/issue-106247.rs => dyn-compatibility/impossible-predicates-multiple_supertrait_upcastable-check.rs} (73%) rename tests/ui/{object-safety => dyn-compatibility}/item-bounds-can-reference-self.rs (100%) rename tests/ui/{object-safety/issue-19538.rs => dyn-compatibility/mention-correct-dyn-incompatible-trait.rs} (90%) rename tests/ui/{object-safety/issue-19538.stderr => dyn-compatibility/mention-correct-dyn-incompatible-trait.stderr} (87%) rename tests/ui/{object-safety/object-safety-issue-22040.rs => dyn-compatibility/mentions-Self-in-super-predicates.rs} (100%) rename tests/ui/{object-safety/object-safety-issue-22040.stderr => dyn-compatibility/mentions-Self-in-super-predicates.stderr} (87%) rename tests/ui/{object-safety/object-safety-mentions-Self.curr.stderr => dyn-compatibility/mentions-Self.curr.stderr} (88%) rename tests/ui/{object-safety/object-safety-mentions-Self.dyn_compatible_for_dispatch.stderr => dyn-compatibility/mentions-Self.dyn_compatible_for_dispatch.stderr} (88%) rename tests/ui/{object-safety/object-safety-mentions-Self.rs => dyn-compatibility/mentions-Self.rs} (100%) rename tests/ui/{traits/object/object-unsafe-missing-assoc-type.rs => dyn-compatibility/missing-assoc-type.rs} (100%) rename tests/ui/{traits/object/object-unsafe-missing-assoc-type.stderr => dyn-compatibility/missing-assoc-type.stderr} (86%) rename tests/ui/{object-safety/object-safety-no-static.curr.stderr => dyn-compatibility/no-static.curr.stderr} (92%) rename tests/ui/{object-safety/object-safety-no-static.dyn_compatible_for_dispatch.stderr => dyn-compatibility/no-static.dyn_compatible_for_dispatch.stderr} (93%) rename tests/ui/{object-safety/object-safety-no-static.rs => dyn-compatibility/no-static.rs} (100%) rename tests/ui/{object-safety/object-safety-phantom-fn.rs => dyn-compatibility/phantom-fn.rs} (92%) rename tests/ui/{object-safety => dyn-compatibility}/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs (100%) rename tests/ui/{object-safety => dyn-compatibility}/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.stderr (100%) rename tests/ui/{object-safety/object-safety-sized-2.curr.stderr => dyn-compatibility/sized-2.curr.stderr} (88%) rename tests/ui/{object-safety/object-safety-sized-2.dyn_compatible_for_dispatch.stderr => dyn-compatibility/sized-2.dyn_compatible_for_dispatch.stderr} (89%) rename tests/ui/{object-safety/object-safety-sized-2.rs => dyn-compatibility/sized-2.rs} (100%) rename tests/ui/{object-safety/object-safety-sized.curr.stderr => dyn-compatibility/sized.curr.stderr} (88%) rename tests/ui/{object-safety/object-safety-sized.dyn_compatible_for_dispatch.stderr => dyn-compatibility/sized.dyn_compatible_for_dispatch.stderr} (89%) rename tests/ui/{object-safety/object-safety-sized.rs => dyn-compatibility/sized.rs} (100%) rename tests/ui/{object-safety/object-safety-supertrait-mentions-GAT.rs => dyn-compatibility/supertrait-mentions-GAT.rs} (100%) rename tests/ui/{object-safety/object-safety-supertrait-mentions-GAT.stderr => dyn-compatibility/supertrait-mentions-GAT.stderr} (86%) rename tests/ui/{object-safety/object-safety-supertrait-mentions-Self.rs => dyn-compatibility/supertrait-mentions-Self.rs} (100%) rename tests/ui/{object-safety/object-safety-supertrait-mentions-Self.stderr => dyn-compatibility/supertrait-mentions-Self.stderr} (86%) rename tests/ui/{object-safety/issue-102762.rs => dyn-compatibility/undispatchable-receiver-and-wc-references-Self.rs} (79%) rename tests/ui/{object-safety/issue-102762.stderr => dyn-compatibility/undispatchable-receiver-and-wc-references-Self.stderr} (87%) rename tests/ui/impl-trait/{object-unsafe-trait-in-return-position-dyn-trait.rs => dyn-incompatible-trait-in-return-position-dyn-trait.rs} (59%) rename tests/ui/impl-trait/{object-unsafe-trait-in-return-position-dyn-trait.stderr => dyn-incompatible-trait-in-return-position-dyn-trait.stderr} (62%) rename tests/ui/impl-trait/{object-unsafe-trait-in-return-position-impl-trait.rs => dyn-incompatible-trait-in-return-position-impl-trait.rs} (61%) rename tests/ui/impl-trait/{object-unsafe-trait-in-return-position-impl-trait.stderr => dyn-incompatible-trait-in-return-position-impl-trait.stderr} (54%) rename tests/ui/impl-trait/in-trait/{cycle-effective-visibilities-during-object-safety.rs => cycle-effective-visibilities-during-dyn-compatibility-check.rs} (100%) rename tests/ui/impl-trait/in-trait/{cycle-effective-visibilities-during-object-safety.stderr => cycle-effective-visibilities-during-dyn-compatibility-check.stderr} (82%) rename tests/ui/impl-trait/in-trait/{object-safety-sized.rs => dyn-compatibility-sized.rs} (100%) rename tests/ui/impl-trait/in-trait/{object-safety.rs => dyn-compatibility.rs} (100%) rename tests/ui/impl-trait/in-trait/{object-safety.stderr => dyn-compatibility.stderr} (91%) rename tests/ui/self/{arbitrary-self-types-not-object-safe.curr.stderr => arbitrary-self-types-dyn-incompatible.curr.stderr} (89%) rename tests/ui/self/{arbitrary-self-types-not-object-safe.dyn_compatible_for_dispatch.stderr => arbitrary-self-types-dyn-incompatible.dyn_compatible_for_dispatch.stderr} (90%) rename tests/ui/self/{arbitrary-self-types-not-object-safe.rs => arbitrary-self-types-dyn-incompatible.rs} (100%) rename tests/ui/self/{object-safety-sized-self-by-value-self.rs => dyn-compatibility-sized-self-by-value-self.rs} (90%) rename tests/ui/self/{object-safety-sized-self-generic-method.rs => dyn-compatibility-sized-self-generic-method.rs} (90%) rename tests/ui/self/{object-safety-sized-self-return-Self.rs => dyn-compatibility-sized-self-return-Self.rs} (90%) rename tests/ui/suggestions/auxiliary/{not-object-safe.rs => dyn-incompatible.rs} (100%) rename tests/ui/suggestions/{object-unsafe-trait-references-self.rs => dyn-incompatible-trait-references-self.rs} (100%) rename tests/ui/suggestions/{object-unsafe-trait-references-self.stderr => dyn-incompatible-trait-references-self.stderr} (87%) rename tests/ui/suggestions/{object-unsafe-trait-should-use-self-2021-without-dyn.rs => dyn-incompatible-trait-should-use-self-2021-without-dyn.rs} (100%) rename tests/ui/suggestions/{object-unsafe-trait-should-use-self-2021-without-dyn.stderr => dyn-incompatible-trait-should-use-self-2021-without-dyn.stderr} (83%) rename tests/ui/suggestions/{object-unsafe-trait-should-use-self-2021.rs => dyn-incompatible-trait-should-use-self-2021.rs} (100%) rename tests/ui/suggestions/{object-unsafe-trait-should-use-self-2021.stderr => dyn-incompatible-trait-should-use-self-2021.stderr} (85%) rename tests/ui/suggestions/{object-unsafe-trait-should-use-self.rs => dyn-incompatible-trait-should-use-self.rs} (100%) rename tests/ui/suggestions/{object-unsafe-trait-should-use-self.stderr => dyn-incompatible-trait-should-use-self.stderr} (86%) rename tests/ui/suggestions/{object-unsafe-trait-should-use-where-sized.fixed => dyn-incompatible-trait-should-use-where-sized.fixed} (100%) rename tests/ui/suggestions/{object-unsafe-trait-should-use-where-sized.rs => dyn-incompatible-trait-should-use-where-sized.rs} (100%) rename tests/ui/suggestions/{object-unsafe-trait-should-use-where-sized.stderr => dyn-incompatible-trait-should-use-where-sized.stderr} (89%) rename tests/ui/traits/next-solver/{object-unsafety.rs => dyn-incompatibility.rs} (100%) rename tests/ui/traits/next-solver/{object-unsafety.stderr => dyn-incompatibility.stderr} (90%) rename tests/ui/traits/non_lifetime_binders/{supertrait-object-safety.rs => supertrait-dyn-compatibility.rs} (100%) rename tests/ui/traits/non_lifetime_binders/{supertrait-object-safety.stderr => supertrait-dyn-compatibility.stderr} (88%) rename tests/ui/traits/vtable/{vtable-non-object-safe.rs => vtable-dyn-incompatible.rs} (78%) rename tests/ui/traits/vtable/{vtable-non-object-safe.stderr => vtable-dyn-incompatible.stderr} (92%) rename tests/ui/unsized-locals/{by-value-trait-object-safety-rpass.rs => by-value-trait-dyn-compatibility-rpass.rs} (100%) rename tests/ui/unsized-locals/{by-value-trait-object-safety-withdefault.rs => by-value-trait-dyn-compatibility-with-default.rs} (100%) rename tests/ui/unsized-locals/{by-value-trait-object-safety.rs => by-value-trait-dyn-compatibility.rs} (100%) rename tests/ui/unsized-locals/{by-value-trait-object-safety.stderr => by-value-trait-dyn-compatibility.stderr} (84%) rename tests/ui/wf/{wf-convert-unsafe-trait-obj-box.rs => wf-convert-dyn-incompat-trait-obj-box.rs} (87%) rename tests/ui/wf/{wf-convert-unsafe-trait-obj-box.stderr => wf-convert-dyn-incompat-trait-obj-box.stderr} (86%) rename tests/ui/wf/{wf-convert-unsafe-trait-obj.rs => wf-convert-dyn-incompat-trait-obj.rs} (87%) rename tests/ui/wf/{wf-convert-unsafe-trait-obj.stderr => wf-convert-dyn-incompat-trait-obj.stderr} (87%) rename tests/ui/wf/{wf-unsafe-trait-obj-match.rs => wf-dyn-incompat-trait-obj-match.rs} (100%) rename tests/ui/wf/{wf-unsafe-trait-obj-match.stderr => wf-dyn-incompat-trait-obj-match.stderr} (89%) rename tests/ui/wf/{wf-object-safe.rs => wf-dyn-incompatible.rs} (57%) rename tests/ui/wf/{wf-object-safe.stderr => wf-dyn-incompatible.stderr} (90%) diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt index 86cae849b97..92aafc5a98e 100644 --- a/src/tools/tidy/src/issues.txt +++ b/src/tools/tidy/src/issues.txt @@ -3173,10 +3173,6 @@ ui/nll/user-annotations/issue-55241.rs ui/nll/user-annotations/issue-55748-pat-types-constrain-bindings.rs ui/nll/user-annotations/issue-57731-ascibed-coupled-types.rs ui/numbers-arithmetic/issue-8460.rs -ui/object-safety/issue-102762.rs -ui/object-safety/issue-102933.rs -ui/object-safety/issue-106247.rs -ui/object-safety/issue-19538.rs ui/on-unimplemented/issue-104140.rs ui/or-patterns/issue-64879-trailing-before-guard.rs ui/or-patterns/issue-67514-irrefutable-param.rs diff --git a/tests/ui/allocator/dyn-compatible.rs b/tests/ui/allocator/dyn-compatible.rs new file mode 100644 index 00000000000..9d8235e58d9 --- /dev/null +++ b/tests/ui/allocator/dyn-compatible.rs @@ -0,0 +1,13 @@ +//@ run-pass + +// Check that `Allocator` is dyn-compatible, this allows for polymorphic allocators + +#![feature(allocator_api)] + +use std::alloc::{Allocator, System}; + +fn ensure_dyn_compatible(_: &dyn Allocator) {} + +fn main() { + ensure_dyn_compatible(&System); +} diff --git a/tests/ui/allocator/object-safe.rs b/tests/ui/allocator/object-safe.rs deleted file mode 100644 index 1c1f4fe0bf6..00000000000 --- a/tests/ui/allocator/object-safe.rs +++ /dev/null @@ -1,13 +0,0 @@ -//@ run-pass - -// Check that `Allocator` is object safe, this allows for polymorphic allocators - -#![feature(allocator_api)] - -use std::alloc::{Allocator, System}; - -fn ensure_object_safe(_: &dyn Allocator) {} - -fn main() { - ensure_object_safe(&System); -} diff --git a/tests/ui/associated-type-bounds/entails-sized-object-safety.rs b/tests/ui/associated-type-bounds/entails-sized-dyn-compatibility.rs similarity index 67% rename from tests/ui/associated-type-bounds/entails-sized-object-safety.rs rename to tests/ui/associated-type-bounds/entails-sized-dyn-compatibility.rs index ad2cbe48209..943df68493f 100644 --- a/tests/ui/associated-type-bounds/entails-sized-object-safety.rs +++ b/tests/ui/associated-type-bounds/entails-sized-dyn-compatibility.rs @@ -4,21 +4,21 @@ trait Tr1: Sized { type As1; } trait Tr2<'a>: Sized { type As2; } trait ObjTr1 { fn foo() -> Self where Self: Tr1; } -fn _assert_obj_safe_1(_: Box) {} +fn _assert_dyn_compat_1(_: Box) {} trait ObjTr2 { fn foo() -> Self where Self: Tr1; } -fn _assert_obj_safe_2(_: Box) {} +fn _assert_dyn_compat_2(_: Box) {} trait ObjTr3 { fn foo() -> Self where Self: Tr1 + 'static + Copy>; } -fn _assert_obj_safe_3(_: Box) {} +fn _assert_dyn_compat_3(_: Box) {} trait ObjTr4 { fn foo() -> Self where Self: Tr1 Tr2<'a>>; } -fn _assert_obj_safe_4(_: Box) {} +fn _assert_dyn_compat_4(_: Box) {} trait ObjTr5 { fn foo() -> Self where for<'a> Self: Tr1>; } -fn _assert_obj_safe_5(_: Box) {} +fn _assert_dyn_compat_5(_: Box) {} trait ObjTr6 { fn foo() -> Self where Self: for<'a> Tr1 Tr2<'b>>>; } -fn _assert_obj_safe_6(_: Box) {} +fn _assert_dyn_compat_6(_: Box) {} fn main() {} diff --git a/tests/ui/async-await/in-trait/object-safety.rs b/tests/ui/async-await/in-trait/dyn-compatibility.rs similarity index 100% rename from tests/ui/async-await/in-trait/object-safety.rs rename to tests/ui/async-await/in-trait/dyn-compatibility.rs diff --git a/tests/ui/async-await/in-trait/object-safety.stderr b/tests/ui/async-await/in-trait/dyn-compatibility.stderr similarity index 90% rename from tests/ui/async-await/in-trait/object-safety.stderr rename to tests/ui/async-await/in-trait/dyn-compatibility.stderr index 8e73abab933..5cc3b6800dd 100644 --- a/tests/ui/async-await/in-trait/object-safety.stderr +++ b/tests/ui/async-await/in-trait/dyn-compatibility.stderr @@ -1,11 +1,11 @@ error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/object-safety.rs:9:12 + --> $DIR/dyn-compatibility.rs:9:12 | LL | let x: &dyn Foo = todo!(); | ^^^^^^^^ `Foo` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety.rs:5:14 + --> $DIR/dyn-compatibility.rs:5:14 | LL | trait Foo { | --- this trait cannot be made into an object... diff --git a/tests/ui/coherence/coherence-impl-trait-for-trait-object-safe.rs b/tests/ui/coherence/coherence-impl-trait-for-trait-dyn-compatible.rs similarity index 54% rename from tests/ui/coherence/coherence-impl-trait-for-trait-object-safe.rs rename to tests/ui/coherence/coherence-impl-trait-for-trait-dyn-compatible.rs index bce3b0fd729..f41d3a783ab 100644 --- a/tests/ui/coherence/coherence-impl-trait-for-trait-object-safe.rs +++ b/tests/ui/coherence/coherence-impl-trait-for-trait-dyn-compatible.rs @@ -1,10 +1,10 @@ // Test that we give suitable error messages when the user attempts to // impl a trait `Trait` for its own object type. -// If the trait is not object-safe, we give a more tailored message +// If the trait is dyn-incompatible, we give a more tailored message // because we're such schnuckels: -trait NotObjectSafe { fn eq(&self, other: Self); } -impl NotObjectSafe for dyn NotObjectSafe { } +trait DynIncompatible { fn eq(&self, other: Self); } +impl DynIncompatible for dyn DynIncompatible { } //~^ ERROR E0038 //~| ERROR E0046 diff --git a/tests/ui/coherence/coherence-impl-trait-for-trait-dyn-compatible.stderr b/tests/ui/coherence/coherence-impl-trait-for-trait-dyn-compatible.stderr new file mode 100644 index 00000000000..542be2dbc30 --- /dev/null +++ b/tests/ui/coherence/coherence-impl-trait-for-trait-dyn-compatible.stderr @@ -0,0 +1,27 @@ +error[E0038]: the trait `DynIncompatible` cannot be made into an object + --> $DIR/coherence-impl-trait-for-trait-dyn-compatible.rs:7:26 + | +LL | impl DynIncompatible for dyn DynIncompatible { } + | ^^^^^^^^^^^^^^^^^^^ `DynIncompatible` cannot be made into an object + | +note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/coherence-impl-trait-for-trait-dyn-compatible.rs:6:45 + | +LL | trait DynIncompatible { fn eq(&self, other: Self); } + | --------------- ^^^^ ...because method `eq` references the `Self` type in this parameter + | | + | this trait cannot be made into an object... + = help: consider moving `eq` to another trait + +error[E0046]: not all trait items implemented, missing: `eq` + --> $DIR/coherence-impl-trait-for-trait-dyn-compatible.rs:7:1 + | +LL | trait DynIncompatible { fn eq(&self, other: Self); } + | -------------------------- `eq` from trait +LL | impl DynIncompatible for dyn DynIncompatible { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `eq` in implementation + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0038, E0046. +For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/coherence/coherence-impl-trait-for-trait-object-safe.stderr b/tests/ui/coherence/coherence-impl-trait-for-trait-object-safe.stderr deleted file mode 100644 index ce65e079ab4..00000000000 --- a/tests/ui/coherence/coherence-impl-trait-for-trait-object-safe.stderr +++ /dev/null @@ -1,27 +0,0 @@ -error[E0038]: the trait `NotObjectSafe` cannot be made into an object - --> $DIR/coherence-impl-trait-for-trait-object-safe.rs:7:24 - | -LL | impl NotObjectSafe for dyn NotObjectSafe { } - | ^^^^^^^^^^^^^^^^^ `NotObjectSafe` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/coherence-impl-trait-for-trait-object-safe.rs:6:43 - | -LL | trait NotObjectSafe { fn eq(&self, other: Self); } - | ------------- ^^^^ ...because method `eq` references the `Self` type in this parameter - | | - | this trait cannot be made into an object... - = help: consider moving `eq` to another trait - -error[E0046]: not all trait items implemented, missing: `eq` - --> $DIR/coherence-impl-trait-for-trait-object-safe.rs:7:1 - | -LL | trait NotObjectSafe { fn eq(&self, other: Self); } - | -------------------------- `eq` from trait -LL | impl NotObjectSafe for dyn NotObjectSafe { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `eq` in implementation - -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0038, E0046. -For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_object_safety.rs b/tests/ui/const-generics/adt_const_params/const_param_ty_dyn_compatibility.rs similarity index 100% rename from tests/ui/const-generics/adt_const_params/const_param_ty_object_safety.rs rename to tests/ui/const-generics/adt_const_params/const_param_ty_dyn_compatibility.rs diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_object_safety.stderr b/tests/ui/const-generics/adt_const_params/const_param_ty_dyn_compatibility.stderr similarity index 93% rename from tests/ui/const-generics/adt_const_params/const_param_ty_object_safety.stderr rename to tests/ui/const-generics/adt_const_params/const_param_ty_dyn_compatibility.stderr index 831b40887ac..84281eb53c9 100644 --- a/tests/ui/const-generics/adt_const_params/const_param_ty_object_safety.stderr +++ b/tests/ui/const-generics/adt_const_params/const_param_ty_dyn_compatibility.stderr @@ -1,5 +1,5 @@ error[E0038]: the trait `ConstParamTy_` cannot be made into an object - --> $DIR/const_param_ty_object_safety.rs:6:12 + --> $DIR/const_param_ty_dyn_compatibility.rs:6:12 | LL | fn foo(a: &dyn ConstParamTy_) {} | ^^^^^^^^^^^^^^^^^ `ConstParamTy_` cannot be made into an object @@ -14,7 +14,7 @@ LL | fn foo(a: &impl ConstParamTy_) {} | ~~~~ error[E0038]: the trait `UnsizedConstParamTy` cannot be made into an object - --> $DIR/const_param_ty_object_safety.rs:9:12 + --> $DIR/const_param_ty_dyn_compatibility.rs:9:12 | LL | fn bar(a: &dyn UnsizedConstParamTy) {} | ^^^^^^^^^^^^^^^^^^^^^^^ `UnsizedConstParamTy` cannot be made into an object diff --git a/tests/ui/const-generics/generic_const_exprs/object-safety-err-ret.rs b/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-ret.rs similarity index 100% rename from tests/ui/const-generics/generic_const_exprs/object-safety-err-ret.rs rename to tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-ret.rs diff --git a/tests/ui/const-generics/generic_const_exprs/object-safety-err-ret.stderr b/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-ret.stderr similarity index 91% rename from tests/ui/const-generics/generic_const_exprs/object-safety-err-ret.stderr rename to tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-ret.stderr index fb57da42bb2..d2017615e67 100644 --- a/tests/ui/const-generics/generic_const_exprs/object-safety-err-ret.stderr +++ b/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-ret.stderr @@ -1,11 +1,11 @@ error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/object-safety-err-ret.rs:17:16 + --> $DIR/dyn-compatibility-err-ret.rs:17:16 | LL | fn use_dyn(v: &dyn Foo) { | ^^^^^^^ `Foo` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-err-ret.rs:8:8 + --> $DIR/dyn-compatibility-err-ret.rs:8:8 | LL | trait Foo { | --- this trait cannot be made into an object... @@ -17,13 +17,13 @@ LL | fn test(&self) -> [u8; bar::()]; = help: only type `()` implements the trait, consider using it directly instead error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/object-safety-err-ret.rs:18:5 + --> $DIR/dyn-compatibility-err-ret.rs:18:5 | LL | v.test(); | ^^^^^^^^ `Foo` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-err-ret.rs:8:8 + --> $DIR/dyn-compatibility-err-ret.rs:8:8 | LL | trait Foo { | --- this trait cannot be made into an object... diff --git a/tests/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.rs b/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-where-bounds.rs similarity index 100% rename from tests/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.rs rename to tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-where-bounds.rs diff --git a/tests/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.stderr b/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-where-bounds.stderr similarity index 88% rename from tests/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.stderr rename to tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-where-bounds.stderr index 831bda71295..26ca2d4df5f 100644 --- a/tests/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.stderr +++ b/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-where-bounds.stderr @@ -1,11 +1,11 @@ error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/object-safety-err-where-bounds.rs:15:16 + --> $DIR/dyn-compatibility-err-where-bounds.rs:15:16 | LL | fn use_dyn(v: &dyn Foo) { | ^^^^^^^ `Foo` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-err-where-bounds.rs:8:8 + --> $DIR/dyn-compatibility-err-where-bounds.rs:8:8 | LL | trait Foo { | --- this trait cannot be made into an object... @@ -15,13 +15,13 @@ LL | fn test(&self) where [u8; bar::()]: Sized; = help: only type `()` implements the trait, consider using it directly instead error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/object-safety-err-where-bounds.rs:17:5 + --> $DIR/dyn-compatibility-err-where-bounds.rs:17:5 | LL | v.test(); | ^^^^^^^^ `Foo` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-err-where-bounds.rs:8:8 + --> $DIR/dyn-compatibility-err-where-bounds.rs:8:8 | LL | trait Foo { | --- this trait cannot be made into an object... diff --git a/tests/ui/const-generics/generic_const_exprs/object-safety-ok-infer-err.rs b/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-ok-infer-err.rs similarity index 100% rename from tests/ui/const-generics/generic_const_exprs/object-safety-ok-infer-err.rs rename to tests/ui/const-generics/generic_const_exprs/dyn-compatibility-ok-infer-err.rs diff --git a/tests/ui/const-generics/generic_const_exprs/object-safety-ok-infer-err.stderr b/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-ok-infer-err.stderr similarity index 85% rename from tests/ui/const-generics/generic_const_exprs/object-safety-ok-infer-err.stderr rename to tests/ui/const-generics/generic_const_exprs/dyn-compatibility-ok-infer-err.stderr index d1e1c976da6..a124fbc6092 100644 --- a/tests/ui/const-generics/generic_const_exprs/object-safety-ok-infer-err.stderr +++ b/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-ok-infer-err.stderr @@ -1,11 +1,11 @@ error[E0284]: type annotations needed - --> $DIR/object-safety-ok-infer-err.rs:19:5 + --> $DIR/dyn-compatibility-ok-infer-err.rs:19:5 | LL | use_dyn(&()); | ^^^^^^^ cannot infer the value of the const parameter `N` declared on the function `use_dyn` | note: required by a const generic parameter in `use_dyn` - --> $DIR/object-safety-ok-infer-err.rs:14:12 + --> $DIR/dyn-compatibility-ok-infer-err.rs:14:12 | LL | fn use_dyn(v: &dyn Foo) where [u8; N + 1]: Sized { | ^^^^^^^^^^^^^^ required by this const generic parameter in `use_dyn` @@ -15,7 +15,7 @@ LL | use_dyn::(&()); | +++++ error[E0284]: type annotations needed - --> $DIR/object-safety-ok-infer-err.rs:19:5 + --> $DIR/dyn-compatibility-ok-infer-err.rs:19:5 | LL | use_dyn(&()); | ^^^^^^^ --- type must be known at this point @@ -23,7 +23,7 @@ LL | use_dyn(&()); | cannot infer the value of the const parameter `N` declared on the function `use_dyn` | note: required for `()` to implement `Foo<_>` - --> $DIR/object-safety-ok-infer-err.rs:8:22 + --> $DIR/dyn-compatibility-ok-infer-err.rs:8:22 | LL | impl Foo for () { | -------------- ^^^^^^ ^^ diff --git a/tests/ui/const-generics/generic_const_exprs/object-safety-ok.rs b/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-ok.rs similarity index 100% rename from tests/ui/const-generics/generic_const_exprs/object-safety-ok.rs rename to tests/ui/const-generics/generic_const_exprs/dyn-compatibility-ok.rs diff --git a/tests/ui/object-safety/almost-supertrait-associated-type.rs b/tests/ui/dyn-compatibility/almost-supertrait-associated-type.rs similarity index 95% rename from tests/ui/object-safety/almost-supertrait-associated-type.rs rename to tests/ui/dyn-compatibility/almost-supertrait-associated-type.rs index 963cdff526e..83076f7d5fc 100644 --- a/tests/ui/object-safety/almost-supertrait-associated-type.rs +++ b/tests/ui/dyn-compatibility/almost-supertrait-associated-type.rs @@ -1,5 +1,5 @@ // Test for fixed unsoundness in #126079. -// Enforces that the associated types that are object safe +// Enforces that the associated types that are dyn-compatible. use std::marker::PhantomData; diff --git a/tests/ui/object-safety/almost-supertrait-associated-type.stderr b/tests/ui/dyn-compatibility/almost-supertrait-associated-type.stderr similarity index 100% rename from tests/ui/object-safety/almost-supertrait-associated-type.stderr rename to tests/ui/dyn-compatibility/almost-supertrait-associated-type.stderr diff --git a/tests/ui/object-safety/assoc_const_bounds.rs b/tests/ui/dyn-compatibility/assoc_const_bounds.rs similarity index 100% rename from tests/ui/object-safety/assoc_const_bounds.rs rename to tests/ui/dyn-compatibility/assoc_const_bounds.rs diff --git a/tests/ui/object-safety/assoc_const_bounds_sized.rs b/tests/ui/dyn-compatibility/assoc_const_bounds_sized.rs similarity index 100% rename from tests/ui/object-safety/assoc_const_bounds_sized.rs rename to tests/ui/dyn-compatibility/assoc_const_bounds_sized.rs diff --git a/tests/ui/object-safety/assoc_type_bounds.rs b/tests/ui/dyn-compatibility/assoc_type_bounds.rs similarity index 100% rename from tests/ui/object-safety/assoc_type_bounds.rs rename to tests/ui/dyn-compatibility/assoc_type_bounds.rs diff --git a/tests/ui/object-safety/assoc_type_bounds.stderr b/tests/ui/dyn-compatibility/assoc_type_bounds.stderr similarity index 100% rename from tests/ui/object-safety/assoc_type_bounds.stderr rename to tests/ui/dyn-compatibility/assoc_type_bounds.stderr diff --git a/tests/ui/object-safety/assoc_type_bounds2.rs b/tests/ui/dyn-compatibility/assoc_type_bounds2.rs similarity index 100% rename from tests/ui/object-safety/assoc_type_bounds2.rs rename to tests/ui/dyn-compatibility/assoc_type_bounds2.rs diff --git a/tests/ui/object-safety/assoc_type_bounds2.stderr b/tests/ui/dyn-compatibility/assoc_type_bounds2.stderr similarity index 100% rename from tests/ui/object-safety/assoc_type_bounds2.stderr rename to tests/ui/dyn-compatibility/assoc_type_bounds2.stderr diff --git a/tests/ui/object-safety/assoc_type_bounds_implicit_sized.fixed b/tests/ui/dyn-compatibility/assoc_type_bounds_implicit_sized.fixed similarity index 100% rename from tests/ui/object-safety/assoc_type_bounds_implicit_sized.fixed rename to tests/ui/dyn-compatibility/assoc_type_bounds_implicit_sized.fixed diff --git a/tests/ui/object-safety/assoc_type_bounds_implicit_sized.rs b/tests/ui/dyn-compatibility/assoc_type_bounds_implicit_sized.rs similarity index 100% rename from tests/ui/object-safety/assoc_type_bounds_implicit_sized.rs rename to tests/ui/dyn-compatibility/assoc_type_bounds_implicit_sized.rs diff --git a/tests/ui/object-safety/assoc_type_bounds_implicit_sized.stderr b/tests/ui/dyn-compatibility/assoc_type_bounds_implicit_sized.stderr similarity index 100% rename from tests/ui/object-safety/assoc_type_bounds_implicit_sized.stderr rename to tests/ui/dyn-compatibility/assoc_type_bounds_implicit_sized.stderr diff --git a/tests/ui/object-safety/assoc_type_bounds_sized.rs b/tests/ui/dyn-compatibility/assoc_type_bounds_sized.rs similarity index 100% rename from tests/ui/object-safety/assoc_type_bounds_sized.rs rename to tests/ui/dyn-compatibility/assoc_type_bounds_sized.rs diff --git a/tests/ui/object-safety/assoc_type_bounds_sized_others.rs b/tests/ui/dyn-compatibility/assoc_type_bounds_sized_others.rs similarity index 100% rename from tests/ui/object-safety/assoc_type_bounds_sized_others.rs rename to tests/ui/dyn-compatibility/assoc_type_bounds_sized_others.rs diff --git a/tests/ui/object-safety/assoc_type_bounds_sized_others.stderr b/tests/ui/dyn-compatibility/assoc_type_bounds_sized_others.stderr similarity index 100% rename from tests/ui/object-safety/assoc_type_bounds_sized_others.stderr rename to tests/ui/dyn-compatibility/assoc_type_bounds_sized_others.stderr diff --git a/tests/ui/object-safety/assoc_type_bounds_sized_unnecessary.rs b/tests/ui/dyn-compatibility/assoc_type_bounds_sized_unnecessary.rs similarity index 100% rename from tests/ui/object-safety/assoc_type_bounds_sized_unnecessary.rs rename to tests/ui/dyn-compatibility/assoc_type_bounds_sized_unnecessary.rs diff --git a/tests/ui/object-safety/assoc_type_bounds_sized_unnecessary.stderr b/tests/ui/dyn-compatibility/assoc_type_bounds_sized_unnecessary.stderr similarity index 100% rename from tests/ui/object-safety/assoc_type_bounds_sized_unnecessary.stderr rename to tests/ui/dyn-compatibility/assoc_type_bounds_sized_unnecessary.stderr diff --git a/tests/ui/object-safety/assoc_type_bounds_sized_used.rs b/tests/ui/dyn-compatibility/assoc_type_bounds_sized_used.rs similarity index 100% rename from tests/ui/object-safety/assoc_type_bounds_sized_used.rs rename to tests/ui/dyn-compatibility/assoc_type_bounds_sized_used.rs diff --git a/tests/ui/object-safety/assoc_type_bounds_sized_used.stderr b/tests/ui/dyn-compatibility/assoc_type_bounds_sized_used.stderr similarity index 100% rename from tests/ui/object-safety/assoc_type_bounds_sized_used.stderr rename to tests/ui/dyn-compatibility/assoc_type_bounds_sized_used.stderr diff --git a/tests/ui/object-safety/object-safety-associated-consts.curr.stderr b/tests/ui/dyn-compatibility/associated-consts.curr.stderr similarity index 86% rename from tests/ui/object-safety/object-safety-associated-consts.curr.stderr rename to tests/ui/dyn-compatibility/associated-consts.curr.stderr index 3c070f17c82..17d184942c7 100644 --- a/tests/ui/object-safety/object-safety-associated-consts.curr.stderr +++ b/tests/ui/dyn-compatibility/associated-consts.curr.stderr @@ -1,11 +1,11 @@ error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-associated-consts.rs:12:31 + --> $DIR/associated-consts.rs:12:31 | LL | fn make_bar(t: &T) -> &dyn Bar { | ^^^^^^^ `Bar` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-associated-consts.rs:9:11 + --> $DIR/associated-consts.rs:9:11 | LL | trait Bar { | --- this trait cannot be made into an object... @@ -14,13 +14,13 @@ LL | const X: usize; = help: consider moving `X` to another trait error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-associated-consts.rs:14:5 + --> $DIR/associated-consts.rs:14:5 | LL | t | ^ `Bar` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-associated-consts.rs:9:11 + --> $DIR/associated-consts.rs:9:11 | LL | trait Bar { | --- this trait cannot be made into an object... diff --git a/tests/ui/object-safety/object-safety-associated-consts.dyn_compatible_for_dispatch.stderr b/tests/ui/dyn-compatibility/associated-consts.dyn_compatible_for_dispatch.stderr similarity index 87% rename from tests/ui/object-safety/object-safety-associated-consts.dyn_compatible_for_dispatch.stderr rename to tests/ui/dyn-compatibility/associated-consts.dyn_compatible_for_dispatch.stderr index 5b98cc35505..cc5120232c2 100644 --- a/tests/ui/object-safety/object-safety-associated-consts.dyn_compatible_for_dispatch.stderr +++ b/tests/ui/dyn-compatibility/associated-consts.dyn_compatible_for_dispatch.stderr @@ -1,11 +1,11 @@ error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-associated-consts.rs:14:5 + --> $DIR/associated-consts.rs:14:5 | LL | t | ^ `Bar` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-associated-consts.rs:9:11 + --> $DIR/associated-consts.rs:9:11 | LL | trait Bar { | --- this trait cannot be made into an object... diff --git a/tests/ui/object-safety/object-safety-associated-consts.rs b/tests/ui/dyn-compatibility/associated-consts.rs similarity index 100% rename from tests/ui/object-safety/object-safety-associated-consts.rs rename to tests/ui/dyn-compatibility/associated-consts.rs diff --git a/tests/ui/object-safety/avoid-ice-on-warning-2.new.stderr b/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.new.stderr similarity index 100% rename from tests/ui/object-safety/avoid-ice-on-warning-2.new.stderr rename to tests/ui/dyn-compatibility/avoid-ice-on-warning-2.new.stderr diff --git a/tests/ui/object-safety/avoid-ice-on-warning-2.old.stderr b/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.old.stderr similarity index 100% rename from tests/ui/object-safety/avoid-ice-on-warning-2.old.stderr rename to tests/ui/dyn-compatibility/avoid-ice-on-warning-2.old.stderr diff --git a/tests/ui/object-safety/avoid-ice-on-warning-2.rs b/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.rs similarity index 100% rename from tests/ui/object-safety/avoid-ice-on-warning-2.rs rename to tests/ui/dyn-compatibility/avoid-ice-on-warning-2.rs diff --git a/tests/ui/object-safety/avoid-ice-on-warning-3.new.stderr b/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.new.stderr similarity index 100% rename from tests/ui/object-safety/avoid-ice-on-warning-3.new.stderr rename to tests/ui/dyn-compatibility/avoid-ice-on-warning-3.new.stderr diff --git a/tests/ui/object-safety/avoid-ice-on-warning-3.old.stderr b/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.old.stderr similarity index 100% rename from tests/ui/object-safety/avoid-ice-on-warning-3.old.stderr rename to tests/ui/dyn-compatibility/avoid-ice-on-warning-3.old.stderr diff --git a/tests/ui/object-safety/avoid-ice-on-warning-3.rs b/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.rs similarity index 100% rename from tests/ui/object-safety/avoid-ice-on-warning-3.rs rename to tests/ui/dyn-compatibility/avoid-ice-on-warning-3.rs diff --git a/tests/ui/object-safety/avoid-ice-on-warning.new.stderr b/tests/ui/dyn-compatibility/avoid-ice-on-warning.new.stderr similarity index 100% rename from tests/ui/object-safety/avoid-ice-on-warning.new.stderr rename to tests/ui/dyn-compatibility/avoid-ice-on-warning.new.stderr diff --git a/tests/ui/object-safety/avoid-ice-on-warning.old.stderr b/tests/ui/dyn-compatibility/avoid-ice-on-warning.old.stderr similarity index 100% rename from tests/ui/object-safety/avoid-ice-on-warning.old.stderr rename to tests/ui/dyn-compatibility/avoid-ice-on-warning.old.stderr diff --git a/tests/ui/object-safety/avoid-ice-on-warning.rs b/tests/ui/dyn-compatibility/avoid-ice-on-warning.rs similarity index 100% rename from tests/ui/object-safety/avoid-ice-on-warning.rs rename to tests/ui/dyn-compatibility/avoid-ice-on-warning.rs diff --git a/tests/ui/object-safety/bare-trait-dont-suggest-dyn.new.fixed b/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.new.fixed similarity index 100% rename from tests/ui/object-safety/bare-trait-dont-suggest-dyn.new.fixed rename to tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.new.fixed diff --git a/tests/ui/object-safety/bare-trait-dont-suggest-dyn.new.stderr b/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.new.stderr similarity index 100% rename from tests/ui/object-safety/bare-trait-dont-suggest-dyn.new.stderr rename to tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.new.stderr diff --git a/tests/ui/object-safety/bare-trait-dont-suggest-dyn.old.stderr b/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.old.stderr similarity index 100% rename from tests/ui/object-safety/bare-trait-dont-suggest-dyn.old.stderr rename to tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.old.stderr diff --git a/tests/ui/object-safety/bare-trait-dont-suggest-dyn.rs b/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.rs similarity index 100% rename from tests/ui/object-safety/bare-trait-dont-suggest-dyn.rs rename to tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.rs diff --git a/tests/ui/object-safety/object-safety-bounds.rs b/tests/ui/dyn-compatibility/bounds.rs similarity index 72% rename from tests/ui/object-safety/object-safety-bounds.rs rename to tests/ui/dyn-compatibility/bounds.rs index 44bd369324a..1e04d11c516 100644 --- a/tests/ui/object-safety/object-safety-bounds.rs +++ b/tests/ui/dyn-compatibility/bounds.rs @@ -1,4 +1,4 @@ -// Traits with bounds mentioning `Self` are not object safe +// Traits with bounds mentioning `Self` are dyn-incompatible. trait X { type U: PartialEq; diff --git a/tests/ui/object-safety/object-safety-bounds.stderr b/tests/ui/dyn-compatibility/bounds.stderr similarity index 89% rename from tests/ui/object-safety/object-safety-bounds.stderr rename to tests/ui/dyn-compatibility/bounds.stderr index 96a81a69639..9231d524fd1 100644 --- a/tests/ui/object-safety/object-safety-bounds.stderr +++ b/tests/ui/dyn-compatibility/bounds.stderr @@ -1,11 +1,11 @@ error[E0038]: the trait `X` cannot be made into an object - --> $DIR/object-safety-bounds.rs:7:15 + --> $DIR/bounds.rs:7:15 | LL | fn f() -> Box> { | ^^^^^^^^^^^^^^ `X` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-bounds.rs:4:13 + --> $DIR/bounds.rs:4:13 | LL | trait X { | - this trait cannot be made into an object... diff --git a/tests/ui/object-safety/object-safety-by-value-self-use.rs b/tests/ui/dyn-compatibility/by-value-self-use.rs similarity index 79% rename from tests/ui/object-safety/object-safety-by-value-self-use.rs rename to tests/ui/dyn-compatibility/by-value-self-use.rs index 8e93c538217..3c04ec0cd88 100644 --- a/tests/ui/object-safety/object-safety-by-value-self-use.rs +++ b/tests/ui/dyn-compatibility/by-value-self-use.rs @@ -1,4 +1,4 @@ -// Check that while a trait with by-value self is object-safe, we +// Check that while a trait with by-value self is dyn-compatible, we // can't actually invoke it from an object (yet...?). #![feature(rustc_attrs)] diff --git a/tests/ui/object-safety/object-safety-by-value-self-use.stderr b/tests/ui/dyn-compatibility/by-value-self-use.stderr similarity index 83% rename from tests/ui/object-safety/object-safety-by-value-self-use.stderr rename to tests/ui/dyn-compatibility/by-value-self-use.stderr index 1701f6059a8..14785b982a3 100644 --- a/tests/ui/object-safety/object-safety-by-value-self-use.stderr +++ b/tests/ui/dyn-compatibility/by-value-self-use.stderr @@ -1,5 +1,5 @@ error[E0161]: cannot move a value of type `dyn Bar` - --> $DIR/object-safety-by-value-self-use.rs:15:5 + --> $DIR/by-value-self-use.rs:15:5 | LL | t.bar() | ^ the size of `dyn Bar` cannot be statically determined diff --git a/tests/ui/object-safety/object-safety-by-value-self.rs b/tests/ui/dyn-compatibility/by-value-self.rs similarity index 90% rename from tests/ui/object-safety/object-safety-by-value-self.rs rename to tests/ui/dyn-compatibility/by-value-self.rs index 0d20032327c..a057a7ff0b5 100644 --- a/tests/ui/object-safety/object-safety-by-value-self.rs +++ b/tests/ui/dyn-compatibility/by-value-self.rs @@ -1,4 +1,4 @@ -// Check that a trait with by-value self is considered object-safe. +// Check that a trait with by-value self is considered dyn-compatible. //@ build-pass (FIXME(62277): could be check-pass?) #![allow(dead_code)] diff --git a/tests/ui/object-safety/call-when-assoc-ty-is-sized.rs b/tests/ui/dyn-compatibility/call-when-assoc-ty-is-sized.rs similarity index 100% rename from tests/ui/object-safety/call-when-assoc-ty-is-sized.rs rename to tests/ui/dyn-compatibility/call-when-assoc-ty-is-sized.rs diff --git a/tests/ui/object-safety/issue-102933.rs b/tests/ui/dyn-compatibility/elaborated-predicates-ordering.rs similarity index 93% rename from tests/ui/object-safety/issue-102933.rs rename to tests/ui/dyn-compatibility/elaborated-predicates-ordering.rs index aa678fea176..d3c3963a673 100644 --- a/tests/ui/object-safety/issue-102933.rs +++ b/tests/ui/dyn-compatibility/elaborated-predicates-ordering.rs @@ -1,4 +1,5 @@ //@ check-pass +// issue: rust-lang/rust#102933 use std::future::Future; diff --git a/tests/ui/object-safety/erroneous_signature.rs b/tests/ui/dyn-compatibility/erroneous_signature.rs similarity index 100% rename from tests/ui/object-safety/erroneous_signature.rs rename to tests/ui/dyn-compatibility/erroneous_signature.rs diff --git a/tests/ui/object-safety/erroneous_signature.stderr b/tests/ui/dyn-compatibility/erroneous_signature.stderr similarity index 100% rename from tests/ui/object-safety/erroneous_signature.stderr rename to tests/ui/dyn-compatibility/erroneous_signature.stderr diff --git a/tests/ui/object-safety/object-safety-generics.curr.stderr b/tests/ui/dyn-compatibility/generics.curr.stderr similarity index 88% rename from tests/ui/object-safety/object-safety-generics.curr.stderr rename to tests/ui/dyn-compatibility/generics.curr.stderr index 7528785d90b..c63db38a080 100644 --- a/tests/ui/object-safety/object-safety-generics.curr.stderr +++ b/tests/ui/dyn-compatibility/generics.curr.stderr @@ -1,11 +1,11 @@ error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-generics.rs:18:31 + --> $DIR/generics.rs:18:31 | LL | fn make_bar(t: &T) -> &dyn Bar { | ^^^^^^^ `Bar` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-generics.rs:10:8 + --> $DIR/generics.rs:10:8 | LL | trait Bar { | --- this trait cannot be made into an object... @@ -14,13 +14,13 @@ LL | fn bar(&self, t: T); = help: consider moving `bar` to another trait error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-generics.rs:25:40 + --> $DIR/generics.rs:25:40 | LL | fn make_bar_explicit(t: &T) -> &dyn Bar { | ^^^^^^^ `Bar` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-generics.rs:10:8 + --> $DIR/generics.rs:10:8 | LL | trait Bar { | --- this trait cannot be made into an object... @@ -29,13 +29,13 @@ LL | fn bar(&self, t: T); = help: consider moving `bar` to another trait error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-generics.rs:20:5 + --> $DIR/generics.rs:20:5 | LL | t | ^ `Bar` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-generics.rs:10:8 + --> $DIR/generics.rs:10:8 | LL | trait Bar { | --- this trait cannot be made into an object... @@ -45,13 +45,13 @@ LL | fn bar(&self, t: T); = note: required for the cast from `&T` to `&dyn Bar` error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-generics.rs:27:10 + --> $DIR/generics.rs:27:10 | LL | t as &dyn Bar | ^^^^^^^^ `Bar` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-generics.rs:10:8 + --> $DIR/generics.rs:10:8 | LL | trait Bar { | --- this trait cannot be made into an object... @@ -60,13 +60,13 @@ LL | fn bar(&self, t: T); = help: consider moving `bar` to another trait error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-generics.rs:27:5 + --> $DIR/generics.rs:27:5 | LL | t as &dyn Bar | ^ `Bar` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-generics.rs:10:8 + --> $DIR/generics.rs:10:8 | LL | trait Bar { | --- this trait cannot be made into an object... diff --git a/tests/ui/object-safety/object-safety-generics.dyn_compatible_for_dispatch.stderr b/tests/ui/dyn-compatibility/generics.dyn_compatible_for_dispatch.stderr similarity index 89% rename from tests/ui/object-safety/object-safety-generics.dyn_compatible_for_dispatch.stderr rename to tests/ui/dyn-compatibility/generics.dyn_compatible_for_dispatch.stderr index 4686b994b33..ba2546ef2dc 100644 --- a/tests/ui/object-safety/object-safety-generics.dyn_compatible_for_dispatch.stderr +++ b/tests/ui/dyn-compatibility/generics.dyn_compatible_for_dispatch.stderr @@ -1,11 +1,11 @@ error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-generics.rs:20:5 + --> $DIR/generics.rs:20:5 | LL | t | ^ `Bar` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-generics.rs:10:8 + --> $DIR/generics.rs:10:8 | LL | trait Bar { | --- this trait cannot be made into an object... @@ -15,13 +15,13 @@ LL | fn bar(&self, t: T); = note: required for the cast from `&T` to `&dyn Bar` error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-generics.rs:27:5 + --> $DIR/generics.rs:27:5 | LL | t as &dyn Bar | ^ `Bar` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-generics.rs:10:8 + --> $DIR/generics.rs:10:8 | LL | trait Bar { | --- this trait cannot be made into an object... diff --git a/tests/ui/object-safety/object-safety-generics.rs b/tests/ui/dyn-compatibility/generics.rs similarity index 100% rename from tests/ui/object-safety/object-safety-generics.rs rename to tests/ui/dyn-compatibility/generics.rs diff --git a/tests/ui/object-safety/issue-106247.rs b/tests/ui/dyn-compatibility/impossible-predicates-multiple_supertrait_upcastable-check.rs similarity index 73% rename from tests/ui/object-safety/issue-106247.rs rename to tests/ui/dyn-compatibility/impossible-predicates-multiple_supertrait_upcastable-check.rs index 20a451a59a1..c2b8ecc141d 100644 --- a/tests/ui/object-safety/issue-106247.rs +++ b/tests/ui/dyn-compatibility/impossible-predicates-multiple_supertrait_upcastable-check.rs @@ -1,4 +1,5 @@ //@ check-pass +// issue: rust-lang/rust#106247 pub trait Trait { fn method(&self) where Self: Sync; diff --git a/tests/ui/object-safety/item-bounds-can-reference-self.rs b/tests/ui/dyn-compatibility/item-bounds-can-reference-self.rs similarity index 100% rename from tests/ui/object-safety/item-bounds-can-reference-self.rs rename to tests/ui/dyn-compatibility/item-bounds-can-reference-self.rs diff --git a/tests/ui/object-safety/issue-19538.rs b/tests/ui/dyn-compatibility/mention-correct-dyn-incompatible-trait.rs similarity index 90% rename from tests/ui/object-safety/issue-19538.rs rename to tests/ui/dyn-compatibility/mention-correct-dyn-incompatible-trait.rs index 7054ef41b1c..1289d2d7874 100644 --- a/tests/ui/object-safety/issue-19538.rs +++ b/tests/ui/dyn-compatibility/mention-correct-dyn-incompatible-trait.rs @@ -1,3 +1,5 @@ +// issue: rust-lang/rust#19538 + trait Foo { fn foo(&self, val: T); } diff --git a/tests/ui/object-safety/issue-19538.stderr b/tests/ui/dyn-compatibility/mention-correct-dyn-incompatible-trait.stderr similarity index 87% rename from tests/ui/object-safety/issue-19538.stderr rename to tests/ui/dyn-compatibility/mention-correct-dyn-incompatible-trait.stderr index 3dbe389686a..7378ec023c9 100644 --- a/tests/ui/object-safety/issue-19538.stderr +++ b/tests/ui/dyn-compatibility/mention-correct-dyn-incompatible-trait.stderr @@ -1,11 +1,11 @@ error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/issue-19538.rs:17:15 + --> $DIR/mention-correct-dyn-incompatible-trait.rs:19:15 | LL | let test: &mut dyn Bar = &mut thing; | ^^^^^^^^^^^^ `Bar` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/issue-19538.rs:2:8 + --> $DIR/mention-correct-dyn-incompatible-trait.rs:4:8 | LL | fn foo(&self, val: T); | ^^^ ...because method `foo` has generic type parameters @@ -16,13 +16,13 @@ LL | trait Bar: Foo { } = help: only type `Thing` implements the trait, consider using it directly instead error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/issue-19538.rs:17:30 + --> $DIR/mention-correct-dyn-incompatible-trait.rs:19:30 | LL | let test: &mut dyn Bar = &mut thing; | ^^^^^^^^^^ `Bar` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/issue-19538.rs:2:8 + --> $DIR/mention-correct-dyn-incompatible-trait.rs:4:8 | LL | fn foo(&self, val: T); | ^^^ ...because method `foo` has generic type parameters diff --git a/tests/ui/object-safety/object-safety-issue-22040.rs b/tests/ui/dyn-compatibility/mentions-Self-in-super-predicates.rs similarity index 100% rename from tests/ui/object-safety/object-safety-issue-22040.rs rename to tests/ui/dyn-compatibility/mentions-Self-in-super-predicates.rs diff --git a/tests/ui/object-safety/object-safety-issue-22040.stderr b/tests/ui/dyn-compatibility/mentions-Self-in-super-predicates.stderr similarity index 87% rename from tests/ui/object-safety/object-safety-issue-22040.stderr rename to tests/ui/dyn-compatibility/mentions-Self-in-super-predicates.stderr index e5723f12258..7578edce7d1 100644 --- a/tests/ui/object-safety/object-safety-issue-22040.stderr +++ b/tests/ui/dyn-compatibility/mentions-Self-in-super-predicates.stderr @@ -1,11 +1,11 @@ error[E0038]: the trait `Expr` cannot be made into an object - --> $DIR/object-safety-issue-22040.rs:12:23 + --> $DIR/mentions-Self-in-super-predicates.rs:12:23 | LL | elements: Vec>, | ^^^^^^^^^^^^^ `Expr` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-issue-22040.rs:5:21 + --> $DIR/mentions-Self-in-super-predicates.rs:5:21 | LL | trait Expr: Debug + PartialEq { | ---- ^^^^^^^^^ ...because it uses `Self` as a type parameter @@ -14,13 +14,13 @@ LL | trait Expr: Debug + PartialEq { = help: only type `SExpr<'x>` implements the trait, consider using it directly instead error[E0038]: the trait `Expr` cannot be made into an object - --> $DIR/object-safety-issue-22040.rs:38:16 + --> $DIR/mentions-Self-in-super-predicates.rs:38:16 | LL | let a: Box = Box::new(SExpr::new()); | ^^^^^^^^ `Expr` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-issue-22040.rs:5:21 + --> $DIR/mentions-Self-in-super-predicates.rs:5:21 | LL | trait Expr: Debug + PartialEq { | ---- ^^^^^^^^^ ...because it uses `Self` as a type parameter @@ -29,13 +29,13 @@ LL | trait Expr: Debug + PartialEq { = help: only type `SExpr<'x>` implements the trait, consider using it directly instead error[E0038]: the trait `Expr` cannot be made into an object - --> $DIR/object-safety-issue-22040.rs:40:16 + --> $DIR/mentions-Self-in-super-predicates.rs:40:16 | LL | let b: Box = Box::new(SExpr::new()); | ^^^^^^^^ `Expr` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-issue-22040.rs:5:21 + --> $DIR/mentions-Self-in-super-predicates.rs:5:21 | LL | trait Expr: Debug + PartialEq { | ---- ^^^^^^^^^ ...because it uses `Self` as a type parameter diff --git a/tests/ui/object-safety/object-safety-mentions-Self.curr.stderr b/tests/ui/dyn-compatibility/mentions-Self.curr.stderr similarity index 88% rename from tests/ui/object-safety/object-safety-mentions-Self.curr.stderr rename to tests/ui/dyn-compatibility/mentions-Self.curr.stderr index 7efb6ec3542..434e41cf218 100644 --- a/tests/ui/object-safety/object-safety-mentions-Self.curr.stderr +++ b/tests/ui/dyn-compatibility/mentions-Self.curr.stderr @@ -1,11 +1,11 @@ error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-mentions-Self.rs:22:31 + --> $DIR/mentions-Self.rs:22:31 | LL | fn make_bar(t: &T) -> &dyn Bar { | ^^^^^^^ `Bar` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-mentions-Self.rs:11:22 + --> $DIR/mentions-Self.rs:11:22 | LL | trait Bar { | --- this trait cannot be made into an object... @@ -14,13 +14,13 @@ LL | fn bar(&self, x: &Self); = help: consider moving `bar` to another trait error[E0038]: the trait `Baz` cannot be made into an object - --> $DIR/object-safety-mentions-Self.rs:28:31 + --> $DIR/mentions-Self.rs:28:31 | LL | fn make_baz(t: &T) -> &dyn Baz { | ^^^^^^^ `Baz` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-mentions-Self.rs:15:22 + --> $DIR/mentions-Self.rs:15:22 | LL | trait Baz { | --- this trait cannot be made into an object... @@ -29,13 +29,13 @@ LL | fn baz(&self) -> Self; = help: consider moving `baz` to another trait error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-mentions-Self.rs:24:5 + --> $DIR/mentions-Self.rs:24:5 | LL | t | ^ `Bar` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-mentions-Self.rs:11:22 + --> $DIR/mentions-Self.rs:11:22 | LL | trait Bar { | --- this trait cannot be made into an object... @@ -45,13 +45,13 @@ LL | fn bar(&self, x: &Self); = note: required for the cast from `&T` to `&dyn Bar` error[E0038]: the trait `Baz` cannot be made into an object - --> $DIR/object-safety-mentions-Self.rs:30:5 + --> $DIR/mentions-Self.rs:30:5 | LL | t | ^ `Baz` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-mentions-Self.rs:15:22 + --> $DIR/mentions-Self.rs:15:22 | LL | trait Baz { | --- this trait cannot be made into an object... diff --git a/tests/ui/object-safety/object-safety-mentions-Self.dyn_compatible_for_dispatch.stderr b/tests/ui/dyn-compatibility/mentions-Self.dyn_compatible_for_dispatch.stderr similarity index 88% rename from tests/ui/object-safety/object-safety-mentions-Self.dyn_compatible_for_dispatch.stderr rename to tests/ui/dyn-compatibility/mentions-Self.dyn_compatible_for_dispatch.stderr index d0efb9c587e..dc2d1f87eb7 100644 --- a/tests/ui/object-safety/object-safety-mentions-Self.dyn_compatible_for_dispatch.stderr +++ b/tests/ui/dyn-compatibility/mentions-Self.dyn_compatible_for_dispatch.stderr @@ -1,11 +1,11 @@ error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-mentions-Self.rs:24:5 + --> $DIR/mentions-Self.rs:24:5 | LL | t | ^ `Bar` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-mentions-Self.rs:11:22 + --> $DIR/mentions-Self.rs:11:22 | LL | trait Bar { | --- this trait cannot be made into an object... @@ -15,13 +15,13 @@ LL | fn bar(&self, x: &Self); = note: required for the cast from `&T` to `&dyn Bar` error[E0038]: the trait `Baz` cannot be made into an object - --> $DIR/object-safety-mentions-Self.rs:30:5 + --> $DIR/mentions-Self.rs:30:5 | LL | t | ^ `Baz` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-mentions-Self.rs:15:22 + --> $DIR/mentions-Self.rs:15:22 | LL | trait Baz { | --- this trait cannot be made into an object... diff --git a/tests/ui/object-safety/object-safety-mentions-Self.rs b/tests/ui/dyn-compatibility/mentions-Self.rs similarity index 100% rename from tests/ui/object-safety/object-safety-mentions-Self.rs rename to tests/ui/dyn-compatibility/mentions-Self.rs diff --git a/tests/ui/traits/object/object-unsafe-missing-assoc-type.rs b/tests/ui/dyn-compatibility/missing-assoc-type.rs similarity index 100% rename from tests/ui/traits/object/object-unsafe-missing-assoc-type.rs rename to tests/ui/dyn-compatibility/missing-assoc-type.rs diff --git a/tests/ui/traits/object/object-unsafe-missing-assoc-type.stderr b/tests/ui/dyn-compatibility/missing-assoc-type.stderr similarity index 86% rename from tests/ui/traits/object/object-unsafe-missing-assoc-type.stderr rename to tests/ui/dyn-compatibility/missing-assoc-type.stderr index 9258b38f26c..f8450ba212d 100644 --- a/tests/ui/traits/object/object-unsafe-missing-assoc-type.stderr +++ b/tests/ui/dyn-compatibility/missing-assoc-type.stderr @@ -1,11 +1,11 @@ error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/object-unsafe-missing-assoc-type.rs:5:16 + --> $DIR/missing-assoc-type.rs:5:16 | LL | fn bar(x: &dyn Foo) {} | ^^^ `Foo` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-unsafe-missing-assoc-type.rs:2:10 + --> $DIR/missing-assoc-type.rs:2:10 | LL | trait Foo { | --- this trait cannot be made into an object... @@ -14,13 +14,13 @@ LL | type Bar; = help: consider moving `Bar` to another trait error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/object-unsafe-missing-assoc-type.rs:5:16 + --> $DIR/missing-assoc-type.rs:5:16 | LL | fn bar(x: &dyn Foo) {} | ^^^ `Foo` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-unsafe-missing-assoc-type.rs:2:10 + --> $DIR/missing-assoc-type.rs:2:10 | LL | trait Foo { | --- this trait cannot be made into an object... @@ -30,13 +30,13 @@ LL | type Bar; = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/object-unsafe-missing-assoc-type.rs:5:16 + --> $DIR/missing-assoc-type.rs:5:16 | LL | fn bar(x: &dyn Foo) {} | ^^^ `Foo` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-unsafe-missing-assoc-type.rs:2:10 + --> $DIR/missing-assoc-type.rs:2:10 | LL | trait Foo { | --- this trait cannot be made into an object... @@ -46,13 +46,13 @@ LL | type Bar; = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/object-unsafe-missing-assoc-type.rs:5:12 + --> $DIR/missing-assoc-type.rs:5:12 | LL | fn bar(x: &dyn Foo) {} | ^^^^^^^ `Foo` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-unsafe-missing-assoc-type.rs:2:10 + --> $DIR/missing-assoc-type.rs:2:10 | LL | trait Foo { | --- this trait cannot be made into an object... diff --git a/tests/ui/object-safety/object-safety-no-static.curr.stderr b/tests/ui/dyn-compatibility/no-static.curr.stderr similarity index 92% rename from tests/ui/object-safety/object-safety-no-static.curr.stderr rename to tests/ui/dyn-compatibility/no-static.curr.stderr index 91c3d89602e..584db779855 100644 --- a/tests/ui/object-safety/object-safety-no-static.curr.stderr +++ b/tests/ui/dyn-compatibility/no-static.curr.stderr @@ -1,11 +1,11 @@ error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/object-safety-no-static.rs:12:22 + --> $DIR/no-static.rs:12:22 | LL | fn diverges() -> Box { | ^^^^^^^ `Foo` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-no-static.rs:9:8 + --> $DIR/no-static.rs:9:8 | LL | trait Foo { | --- this trait cannot be made into an object... @@ -22,13 +22,13 @@ LL | fn foo() where Self: Sized {} | +++++++++++++++++ error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/object-safety-no-static.rs:22:12 + --> $DIR/no-static.rs:22:12 | LL | let b: Box = Box::new(Bar); | ^^^^^^^^^^^^ `Foo` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-no-static.rs:9:8 + --> $DIR/no-static.rs:9:8 | LL | trait Foo { | --- this trait cannot be made into an object... @@ -45,13 +45,13 @@ LL | fn foo() where Self: Sized {} | +++++++++++++++++ error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/object-safety-no-static.rs:22:27 + --> $DIR/no-static.rs:22:27 | LL | let b: Box = Box::new(Bar); | ^^^^^^^^^^^^^ `Foo` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-no-static.rs:9:8 + --> $DIR/no-static.rs:9:8 | LL | trait Foo { | --- this trait cannot be made into an object... diff --git a/tests/ui/object-safety/object-safety-no-static.dyn_compatible_for_dispatch.stderr b/tests/ui/dyn-compatibility/no-static.dyn_compatible_for_dispatch.stderr similarity index 93% rename from tests/ui/object-safety/object-safety-no-static.dyn_compatible_for_dispatch.stderr rename to tests/ui/dyn-compatibility/no-static.dyn_compatible_for_dispatch.stderr index 52f6865b6f3..f2deb3b8d84 100644 --- a/tests/ui/object-safety/object-safety-no-static.dyn_compatible_for_dispatch.stderr +++ b/tests/ui/dyn-compatibility/no-static.dyn_compatible_for_dispatch.stderr @@ -1,11 +1,11 @@ error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/object-safety-no-static.rs:22:27 + --> $DIR/no-static.rs:22:27 | LL | let b: Box = Box::new(Bar); | ^^^^^^^^^^^^^ `Foo` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-no-static.rs:9:8 + --> $DIR/no-static.rs:9:8 | LL | trait Foo { | --- this trait cannot be made into an object... diff --git a/tests/ui/object-safety/object-safety-no-static.rs b/tests/ui/dyn-compatibility/no-static.rs similarity index 100% rename from tests/ui/object-safety/object-safety-no-static.rs rename to tests/ui/dyn-compatibility/no-static.rs diff --git a/tests/ui/object-safety/object-safety-phantom-fn.rs b/tests/ui/dyn-compatibility/phantom-fn.rs similarity index 92% rename from tests/ui/object-safety/object-safety-phantom-fn.rs rename to tests/ui/dyn-compatibility/phantom-fn.rs index 1019c24859f..9e410da82ee 100644 --- a/tests/ui/object-safety/object-safety-phantom-fn.rs +++ b/tests/ui/dyn-compatibility/phantom-fn.rs @@ -1,4 +1,4 @@ -// Check that `Self` appearing in a phantom fn does not make a trait not object safe. +// Check that `Self` appearing in a phantom fn does not make a trait dyn-incompatible. //@ build-pass (FIXME(62277): could be check-pass?) #![allow(dead_code)] diff --git a/tests/ui/object-safety/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs b/tests/ui/dyn-compatibility/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs similarity index 100% rename from tests/ui/object-safety/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs rename to tests/ui/dyn-compatibility/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs diff --git a/tests/ui/object-safety/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.stderr b/tests/ui/dyn-compatibility/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.stderr similarity index 100% rename from tests/ui/object-safety/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.stderr rename to tests/ui/dyn-compatibility/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.stderr diff --git a/tests/ui/object-safety/object-safety-sized-2.curr.stderr b/tests/ui/dyn-compatibility/sized-2.curr.stderr similarity index 88% rename from tests/ui/object-safety/object-safety-sized-2.curr.stderr rename to tests/ui/dyn-compatibility/sized-2.curr.stderr index 4ce7ac5704e..1017fde53d3 100644 --- a/tests/ui/object-safety/object-safety-sized-2.curr.stderr +++ b/tests/ui/dyn-compatibility/sized-2.curr.stderr @@ -1,11 +1,11 @@ error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-sized-2.rs:14:31 + --> $DIR/sized-2.rs:14:31 | LL | fn make_bar(t: &T) -> &dyn Bar { | ^^^^^^^ `Bar` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-sized-2.rs:9:18 + --> $DIR/sized-2.rs:9:18 | LL | trait Bar | --- this trait cannot be made into an object... @@ -13,13 +13,13 @@ LL | where Self : Sized | ^^^^^ ...because it requires `Self: Sized` error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-sized-2.rs:16:5 + --> $DIR/sized-2.rs:16:5 | LL | t | ^ `Bar` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-sized-2.rs:9:18 + --> $DIR/sized-2.rs:9:18 | LL | trait Bar | --- this trait cannot be made into an object... diff --git a/tests/ui/object-safety/object-safety-sized-2.dyn_compatible_for_dispatch.stderr b/tests/ui/dyn-compatibility/sized-2.dyn_compatible_for_dispatch.stderr similarity index 89% rename from tests/ui/object-safety/object-safety-sized-2.dyn_compatible_for_dispatch.stderr rename to tests/ui/dyn-compatibility/sized-2.dyn_compatible_for_dispatch.stderr index 99066c104b7..534cf0f1b03 100644 --- a/tests/ui/object-safety/object-safety-sized-2.dyn_compatible_for_dispatch.stderr +++ b/tests/ui/dyn-compatibility/sized-2.dyn_compatible_for_dispatch.stderr @@ -1,11 +1,11 @@ error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-sized-2.rs:16:5 + --> $DIR/sized-2.rs:16:5 | LL | t | ^ `Bar` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-sized-2.rs:9:18 + --> $DIR/sized-2.rs:9:18 | LL | trait Bar | --- this trait cannot be made into an object... diff --git a/tests/ui/object-safety/object-safety-sized-2.rs b/tests/ui/dyn-compatibility/sized-2.rs similarity index 100% rename from tests/ui/object-safety/object-safety-sized-2.rs rename to tests/ui/dyn-compatibility/sized-2.rs diff --git a/tests/ui/object-safety/object-safety-sized.curr.stderr b/tests/ui/dyn-compatibility/sized.curr.stderr similarity index 88% rename from tests/ui/object-safety/object-safety-sized.curr.stderr rename to tests/ui/dyn-compatibility/sized.curr.stderr index b61f968d902..613833aad12 100644 --- a/tests/ui/object-safety/object-safety-sized.curr.stderr +++ b/tests/ui/dyn-compatibility/sized.curr.stderr @@ -1,11 +1,11 @@ error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-sized.rs:12:32 + --> $DIR/sized.rs:12:32 | LL | fn make_bar(t: &T) -> &dyn Bar { | ^^^^^^^ `Bar` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-sized.rs:8:12 + --> $DIR/sized.rs:8:12 | LL | trait Bar: Sized { | --- ^^^^^ ...because it requires `Self: Sized` @@ -13,13 +13,13 @@ LL | trait Bar: Sized { | this trait cannot be made into an object... error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-sized.rs:14:5 + --> $DIR/sized.rs:14:5 | LL | t | ^ `Bar` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-sized.rs:8:12 + --> $DIR/sized.rs:8:12 | LL | trait Bar: Sized { | --- ^^^^^ ...because it requires `Self: Sized` diff --git a/tests/ui/object-safety/object-safety-sized.dyn_compatible_for_dispatch.stderr b/tests/ui/dyn-compatibility/sized.dyn_compatible_for_dispatch.stderr similarity index 89% rename from tests/ui/object-safety/object-safety-sized.dyn_compatible_for_dispatch.stderr rename to tests/ui/dyn-compatibility/sized.dyn_compatible_for_dispatch.stderr index 5ce713375a4..cf847bc1577 100644 --- a/tests/ui/object-safety/object-safety-sized.dyn_compatible_for_dispatch.stderr +++ b/tests/ui/dyn-compatibility/sized.dyn_compatible_for_dispatch.stderr @@ -1,11 +1,11 @@ error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-sized.rs:14:5 + --> $DIR/sized.rs:14:5 | LL | t | ^ `Bar` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-sized.rs:8:12 + --> $DIR/sized.rs:8:12 | LL | trait Bar: Sized { | --- ^^^^^ ...because it requires `Self: Sized` diff --git a/tests/ui/object-safety/object-safety-sized.rs b/tests/ui/dyn-compatibility/sized.rs similarity index 100% rename from tests/ui/object-safety/object-safety-sized.rs rename to tests/ui/dyn-compatibility/sized.rs diff --git a/tests/ui/object-safety/object-safety-supertrait-mentions-GAT.rs b/tests/ui/dyn-compatibility/supertrait-mentions-GAT.rs similarity index 100% rename from tests/ui/object-safety/object-safety-supertrait-mentions-GAT.rs rename to tests/ui/dyn-compatibility/supertrait-mentions-GAT.rs diff --git a/tests/ui/object-safety/object-safety-supertrait-mentions-GAT.stderr b/tests/ui/dyn-compatibility/supertrait-mentions-GAT.stderr similarity index 86% rename from tests/ui/object-safety/object-safety-supertrait-mentions-GAT.stderr rename to tests/ui/dyn-compatibility/supertrait-mentions-GAT.stderr index 4d44627e779..ac5a5b28d94 100644 --- a/tests/ui/object-safety/object-safety-supertrait-mentions-GAT.stderr +++ b/tests/ui/dyn-compatibility/supertrait-mentions-GAT.stderr @@ -1,14 +1,14 @@ error[E0311]: the parameter type `Self` may not live long enough | note: ...that is required by this bound - --> $DIR/object-safety-supertrait-mentions-GAT.rs:6:15 + --> $DIR/supertrait-mentions-GAT.rs:6:15 | LL | Self: 'a; | ^^ = help: consider adding an explicit lifetime bound `Self: 'a`... error: associated item referring to unboxed trait object for its own trait - --> $DIR/object-safety-supertrait-mentions-GAT.rs:10:20 + --> $DIR/supertrait-mentions-GAT.rs:10:20 | LL | trait SuperTrait: for<'a> GatTrait = T> { | ---------- in this trait @@ -21,13 +21,13 @@ LL | fn c(&self) -> Self; | ~~~~ error[E0038]: the trait `SuperTrait` cannot be made into an object - --> $DIR/object-safety-supertrait-mentions-GAT.rs:10:20 + --> $DIR/supertrait-mentions-GAT.rs:10:20 | LL | fn c(&self) -> dyn SuperTrait; | ^^^^^^^^^^^^^^^^^ `SuperTrait` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-supertrait-mentions-GAT.rs:4:10 + --> $DIR/supertrait-mentions-GAT.rs:4:10 | LL | type Gat<'a> | ^^^ ...because it contains the generic associated type `Gat` diff --git a/tests/ui/object-safety/object-safety-supertrait-mentions-Self.rs b/tests/ui/dyn-compatibility/supertrait-mentions-Self.rs similarity index 100% rename from tests/ui/object-safety/object-safety-supertrait-mentions-Self.rs rename to tests/ui/dyn-compatibility/supertrait-mentions-Self.rs diff --git a/tests/ui/object-safety/object-safety-supertrait-mentions-Self.stderr b/tests/ui/dyn-compatibility/supertrait-mentions-Self.stderr similarity index 86% rename from tests/ui/object-safety/object-safety-supertrait-mentions-Self.stderr rename to tests/ui/dyn-compatibility/supertrait-mentions-Self.stderr index b1a70fb859d..6474b115c46 100644 --- a/tests/ui/object-safety/object-safety-supertrait-mentions-Self.stderr +++ b/tests/ui/dyn-compatibility/supertrait-mentions-Self.stderr @@ -1,11 +1,11 @@ error[E0277]: the size for values of type `Self` cannot be known at compilation time - --> $DIR/object-safety-supertrait-mentions-Self.rs:8:13 + --> $DIR/supertrait-mentions-Self.rs:8:13 | LL | trait Baz : Bar { | ^^^^^^^^^ doesn't have a size known at compile-time | note: required by an implicit `Sized` bound in `Bar` - --> $DIR/object-safety-supertrait-mentions-Self.rs:4:11 + --> $DIR/supertrait-mentions-Self.rs:4:11 | LL | trait Bar { | ^ required by the implicit `Sized` requirement on this type parameter in `Bar` @@ -19,13 +19,13 @@ LL | trait Bar { | ++++++++ error[E0038]: the trait `Baz` cannot be made into an object - --> $DIR/object-safety-supertrait-mentions-Self.rs:16:31 + --> $DIR/supertrait-mentions-Self.rs:16:31 | LL | fn make_baz(t: &T) -> &dyn Baz { | ^^^^^^^ `Baz` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-supertrait-mentions-Self.rs:8:13 + --> $DIR/supertrait-mentions-Self.rs:8:13 | LL | trait Baz : Bar { | --- ^^^^^^^^^ ...because it uses `Self` as a type parameter diff --git a/tests/ui/object-safety/issue-102762.rs b/tests/ui/dyn-compatibility/undispatchable-receiver-and-wc-references-Self.rs similarity index 79% rename from tests/ui/object-safety/issue-102762.rs rename to tests/ui/dyn-compatibility/undispatchable-receiver-and-wc-references-Self.rs index 576f73e08bc..5c71bd7769c 100644 --- a/tests/ui/object-safety/issue-102762.rs +++ b/tests/ui/dyn-compatibility/undispatchable-receiver-and-wc-references-Self.rs @@ -1,7 +1,8 @@ //@ compile-flags: --crate-type=lib // This test checks that the `where_clauses_object_safety` lint does not cause -// other object safety *hard errors* to be suppressed, because we currently -// only emit one object safety error per trait... +// other dyn-compatibility *hard errors* to be suppressed, because we currently +// only emit one dyn-compatibility error per trait... +// issue: rust-lang/rust#102762 use std::future::Future; use std::pin::Pin; diff --git a/tests/ui/object-safety/issue-102762.stderr b/tests/ui/dyn-compatibility/undispatchable-receiver-and-wc-references-Self.stderr similarity index 87% rename from tests/ui/object-safety/issue-102762.stderr rename to tests/ui/dyn-compatibility/undispatchable-receiver-and-wc-references-Self.stderr index 05451eb8399..8d62ac9d923 100644 --- a/tests/ui/object-safety/issue-102762.stderr +++ b/tests/ui/dyn-compatibility/undispatchable-receiver-and-wc-references-Self.stderr @@ -1,5 +1,5 @@ error[E0038]: the trait `Fetcher` cannot be made into an object - --> $DIR/issue-102762.rs:18:21 + --> $DIR/undispatchable-receiver-and-wc-references-Self.rs:19:21 | LL | fn get<'a>(self: &'a Box) -> Pin> + 'a>> | ------------- help: consider changing method `get`'s `self` parameter to be `&self`: `&Self` @@ -8,7 +8,7 @@ LL | fn fetcher() -> Box { | ^^^^^^^^^^^ `Fetcher` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/issue-102762.rs:10:22 + --> $DIR/undispatchable-receiver-and-wc-references-Self.rs:11:22 | LL | pub trait Fetcher: Send + Sync { | ------- this trait cannot be made into an object... @@ -16,7 +16,7 @@ LL | fn get<'a>(self: &'a Box) -> Pin> | ^^^^^^^^^^^^^ ...because method `get`'s `self` parameter cannot be dispatched on error[E0038]: the trait `Fetcher` cannot be made into an object - --> $DIR/issue-102762.rs:24:19 + --> $DIR/undispatchable-receiver-and-wc-references-Self.rs:25:19 | LL | fn get<'a>(self: &'a Box) -> Pin> + 'a>> | ------------- help: consider changing method `get`'s `self` parameter to be `&self`: `&Self` @@ -25,7 +25,7 @@ LL | let fetcher = fetcher(); | ^^^^^^^^^ `Fetcher` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/issue-102762.rs:10:22 + --> $DIR/undispatchable-receiver-and-wc-references-Self.rs:11:22 | LL | pub trait Fetcher: Send + Sync { | ------- this trait cannot be made into an object... @@ -33,7 +33,7 @@ LL | fn get<'a>(self: &'a Box) -> Pin> | ^^^^^^^^^^^^^ ...because method `get`'s `self` parameter cannot be dispatched on error[E0038]: the trait `Fetcher` cannot be made into an object - --> $DIR/issue-102762.rs:26:13 + --> $DIR/undispatchable-receiver-and-wc-references-Self.rs:27:13 | LL | fn get<'a>(self: &'a Box) -> Pin> + 'a>> | ------------- help: consider changing method `get`'s `self` parameter to be `&self`: `&Self` @@ -42,7 +42,7 @@ LL | let _ = fetcher.get(); | ^^^^^^^^^^^^^ `Fetcher` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/issue-102762.rs:10:22 + --> $DIR/undispatchable-receiver-and-wc-references-Self.rs:11:22 | LL | pub trait Fetcher: Send + Sync { | ------- this trait cannot be made into an object... diff --git a/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.rs b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.rs index 23857cbaca8..3c9e903d4ba 100644 --- a/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.rs +++ b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.rs @@ -1,4 +1,4 @@ -// Check that a self parameter type requires a DispatchFromDyn impl to be object safe +// Check that a self parameter type requires a DispatchFromDyn impl to be dyn-compatible. #![feature(arbitrary_self_types, unsize, coerce_unsized)] diff --git a/tests/ui/feature-gates/feature-gate-dyn_compatible_for_dispatch.rs b/tests/ui/feature-gates/feature-gate-dyn_compatible_for_dispatch.rs index 2dbba370a51..e38ab66dbe5 100644 --- a/tests/ui/feature-gates/feature-gate-dyn_compatible_for_dispatch.rs +++ b/tests/ui/feature-gates/feature-gate-dyn_compatible_for_dispatch.rs @@ -15,20 +15,20 @@ trait DynIncompatible4 { fn foo(&self, s: &Self); } -fn takes_non_object_safe_ref(obj: &dyn DynIncompatible1) { +fn takes_dyn_incompatible_ref(obj: &dyn DynIncompatible1) { //~^ ERROR E0038 } -fn return_non_object_safe_ref() -> &'static dyn DynIncompatible2 { +fn return_dyn_incompatible_ref() -> &'static dyn DynIncompatible2 { //~^ ERROR E0038 loop {} } -fn takes_non_object_safe_box(obj: Box) { +fn takes_dyn_incompatible_box(obj: Box) { //~^ ERROR E0038 } -fn return_non_object_safe_rc() -> std::rc::Rc { +fn return_dyn_incompatible_rc() -> std::rc::Rc { //~^ ERROR E0038 loop {} } diff --git a/tests/ui/feature-gates/feature-gate-dyn_compatible_for_dispatch.stderr b/tests/ui/feature-gates/feature-gate-dyn_compatible_for_dispatch.stderr index 3cb73dfd52c..ed021c154a5 100644 --- a/tests/ui/feature-gates/feature-gate-dyn_compatible_for_dispatch.stderr +++ b/tests/ui/feature-gates/feature-gate-dyn_compatible_for_dispatch.stderr @@ -1,8 +1,8 @@ error[E0038]: the trait `DynIncompatible1` cannot be made into an object - --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:18:39 + --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:18:40 | -LL | fn takes_non_object_safe_ref(obj: &dyn DynIncompatible1) { - | ^^^^^^^^^^^^^^^^^^^^ `DynIncompatible1` cannot be made into an object +LL | fn takes_dyn_incompatible_ref(obj: &dyn DynIncompatible1) { + | ^^^^^^^^^^^^^^^^^^^^ `DynIncompatible1` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:4:25 @@ -13,10 +13,10 @@ LL | trait DynIncompatible1: Sized {} | this trait cannot be made into an object... error[E0038]: the trait `DynIncompatible2` cannot be made into an object - --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:22:45 + --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:22:46 | -LL | fn return_non_object_safe_ref() -> &'static dyn DynIncompatible2 { - | ^^^^^^^^^^^^^^^^^^^^ `DynIncompatible2` cannot be made into an object +LL | fn return_dyn_incompatible_ref() -> &'static dyn DynIncompatible2 { + | ^^^^^^^^^^^^^^^^^^^^ `DynIncompatible2` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:7:8 @@ -35,10 +35,10 @@ LL | fn static_fn() where Self: Sized {} | +++++++++++++++++ error[E0038]: the trait `DynIncompatible3` cannot be made into an object - --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:27:39 + --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:27:40 | -LL | fn takes_non_object_safe_box(obj: Box) { - | ^^^^^^^^^^^^^^^^^^^^ `DynIncompatible3` cannot be made into an object +LL | fn takes_dyn_incompatible_box(obj: Box) { + | ^^^^^^^^^^^^^^^^^^^^ `DynIncompatible3` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:11:8 @@ -50,10 +50,10 @@ LL | fn foo(&self); = help: consider moving `foo` to another trait error[E0038]: the trait `DynIncompatible4` cannot be made into an object - --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:31:47 + --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:31:48 | -LL | fn return_non_object_safe_rc() -> std::rc::Rc { - | ^^^^^^^^^^^^^^^^^^^^ `DynIncompatible4` cannot be made into an object +LL | fn return_dyn_incompatible_rc() -> std::rc::Rc { + | ^^^^^^^^^^^^^^^^^^^^ `DynIncompatible4` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:15:22 diff --git a/tests/ui/generic-associated-types/trait-objects.rs b/tests/ui/generic-associated-types/trait-objects.rs index 277ffcc1f0d..743a3df0acc 100644 --- a/tests/ui/generic-associated-types/trait-objects.rs +++ b/tests/ui/generic-associated-types/trait-objects.rs @@ -6,7 +6,7 @@ trait StreamingIterator { type Item<'a> where Self: 'a; fn size_hint(&self) -> (usize, Option); - // Uncommenting makes `StreamingIterator` not object safe + // Uncommenting makes `StreamingIterator` dyn-incompatible. // fn next(&mut self) -> Self::Item<'_>; } diff --git a/tests/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.rs b/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.rs similarity index 59% rename from tests/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.rs rename to tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.rs index 068f7d3eea6..76dbb05f53d 100644 --- a/tests/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.rs +++ b/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.rs @@ -1,24 +1,25 @@ #![allow(bare_trait_objects)] -trait NotObjectSafe { + +trait DynIncompatible { fn foo() -> Self; } struct A; struct B; -impl NotObjectSafe for A { +impl DynIncompatible for A { fn foo() -> Self { A } } -impl NotObjectSafe for B { +impl DynIncompatible for B { fn foo() -> Self { B } } -fn car() -> dyn NotObjectSafe { //~ ERROR the trait `NotObjectSafe` cannot be made into an object +fn car() -> dyn DynIncompatible { //~ ERROR the trait `DynIncompatible` cannot be made into an object //~^ ERROR return type cannot have an unboxed trait object if true { return A; @@ -26,7 +27,7 @@ fn car() -> dyn NotObjectSafe { //~ ERROR the trait `NotObjectSafe` cannot be ma B } -fn cat() -> Box { //~ ERROR the trait `NotObjectSafe` cannot be made into an +fn cat() -> Box { //~ ERROR the trait `DynIncompatible` cannot be made into an if true { return Box::new(A); //~ ERROR cannot be made into an object } diff --git a/tests/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.stderr b/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.stderr similarity index 62% rename from tests/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.stderr rename to tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.stderr index 2a36824e292..576bd909cbc 100644 --- a/tests/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.stderr +++ b/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.stderr @@ -1,17 +1,17 @@ -error[E0038]: the trait `NotObjectSafe` cannot be made into an object - --> $DIR/object-unsafe-trait-in-return-position-dyn-trait.rs:21:13 +error[E0038]: the trait `DynIncompatible` cannot be made into an object + --> $DIR/dyn-incompatible-trait-in-return-position-dyn-trait.rs:22:13 | -LL | fn car() -> dyn NotObjectSafe { - | ^^^^^^^^^^^^^^^^^ `NotObjectSafe` cannot be made into an object +LL | fn car() -> dyn DynIncompatible { + | ^^^^^^^^^^^^^^^^^^^ `DynIncompatible` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-unsafe-trait-in-return-position-dyn-trait.rs:3:8 + --> $DIR/dyn-incompatible-trait-in-return-position-dyn-trait.rs:4:8 | -LL | trait NotObjectSafe { - | ------------- this trait cannot be made into an object... +LL | trait DynIncompatible { + | --------------- this trait cannot be made into an object... LL | fn foo() -> Self; | ^^^ ...because associated function `foo` has no `self` parameter - = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `NotObjectSafe` for this new enum and using it instead: + = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `DynIncompatible` for this new enum and using it instead: A B help: consider turning `foo` into a method by giving it a `&self` argument @@ -23,20 +23,20 @@ help: alternatively, consider constraining `foo` so it does not apply to trait o LL | fn foo() -> Self where Self: Sized; | +++++++++++++++++ -error[E0038]: the trait `NotObjectSafe` cannot be made into an object - --> $DIR/object-unsafe-trait-in-return-position-dyn-trait.rs:29:17 +error[E0038]: the trait `DynIncompatible` cannot be made into an object + --> $DIR/dyn-incompatible-trait-in-return-position-dyn-trait.rs:30:17 | -LL | fn cat() -> Box { - | ^^^^^^^^^^^^^^^^^ `NotObjectSafe` cannot be made into an object +LL | fn cat() -> Box { + | ^^^^^^^^^^^^^^^^^^^ `DynIncompatible` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-unsafe-trait-in-return-position-dyn-trait.rs:3:8 + --> $DIR/dyn-incompatible-trait-in-return-position-dyn-trait.rs:4:8 | -LL | trait NotObjectSafe { - | ------------- this trait cannot be made into an object... +LL | trait DynIncompatible { + | --------------- this trait cannot be made into an object... LL | fn foo() -> Self; | ^^^ ...because associated function `foo` has no `self` parameter - = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `NotObjectSafe` for this new enum and using it instead: + = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `DynIncompatible` for this new enum and using it instead: A B help: consider turning `foo` into a method by giving it a `&self` argument @@ -49,15 +49,15 @@ LL | fn foo() -> Self where Self: Sized; | +++++++++++++++++ error[E0746]: return type cannot have an unboxed trait object - --> $DIR/object-unsafe-trait-in-return-position-dyn-trait.rs:21:13 + --> $DIR/dyn-incompatible-trait-in-return-position-dyn-trait.rs:22:13 | -LL | fn car() -> dyn NotObjectSafe { - | ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time +LL | fn car() -> dyn DynIncompatible { + | ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: if there were a single returned type, you could use `impl Trait` instead help: box the return type, and wrap all of the returned values in `Box::new` | -LL ~ fn car() -> Box { +LL ~ fn car() -> Box { LL | LL | if true { LL ~ return Box::new(A); @@ -65,23 +65,23 @@ LL | } LL ~ Box::new(B) | -error[E0038]: the trait `NotObjectSafe` cannot be made into an object - --> $DIR/object-unsafe-trait-in-return-position-dyn-trait.rs:31:16 +error[E0038]: the trait `DynIncompatible` cannot be made into an object + --> $DIR/dyn-incompatible-trait-in-return-position-dyn-trait.rs:32:16 | LL | return Box::new(A); - | ^^^^^^^^^^^ `NotObjectSafe` cannot be made into an object + | ^^^^^^^^^^^ `DynIncompatible` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-unsafe-trait-in-return-position-dyn-trait.rs:3:8 + --> $DIR/dyn-incompatible-trait-in-return-position-dyn-trait.rs:4:8 | -LL | trait NotObjectSafe { - | ------------- this trait cannot be made into an object... +LL | trait DynIncompatible { + | --------------- this trait cannot be made into an object... LL | fn foo() -> Self; | ^^^ ...because associated function `foo` has no `self` parameter - = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `NotObjectSafe` for this new enum and using it instead: + = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `DynIncompatible` for this new enum and using it instead: A B - = note: required for the cast from `Box` to `Box<(dyn NotObjectSafe + 'static)>` + = note: required for the cast from `Box` to `Box<(dyn DynIncompatible + 'static)>` help: consider turning `foo` into a method by giving it a `&self` argument | LL | fn foo(&self) -> Self; @@ -91,23 +91,23 @@ help: alternatively, consider constraining `foo` so it does not apply to trait o LL | fn foo() -> Self where Self: Sized; | +++++++++++++++++ -error[E0038]: the trait `NotObjectSafe` cannot be made into an object - --> $DIR/object-unsafe-trait-in-return-position-dyn-trait.rs:33:5 +error[E0038]: the trait `DynIncompatible` cannot be made into an object + --> $DIR/dyn-incompatible-trait-in-return-position-dyn-trait.rs:34:5 | LL | Box::new(B) - | ^^^^^^^^^^^ `NotObjectSafe` cannot be made into an object + | ^^^^^^^^^^^ `DynIncompatible` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-unsafe-trait-in-return-position-dyn-trait.rs:3:8 + --> $DIR/dyn-incompatible-trait-in-return-position-dyn-trait.rs:4:8 | -LL | trait NotObjectSafe { - | ------------- this trait cannot be made into an object... +LL | trait DynIncompatible { + | --------------- this trait cannot be made into an object... LL | fn foo() -> Self; | ^^^ ...because associated function `foo` has no `self` parameter - = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `NotObjectSafe` for this new enum and using it instead: + = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `DynIncompatible` for this new enum and using it instead: A B - = note: required for the cast from `Box` to `Box<(dyn NotObjectSafe + 'static)>` + = note: required for the cast from `Box` to `Box<(dyn DynIncompatible + 'static)>` help: consider turning `foo` into a method by giving it a `&self` argument | LL | fn foo(&self) -> Self; diff --git a/tests/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.rs b/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-impl-trait.rs similarity index 61% rename from tests/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.rs rename to tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-impl-trait.rs index 503515013b9..25a901e4ff3 100644 --- a/tests/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.rs +++ b/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-impl-trait.rs @@ -1,42 +1,42 @@ -trait NotObjectSafe { +trait DynIncompatible { fn foo() -> Self; } -trait ObjectSafe { +trait DynCompatible { fn bar(&self); } struct A; struct B; -impl NotObjectSafe for A { +impl DynIncompatible for A { fn foo() -> Self { A } } -impl NotObjectSafe for B { +impl DynIncompatible for B { fn foo() -> Self { B } } -impl ObjectSafe for A { +impl DynCompatible for A { fn bar(&self) {} } -impl ObjectSafe for B { +impl DynCompatible for B { fn bar(&self) {} } -fn can() -> impl NotObjectSafe { +fn can() -> impl DynIncompatible { if true { return A; } B //~ ERROR mismatched types } -fn cat() -> impl ObjectSafe { +fn cat() -> impl DynCompatible { if true { return A; } diff --git a/tests/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.stderr b/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-impl-trait.stderr similarity index 54% rename from tests/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.stderr rename to tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-impl-trait.stderr index e5147bcea16..6a485881bfc 100644 --- a/tests/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.stderr +++ b/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-impl-trait.stderr @@ -1,17 +1,17 @@ error[E0308]: mismatched types - --> $DIR/object-unsafe-trait-in-return-position-impl-trait.rs:36:5 + --> $DIR/dyn-incompatible-trait-in-return-position-impl-trait.rs:36:5 | -LL | fn can() -> impl NotObjectSafe { - | ------------------ expected `A` because of return type +LL | fn can() -> impl DynIncompatible { + | -------------------- expected `A` because of return type ... LL | B | ^ expected `A`, found `B` error[E0308]: mismatched types - --> $DIR/object-unsafe-trait-in-return-position-impl-trait.rs:43:5 + --> $DIR/dyn-incompatible-trait-in-return-position-impl-trait.rs:43:5 | -LL | fn cat() -> impl ObjectSafe { - | --------------- expected `A` because of return type +LL | fn cat() -> impl DynCompatible { + | ------------------ expected `A` because of return type ... LL | B | ^ expected `A`, found `B` diff --git a/tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-object-safety.rs b/tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-dyn-compatibility-check.rs similarity index 100% rename from tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-object-safety.rs rename to tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-dyn-compatibility-check.rs diff --git a/tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-object-safety.stderr b/tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-dyn-compatibility-check.stderr similarity index 82% rename from tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-object-safety.stderr rename to tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-dyn-compatibility-check.stderr index af624e2a758..a975b6204aa 100644 --- a/tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-object-safety.stderr +++ b/tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-dyn-compatibility-check.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `&dyn MyTrait: MyTrait` is not satisfied - --> $DIR/cycle-effective-visibilities-during-object-safety.rs:20:22 + --> $DIR/cycle-effective-visibilities-during-dyn-compatibility-check.rs:20:22 | LL | MyTrait::foo(&self) | ------------ ^^^^^ the trait `MyTrait` is not implemented for `&dyn MyTrait` @@ -9,13 +9,13 @@ LL | MyTrait::foo(&self) = help: the trait `MyTrait` is implemented for `Outer` error[E0038]: the trait `MyTrait` cannot be made into an object - --> $DIR/cycle-effective-visibilities-during-object-safety.rs:20:9 + --> $DIR/cycle-effective-visibilities-during-dyn-compatibility-check.rs:20:9 | LL | MyTrait::foo(&self) | ^^^^^^^^^^^^ `MyTrait` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/cycle-effective-visibilities-during-object-safety.rs:5:22 + --> $DIR/cycle-effective-visibilities-during-dyn-compatibility-check.rs:5:22 | LL | trait MyTrait { | ------- this trait cannot be made into an object... @@ -25,7 +25,7 @@ LL | fn foo(&self) -> impl Marker; = help: only type `Outer` implements the trait, consider using it directly instead error[E0277]: the trait bound `&dyn MyTrait: MyTrait` is not satisfied - --> $DIR/cycle-effective-visibilities-during-object-safety.rs:20:9 + --> $DIR/cycle-effective-visibilities-during-dyn-compatibility-check.rs:20:9 | LL | MyTrait::foo(&self) | ^^^^^^^^^^^^^^^^^^^ the trait `MyTrait` is not implemented for `&dyn MyTrait` @@ -33,13 +33,13 @@ LL | MyTrait::foo(&self) = help: the trait `MyTrait` is implemented for `Outer` error[E0038]: the trait `MyTrait` cannot be made into an object - --> $DIR/cycle-effective-visibilities-during-object-safety.rs:16:6 + --> $DIR/cycle-effective-visibilities-during-dyn-compatibility-check.rs:16:6 | LL | impl dyn MyTrait { | ^^^^^^^^^^^ `MyTrait` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/cycle-effective-visibilities-during-object-safety.rs:5:22 + --> $DIR/cycle-effective-visibilities-during-dyn-compatibility-check.rs:5:22 | LL | trait MyTrait { | ------- this trait cannot be made into an object... @@ -49,13 +49,13 @@ LL | fn foo(&self) -> impl Marker; = help: only type `Outer` implements the trait, consider using it directly instead error[E0038]: the trait `MyTrait` cannot be made into an object - --> $DIR/cycle-effective-visibilities-during-object-safety.rs:18:15 + --> $DIR/cycle-effective-visibilities-during-dyn-compatibility-check.rs:18:15 | LL | fn other(&self) -> impl Marker { | ^^^^ `MyTrait` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/cycle-effective-visibilities-during-object-safety.rs:5:22 + --> $DIR/cycle-effective-visibilities-during-dyn-compatibility-check.rs:5:22 | LL | trait MyTrait { | ------- this trait cannot be made into an object... diff --git a/tests/ui/impl-trait/in-trait/object-safety-sized.rs b/tests/ui/impl-trait/in-trait/dyn-compatibility-sized.rs similarity index 100% rename from tests/ui/impl-trait/in-trait/object-safety-sized.rs rename to tests/ui/impl-trait/in-trait/dyn-compatibility-sized.rs diff --git a/tests/ui/impl-trait/in-trait/object-safety.rs b/tests/ui/impl-trait/in-trait/dyn-compatibility.rs similarity index 100% rename from tests/ui/impl-trait/in-trait/object-safety.rs rename to tests/ui/impl-trait/in-trait/dyn-compatibility.rs diff --git a/tests/ui/impl-trait/in-trait/object-safety.stderr b/tests/ui/impl-trait/in-trait/dyn-compatibility.stderr similarity index 91% rename from tests/ui/impl-trait/in-trait/object-safety.stderr rename to tests/ui/impl-trait/in-trait/dyn-compatibility.stderr index e2f23bca621..115cb014b8c 100644 --- a/tests/ui/impl-trait/in-trait/object-safety.stderr +++ b/tests/ui/impl-trait/in-trait/dyn-compatibility.stderr @@ -1,11 +1,11 @@ error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/object-safety.rs:14:33 + --> $DIR/dyn-compatibility.rs:14:33 | LL | let i = Box::new(42_u32) as Box; | ^^^^^^^^^^^^ `Foo` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety.rs:4:22 + --> $DIR/dyn-compatibility.rs:4:22 | LL | trait Foo { | --- this trait cannot be made into an object... @@ -15,13 +15,13 @@ LL | fn baz(&self) -> impl Debug; = help: only type `u32` implements the trait, consider using it directly instead error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/object-safety.rs:17:15 + --> $DIR/dyn-compatibility.rs:17:15 | LL | let s = i.baz(); | ^^^ `Foo` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety.rs:4:22 + --> $DIR/dyn-compatibility.rs:4:22 | LL | trait Foo { | --- this trait cannot be made into an object... @@ -31,13 +31,13 @@ LL | fn baz(&self) -> impl Debug; = help: only type `u32` implements the trait, consider using it directly instead error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/object-safety.rs:17:13 + --> $DIR/dyn-compatibility.rs:17:13 | LL | let s = i.baz(); | ^^^^^^^ `Foo` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety.rs:4:22 + --> $DIR/dyn-compatibility.rs:4:22 | LL | trait Foo { | --- this trait cannot be made into an object... @@ -47,13 +47,13 @@ LL | fn baz(&self) -> impl Debug; = help: only type `u32` implements the trait, consider using it directly instead error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/object-safety.rs:14:13 + --> $DIR/dyn-compatibility.rs:14:13 | LL | let i = Box::new(42_u32) as Box; | ^^^^^^^^^^^^^^^^ `Foo` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety.rs:4:22 + --> $DIR/dyn-compatibility.rs:4:22 | LL | trait Foo { | --- this trait cannot be made into an object... diff --git a/tests/ui/issues/issue-58734.rs b/tests/ui/issues/issue-58734.rs index c838fde5d73..9b630666baf 100644 --- a/tests/ui/issues/issue-58734.rs +++ b/tests/ui/issues/issue-58734.rs @@ -1,22 +1,22 @@ trait Trait { fn exists(self) -> (); - fn not_object_safe() -> Self; + fn dyn_incompatible() -> Self; } impl Trait for () { fn exists(self) -> () { } - fn not_object_safe() -> Self { + fn dyn_incompatible() -> Self { () } } fn main() { - // object-safe or not, this call is OK + // dyn-compatible or not, this call is OK Trait::exists(()); - // no object safety error + // no dyn-compatibility error Trait::nonexistent(()); //~^ ERROR no function or associated item named `nonexistent` found //~| WARN trait objects without an explicit `dyn` are deprecated diff --git a/tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/downcast-unsafe-trait-objects.rs b/tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/downcast-unsafe-trait-objects.rs index e9206789756..b1b2dcf3eb9 100644 --- a/tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/downcast-unsafe-trait-objects.rs +++ b/tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/downcast-unsafe-trait-objects.rs @@ -1,4 +1,4 @@ -// Check that we if we get ahold of an object unsafe trait +// Check that we if we get ahold of a dyn-incompatible trait // object with auto traits and lifetimes, we can downcast it // //@ check-pass diff --git a/tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/manual-self-impl-for-unsafe-obj.rs b/tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/manual-self-impl-for-unsafe-obj.rs index 37e6f948ad1..425dc130d45 100644 --- a/tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/manual-self-impl-for-unsafe-obj.rs +++ b/tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/manual-self-impl-for-unsafe-obj.rs @@ -1,4 +1,4 @@ -// Check that we can manually implement an object-unsafe trait for its trait object. +// Check that we can manually implement a dyn-incompatible trait for its trait object. //@ revisions: current next //@ ignore-compare-mode-next-solver (explicit revisions) diff --git a/tests/ui/sanitizer/cfi/async-closures.rs b/tests/ui/sanitizer/cfi/async-closures.rs index d94f2992d84..4eaa44cfa3f 100644 --- a/tests/ui/sanitizer/cfi/async-closures.rs +++ b/tests/ui/sanitizer/cfi/async-closures.rs @@ -21,7 +21,7 @@ use std::ops::AsyncFn; #[inline(never)] fn identity(x: T) -> T { x } -// We can't actually create a `dyn AsyncFn()`, because it's not object-safe, but we should check +// We can't actually create a `dyn AsyncFn()`, because it's dyn-incompatible, but we should check // that we don't bug out when we encounter one. fn main() { diff --git a/tests/ui/self/arbitrary-self-types-not-object-safe.curr.stderr b/tests/ui/self/arbitrary-self-types-dyn-incompatible.curr.stderr similarity index 89% rename from tests/ui/self/arbitrary-self-types-not-object-safe.curr.stderr rename to tests/ui/self/arbitrary-self-types-dyn-incompatible.curr.stderr index e2d73fc08f6..2eb7597d5c1 100644 --- a/tests/ui/self/arbitrary-self-types-not-object-safe.curr.stderr +++ b/tests/ui/self/arbitrary-self-types-dyn-incompatible.curr.stderr @@ -1,5 +1,5 @@ error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/arbitrary-self-types-not-object-safe.rs:33:32 + --> $DIR/arbitrary-self-types-dyn-incompatible.rs:33:32 | LL | fn foo(self: &Rc) -> usize; | --------- help: consider changing method `foo`'s `self` parameter to be `&self`: `&Self` @@ -8,7 +8,7 @@ LL | let x = Rc::new(5usize) as Rc; | ^^^^^^^^^^^ `Foo` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/arbitrary-self-types-not-object-safe.rs:8:18 + --> $DIR/arbitrary-self-types-dyn-incompatible.rs:8:18 | LL | trait Foo { | --- this trait cannot be made into an object... @@ -17,7 +17,7 @@ LL | fn foo(self: &Rc) -> usize; = help: only type `usize` implements the trait, consider using it directly instead error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/arbitrary-self-types-not-object-safe.rs:33:13 + --> $DIR/arbitrary-self-types-dyn-incompatible.rs:33:13 | LL | fn foo(self: &Rc) -> usize; | --------- help: consider changing method `foo`'s `self` parameter to be `&self`: `&Self` @@ -26,7 +26,7 @@ LL | let x = Rc::new(5usize) as Rc; | ^^^^^^^^^^^^^^^ `Foo` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/arbitrary-self-types-not-object-safe.rs:8:18 + --> $DIR/arbitrary-self-types-dyn-incompatible.rs:8:18 | LL | trait Foo { | --- this trait cannot be made into an object... diff --git a/tests/ui/self/arbitrary-self-types-not-object-safe.dyn_compatible_for_dispatch.stderr b/tests/ui/self/arbitrary-self-types-dyn-incompatible.dyn_compatible_for_dispatch.stderr similarity index 90% rename from tests/ui/self/arbitrary-self-types-not-object-safe.dyn_compatible_for_dispatch.stderr rename to tests/ui/self/arbitrary-self-types-dyn-incompatible.dyn_compatible_for_dispatch.stderr index fda07765c66..02af692c4a3 100644 --- a/tests/ui/self/arbitrary-self-types-not-object-safe.dyn_compatible_for_dispatch.stderr +++ b/tests/ui/self/arbitrary-self-types-dyn-incompatible.dyn_compatible_for_dispatch.stderr @@ -1,5 +1,5 @@ error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/arbitrary-self-types-not-object-safe.rs:33:13 + --> $DIR/arbitrary-self-types-dyn-incompatible.rs:33:13 | LL | fn foo(self: &Rc) -> usize; | --------- help: consider changing method `foo`'s `self` parameter to be `&self`: `&Self` @@ -8,7 +8,7 @@ LL | let x = Rc::new(5usize) as Rc; | ^^^^^^^^^^^^^^^ `Foo` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/arbitrary-self-types-not-object-safe.rs:8:18 + --> $DIR/arbitrary-self-types-dyn-incompatible.rs:8:18 | LL | trait Foo { | --- this trait cannot be made into an object... diff --git a/tests/ui/self/arbitrary-self-types-not-object-safe.rs b/tests/ui/self/arbitrary-self-types-dyn-incompatible.rs similarity index 100% rename from tests/ui/self/arbitrary-self-types-not-object-safe.rs rename to tests/ui/self/arbitrary-self-types-dyn-incompatible.rs diff --git a/tests/ui/self/arbitrary_self_types_pointers_and_wrappers.rs b/tests/ui/self/arbitrary_self_types_pointers_and_wrappers.rs index d7149002e7b..76d7754384e 100644 --- a/tests/ui/self/arbitrary_self_types_pointers_and_wrappers.rs +++ b/tests/ui/self/arbitrary_self_types_pointers_and_wrappers.rs @@ -50,9 +50,9 @@ impl, U> DispatchFromDyn> for Wrapper {} trait Trait { - // This method isn't object-safe yet. Unsized by-value `self` is object-safe (but not callable - // without unsized_locals), but wrappers arond `Self` currently are not. - // FIXME (mikeyhew) uncomment this when unsized rvalues object-safety is implemented + // This method isn't dyn-compatible yet. Unsized by-value `self` is dyn-compatible (but not + // callable without unsized_locals), but wrappers arond `Self` currently are not. + // FIXME (mikeyhew) uncomment this when unsized rvalues dyn-compatibility is implemented // fn wrapper(self: Wrapper) -> i32; fn ptr_wrapper(self: Ptr>) -> i32; fn wrapper_ptr(self: Wrapper>) -> i32; diff --git a/tests/ui/self/object-safety-sized-self-by-value-self.rs b/tests/ui/self/dyn-compatibility-sized-self-by-value-self.rs similarity index 90% rename from tests/ui/self/object-safety-sized-self-by-value-self.rs rename to tests/ui/self/dyn-compatibility-sized-self-by-value-self.rs index d902812eb9a..658371c95e2 100644 --- a/tests/ui/self/object-safety-sized-self-by-value-self.rs +++ b/tests/ui/self/dyn-compatibility-sized-self-by-value-self.rs @@ -1,6 +1,6 @@ //@ run-pass #![allow(unused_mut)] -// Check that a trait is still object-safe (and usable) if it has +// Check that a trait is still dyn-compatible (and usable) if it has // methods with by-value self so long as they require `Self : Sized`. diff --git a/tests/ui/self/object-safety-sized-self-generic-method.rs b/tests/ui/self/dyn-compatibility-sized-self-generic-method.rs similarity index 90% rename from tests/ui/self/object-safety-sized-self-generic-method.rs rename to tests/ui/self/dyn-compatibility-sized-self-generic-method.rs index 7a2ebd2cb79..a7b5013694f 100644 --- a/tests/ui/self/object-safety-sized-self-generic-method.rs +++ b/tests/ui/self/dyn-compatibility-sized-self-generic-method.rs @@ -1,6 +1,6 @@ //@ run-pass #![allow(unused_variables)] -// Check that a trait is still object-safe (and usable) if it has +// Check that a trait is still dyn-compatible (and usable) if it has // generic methods so long as they require `Self : Sized`. diff --git a/tests/ui/self/object-safety-sized-self-return-Self.rs b/tests/ui/self/dyn-compatibility-sized-self-return-Self.rs similarity index 90% rename from tests/ui/self/object-safety-sized-self-return-Self.rs rename to tests/ui/self/dyn-compatibility-sized-self-return-Self.rs index 9fc3f856772..a15f4fd7813 100644 --- a/tests/ui/self/object-safety-sized-self-return-Self.rs +++ b/tests/ui/self/dyn-compatibility-sized-self-return-Self.rs @@ -1,5 +1,5 @@ //@ run-pass -// Check that a trait is still object-safe (and usable) if it has +// Check that a trait is still dyn-compatible (and usable) if it has // methods that return `Self` so long as they require `Self : Sized`. diff --git a/tests/ui/specialization/issue-44861.rs b/tests/ui/specialization/issue-44861.rs index 79d9b9490d0..9d6517e613a 100644 --- a/tests/ui/specialization/issue-44861.rs +++ b/tests/ui/specialization/issue-44861.rs @@ -12,9 +12,9 @@ pub trait Smartass { type Data2: CoerceUnsized<*const [u8]>; } -pub trait MaybeObjectSafe {} +pub trait MaybeDynCompatible {} -impl MaybeObjectSafe for () {} +impl MaybeDynCompatible for () {} impl Smartass for T { type Data = ::Data2; @@ -26,7 +26,7 @@ impl Smartass for () { type Data2 = *const [u8; 1]; } -impl Smartass for dyn MaybeObjectSafe { +impl Smartass for dyn MaybeDynCompatible { type Data = *const [u8]; type Data2 = *const [u8; 0]; } @@ -35,6 +35,6 @@ impl CoerceUnsized> for S where ::Data: std::ops::CoerceUnsized<::Data> {} -pub fn conv(s: SmartassPtr<()>) -> SmartassPtr { +pub fn conv(s: SmartassPtr<()>) -> SmartassPtr { s } diff --git a/tests/ui/suggestions/auxiliary/not-object-safe.rs b/tests/ui/suggestions/auxiliary/dyn-incompatible.rs similarity index 100% rename from tests/ui/suggestions/auxiliary/not-object-safe.rs rename to tests/ui/suggestions/auxiliary/dyn-incompatible.rs diff --git a/tests/ui/suggestions/object-unsafe-trait-references-self.rs b/tests/ui/suggestions/dyn-incompatible-trait-references-self.rs similarity index 100% rename from tests/ui/suggestions/object-unsafe-trait-references-self.rs rename to tests/ui/suggestions/dyn-incompatible-trait-references-self.rs diff --git a/tests/ui/suggestions/object-unsafe-trait-references-self.stderr b/tests/ui/suggestions/dyn-incompatible-trait-references-self.stderr similarity index 87% rename from tests/ui/suggestions/object-unsafe-trait-references-self.stderr rename to tests/ui/suggestions/dyn-incompatible-trait-references-self.stderr index c00bb3efbf6..242c44abd9d 100644 --- a/tests/ui/suggestions/object-unsafe-trait-references-self.stderr +++ b/tests/ui/suggestions/dyn-incompatible-trait-references-self.stderr @@ -1,11 +1,11 @@ error[E0038]: the trait `Trait` cannot be made into an object - --> $DIR/object-unsafe-trait-references-self.rs:9:12 + --> $DIR/dyn-incompatible-trait-references-self.rs:9:12 | LL | fn bar(x: &dyn Trait) {} | ^^^^^^^^^ `Trait` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-unsafe-trait-references-self.rs:2:22 + --> $DIR/dyn-incompatible-trait-references-self.rs:2:22 | LL | trait Trait { | ----- this trait cannot be made into an object... @@ -18,13 +18,13 @@ LL | fn bat(&self) -> Self {} = help: consider moving `bat` to another trait error[E0038]: the trait `Other` cannot be made into an object - --> $DIR/object-unsafe-trait-references-self.rs:13:12 + --> $DIR/dyn-incompatible-trait-references-self.rs:13:12 | LL | fn foo(x: &dyn Other) {} | ^^^^^^^^^ `Other` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-unsafe-trait-references-self.rs:11:14 + --> $DIR/dyn-incompatible-trait-references-self.rs:11:14 | LL | trait Other: Sized {} | ----- ^^^^^ ...because it requires `Self: Sized` @@ -32,7 +32,7 @@ LL | trait Other: Sized {} | this trait cannot be made into an object... error[E0277]: the size for values of type `Self` cannot be known at compilation time - --> $DIR/object-unsafe-trait-references-self.rs:2:22 + --> $DIR/dyn-incompatible-trait-references-self.rs:2:22 | LL | fn baz(&self, _: Self) {} | ^^^^ doesn't have a size known at compile-time @@ -48,7 +48,7 @@ LL | fn baz(&self, _: &Self) {} | + error[E0308]: mismatched types - --> $DIR/object-unsafe-trait-references-self.rs:4:27 + --> $DIR/dyn-incompatible-trait-references-self.rs:4:27 | LL | trait Trait { | ----------- expected this type parameter @@ -60,7 +60,7 @@ LL | fn bat(&self) -> Self {} found unit type `()` error[E0277]: the size for values of type `Self` cannot be known at compilation time - --> $DIR/object-unsafe-trait-references-self.rs:4:22 + --> $DIR/dyn-incompatible-trait-references-self.rs:4:22 | LL | fn bat(&self) -> Self {} | ^^^^ doesn't have a size known at compile-time diff --git a/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021-without-dyn.rs b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs similarity index 100% rename from tests/ui/suggestions/object-unsafe-trait-should-use-self-2021-without-dyn.rs rename to tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs diff --git a/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021-without-dyn.stderr b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021-without-dyn.stderr similarity index 83% rename from tests/ui/suggestions/object-unsafe-trait-should-use-self-2021-without-dyn.stderr rename to tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021-without-dyn.stderr index a17f821ebec..53304382584 100644 --- a/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021-without-dyn.stderr +++ b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021-without-dyn.stderr @@ -1,5 +1,5 @@ error: associated item referring to unboxed trait object for its own trait - --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:4:13 + --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:4:13 | LL | trait A: Sized { | - in this trait @@ -12,13 +12,13 @@ LL | fn f(a: Self) -> Self; | ~~~~ ~~~~ error[E0038]: the trait `A` cannot be made into an object - --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:4:13 + --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:4:13 | LL | fn f(a: A) -> A; | ^ `A` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:3:10 + --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:3:10 | LL | trait A: Sized { | - ^^^^^ ...because it requires `Self: Sized` @@ -26,7 +26,7 @@ LL | trait A: Sized { | this trait cannot be made into an object... error: associated item referring to unboxed trait object for its own trait - --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:11:13 + --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:11:13 | LL | trait B { | - in this trait @@ -39,13 +39,13 @@ LL | fn f(b: Self) -> Self; | ~~~~ ~~~~ error[E0038]: the trait `B` cannot be made into an object - --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:11:13 + --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:11:13 | LL | fn f(b: B) -> B; | ^ `B` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:11:8 + --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:11:8 | LL | trait B { | - this trait cannot be made into an object... @@ -61,7 +61,7 @@ LL | fn f(b: B) -> B where Self: Sized; | +++++++++++++++++ error: associated item referring to unboxed trait object for its own trait - --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:18:20 + --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:18:20 | LL | trait C { | - in this trait @@ -74,7 +74,7 @@ LL | fn f(&self, c: Self) -> Self; | ~~~~ ~~~~ error[E0038]: the trait `C` cannot be made into an object - --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:18:20 + --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:18:20 | LL | fn f(&self, c: C) -> C; | ----- ^ `C` cannot be made into an object @@ -82,7 +82,7 @@ LL | fn f(&self, c: C) -> C; | help: consider changing method `f`'s `self` parameter to be `&self` (notice the capitalization): `&Self` | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:18:10 + --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:18:10 | LL | trait C { | - this trait cannot be made into an object... @@ -90,7 +90,7 @@ LL | fn f(&self, c: C) -> C; | ^^^^^ ...because method `f`'s `self` parameter cannot be dispatched on error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:4:13 + --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:4:13 | LL | fn f(a: A) -> A; | ^ @@ -106,7 +106,7 @@ LL | fn f(a: impl A) -> A; | ++++ error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:4:19 + --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:4:19 | LL | fn f(a: A) -> A; | ^ @@ -117,7 +117,7 @@ LL | fn f(a: A) -> impl A; | ++++ error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:11:13 + --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:11:13 | LL | fn f(b: B) -> B; | ^ @@ -133,7 +133,7 @@ LL | fn f(b: impl B) -> B; | ++++ error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:11:19 + --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:11:19 | LL | fn f(b: B) -> B; | ^ @@ -144,7 +144,7 @@ LL | fn f(b: B) -> impl B; | ++++ error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:18:20 + --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:18:20 | LL | fn f(&self, c: C) -> C; | ^ @@ -160,7 +160,7 @@ LL | fn f(&self, c: impl C) -> C; | ++++ error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:18:26 + --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:18:26 | LL | fn f(&self, c: C) -> C; | ^ diff --git a/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021.rs b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021.rs similarity index 100% rename from tests/ui/suggestions/object-unsafe-trait-should-use-self-2021.rs rename to tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021.rs diff --git a/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021.stderr b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021.stderr similarity index 85% rename from tests/ui/suggestions/object-unsafe-trait-should-use-self-2021.stderr rename to tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021.stderr index a7d36d9ebee..5e0d1a14452 100644 --- a/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021.stderr +++ b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021.stderr @@ -1,5 +1,5 @@ error: associated item referring to unboxed trait object for its own trait - --> $DIR/object-unsafe-trait-should-use-self-2021.rs:4:13 + --> $DIR/dyn-incompatible-trait-should-use-self-2021.rs:4:13 | LL | trait A: Sized { | - in this trait @@ -12,13 +12,13 @@ LL | fn f(a: Self) -> Self; | ~~~~ ~~~~ error[E0038]: the trait `A` cannot be made into an object - --> $DIR/object-unsafe-trait-should-use-self-2021.rs:4:13 + --> $DIR/dyn-incompatible-trait-should-use-self-2021.rs:4:13 | LL | fn f(a: dyn A) -> dyn A; | ^^^^^ `A` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-unsafe-trait-should-use-self-2021.rs:3:10 + --> $DIR/dyn-incompatible-trait-should-use-self-2021.rs:3:10 | LL | trait A: Sized { | - ^^^^^ ...because it requires `Self: Sized` @@ -26,7 +26,7 @@ LL | trait A: Sized { | this trait cannot be made into an object... error: associated item referring to unboxed trait object for its own trait - --> $DIR/object-unsafe-trait-should-use-self-2021.rs:9:13 + --> $DIR/dyn-incompatible-trait-should-use-self-2021.rs:9:13 | LL | trait B { | - in this trait @@ -39,13 +39,13 @@ LL | fn f(a: Self) -> Self; | ~~~~ ~~~~ error[E0038]: the trait `B` cannot be made into an object - --> $DIR/object-unsafe-trait-should-use-self-2021.rs:9:13 + --> $DIR/dyn-incompatible-trait-should-use-self-2021.rs:9:13 | LL | fn f(a: dyn B) -> dyn B; | ^^^^^ `B` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-unsafe-trait-should-use-self-2021.rs:9:8 + --> $DIR/dyn-incompatible-trait-should-use-self-2021.rs:9:8 | LL | trait B { | - this trait cannot be made into an object... diff --git a/tests/ui/suggestions/object-unsafe-trait-should-use-self.rs b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self.rs similarity index 100% rename from tests/ui/suggestions/object-unsafe-trait-should-use-self.rs rename to tests/ui/suggestions/dyn-incompatible-trait-should-use-self.rs diff --git a/tests/ui/suggestions/object-unsafe-trait-should-use-self.stderr b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self.stderr similarity index 86% rename from tests/ui/suggestions/object-unsafe-trait-should-use-self.stderr rename to tests/ui/suggestions/dyn-incompatible-trait-should-use-self.stderr index 28952933c64..93f6ea2b12e 100644 --- a/tests/ui/suggestions/object-unsafe-trait-should-use-self.stderr +++ b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self.stderr @@ -1,5 +1,5 @@ error: associated item referring to unboxed trait object for its own trait - --> $DIR/object-unsafe-trait-should-use-self.rs:3:13 + --> $DIR/dyn-incompatible-trait-should-use-self.rs:3:13 | LL | trait A: Sized { | - in this trait @@ -12,13 +12,13 @@ LL | fn f(a: Self) -> Self; | ~~~~ ~~~~ error[E0038]: the trait `A` cannot be made into an object - --> $DIR/object-unsafe-trait-should-use-self.rs:3:13 + --> $DIR/dyn-incompatible-trait-should-use-self.rs:3:13 | LL | fn f(a: A) -> A; | ^ `A` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-unsafe-trait-should-use-self.rs:2:10 + --> $DIR/dyn-incompatible-trait-should-use-self.rs:2:10 | LL | trait A: Sized { | - ^^^^^ ...because it requires `Self: Sized` @@ -26,7 +26,7 @@ LL | trait A: Sized { | this trait cannot be made into an object... error: associated item referring to unboxed trait object for its own trait - --> $DIR/object-unsafe-trait-should-use-self.rs:8:13 + --> $DIR/dyn-incompatible-trait-should-use-self.rs:8:13 | LL | trait B { | - in this trait @@ -39,13 +39,13 @@ LL | fn f(a: Self) -> Self; | ~~~~ ~~~~ error[E0038]: the trait `B` cannot be made into an object - --> $DIR/object-unsafe-trait-should-use-self.rs:8:13 + --> $DIR/dyn-incompatible-trait-should-use-self.rs:8:13 | LL | fn f(a: B) -> B; | ^ `B` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-unsafe-trait-should-use-self.rs:8:8 + --> $DIR/dyn-incompatible-trait-should-use-self.rs:8:8 | LL | trait B { | - this trait cannot be made into an object... diff --git a/tests/ui/suggestions/object-unsafe-trait-should-use-where-sized.fixed b/tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.fixed similarity index 100% rename from tests/ui/suggestions/object-unsafe-trait-should-use-where-sized.fixed rename to tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.fixed diff --git a/tests/ui/suggestions/object-unsafe-trait-should-use-where-sized.rs b/tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.rs similarity index 100% rename from tests/ui/suggestions/object-unsafe-trait-should-use-where-sized.rs rename to tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.rs diff --git a/tests/ui/suggestions/object-unsafe-trait-should-use-where-sized.stderr b/tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.stderr similarity index 89% rename from tests/ui/suggestions/object-unsafe-trait-should-use-where-sized.stderr rename to tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.stderr index 5e3a0290d42..beafd7c2ab0 100644 --- a/tests/ui/suggestions/object-unsafe-trait-should-use-where-sized.stderr +++ b/tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.stderr @@ -1,11 +1,11 @@ error[E0038]: the trait `Trait` cannot be made into an object - --> $DIR/object-unsafe-trait-should-use-where-sized.rs:9:12 + --> $DIR/dyn-incompatible-trait-should-use-where-sized.rs:9:12 | LL | fn bar(x: &dyn Trait) {} | ^^^^^^^^^ `Trait` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-unsafe-trait-should-use-where-sized.rs:5:8 + --> $DIR/dyn-incompatible-trait-should-use-where-sized.rs:5:8 | LL | trait Trait { | ----- this trait cannot be made into an object... @@ -27,7 +27,7 @@ LL | fn bar(self: &Self) {} | ~~~~~ error[E0307]: invalid `self` parameter type: `()` - --> $DIR/object-unsafe-trait-should-use-where-sized.rs:6:18 + --> $DIR/dyn-incompatible-trait-should-use-where-sized.rs:6:18 | LL | fn bar(self: ()) {} | ^^ diff --git a/tests/ui/suggestions/issue-98500.rs b/tests/ui/suggestions/issue-98500.rs index b6fd9e7c23f..289b16abf4b 100644 --- a/tests/ui/suggestions/issue-98500.rs +++ b/tests/ui/suggestions/issue-98500.rs @@ -1,9 +1,9 @@ -//@ aux-build:not-object-safe.rs +//@ aux-build:dyn-incompatible.rs -extern crate not_object_safe; +extern crate dyn_incompatible; pub trait B where - Self: not_object_safe::A, + Self: dyn_incompatible::A, { fn f2(&self); } diff --git a/tests/ui/suggestions/issue-98500.stderr b/tests/ui/suggestions/issue-98500.stderr index c4b446763af..d7136ec1a64 100644 --- a/tests/ui/suggestions/issue-98500.stderr +++ b/tests/ui/suggestions/issue-98500.stderr @@ -5,7 +5,7 @@ LL | struct S(Box); | ^^^^^ `B` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/auxiliary/not-object-safe.rs:4:8 + --> $DIR/auxiliary/dyn-incompatible.rs:4:8 | LL | fn f(); | ^ ...because associated function `f` has no `self` parameter diff --git a/tests/ui/traits/alias/no-duplicates.rs b/tests/ui/traits/alias/no-duplicates.rs index 88feb89170d..d0829ab4cec 100644 --- a/tests/ui/traits/alias/no-duplicates.rs +++ b/tests/ui/traits/alias/no-duplicates.rs @@ -1,4 +1,4 @@ -// The purpose of this test is to demonstrate that duplicating object safe traits +// The purpose of this test is to demonstrate that duplicating dyn-compatible traits // that are not auto traits is rejected with trait aliases even though one could // reasonably accept this. @@ -6,7 +6,7 @@ use std::marker::Unpin; -// Some arbitrary object-safe trait: +// Some arbitrary dyn-compatible trait: trait Obj {} // Nest a few levels deep: diff --git a/tests/ui/traits/alias/no-extra-traits.rs b/tests/ui/traits/alias/no-extra-traits.rs index 4dad8c0f873..f3d35a8cd03 100644 --- a/tests/ui/traits/alias/no-extra-traits.rs +++ b/tests/ui/traits/alias/no-extra-traits.rs @@ -5,7 +5,7 @@ use std::marker::Unpin; -// Some arbitrary object-safe traits: +// Some arbitrary dyn-compatible traits: trait ObjA {} trait ObjB {} diff --git a/tests/ui/traits/alias/object-wf.rs b/tests/ui/traits/alias/object-wf.rs index 3abffd22d14..a14cfea3bd7 100644 --- a/tests/ui/traits/alias/object-wf.rs +++ b/tests/ui/traits/alias/object-wf.rs @@ -20,7 +20,7 @@ fn _f0() { let _: Box; } -// Include object safe traits: +// Include dyn-compatible traits: fn _f1() { let _: Box; @@ -28,7 +28,7 @@ fn _f1() { let _: Box; } -// And when the object safe trait is in a trait alias: +// And when the dyn-compatible trait is in a trait alias: trait _2 = Obj; diff --git a/tests/ui/traits/next-solver/object-unsafety.rs b/tests/ui/traits/next-solver/dyn-incompatibility.rs similarity index 100% rename from tests/ui/traits/next-solver/object-unsafety.rs rename to tests/ui/traits/next-solver/dyn-incompatibility.rs diff --git a/tests/ui/traits/next-solver/object-unsafety.stderr b/tests/ui/traits/next-solver/dyn-incompatibility.stderr similarity index 90% rename from tests/ui/traits/next-solver/object-unsafety.stderr rename to tests/ui/traits/next-solver/dyn-incompatibility.stderr index 75d0ce24413..7f2c0646ef5 100644 --- a/tests/ui/traits/next-solver/object-unsafety.stderr +++ b/tests/ui/traits/next-solver/dyn-incompatibility.stderr @@ -1,12 +1,12 @@ error[E0277]: the trait bound `T: Copy` is not satisfied in `dyn Setup` - --> $DIR/object-unsafety.rs:12:12 + --> $DIR/dyn-incompatibility.rs:12:12 | LL | copy::>(t) | ^^^^^^^^^^^^^^^^^ within `dyn Setup`, the trait `Copy` is not implemented for `T`, which is required by `dyn Setup: Setup` | = note: required because it appears within the type `dyn Setup` note: required by a bound in `copy` - --> $DIR/object-unsafety.rs:7:12 + --> $DIR/dyn-incompatibility.rs:7:12 | LL | fn copy(from: &U::From) -> U::From { | ^^^^^ required by this bound in `copy` @@ -16,7 +16,7 @@ LL | pub fn copy_any(t: &T) -> T { | +++++++++++++++++++ error[E0308]: mismatched types - --> $DIR/object-unsafety.rs:12:31 + --> $DIR/dyn-incompatibility.rs:12:31 | LL | copy::>(t) | ------------------------- ^ types differ @@ -26,13 +26,13 @@ LL | copy::>(t) = note: expected reference `& as Setup>::From` found reference `&T` note: function defined here - --> $DIR/object-unsafety.rs:7:4 + --> $DIR/dyn-incompatibility.rs:7:4 | LL | fn copy(from: &U::From) -> U::From { | ^^^^ -------------- error[E0277]: the trait bound `T: Copy` is not satisfied in `dyn Setup` - --> $DIR/object-unsafety.rs:12:5 + --> $DIR/dyn-incompatibility.rs:12:5 | LL | copy::>(t) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `dyn Setup`, the trait `Copy` is not implemented for `T`, which is required by `dyn Setup: Setup` diff --git a/tests/ui/traits/non_lifetime_binders/supertrait-object-safety.rs b/tests/ui/traits/non_lifetime_binders/supertrait-dyn-compatibility.rs similarity index 100% rename from tests/ui/traits/non_lifetime_binders/supertrait-object-safety.rs rename to tests/ui/traits/non_lifetime_binders/supertrait-dyn-compatibility.rs diff --git a/tests/ui/traits/non_lifetime_binders/supertrait-object-safety.stderr b/tests/ui/traits/non_lifetime_binders/supertrait-dyn-compatibility.stderr similarity index 88% rename from tests/ui/traits/non_lifetime_binders/supertrait-object-safety.stderr rename to tests/ui/traits/non_lifetime_binders/supertrait-dyn-compatibility.stderr index 0854ea28150..dd2dca74f90 100644 --- a/tests/ui/traits/non_lifetime_binders/supertrait-object-safety.stderr +++ b/tests/ui/traits/non_lifetime_binders/supertrait-dyn-compatibility.stderr @@ -1,5 +1,5 @@ warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/supertrait-object-safety.rs:1:12 + --> $DIR/supertrait-dyn-compatibility.rs:1:12 | LL | #![feature(non_lifetime_binders)] | ^^^^^^^^^^^^^^^^^^^^ @@ -8,13 +8,13 @@ LL | #![feature(non_lifetime_binders)] = note: `#[warn(incomplete_features)]` on by default error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/supertrait-object-safety.rs:19:23 + --> $DIR/supertrait-dyn-compatibility.rs:19:23 | LL | let x: &dyn Foo = &(); | ^^^ `Foo` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/supertrait-object-safety.rs:4:12 + --> $DIR/supertrait-dyn-compatibility.rs:4:12 | LL | trait Foo: for Bar {} | --- ^^^^^^^^^^^^^ ...because where clause cannot reference non-lifetime `for<...>` variables @@ -24,13 +24,13 @@ LL | trait Foo: for Bar {} = note: required for the cast from `&()` to `&dyn Foo` error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/supertrait-object-safety.rs:19:12 + --> $DIR/supertrait-dyn-compatibility.rs:19:12 | LL | let x: &dyn Foo = &(); | ^^^^^^^^ `Foo` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/supertrait-object-safety.rs:4:12 + --> $DIR/supertrait-dyn-compatibility.rs:4:12 | LL | trait Foo: for Bar {} | --- ^^^^^^^^^^^^^ ...because where clause cannot reference non-lifetime `for<...>` variables @@ -39,13 +39,13 @@ LL | trait Foo: for Bar {} = help: only type `()` implements the trait, consider using it directly instead error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/supertrait-object-safety.rs:22:5 + --> $DIR/supertrait-dyn-compatibility.rs:22:5 | LL | needs_bar(x); | ^^^^^^^^^ `Foo` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/supertrait-object-safety.rs:4:12 + --> $DIR/supertrait-dyn-compatibility.rs:4:12 | LL | trait Foo: for Bar {} | --- ^^^^^^^^^^^^^ ...because where clause cannot reference non-lifetime `for<...>` variables diff --git a/tests/ui/traits/object/print_vtable_sizes.rs b/tests/ui/traits/object/print_vtable_sizes.rs index 684458d079e..2b1745da5f3 100644 --- a/tests/ui/traits/object/print_vtable_sizes.rs +++ b/tests/ui/traits/object/print_vtable_sizes.rs @@ -7,7 +7,7 @@ trait A: AsRef<[T::V]> + AsMut<[T::V]> {} trait B: AsRef + AsRef + AsRef + AsRef {} trait C { - fn x() {} // not object safe, shouldn't be reported + fn x() {} // not dyn-compatible, shouldn't be reported } // This does not have any upcasting cost, diff --git a/tests/ui/traits/object/safety.rs b/tests/ui/traits/object/safety.rs index f43d332d696..f4abcf8542e 100644 --- a/tests/ui/traits/object/safety.rs +++ b/tests/ui/traits/object/safety.rs @@ -1,4 +1,4 @@ -// Check that static methods are not object-safe. +// Check that static methods render the trait dyn-incompatible. trait Tr { fn foo(); diff --git a/tests/ui/traits/vtable/vtable-non-object-safe.rs b/tests/ui/traits/vtable/vtable-dyn-incompatible.rs similarity index 78% rename from tests/ui/traits/vtable/vtable-non-object-safe.rs rename to tests/ui/traits/vtable/vtable-dyn-incompatible.rs index f98af0f23b7..64a8138bdcf 100644 --- a/tests/ui/traits/vtable/vtable-non-object-safe.rs +++ b/tests/ui/traits/vtable/vtable-dyn-incompatible.rs @@ -1,7 +1,7 @@ //@ build-fail #![feature(rustc_attrs)] -// Ensure that non-object-safe methods in Iterator does not generate +// Ensure that dyn-incompatible methods in Iterator does not generate // vtable entries. #[rustc_dump_vtable] diff --git a/tests/ui/traits/vtable/vtable-non-object-safe.stderr b/tests/ui/traits/vtable/vtable-dyn-incompatible.stderr similarity index 92% rename from tests/ui/traits/vtable/vtable-non-object-safe.stderr rename to tests/ui/traits/vtable/vtable-dyn-incompatible.stderr index 53eef5d0b13..e442c3eac00 100644 --- a/tests/ui/traits/vtable/vtable-non-object-safe.stderr +++ b/tests/ui/traits/vtable/vtable-dyn-incompatible.stderr @@ -7,7 +7,7 @@ error: vtable entries for ` as A>`: [ Method( as Iterator>::advance_by), Method( as Iterator>::nth), ] - --> $DIR/vtable-non-object-safe.rs:8:1 + --> $DIR/vtable-dyn-incompatible.rs:8:1 | LL | trait A: Iterator {} | ^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/traits/wf-object/no-duplicates.rs b/tests/ui/traits/wf-object/no-duplicates.rs index 678ede58296..83544064ce2 100644 --- a/tests/ui/traits/wf-object/no-duplicates.rs +++ b/tests/ui/traits/wf-object/no-duplicates.rs @@ -1,7 +1,7 @@ -// The purpose of this test is to demonstrate that duplicating object safe traits +// The purpose of this test is to demonstrate that duplicating dyn-compatible traits // that are not auto-traits is rejected even though one could reasonably accept this. -// Some arbitrary object-safe trait: +// Some arbitrary dyn-compatible trait: trait Obj {} // Demonstrate that recursive expansion of trait aliases doesn't affect stable behavior: diff --git a/tests/ui/traits/wf-object/reverse-order.rs b/tests/ui/traits/wf-object/reverse-order.rs index b8f2aae8966..99c727cc332 100644 --- a/tests/ui/traits/wf-object/reverse-order.rs +++ b/tests/ui/traits/wf-object/reverse-order.rs @@ -2,7 +2,7 @@ // Ensure that `dyn $($AutoTrait)+ ObjSafe` is well-formed. -// Some arbitrary object-safe trait: +// Some arbitrary dyn-compatible trait: trait Obj {} type _0 = dyn Unpin; diff --git a/tests/ui/unsized-locals/by-value-trait-object-safety-rpass.rs b/tests/ui/unsized-locals/by-value-trait-dyn-compatibility-rpass.rs similarity index 100% rename from tests/ui/unsized-locals/by-value-trait-object-safety-rpass.rs rename to tests/ui/unsized-locals/by-value-trait-dyn-compatibility-rpass.rs diff --git a/tests/ui/unsized-locals/by-value-trait-object-safety-withdefault.rs b/tests/ui/unsized-locals/by-value-trait-dyn-compatibility-with-default.rs similarity index 100% rename from tests/ui/unsized-locals/by-value-trait-object-safety-withdefault.rs rename to tests/ui/unsized-locals/by-value-trait-dyn-compatibility-with-default.rs diff --git a/tests/ui/unsized-locals/by-value-trait-object-safety.rs b/tests/ui/unsized-locals/by-value-trait-dyn-compatibility.rs similarity index 100% rename from tests/ui/unsized-locals/by-value-trait-object-safety.rs rename to tests/ui/unsized-locals/by-value-trait-dyn-compatibility.rs diff --git a/tests/ui/unsized-locals/by-value-trait-object-safety.stderr b/tests/ui/unsized-locals/by-value-trait-dyn-compatibility.stderr similarity index 84% rename from tests/ui/unsized-locals/by-value-trait-object-safety.stderr rename to tests/ui/unsized-locals/by-value-trait-dyn-compatibility.stderr index 6a93464febb..223624cfca4 100644 --- a/tests/ui/unsized-locals/by-value-trait-object-safety.stderr +++ b/tests/ui/unsized-locals/by-value-trait-dyn-compatibility.stderr @@ -1,5 +1,5 @@ warning: the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/by-value-trait-object-safety.rs:1:12 + --> $DIR/by-value-trait-dyn-compatibility.rs:1:12 | LL | #![feature(unsized_locals)] | ^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | #![feature(unsized_locals)] = note: `#[warn(incomplete_features)]` on by default error: the `foo` method cannot be invoked on a trait object - --> $DIR/by-value-trait-object-safety.rs:20:7 + --> $DIR/by-value-trait-dyn-compatibility.rs:20:7 | LL | Self: Sized; | ----- this has a `Sized` requirement diff --git a/tests/ui/wf/wf-convert-unsafe-trait-obj-box.rs b/tests/ui/wf/wf-convert-dyn-incompat-trait-obj-box.rs similarity index 87% rename from tests/ui/wf/wf-convert-unsafe-trait-obj-box.rs rename to tests/ui/wf/wf-convert-dyn-incompat-trait-obj-box.rs index e32b04c4715..26292a1d218 100644 --- a/tests/ui/wf/wf-convert-unsafe-trait-obj-box.rs +++ b/tests/ui/wf/wf-convert-dyn-incompat-trait-obj-box.rs @@ -1,5 +1,5 @@ // Check that we do not allow casts or coercions -// to object unsafe trait objects inside a Box +// to dyn-incompatible trait objects inside a Box #![feature(dyn_compatible_for_dispatch)] diff --git a/tests/ui/wf/wf-convert-unsafe-trait-obj-box.stderr b/tests/ui/wf/wf-convert-dyn-incompat-trait-obj-box.stderr similarity index 86% rename from tests/ui/wf/wf-convert-unsafe-trait-obj-box.stderr rename to tests/ui/wf/wf-convert-dyn-incompat-trait-obj-box.stderr index 2565e25a242..38426545bc8 100644 --- a/tests/ui/wf/wf-convert-unsafe-trait-obj-box.stderr +++ b/tests/ui/wf/wf-convert-dyn-incompat-trait-obj-box.stderr @@ -1,11 +1,11 @@ error[E0038]: the trait `Trait` cannot be made into an object - --> $DIR/wf-convert-unsafe-trait-obj-box.rs:16:33 + --> $DIR/wf-convert-dyn-incompat-trait-obj-box.rs:16:33 | LL | let t_box: Box = Box::new(S); | ^^^^^^^^^^^ `Trait` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/wf-convert-unsafe-trait-obj-box.rs:6:14 + --> $DIR/wf-convert-dyn-incompat-trait-obj-box.rs:6:14 | LL | trait Trait: Sized {} | ----- ^^^^^ ...because it requires `Self: Sized` @@ -15,13 +15,13 @@ LL | trait Trait: Sized {} = note: required for the cast from `Box` to `Box` error[E0038]: the trait `Trait` cannot be made into an object - --> $DIR/wf-convert-unsafe-trait-obj-box.rs:17:15 + --> $DIR/wf-convert-dyn-incompat-trait-obj-box.rs:17:15 | LL | takes_box(Box::new(S)); | ^^^^^^^^^^^ `Trait` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/wf-convert-unsafe-trait-obj-box.rs:6:14 + --> $DIR/wf-convert-dyn-incompat-trait-obj-box.rs:6:14 | LL | trait Trait: Sized {} | ----- ^^^^^ ...because it requires `Self: Sized` @@ -31,13 +31,13 @@ LL | trait Trait: Sized {} = note: required for the cast from `Box` to `Box<(dyn Trait + 'static)>` error[E0038]: the trait `Trait` cannot be made into an object - --> $DIR/wf-convert-unsafe-trait-obj-box.rs:15:5 + --> $DIR/wf-convert-dyn-incompat-trait-obj-box.rs:15:5 | LL | Box::new(S) as Box; | ^^^^^^^^^^^ `Trait` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/wf-convert-unsafe-trait-obj-box.rs:6:14 + --> $DIR/wf-convert-dyn-incompat-trait-obj-box.rs:6:14 | LL | trait Trait: Sized {} | ----- ^^^^^ ...because it requires `Self: Sized` diff --git a/tests/ui/wf/wf-convert-unsafe-trait-obj.rs b/tests/ui/wf/wf-convert-dyn-incompat-trait-obj.rs similarity index 87% rename from tests/ui/wf/wf-convert-unsafe-trait-obj.rs rename to tests/ui/wf/wf-convert-dyn-incompat-trait-obj.rs index 6f386352819..ec4bb2897f9 100644 --- a/tests/ui/wf/wf-convert-unsafe-trait-obj.rs +++ b/tests/ui/wf/wf-convert-dyn-incompat-trait-obj.rs @@ -1,5 +1,5 @@ // Check that we do not allow casts or coercions -// to object unsafe trait objects by ref +// to dyn-incompatible trait objects by ref #![feature(dyn_compatible_for_dispatch)] diff --git a/tests/ui/wf/wf-convert-unsafe-trait-obj.stderr b/tests/ui/wf/wf-convert-dyn-incompat-trait-obj.stderr similarity index 87% rename from tests/ui/wf/wf-convert-unsafe-trait-obj.stderr rename to tests/ui/wf/wf-convert-dyn-incompat-trait-obj.stderr index 97f6bcd0428..94259aa5b0a 100644 --- a/tests/ui/wf/wf-convert-unsafe-trait-obj.stderr +++ b/tests/ui/wf/wf-convert-dyn-incompat-trait-obj.stderr @@ -1,11 +1,11 @@ error[E0038]: the trait `Trait` cannot be made into an object - --> $DIR/wf-convert-unsafe-trait-obj.rs:16:25 + --> $DIR/wf-convert-dyn-incompat-trait-obj.rs:16:25 | LL | let t: &dyn Trait = &S; | ^^ `Trait` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/wf-convert-unsafe-trait-obj.rs:6:14 + --> $DIR/wf-convert-dyn-incompat-trait-obj.rs:6:14 | LL | trait Trait: Sized {} | ----- ^^^^^ ...because it requires `Self: Sized` @@ -15,13 +15,13 @@ LL | trait Trait: Sized {} = note: required for the cast from `&S` to `&dyn Trait` error[E0038]: the trait `Trait` cannot be made into an object - --> $DIR/wf-convert-unsafe-trait-obj.rs:17:17 + --> $DIR/wf-convert-dyn-incompat-trait-obj.rs:17:17 | LL | takes_trait(&S); | ^^ `Trait` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/wf-convert-unsafe-trait-obj.rs:6:14 + --> $DIR/wf-convert-dyn-incompat-trait-obj.rs:6:14 | LL | trait Trait: Sized {} | ----- ^^^^^ ...because it requires `Self: Sized` @@ -31,13 +31,13 @@ LL | trait Trait: Sized {} = note: required for the cast from `&S` to `&dyn Trait` error[E0038]: the trait `Trait` cannot be made into an object - --> $DIR/wf-convert-unsafe-trait-obj.rs:15:5 + --> $DIR/wf-convert-dyn-incompat-trait-obj.rs:15:5 | LL | &S as &dyn Trait; | ^^ `Trait` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/wf-convert-unsafe-trait-obj.rs:6:14 + --> $DIR/wf-convert-dyn-incompat-trait-obj.rs:6:14 | LL | trait Trait: Sized {} | ----- ^^^^^ ...because it requires `Self: Sized` diff --git a/tests/ui/wf/wf-unsafe-trait-obj-match.rs b/tests/ui/wf/wf-dyn-incompat-trait-obj-match.rs similarity index 100% rename from tests/ui/wf/wf-unsafe-trait-obj-match.rs rename to tests/ui/wf/wf-dyn-incompat-trait-obj-match.rs diff --git a/tests/ui/wf/wf-unsafe-trait-obj-match.stderr b/tests/ui/wf/wf-dyn-incompat-trait-obj-match.stderr similarity index 89% rename from tests/ui/wf/wf-unsafe-trait-obj-match.stderr rename to tests/ui/wf/wf-dyn-incompat-trait-obj-match.stderr index edbdec6a5ef..d7366e12256 100644 --- a/tests/ui/wf/wf-unsafe-trait-obj-match.stderr +++ b/tests/ui/wf/wf-dyn-incompat-trait-obj-match.stderr @@ -1,5 +1,5 @@ error[E0308]: `match` arms have incompatible types - --> $DIR/wf-unsafe-trait-obj-match.rs:23:17 + --> $DIR/wf-dyn-incompat-trait-obj-match.rs:23:17 | LL | / match opt() { LL | | Some(()) => &S, @@ -13,13 +13,13 @@ LL | | } found reference `&R` error[E0038]: the trait `Trait` cannot be made into an object - --> $DIR/wf-unsafe-trait-obj-match.rs:26:21 + --> $DIR/wf-dyn-incompat-trait-obj-match.rs:26:21 | LL | Some(()) => &S, | ^^ `Trait` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/wf-unsafe-trait-obj-match.rs:6:14 + --> $DIR/wf-dyn-incompat-trait-obj-match.rs:6:14 | LL | trait Trait: Sized {} | ----- ^^^^^ ...because it requires `Self: Sized` @@ -31,7 +31,7 @@ LL | trait Trait: Sized {} = note: required for the cast from `&S` to `&dyn Trait` error[E0038]: the trait `Trait` cannot be made into an object - --> $DIR/wf-unsafe-trait-obj-match.rs:25:25 + --> $DIR/wf-dyn-incompat-trait-obj-match.rs:25:25 | LL | let t: &dyn Trait = match opt() { | _________________________^ @@ -41,7 +41,7 @@ LL | | }; | |_____^ `Trait` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/wf-unsafe-trait-obj-match.rs:6:14 + --> $DIR/wf-dyn-incompat-trait-obj-match.rs:6:14 | LL | trait Trait: Sized {} | ----- ^^^^^ ...because it requires `Self: Sized` diff --git a/tests/ui/wf/wf-object-safe.rs b/tests/ui/wf/wf-dyn-incompatible.rs similarity index 57% rename from tests/ui/wf/wf-object-safe.rs rename to tests/ui/wf/wf-dyn-incompatible.rs index 42e6917551f..16e7ca1cbc6 100644 --- a/tests/ui/wf/wf-object-safe.rs +++ b/tests/ui/wf/wf-dyn-incompatible.rs @@ -1,4 +1,4 @@ -// Check that object-safe traits are not WF when used as object types. +// Check that dyn-incompatible traits are not WF when used as trait object types. // Issue #21953. trait A { diff --git a/tests/ui/wf/wf-object-safe.stderr b/tests/ui/wf/wf-dyn-incompatible.stderr similarity index 90% rename from tests/ui/wf/wf-object-safe.stderr rename to tests/ui/wf/wf-dyn-incompatible.stderr index 7c14f3d2f8b..cf016b63c74 100644 --- a/tests/ui/wf/wf-object-safe.stderr +++ b/tests/ui/wf/wf-dyn-incompatible.stderr @@ -1,11 +1,11 @@ error[E0038]: the trait `A` cannot be made into an object - --> $DIR/wf-object-safe.rs:9:13 + --> $DIR/wf-dyn-incompatible.rs:9:13 | LL | let _x: &dyn A; | ^^^^^^ `A` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/wf-object-safe.rs:5:23 + --> $DIR/wf-dyn-incompatible.rs:5:23 | LL | trait A { | - this trait cannot be made into an object... From 0c41c3414c0e89ccb19310a4ec423ac83a48f039 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Mon, 7 Oct 2024 19:34:13 -0400 Subject: [PATCH 137/357] Allow zero-size reads/writes on null pointers --- library/core/src/intrinsics.rs | 19 ++++++++++++------- library/core/src/ptr/mod.rs | 21 +++++++++++++-------- library/core/src/slice/raw.rs | 4 ++-- library/core/src/ub_checks.rs | 4 ++-- 4 files changed, 29 insertions(+), 19 deletions(-) diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index d7a2f1909ca..d76b7ca66cc 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -64,6 +64,7 @@ #![allow(missing_docs)] use crate::marker::{DiscriminantKind, Tuple}; +use crate::mem::SizedTypeProperties; use crate::{ptr, ub_checks}; pub mod mir; @@ -3311,10 +3312,12 @@ pub const unsafe fn copy_nonoverlapping(src: *const T, dst: *mut T, count: us size: usize = size_of::(), align: usize = align_of::(), count: usize = count, - ) => - ub_checks::is_aligned_and_not_null(src, align) - && ub_checks::is_aligned_and_not_null(dst, align) - && ub_checks::is_nonoverlapping(src, dst, size, count) + ) => { + let zero_size = count == 0 || size == 0; + ub_checks::is_aligned_and_not_null(src, align, zero_size) + && ub_checks::is_aligned_and_not_null(dst, align, zero_size) + && ub_checks::is_nonoverlapping(src, dst, size, count) + } ); // SAFETY: the safety contract for `copy_nonoverlapping` must be @@ -3412,9 +3415,10 @@ pub const unsafe fn copy(src: *const T, dst: *mut T, count: usize) { src: *const () = src as *const (), dst: *mut () = dst as *mut (), align: usize = align_of::(), + zero_size: bool = T::IS_ZST || count == 0, ) => - ub_checks::is_aligned_and_not_null(src, align) - && ub_checks::is_aligned_and_not_null(dst, align) + ub_checks::is_aligned_and_not_null(src, align, zero_size) + && ub_checks::is_aligned_and_not_null(dst, align, zero_size) ); copy(src, dst, count) } @@ -3491,7 +3495,8 @@ pub const unsafe fn write_bytes(dst: *mut T, val: u8, count: usize) { ( addr: *const () = dst as *const (), align: usize = align_of::(), - ) => ub_checks::is_aligned_and_not_null(addr, align) + zero_size: bool = T::IS_ZST || count == 0, + ) => ub_checks::is_aligned_and_not_null(addr, align, zero_size) ); write_bytes(dst, val, count) } diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 67f1b0cd16d..53ca5a7f198 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -448,7 +448,7 @@ use crate::cmp::Ordering; use crate::marker::FnPtr; -use crate::mem::{self, MaybeUninit}; +use crate::mem::{self, MaybeUninit, SizedTypeProperties}; use crate::{fmt, hash, intrinsics, ub_checks}; mod alignment; @@ -1165,10 +1165,12 @@ pub const unsafe fn swap_nonoverlapping(x: *mut T, y: *mut T, count: usize) { size: usize = size_of::(), align: usize = align_of::(), count: usize = count, - ) => - ub_checks::is_aligned_and_not_null(x, align) - && ub_checks::is_aligned_and_not_null(y, align) - && ub_checks::is_nonoverlapping(x, y, size, count) + ) => { + let zero_size = size == 0 || count == 0; + ub_checks::is_aligned_and_not_null(x, align, zero_size) + && ub_checks::is_aligned_and_not_null(y, align, zero_size) + && ub_checks::is_nonoverlapping(x, y, size, count) + } ); // Split up the slice into small power-of-two-sized chunks that LLVM is able @@ -1277,7 +1279,8 @@ pub const unsafe fn replace(dst: *mut T, src: T) -> T { ( addr: *const () = dst as *const (), align: usize = align_of::(), - ) => ub_checks::is_aligned_and_not_null(addr, align) + is_zst: bool = T::IS_ZST, + ) => ub_checks::is_aligned_and_not_null(addr, align, is_zst) ); mem::replace(&mut *dst, src) } @@ -1806,7 +1809,8 @@ pub unsafe fn read_volatile(src: *const T) -> T { ( addr: *const () = src as *const (), align: usize = align_of::(), - ) => ub_checks::is_aligned_and_not_null(addr, align) + is_zst: bool = T::IS_ZST, + ) => ub_checks::is_aligned_and_not_null(addr, align, is_zst) ); intrinsics::volatile_load(src) } @@ -1885,7 +1889,8 @@ pub unsafe fn write_volatile(dst: *mut T, src: T) { ( addr: *mut () = dst as *mut (), align: usize = align_of::(), - ) => ub_checks::is_aligned_and_not_null(addr, align) + is_zst: bool = T::IS_ZST, + ) => ub_checks::is_aligned_and_not_null(addr, align, is_zst) ); intrinsics::volatile_store(dst, src); } diff --git a/library/core/src/slice/raw.rs b/library/core/src/slice/raw.rs index 84e916b9a84..27bbadf7c89 100644 --- a/library/core/src/slice/raw.rs +++ b/library/core/src/slice/raw.rs @@ -132,7 +132,7 @@ pub const unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] align: usize = align_of::(), len: usize = len, ) => - ub_checks::is_aligned_and_not_null(data, align) + ub_checks::is_aligned_and_not_null(data, align, false) && ub_checks::is_valid_allocation_size(size, len) ); &*ptr::slice_from_raw_parts(data, len) @@ -187,7 +187,7 @@ pub const unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a m align: usize = align_of::(), len: usize = len, ) => - ub_checks::is_aligned_and_not_null(data, align) + ub_checks::is_aligned_and_not_null(data, align, false) && ub_checks::is_valid_allocation_size(size, len) ); &mut *ptr::slice_from_raw_parts_mut(data, len) diff --git a/library/core/src/ub_checks.rs b/library/core/src/ub_checks.rs index c1a8c34539e..2ea30e77609 100644 --- a/library/core/src/ub_checks.rs +++ b/library/core/src/ub_checks.rs @@ -116,8 +116,8 @@ pub(crate) const fn check_language_ub() -> bool { /// for `assert_unsafe_precondition!` with `check_language_ub`, in which case the /// check is anyway not executed in `const`. #[inline] -pub(crate) const fn is_aligned_and_not_null(ptr: *const (), align: usize) -> bool { - !ptr.is_null() && ptr.is_aligned_to(align) +pub(crate) const fn is_aligned_and_not_null(ptr: *const (), align: usize, is_zst: bool) -> bool { + if is_zst { ptr.is_aligned_to(align) } else { !ptr.is_null() && ptr.is_aligned_to(align) } } #[inline] From 84dacc18829e24ec5d61087a233de68ef57dfabc Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Mon, 7 Oct 2024 19:34:25 -0400 Subject: [PATCH 138/357] Add more precondition check tests --- library/core/src/ascii/ascii_char.rs | 2 +- library/core/src/ptr/mod.rs | 6 +++-- tests/ui/precondition-checks/alignment.rs | 11 ++++++++ .../ascii-char-digit_unchecked.rs | 11 ++++++++ .../precondition-checks/assert_unchecked.rs | 9 +++++++ .../char-from_u32_unchecked.rs | 9 +++++++ .../copy-nonoverlapping.rs | 25 +++++++++++++++++++ tests/ui/precondition-checks/copy.rs | 23 +++++++++++++++++ tests/ui/precondition-checks/layout.rs | 15 +++++++++++ .../precondition-checks/misaligned-slice.rs | 10 -------- tests/ui/precondition-checks/nonnull.rs | 9 +++++++ .../nonzero-from_mut_unchecked.rs | 12 +++++++++ .../nonzero-new_unchecked.rs | 9 +++++++ tests/ui/precondition-checks/null-slice.rs | 10 -------- .../out-of-bounds-get-unchecked.rs | 11 -------- tests/ui/precondition-checks/read.rs | 18 +++++++++++++ tests/ui/precondition-checks/read_volatile.rs | 17 +++++++++++++ tests/ui/precondition-checks/replace.rs | 17 +++++++++++++ .../slice-from-raw-parts-mut.rs | 16 ++++++++++++ .../slice-from-raw-parts.rs | 15 +++++++++++ .../slice-get_unchecked.rs | 20 +++++++++++++++ .../slice-get_unchecked_mut.rs | 20 +++++++++++++++ .../slice-swap_unchecked.rs | 14 +++++++++++ .../precondition-checks/str-get_unchecked.rs | 18 +++++++++++++ .../str-get_unchecked_mut.rs | 19 ++++++++++++++ .../swap-nonoverlapping.rs | 25 +++++++++++++++++++ tests/ui/precondition-checks/unchecked_add.rs | 9 +++++++ tests/ui/precondition-checks/unchecked_mul.rs | 9 +++++++ tests/ui/precondition-checks/unchecked_shl.rs | 11 ++++++++ tests/ui/precondition-checks/unchecked_shr.rs | 11 ++++++++ tests/ui/precondition-checks/unchecked_sub.rs | 9 +++++++ .../unreachable_unchecked.rs | 9 +++++++ tests/ui/precondition-checks/write.rs | 18 +++++++++++++ tests/ui/precondition-checks/write_bytes.rs | 18 +++++++++++++ .../ui/precondition-checks/write_volatile.rs | 17 +++++++++++++ 35 files changed, 448 insertions(+), 34 deletions(-) create mode 100644 tests/ui/precondition-checks/alignment.rs create mode 100644 tests/ui/precondition-checks/ascii-char-digit_unchecked.rs create mode 100644 tests/ui/precondition-checks/assert_unchecked.rs create mode 100644 tests/ui/precondition-checks/char-from_u32_unchecked.rs create mode 100644 tests/ui/precondition-checks/copy-nonoverlapping.rs create mode 100644 tests/ui/precondition-checks/copy.rs create mode 100644 tests/ui/precondition-checks/layout.rs delete mode 100644 tests/ui/precondition-checks/misaligned-slice.rs create mode 100644 tests/ui/precondition-checks/nonnull.rs create mode 100644 tests/ui/precondition-checks/nonzero-from_mut_unchecked.rs create mode 100644 tests/ui/precondition-checks/nonzero-new_unchecked.rs delete mode 100644 tests/ui/precondition-checks/null-slice.rs delete mode 100644 tests/ui/precondition-checks/out-of-bounds-get-unchecked.rs create mode 100644 tests/ui/precondition-checks/read.rs create mode 100644 tests/ui/precondition-checks/read_volatile.rs create mode 100644 tests/ui/precondition-checks/replace.rs create mode 100644 tests/ui/precondition-checks/slice-from-raw-parts-mut.rs create mode 100644 tests/ui/precondition-checks/slice-from-raw-parts.rs create mode 100644 tests/ui/precondition-checks/slice-get_unchecked.rs create mode 100644 tests/ui/precondition-checks/slice-get_unchecked_mut.rs create mode 100644 tests/ui/precondition-checks/slice-swap_unchecked.rs create mode 100644 tests/ui/precondition-checks/str-get_unchecked.rs create mode 100644 tests/ui/precondition-checks/str-get_unchecked_mut.rs create mode 100644 tests/ui/precondition-checks/swap-nonoverlapping.rs create mode 100644 tests/ui/precondition-checks/unchecked_add.rs create mode 100644 tests/ui/precondition-checks/unchecked_mul.rs create mode 100644 tests/ui/precondition-checks/unchecked_shl.rs create mode 100644 tests/ui/precondition-checks/unchecked_shr.rs create mode 100644 tests/ui/precondition-checks/unchecked_sub.rs create mode 100644 tests/ui/precondition-checks/unreachable_unchecked.rs create mode 100644 tests/ui/precondition-checks/write.rs create mode 100644 tests/ui/precondition-checks/write_bytes.rs create mode 100644 tests/ui/precondition-checks/write_volatile.rs diff --git a/library/core/src/ascii/ascii_char.rs b/library/core/src/ascii/ascii_char.rs index ce09a0b444d..48de4f17b1b 100644 --- a/library/core/src/ascii/ascii_char.rs +++ b/library/core/src/ascii/ascii_char.rs @@ -506,7 +506,7 @@ impl AsciiChar { pub const unsafe fn digit_unchecked(d: u8) -> Self { assert_unsafe_precondition!( check_language_ub, - "`AsciiChar::digit_unchecked` input cannot exceed 9.", + "`ascii::Char::digit_unchecked` input cannot exceed 9.", (d: u8 = d) => d < 10 ); diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 53ca5a7f198..62160937083 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -1432,7 +1432,8 @@ pub const unsafe fn read(src: *const T) -> T { ( addr: *const () = src as *const (), align: usize = align_of::(), - ) => ub_checks::is_aligned_and_not_null(addr, align) + is_zst: bool = T::IS_ZST, + ) => ub_checks::is_aligned_and_not_null(addr, align, is_zst) ); crate::intrinsics::read_via_copy(src) } @@ -1637,7 +1638,8 @@ pub const unsafe fn write(dst: *mut T, src: T) { ( addr: *mut () = dst as *mut (), align: usize = align_of::(), - ) => ub_checks::is_aligned_and_not_null(addr, align) + is_zst: bool = T::IS_ZST, + ) => ub_checks::is_aligned_and_not_null(addr, align, is_zst) ); intrinsics::write_via_move(dst, src) } diff --git a/tests/ui/precondition-checks/alignment.rs b/tests/ui/precondition-checks/alignment.rs new file mode 100644 index 00000000000..92400528fa0 --- /dev/null +++ b/tests/ui/precondition-checks/alignment.rs @@ -0,0 +1,11 @@ +//@ run-fail +//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes +//@ error-pattern: unsafe precondition(s) violated: Alignment::new_unchecked requires + +#![feature(ptr_alignment_type)] + +fn main() { + unsafe { + std::ptr::Alignment::new_unchecked(0); + } +} diff --git a/tests/ui/precondition-checks/ascii-char-digit_unchecked.rs b/tests/ui/precondition-checks/ascii-char-digit_unchecked.rs new file mode 100644 index 00000000000..30c6f79fb08 --- /dev/null +++ b/tests/ui/precondition-checks/ascii-char-digit_unchecked.rs @@ -0,0 +1,11 @@ +//@ run-fail +//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes +//@ error-pattern: unsafe precondition(s) violated: `ascii::Char::digit_unchecked` input cannot exceed 9 + +#![feature(ascii_char)] + +fn main() { + unsafe { + std::ascii::Char::digit_unchecked(b'a'); + } +} diff --git a/tests/ui/precondition-checks/assert_unchecked.rs b/tests/ui/precondition-checks/assert_unchecked.rs new file mode 100644 index 00000000000..22b2b414550 --- /dev/null +++ b/tests/ui/precondition-checks/assert_unchecked.rs @@ -0,0 +1,9 @@ +//@ run-fail +//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes +//@ error-pattern: unsafe precondition(s) violated: hint::assert_unchecked must never be called when the condition is false + +fn main() { + unsafe { + std::hint::assert_unchecked(false); + } +} diff --git a/tests/ui/precondition-checks/char-from_u32_unchecked.rs b/tests/ui/precondition-checks/char-from_u32_unchecked.rs new file mode 100644 index 00000000000..d950f20c772 --- /dev/null +++ b/tests/ui/precondition-checks/char-from_u32_unchecked.rs @@ -0,0 +1,9 @@ +//@ run-fail +//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes +//@ error-pattern: unsafe precondition(s) violated: invalid value for `char` + +fn main() { + unsafe { + char::from_u32_unchecked(0xD801); + } +} diff --git a/tests/ui/precondition-checks/copy-nonoverlapping.rs b/tests/ui/precondition-checks/copy-nonoverlapping.rs new file mode 100644 index 00000000000..81018e4bff3 --- /dev/null +++ b/tests/ui/precondition-checks/copy-nonoverlapping.rs @@ -0,0 +1,25 @@ +//@ run-fail +//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes +//@ error-pattern: unsafe precondition(s) violated: ptr::copy_nonoverlapping requires +//@ revisions: null_src null_dst misaligned_src misaligned_dst overlapping + +use std::ptr; + +fn main() { + let src = [0u16; 3]; + let mut dst = [0u16; 3]; + let src = src.as_ptr(); + let dst = dst.as_mut_ptr(); + unsafe { + #[cfg(null_src)] + ptr::copy_nonoverlapping(ptr::null(), dst, 1); + #[cfg(null_dst)] + ptr::copy_nonoverlapping(src, ptr::null_mut(), 1); + #[cfg(misaligned_src)] + ptr::copy_nonoverlapping(src.byte_add(1), dst, 1); + #[cfg(misaligned_dst)] + ptr::copy_nonoverlapping(src, dst.byte_add(1), 1); + #[cfg(overlapping)] + ptr::copy_nonoverlapping(dst, dst.add(1), 2); + } +} diff --git a/tests/ui/precondition-checks/copy.rs b/tests/ui/precondition-checks/copy.rs new file mode 100644 index 00000000000..694853f950a --- /dev/null +++ b/tests/ui/precondition-checks/copy.rs @@ -0,0 +1,23 @@ +//@ run-fail +//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes +//@ error-pattern: unsafe precondition(s) violated: ptr::copy requires +//@ revisions: null_src null_dst misaligned_src misaligned_dst + +use std::ptr; + +fn main() { + let src = [0u16; 3]; + let mut dst = [0u16; 3]; + let src = src.as_ptr(); + let dst = dst.as_mut_ptr(); + unsafe { + #[cfg(null_src)] + ptr::copy(ptr::null(), dst, 1); + #[cfg(null_dst)] + ptr::copy(src, ptr::null_mut(), 1); + #[cfg(misaligned_src)] + ptr::copy(src.byte_add(1), dst, 1); + #[cfg(misaligned_dst)] + ptr::copy(src, dst.byte_add(1), 1); + } +} diff --git a/tests/ui/precondition-checks/layout.rs b/tests/ui/precondition-checks/layout.rs new file mode 100644 index 00000000000..4fd1bbc4a99 --- /dev/null +++ b/tests/ui/precondition-checks/layout.rs @@ -0,0 +1,15 @@ +//@ run-fail +//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes +//@ error-pattern: unsafe precondition(s) violated: Layout::from_size_align_unchecked requires +//@ revisions: toolarge badalign +//@[toolarge] compile-flags: --cfg toolarge +//@[badalign] compile-flags: --cfg badalign + +fn main() { + unsafe { + #[cfg(toolarge)] + std::alloc::Layout::from_size_align_unchecked(isize::MAX as usize, 2); + #[cfg(badalign)] + std::alloc::Layout::from_size_align_unchecked(1, 3); + } +} diff --git a/tests/ui/precondition-checks/misaligned-slice.rs b/tests/ui/precondition-checks/misaligned-slice.rs deleted file mode 100644 index 2963a0b5e63..00000000000 --- a/tests/ui/precondition-checks/misaligned-slice.rs +++ /dev/null @@ -1,10 +0,0 @@ -//@ run-fail -//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes -//@ error-pattern: unsafe precondition(s) violated: slice::from_raw_parts -//@ ignore-debug - -fn main() { - unsafe { - let _s: &[u64] = std::slice::from_raw_parts(1usize as *const u64, 0); - } -} diff --git a/tests/ui/precondition-checks/nonnull.rs b/tests/ui/precondition-checks/nonnull.rs new file mode 100644 index 00000000000..6b8edd4e582 --- /dev/null +++ b/tests/ui/precondition-checks/nonnull.rs @@ -0,0 +1,9 @@ +//@ run-fail +//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes +//@ error-pattern: unsafe precondition(s) violated: NonNull::new_unchecked requires + +fn main() { + unsafe { + std::ptr::NonNull::new_unchecked(std::ptr::null_mut::()); + } +} diff --git a/tests/ui/precondition-checks/nonzero-from_mut_unchecked.rs b/tests/ui/precondition-checks/nonzero-from_mut_unchecked.rs new file mode 100644 index 00000000000..46ce7dc356f --- /dev/null +++ b/tests/ui/precondition-checks/nonzero-from_mut_unchecked.rs @@ -0,0 +1,12 @@ +//@ run-fail +//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes +//@ error-pattern: unsafe precondition(s) violated: NonZero::from_mut_unchecked requires + +#![feature(nonzero_from_mut)] + +fn main() { + unsafe { + let mut num = 0u8; + std::num::NonZeroU8::from_mut_unchecked(&mut num); + } +} diff --git a/tests/ui/precondition-checks/nonzero-new_unchecked.rs b/tests/ui/precondition-checks/nonzero-new_unchecked.rs new file mode 100644 index 00000000000..7827a42844f --- /dev/null +++ b/tests/ui/precondition-checks/nonzero-new_unchecked.rs @@ -0,0 +1,9 @@ +//@ run-fail +//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes +//@ error-pattern: unsafe precondition(s) violated: NonZero::new_unchecked requires + +fn main() { + unsafe { + std::num::NonZeroU8::new_unchecked(0); + } +} diff --git a/tests/ui/precondition-checks/null-slice.rs b/tests/ui/precondition-checks/null-slice.rs deleted file mode 100644 index 280960358b7..00000000000 --- a/tests/ui/precondition-checks/null-slice.rs +++ /dev/null @@ -1,10 +0,0 @@ -//@ run-fail -//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes -//@ error-pattern: unsafe precondition(s) violated: slice::from_raw_parts -//@ ignore-debug - -fn main() { - unsafe { - let _s: &[u8] = std::slice::from_raw_parts(std::ptr::null(), 0); - } -} diff --git a/tests/ui/precondition-checks/out-of-bounds-get-unchecked.rs b/tests/ui/precondition-checks/out-of-bounds-get-unchecked.rs deleted file mode 100644 index 011e92183fa..00000000000 --- a/tests/ui/precondition-checks/out-of-bounds-get-unchecked.rs +++ /dev/null @@ -1,11 +0,0 @@ -//@ run-fail -//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes -//@ error-pattern: slice::get_unchecked requires -//@ ignore-debug - -fn main() { - unsafe { - let sli: &[u8] = &[0]; - sli.get_unchecked(1); - } -} diff --git a/tests/ui/precondition-checks/read.rs b/tests/ui/precondition-checks/read.rs new file mode 100644 index 00000000000..ab9921a0cee --- /dev/null +++ b/tests/ui/precondition-checks/read.rs @@ -0,0 +1,18 @@ +//@ run-fail +//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes +//@ error-pattern: unsafe precondition(s) violated: ptr::read requires +//@ revisions: null misaligned +//@ ignore-test + +use std::ptr; + +fn main() { + let src = [0u16; 2]; + let src = src.as_ptr(); + unsafe { + #[cfg(null)] + ptr::read(ptr::null::()); + #[cfg(misaligned)] + ptr::read(src.byte_add(1)); + } +} diff --git a/tests/ui/precondition-checks/read_volatile.rs b/tests/ui/precondition-checks/read_volatile.rs new file mode 100644 index 00000000000..e14881d0290 --- /dev/null +++ b/tests/ui/precondition-checks/read_volatile.rs @@ -0,0 +1,17 @@ +//@ run-fail +//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes +//@ error-pattern: unsafe precondition(s) violated: ptr::read_volatile requires +//@ revisions: null misaligned + +use std::ptr; + +fn main() { + let src = [0u16; 2]; + let src = src.as_ptr(); + unsafe { + #[cfg(null)] + ptr::read_volatile(ptr::null::()); + #[cfg(misaligned)] + ptr::read_volatile(src.byte_add(1)); + } +} diff --git a/tests/ui/precondition-checks/replace.rs b/tests/ui/precondition-checks/replace.rs new file mode 100644 index 00000000000..2808cee7b64 --- /dev/null +++ b/tests/ui/precondition-checks/replace.rs @@ -0,0 +1,17 @@ +//@ run-fail +//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes +//@ error-pattern: unsafe precondition(s) violated: ptr::replace requires +//@ revisions: null misaligned + +use std::ptr; + +fn main() { + let mut dst = [0u16; 2]; + let dst = dst.as_mut_ptr(); + unsafe { + #[cfg(null)] + ptr::replace(ptr::null_mut::(), 1); + #[cfg(misaligned)] + ptr::replace(dst.byte_add(1), 1u16); + } +} diff --git a/tests/ui/precondition-checks/slice-from-raw-parts-mut.rs b/tests/ui/precondition-checks/slice-from-raw-parts-mut.rs new file mode 100644 index 00000000000..3801639e255 --- /dev/null +++ b/tests/ui/precondition-checks/slice-from-raw-parts-mut.rs @@ -0,0 +1,16 @@ +//@ run-fail +//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes +//@ error-pattern: unsafe precondition(s) violated: slice::from_raw_parts_mut requires +//@ revisions: null misaligned toolarge + +fn main() { + unsafe { + #[cfg(null)] + let _s: &mut [u8] = std::slice::from_raw_parts_mut(std::ptr::null_mut(), 0); + #[cfg(misaligned)] + let _s: &mut [u16] = std::slice::from_raw_parts_mut(1usize as *mut u16, 0); + #[cfg(toolarge)] + let _s: &mut [u16] = + std::slice::from_raw_parts_mut(2usize as *mut u16, isize::MAX as usize); + } +} diff --git a/tests/ui/precondition-checks/slice-from-raw-parts.rs b/tests/ui/precondition-checks/slice-from-raw-parts.rs new file mode 100644 index 00000000000..a3690fa045e --- /dev/null +++ b/tests/ui/precondition-checks/slice-from-raw-parts.rs @@ -0,0 +1,15 @@ +//@ run-fail +//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes +//@ error-pattern: unsafe precondition(s) violated: slice::from_raw_parts requires +//@ revisions: null misaligned toolarge + +fn main() { + unsafe { + #[cfg(null)] + let _s: &[u8] = std::slice::from_raw_parts(std::ptr::null(), 0); + #[cfg(misaligned)] + let _s: &[u16] = std::slice::from_raw_parts(1usize as *const u16, 0); + #[cfg(toolarge)] + let _s: &[u16] = std::slice::from_raw_parts(2usize as *const u16, isize::MAX as usize); + } +} diff --git a/tests/ui/precondition-checks/slice-get_unchecked.rs b/tests/ui/precondition-checks/slice-get_unchecked.rs new file mode 100644 index 00000000000..1d8188fb953 --- /dev/null +++ b/tests/ui/precondition-checks/slice-get_unchecked.rs @@ -0,0 +1,20 @@ +//@ run-fail +//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes +//@ error-pattern: unsafe precondition(s) violated: slice::get_unchecked requires +//@ revisions: usize range range_to range_from backwards_range + +fn main() { + unsafe { + let s = &[0]; + #[cfg(usize)] + s.get_unchecked(1); + #[cfg(range)] + s.get_unchecked(1..2); + #[cfg(range_to)] + s.get_unchecked(..2); + #[cfg(range_from)] + s.get_unchecked(2..); + #[cfg(backwards_range)] + s.get_unchecked(1..0); + } +} diff --git a/tests/ui/precondition-checks/slice-get_unchecked_mut.rs b/tests/ui/precondition-checks/slice-get_unchecked_mut.rs new file mode 100644 index 00000000000..34c1454af43 --- /dev/null +++ b/tests/ui/precondition-checks/slice-get_unchecked_mut.rs @@ -0,0 +1,20 @@ +//@ run-fail +//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes +//@ error-pattern: unsafe precondition(s) violated: slice::get_unchecked_mut requires +//@ revisions: usize range range_to range_from backwards_range + +fn main() { + unsafe { + let mut s = &mut [0]; + #[cfg(usize)] + s.get_unchecked_mut(1); + #[cfg(range)] + s.get_unchecked_mut(1..2); + #[cfg(range_to)] + s.get_unchecked_mut(..2); + #[cfg(range_from)] + s.get_unchecked_mut(2..); + #[cfg(backwards_range)] + s.get_unchecked_mut(1..0); + } +} diff --git a/tests/ui/precondition-checks/slice-swap_unchecked.rs b/tests/ui/precondition-checks/slice-swap_unchecked.rs new file mode 100644 index 00000000000..227a49091ec --- /dev/null +++ b/tests/ui/precondition-checks/slice-swap_unchecked.rs @@ -0,0 +1,14 @@ +//@ run-fail +//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes +//@ error-pattern: index out of bounds: the len is 2 but the index is 2 +//@ revisions: oob_a oob_b + +fn main() { + let mut pair = [0u8; 2]; + unsafe { + #[cfg(oob_a)] + pair.swap(0, 2); + #[cfg(oob_b)] + pair.swap(2, 0); + } +} diff --git a/tests/ui/precondition-checks/str-get_unchecked.rs b/tests/ui/precondition-checks/str-get_unchecked.rs new file mode 100644 index 00000000000..14d17f997ec --- /dev/null +++ b/tests/ui/precondition-checks/str-get_unchecked.rs @@ -0,0 +1,18 @@ +//@ run-fail +//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes +//@ error-pattern: unsafe precondition(s) violated: str::get_unchecked requires +//@ revisions: range range_to range_from backwards_range + +fn main() { + unsafe { + let s = "💅"; + #[cfg(range)] + s.get_unchecked(4..5); + #[cfg(range_to)] + s.get_unchecked(..5); + #[cfg(range_from)] + s.get_unchecked(5..); + #[cfg(backwards_range)] + s.get_unchecked(1..0); + } +} diff --git a/tests/ui/precondition-checks/str-get_unchecked_mut.rs b/tests/ui/precondition-checks/str-get_unchecked_mut.rs new file mode 100644 index 00000000000..ca1b1690055 --- /dev/null +++ b/tests/ui/precondition-checks/str-get_unchecked_mut.rs @@ -0,0 +1,19 @@ +//@ run-fail +//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes +//@ error-pattern: unsafe precondition(s) violated: str::get_unchecked_mut requires +//@ revisions: range range_to range_from backwards_range + +fn main() { + unsafe { + let mut s: String = "💅".chars().collect(); + let mut s: &mut str = &mut s; + #[cfg(range)] + s.get_unchecked_mut(4..5); + #[cfg(range_to)] + s.get_unchecked_mut(..5); + #[cfg(range_from)] + s.get_unchecked_mut(5..); + #[cfg(backwards_range)] + s.get_unchecked_mut(1..0); + } +} diff --git a/tests/ui/precondition-checks/swap-nonoverlapping.rs b/tests/ui/precondition-checks/swap-nonoverlapping.rs new file mode 100644 index 00000000000..52e4a3c870b --- /dev/null +++ b/tests/ui/precondition-checks/swap-nonoverlapping.rs @@ -0,0 +1,25 @@ +//@ run-fail +//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes +//@ error-pattern: unsafe precondition(s) violated: ptr::swap_nonoverlapping requires +//@ revisions: null_src null_dst misaligned_src misaligned_dst overlapping + +use std::ptr; + +fn main() { + let mut src = [0u16; 3]; + let mut dst = [0u16; 3]; + let src = src.as_mut_ptr(); + let dst = dst.as_mut_ptr(); + unsafe { + #[cfg(null_src)] + ptr::swap_nonoverlapping(ptr::null_mut(), dst, 1); + #[cfg(null_dst)] + ptr::swap_nonoverlapping(src, ptr::null_mut(), 1); + #[cfg(misaligned_src)] + ptr::swap_nonoverlapping(src.byte_add(1), dst, 1); + #[cfg(misaligned_dst)] + ptr::swap_nonoverlapping(src, dst.byte_add(1), 1); + #[cfg(overlapping)] + ptr::swap_nonoverlapping(dst, dst.add(1), 2); + } +} diff --git a/tests/ui/precondition-checks/unchecked_add.rs b/tests/ui/precondition-checks/unchecked_add.rs new file mode 100644 index 00000000000..f44a6ea32ad --- /dev/null +++ b/tests/ui/precondition-checks/unchecked_add.rs @@ -0,0 +1,9 @@ +//@ run-fail +//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes +//@ error-pattern: unsafe precondition(s) violated: u8::unchecked_add cannot overflow + +fn main() { + unsafe { + 1u8.unchecked_add(u8::MAX); + } +} diff --git a/tests/ui/precondition-checks/unchecked_mul.rs b/tests/ui/precondition-checks/unchecked_mul.rs new file mode 100644 index 00000000000..66655dda136 --- /dev/null +++ b/tests/ui/precondition-checks/unchecked_mul.rs @@ -0,0 +1,9 @@ +//@ run-fail +//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes +//@ error-pattern: unsafe precondition(s) violated: u8::unchecked_add cannot overflow + +fn main() { + unsafe { + 2u8.unchecked_add(u8::MAX); + } +} diff --git a/tests/ui/precondition-checks/unchecked_shl.rs b/tests/ui/precondition-checks/unchecked_shl.rs new file mode 100644 index 00000000000..1c96db0b1ec --- /dev/null +++ b/tests/ui/precondition-checks/unchecked_shl.rs @@ -0,0 +1,11 @@ +//@ run-fail +//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes +//@ error-pattern: unsafe precondition(s) violated: u8::unchecked_shl cannot overflow + +#![feature(unchecked_shifts)] + +fn main() { + unsafe { + 0u8.unchecked_shl(u8::BITS); + } +} diff --git a/tests/ui/precondition-checks/unchecked_shr.rs b/tests/ui/precondition-checks/unchecked_shr.rs new file mode 100644 index 00000000000..4a6d9ffb1d3 --- /dev/null +++ b/tests/ui/precondition-checks/unchecked_shr.rs @@ -0,0 +1,11 @@ +//@ run-fail +//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes +//@ error-pattern: unsafe precondition(s) violated: u8::unchecked_shr cannot overflow + +#![feature(unchecked_shifts)] + +fn main() { + unsafe { + 0u8.unchecked_shr(u8::BITS); + } +} diff --git a/tests/ui/precondition-checks/unchecked_sub.rs b/tests/ui/precondition-checks/unchecked_sub.rs new file mode 100644 index 00000000000..545dde0e278 --- /dev/null +++ b/tests/ui/precondition-checks/unchecked_sub.rs @@ -0,0 +1,9 @@ +//@ run-fail +//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes +//@ error-pattern: unsafe precondition(s) violated: u8::unchecked_sub cannot overflow + +fn main() { + unsafe { + 0u8.unchecked_sub(1u8); + } +} diff --git a/tests/ui/precondition-checks/unreachable_unchecked.rs b/tests/ui/precondition-checks/unreachable_unchecked.rs new file mode 100644 index 00000000000..2435450c4b5 --- /dev/null +++ b/tests/ui/precondition-checks/unreachable_unchecked.rs @@ -0,0 +1,9 @@ +//@ run-fail +//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes +//@ error-pattern: unsafe precondition(s) violated: hint::unreachable_unchecked must never be reached + +fn main() { + unsafe { + std::hint::unreachable_unchecked(); + } +} diff --git a/tests/ui/precondition-checks/write.rs b/tests/ui/precondition-checks/write.rs new file mode 100644 index 00000000000..f76e776fcf3 --- /dev/null +++ b/tests/ui/precondition-checks/write.rs @@ -0,0 +1,18 @@ +//@ run-fail +//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes +//@ error-pattern: unsafe precondition(s) violated: ptr::write requires +//@ revisions: null misaligned +//@ ignore-test + +use std::ptr; + +fn main() { + let mut dst = [0u16; 2]; + let mut dst = dst.as_mut_ptr(); + unsafe { + #[cfg(null)] + ptr::write(ptr::null_mut::(), 1u8); + #[cfg(misaligned)] + ptr::write(dst.byte_add(1), 1u16); + } +} diff --git a/tests/ui/precondition-checks/write_bytes.rs b/tests/ui/precondition-checks/write_bytes.rs new file mode 100644 index 00000000000..3f64be9d1ee --- /dev/null +++ b/tests/ui/precondition-checks/write_bytes.rs @@ -0,0 +1,18 @@ +//@ run-fail +//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes +//@ error-pattern: unsafe precondition(s) violated: ptr::write requires +//@ revisions: null misaligned +//@ ignore-test + +use std::ptr; + +fn main() { + let mut dst = [0u16; 2]; + let mut dst = dst.as_mut_ptr(); + unsafe { + #[cfg(null)] + ptr::write_bytes(ptr::null_mut::(), 1u8, 2); + #[cfg(misaligned)] + ptr::write_bytes(dst.byte_add(1), 1u8, 2); + } +} diff --git a/tests/ui/precondition-checks/write_volatile.rs b/tests/ui/precondition-checks/write_volatile.rs new file mode 100644 index 00000000000..ac0b89b5ecf --- /dev/null +++ b/tests/ui/precondition-checks/write_volatile.rs @@ -0,0 +1,17 @@ +//@ run-fail +//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes +//@ error-pattern: unsafe precondition(s) violated: ptr::write_volatile requires +//@ revisions: null misaligned + +use std::ptr; + +fn main() { + let mut dst = [0u16; 2]; + let mut dst = dst.as_mut_ptr(); + unsafe { + #[cfg(null)] + ptr::write_volatile(ptr::null_mut::(), 1u8); + #[cfg(misaligned)] + ptr::write_volatile(dst.byte_add(1), 1u16); + } +} From aec09a43efed613ed12e32cef5d1bd94750e04eb Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Wed, 9 Oct 2024 18:34:33 -0400 Subject: [PATCH 139/357] Clean up is_aligned_and_not_null --- library/core/src/ub_checks.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/core/src/ub_checks.rs b/library/core/src/ub_checks.rs index 2ea30e77609..daaaf5a7195 100644 --- a/library/core/src/ub_checks.rs +++ b/library/core/src/ub_checks.rs @@ -109,15 +109,15 @@ pub(crate) const fn check_language_ub() -> bool { intrinsics::ub_checks() && const_eval_select((), comptime, runtime) } -/// Checks whether `ptr` is properly aligned with respect to -/// `align_of::()`. +/// Checks whether `ptr` is properly aligned with respect to the given alignment, and +/// if `is_zst == false`, that `ptr` is not null. /// /// In `const` this is approximate and can fail spuriously. It is primarily intended /// for `assert_unsafe_precondition!` with `check_language_ub`, in which case the /// check is anyway not executed in `const`. #[inline] pub(crate) const fn is_aligned_and_not_null(ptr: *const (), align: usize, is_zst: bool) -> bool { - if is_zst { ptr.is_aligned_to(align) } else { !ptr.is_null() && ptr.is_aligned_to(align) } + ptr.is_aligned_to(align) && (is_zst || !ptr.is_null()) } #[inline] From a3606d7ee3dd9d910578a81b2992e61521b1ce21 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Wed, 9 Oct 2024 18:46:06 -0400 Subject: [PATCH 140/357] Add a test for zero-sized writes through null --- .../ui/precondition-checks/zero-size-null.rs | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 tests/ui/precondition-checks/zero-size-null.rs diff --git a/tests/ui/precondition-checks/zero-size-null.rs b/tests/ui/precondition-checks/zero-size-null.rs new file mode 100644 index 00000000000..43a81175f94 --- /dev/null +++ b/tests/ui/precondition-checks/zero-size-null.rs @@ -0,0 +1,21 @@ +// Test that none of the precondition checks panic on zero-sized reads or writes through null. + +//@ run-pass +//@ compile-flags: -Zmir-opt-level=0 -Copt-level=0 -Cdebug-assertions=yes + +use std::ptr; + +fn main() { + unsafe { + ptr::copy_nonoverlapping::(ptr::null(), ptr::null_mut(), 0); + ptr::copy_nonoverlapping::<()>(ptr::null(), ptr::null_mut(), 123); + ptr::copy::(ptr::null(), ptr::null_mut(), 0); + ptr::copy::<()>(ptr::null(), ptr::null_mut(), 123); + ptr::swap::<()>(ptr::null_mut(), ptr::null_mut()); + ptr::replace::<()>(ptr::null_mut(), ()); + ptr::read::<()>(ptr::null()); + ptr::write::<()>(ptr::null_mut(), ()); + ptr::read_volatile::<()>(ptr::null()); + ptr::write_volatile::<()>(ptr::null_mut(), ()); + } +} From d6aaf7b036868c29e74ec380493f81ecbd1a4503 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Thu, 10 Oct 2024 03:38:10 +0200 Subject: [PATCH 141/357] Avoid redundant -Wl,-dylib flag when linking --- compiler/rustc_codegen_ssa/src/back/linker.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index 3f3d305da01..c4bb82d0dd7 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -404,12 +404,14 @@ impl<'a> GccLinker<'a> { fn build_dylib(&mut self, crate_type: CrateType, out_filename: &Path) { // On mac we need to tell the linker to let this library be rpathed if self.sess.target.is_like_osx { - if !self.is_ld { + if self.is_cc() { + // `-dynamiclib` makes `cc` pass `-dylib` to the linker. self.cc_arg("-dynamiclib"); + } else { + self.link_arg("-dylib"); + // Clang also sets `-dynamic`, but that's implied by `-dylib`, so unnecessary. } - self.link_arg("-dylib"); - // Note that the `osx_rpath_install_name` option here is a hack // purely to support bootstrap right now, we should get a more // principled solution at some point to force the compiler to pass From 09b634a4ba72336f1de2e3f5dccadd6e5bc3a011 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Thu, 10 Oct 2024 04:03:48 +0200 Subject: [PATCH 142/357] Fix hardcoded strip path when cross-compiling from Linux to Darwin --- compiler/rustc_codegen_ssa/src/back/link.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index e7b1c63a822..34dc599e4fd 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1087,7 +1087,9 @@ fn link_natively( let strip = sess.opts.cg.strip; if sess.target.is_like_osx { - let stripcmd = "/usr/bin/strip"; + // Use system `strip` when running on host macOS. + // + let stripcmd = if cfg!(target_os = "macos") { "/usr/bin/strip" } else { "strip" }; match (strip, crate_type) { (Strip::Debuginfo, _) => { strip_symbols_with_external_utility(sess, stripcmd, out_filename, Some("-S")) From 2a8f08083f32ed64fb367282b4896ee792f0c4a8 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 10 Oct 2024 00:20:37 -0400 Subject: [PATCH 143/357] Structurallyresolve adts and tuples expectations too --- compiler/rustc_hir_typeck/src/expr.rs | 4 +-- .../traits/next-solver/typeck/guide-ctors.rs | 32 +++++++++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) create mode 100644 tests/ui/traits/next-solver/typeck/guide-ctors.rs diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 95ca3e66472..c5b7fc1eabd 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -1783,7 +1783,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr: &'tcx hir::Expr<'tcx>, ) -> Ty<'tcx> { let flds = expected.only_has_type(self).and_then(|ty| { - let ty = self.resolve_vars_with_obligations(ty); + let ty = self.try_structurally_resolve_type(expr.span, ty); match ty.kind() { ty::Tuple(flds) => Some(&flds[..]), _ => None, @@ -1861,7 +1861,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) { let tcx = self.tcx; - let adt_ty = self.resolve_vars_with_obligations(adt_ty); + let adt_ty = self.try_structurally_resolve_type(span, adt_ty); let adt_ty_hint = expected.only_has_type(self).and_then(|expected| { self.fudge_inference_if_ok(|| { let ocx = ObligationCtxt::new(self); diff --git a/tests/ui/traits/next-solver/typeck/guide-ctors.rs b/tests/ui/traits/next-solver/typeck/guide-ctors.rs new file mode 100644 index 00000000000..7432ea78a56 --- /dev/null +++ b/tests/ui/traits/next-solver/typeck/guide-ctors.rs @@ -0,0 +1,32 @@ +//@ compile-flags: -Znext-solver +//@ check-pass + +// Makes sure we structurally normalize before trying to use expectation to guide +// coercion in adt and tuples. + +use std::any::Any; + +trait Coerce { + type Assoc; +} + +struct TupleGuidance; +impl Coerce for TupleGuidance { + type Assoc = (&'static dyn Any,); +} + +struct AdtGuidance; +impl Coerce for AdtGuidance { + type Assoc = Adt<&'static dyn Any>; +} + +struct Adt { + f: T, +} + +fn foo<'a, T: Coerce>(_: T::Assoc) {} + +fn main() { + foo::((&0u32,)); + foo::(Adt { f: &0u32 }); +} From e48159953692320c4866c960e144f7af5551c998 Mon Sep 17 00:00:00 2001 From: Jacob Pratt Date: Thu, 10 Oct 2024 01:09:13 -0400 Subject: [PATCH 144/357] Add myself back to review rotation --- triagebot.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/triagebot.toml b/triagebot.toml index d3e4af9b718..231a7bba1f7 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -923,7 +923,6 @@ contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html" users_on_vacation = [ "BoxyUwU", "fmease", - "jhpratt", "jyn514", "oli-obk", ] From eb76079911b3011e6c41bd69bc6536ad442c2cd2 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 10 Oct 2024 07:53:16 +0200 Subject: [PATCH 145/357] epoll event adding: no need to join, there's no old clock here --- src/tools/miri/src/shims/unix/linux/epoll.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/src/shims/unix/linux/epoll.rs b/src/tools/miri/src/shims/unix/linux/epoll.rs index cc6b9e94f36..9ff7dbbdf84 100644 --- a/src/tools/miri/src/shims/unix/linux/epoll.rs +++ b/src/tools/miri/src/shims/unix/linux/epoll.rs @@ -626,7 +626,7 @@ fn check_and_update_one_event_interest<'tcx>( let mut event_instance = EpollEventInstance::new(flags, epoll_event_interest.data); // If we are tracking data races, remember the current clock so we can sync with it later. ecx.release_clock(|clock| { - event_instance.clock.join(clock); + event_instance.clock.clone_from(clock); }); // Triggers the notification by inserting it to the ready list. ready_list.insert(epoll_key, event_instance); From b198a4666505a94efbd0a5fb443bb3cf8997be9a Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Thu, 10 Oct 2024 08:54:23 +0300 Subject: [PATCH 146/357] disable `download-rustc` if LLVM submodule has changes in CI Signed-off-by: onur-ozkan --- src/bootstrap/src/core/config/config.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 9f84b492b80..3f025a198cb 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -2399,6 +2399,20 @@ impl Config { Some(commit) => { self.download_ci_rustc(commit); + // CI-rustc can't be used without CI-LLVM. If `self.llvm_from_ci` is false, it means the "if-unchanged" + // logic has detected some changes in the LLVM submodule (download-ci-llvm=false can't happen here as + // we don't allow it while parsing the configuration). + if !self.llvm_from_ci { + // This happens when LLVM submodule is updated in CI, we should disable ci-rustc without an error + // to not break CI. For non-CI environments, we should return an error. + if CiEnv::is_ci() { + println!("WARNING: LLVM submodule has changes, `download-rustc` will be disabled."); + return None; + } else { + panic!("ERROR: LLVM submodule has changes, `download-rustc` can't be used."); + } + } + if let Some(config_path) = &self.config { let ci_config_toml = match self.get_builder_toml("ci-rustc") { Ok(ci_config_toml) => ci_config_toml, From 7e21dce98c795f98d781894a9180cfcb59b3cd97 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 8 Oct 2024 08:46:14 +0200 Subject: [PATCH 147/357] remove handle_unsupported_foreign_item helper --- src/tools/miri/src/helpers.rs | 16 ---------------- src/tools/miri/src/shims/foreign_items.rs | 12 +++++++++--- .../miri/src/shims/unix/linux/foreign_items.rs | 5 +---- .../miri/tests/panic/unsupported_syscall.rs | 9 --------- .../miri/tests/panic/unsupported_syscall.stderr | 4 ---- 5 files changed, 10 insertions(+), 36 deletions(-) delete mode 100644 src/tools/miri/tests/panic/unsupported_syscall.rs delete mode 100644 src/tools/miri/tests/panic/unsupported_syscall.stderr diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index 013bfe03aaf..8bd429deefc 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -14,7 +14,6 @@ use rustc_index::IndexVec; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::middle::dependency_format::Linkage; use rustc_middle::middle::exported_symbols::ExportedSymbol; -use rustc_middle::mir; use rustc_middle::ty::layout::{FnAbiOf, LayoutOf, MaybeResult, TyAndLayout}; use rustc_middle::ty::{self, FloatTy, IntTy, Ty, TyCtxt, UintTy}; use rustc_session::config::CrateType; @@ -949,21 +948,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { crate_name == "std" || crate_name == "std_miri_test" } - /// Handler that should be called when an unsupported foreign item is encountered. - /// This function will either panic within the context of the emulated application - /// or return an error in the Miri process context - fn handle_unsupported_foreign_item(&mut self, error_msg: String) -> InterpResult<'tcx, ()> { - let this = self.eval_context_mut(); - if this.machine.panic_on_unsupported { - // message is slightly different here to make automated analysis easier - let error_msg = format!("unsupported Miri functionality: {error_msg}"); - this.start_panic(error_msg.as_ref(), mir::UnwindAction::Continue)?; - interp_ok(()) - } else { - throw_machine_stop!(TerminationInfo::UnsupportedForeignItem(error_msg)); - } - } - fn check_abi_and_shim_symbol_clash( &mut self, abi: Abi, diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index 78b07f68b44..1a6c5e9112f 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -83,11 +83,17 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { return interp_ok(Some(body)); } - this.handle_unsupported_foreign_item(format!( + let error_msg = format!( "can't call foreign function `{link_name}` on OS `{os}`", os = this.tcx.sess.target.os, - ))?; - return interp_ok(None); + ); + if this.machine.panic_on_unsupported { + // message is slightly different here to make automated analysis easier + let error_msg = format!("unsupported Miri functionality: {error_msg}"); + this.start_panic(error_msg.as_ref(), mir::UnwindAction::Continue)?; + } else { + throw_machine_stop!(TerminationInfo::UnsupportedForeignItem(error_msg)); + } } } diff --git a/src/tools/miri/src/shims/unix/linux/foreign_items.rs b/src/tools/miri/src/shims/unix/linux/foreign_items.rs index 2a72004378e..2f3e1f29dd2 100644 --- a/src/tools/miri/src/shims/unix/linux/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/linux/foreign_items.rs @@ -168,10 +168,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_int(result.to_i32()?, dest)?; } id => { - this.handle_unsupported_foreign_item(format!( - "can't execute syscall with ID {id}" - ))?; - return interp_ok(EmulateItemResult::AlreadyJumped); + throw_unsup_format!("can't execute syscall with ID {id}"); } } } diff --git a/src/tools/miri/tests/panic/unsupported_syscall.rs b/src/tools/miri/tests/panic/unsupported_syscall.rs deleted file mode 100644 index bbb076b169a..00000000000 --- a/src/tools/miri/tests/panic/unsupported_syscall.rs +++ /dev/null @@ -1,9 +0,0 @@ -//@ignore-target: windows # no `syscall` on Windows -//@ignore-target: apple # `syscall` is not supported on macOS -//@compile-flags: -Zmiri-panic-on-unsupported - -fn main() { - unsafe { - libc::syscall(0); - } -} diff --git a/src/tools/miri/tests/panic/unsupported_syscall.stderr b/src/tools/miri/tests/panic/unsupported_syscall.stderr deleted file mode 100644 index e9b2b5b6652..00000000000 --- a/src/tools/miri/tests/panic/unsupported_syscall.stderr +++ /dev/null @@ -1,4 +0,0 @@ -thread 'main' panicked at tests/panic/unsupported_syscall.rs:LL:CC: -unsupported Miri functionality: can't execute syscall with ID 0 -note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect From 9e2688c5f5993c7fb66fd0e092aec57581fbecec Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 10 Oct 2024 08:32:17 +0200 Subject: [PATCH 148/357] remove -Zmiri-panic-on-unsupported flag --- src/tools/miri/README.md | 5 ----- src/tools/miri/src/bin/miri.rs | 2 -- src/tools/miri/src/eval.rs | 3 --- src/tools/miri/src/machine.rs | 7 ------- src/tools/miri/src/shims/foreign_items.rs | 11 ++--------- .../miri/tests/panic/unsupported_foreign_function.rs | 12 ------------ .../tests/panic/unsupported_foreign_function.stderr | 4 ---- 7 files changed, 2 insertions(+), 42 deletions(-) delete mode 100644 src/tools/miri/tests/panic/unsupported_foreign_function.rs delete mode 100644 src/tools/miri/tests/panic/unsupported_foreign_function.stderr diff --git a/src/tools/miri/README.md b/src/tools/miri/README.md index 9a50079bc94..a73fefaaf34 100644 --- a/src/tools/miri/README.md +++ b/src/tools/miri/README.md @@ -392,11 +392,6 @@ to Miri failing to detect cases of undefined behavior in a program. but reports to the program that it did actually write. This is useful when you are not interested in the actual program's output, but only want to see Miri's errors and warnings. -* `-Zmiri-panic-on-unsupported` will make some forms of unsupported functionality, - such as FFI and unsupported syscalls, panic within the context of the emulated - application instead of raising an error within the context of Miri (and halting - execution). Note that code might not expect these operations to ever panic, so - this flag can lead to strange (mis)behavior. * `-Zmiri-recursive-validation` is a *highly experimental* flag that makes validity checking recurse below references. * `-Zmiri-retag-fields[=]` controls when Stacked Borrows retagging recurses into diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs index 8d3ae97e0e9..717229ba8b3 100644 --- a/src/tools/miri/src/bin/miri.rs +++ b/src/tools/miri/src/bin/miri.rs @@ -530,8 +530,6 @@ fn main() { } else if arg == "-Zmiri-ignore-leaks" { miri_config.ignore_leaks = true; miri_config.collect_leak_backtraces = false; - } else if arg == "-Zmiri-panic-on-unsupported" { - miri_config.panic_on_unsupported = true; } else if arg == "-Zmiri-strict-provenance" { miri_config.provenance_mode = ProvenanceMode::Strict; } else if arg == "-Zmiri-permissive-provenance" { diff --git a/src/tools/miri/src/eval.rs b/src/tools/miri/src/eval.rs index ece76e581f2..75dce211dd4 100644 --- a/src/tools/miri/src/eval.rs +++ b/src/tools/miri/src/eval.rs @@ -129,8 +129,6 @@ pub struct MiriConfig { /// If `Some`, enable the `measureme` profiler, writing results to a file /// with the specified prefix. pub measureme_out: Option, - /// Panic when unsupported functionality is encountered. - pub panic_on_unsupported: bool, /// Which style to use for printing backtraces. pub backtrace_style: BacktraceStyle, /// Which provenance to use for int2ptr casts @@ -183,7 +181,6 @@ impl Default for MiriConfig { track_outdated_loads: false, cmpxchg_weak_failure_rate: 0.8, // 80% measureme_out: None, - panic_on_unsupported: false, backtrace_style: BacktraceStyle::Short, provenance_mode: ProvenanceMode::Default, mute_stdout_stderr: false, diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index b9cebcfe9cd..0d28a4ed3e4 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -496,11 +496,6 @@ pub struct MiriMachine<'tcx> { /// `None` means no `Instance` exported under the given name is found. pub(crate) exported_symbols_cache: FxHashMap>>, - /// Whether to raise a panic in the context of the evaluated process when unsupported - /// functionality is encountered. If `false`, an error is propagated in the Miri application context - /// instead (default behavior) - pub(crate) panic_on_unsupported: bool, - /// Equivalent setting as RUST_BACKTRACE on encountering an error. pub(crate) backtrace_style: BacktraceStyle, @@ -667,7 +662,6 @@ impl<'tcx> MiriMachine<'tcx> { profiler, string_cache: Default::default(), exported_symbols_cache: FxHashMap::default(), - panic_on_unsupported: config.panic_on_unsupported, backtrace_style: config.backtrace_style, local_crates, extern_statics: FxHashMap::default(), @@ -807,7 +801,6 @@ impl VisitProvenance for MiriMachine<'_> { profiler: _, string_cache: _, exported_symbols_cache: _, - panic_on_unsupported: _, backtrace_style: _, local_crates: _, rng: _, diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index 1a6c5e9112f..7fce5b63306 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -83,17 +83,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { return interp_ok(Some(body)); } - let error_msg = format!( + throw_machine_stop!(TerminationInfo::UnsupportedForeignItem(format!( "can't call foreign function `{link_name}` on OS `{os}`", os = this.tcx.sess.target.os, - ); - if this.machine.panic_on_unsupported { - // message is slightly different here to make automated analysis easier - let error_msg = format!("unsupported Miri functionality: {error_msg}"); - this.start_panic(error_msg.as_ref(), mir::UnwindAction::Continue)?; - } else { - throw_machine_stop!(TerminationInfo::UnsupportedForeignItem(error_msg)); - } + ))); } } diff --git a/src/tools/miri/tests/panic/unsupported_foreign_function.rs b/src/tools/miri/tests/panic/unsupported_foreign_function.rs deleted file mode 100644 index b8301c50772..00000000000 --- a/src/tools/miri/tests/panic/unsupported_foreign_function.rs +++ /dev/null @@ -1,12 +0,0 @@ -//@compile-flags: -Zmiri-panic-on-unsupported -//@normalize-stderr-test: "OS `.*`" -> "$$OS" - -fn main() { - extern "Rust" { - fn foo(); - } - - unsafe { - foo(); - } -} diff --git a/src/tools/miri/tests/panic/unsupported_foreign_function.stderr b/src/tools/miri/tests/panic/unsupported_foreign_function.stderr deleted file mode 100644 index 278af9612d6..00000000000 --- a/src/tools/miri/tests/panic/unsupported_foreign_function.stderr +++ /dev/null @@ -1,4 +0,0 @@ -thread 'main' panicked at tests/panic/unsupported_foreign_function.rs:LL:CC: -unsupported Miri functionality: can't call foreign function `foo` on $OS -note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect From ef5157765691acba2b82e071b0ca4410ed71a252 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Sat, 5 Oct 2024 21:50:21 +0300 Subject: [PATCH 149/357] make `llvm::is_ci_llvm_modified` logic more precise Signed-off-by: onur-ozkan --- src/bootstrap/src/core/build_steps/llvm.rs | 35 +++++++++++++++------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index 30213584157..4b403407a20 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -20,10 +20,9 @@ use build_helper::git::get_closest_merge_commit; use crate::core::builder::{Builder, RunConfig, ShouldRun, Step}; use crate::core::config::{Config, TargetSelection}; -use crate::utils::channel; use crate::utils::exec::command; use crate::utils::helpers::{ - self, HashStamp, exe, get_clang_cl_resource_dir, output, t, unhashed_basename, up_to_date, + self, HashStamp, exe, get_clang_cl_resource_dir, t, unhashed_basename, up_to_date, }; use crate::{CLang, GitRepo, Kind, generate_smart_stamp_hash}; @@ -166,7 +165,7 @@ pub(crate) fn detect_llvm_sha(config: &Config, is_git: bool) -> String { config.src.join("src/version"), ]) .unwrap() - } else if let Some(info) = channel::read_commit_info_file(&config.src) { + } else if let Some(info) = crate::utils::channel::read_commit_info_file(&config.src) { info.sha.trim().to_owned() } else { "".to_owned() @@ -242,15 +241,29 @@ pub(crate) fn is_ci_llvm_available(config: &Config, asserts: bool) -> bool { /// Returns true if we're running in CI with modified LLVM (and thus can't download it) pub(crate) fn is_ci_llvm_modified(config: &Config) -> bool { - CiEnv::is_rust_lang_managed_ci_job() && config.rust_info.is_managed_git_subrepository() && { - // We assume we have access to git, so it's okay to unconditionally pass - // `true` here. - let llvm_sha = detect_llvm_sha(config, true); - let head_sha = - output(helpers::git(Some(&config.src)).arg("rev-parse").arg("HEAD").as_command_mut()); - let head_sha = head_sha.trim(); - llvm_sha == head_sha + // If not running in a CI environment, return false. + if !CiEnv::is_ci() { + return false; } + + // In rust-lang/rust managed CI, assert the existence of the LLVM submodule. + if CiEnv::is_rust_lang_managed_ci_job() { + assert!( + config.in_tree_llvm_info.is_managed_git_subrepository(), + "LLVM submodule must be fetched in rust-lang/rust managed CI builders." + ); + } + // If LLVM submodule isn't present, skip the change check as it won't work. + else if !config.in_tree_llvm_info.is_managed_git_subrepository() { + return false; + } + + let llvm_sha = detect_llvm_sha(config, true); + let head_sha = crate::output( + helpers::git(Some(&config.src)).arg("rev-parse").arg("HEAD").as_command_mut(), + ); + let head_sha = head_sha.trim(); + llvm_sha == head_sha } #[derive(Debug, Clone, Hash, PartialEq, Eq)] From f6b75575e1228762fb1bbe735cb25bf868c48d8b Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Thu, 10 Oct 2024 10:24:41 +0300 Subject: [PATCH 150/357] stabilize `download_ci_llvm` test Signed-off-by: onur-ozkan --- src/bootstrap/src/core/config/tests.rs | 36 ++++++++++---------------- 1 file changed, 14 insertions(+), 22 deletions(-) diff --git a/src/bootstrap/src/core/config/tests.rs b/src/bootstrap/src/core/config/tests.rs index e38d4eac051..01379db500b 100644 --- a/src/bootstrap/src/core/config/tests.rs +++ b/src/bootstrap/src/core/config/tests.rs @@ -20,29 +20,21 @@ fn parse(config: &str) -> Config { #[test] fn download_ci_llvm() { - if crate::core::build_steps::llvm::is_ci_llvm_modified(&parse("")) { - eprintln!("Detected LLVM as non-available: running in CI and modified LLVM in this change"); - return; + assert!(parse("").llvm_from_ci); + assert!(parse("llvm.download-ci-llvm = true").llvm_from_ci); + assert!(!parse("llvm.download-ci-llvm = false").llvm_from_ci); + + let if_unchanged_config = parse("llvm.download-ci-llvm = \"if-unchanged\""); + if if_unchanged_config.llvm_from_ci { + let has_changes = if_unchanged_config + .last_modified_commit(&["src/llvm-project"], "download-ci-llvm", true) + .is_none(); + + assert!( + !has_changes, + "CI LLVM can't be enabled with 'if-unchanged' while there are changes in LLVM submodule." + ); } - - let parse_llvm = |s| parse(s).llvm_from_ci; - let if_unchanged = parse_llvm("llvm.download-ci-llvm = \"if-unchanged\""); - - assert!(parse_llvm("llvm.download-ci-llvm = true")); - assert!(!parse_llvm("llvm.download-ci-llvm = false")); - assert_eq!(parse_llvm(""), if_unchanged); - assert_eq!(parse_llvm("rust.channel = \"dev\""), if_unchanged); - assert!(parse_llvm("rust.channel = \"stable\"")); - assert_eq!(parse_llvm("build.build = \"x86_64-unknown-linux-gnu\""), if_unchanged); - assert_eq!( - parse_llvm( - "llvm.assertions = true \r\n build.build = \"x86_64-unknown-linux-gnu\" \r\n llvm.download-ci-llvm = \"if-unchanged\"" - ), - if_unchanged - ); - assert!(!parse_llvm( - "llvm.assertions = true \r\n build.build = \"aarch64-apple-darwin\" \r\n llvm.download-ci-llvm = \"if-unchanged\"" - )); } // FIXME(onur-ozkan): extend scope of the test From b27aee9b8b21b367d12b499de29023d429b0ba79 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Wed, 9 Oct 2024 22:22:13 +0300 Subject: [PATCH 151/357] stabilize `ci_rustc_if_unchanged_logic` test Signed-off-by: onur-ozkan --- src/bootstrap/src/core/builder/tests.rs | 37 +++++++------------------ 1 file changed, 10 insertions(+), 27 deletions(-) diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index 4ab1ef1ad0f..695a66834d4 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -1,7 +1,5 @@ use std::thread; -use build_helper::git::get_closest_merge_commit; - use super::*; use crate::Flags; use crate::core::build_steps::doc::DocumentationFormat; @@ -214,8 +212,6 @@ fn alias_and_path_for_library() { assert_eq!(first(cache.all::()), &[doc_std!(A => A, stage = 0)]); } -// FIXME: This is failing in various runners in merge CI. -#[ignore] #[test] fn ci_rustc_if_unchanged_logic() { let config = Config::parse_inner( @@ -227,10 +223,6 @@ fn ci_rustc_if_unchanged_logic() { |&_| Ok(Default::default()), ); - if config.rust_info.is_from_tarball() { - return; - } - let build = Build::new(config.clone()); let builder = Builder::new(&build); @@ -240,26 +232,17 @@ fn ci_rustc_if_unchanged_logic() { builder.run_step_descriptions(&Builder::get_step_descriptions(config.cmd.kind()), &[]); - let compiler_path = build.src.join("compiler"); - let library_path = build.src.join("library"); + // Make sure "if-unchanged" logic doesn't try to use CI rustc while there are changes + // in compiler and/or library. + if config.download_rustc_commit.is_some() { + let has_changes = + config.last_modified_commit(&["compiler", "library"], "download-rustc", true).is_none(); - let commit = - get_closest_merge_commit(Some(&builder.config.src), &builder.config.git_config(), &[ - compiler_path.clone(), - library_path.clone(), - ]) - .unwrap(); - - let has_changes = !helpers::git(Some(&builder.src)) - .args(["diff-index", "--quiet", &commit]) - .arg("--") - .args([compiler_path, library_path]) - .as_command_mut() - .status() - .unwrap() - .success(); - - assert!(has_changes == config.download_rustc_commit.is_none()); + assert!( + !has_changes, + "CI-rustc can't be used with 'if-unchanged' while there are changes in compiler and/or library." + ); + } } mod defaults { From de744eafe134a2f0ddde8db1b0d94ec5f8bc1481 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Thu, 10 Oct 2024 08:33:14 +0300 Subject: [PATCH 152/357] update `rustc_borrowck::places_conflict` doc-comment Signed-off-by: onur-ozkan --- compiler/rustc_borrowck/src/places_conflict.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_borrowck/src/places_conflict.rs b/compiler/rustc_borrowck/src/places_conflict.rs index 519ba0b9e0c..679e111caa9 100644 --- a/compiler/rustc_borrowck/src/places_conflict.rs +++ b/compiler/rustc_borrowck/src/places_conflict.rs @@ -3,7 +3,7 @@ //! we can prove overlap one way or another. Essentially, we treat `Overlap` as //! a monoid and report a conflict if the product ends up not being `Disjoint`. //! -//! At each step, if we didn't run out of borrow or place, we know that our elements +//! On each step, if we didn't run out of borrow or place, we know that our elements //! have the same type, and that they only overlap if they are the identical. //! //! For example, if we are comparing these: From a21a9fe3322cf3c3707f6e6ac644dfbe118a66dc Mon Sep 17 00:00:00 2001 From: bors Date: Thu, 10 Oct 2024 09:17:20 +0000 Subject: [PATCH 153/357] Auto merge of #13464 - y21:issue13458, r=flip1995 Don't warn on proc macro generated code in `needless_return` Fixes #13458 Fixes #13457 Fixes #13467 Fixes #13479 Fixes #13481 Fixes #13526 Fixes #13486 The fix is unfortunately a little more convoluted than just simply adding a `is_from_proc_macro`. That check *does* fix the issue, however it also introduces a bunch of false negatives in the tests, specifically when the returned expression is in a different syntax context, e.g. `return format!(..)`. The proc macro check builds up a start and end pattern based on the HIR nodes and compares it to a snippet of the span, however that would currently fail for `return format!(..)` because we would have the patterns `("return", )`, which doesn't compare equal. So we now return an empty string pattern for when it's in a different syntax context. "Hide whitespace" helps a bit for reviewing the proc macro detection change changelog: none --- src/tools/clippy/clippy_lints/src/returns.rs | 2 +- .../clippy_utils/src/check_proc_macro.rs | 135 +++++++++++------- .../clippy/tests/ui/dbg_macro/dbg_macro.fixed | 2 +- .../clippy/tests/ui/dbg_macro/dbg_macro.rs | 2 +- .../clippy/tests/ui/needless_return.fixed | 8 ++ src/tools/clippy/tests/ui/needless_return.rs | 8 ++ .../clippy/tests/ui/needless_return.stderr | 128 ++++++++--------- 7 files changed, 164 insertions(+), 121 deletions(-) diff --git a/src/tools/clippy/clippy_lints/src/returns.rs b/src/tools/clippy/clippy_lints/src/returns.rs index f6f75d8c798..662745e4b5d 100644 --- a/src/tools/clippy/clippy_lints/src/returns.rs +++ b/src/tools/clippy/clippy_lints/src/returns.rs @@ -407,7 +407,7 @@ fn check_final_expr<'tcx>( } } - if ret_span.from_expansion() { + if ret_span.from_expansion() || is_from_proc_macro(cx, expr) { return; } diff --git a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs index b18997e6ee4..bfb3a76ad25 100644 --- a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs +++ b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs @@ -141,62 +141,89 @@ fn path_search_pat(path: &Path<'_>) -> (Pat, Pat) { /// Get the search patterns to use for the given expression fn expr_search_pat(tcx: TyCtxt<'_>, e: &Expr<'_>) -> (Pat, Pat) { - match e.kind { - ExprKind::ConstBlock(_) => (Pat::Str("const"), Pat::Str("}")), - // Parenthesis are trimmed from the text before the search patterns are matched. - // See: `span_matches_pat` - ExprKind::Tup([]) => (Pat::Str(")"), Pat::Str("(")), - ExprKind::Unary(UnOp::Deref, e) => (Pat::Str("*"), expr_search_pat(tcx, e).1), - ExprKind::Unary(UnOp::Not, e) => (Pat::Str("!"), expr_search_pat(tcx, e).1), - ExprKind::Unary(UnOp::Neg, e) => (Pat::Str("-"), expr_search_pat(tcx, e).1), - ExprKind::Lit(lit) => lit_search_pat(&lit.node), - ExprKind::Array(_) | ExprKind::Repeat(..) => (Pat::Str("["), Pat::Str("]")), - ExprKind::Call(e, []) | ExprKind::MethodCall(_, e, [], _) => (expr_search_pat(tcx, e).0, Pat::Str("(")), - ExprKind::Call(first, [.., last]) - | ExprKind::MethodCall(_, first, [.., last], _) - | ExprKind::Binary(_, first, last) - | ExprKind::Tup([first, .., last]) - | ExprKind::Assign(first, last, _) - | ExprKind::AssignOp(_, first, last) => (expr_search_pat(tcx, first).0, expr_search_pat(tcx, last).1), - ExprKind::Tup([e]) | ExprKind::DropTemps(e) => expr_search_pat(tcx, e), - ExprKind::Cast(e, _) | ExprKind::Type(e, _) => (expr_search_pat(tcx, e).0, Pat::Str("")), - ExprKind::Let(let_expr) => (Pat::Str("let"), expr_search_pat(tcx, let_expr.init).1), - ExprKind::If(..) => (Pat::Str("if"), Pat::Str("}")), - ExprKind::Loop(_, Some(_), _, _) | ExprKind::Block(_, Some(_)) => (Pat::Str("'"), Pat::Str("}")), - ExprKind::Loop(_, None, LoopSource::Loop, _) => (Pat::Str("loop"), Pat::Str("}")), - ExprKind::Loop(_, None, LoopSource::While, _) => (Pat::Str("while"), Pat::Str("}")), - ExprKind::Loop(_, None, LoopSource::ForLoop, _) | ExprKind::Match(_, _, MatchSource::ForLoopDesugar) => { - (Pat::Str("for"), Pat::Str("}")) - }, - ExprKind::Match(_, _, MatchSource::Normal) => (Pat::Str("match"), Pat::Str("}")), - ExprKind::Match(e, _, MatchSource::TryDesugar(_)) => (expr_search_pat(tcx, e).0, Pat::Str("?")), - ExprKind::Match(e, _, MatchSource::AwaitDesugar) | ExprKind::Yield(e, YieldSource::Await { .. }) => { - (expr_search_pat(tcx, e).0, Pat::Str("await")) - }, - ExprKind::Closure(&Closure { body, .. }) => (Pat::Str(""), expr_search_pat(tcx, tcx.hir().body(body).value).1), - ExprKind::Block( - Block { - rules: BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided), - .. + fn expr_search_pat_inner(tcx: TyCtxt<'_>, e: &Expr<'_>, outer_span: Span) -> (Pat, Pat) { + // The expression can have subexpressions in different contexts, in which case + // building up a search pattern from the macro expansion would lead to false positives; + // e.g. `return format!(..)` would be considered to be from a proc macro + // if we build up a pattern for the macro expansion and compare it to the invocation `format!()`. + // So instead we return an empty pattern such that `span_matches_pat` always returns true. + if !e.span.eq_ctxt(outer_span) { + return (Pat::Str(""), Pat::Str("")); + } + + match e.kind { + ExprKind::ConstBlock(_) => (Pat::Str("const"), Pat::Str("}")), + // Parenthesis are trimmed from the text before the search patterns are matched. + // See: `span_matches_pat` + ExprKind::Tup([]) => (Pat::Str(")"), Pat::Str("(")), + ExprKind::Unary(UnOp::Deref, e) => (Pat::Str("*"), expr_search_pat_inner(tcx, e, outer_span).1), + ExprKind::Unary(UnOp::Not, e) => (Pat::Str("!"), expr_search_pat_inner(tcx, e, outer_span).1), + ExprKind::Unary(UnOp::Neg, e) => (Pat::Str("-"), expr_search_pat_inner(tcx, e, outer_span).1), + ExprKind::Lit(lit) => lit_search_pat(&lit.node), + ExprKind::Array(_) | ExprKind::Repeat(..) => (Pat::Str("["), Pat::Str("]")), + ExprKind::Call(e, []) | ExprKind::MethodCall(_, e, [], _) => { + (expr_search_pat_inner(tcx, e, outer_span).0, Pat::Str("(")) }, - None, - ) => (Pat::Str("unsafe"), Pat::Str("}")), - ExprKind::Block(_, None) => (Pat::Str("{"), Pat::Str("}")), - ExprKind::Field(e, name) => (expr_search_pat(tcx, e).0, Pat::Sym(name.name)), - ExprKind::Index(e, _, _) => (expr_search_pat(tcx, e).0, Pat::Str("]")), - ExprKind::Path(ref path) => qpath_search_pat(path), - ExprKind::AddrOf(_, _, e) => (Pat::Str("&"), expr_search_pat(tcx, e).1), - ExprKind::Break(Destination { label: None, .. }, None) => (Pat::Str("break"), Pat::Str("break")), - ExprKind::Break(Destination { label: Some(name), .. }, None) => (Pat::Str("break"), Pat::Sym(name.ident.name)), - ExprKind::Break(_, Some(e)) => (Pat::Str("break"), expr_search_pat(tcx, e).1), - ExprKind::Continue(Destination { label: None, .. }) => (Pat::Str("continue"), Pat::Str("continue")), - ExprKind::Continue(Destination { label: Some(name), .. }) => (Pat::Str("continue"), Pat::Sym(name.ident.name)), - ExprKind::Ret(None) => (Pat::Str("return"), Pat::Str("return")), - ExprKind::Ret(Some(e)) => (Pat::Str("return"), expr_search_pat(tcx, e).1), - ExprKind::Struct(path, _, _) => (qpath_search_pat(path).0, Pat::Str("}")), - ExprKind::Yield(e, YieldSource::Yield) => (Pat::Str("yield"), expr_search_pat(tcx, e).1), - _ => (Pat::Str(""), Pat::Str("")), + ExprKind::Call(first, [.., last]) + | ExprKind::MethodCall(_, first, [.., last], _) + | ExprKind::Binary(_, first, last) + | ExprKind::Tup([first, .., last]) + | ExprKind::Assign(first, last, _) + | ExprKind::AssignOp(_, first, last) => ( + expr_search_pat_inner(tcx, first, outer_span).0, + expr_search_pat_inner(tcx, last, outer_span).1, + ), + ExprKind::Tup([e]) | ExprKind::DropTemps(e) => expr_search_pat_inner(tcx, e, outer_span), + ExprKind::Cast(e, _) | ExprKind::Type(e, _) => (expr_search_pat_inner(tcx, e, outer_span).0, Pat::Str("")), + ExprKind::Let(let_expr) => (Pat::Str("let"), expr_search_pat_inner(tcx, let_expr.init, outer_span).1), + ExprKind::If(..) => (Pat::Str("if"), Pat::Str("}")), + ExprKind::Loop(_, Some(_), _, _) | ExprKind::Block(_, Some(_)) => (Pat::Str("'"), Pat::Str("}")), + ExprKind::Loop(_, None, LoopSource::Loop, _) => (Pat::Str("loop"), Pat::Str("}")), + ExprKind::Loop(_, None, LoopSource::While, _) => (Pat::Str("while"), Pat::Str("}")), + ExprKind::Loop(_, None, LoopSource::ForLoop, _) | ExprKind::Match(_, _, MatchSource::ForLoopDesugar) => { + (Pat::Str("for"), Pat::Str("}")) + }, + ExprKind::Match(_, _, MatchSource::Normal) => (Pat::Str("match"), Pat::Str("}")), + ExprKind::Match(e, _, MatchSource::TryDesugar(_)) => { + (expr_search_pat_inner(tcx, e, outer_span).0, Pat::Str("?")) + }, + ExprKind::Match(e, _, MatchSource::AwaitDesugar) | ExprKind::Yield(e, YieldSource::Await { .. }) => { + (expr_search_pat_inner(tcx, e, outer_span).0, Pat::Str("await")) + }, + ExprKind::Closure(&Closure { body, .. }) => ( + Pat::Str(""), + expr_search_pat_inner(tcx, tcx.hir().body(body).value, outer_span).1, + ), + ExprKind::Block( + Block { + rules: BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided), + .. + }, + None, + ) => (Pat::Str("unsafe"), Pat::Str("}")), + ExprKind::Block(_, None) => (Pat::Str("{"), Pat::Str("}")), + ExprKind::Field(e, name) => (expr_search_pat_inner(tcx, e, outer_span).0, Pat::Sym(name.name)), + ExprKind::Index(e, _, _) => (expr_search_pat_inner(tcx, e, outer_span).0, Pat::Str("]")), + ExprKind::Path(ref path) => qpath_search_pat(path), + ExprKind::AddrOf(_, _, e) => (Pat::Str("&"), expr_search_pat_inner(tcx, e, outer_span).1), + ExprKind::Break(Destination { label: None, .. }, None) => (Pat::Str("break"), Pat::Str("break")), + ExprKind::Break(Destination { label: Some(name), .. }, None) => { + (Pat::Str("break"), Pat::Sym(name.ident.name)) + }, + ExprKind::Break(_, Some(e)) => (Pat::Str("break"), expr_search_pat_inner(tcx, e, outer_span).1), + ExprKind::Continue(Destination { label: None, .. }) => (Pat::Str("continue"), Pat::Str("continue")), + ExprKind::Continue(Destination { label: Some(name), .. }) => { + (Pat::Str("continue"), Pat::Sym(name.ident.name)) + }, + ExprKind::Ret(None) => (Pat::Str("return"), Pat::Str("return")), + ExprKind::Ret(Some(e)) => (Pat::Str("return"), expr_search_pat_inner(tcx, e, outer_span).1), + ExprKind::Struct(path, _, _) => (qpath_search_pat(path).0, Pat::Str("}")), + ExprKind::Yield(e, YieldSource::Yield) => (Pat::Str("yield"), expr_search_pat_inner(tcx, e, outer_span).1), + _ => (Pat::Str(""), Pat::Str("")), + } } + + expr_search_pat_inner(tcx, e, e.span) } fn fn_header_search_pat(header: FnHeader) -> Pat { diff --git a/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.fixed b/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.fixed index e3525191423..bda9221a5e1 100644 --- a/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.fixed +++ b/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.fixed @@ -1,5 +1,5 @@ #![warn(clippy::dbg_macro)] -#![allow(clippy::unnecessary_operation, clippy::no_effect)] +#![allow(clippy::unnecessary_operation, clippy::no_effect, clippy::unit_arg)] fn foo(n: u32) -> u32 { if let Some(n) = n.checked_sub(4) { n } else { n } diff --git a/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.rs b/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.rs index 80606c2db05..8244254026b 100644 --- a/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.rs +++ b/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.rs @@ -1,5 +1,5 @@ #![warn(clippy::dbg_macro)] -#![allow(clippy::unnecessary_operation, clippy::no_effect)] +#![allow(clippy::unnecessary_operation, clippy::no_effect, clippy::unit_arg)] fn foo(n: u32) -> u32 { if let Some(n) = dbg!(n.checked_sub(4)) { n } else { n } diff --git a/src/tools/clippy/tests/ui/needless_return.fixed b/src/tools/clippy/tests/ui/needless_return.fixed index ca422e605d6..aa2a274525b 100644 --- a/src/tools/clippy/tests/ui/needless_return.fixed +++ b/src/tools/clippy/tests/ui/needless_return.fixed @@ -1,3 +1,4 @@ +//@aux-build:proc_macros.rs #![feature(yeet_expr)] #![allow(unused)] #![allow( @@ -9,6 +10,9 @@ )] #![warn(clippy::needless_return)] +extern crate proc_macros; +use proc_macros::with_span; + use std::cell::RefCell; macro_rules! the_answer { @@ -359,6 +363,10 @@ fn issue12907() -> String { "".split("").next().unwrap().to_string() } +fn issue13458() { + with_span!(span return); +} + fn main() {} fn a(x: Option) -> Option { diff --git a/src/tools/clippy/tests/ui/needless_return.rs b/src/tools/clippy/tests/ui/needless_return.rs index aad6e13136f..bf67cfd3698 100644 --- a/src/tools/clippy/tests/ui/needless_return.rs +++ b/src/tools/clippy/tests/ui/needless_return.rs @@ -1,3 +1,4 @@ +//@aux-build:proc_macros.rs #![feature(yeet_expr)] #![allow(unused)] #![allow( @@ -9,6 +10,9 @@ )] #![warn(clippy::needless_return)] +extern crate proc_macros; +use proc_macros::with_span; + use std::cell::RefCell; macro_rules! the_answer { @@ -369,6 +373,10 @@ fn issue12907() -> String { return "".split("").next().unwrap().to_string(); } +fn issue13458() { + with_span!(span return); +} + fn main() {} fn a(x: Option) -> Option { diff --git a/src/tools/clippy/tests/ui/needless_return.stderr b/src/tools/clippy/tests/ui/needless_return.stderr index da0fa220d8c..d3c2a6badc0 100644 --- a/src/tools/clippy/tests/ui/needless_return.stderr +++ b/src/tools/clippy/tests/ui/needless_return.stderr @@ -1,5 +1,5 @@ error: unneeded `return` statement - --> tests/ui/needless_return.rs:25:5 + --> tests/ui/needless_return.rs:29:5 | LL | return true; | ^^^^^^^^^^^ @@ -13,7 +13,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:29:5 + --> tests/ui/needless_return.rs:33:5 | LL | return true; | ^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:34:5 + --> tests/ui/needless_return.rs:38:5 | LL | return true;;; | ^^^^^^^^^^^ @@ -37,7 +37,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:39:5 + --> tests/ui/needless_return.rs:43:5 | LL | return true;; ; ; | ^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:44:9 + --> tests/ui/needless_return.rs:48:9 | LL | return true; | ^^^^^^^^^^^ @@ -61,7 +61,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:46:9 + --> tests/ui/needless_return.rs:50:9 | LL | return false; | ^^^^^^^^^^^^ @@ -73,7 +73,7 @@ LL + false | error: unneeded `return` statement - --> tests/ui/needless_return.rs:52:17 + --> tests/ui/needless_return.rs:56:17 | LL | true => return false, | ^^^^^^^^^^^^ @@ -84,7 +84,7 @@ LL | true => false, | ~~~~~ error: unneeded `return` statement - --> tests/ui/needless_return.rs:54:13 + --> tests/ui/needless_return.rs:58:13 | LL | return true; | ^^^^^^^^^^^ @@ -96,7 +96,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:61:9 + --> tests/ui/needless_return.rs:65:9 | LL | return true; | ^^^^^^^^^^^ @@ -108,7 +108,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:63:16 + --> tests/ui/needless_return.rs:67:16 | LL | let _ = || return true; | ^^^^^^^^^^^ @@ -119,7 +119,7 @@ LL | let _ = || true; | ~~~~ error: unneeded `return` statement - --> tests/ui/needless_return.rs:67:5 + --> tests/ui/needless_return.rs:71:5 | LL | return the_answer!(); | ^^^^^^^^^^^^^^^^^^^^ @@ -131,7 +131,7 @@ LL + the_answer!() | error: unneeded `return` statement - --> tests/ui/needless_return.rs:70:21 + --> tests/ui/needless_return.rs:74:21 | LL | fn test_void_fun() { | _____________________^ @@ -146,7 +146,7 @@ LL + fn test_void_fun() { | error: unneeded `return` statement - --> tests/ui/needless_return.rs:75:11 + --> tests/ui/needless_return.rs:79:11 | LL | if b { | ___________^ @@ -161,7 +161,7 @@ LL + if b { | error: unneeded `return` statement - --> tests/ui/needless_return.rs:77:13 + --> tests/ui/needless_return.rs:81:13 | LL | } else { | _____________^ @@ -176,7 +176,7 @@ LL + } else { | error: unneeded `return` statement - --> tests/ui/needless_return.rs:85:14 + --> tests/ui/needless_return.rs:89:14 | LL | _ => return, | ^^^^^^ @@ -187,7 +187,7 @@ LL | _ => (), | ~~ error: unneeded `return` statement - --> tests/ui/needless_return.rs:93:24 + --> tests/ui/needless_return.rs:97:24 | LL | let _ = 42; | ________________________^ @@ -202,7 +202,7 @@ LL + let _ = 42; | error: unneeded `return` statement - --> tests/ui/needless_return.rs:96:14 + --> tests/ui/needless_return.rs:100:14 | LL | _ => return, | ^^^^^^ @@ -213,7 +213,7 @@ LL | _ => (), | ~~ error: unneeded `return` statement - --> tests/ui/needless_return.rs:109:9 + --> tests/ui/needless_return.rs:113:9 | LL | return String::from("test"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -225,7 +225,7 @@ LL + String::from("test") | error: unneeded `return` statement - --> tests/ui/needless_return.rs:111:9 + --> tests/ui/needless_return.rs:115:9 | LL | return String::new(); | ^^^^^^^^^^^^^^^^^^^^ @@ -237,7 +237,7 @@ LL + String::new() | error: unneeded `return` statement - --> tests/ui/needless_return.rs:133:32 + --> tests/ui/needless_return.rs:137:32 | LL | bar.unwrap_or_else(|_| return) | ^^^^^^ @@ -248,7 +248,7 @@ LL | bar.unwrap_or_else(|_| {}) | ~~ error: unneeded `return` statement - --> tests/ui/needless_return.rs:137:21 + --> tests/ui/needless_return.rs:141:21 | LL | let _ = || { | _____________________^ @@ -263,7 +263,7 @@ LL + let _ = || { | error: unneeded `return` statement - --> tests/ui/needless_return.rs:140:20 + --> tests/ui/needless_return.rs:144:20 | LL | let _ = || return; | ^^^^^^ @@ -274,7 +274,7 @@ LL | let _ = || {}; | ~~ error: unneeded `return` statement - --> tests/ui/needless_return.rs:146:32 + --> tests/ui/needless_return.rs:150:32 | LL | res.unwrap_or_else(|_| return Foo) | ^^^^^^^^^^ @@ -284,18 +284,6 @@ help: remove `return` LL | res.unwrap_or_else(|_| Foo) | ~~~ -error: unneeded `return` statement - --> tests/ui/needless_return.rs:155:5 - | -LL | return true; - | ^^^^^^^^^^^ - | -help: remove `return` - | -LL - return true; -LL + true - | - error: unneeded `return` statement --> tests/ui/needless_return.rs:159:5 | @@ -309,7 +297,19 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:164:9 + --> tests/ui/needless_return.rs:163:5 + | +LL | return true; + | ^^^^^^^^^^^ + | +help: remove `return` + | +LL - return true; +LL + true + | + +error: unneeded `return` statement + --> tests/ui/needless_return.rs:168:9 | LL | return true; | ^^^^^^^^^^^ @@ -321,7 +321,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:166:9 + --> tests/ui/needless_return.rs:170:9 | LL | return false; | ^^^^^^^^^^^^ @@ -333,7 +333,7 @@ LL + false | error: unneeded `return` statement - --> tests/ui/needless_return.rs:172:17 + --> tests/ui/needless_return.rs:176:17 | LL | true => return false, | ^^^^^^^^^^^^ @@ -344,7 +344,7 @@ LL | true => false, | ~~~~~ error: unneeded `return` statement - --> tests/ui/needless_return.rs:174:13 + --> tests/ui/needless_return.rs:178:13 | LL | return true; | ^^^^^^^^^^^ @@ -356,7 +356,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:181:9 + --> tests/ui/needless_return.rs:185:9 | LL | return true; | ^^^^^^^^^^^ @@ -368,7 +368,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:183:16 + --> tests/ui/needless_return.rs:187:16 | LL | let _ = || return true; | ^^^^^^^^^^^ @@ -379,7 +379,7 @@ LL | let _ = || true; | ~~~~ error: unneeded `return` statement - --> tests/ui/needless_return.rs:187:5 + --> tests/ui/needless_return.rs:191:5 | LL | return the_answer!(); | ^^^^^^^^^^^^^^^^^^^^ @@ -391,7 +391,7 @@ LL + the_answer!() | error: unneeded `return` statement - --> tests/ui/needless_return.rs:190:33 + --> tests/ui/needless_return.rs:194:33 | LL | async fn async_test_void_fun() { | _________________________________^ @@ -406,7 +406,7 @@ LL + async fn async_test_void_fun() { | error: unneeded `return` statement - --> tests/ui/needless_return.rs:195:11 + --> tests/ui/needless_return.rs:199:11 | LL | if b { | ___________^ @@ -421,7 +421,7 @@ LL + if b { | error: unneeded `return` statement - --> tests/ui/needless_return.rs:197:13 + --> tests/ui/needless_return.rs:201:13 | LL | } else { | _____________^ @@ -436,7 +436,7 @@ LL + } else { | error: unneeded `return` statement - --> tests/ui/needless_return.rs:205:14 + --> tests/ui/needless_return.rs:209:14 | LL | _ => return, | ^^^^^^ @@ -447,7 +447,7 @@ LL | _ => (), | ~~ error: unneeded `return` statement - --> tests/ui/needless_return.rs:218:9 + --> tests/ui/needless_return.rs:222:9 | LL | return String::from("test"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -459,7 +459,7 @@ LL + String::from("test") | error: unneeded `return` statement - --> tests/ui/needless_return.rs:220:9 + --> tests/ui/needless_return.rs:224:9 | LL | return String::new(); | ^^^^^^^^^^^^^^^^^^^^ @@ -471,7 +471,7 @@ LL + String::new() | error: unneeded `return` statement - --> tests/ui/needless_return.rs:236:5 + --> tests/ui/needless_return.rs:240:5 | LL | return format!("Hello {}", "world!"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -483,7 +483,7 @@ LL + format!("Hello {}", "world!") | error: unneeded `return` statement - --> tests/ui/needless_return.rs:277:9 + --> tests/ui/needless_return.rs:281:9 | LL | return true; | ^^^^^^^^^^^ @@ -497,7 +497,7 @@ LL ~ } | error: unneeded `return` statement - --> tests/ui/needless_return.rs:279:9 + --> tests/ui/needless_return.rs:283:9 | LL | return false; | ^^^^^^^^^^^^ @@ -509,7 +509,7 @@ LL ~ } | error: unneeded `return` statement - --> tests/ui/needless_return.rs:286:13 + --> tests/ui/needless_return.rs:290:13 | LL | return 10; | ^^^^^^^^^ @@ -524,7 +524,7 @@ LL ~ } | error: unneeded `return` statement - --> tests/ui/needless_return.rs:289:13 + --> tests/ui/needless_return.rs:293:13 | LL | return 100; | ^^^^^^^^^^ @@ -537,7 +537,7 @@ LL ~ } | error: unneeded `return` statement - --> tests/ui/needless_return.rs:297:9 + --> tests/ui/needless_return.rs:301:9 | LL | return 0; | ^^^^^^^^ @@ -549,7 +549,7 @@ LL ~ } | error: unneeded `return` statement - --> tests/ui/needless_return.rs:304:13 + --> tests/ui/needless_return.rs:308:13 | LL | return *(x as *const isize); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -564,7 +564,7 @@ LL ~ } | error: unneeded `return` statement - --> tests/ui/needless_return.rs:306:13 + --> tests/ui/needless_return.rs:310:13 | LL | return !*(x as *const isize); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -577,7 +577,7 @@ LL ~ } | error: unneeded `return` statement - --> tests/ui/needless_return.rs:313:20 + --> tests/ui/needless_return.rs:317:20 | LL | let _ = 42; | ____________________^ @@ -594,7 +594,7 @@ LL + let _ = 42; | error: unneeded `return` statement - --> tests/ui/needless_return.rs:320:20 + --> tests/ui/needless_return.rs:324:20 | LL | let _ = 42; return; | ^^^^^^^ @@ -606,7 +606,7 @@ LL + let _ = 42; | error: unneeded `return` statement - --> tests/ui/needless_return.rs:332:9 + --> tests/ui/needless_return.rs:336:9 | LL | return Ok(format!("ok!")); | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -618,7 +618,7 @@ LL + Ok(format!("ok!")) | error: unneeded `return` statement - --> tests/ui/needless_return.rs:334:9 + --> tests/ui/needless_return.rs:338:9 | LL | return Err(format!("err!")); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -630,7 +630,7 @@ LL + Err(format!("err!")) | error: unneeded `return` statement - --> tests/ui/needless_return.rs:340:9 + --> tests/ui/needless_return.rs:344:9 | LL | return if true { 1 } else { 2 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -642,7 +642,7 @@ LL + if true { 1 } else { 2 } | error: unneeded `return` statement - --> tests/ui/needless_return.rs:344:9 + --> tests/ui/needless_return.rs:348:9 | LL | return if b1 { 0 } else { 1 } | if b2 { 2 } else { 3 } | if b3 { 4 } else { 5 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -654,7 +654,7 @@ LL + (if b1 { 0 } else { 1 } | if b2 { 2 } else { 3 } | if b3 { 4 } else | error: unneeded `return` statement - --> tests/ui/needless_return.rs:365:5 + --> tests/ui/needless_return.rs:369:5 | LL | return { "a".to_string() } + "b" + { "c" }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -666,7 +666,7 @@ LL + ({ "a".to_string() } + "b" + { "c" }) | error: unneeded `return` statement - --> tests/ui/needless_return.rs:369:5 + --> tests/ui/needless_return.rs:373:5 | LL | return "".split("").next().unwrap().to_string(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From b12dc2091012d1e8074ccea0ffe6ac16de1ba802 Mon Sep 17 00:00:00 2001 From: Manuel Drehwald Date: Thu, 10 Oct 2024 11:38:28 +0200 Subject: [PATCH 154/357] add config to explicitely test rustc with autodiff/enzyme disabled --- src/tools/compiletest/src/command-list.rs | 1 + src/tools/compiletest/src/header/cfg.rs | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/src/tools/compiletest/src/command-list.rs b/src/tools/compiletest/src/command-list.rs index 53db55d0c10..ab57320b4d9 100644 --- a/src/tools/compiletest/src/command-list.rs +++ b/src/tools/compiletest/src/command-list.rs @@ -49,6 +49,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "ignore-eabi", "ignore-emscripten", "ignore-endian-big", + "ignore-enzyme", "ignore-freebsd", "ignore-fuchsia", "ignore-gdb", diff --git a/src/tools/compiletest/src/header/cfg.rs b/src/tools/compiletest/src/header/cfg.rs index 6e351aa27b9..b9314f0abbb 100644 --- a/src/tools/compiletest/src/header/cfg.rs +++ b/src/tools/compiletest/src/header/cfg.rs @@ -166,6 +166,12 @@ pub(super) fn parse_cfg_name_directive<'a>( message: "when the target vendor is Apple" } + condition! { + name: "enzyme", + condition: config.has_enzyme, + message: "when rustc is built with LLVM Enzyme" + } + // Technically the locally built compiler uses the "dev" channel rather than the "nightly" // channel, even though most people don't know or won't care about it. To avoid confusion, we // treat the "dev" channel as the "nightly" channel when processing the directive. From 1edff466e19c4e2e2f8035de5a25d8a2dc2fef96 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Thu, 10 Oct 2024 11:46:11 +0200 Subject: [PATCH 155/357] Avoid redundant additions to PATH when linking --- compiler/rustc_session/src/session.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index d67e69fe0fb..27879d817b2 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -454,6 +454,8 @@ impl Session { let bin_path = filesearch::make_target_bin_path(&self.sysroot, config::host_triple()); let fallback_sysroot_paths = filesearch::sysroot_candidates() .into_iter() + // Ignore sysroot candidate if it was the same as the sysroot path we just used. + .filter(|sysroot| *sysroot != self.sysroot) .map(|sysroot| filesearch::make_target_bin_path(&sysroot, config::host_triple())); let search_paths = std::iter::once(bin_path).chain(fallback_sysroot_paths); From 09da2ebd63107997e1319c2a076021660285ef40 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 4 Oct 2024 11:56:45 -0400 Subject: [PATCH 156/357] Move ty::Error branch into super_combine_tys --- .../rustc_infer/src/infer/relate/combine.rs | 5 ++++ .../src/infer/relate/type_relating.rs | 5 ---- ...invalid-type-bound-suggest-issue-127555.rs | 1 - ...lid-type-bound-suggest-issue-127555.stderr | 16 ++--------- ...-predicate-entailment-error.current.stderr | 28 +------------------ ...lse-positive-predicate-entailment-error.rs | 3 +- .../in-trait/return-dont-satisfy-bounds.rs | 1 - .../return-dont-satisfy-bounds.stderr | 14 ++-------- .../rpitit-captures-more-method-lifetimes.rs | 1 - ...itit-captures-more-method-lifetimes.stderr | 19 +------------ 10 files changed, 12 insertions(+), 81 deletions(-) diff --git a/compiler/rustc_infer/src/infer/relate/combine.rs b/compiler/rustc_infer/src/infer/relate/combine.rs index c4f5a85a8be..f879fbc5578 100644 --- a/compiler/rustc_infer/src/infer/relate/combine.rs +++ b/compiler/rustc_infer/src/infer/relate/combine.rs @@ -43,6 +43,11 @@ impl<'tcx> InferCtxt<'tcx> { debug_assert!(!b.has_escaping_bound_vars()); match (a.kind(), b.kind()) { + (&ty::Error(e), _) | (_, &ty::Error(e)) => { + self.set_tainted_by_errors(e); + return Ok(Ty::new_error(self.tcx, e)); + } + // Relate integral variables to other types (&ty::Infer(ty::IntVar(a_id)), &ty::Infer(ty::IntVar(b_id))) => { self.inner.borrow_mut().int_unification_table().union(a_id, b_id); diff --git a/compiler/rustc_infer/src/infer/relate/type_relating.rs b/compiler/rustc_infer/src/infer/relate/type_relating.rs index 4b4b13e919c..d99acabb825 100644 --- a/compiler/rustc_infer/src/infer/relate/type_relating.rs +++ b/compiler/rustc_infer/src/infer/relate/type_relating.rs @@ -183,11 +183,6 @@ impl<'tcx> TypeRelation> for TypeRelating<'_, 'tcx> { )?; } - (&ty::Error(e), _) | (_, &ty::Error(e)) => { - infcx.set_tainted_by_errors(e); - return Ok(Ty::new_error(self.cx(), e)); - } - ( &ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, .. }), &ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }), diff --git a/tests/ui/associated-types/remove-invalid-type-bound-suggest-issue-127555.rs b/tests/ui/associated-types/remove-invalid-type-bound-suggest-issue-127555.rs index 6083cc7d96d..b4df58b3c25 100644 --- a/tests/ui/associated-types/remove-invalid-type-bound-suggest-issue-127555.rs +++ b/tests/ui/associated-types/remove-invalid-type-bound-suggest-issue-127555.rs @@ -14,7 +14,6 @@ impl Foo for Baz { //~^ ERROR `F` cannot be sent between threads safely where F: FnMut() + Send, - //~^ ERROR impl has stricter requirements than trait { () } diff --git a/tests/ui/associated-types/remove-invalid-type-bound-suggest-issue-127555.stderr b/tests/ui/associated-types/remove-invalid-type-bound-suggest-issue-127555.stderr index 7f3cd2a5900..e6379954776 100644 --- a/tests/ui/associated-types/remove-invalid-type-bound-suggest-issue-127555.stderr +++ b/tests/ui/associated-types/remove-invalid-type-bound-suggest-issue-127555.stderr @@ -16,18 +16,6 @@ LL | async fn bar(&mut self, _func: F) -> () LL | F: FnMut() + Send, | ^^^^ required by this bound in `::bar` -error[E0276]: impl has stricter requirements than trait - --> $DIR/remove-invalid-type-bound-suggest-issue-127555.rs:16:22 - | -LL | / fn bar(&mut self, func: F) -> impl std::future::Future + Send -LL | | where -LL | | F: FnMut(); - | |___________________- definition of `bar` from trait -... -LL | F: FnMut() + Send, - | ^^^^ impl has extra requirement `F: Send` +error: aborting due to 1 previous error -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0276, E0277. -For more information about an error, try `rustc --explain E0276`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.current.stderr b/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.current.stderr index d71c1768a6a..058517f0014 100644 --- a/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.current.stderr +++ b/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.current.stderr @@ -73,32 +73,6 @@ help: consider further restricting this bound LL | F: Callback + MyFn, | +++++++++++ -error[E0277]: the trait bound `F: Callback` is not satisfied - --> $DIR/false-positive-predicate-entailment-error.rs:43:12 - | -LL | F: Callback, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `MyFn` is not implemented for `F`, which is required by `F: Callback` - | -note: required for `F` to implement `Callback` - --> $DIR/false-positive-predicate-entailment-error.rs:14:21 - | -LL | impl> Callback for F { - | ------- ^^^^^^^^^^^ ^ - | | - | unsatisfied trait bound introduced here -note: the requirement `F: Callback` appears on the `impl`'s method `autobatch` but not on the corresponding trait's method - --> $DIR/false-positive-predicate-entailment-error.rs:25:8 - | -LL | trait ChannelSender { - | ------------- in this trait -... -LL | fn autobatch(self) -> impl Trait - | ^^^^^^^^^ this trait's method doesn't have the requirement `F: Callback` -help: consider further restricting this bound - | -LL | F: Callback + MyFn, - | +++++++++++ - error[E0277]: the trait bound `F: MyFn` is not satisfied --> $DIR/false-positive-predicate-entailment-error.rs:36:30 | @@ -168,6 +142,6 @@ help: consider further restricting this bound LL | F: Callback + MyFn, | +++++++++++ -error: aborting due to 8 previous errors +error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.rs b/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.rs index 59fdeab9e0a..2987d183e04 100644 --- a/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.rs +++ b/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.rs @@ -41,8 +41,7 @@ impl ChannelSender for Sender { //[current]~| ERROR the trait bound `F: MyFn` is not satisfied where F: Callback, - //[current]~^ ERROR the trait bound `F: Callback` is not satisfied - //[current]~| ERROR the trait bound `F: MyFn` is not satisfied + //[current]~^ ERROR the trait bound `F: MyFn` is not satisfied { Thing } diff --git a/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.rs b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.rs index 84bc39d9263..ee47de2c732 100644 --- a/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.rs +++ b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.rs @@ -8,7 +8,6 @@ impl Foo for Bar { fn foo>(self) -> impl Foo { //~^ ERROR: the trait bound `impl Foo: Foo` is not satisfied [E0277] //~| ERROR: the trait bound `Bar: Foo` is not satisfied [E0277] - //~| ERROR: impl has stricter requirements than trait //~| ERROR: the trait bound `F2: Foo` is not satisfied self } diff --git a/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr index ae449099987..768224e4c51 100644 --- a/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr +++ b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr @@ -23,15 +23,6 @@ note: required by a bound in `>::foo` LL | fn foo>(self) -> impl Foo { | ^^^^^^^ required by this bound in `>::foo` -error[E0276]: impl has stricter requirements than trait - --> $DIR/return-dont-satisfy-bounds.rs:8:16 - | -LL | fn foo(self) -> impl Foo; - | -------------------------------- definition of `foo` from trait -... -LL | fn foo>(self) -> impl Foo { - | ^^^^^^^ impl has extra requirement `F2: Foo` - error[E0277]: the trait bound `Bar: Foo` is not satisfied --> $DIR/return-dont-satisfy-bounds.rs:8:34 | @@ -44,7 +35,6 @@ LL | self = help: the trait `Foo` is implemented for `Bar` = help: for that trait implementation, expected `char`, found `u8` -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0276, E0277. -For more information about an error, try `rustc --explain E0276`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.rs b/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.rs index 71a91fe319e..062351afecb 100644 --- a/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.rs +++ b/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.rs @@ -10,7 +10,6 @@ pub trait Foo { impl Foo for () { fn bar<'im: 'im>(&'im mut self) -> impl Sized + 'im {} //~^ ERROR return type captures more lifetimes than trait definition - //~| WARN impl trait in impl method signature does not match trait method signature } fn main() {} diff --git a/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.stderr b/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.stderr index 339e2e6335e..b390a23eef4 100644 --- a/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.stderr +++ b/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.stderr @@ -21,22 +21,5 @@ LL | fn bar<'tr: 'tr>(&'tr mut self) -> impl Sized + use; | ^^^^^^^^^^^^^^^^^^^^^^ = note: hidden type inferred to be `impl Sized + 'im` -warning: impl trait in impl method signature does not match trait method signature - --> $DIR/rpitit-captures-more-method-lifetimes.rs:11:40 - | -LL | fn bar<'tr: 'tr>(&'tr mut self) -> impl Sized + use; - | ---------------------- return type from trait method defined here -... -LL | fn bar<'im: 'im>(&'im mut self) -> impl Sized + 'im {} - | ^^^^^^^^^^^^^^^^ - | - = note: add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate - = note: we are soliciting feedback, see issue #121718 for more information - = note: `#[warn(refining_impl_trait_reachable)]` on by default -help: replace the return type so that it matches the trait - | -LL | fn bar<'im: 'im>(&'im mut self) -> impl Sized {} - | ~~~~~~~~~~ - -error: aborting due to 2 previous errors; 1 warning emitted +error: aborting due to 2 previous errors From ce7a61b9d0bb4b7bb99ade4bff2449fabc9afd3f Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 4 Oct 2024 12:33:51 -0400 Subject: [PATCH 157/357] Uplift super_combine --- .../src/type_check/relate_tys.rs | 1 + compiler/rustc_infer/src/infer/context.rs | 69 ++++- .../rustc_infer/src/infer/relate/combine.rs | 245 ----------------- .../src/infer/relate/generalize.rs | 2 +- .../rustc_infer/src/infer/relate/lattice.rs | 1 + compiler/rustc_infer/src/infer/relate/mod.rs | 6 +- .../src/infer/relate/type_relating.rs | 1 + compiler/rustc_next_trait_solver/src/lib.rs | 1 - .../rustc_next_trait_solver/src/relate.rs | 15 -- .../src/relate/combine.rs | 34 --- compiler/rustc_type_ir/src/infer_ctxt.rs | 37 ++- compiler/rustc_type_ir/src/relate.rs | 14 + compiler/rustc_type_ir/src/relate/combine.rs | 255 ++++++++++++++++++ 13 files changed, 376 insertions(+), 305 deletions(-) delete mode 100644 compiler/rustc_infer/src/infer/relate/combine.rs delete mode 100644 compiler/rustc_next_trait_solver/src/relate.rs delete mode 100644 compiler/rustc_next_trait_solver/src/relate/combine.rs create mode 100644 compiler/rustc_type_ir/src/relate/combine.rs diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs index bf079e813f1..e72c21e8fad 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -11,6 +11,7 @@ use rustc_middle::span_bug; use rustc_middle::traits::ObligationCause; use rustc_middle::traits::query::NoSolution; use rustc_middle::ty::fold::FnMutDelegate; +use rustc_middle::ty::relate::combine::InferCtxtCombineExt; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt}; use rustc_span::symbol::sym; use rustc_span::{Span, Symbol}; diff --git a/compiler/rustc_infer/src/infer/context.rs b/compiler/rustc_infer/src/infer/context.rs index c06836edcfb..10b22c98a0d 100644 --- a/compiler/rustc_infer/src/infer/context.rs +++ b/compiler/rustc_infer/src/infer/context.rs @@ -1,22 +1,27 @@ ///! Definition of `InferCtxtLike` from the librarified type layer. use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_middle::infer::unify_key::EffectVarValue; use rustc_middle::traits::ObligationCause; use rustc_middle::traits::solve::{Goal, NoSolution, SolverMode}; use rustc_middle::ty::fold::TypeFoldable; +use rustc_middle::ty::relate::combine::PredicateEmittingRelation; +use rustc_middle::ty::relate::{Relate, RelateResult}; use rustc_middle::ty::{self, Ty, TyCtxt}; -use rustc_span::DUMMY_SP; -use rustc_type_ir::InferCtxtLike; -use rustc_type_ir::relate::Relate; +use rustc_span::{DUMMY_SP, ErrorGuaranteed}; use super::{BoundRegionConversionTime, InferCtxt, SubregionOrigin}; -impl<'tcx> InferCtxtLike for InferCtxt<'tcx> { +impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> { type Interner = TyCtxt<'tcx>; fn cx(&self) -> TyCtxt<'tcx> { self.tcx } + fn next_trait_solver(&self) -> bool { + self.next_trait_solver + } + fn solver_mode(&self) -> ty::solve::SolverMode { match self.intercrate { true => SolverMode::Coherence, @@ -131,6 +136,59 @@ impl<'tcx> InferCtxtLike for InferCtxt<'tcx> { self.enter_forall(value, f) } + fn equate_int_vids_raw(&self, a: rustc_type_ir::IntVid, b: rustc_type_ir::IntVid) { + self.inner.borrow_mut().int_unification_table().union(a, b); + } + + fn equate_float_vids_raw(&self, a: rustc_type_ir::FloatVid, b: rustc_type_ir::FloatVid) { + self.inner.borrow_mut().float_unification_table().union(a, b); + } + + fn equate_const_vids_raw(&self, a: rustc_type_ir::ConstVid, b: rustc_type_ir::ConstVid) { + self.inner.borrow_mut().const_unification_table().union(a, b); + } + + fn equate_effect_vids_raw(&self, a: rustc_type_ir::EffectVid, b: rustc_type_ir::EffectVid) { + self.inner.borrow_mut().effect_unification_table().union(a, b); + } + + fn instantiate_int_var_raw( + &self, + vid: rustc_type_ir::IntVid, + value: rustc_type_ir::IntVarValue, + ) { + self.inner.borrow_mut().int_unification_table().union_value(vid, value); + } + + fn instantiate_float_var_raw( + &self, + vid: rustc_type_ir::FloatVid, + value: rustc_type_ir::FloatVarValue, + ) { + self.inner.borrow_mut().float_unification_table().union_value(vid, value); + } + + fn instantiate_effect_var_raw(&self, vid: rustc_type_ir::EffectVid, value: ty::Const<'tcx>) { + self.inner + .borrow_mut() + .effect_unification_table() + .union_value(vid, EffectVarValue::Known(value)); + } + + fn instantiate_const_var_raw>( + &self, + relation: &mut R, + target_is_expected: bool, + target_vid: rustc_type_ir::ConstVid, + source_ct: ty::Const<'tcx>, + ) -> RelateResult<'tcx, ()> { + self.instantiate_const_var(relation, target_is_expected, target_vid, source_ct) + } + + fn set_tainted_by_errors(&self, e: ErrorGuaranteed) { + self.set_tainted_by_errors(e) + } + fn relate>>( &self, param_env: ty::ParamEnv<'tcx>, @@ -154,6 +212,9 @@ impl<'tcx> InferCtxtLike for InferCtxt<'tcx> { fn shallow_resolve(&self, ty: Ty<'tcx>) -> Ty<'tcx> { self.shallow_resolve(ty) } + fn shallow_resolve_const(&self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> { + self.shallow_resolve_const(ct) + } fn resolve_vars_if_possible(&self, value: T) -> T where diff --git a/compiler/rustc_infer/src/infer/relate/combine.rs b/compiler/rustc_infer/src/infer/relate/combine.rs deleted file mode 100644 index f879fbc5578..00000000000 --- a/compiler/rustc_infer/src/infer/relate/combine.rs +++ /dev/null @@ -1,245 +0,0 @@ -//! There are four type combiners: `TypeRelating`, `Lub`, and `Glb`, -//! and `NllTypeRelating` in rustc_borrowck, which is only used for NLL. -//! -//! Each implements the trait [TypeRelation] and contains methods for -//! combining two instances of various things and yielding a new instance. -//! These combiner methods always yield a `Result`. To relate two -//! types, you can use `infcx.at(cause, param_env)` which then allows -//! you to use the relevant methods of [At](crate::infer::at::At). -//! -//! Combiners mostly do their specific behavior and then hand off the -//! bulk of the work to [InferCtxt::super_combine_tys] and -//! [InferCtxt::super_combine_consts]. -//! -//! Combining two types may have side-effects on the inference contexts -//! which can be undone by using snapshots. You probably want to use -//! either [InferCtxt::commit_if_ok] or [InferCtxt::probe]. -//! -//! On success, the LUB/GLB operations return the appropriate bound. The -//! return value of `Equate` or `Sub` shouldn't really be used. - -use rustc_middle::bug; -use rustc_middle::infer::unify_key::EffectVarValue; -use rustc_middle::ty::error::{ExpectedFound, TypeError}; -use rustc_middle::ty::{self, InferConst, IntType, Ty, TypeVisitableExt, UintType}; -pub use rustc_next_trait_solver::relate::combine::*; -use tracing::debug; - -use super::{RelateResult, StructurallyRelateAliases}; -use crate::infer::{InferCtxt, relate}; - -impl<'tcx> InferCtxt<'tcx> { - pub fn super_combine_tys( - &self, - relation: &mut R, - a: Ty<'tcx>, - b: Ty<'tcx>, - ) -> RelateResult<'tcx, Ty<'tcx>> - where - R: PredicateEmittingRelation>, - { - debug!("super_combine_tys::<{}>({:?}, {:?})", std::any::type_name::(), a, b); - debug_assert!(!a.has_escaping_bound_vars()); - debug_assert!(!b.has_escaping_bound_vars()); - - match (a.kind(), b.kind()) { - (&ty::Error(e), _) | (_, &ty::Error(e)) => { - self.set_tainted_by_errors(e); - return Ok(Ty::new_error(self.tcx, e)); - } - - // Relate integral variables to other types - (&ty::Infer(ty::IntVar(a_id)), &ty::Infer(ty::IntVar(b_id))) => { - self.inner.borrow_mut().int_unification_table().union(a_id, b_id); - Ok(a) - } - (&ty::Infer(ty::IntVar(v_id)), &ty::Int(v)) => { - self.unify_integral_variable(v_id, IntType(v)); - Ok(b) - } - (&ty::Int(v), &ty::Infer(ty::IntVar(v_id))) => { - self.unify_integral_variable(v_id, IntType(v)); - Ok(a) - } - (&ty::Infer(ty::IntVar(v_id)), &ty::Uint(v)) => { - self.unify_integral_variable(v_id, UintType(v)); - Ok(b) - } - (&ty::Uint(v), &ty::Infer(ty::IntVar(v_id))) => { - self.unify_integral_variable(v_id, UintType(v)); - Ok(a) - } - - // Relate floating-point variables to other types - (&ty::Infer(ty::FloatVar(a_id)), &ty::Infer(ty::FloatVar(b_id))) => { - self.inner.borrow_mut().float_unification_table().union(a_id, b_id); - Ok(a) - } - (&ty::Infer(ty::FloatVar(v_id)), &ty::Float(v)) => { - self.unify_float_variable(v_id, ty::FloatVarValue::Known(v)); - Ok(b) - } - (&ty::Float(v), &ty::Infer(ty::FloatVar(v_id))) => { - self.unify_float_variable(v_id, ty::FloatVarValue::Known(v)); - Ok(a) - } - - // We don't expect `TyVar` or `Fresh*` vars at this point with lazy norm. - (ty::Alias(..), ty::Infer(ty::TyVar(_))) | (ty::Infer(ty::TyVar(_)), ty::Alias(..)) - if self.next_trait_solver() => - { - bug!( - "We do not expect to encounter `TyVar` this late in combine \ - -- they should have been handled earlier" - ) - } - (_, ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_))) - | (ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)), _) - if self.next_trait_solver() => - { - bug!("We do not expect to encounter `Fresh` variables in the new solver") - } - - (_, ty::Alias(..)) | (ty::Alias(..), _) if self.next_trait_solver() => { - match relation.structurally_relate_aliases() { - StructurallyRelateAliases::Yes => { - relate::structurally_relate_tys(relation, a, b) - } - StructurallyRelateAliases::No => { - relation.register_alias_relate_predicate(a, b); - Ok(a) - } - } - } - - // All other cases of inference are errors - (&ty::Infer(_), _) | (_, &ty::Infer(_)) => { - Err(TypeError::Sorts(ExpectedFound::new(true, a, b))) - } - - // During coherence, opaque types should be treated as *possibly* - // equal to any other type (except for possibly itself). This is an - // extremely heavy hammer, but can be relaxed in a forwards-compatible - // way later. - (&ty::Alias(ty::Opaque, _), _) | (_, &ty::Alias(ty::Opaque, _)) if self.intercrate => { - relation.register_predicates([ty::Binder::dummy(ty::PredicateKind::Ambiguous)]); - Ok(a) - } - - _ => relate::structurally_relate_tys(relation, a, b), - } - } - - pub fn super_combine_consts( - &self, - relation: &mut R, - a: ty::Const<'tcx>, - b: ty::Const<'tcx>, - ) -> RelateResult<'tcx, ty::Const<'tcx>> - where - R: PredicateEmittingRelation>, - { - debug!("super_combine_consts::<{}>({:?}, {:?})", std::any::type_name::(), a, b); - debug_assert!(!a.has_escaping_bound_vars()); - debug_assert!(!b.has_escaping_bound_vars()); - - if a == b { - return Ok(a); - } - - let a = self.shallow_resolve_const(a); - let b = self.shallow_resolve_const(b); - - match (a.kind(), b.kind()) { - ( - ty::ConstKind::Infer(InferConst::Var(a_vid)), - ty::ConstKind::Infer(InferConst::Var(b_vid)), - ) => { - self.inner.borrow_mut().const_unification_table().union(a_vid, b_vid); - Ok(a) - } - - ( - ty::ConstKind::Infer(InferConst::EffectVar(a_vid)), - ty::ConstKind::Infer(InferConst::EffectVar(b_vid)), - ) => { - self.inner.borrow_mut().effect_unification_table().union(a_vid, b_vid); - Ok(a) - } - - // All other cases of inference with other variables are errors. - ( - ty::ConstKind::Infer(InferConst::Var(_) | InferConst::EffectVar(_)), - ty::ConstKind::Infer(_), - ) - | ( - ty::ConstKind::Infer(_), - ty::ConstKind::Infer(InferConst::Var(_) | InferConst::EffectVar(_)), - ) => { - bug!( - "tried to combine ConstKind::Infer/ConstKind::Infer(InferConst::Var): {a:?} and {b:?}" - ) - } - - (ty::ConstKind::Infer(InferConst::Var(vid)), _) => { - self.instantiate_const_var(relation, true, vid, b)?; - Ok(b) - } - - (_, ty::ConstKind::Infer(InferConst::Var(vid))) => { - self.instantiate_const_var(relation, false, vid, a)?; - Ok(a) - } - - (ty::ConstKind::Infer(InferConst::EffectVar(vid)), _) => { - Ok(self.unify_effect_variable(vid, b)) - } - - (_, ty::ConstKind::Infer(InferConst::EffectVar(vid))) => { - Ok(self.unify_effect_variable(vid, a)) - } - - (ty::ConstKind::Unevaluated(..), _) | (_, ty::ConstKind::Unevaluated(..)) - if self.tcx.features().generic_const_exprs || self.next_trait_solver() => - { - match relation.structurally_relate_aliases() { - StructurallyRelateAliases::No => { - relation.register_predicates([if self.next_trait_solver() { - ty::PredicateKind::AliasRelate( - a.into(), - b.into(), - ty::AliasRelationDirection::Equate, - ) - } else { - ty::PredicateKind::ConstEquate(a, b) - }]); - - Ok(b) - } - StructurallyRelateAliases::Yes => { - relate::structurally_relate_consts(relation, a, b) - } - } - } - _ => relate::structurally_relate_consts(relation, a, b), - } - } - - #[inline(always)] - fn unify_integral_variable(&self, vid: ty::IntVid, val: ty::IntVarValue) { - self.inner.borrow_mut().int_unification_table().union_value(vid, val); - } - - #[inline(always)] - fn unify_float_variable(&self, vid: ty::FloatVid, val: ty::FloatVarValue) { - self.inner.borrow_mut().float_unification_table().union_value(vid, val); - } - - fn unify_effect_variable(&self, vid: ty::EffectVid, val: ty::Const<'tcx>) -> ty::Const<'tcx> { - self.inner - .borrow_mut() - .effect_unification_table() - .union_value(vid, EffectVarValue::Known(val)); - val - } -} diff --git a/compiler/rustc_infer/src/infer/relate/generalize.rs b/compiler/rustc_infer/src/infer/relate/generalize.rs index 726a2296d11..7049444db9b 100644 --- a/compiler/rustc_infer/src/infer/relate/generalize.rs +++ b/compiler/rustc_infer/src/infer/relate/generalize.rs @@ -183,7 +183,7 @@ impl<'tcx> InferCtxt<'tcx> { /// /// See `tests/ui/const-generics/occurs-check/` for more examples where this is relevant. #[instrument(level = "debug", skip(self, relation))] - pub(super) fn instantiate_const_var>>( + pub(crate) fn instantiate_const_var>>( &self, relation: &mut R, target_is_expected: bool, diff --git a/compiler/rustc_infer/src/infer/relate/lattice.rs b/compiler/rustc_infer/src/infer/relate/lattice.rs index 8cec312abf7..fc208a08471 100644 --- a/compiler/rustc_infer/src/infer/relate/lattice.rs +++ b/compiler/rustc_infer/src/infer/relate/lattice.rs @@ -18,6 +18,7 @@ //! [lattices]: https://en.wikipedia.org/wiki/Lattice_(order) use rustc_middle::traits::solve::Goal; +use rustc_middle::ty::relate::combine::InferCtxtCombineExt; use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation}; use rustc_middle::ty::{self, Ty, TyCtxt, TyVar, TypeVisitableExt}; use rustc_span::Span; diff --git a/compiler/rustc_infer/src/infer/relate/mod.rs b/compiler/rustc_infer/src/infer/relate/mod.rs index baab5bb274a..e156f72d78d 100644 --- a/compiler/rustc_infer/src/infer/relate/mod.rs +++ b/compiler/rustc_infer/src/infer/relate/mod.rs @@ -3,12 +3,10 @@ //! As well as the implementation of `Relate` for interned things (`Ty`/`Const`/etc). pub use rustc_middle::ty::relate::RelateResult; -pub use rustc_next_trait_solver::relate::*; - -pub use self::combine::PredicateEmittingRelation; +pub use rustc_type_ir::relate::combine::PredicateEmittingRelation; +pub use rustc_type_ir::relate::*; #[allow(hidden_glob_reexports)] -pub(super) mod combine; mod generalize; mod higher_ranked; pub(super) mod lattice; diff --git a/compiler/rustc_infer/src/infer/relate/type_relating.rs b/compiler/rustc_infer/src/infer/relate/type_relating.rs index d99acabb825..d2dc4589103 100644 --- a/compiler/rustc_infer/src/infer/relate/type_relating.rs +++ b/compiler/rustc_infer/src/infer/relate/type_relating.rs @@ -1,4 +1,5 @@ use rustc_middle::traits::solve::Goal; +use rustc_middle::ty::relate::combine::InferCtxtCombineExt; use rustc_middle::ty::relate::{ Relate, RelateResult, TypeRelation, relate_args_invariantly, relate_args_with_variances, }; diff --git a/compiler/rustc_next_trait_solver/src/lib.rs b/compiler/rustc_next_trait_solver/src/lib.rs index ca140500e2c..de74ac32804 100644 --- a/compiler/rustc_next_trait_solver/src/lib.rs +++ b/compiler/rustc_next_trait_solver/src/lib.rs @@ -12,6 +12,5 @@ pub mod canonicalizer; pub mod coherence; pub mod delegate; -pub mod relate; pub mod resolve; pub mod solve; diff --git a/compiler/rustc_next_trait_solver/src/relate.rs b/compiler/rustc_next_trait_solver/src/relate.rs deleted file mode 100644 index db819961bbd..00000000000 --- a/compiler/rustc_next_trait_solver/src/relate.rs +++ /dev/null @@ -1,15 +0,0 @@ -pub use rustc_type_ir::relate::*; - -pub mod combine; - -/// Whether aliases should be related structurally or not. Used -/// to adjust the behavior of generalization and combine. -/// -/// This should always be `No` unless in a few special-cases when -/// instantiating canonical responses and in the new solver. Each -/// such case should have a comment explaining why it is used. -#[derive(Debug, Copy, Clone)] -pub enum StructurallyRelateAliases { - Yes, - No, -} diff --git a/compiler/rustc_next_trait_solver/src/relate/combine.rs b/compiler/rustc_next_trait_solver/src/relate/combine.rs deleted file mode 100644 index 96968327d8e..00000000000 --- a/compiler/rustc_next_trait_solver/src/relate/combine.rs +++ /dev/null @@ -1,34 +0,0 @@ -pub use rustc_type_ir::relate::*; -use rustc_type_ir::solve::Goal; -use rustc_type_ir::{InferCtxtLike, Interner, Upcast}; - -use super::StructurallyRelateAliases; - -pub trait PredicateEmittingRelation::Interner>: - TypeRelation -where - Infcx: InferCtxtLike, - I: Interner, -{ - fn span(&self) -> I::Span; - - fn param_env(&self) -> I::ParamEnv; - - /// Whether aliases should be related structurally. This is pretty much - /// always `No` unless you're equating in some specific locations of the - /// new solver. See the comments in these use-cases for more details. - fn structurally_relate_aliases(&self) -> StructurallyRelateAliases; - - /// Register obligations that must hold in order for this relation to hold - fn register_goals(&mut self, obligations: impl IntoIterator>); - - /// Register predicates that must hold in order for this relation to hold. - /// This uses the default `param_env` of the obligation. - fn register_predicates( - &mut self, - obligations: impl IntoIterator>, - ); - - /// Register `AliasRelate` obligation(s) that both types must be related to each other. - fn register_alias_relate_predicate(&mut self, a: I::Ty, b: I::Ty); -} diff --git a/compiler/rustc_type_ir/src/infer_ctxt.rs b/compiler/rustc_type_ir/src/infer_ctxt.rs index 1d0b2345b80..2f6476c6e23 100644 --- a/compiler/rustc_type_ir/src/infer_ctxt.rs +++ b/compiler/rustc_type_ir/src/infer_ctxt.rs @@ -1,5 +1,6 @@ use crate::fold::TypeFoldable; -use crate::relate::Relate; +use crate::relate::combine::PredicateEmittingRelation; +use crate::relate::{Relate, RelateResult}; use crate::solve::{Goal, NoSolution, SolverMode}; use crate::{self as ty, Interner}; @@ -7,6 +8,14 @@ pub trait InferCtxtLike: Sized { type Interner: Interner; fn cx(&self) -> Self::Interner; + /// Whether the new trait solver is enabled. This only exists because rustc + /// shares code between the new and old trait solvers; for all other users, + /// this should always be true. If this is unknowingly false and you try to + /// use the new trait solver, things will break badly. + fn next_trait_solver(&self) -> bool { + true + } + fn solver_mode(&self) -> SolverMode; fn universe(&self) -> ty::UniverseIndex; @@ -58,6 +67,28 @@ pub trait InferCtxtLike: Sized { f: impl FnOnce(T) -> U, ) -> U; + fn equate_int_vids_raw(&self, a: ty::IntVid, b: ty::IntVid); + fn equate_float_vids_raw(&self, a: ty::FloatVid, b: ty::FloatVid); + fn equate_const_vids_raw(&self, a: ty::ConstVid, b: ty::ConstVid); + fn equate_effect_vids_raw(&self, a: ty::EffectVid, b: ty::EffectVid); + + fn instantiate_int_var_raw(&self, vid: ty::IntVid, value: ty::IntVarValue); + fn instantiate_float_var_raw(&self, vid: ty::FloatVid, value: ty::FloatVarValue); + fn instantiate_effect_var_raw( + &self, + vid: ty::EffectVid, + value: ::Const, + ); + fn instantiate_const_var_raw>( + &self, + relation: &mut R, + target_is_expected: bool, + target_vid: ty::ConstVid, + source_ct: ::Const, + ) -> RelateResult; + + fn set_tainted_by_errors(&self, e: ::ErrorGuaranteed); + fn relate>( &self, param_env: ::ParamEnv, @@ -77,6 +108,10 @@ pub trait InferCtxtLike: Sized { &self, ty: ::Ty, ) -> ::Ty; + fn shallow_resolve_const( + &self, + ty: ::Const, + ) -> ::Const; fn resolve_vars_if_possible(&self, value: T) -> T where diff --git a/compiler/rustc_type_ir/src/relate.rs b/compiler/rustc_type_ir/src/relate.rs index 9c725f34d8e..8e5d917e915 100644 --- a/compiler/rustc_type_ir/src/relate.rs +++ b/compiler/rustc_type_ir/src/relate.rs @@ -9,8 +9,22 @@ use crate::fold::TypeFoldable; use crate::inherent::*; use crate::{self as ty, Interner}; +pub mod combine; + pub type RelateResult = Result>; +/// Whether aliases should be related structurally or not. Used +/// to adjust the behavior of generalization and combine. +/// +/// This should always be `No` unless in a few special-cases when +/// instantiating canonical responses and in the new solver. Each +/// such case should have a comment explaining why it is used. +#[derive(Debug, Copy, Clone)] +pub enum StructurallyRelateAliases { + Yes, + No, +} + /// Extra information about why we ended up with a particular variance. /// This is only used to add more information to error messages, and /// has no effect on soundness. While choosing the 'wrong' `VarianceDiagInfo` diff --git a/compiler/rustc_type_ir/src/relate/combine.rs b/compiler/rustc_type_ir/src/relate/combine.rs new file mode 100644 index 00000000000..9dfcde609c7 --- /dev/null +++ b/compiler/rustc_type_ir/src/relate/combine.rs @@ -0,0 +1,255 @@ +use tracing::debug; + +use super::{ + ExpectedFound, RelateResult, StructurallyRelateAliases, TypeRelation, + structurally_relate_consts, structurally_relate_tys, +}; +use crate::error::TypeError; +use crate::inherent::*; +use crate::solve::{Goal, SolverMode}; +use crate::visit::TypeVisitableExt as _; +use crate::{self as ty, InferCtxtLike, Interner, Upcast}; + +pub trait PredicateEmittingRelation::Interner>: + TypeRelation +where + Infcx: InferCtxtLike, + I: Interner, +{ + fn span(&self) -> I::Span; + + fn param_env(&self) -> I::ParamEnv; + + /// Whether aliases should be related structurally. This is pretty much + /// always `No` unless you're equating in some specific locations of the + /// new solver. See the comments in these use-cases for more details. + fn structurally_relate_aliases(&self) -> StructurallyRelateAliases; + + /// Register obligations that must hold in order for this relation to hold + fn register_goals(&mut self, obligations: impl IntoIterator>); + + /// Register predicates that must hold in order for this relation to hold. + /// This uses the default `param_env` of the obligation. + fn register_predicates( + &mut self, + obligations: impl IntoIterator>, + ); + + /// Register `AliasRelate` obligation(s) that both types must be related to each other. + fn register_alias_relate_predicate(&mut self, a: I::Ty, b: I::Ty); +} + +pub trait InferCtxtCombineExt: InferCtxtLike { + fn super_combine_tys(&self, relation: &mut R, a: I::Ty, b: I::Ty) -> RelateResult + where + R: PredicateEmittingRelation; + + fn super_combine_consts( + &self, + relation: &mut R, + a: I::Const, + b: I::Const, + ) -> RelateResult + where + R: PredicateEmittingRelation; +} + +impl> InferCtxtCombineExt for Infcx { + fn super_combine_tys(&self, relation: &mut R, a: I::Ty, b: I::Ty) -> RelateResult + where + R: PredicateEmittingRelation, + { + debug!("super_combine_tys::<{}>({:?}, {:?})", std::any::type_name::(), a, b); + debug_assert!(!a.has_escaping_bound_vars()); + debug_assert!(!b.has_escaping_bound_vars()); + + match (a.kind(), b.kind()) { + (ty::Error(e), _) | (_, ty::Error(e)) => { + self.set_tainted_by_errors(e); + return Ok(Ty::new_error(self.cx(), e)); + } + + // Relate integral variables to other types + (ty::Infer(ty::IntVar(a_id)), ty::Infer(ty::IntVar(b_id))) => { + self.equate_int_vids_raw(a_id, b_id); + Ok(a) + } + (ty::Infer(ty::IntVar(v_id)), ty::Int(v)) => { + self.instantiate_int_var_raw(v_id, ty::IntVarValue::IntType(v)); + Ok(b) + } + (ty::Int(v), ty::Infer(ty::IntVar(v_id))) => { + self.instantiate_int_var_raw(v_id, ty::IntVarValue::IntType(v)); + Ok(a) + } + (ty::Infer(ty::IntVar(v_id)), ty::Uint(v)) => { + self.instantiate_int_var_raw(v_id, ty::IntVarValue::UintType(v)); + Ok(b) + } + (ty::Uint(v), ty::Infer(ty::IntVar(v_id))) => { + self.instantiate_int_var_raw(v_id, ty::IntVarValue::UintType(v)); + Ok(a) + } + + // Relate floating-point variables to other types + (ty::Infer(ty::FloatVar(a_id)), ty::Infer(ty::FloatVar(b_id))) => { + self.equate_float_vids_raw(a_id, b_id); + Ok(a) + } + (ty::Infer(ty::FloatVar(v_id)), ty::Float(v)) => { + self.instantiate_float_var_raw(v_id, ty::FloatVarValue::Known(v)); + Ok(b) + } + (ty::Float(v), ty::Infer(ty::FloatVar(v_id))) => { + self.instantiate_float_var_raw(v_id, ty::FloatVarValue::Known(v)); + Ok(a) + } + + // We don't expect `TyVar` or `Fresh*` vars at this point with lazy norm. + (ty::Alias(..), ty::Infer(ty::TyVar(_))) | (ty::Infer(ty::TyVar(_)), ty::Alias(..)) + if self.next_trait_solver() => + { + panic!( + "We do not expect to encounter `TyVar` this late in combine \ + -- they should have been handled earlier" + ) + } + (_, ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_))) + | (ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)), _) + if self.next_trait_solver() => + { + panic!("We do not expect to encounter `Fresh` variables in the new solver") + } + + (_, ty::Alias(..)) | (ty::Alias(..), _) if self.next_trait_solver() => { + match relation.structurally_relate_aliases() { + StructurallyRelateAliases::Yes => structurally_relate_tys(relation, a, b), + StructurallyRelateAliases::No => { + relation.register_alias_relate_predicate(a, b); + Ok(a) + } + } + } + + // All other cases of inference are errors + (ty::Infer(_), _) | (_, ty::Infer(_)) => { + Err(TypeError::Sorts(ExpectedFound::new(true, a, b))) + } + + (ty::Alias(ty::Opaque, _), _) | (_, ty::Alias(ty::Opaque, _)) => { + match self.solver_mode() { + SolverMode::Normal => { + assert!(!self.next_trait_solver()); + structurally_relate_tys(relation, a, b) + } + // During coherence, opaque types should be treated as *possibly* + // equal to any other type (except for possibly itself). This is an + // extremely heavy hammer, but can be relaxed in a forwards-compatible + // way later. + SolverMode::Coherence => { + relation + .register_predicates([ty::Binder::dummy(ty::PredicateKind::Ambiguous)]); + Ok(a) + } + } + } + + _ => structurally_relate_tys(relation, a, b), + } + } + + fn super_combine_consts( + &self, + relation: &mut R, + a: I::Const, + b: I::Const, + ) -> RelateResult + where + R: PredicateEmittingRelation, + { + debug!("super_combine_consts::<{}>({:?}, {:?})", std::any::type_name::(), a, b); + debug_assert!(!a.has_escaping_bound_vars()); + debug_assert!(!b.has_escaping_bound_vars()); + + if a == b { + return Ok(a); + } + + let a = self.shallow_resolve_const(a); + let b = self.shallow_resolve_const(b); + + match (a.kind(), b.kind()) { + ( + ty::ConstKind::Infer(ty::InferConst::Var(a_vid)), + ty::ConstKind::Infer(ty::InferConst::Var(b_vid)), + ) => { + self.equate_const_vids_raw(a_vid, b_vid); + Ok(a) + } + + ( + ty::ConstKind::Infer(ty::InferConst::EffectVar(a_vid)), + ty::ConstKind::Infer(ty::InferConst::EffectVar(b_vid)), + ) => { + self.equate_effect_vids_raw(a_vid, b_vid); + Ok(a) + } + + // All other cases of inference with other variables are errors. + ( + ty::ConstKind::Infer(ty::InferConst::Var(_) | ty::InferConst::EffectVar(_)), + ty::ConstKind::Infer(_), + ) + | ( + ty::ConstKind::Infer(_), + ty::ConstKind::Infer(ty::InferConst::Var(_) | ty::InferConst::EffectVar(_)), + ) => { + panic!( + "tried to combine ConstKind::Infer/ConstKind::Infer(InferConst::Var): {a:?} and {b:?}" + ) + } + + (ty::ConstKind::Infer(ty::InferConst::Var(vid)), _) => { + self.instantiate_const_var_raw(relation, true, vid, b)?; + Ok(b) + } + + (_, ty::ConstKind::Infer(ty::InferConst::Var(vid))) => { + self.instantiate_const_var_raw(relation, false, vid, a)?; + Ok(a) + } + + (ty::ConstKind::Infer(ty::InferConst::EffectVar(vid)), _) => { + self.instantiate_effect_var_raw(vid, b); + Ok(b) + } + + (_, ty::ConstKind::Infer(ty::InferConst::EffectVar(vid))) => { + self.instantiate_effect_var_raw(vid, a); + Ok(a) + } + + (ty::ConstKind::Unevaluated(..), _) | (_, ty::ConstKind::Unevaluated(..)) + if self.cx().features().generic_const_exprs() || self.next_trait_solver() => + { + match relation.structurally_relate_aliases() { + StructurallyRelateAliases::No => { + relation.register_predicates([if self.next_trait_solver() { + ty::PredicateKind::AliasRelate( + a.into(), + b.into(), + ty::AliasRelationDirection::Equate, + ) + } else { + ty::PredicateKind::ConstEquate(a, b) + }]); + + Ok(b) + } + StructurallyRelateAliases::Yes => structurally_relate_consts(relation, a, b), + } + } + _ => structurally_relate_consts(relation, a, b), + } + } +} From efb1c23ff602485531d65d31ed014d4575a12cec Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 4 Oct 2024 12:58:20 -0400 Subject: [PATCH 158/357] Introduce SolverRelating --- compiler/rustc_infer/src/infer/context.rs | 35 +- compiler/rustc_middle/src/ty/context.rs | 6 + compiler/rustc_type_ir/src/infer_ctxt.rs | 15 + compiler/rustc_type_ir/src/inherent.rs | 4 + compiler/rustc_type_ir/src/interner.rs | 2 +- compiler/rustc_type_ir/src/lib.rs | 4 +- compiler/rustc_type_ir/src/relate.rs | 1 + .../src/relate/solver_relating.rs | 324 ++++++++++++++++++ 8 files changed, 387 insertions(+), 4 deletions(-) create mode 100644 compiler/rustc_type_ir/src/relate/solver_relating.rs diff --git a/compiler/rustc_infer/src/infer/context.rs b/compiler/rustc_infer/src/infer/context.rs index 10b22c98a0d..497be6b5404 100644 --- a/compiler/rustc_infer/src/infer/context.rs +++ b/compiler/rustc_infer/src/infer/context.rs @@ -136,6 +136,10 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> { self.enter_forall(value, f) } + fn equate_ty_vids_raw(&self, a: rustc_type_ir::TyVid, b: rustc_type_ir::TyVid) { + self.inner.borrow_mut().type_variables().equate(a, b); + } + fn equate_int_vids_raw(&self, a: rustc_type_ir::IntVid, b: rustc_type_ir::IntVid) { self.inner.borrow_mut().int_unification_table().union(a, b); } @@ -152,6 +156,23 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> { self.inner.borrow_mut().effect_unification_table().union(a, b); } + fn instantiate_ty_var_raw>( + &self, + relation: &mut R, + target_is_expected: bool, + target_vid: rustc_type_ir::TyVid, + instantiation_variance: rustc_type_ir::Variance, + source_ty: Ty<'tcx>, + ) -> RelateResult<'tcx, ()> { + self.instantiate_ty_var( + relation, + target_is_expected, + target_vid, + instantiation_variance, + source_ty, + ) + } + fn instantiate_int_var_raw( &self, vid: rustc_type_ir::IntVid, @@ -228,7 +249,19 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> { } fn sub_regions(&self, sub: ty::Region<'tcx>, sup: ty::Region<'tcx>) { - self.sub_regions(SubregionOrigin::RelateRegionParamBound(DUMMY_SP, None), sub, sup) + self.inner.borrow_mut().unwrap_region_constraints().make_subregion( + SubregionOrigin::RelateRegionParamBound(DUMMY_SP, None), + sub, + sup, + ); + } + + fn equate_regions(&self, a: ty::Region<'tcx>, b: ty::Region<'tcx>) { + self.inner.borrow_mut().unwrap_region_constraints().make_eqregion( + SubregionOrigin::RelateRegionParamBound(DUMMY_SP, None), + a, + b, + ); } fn register_ty_outlives(&self, ty: Ty<'tcx>, r: ty::Region<'tcx>) { diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 4a02fce5e7d..90265f67bc1 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -698,6 +698,12 @@ impl<'tcx> rustc_type_ir::inherent::Features> for &'tcx rustc_featu } } +impl<'tcx> rustc_type_ir::inherent::Span> for Span { + fn dummy() -> Self { + DUMMY_SP + } +} + type InternedSet<'tcx, T> = ShardedHashMap, ()>; pub struct CtxtInterners<'tcx> { diff --git a/compiler/rustc_type_ir/src/infer_ctxt.rs b/compiler/rustc_type_ir/src/infer_ctxt.rs index 2f6476c6e23..4b44b5a495e 100644 --- a/compiler/rustc_type_ir/src/infer_ctxt.rs +++ b/compiler/rustc_type_ir/src/infer_ctxt.rs @@ -67,11 +67,20 @@ pub trait InferCtxtLike: Sized { f: impl FnOnce(T) -> U, ) -> U; + fn equate_ty_vids_raw(&self, a: ty::TyVid, b: ty::TyVid); fn equate_int_vids_raw(&self, a: ty::IntVid, b: ty::IntVid); fn equate_float_vids_raw(&self, a: ty::FloatVid, b: ty::FloatVid); fn equate_const_vids_raw(&self, a: ty::ConstVid, b: ty::ConstVid); fn equate_effect_vids_raw(&self, a: ty::EffectVid, b: ty::EffectVid); + fn instantiate_ty_var_raw>( + &self, + relation: &mut R, + target_is_expected: bool, + target_vid: ty::TyVid, + instantiation_variance: ty::Variance, + source_ty: ::Ty, + ) -> RelateResult; fn instantiate_int_var_raw(&self, vid: ty::IntVid, value: ty::IntVarValue); fn instantiate_float_var_raw(&self, vid: ty::FloatVid, value: ty::FloatVarValue); fn instantiate_effect_var_raw( @@ -125,6 +134,12 @@ pub trait InferCtxtLike: Sized { sup: ::Region, ); + fn equate_regions( + &self, + a: ::Region, + b: ::Region, + ); + fn register_ty_outlives( &self, ty: ::Ty, diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index 69665df4bfc..f7875bb5152 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -565,6 +565,10 @@ pub trait BoundExistentialPredicates: ) -> impl IntoIterator>>; } +pub trait Span: Copy + Debug + Hash + Eq + TypeFoldable { + fn dummy() -> Self; +} + pub trait SliceLike: Sized + Copy { type Item: Copy; type IntoIter: Iterator; diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index b2ac67efef6..a72e7b482a6 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -36,7 +36,7 @@ pub trait Interner: { type DefId: DefId; type LocalDefId: Copy + Debug + Hash + Eq + Into + TypeFoldable; - type Span: Copy + Debug + Hash + Eq + TypeFoldable; + type Span: Span; type GenericArgs: GenericArgs; type GenericArgsSlice: Copy + Debug + Hash + Eq + SliceLike; diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index 02a9ad1e35f..51c887fc4da 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -206,8 +206,8 @@ pub fn debug_bound_var( } } -#[derive(Copy, Clone, PartialEq, Eq)] -#[cfg_attr(feature = "nightly", derive(Decodable, Encodable, Hash, HashStable_NoContext))] +#[derive(Copy, Clone, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "nightly", derive(Decodable, Encodable, HashStable_NoContext))] #[cfg_attr(feature = "nightly", rustc_pass_by_value)] pub enum Variance { Covariant, // T <: T iff A <: B -- e.g., function return type diff --git a/compiler/rustc_type_ir/src/relate.rs b/compiler/rustc_type_ir/src/relate.rs index 8e5d917e915..1302906adab 100644 --- a/compiler/rustc_type_ir/src/relate.rs +++ b/compiler/rustc_type_ir/src/relate.rs @@ -10,6 +10,7 @@ use crate::inherent::*; use crate::{self as ty, Interner}; pub mod combine; +pub mod solver_relating; pub type RelateResult = Result>; diff --git a/compiler/rustc_type_ir/src/relate/solver_relating.rs b/compiler/rustc_type_ir/src/relate/solver_relating.rs new file mode 100644 index 00000000000..18a4d5189bb --- /dev/null +++ b/compiler/rustc_type_ir/src/relate/solver_relating.rs @@ -0,0 +1,324 @@ +pub use rustc_type_ir::relate::*; +use rustc_type_ir::solve::Goal; +use rustc_type_ir::{self as ty, InferCtxtLike, Interner}; +use tracing::{debug, instrument}; + +use self::combine::{InferCtxtCombineExt, PredicateEmittingRelation}; +use crate::data_structures::DelayedSet; + +#[allow(unused)] +/// Enforce that `a` is equal to or a subtype of `b`. +pub struct SolverRelating<'infcx, Infcx, I: Interner> { + infcx: &'infcx Infcx, + // Immutable fields. + structurally_relate_aliases: StructurallyRelateAliases, + param_env: I::ParamEnv, + // Mutable fields. + ambient_variance: ty::Variance, + goals: Vec>, + /// The cache only tracks the `ambient_variance` as it's the + /// only field which is mutable and which meaningfully changes + /// the result when relating types. + /// + /// The cache does not track whether the state of the + /// `Infcx` has been changed or whether we've added any + /// goals to `self.goals`. Whether a goal is added once or multiple + /// times is not really meaningful. + /// + /// Changes in the inference state may delay some type inference to + /// the next fulfillment loop. Given that this loop is already + /// necessary, this is also not a meaningful change. Consider + /// the following three relations: + /// ```text + /// Vec sub Vec + /// ?0 eq u32 + /// Vec sub Vec + /// ``` + /// Without a cache, the second `Vec sub Vec` would eagerly + /// constrain `?1` to `u32`. When using the cache entry from the + /// first time we've related these types, this only happens when + /// later proving the `Subtype(?0, ?1)` goal from the first relation. + cache: DelayedSet<(ty::Variance, I::Ty, I::Ty)>, +} + +impl<'infcx, Infcx, I> SolverRelating<'infcx, Infcx, I> +where + Infcx: InferCtxtLike, + I: Interner, +{ +} + +impl TypeRelation for SolverRelating<'_, Infcx, I> +where + Infcx: InferCtxtLike, + I: Interner, +{ + fn cx(&self) -> I { + self.infcx.cx() + } + + fn relate_item_args( + &mut self, + item_def_id: I::DefId, + a_arg: I::GenericArgs, + b_arg: I::GenericArgs, + ) -> RelateResult { + if self.ambient_variance == ty::Invariant { + // Avoid fetching the variance if we are in an invariant + // context; no need, and it can induce dependency cycles + // (e.g., #41849). + relate_args_invariantly(self, a_arg, b_arg) + } else { + let tcx = self.cx(); + let opt_variances = tcx.variances_of(item_def_id); + relate_args_with_variances(self, item_def_id, opt_variances, a_arg, b_arg, false) + } + } + + fn relate_with_variance>( + &mut self, + variance: ty::Variance, + _info: VarianceDiagInfo, + a: T, + b: T, + ) -> RelateResult { + let old_ambient_variance = self.ambient_variance; + self.ambient_variance = self.ambient_variance.xform(variance); + debug!(?self.ambient_variance, "new ambient variance"); + + let r = if self.ambient_variance == ty::Bivariant { Ok(a) } else { self.relate(a, b) }; + + self.ambient_variance = old_ambient_variance; + r + } + + #[instrument(skip(self), level = "trace")] + fn tys(&mut self, a: I::Ty, b: I::Ty) -> RelateResult { + if a == b { + return Ok(a); + } + + let infcx = self.infcx; + let a = infcx.shallow_resolve(a); + let b = infcx.shallow_resolve(b); + + if self.cache.contains(&(self.ambient_variance, a, b)) { + return Ok(a); + } + + match (a.kind(), b.kind()) { + (ty::Infer(ty::TyVar(a_id)), ty::Infer(ty::TyVar(b_id))) => { + match self.ambient_variance { + ty::Covariant => { + // can't make progress on `A <: B` if both A and B are + // type variables, so record an obligation. + self.goals.push(Goal::new( + self.cx(), + self.param_env, + ty::Binder::dummy(ty::PredicateKind::Subtype(ty::SubtypePredicate { + a_is_expected: true, + a, + b, + })), + )); + } + ty::Contravariant => { + // can't make progress on `B <: A` if both A and B are + // type variables, so record an obligation. + self.goals.push(Goal::new( + self.cx(), + self.param_env, + ty::Binder::dummy(ty::PredicateKind::Subtype(ty::SubtypePredicate { + a_is_expected: false, + a: b, + b: a, + })), + )); + } + ty::Invariant => { + infcx.equate_ty_vids_raw(a_id, b_id); + } + ty::Bivariant => { + unreachable!("Expected bivariance to be handled in relate_with_variance") + } + } + } + + (ty::Infer(ty::TyVar(a_vid)), _) => { + infcx.instantiate_ty_var_raw(self, true, a_vid, self.ambient_variance, b)?; + } + (_, ty::Infer(ty::TyVar(b_vid))) => { + infcx.instantiate_ty_var_raw( + self, + false, + b_vid, + self.ambient_variance.xform(ty::Contravariant), + a, + )?; + } + + _ => { + self.infcx.super_combine_tys(self, a, b)?; + } + } + + assert!(self.cache.insert((self.ambient_variance, a, b))); + + Ok(a) + } + + #[instrument(skip(self), level = "trace")] + fn regions(&mut self, a: I::Region, b: I::Region) -> RelateResult { + match self.ambient_variance { + // Subtype(&'a u8, &'b u8) => Outlives('a: 'b) => SubRegion('b, 'a) + ty::Covariant => self.infcx.sub_regions(b, a), + // Suptype(&'a u8, &'b u8) => Outlives('b: 'a) => SubRegion('a, 'b) + ty::Contravariant => self.infcx.sub_regions(a, b), + ty::Invariant => self.infcx.equate_regions(a, b), + ty::Bivariant => { + unreachable!("Expected bivariance to be handled in relate_with_variance") + } + } + + Ok(a) + } + + #[instrument(skip(self), level = "trace")] + fn consts(&mut self, a: I::Const, b: I::Const) -> RelateResult { + self.infcx.super_combine_consts(self, a, b) + } + + fn binders( + &mut self, + a: ty::Binder, + b: ty::Binder, + ) -> RelateResult> + where + T: Relate, + { + // If they're equal, then short-circuit. + if a == b { + return Ok(a); + } + + // If they have no bound vars, relate normally. + if let Some(a_inner) = a.no_bound_vars() { + if let Some(b_inner) = b.no_bound_vars() { + self.relate(a_inner, b_inner)?; + return Ok(a); + } + }; + + match self.ambient_variance { + // Checks whether `for<..> sub <: for<..> sup` holds. + // + // For this to hold, **all** instantiations of the super type + // have to be a super type of **at least one** instantiation of + // the subtype. + // + // This is implemented by first entering a new universe. + // We then replace all bound variables in `sup` with placeholders, + // and all bound variables in `sub` with inference vars. + // We can then just relate the two resulting types as normal. + // + // Note: this is a subtle algorithm. For a full explanation, please see + // the [rustc dev guide][rd] + // + // [rd]: https://rustc-dev-guide.rust-lang.org/borrow_check/region_inference/placeholders_and_universes.html + ty::Covariant => { + self.infcx.enter_forall(b, |b| { + let a = self.infcx.instantiate_binder_with_infer(a); + self.relate(a, b) + })?; + } + ty::Contravariant => { + self.infcx.enter_forall(a, |a| { + let b = self.infcx.instantiate_binder_with_infer(b); + self.relate(a, b) + })?; + } + + // When **equating** binders, we check that there is a 1-to-1 + // correspondence between the bound vars in both types. + // + // We do so by separately instantiating one of the binders with + // placeholders and the other with inference variables and then + // equating the instantiated types. + // + // We want `for<..> A == for<..> B` -- therefore we want + // `exists<..> A == for<..> B` and `exists<..> B == for<..> A`. + // Check if `exists<..> A == for<..> B` + ty::Invariant => { + self.infcx.enter_forall(b, |b| { + let a = self.infcx.instantiate_binder_with_infer(a); + self.relate(a, b) + })?; + + // Check if `exists<..> B == for<..> A`. + self.infcx.enter_forall(a, |a| { + let b = self.infcx.instantiate_binder_with_infer(b); + self.relate(a, b) + })?; + } + ty::Bivariant => { + unreachable!("Expected bivariance to be handled in relate_with_variance") + } + } + Ok(a) + } +} + +impl PredicateEmittingRelation for SolverRelating<'_, Infcx, I> +where + Infcx: InferCtxtLike, + I: Interner, +{ + fn span(&self) -> I::Span { + Span::dummy() + } + + fn param_env(&self) -> I::ParamEnv { + self.param_env + } + + fn structurally_relate_aliases(&self) -> StructurallyRelateAliases { + self.structurally_relate_aliases + } + + fn register_predicates( + &mut self, + obligations: impl IntoIterator>, + ) { + self.goals.extend( + obligations.into_iter().map(|pred| Goal::new(self.infcx.cx(), self.param_env, pred)), + ); + } + + fn register_goals(&mut self, obligations: impl IntoIterator>) { + self.goals.extend(obligations); + } + + fn register_alias_relate_predicate(&mut self, a: I::Ty, b: I::Ty) { + self.register_predicates([ty::Binder::dummy(match self.ambient_variance { + ty::Covariant => ty::PredicateKind::AliasRelate( + a.into(), + b.into(), + ty::AliasRelationDirection::Subtype, + ), + // a :> b is b <: a + ty::Contravariant => ty::PredicateKind::AliasRelate( + b.into(), + a.into(), + ty::AliasRelationDirection::Subtype, + ), + ty::Invariant => ty::PredicateKind::AliasRelate( + a.into(), + b.into(), + ty::AliasRelationDirection::Equate, + ), + ty::Bivariant => { + unreachable!("Expected bivariance to be handled in relate_with_variance") + } + })]); + } +} From 3da257a98d44efb5f1a7df2e4237935bcf0f2b92 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 6 Aug 2024 12:50:18 -0400 Subject: [PATCH 159/357] Use SolverRelating in new solver --- compiler/rustc_infer/src/infer/at.rs | 43 ------------- compiler/rustc_infer/src/infer/context.rs | 24 +------ compiler/rustc_infer/src/infer/mod.rs | 6 -- compiler/rustc_infer/src/infer/relate/mod.rs | 1 - .../src/solve/eval_ctxt/canonical.rs | 1 + .../src/solve/eval_ctxt/mod.rs | 1 + .../src/error_reporting/infer/mod.rs | 6 -- compiler/rustc_type_ir/src/infer_ctxt.rs | 19 +----- .../src/relate/solver_relating.rs | 64 ++++++++++++++++++- 9 files changed, 68 insertions(+), 97 deletions(-) diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs index 5422761a6cf..ee9f548c1d4 100644 --- a/compiler/rustc_infer/src/infer/at.rs +++ b/compiler/rustc_infer/src/infer/at.rs @@ -208,49 +208,6 @@ impl<'a, 'tcx> At<'a, 'tcx> { } } - /// Used in the new solver since we don't care about tracking an `ObligationCause`. - pub fn relate_no_trace( - self, - expected: T, - variance: ty::Variance, - actual: T, - ) -> Result>>, NoSolution> - where - T: Relate>, - { - let mut op = TypeRelating::new( - self.infcx, - TypeTrace::dummy(self.cause), - self.param_env, - DefineOpaqueTypes::Yes, - StructurallyRelateAliases::No, - variance, - ); - op.relate(expected, actual)?; - Ok(op.into_obligations().into_iter().map(|o| o.into()).collect()) - } - - /// Used in the new solver since we don't care about tracking an `ObligationCause`. - pub fn eq_structurally_relating_aliases_no_trace( - self, - expected: T, - actual: T, - ) -> Result>>, NoSolution> - where - T: Relate>, - { - let mut op = TypeRelating::new( - self.infcx, - TypeTrace::dummy(self.cause), - self.param_env, - DefineOpaqueTypes::Yes, - StructurallyRelateAliases::Yes, - ty::Invariant, - ); - op.relate(expected, actual)?; - Ok(op.into_obligations().into_iter().map(|o| o.into()).collect()) - } - /// Computes the least-upper-bound, or mutual supertype, of two /// values. The order of the arguments doesn't matter, but since /// this can result in an error (e.g., if asked to compute LUB of diff --git a/compiler/rustc_infer/src/infer/context.rs b/compiler/rustc_infer/src/infer/context.rs index 497be6b5404..57007752cad 100644 --- a/compiler/rustc_infer/src/infer/context.rs +++ b/compiler/rustc_infer/src/infer/context.rs @@ -2,10 +2,10 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::infer::unify_key::EffectVarValue; use rustc_middle::traits::ObligationCause; -use rustc_middle::traits::solve::{Goal, NoSolution, SolverMode}; +use rustc_middle::traits::solve::SolverMode; use rustc_middle::ty::fold::TypeFoldable; +use rustc_middle::ty::relate::RelateResult; use rustc_middle::ty::relate::combine::PredicateEmittingRelation; -use rustc_middle::ty::relate::{Relate, RelateResult}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::{DUMMY_SP, ErrorGuaranteed}; @@ -210,26 +210,6 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> { self.set_tainted_by_errors(e) } - fn relate>>( - &self, - param_env: ty::ParamEnv<'tcx>, - lhs: T, - variance: ty::Variance, - rhs: T, - ) -> Result>>, NoSolution> { - self.at(&ObligationCause::dummy(), param_env).relate_no_trace(lhs, variance, rhs) - } - - fn eq_structurally_relating_aliases>>( - &self, - param_env: ty::ParamEnv<'tcx>, - lhs: T, - rhs: T, - ) -> Result>>, NoSolution> { - self.at(&ObligationCause::dummy(), param_env) - .eq_structurally_relating_aliases_no_trace(lhs, rhs) - } - fn shallow_resolve(&self, ty: Ty<'tcx>) -> Ty<'tcx> { self.shallow_resolve(ty) } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 21f9bf028d5..bc813305ba4 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -32,7 +32,6 @@ use rustc_middle::infer::unify_key::{ use rustc_middle::mir::ConstraintCategory; use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult}; use rustc_middle::traits::select; -use rustc_middle::traits::solve::{Goal, NoSolution}; pub use rustc_middle::ty::IntVarValue; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::fold::{ @@ -340,7 +339,6 @@ pub enum ValuePairs<'tcx> { PolySigs(ExpectedFound>), ExistentialTraitRef(ExpectedFound>), ExistentialProjection(ExpectedFound>), - Dummy, } impl<'tcx> ValuePairs<'tcx> { @@ -1638,10 +1636,6 @@ impl<'tcx> TypeTrace<'tcx> { values: ValuePairs::Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())), } } - - fn dummy(cause: &ObligationCause<'tcx>) -> TypeTrace<'tcx> { - TypeTrace { cause: cause.clone(), values: ValuePairs::Dummy } - } } impl<'tcx> SubregionOrigin<'tcx> { diff --git a/compiler/rustc_infer/src/infer/relate/mod.rs b/compiler/rustc_infer/src/infer/relate/mod.rs index e156f72d78d..e6d1003cab6 100644 --- a/compiler/rustc_infer/src/infer/relate/mod.rs +++ b/compiler/rustc_infer/src/infer/relate/mod.rs @@ -6,7 +6,6 @@ pub use rustc_middle::ty::relate::RelateResult; pub use rustc_type_ir::relate::combine::PredicateEmittingRelation; pub use rustc_type_ir::relate::*; -#[allow(hidden_glob_reexports)] mod generalize; mod higher_ranked; pub(super) mod lattice; diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs index 252a9ed1a2e..3b6197c6759 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs @@ -14,6 +14,7 @@ use std::iter; use rustc_index::IndexVec; use rustc_type_ir::fold::TypeFoldable; use rustc_type_ir::inherent::*; +use rustc_type_ir::relate::solver_relating::RelateExt; use rustc_type_ir::{self as ty, Canonical, CanonicalVarValues, InferCtxtLike, Interner}; use tracing::{instrument, trace}; diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index ffa800348f2..970ef905dfd 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -7,6 +7,7 @@ use rustc_type_ir::data_structures::{HashMap, HashSet, ensure_sufficient_stack}; use rustc_type_ir::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; use rustc_type_ir::inherent::*; use rustc_type_ir::relate::Relate; +use rustc_type_ir::relate::solver_relating::RelateExt; use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor}; use rustc_type_ir::{self as ty, CanonicalVarValues, InferCtxtLike, Interner}; use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic}; diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs index c7b3f704330..bd78a6ee3af 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs @@ -1285,9 +1285,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ValuePairs::ExistentialProjection(_) => { (false, Mismatch::Fixed("existential projection")) } - ValuePairs::Dummy => { - bug!("do not expect to report a type error from a ValuePairs::Dummy") - } }; let Some(vals) = self.values_str(values) else { // Derived error. Cancel the emitter. @@ -1853,9 +1850,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let (exp, fnd) = self.cmp_fn_sig(&exp_found.expected, &exp_found.found); Some((exp, fnd, None)) } - ValuePairs::Dummy => { - bug!("do not expect to report a type error from a ValuePairs::Dummy") - } } } diff --git a/compiler/rustc_type_ir/src/infer_ctxt.rs b/compiler/rustc_type_ir/src/infer_ctxt.rs index 4b44b5a495e..b9f5cde653e 100644 --- a/compiler/rustc_type_ir/src/infer_ctxt.rs +++ b/compiler/rustc_type_ir/src/infer_ctxt.rs @@ -1,7 +1,7 @@ use crate::fold::TypeFoldable; +use crate::relate::RelateResult; use crate::relate::combine::PredicateEmittingRelation; -use crate::relate::{Relate, RelateResult}; -use crate::solve::{Goal, NoSolution, SolverMode}; +use crate::solve::SolverMode; use crate::{self as ty, Interner}; pub trait InferCtxtLike: Sized { @@ -98,21 +98,6 @@ pub trait InferCtxtLike: Sized { fn set_tainted_by_errors(&self, e: ::ErrorGuaranteed); - fn relate>( - &self, - param_env: ::ParamEnv, - lhs: T, - variance: ty::Variance, - rhs: T, - ) -> Result::Predicate>>, NoSolution>; - - fn eq_structurally_relating_aliases>( - &self, - param_env: ::ParamEnv, - lhs: T, - rhs: T, - ) -> Result::Predicate>>, NoSolution>; - fn shallow_resolve( &self, ty: ::Ty, diff --git a/compiler/rustc_type_ir/src/relate/solver_relating.rs b/compiler/rustc_type_ir/src/relate/solver_relating.rs index 18a4d5189bb..a2521eda6dd 100644 --- a/compiler/rustc_type_ir/src/relate/solver_relating.rs +++ b/compiler/rustc_type_ir/src/relate/solver_relating.rs @@ -1,12 +1,57 @@ pub use rustc_type_ir::relate::*; -use rustc_type_ir::solve::Goal; +use rustc_type_ir::solve::{Goal, NoSolution}; use rustc_type_ir::{self as ty, InferCtxtLike, Interner}; use tracing::{debug, instrument}; use self::combine::{InferCtxtCombineExt, PredicateEmittingRelation}; use crate::data_structures::DelayedSet; -#[allow(unused)] +pub trait RelateExt: InferCtxtLike { + fn relate>( + &self, + param_env: ::ParamEnv, + lhs: T, + variance: ty::Variance, + rhs: T, + ) -> Result::Predicate>>, NoSolution>; + + fn eq_structurally_relating_aliases>( + &self, + param_env: ::ParamEnv, + lhs: T, + rhs: T, + ) -> Result::Predicate>>, NoSolution>; +} + +impl RelateExt for Infcx { + fn relate>( + &self, + param_env: ::ParamEnv, + lhs: T, + variance: ty::Variance, + rhs: T, + ) -> Result::Predicate>>, NoSolution> + { + let mut relate = + SolverRelating::new(self, StructurallyRelateAliases::No, variance, param_env); + relate.relate(lhs, rhs)?; + Ok(relate.goals) + } + + fn eq_structurally_relating_aliases>( + &self, + param_env: ::ParamEnv, + lhs: T, + rhs: T, + ) -> Result::Predicate>>, NoSolution> + { + let mut relate = + SolverRelating::new(self, StructurallyRelateAliases::Yes, ty::Invariant, param_env); + relate.relate(lhs, rhs)?; + Ok(relate.goals) + } +} + /// Enforce that `a` is equal to or a subtype of `b`. pub struct SolverRelating<'infcx, Infcx, I: Interner> { infcx: &'infcx Infcx, @@ -46,6 +91,21 @@ where Infcx: InferCtxtLike, I: Interner, { + fn new( + infcx: &'infcx Infcx, + structurally_relate_aliases: StructurallyRelateAliases, + ambient_variance: ty::Variance, + param_env: I::ParamEnv, + ) -> Self { + SolverRelating { + infcx, + structurally_relate_aliases, + ambient_variance, + param_env, + goals: vec![], + cache: Default::default(), + } + } } impl TypeRelation for SolverRelating<'_, Infcx, I> From 30a2ecddb45f30dc62946770ef88df115f194b17 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 4 Oct 2024 13:07:34 -0400 Subject: [PATCH 160/357] Remove unnecessary StructurallyRelateAliases from CombineFields/TypeRelating --- compiler/rustc_infer/src/infer/at.rs | 5 +---- compiler/rustc_infer/src/infer/relate/type_relating.rs | 5 +---- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs index ee9f548c1d4..1b99effabc0 100644 --- a/compiler/rustc_infer/src/infer/at.rs +++ b/compiler/rustc_infer/src/infer/at.rs @@ -31,7 +31,7 @@ use rustc_middle::ty::{Const, ImplSubject}; use super::*; use crate::infer::relate::type_relating::TypeRelating; -use crate::infer::relate::{Relate, StructurallyRelateAliases, TypeRelation}; +use crate::infer::relate::{Relate, TypeRelation}; /// Whether we should define opaque types or just treat them opaquely. /// @@ -114,7 +114,6 @@ impl<'a, 'tcx> At<'a, 'tcx> { ToTrace::to_trace(self.cause, expected, actual), self.param_env, define_opaque_types, - StructurallyRelateAliases::No, ty::Contravariant, ); op.relate(expected, actual)?; @@ -136,7 +135,6 @@ impl<'a, 'tcx> At<'a, 'tcx> { ToTrace::to_trace(self.cause, expected, actual), self.param_env, define_opaque_types, - StructurallyRelateAliases::No, ty::Covariant, ); op.relate(expected, actual)?; @@ -177,7 +175,6 @@ impl<'a, 'tcx> At<'a, 'tcx> { trace, self.param_env, define_opaque_types, - StructurallyRelateAliases::No, ty::Invariant, ); op.relate(expected, actual)?; diff --git a/compiler/rustc_infer/src/infer/relate/type_relating.rs b/compiler/rustc_infer/src/infer/relate/type_relating.rs index d2dc4589103..6129faf3d50 100644 --- a/compiler/rustc_infer/src/infer/relate/type_relating.rs +++ b/compiler/rustc_infer/src/infer/relate/type_relating.rs @@ -21,7 +21,6 @@ pub(crate) struct TypeRelating<'infcx, 'tcx> { trace: TypeTrace<'tcx>, param_env: ty::ParamEnv<'tcx>, define_opaque_types: DefineOpaqueTypes, - structurally_relate_aliases: StructurallyRelateAliases, // Mutable fields. ambient_variance: ty::Variance, @@ -57,7 +56,6 @@ impl<'infcx, 'tcx> TypeRelating<'infcx, 'tcx> { trace: TypeTrace<'tcx>, param_env: ty::ParamEnv<'tcx>, define_opaque_types: DefineOpaqueTypes, - structurally_relate_aliases: StructurallyRelateAliases, ambient_variance: ty::Variance, ) -> TypeRelating<'infcx, 'tcx> { TypeRelating { @@ -65,7 +63,6 @@ impl<'infcx, 'tcx> TypeRelating<'infcx, 'tcx> { trace, param_env, define_opaque_types, - structurally_relate_aliases, ambient_variance, obligations: vec![], cache: Default::default(), @@ -353,7 +350,7 @@ impl<'tcx> PredicateEmittingRelation> for TypeRelating<'_, 'tcx> } fn structurally_relate_aliases(&self) -> StructurallyRelateAliases { - self.structurally_relate_aliases + StructurallyRelateAliases::No } fn register_predicates( From a4cd2202ef10e217e2905ba905dd5536958528ab Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 4 Oct 2024 13:30:51 -0400 Subject: [PATCH 161/357] Use SolverRelating in favor of TypeRelating in the old solver where possible --- compiler/rustc_infer/src/infer/at.rs | 98 ++++++++++++++----- .../src/infer/relate/type_relating.rs | 5 +- .../src/solve/eval_ctxt/mod.rs | 2 +- .../src/relate/solver_relating.rs | 26 +++-- 4 files changed, 92 insertions(+), 39 deletions(-) diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs index 1b99effabc0..8c943a961e7 100644 --- a/compiler/rustc_infer/src/infer/at.rs +++ b/compiler/rustc_infer/src/infer/at.rs @@ -27,11 +27,14 @@ use relate::lattice::{LatticeOp, LatticeOpKind}; use rustc_middle::bug; +use rustc_middle::ty::relate::solver_relating::RelateExt as NextSolverRelate; use rustc_middle::ty::{Const, ImplSubject}; use super::*; use crate::infer::relate::type_relating::TypeRelating; use crate::infer::relate::{Relate, TypeRelation}; +use crate::traits::Obligation; +use crate::traits::solve::Goal; /// Whether we should define opaque types or just treat them opaquely. /// @@ -109,15 +112,26 @@ impl<'a, 'tcx> At<'a, 'tcx> { where T: ToTrace<'tcx>, { - let mut op = TypeRelating::new( - self.infcx, - ToTrace::to_trace(self.cause, expected, actual), - self.param_env, - define_opaque_types, - ty::Contravariant, - ); - op.relate(expected, actual)?; - Ok(InferOk { value: (), obligations: op.into_obligations() }) + if self.infcx.next_trait_solver { + NextSolverRelate::relate( + self.infcx, + self.param_env, + expected, + ty::Contravariant, + actual, + ) + .map(|goals| self.goals_to_obligations(goals)) + } else { + let mut op = TypeRelating::new( + self.infcx, + ToTrace::to_trace(self.cause, expected, actual), + self.param_env, + define_opaque_types, + ty::Contravariant, + ); + op.relate(expected, actual)?; + Ok(InferOk { value: (), obligations: op.into_obligations() }) + } } /// Makes `expected <: actual`. @@ -130,15 +144,20 @@ impl<'a, 'tcx> At<'a, 'tcx> { where T: ToTrace<'tcx>, { - let mut op = TypeRelating::new( - self.infcx, - ToTrace::to_trace(self.cause, expected, actual), - self.param_env, - define_opaque_types, - ty::Covariant, - ); - op.relate(expected, actual)?; - Ok(InferOk { value: (), obligations: op.into_obligations() }) + if self.infcx.next_trait_solver { + NextSolverRelate::relate(self.infcx, self.param_env, expected, ty::Covariant, actual) + .map(|goals| self.goals_to_obligations(goals)) + } else { + let mut op = TypeRelating::new( + self.infcx, + ToTrace::to_trace(self.cause, expected, actual), + self.param_env, + define_opaque_types, + ty::Covariant, + ); + op.relate(expected, actual)?; + Ok(InferOk { value: (), obligations: op.into_obligations() }) + } } /// Makes `expected == actual`. @@ -170,15 +189,20 @@ impl<'a, 'tcx> At<'a, 'tcx> { where T: Relate>, { - let mut op = TypeRelating::new( - self.infcx, - trace, - self.param_env, - define_opaque_types, - ty::Invariant, - ); - op.relate(expected, actual)?; - Ok(InferOk { value: (), obligations: op.into_obligations() }) + if self.infcx.next_trait_solver { + NextSolverRelate::relate(self.infcx, self.param_env, expected, ty::Invariant, actual) + .map(|goals| self.goals_to_obligations(goals)) + } else { + let mut op = TypeRelating::new( + self.infcx, + trace, + self.param_env, + define_opaque_types, + ty::Invariant, + ); + op.relate(expected, actual)?; + Ok(InferOk { value: (), obligations: op.into_obligations() }) + } } pub fn relate( @@ -223,6 +247,26 @@ impl<'a, 'tcx> At<'a, 'tcx> { let value = op.relate(expected, actual)?; Ok(InferOk { value, obligations: op.into_obligations() }) } + + fn goals_to_obligations( + &self, + goals: Vec>>, + ) -> InferOk<'tcx, ()> { + InferOk { + value: (), + obligations: goals + .into_iter() + .map(|goal| { + Obligation::new( + self.infcx.tcx, + self.cause.clone(), + goal.param_env, + goal.predicate, + ) + }) + .collect(), + } + } } impl<'tcx> ToTrace<'tcx> for ImplSubject<'tcx> { diff --git a/compiler/rustc_infer/src/infer/relate/type_relating.rs b/compiler/rustc_infer/src/infer/relate/type_relating.rs index 6129faf3d50..1cc968ca275 100644 --- a/compiler/rustc_infer/src/infer/relate/type_relating.rs +++ b/compiler/rustc_infer/src/infer/relate/type_relating.rs @@ -58,6 +58,7 @@ impl<'infcx, 'tcx> TypeRelating<'infcx, 'tcx> { define_opaque_types: DefineOpaqueTypes, ambient_variance: ty::Variance, ) -> TypeRelating<'infcx, 'tcx> { + assert!(!infcx.next_trait_solver); TypeRelating { infcx, trace, @@ -190,9 +191,7 @@ impl<'tcx> TypeRelation> for TypeRelating<'_, 'tcx> { (&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _) | (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. })) - if self.define_opaque_types == DefineOpaqueTypes::Yes - && def_id.is_local() - && !infcx.next_trait_solver() => + if self.define_opaque_types == DefineOpaqueTypes::Yes && def_id.is_local() => { self.register_goals(infcx.handle_opaque_type( a, diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index 970ef905dfd..785bed4ec69 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -836,7 +836,7 @@ where lhs: T, rhs: T, ) -> Result>, NoSolution> { - self.delegate.relate(param_env, lhs, ty::Variance::Invariant, rhs) + Ok(self.delegate.relate(param_env, lhs, ty::Variance::Invariant, rhs)?) } pub(super) fn instantiate_binder_with_infer + Copy>( diff --git a/compiler/rustc_type_ir/src/relate/solver_relating.rs b/compiler/rustc_type_ir/src/relate/solver_relating.rs index a2521eda6dd..edbfaed9709 100644 --- a/compiler/rustc_type_ir/src/relate/solver_relating.rs +++ b/compiler/rustc_type_ir/src/relate/solver_relating.rs @@ -1,5 +1,5 @@ pub use rustc_type_ir::relate::*; -use rustc_type_ir::solve::{Goal, NoSolution}; +use rustc_type_ir::solve::Goal; use rustc_type_ir::{self as ty, InferCtxtLike, Interner}; use tracing::{debug, instrument}; @@ -13,14 +13,20 @@ pub trait RelateExt: InferCtxtLike { lhs: T, variance: ty::Variance, rhs: T, - ) -> Result::Predicate>>, NoSolution>; + ) -> Result< + Vec::Predicate>>, + TypeError, + >; fn eq_structurally_relating_aliases>( &self, param_env: ::ParamEnv, lhs: T, rhs: T, - ) -> Result::Predicate>>, NoSolution>; + ) -> Result< + Vec::Predicate>>, + TypeError, + >; } impl RelateExt for Infcx { @@ -30,8 +36,10 @@ impl RelateExt for Infcx { lhs: T, variance: ty::Variance, rhs: T, - ) -> Result::Predicate>>, NoSolution> - { + ) -> Result< + Vec::Predicate>>, + TypeError, + > { let mut relate = SolverRelating::new(self, StructurallyRelateAliases::No, variance, param_env); relate.relate(lhs, rhs)?; @@ -43,8 +51,10 @@ impl RelateExt for Infcx { param_env: ::ParamEnv, lhs: T, rhs: T, - ) -> Result::Predicate>>, NoSolution> - { + ) -> Result< + Vec::Predicate>>, + TypeError, + > { let mut relate = SolverRelating::new(self, StructurallyRelateAliases::Yes, ty::Invariant, param_env); relate.relate(lhs, rhs)?; @@ -91,7 +101,7 @@ where Infcx: InferCtxtLike, I: Interner, { - fn new( + pub fn new( infcx: &'infcx Infcx, structurally_relate_aliases: StructurallyRelateAliases, ambient_variance: ty::Variance, From 8715bfbf0ef398780451e9f45d036cf8353b1e60 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 10 Oct 2024 05:40:56 -0400 Subject: [PATCH 162/357] Make super combine into fns --- .../src/type_check/relate_tys.rs | 8 +- .../rustc_infer/src/infer/relate/lattice.rs | 8 +- .../src/infer/relate/type_relating.rs | 8 +- compiler/rustc_type_ir/src/relate/combine.rs | 395 +++++++++--------- .../src/relate/solver_relating.rs | 6 +- 5 files changed, 208 insertions(+), 217 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs index e72c21e8fad..cfc14d146bd 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -11,7 +11,7 @@ use rustc_middle::span_bug; use rustc_middle::traits::ObligationCause; use rustc_middle::traits::query::NoSolution; use rustc_middle::ty::fold::FnMutDelegate; -use rustc_middle::ty::relate::combine::InferCtxtCombineExt; +use rustc_middle::ty::relate::combine::{super_combine_consts, super_combine_tys}; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt}; use rustc_span::symbol::sym; use rustc_span::{Span, Symbol}; @@ -363,7 +363,7 @@ impl<'b, 'tcx> TypeRelation> for NllTypeRelating<'_, 'b, 'tcx> { &ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, .. }), &ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }), ) if a_def_id == b_def_id || infcx.next_trait_solver() => { - infcx.super_combine_tys(self, a, b).map(|_| ()).or_else(|err| { + super_combine_tys(&infcx.infcx, self, a, b).map(|_| ()).or_else(|err| { // This behavior is only there for the old solver, the new solver // shouldn't ever fail. Instead, it unconditionally emits an // alias-relate goal. @@ -386,7 +386,7 @@ impl<'b, 'tcx> TypeRelation> for NllTypeRelating<'_, 'b, 'tcx> { debug!(?a, ?b, ?self.ambient_variance); // Will also handle unification of `IntVar` and `FloatVar`. - self.type_checker.infcx.super_combine_tys(self, a, b)?; + super_combine_tys(&self.type_checker.infcx.infcx, self, a, b)?; } } @@ -423,7 +423,7 @@ impl<'b, 'tcx> TypeRelation> for NllTypeRelating<'_, 'b, 'tcx> { assert!(!a.has_non_region_infer(), "unexpected inference var {:?}", a); assert!(!b.has_non_region_infer(), "unexpected inference var {:?}", b); - self.type_checker.infcx.super_combine_consts(self, a, b) + super_combine_consts(&self.type_checker.infcx.infcx, self, a, b) } #[instrument(skip(self), level = "trace")] diff --git a/compiler/rustc_infer/src/infer/relate/lattice.rs b/compiler/rustc_infer/src/infer/relate/lattice.rs index fc208a08471..7eb61abfbc1 100644 --- a/compiler/rustc_infer/src/infer/relate/lattice.rs +++ b/compiler/rustc_infer/src/infer/relate/lattice.rs @@ -18,7 +18,7 @@ //! [lattices]: https://en.wikipedia.org/wiki/Lattice_(order) use rustc_middle::traits::solve::Goal; -use rustc_middle::ty::relate::combine::InferCtxtCombineExt; +use rustc_middle::ty::relate::combine::{super_combine_consts, super_combine_tys}; use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation}; use rustc_middle::ty::{self, Ty, TyCtxt, TyVar, TypeVisitableExt}; use rustc_span::Span; @@ -149,7 +149,7 @@ impl<'tcx> TypeRelation> for LatticeOp<'_, 'tcx> { ( &ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, .. }), &ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }), - ) if a_def_id == b_def_id => infcx.super_combine_tys(self, a, b), + ) if a_def_id == b_def_id => super_combine_tys(infcx, self, a, b), (&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _) | (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. })) @@ -164,7 +164,7 @@ impl<'tcx> TypeRelation> for LatticeOp<'_, 'tcx> { Ok(a) } - _ => infcx.super_combine_tys(self, a, b), + _ => super_combine_tys(infcx, self, a, b), } } @@ -192,7 +192,7 @@ impl<'tcx> TypeRelation> for LatticeOp<'_, 'tcx> { a: ty::Const<'tcx>, b: ty::Const<'tcx>, ) -> RelateResult<'tcx, ty::Const<'tcx>> { - self.infcx.super_combine_consts(self, a, b) + super_combine_consts(self.infcx, self, a, b) } fn binders( diff --git a/compiler/rustc_infer/src/infer/relate/type_relating.rs b/compiler/rustc_infer/src/infer/relate/type_relating.rs index 1cc968ca275..35103c070c2 100644 --- a/compiler/rustc_infer/src/infer/relate/type_relating.rs +++ b/compiler/rustc_infer/src/infer/relate/type_relating.rs @@ -1,5 +1,5 @@ use rustc_middle::traits::solve::Goal; -use rustc_middle::ty::relate::combine::InferCtxtCombineExt; +use rustc_middle::ty::relate::combine::{super_combine_consts, super_combine_tys}; use rustc_middle::ty::relate::{ Relate, RelateResult, TypeRelation, relate_args_invariantly, relate_args_with_variances, }; @@ -186,7 +186,7 @@ impl<'tcx> TypeRelation> for TypeRelating<'_, 'tcx> { &ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, .. }), &ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }), ) if a_def_id == b_def_id => { - infcx.super_combine_tys(self, a, b)?; + super_combine_tys(infcx, self, a, b)?; } (&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _) @@ -202,7 +202,7 @@ impl<'tcx> TypeRelation> for TypeRelating<'_, 'tcx> { } _ => { - infcx.super_combine_tys(self, a, b)?; + super_combine_tys(infcx, self, a, b)?; } } @@ -257,7 +257,7 @@ impl<'tcx> TypeRelation> for TypeRelating<'_, 'tcx> { a: ty::Const<'tcx>, b: ty::Const<'tcx>, ) -> RelateResult<'tcx, ty::Const<'tcx>> { - self.infcx.super_combine_consts(self, a, b) + super_combine_consts(self.infcx, self, a, b) } fn binders( diff --git a/compiler/rustc_type_ir/src/relate/combine.rs b/compiler/rustc_type_ir/src/relate/combine.rs index 9dfcde609c7..60a953801a4 100644 --- a/compiler/rustc_type_ir/src/relate/combine.rs +++ b/compiler/rustc_type_ir/src/relate/combine.rs @@ -39,217 +39,208 @@ where fn register_alias_relate_predicate(&mut self, a: I::Ty, b: I::Ty); } -pub trait InferCtxtCombineExt: InferCtxtLike { - fn super_combine_tys(&self, relation: &mut R, a: I::Ty, b: I::Ty) -> RelateResult - where - R: PredicateEmittingRelation; +pub fn super_combine_tys( + infcx: &Infcx, + relation: &mut R, + a: I::Ty, + b: I::Ty, +) -> RelateResult +where + Infcx: InferCtxtLike, + I: Interner, + R: PredicateEmittingRelation, +{ + debug!("super_combine_tys::<{}>({:?}, {:?})", std::any::type_name::(), a, b); + debug_assert!(!a.has_escaping_bound_vars()); + debug_assert!(!b.has_escaping_bound_vars()); - fn super_combine_consts( - &self, - relation: &mut R, - a: I::Const, - b: I::Const, - ) -> RelateResult - where - R: PredicateEmittingRelation; -} + match (a.kind(), b.kind()) { + (ty::Error(e), _) | (_, ty::Error(e)) => { + infcx.set_tainted_by_errors(e); + return Ok(Ty::new_error(infcx.cx(), e)); + } -impl> InferCtxtCombineExt for Infcx { - fn super_combine_tys(&self, relation: &mut R, a: I::Ty, b: I::Ty) -> RelateResult - where - R: PredicateEmittingRelation, - { - debug!("super_combine_tys::<{}>({:?}, {:?})", std::any::type_name::(), a, b); - debug_assert!(!a.has_escaping_bound_vars()); - debug_assert!(!b.has_escaping_bound_vars()); + // Relate integral variables to other types + (ty::Infer(ty::IntVar(a_id)), ty::Infer(ty::IntVar(b_id))) => { + infcx.equate_int_vids_raw(a_id, b_id); + Ok(a) + } + (ty::Infer(ty::IntVar(v_id)), ty::Int(v)) => { + infcx.instantiate_int_var_raw(v_id, ty::IntVarValue::IntType(v)); + Ok(b) + } + (ty::Int(v), ty::Infer(ty::IntVar(v_id))) => { + infcx.instantiate_int_var_raw(v_id, ty::IntVarValue::IntType(v)); + Ok(a) + } + (ty::Infer(ty::IntVar(v_id)), ty::Uint(v)) => { + infcx.instantiate_int_var_raw(v_id, ty::IntVarValue::UintType(v)); + Ok(b) + } + (ty::Uint(v), ty::Infer(ty::IntVar(v_id))) => { + infcx.instantiate_int_var_raw(v_id, ty::IntVarValue::UintType(v)); + Ok(a) + } - match (a.kind(), b.kind()) { - (ty::Error(e), _) | (_, ty::Error(e)) => { - self.set_tainted_by_errors(e); - return Ok(Ty::new_error(self.cx(), e)); - } + // Relate floating-point variables to other types + (ty::Infer(ty::FloatVar(a_id)), ty::Infer(ty::FloatVar(b_id))) => { + infcx.equate_float_vids_raw(a_id, b_id); + Ok(a) + } + (ty::Infer(ty::FloatVar(v_id)), ty::Float(v)) => { + infcx.instantiate_float_var_raw(v_id, ty::FloatVarValue::Known(v)); + Ok(b) + } + (ty::Float(v), ty::Infer(ty::FloatVar(v_id))) => { + infcx.instantiate_float_var_raw(v_id, ty::FloatVarValue::Known(v)); + Ok(a) + } - // Relate integral variables to other types - (ty::Infer(ty::IntVar(a_id)), ty::Infer(ty::IntVar(b_id))) => { - self.equate_int_vids_raw(a_id, b_id); - Ok(a) - } - (ty::Infer(ty::IntVar(v_id)), ty::Int(v)) => { - self.instantiate_int_var_raw(v_id, ty::IntVarValue::IntType(v)); - Ok(b) - } - (ty::Int(v), ty::Infer(ty::IntVar(v_id))) => { - self.instantiate_int_var_raw(v_id, ty::IntVarValue::IntType(v)); - Ok(a) - } - (ty::Infer(ty::IntVar(v_id)), ty::Uint(v)) => { - self.instantiate_int_var_raw(v_id, ty::IntVarValue::UintType(v)); - Ok(b) - } - (ty::Uint(v), ty::Infer(ty::IntVar(v_id))) => { - self.instantiate_int_var_raw(v_id, ty::IntVarValue::UintType(v)); - Ok(a) - } - - // Relate floating-point variables to other types - (ty::Infer(ty::FloatVar(a_id)), ty::Infer(ty::FloatVar(b_id))) => { - self.equate_float_vids_raw(a_id, b_id); - Ok(a) - } - (ty::Infer(ty::FloatVar(v_id)), ty::Float(v)) => { - self.instantiate_float_var_raw(v_id, ty::FloatVarValue::Known(v)); - Ok(b) - } - (ty::Float(v), ty::Infer(ty::FloatVar(v_id))) => { - self.instantiate_float_var_raw(v_id, ty::FloatVarValue::Known(v)); - Ok(a) - } - - // We don't expect `TyVar` or `Fresh*` vars at this point with lazy norm. - (ty::Alias(..), ty::Infer(ty::TyVar(_))) | (ty::Infer(ty::TyVar(_)), ty::Alias(..)) - if self.next_trait_solver() => - { - panic!( - "We do not expect to encounter `TyVar` this late in combine \ + // We don't expect `TyVar` or `Fresh*` vars at this point with lazy norm. + (ty::Alias(..), ty::Infer(ty::TyVar(_))) | (ty::Infer(ty::TyVar(_)), ty::Alias(..)) + if infcx.next_trait_solver() => + { + panic!( + "We do not expect to encounter `TyVar` this late in combine \ -- they should have been handled earlier" - ) - } - (_, ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_))) - | (ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)), _) - if self.next_trait_solver() => - { - panic!("We do not expect to encounter `Fresh` variables in the new solver") - } - - (_, ty::Alias(..)) | (ty::Alias(..), _) if self.next_trait_solver() => { - match relation.structurally_relate_aliases() { - StructurallyRelateAliases::Yes => structurally_relate_tys(relation, a, b), - StructurallyRelateAliases::No => { - relation.register_alias_relate_predicate(a, b); - Ok(a) - } - } - } - - // All other cases of inference are errors - (ty::Infer(_), _) | (_, ty::Infer(_)) => { - Err(TypeError::Sorts(ExpectedFound::new(true, a, b))) - } - - (ty::Alias(ty::Opaque, _), _) | (_, ty::Alias(ty::Opaque, _)) => { - match self.solver_mode() { - SolverMode::Normal => { - assert!(!self.next_trait_solver()); - structurally_relate_tys(relation, a, b) - } - // During coherence, opaque types should be treated as *possibly* - // equal to any other type (except for possibly itself). This is an - // extremely heavy hammer, but can be relaxed in a forwards-compatible - // way later. - SolverMode::Coherence => { - relation - .register_predicates([ty::Binder::dummy(ty::PredicateKind::Ambiguous)]); - Ok(a) - } - } - } - - _ => structurally_relate_tys(relation, a, b), - } - } - - fn super_combine_consts( - &self, - relation: &mut R, - a: I::Const, - b: I::Const, - ) -> RelateResult - where - R: PredicateEmittingRelation, - { - debug!("super_combine_consts::<{}>({:?}, {:?})", std::any::type_name::(), a, b); - debug_assert!(!a.has_escaping_bound_vars()); - debug_assert!(!b.has_escaping_bound_vars()); - - if a == b { - return Ok(a); - } - - let a = self.shallow_resolve_const(a); - let b = self.shallow_resolve_const(b); - - match (a.kind(), b.kind()) { - ( - ty::ConstKind::Infer(ty::InferConst::Var(a_vid)), - ty::ConstKind::Infer(ty::InferConst::Var(b_vid)), - ) => { - self.equate_const_vids_raw(a_vid, b_vid); - Ok(a) - } - - ( - ty::ConstKind::Infer(ty::InferConst::EffectVar(a_vid)), - ty::ConstKind::Infer(ty::InferConst::EffectVar(b_vid)), - ) => { - self.equate_effect_vids_raw(a_vid, b_vid); - Ok(a) - } - - // All other cases of inference with other variables are errors. - ( - ty::ConstKind::Infer(ty::InferConst::Var(_) | ty::InferConst::EffectVar(_)), - ty::ConstKind::Infer(_), ) - | ( - ty::ConstKind::Infer(_), - ty::ConstKind::Infer(ty::InferConst::Var(_) | ty::InferConst::EffectVar(_)), - ) => { - panic!( - "tried to combine ConstKind::Infer/ConstKind::Infer(InferConst::Var): {a:?} and {b:?}" - ) - } + } + (_, ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_))) + | (ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)), _) + if infcx.next_trait_solver() => + { + panic!("We do not expect to encounter `Fresh` variables in the new solver") + } - (ty::ConstKind::Infer(ty::InferConst::Var(vid)), _) => { - self.instantiate_const_var_raw(relation, true, vid, b)?; - Ok(b) - } - - (_, ty::ConstKind::Infer(ty::InferConst::Var(vid))) => { - self.instantiate_const_var_raw(relation, false, vid, a)?; - Ok(a) - } - - (ty::ConstKind::Infer(ty::InferConst::EffectVar(vid)), _) => { - self.instantiate_effect_var_raw(vid, b); - Ok(b) - } - - (_, ty::ConstKind::Infer(ty::InferConst::EffectVar(vid))) => { - self.instantiate_effect_var_raw(vid, a); - Ok(a) - } - - (ty::ConstKind::Unevaluated(..), _) | (_, ty::ConstKind::Unevaluated(..)) - if self.cx().features().generic_const_exprs() || self.next_trait_solver() => - { - match relation.structurally_relate_aliases() { - StructurallyRelateAliases::No => { - relation.register_predicates([if self.next_trait_solver() { - ty::PredicateKind::AliasRelate( - a.into(), - b.into(), - ty::AliasRelationDirection::Equate, - ) - } else { - ty::PredicateKind::ConstEquate(a, b) - }]); - - Ok(b) - } - StructurallyRelateAliases::Yes => structurally_relate_consts(relation, a, b), + (_, ty::Alias(..)) | (ty::Alias(..), _) if infcx.next_trait_solver() => { + match relation.structurally_relate_aliases() { + StructurallyRelateAliases::Yes => structurally_relate_tys(relation, a, b), + StructurallyRelateAliases::No => { + relation.register_alias_relate_predicate(a, b); + Ok(a) } } - _ => structurally_relate_consts(relation, a, b), } + + // All other cases of inference are errors + (ty::Infer(_), _) | (_, ty::Infer(_)) => { + Err(TypeError::Sorts(ExpectedFound::new(true, a, b))) + } + + (ty::Alias(ty::Opaque, _), _) | (_, ty::Alias(ty::Opaque, _)) => { + match infcx.solver_mode() { + SolverMode::Normal => { + assert!(!infcx.next_trait_solver()); + structurally_relate_tys(relation, a, b) + } + // During coherence, opaque types should be treated as *possibly* + // equal to any other type (except for possibly itinfcx). This is an + // extremely heavy hammer, but can be relaxed in a forwards-compatible + // way later. + SolverMode::Coherence => { + relation.register_predicates([ty::Binder::dummy(ty::PredicateKind::Ambiguous)]); + Ok(a) + } + } + } + + _ => structurally_relate_tys(relation, a, b), + } +} + +pub fn super_combine_consts( + infcx: &Infcx, + relation: &mut R, + a: I::Const, + b: I::Const, +) -> RelateResult +where + Infcx: InferCtxtLike, + I: Interner, + R: PredicateEmittingRelation, +{ + debug!("super_combine_consts::<{}>({:?}, {:?})", std::any::type_name::(), a, b); + debug_assert!(!a.has_escaping_bound_vars()); + debug_assert!(!b.has_escaping_bound_vars()); + + if a == b { + return Ok(a); + } + + let a = infcx.shallow_resolve_const(a); + let b = infcx.shallow_resolve_const(b); + + match (a.kind(), b.kind()) { + ( + ty::ConstKind::Infer(ty::InferConst::Var(a_vid)), + ty::ConstKind::Infer(ty::InferConst::Var(b_vid)), + ) => { + infcx.equate_const_vids_raw(a_vid, b_vid); + Ok(a) + } + + ( + ty::ConstKind::Infer(ty::InferConst::EffectVar(a_vid)), + ty::ConstKind::Infer(ty::InferConst::EffectVar(b_vid)), + ) => { + infcx.equate_effect_vids_raw(a_vid, b_vid); + Ok(a) + } + + // All other cases of inference with other variables are errors. + ( + ty::ConstKind::Infer(ty::InferConst::Var(_) | ty::InferConst::EffectVar(_)), + ty::ConstKind::Infer(_), + ) + | ( + ty::ConstKind::Infer(_), + ty::ConstKind::Infer(ty::InferConst::Var(_) | ty::InferConst::EffectVar(_)), + ) => { + panic!( + "tried to combine ConstKind::Infer/ConstKind::Infer(InferConst::Var): {a:?} and {b:?}" + ) + } + + (ty::ConstKind::Infer(ty::InferConst::Var(vid)), _) => { + infcx.instantiate_const_var_raw(relation, true, vid, b)?; + Ok(b) + } + + (_, ty::ConstKind::Infer(ty::InferConst::Var(vid))) => { + infcx.instantiate_const_var_raw(relation, false, vid, a)?; + Ok(a) + } + + (ty::ConstKind::Infer(ty::InferConst::EffectVar(vid)), _) => { + infcx.instantiate_effect_var_raw(vid, b); + Ok(b) + } + + (_, ty::ConstKind::Infer(ty::InferConst::EffectVar(vid))) => { + infcx.instantiate_effect_var_raw(vid, a); + Ok(a) + } + + (ty::ConstKind::Unevaluated(..), _) | (_, ty::ConstKind::Unevaluated(..)) + if infcx.cx().features().generic_const_exprs() || infcx.next_trait_solver() => + { + match relation.structurally_relate_aliases() { + StructurallyRelateAliases::No => { + relation.register_predicates([if infcx.next_trait_solver() { + ty::PredicateKind::AliasRelate( + a.into(), + b.into(), + ty::AliasRelationDirection::Equate, + ) + } else { + ty::PredicateKind::ConstEquate(a, b) + }]); + + Ok(b) + } + StructurallyRelateAliases::Yes => structurally_relate_consts(relation, a, b), + } + } + _ => structurally_relate_consts(relation, a, b), } } diff --git a/compiler/rustc_type_ir/src/relate/solver_relating.rs b/compiler/rustc_type_ir/src/relate/solver_relating.rs index edbfaed9709..ad10ad5af9c 100644 --- a/compiler/rustc_type_ir/src/relate/solver_relating.rs +++ b/compiler/rustc_type_ir/src/relate/solver_relating.rs @@ -3,7 +3,7 @@ use rustc_type_ir::solve::Goal; use rustc_type_ir::{self as ty, InferCtxtLike, Interner}; use tracing::{debug, instrument}; -use self::combine::{InferCtxtCombineExt, PredicateEmittingRelation}; +use self::combine::{PredicateEmittingRelation, super_combine_consts, super_combine_tys}; use crate::data_structures::DelayedSet; pub trait RelateExt: InferCtxtLike { @@ -228,7 +228,7 @@ where } _ => { - self.infcx.super_combine_tys(self, a, b)?; + super_combine_tys(self.infcx, self, a, b)?; } } @@ -255,7 +255,7 @@ where #[instrument(skip(self), level = "trace")] fn consts(&mut self, a: I::Const, b: I::Const) -> RelateResult { - self.infcx.super_combine_consts(self, a, b) + super_combine_consts(self.infcx, self, a, b) } fn binders( From d6fd45c2e3ee24bedbc1b7643b622ab97f29537f Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 10 Oct 2024 09:26:49 +0000 Subject: [PATCH 163/357] impossible obligations check fast path --- .../src/solve/eval_ctxt/mod.rs | 72 ++++++++++++++----- .../rustc_next_trait_solver/src/solve/mod.rs | 8 +++ .../src/solve/search_graph.rs | 3 - compiler/rustc_trait_selection/src/solve.rs | 1 + .../src/solve/fulfill.rs | 15 ++-- .../src/traits/coherence.rs | 13 +++- .../rustc_type_ir/src/search_graph/mod.rs | 12 ++-- tests/crashes/124894.rs | 11 --- 8 files changed, 90 insertions(+), 45 deletions(-) delete mode 100644 tests/crashes/124894.rs diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index ffa800348f2..bc324dcbf51 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -18,8 +18,8 @@ use crate::solve::inspect::{self, ProofTreeBuilder}; use crate::solve::search_graph::SearchGraph; use crate::solve::{ CanonicalInput, CanonicalResponse, Certainty, FIXPOINT_STEP_LIMIT, Goal, GoalEvaluationKind, - GoalSource, NestedNormalizationGoals, NoSolution, PredefinedOpaquesData, QueryResult, - SolverMode, + GoalSource, HasChanged, NestedNormalizationGoals, NoSolution, PredefinedOpaquesData, + QueryResult, SolverMode, }; pub(super) mod canonical; @@ -126,11 +126,31 @@ pub enum GenerateProofTree { } pub trait SolverDelegateEvalExt: SolverDelegate { + /// Evaluates a goal from **outside** of the trait solver. + /// + /// Using this while inside of the solver is wrong as it uses a new + /// search graph which would break cycle detection. fn evaluate_root_goal( &self, goal: Goal::Predicate>, generate_proof_tree: GenerateProofTree, - ) -> (Result<(bool, Certainty), NoSolution>, Option>); + ) -> ( + Result<(HasChanged, Certainty), NoSolution>, + Option>, + ); + + /// Check whether evaluating `goal` with a depth of `root_depth` may + /// succeed. This only returns `false` if the goal is guaranteed to + /// not hold. In case evaluation overflows and fails with ambiguity this + /// returns `true`. + /// + /// This is only intended to be used as a performance optimization + /// in coherence checking. + fn root_goal_may_hold_with_depth( + &self, + root_depth: usize, + goal: Goal::Predicate>, + ) -> bool; // FIXME: This is only exposed because we need to use it in `analyse.rs` // which is not yet uplifted. Once that's done, we should remove this. @@ -139,7 +159,7 @@ pub trait SolverDelegateEvalExt: SolverDelegate { goal: Goal::Predicate>, generate_proof_tree: GenerateProofTree, ) -> ( - Result<(NestedNormalizationGoals, bool, Certainty), NoSolution>, + Result<(NestedNormalizationGoals, HasChanged, Certainty), NoSolution>, Option>, ); } @@ -149,31 +169,41 @@ where D: SolverDelegate, I: Interner, { - /// Evaluates a goal from **outside** of the trait solver. - /// - /// Using this while inside of the solver is wrong as it uses a new - /// search graph which would break cycle detection. #[instrument(level = "debug", skip(self))] fn evaluate_root_goal( &self, goal: Goal, generate_proof_tree: GenerateProofTree, - ) -> (Result<(bool, Certainty), NoSolution>, Option>) { - EvalCtxt::enter_root(self, generate_proof_tree, |ecx| { + ) -> (Result<(HasChanged, Certainty), NoSolution>, Option>) { + EvalCtxt::enter_root(self, self.cx().recursion_limit(), generate_proof_tree, |ecx| { ecx.evaluate_goal(GoalEvaluationKind::Root, GoalSource::Misc, goal) }) } + fn root_goal_may_hold_with_depth( + &self, + root_depth: usize, + goal: Goal::Predicate>, + ) -> bool { + self.probe(|| { + EvalCtxt::enter_root(self, root_depth, GenerateProofTree::No, |ecx| { + ecx.evaluate_goal(GoalEvaluationKind::Root, GoalSource::Misc, goal) + }) + .0 + }) + .is_ok() + } + #[instrument(level = "debug", skip(self))] fn evaluate_root_goal_raw( &self, goal: Goal, generate_proof_tree: GenerateProofTree, ) -> ( - Result<(NestedNormalizationGoals, bool, Certainty), NoSolution>, + Result<(NestedNormalizationGoals, HasChanged, Certainty), NoSolution>, Option>, ) { - EvalCtxt::enter_root(self, generate_proof_tree, |ecx| { + EvalCtxt::enter_root(self, self.cx().recursion_limit(), generate_proof_tree, |ecx| { ecx.evaluate_goal_raw(GoalEvaluationKind::Root, GoalSource::Misc, goal) }) } @@ -197,10 +227,11 @@ where /// over using this manually (such as [`SolverDelegateEvalExt::evaluate_root_goal`]). pub(super) fn enter_root( delegate: &D, + root_depth: usize, generate_proof_tree: GenerateProofTree, f: impl FnOnce(&mut EvalCtxt<'_, D>) -> R, ) -> (R, Option>) { - let mut search_graph = SearchGraph::new(delegate.solver_mode()); + let mut search_graph = SearchGraph::new(delegate.solver_mode(), root_depth); let mut ecx = EvalCtxt { delegate, @@ -339,7 +370,7 @@ where goal_evaluation_kind: GoalEvaluationKind, source: GoalSource, goal: Goal, - ) -> Result<(bool, Certainty), NoSolution> { + ) -> Result<(HasChanged, Certainty), NoSolution> { let (normalization_nested_goals, has_changed, certainty) = self.evaluate_goal_raw(goal_evaluation_kind, source, goal)?; assert!(normalization_nested_goals.is_empty()); @@ -360,7 +391,7 @@ where goal_evaluation_kind: GoalEvaluationKind, _source: GoalSource, goal: Goal, - ) -> Result<(NestedNormalizationGoals, bool, Certainty), NoSolution> { + ) -> Result<(NestedNormalizationGoals, HasChanged, Certainty), NoSolution> { let (orig_values, canonical_goal) = self.canonicalize_goal(goal); let mut goal_evaluation = self.inspect.new_goal_evaluation(goal, &orig_values, goal_evaluation_kind); @@ -378,8 +409,13 @@ where Ok(response) => response, }; - let has_changed = !response.value.var_values.is_identity_modulo_regions() - || !response.value.external_constraints.opaque_types.is_empty(); + let has_changed = if !response.value.var_values.is_identity_modulo_regions() + || !response.value.external_constraints.opaque_types.is_empty() + { + HasChanged::Yes + } else { + HasChanged::No + }; let (normalization_nested_goals, certainty) = self.instantiate_and_apply_query_response(goal.param_env, orig_values, response); @@ -552,7 +588,7 @@ where for (source, goal) in goals.goals { let (has_changed, certainty) = self.evaluate_goal(GoalEvaluationKind::Nested, source, goal)?; - if has_changed { + if has_changed == HasChanged::Yes { unchanged_certainty = None; } diff --git a/compiler/rustc_next_trait_solver/src/solve/mod.rs b/compiler/rustc_next_trait_solver/src/solve/mod.rs index 309ab7f28d1..97f7c71f3fc 100644 --- a/compiler/rustc_next_trait_solver/src/solve/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/mod.rs @@ -48,6 +48,14 @@ enum GoalEvaluationKind { Nested, } +/// Whether evaluating this goal ended up changing the +/// inference state. +#[derive(PartialEq, Eq, Debug, Hash, Clone, Copy)] +pub enum HasChanged { + Yes, + No, +} + // FIXME(trait-system-refactor-initiative#117): we don't detect whether a response // ended up pulling down any universes. fn has_no_inference_or_external_constraints( diff --git a/compiler/rustc_next_trait_solver/src/solve/search_graph.rs b/compiler/rustc_next_trait_solver/src/solve/search_graph.rs index e47cc03f5ad..0e3f179b0c8 100644 --- a/compiler/rustc_next_trait_solver/src/solve/search_graph.rs +++ b/compiler/rustc_next_trait_solver/src/solve/search_graph.rs @@ -40,9 +40,6 @@ where } const DIVIDE_AVAILABLE_DEPTH_ON_OVERFLOW: usize = 4; - fn recursion_limit(cx: I) -> usize { - cx.recursion_limit() - } fn initial_provisional_result( cx: I, diff --git a/compiler/rustc_trait_selection/src/solve.rs b/compiler/rustc_trait_selection/src/solve.rs index e47f5389cd1..d425ab50ae0 100644 --- a/compiler/rustc_trait_selection/src/solve.rs +++ b/compiler/rustc_trait_selection/src/solve.rs @@ -6,6 +6,7 @@ pub mod inspect; mod normalize; mod select; +pub(crate) use delegate::SolverDelegate; pub use fulfill::{FulfillmentCtxt, NextSolverError}; pub(crate) use normalize::deeply_normalize_for_diagnostics; pub use normalize::{deeply_normalize, deeply_normalize_with_skipped_universes}; diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index c6e3ba3c957..081d7a6a769 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -12,7 +12,7 @@ use rustc_infer::traits::{ use rustc_middle::bug; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::{self, TyCtxt}; -use rustc_next_trait_solver::solve::{GenerateProofTree, SolverDelegateEvalExt as _}; +use rustc_next_trait_solver::solve::{GenerateProofTree, HasChanged, SolverDelegateEvalExt as _}; use tracing::instrument; use super::Certainty; @@ -86,10 +86,7 @@ impl<'tcx> ObligationStorage<'tcx> { let result = <&SolverDelegate<'tcx>>::from(infcx) .evaluate_root_goal(goal, GenerateProofTree::No) .0; - match result { - Ok((has_changed, _)) => has_changed, - _ => false, - } + matches!(result, Ok((HasChanged::Yes, _))) })); }) } @@ -113,7 +110,7 @@ impl<'tcx, E: 'tcx> FulfillmentCtxt<'tcx, E> { &self, infcx: &InferCtxt<'tcx>, obligation: &PredicateObligation<'tcx>, - result: &Result<(bool, Certainty), NoSolution>, + result: &Result<(HasChanged, Certainty), NoSolution>, ) { if let Some(inspector) = infcx.obligation_inspector.get() { let result = match result { @@ -181,7 +178,11 @@ where continue; } }; - has_changed |= changed; + + if changed == HasChanged::Yes { + has_changed = true; + } + match certainty { Certainty::Yes => {} Certainty::Maybe(_) => self.obligations.register(obligation), diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 27d2a3c15b9..b29e41beab5 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -19,6 +19,7 @@ use rustc_middle::ty::fast_reject::DeepRejectCtxt; use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor}; use rustc_middle::ty::{self, Ty, TyCtxt}; pub use rustc_next_trait_solver::coherence::*; +use rustc_next_trait_solver::solve::SolverDelegateEvalExt; use rustc_span::symbol::sym; use rustc_span::{DUMMY_SP, Span}; use tracing::{debug, instrument, warn}; @@ -28,7 +29,7 @@ use crate::error_reporting::traits::suggest_new_overflow_limit; use crate::infer::InferOk; use crate::infer::outlives::env::OutlivesEnvironment; use crate::solve::inspect::{InspectGoal, ProofTreeInferCtxtExt, ProofTreeVisitor}; -use crate::solve::{deeply_normalize_for_diagnostics, inspect}; +use crate::solve::{SolverDelegate, deeply_normalize_for_diagnostics, inspect}; use crate::traits::query::evaluate_obligation::InferCtxtExt; use crate::traits::select::IntercrateAmbiguityCause; use crate::traits::{ @@ -333,6 +334,16 @@ fn impl_intersection_has_impossible_obligation<'a, 'cx, 'tcx>( let infcx = selcx.infcx; if infcx.next_trait_solver() { + // A fast path optimization, try evaluating all goals with + // a very low recursion depth and bail if any of them don't + // hold. + if !obligations.iter().all(|o| { + <&SolverDelegate<'tcx>>::from(infcx) + .root_goal_may_hold_with_depth(8, Goal::new(infcx.tcx, o.param_env, o.predicate)) + }) { + return IntersectionHasImpossibleObligations::Yes; + } + let ocx = ObligationCtxt::new_with_diagnostics(infcx); ocx.register_obligations(obligations.iter().cloned()); let errors_and_ambiguities = ocx.select_all_or_error(); diff --git a/compiler/rustc_type_ir/src/search_graph/mod.rs b/compiler/rustc_type_ir/src/search_graph/mod.rs index ac4d0795a92..f4fb03562de 100644 --- a/compiler/rustc_type_ir/src/search_graph/mod.rs +++ b/compiler/rustc_type_ir/src/search_graph/mod.rs @@ -81,7 +81,6 @@ pub trait Delegate { fn inspect_is_noop(inspect: &mut Self::ProofTreeBuilder) -> bool; const DIVIDE_AVAILABLE_DEPTH_ON_OVERFLOW: usize; - fn recursion_limit(cx: Self::Cx) -> usize; fn initial_provisional_result( cx: Self::Cx, @@ -156,7 +155,7 @@ impl AvailableDepth { /// the remaining depth of all nested goals to prevent hangs /// in case there is exponential blowup. fn allowed_depth_for_nested( - cx: D::Cx, + root_depth: AvailableDepth, stack: &IndexVec>, ) -> Option { if let Some(last) = stack.raw.last() { @@ -170,7 +169,7 @@ impl AvailableDepth { AvailableDepth(last.available_depth.0 - 1) }) } else { - Some(AvailableDepth(D::recursion_limit(cx))) + Some(root_depth) } } @@ -360,6 +359,7 @@ struct ProvisionalCacheEntry { pub struct SearchGraph, X: Cx = ::Cx> { mode: SolverMode, + root_depth: AvailableDepth, /// The stack of goals currently being computed. /// /// An element is *deeper* in the stack if its index is *lower*. @@ -374,9 +374,10 @@ pub struct SearchGraph, X: Cx = ::Cx> { } impl, X: Cx> SearchGraph { - pub fn new(mode: SolverMode) -> SearchGraph { + pub fn new(mode: SolverMode, root_depth: usize) -> SearchGraph { Self { mode, + root_depth: AvailableDepth(root_depth), stack: Default::default(), provisional_cache: Default::default(), _marker: PhantomData, @@ -460,7 +461,8 @@ impl, X: Cx> SearchGraph { inspect: &mut D::ProofTreeBuilder, mut evaluate_goal: impl FnMut(&mut Self, &mut D::ProofTreeBuilder) -> X::Result, ) -> X::Result { - let Some(available_depth) = AvailableDepth::allowed_depth_for_nested::(cx, &self.stack) + let Some(available_depth) = + AvailableDepth::allowed_depth_for_nested::(self.root_depth, &self.stack) else { return self.handle_overflow(cx, input, inspect); }; diff --git a/tests/crashes/124894.rs b/tests/crashes/124894.rs deleted file mode 100644 index 230cf4a89c1..00000000000 --- a/tests/crashes/124894.rs +++ /dev/null @@ -1,11 +0,0 @@ -//@ known-bug: rust-lang/rust#124894 -//@ compile-flags: -Znext-solver=coherence - -#![feature(generic_const_exprs)] - -pub trait IsTrue {} -impl IsZST for T where (): IsTrue<{ std::mem::size_of::() == 0 }> {} - -pub trait IsZST {} - -impl IsZST for IsZST {} From 2900c58a02c48da60a2d2d45613acf25164efa2b Mon Sep 17 00:00:00 2001 From: Kajetan Puchalski Date: Thu, 19 Sep 2024 08:28:09 +0000 Subject: [PATCH 164/357] stdarch: Bump stdarch submodule --- library/stdarch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/stdarch b/library/stdarch index ace72223a0e..c881fe3231b 160000 --- a/library/stdarch +++ b/library/stdarch @@ -1 +1 @@ -Subproject commit ace72223a0e321c1b0a37b5862aa756fe8ab5111 +Subproject commit c881fe3231b3947a4766aa15a26a93022fbb8723 From 335f67b6527cbeb576151dab1dadec161eaede45 Mon Sep 17 00:00:00 2001 From: Kajetan Puchalski Date: Tue, 3 Sep 2024 13:51:54 +0100 Subject: [PATCH 165/357] rustc_target: Add sme-b16b16 as an explicit aarch64 target feature LLVM 20 split out what used to be called b16b16 and correspond to aarch64 FEAT_SVE_B16B16 into sve-b16b16 and sme-b16b16. Add sme-b16b16 as an explicit feature and update the codegen accordingly. --- compiler/rustc_codegen_llvm/src/llvm_util.rs | 4 +++- compiler/rustc_target/src/target_features.rs | 4 +++- library/std/tests/run-time-detect.rs | 1 + tests/ui/check-cfg/mix.stderr | 2 +- tests/ui/check-cfg/well-known-values.stderr | 2 +- 5 files changed, 9 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index bd847cd0068..8290e1a9544 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -247,7 +247,9 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option Some(LLVMFeature::new("perfmon")), ("aarch64", "paca") => Some(LLVMFeature::new("pauth")), ("aarch64", "pacg") => Some(LLVMFeature::new("pauth")), - ("aarch64", "sve-b16b16") => Some(LLVMFeature::new("b16b16")), + // Before LLVM 20 those two features were packaged together as b16b16 + ("aarch64", "sve-b16b16") if get_version().0 < 20 => Some(LLVMFeature::new("b16b16")), + ("aarch64", "sme-b16b16") if get_version().0 < 20 => Some(LLVMFeature::new("b16b16")), ("aarch64", "flagm2") => Some(LLVMFeature::new("altnzcv")), // Rust ties fp and neon together. ("aarch64", "neon") => { diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index 0a98b363b1a..e92366d5c5c 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -191,6 +191,8 @@ const AARCH64_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("sm4", Stable, &["neon"]), // FEAT_SME ("sme", Unstable(sym::aarch64_unstable_target_feature), &["bf16"]), + // FEAT_SME_B16B16 + ("sme-b16b16", Unstable(sym::aarch64_unstable_target_feature), &["bf16", "sme2", "sve-b16b16"]), // FEAT_SME_F16F16 ("sme-f16f16", Unstable(sym::aarch64_unstable_target_feature), &["sme2"]), // FEAT_SME_F64F64 @@ -227,7 +229,7 @@ const AARCH64_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ // // "For backwards compatibility, Neon and VFP are required in the latest architectures." ("sve", Stable, &["neon"]), - // FEAT_SVE_B16B16 (SVE or SME Instructions) + // FEAT_SVE_B16B16 (SVE or SME Z-targeting instructions) ("sve-b16b16", Unstable(sym::aarch64_unstable_target_feature), &["bf16"]), // FEAT_SVE2 ("sve2", Stable, &["sve"]), diff --git a/library/std/tests/run-time-detect.rs b/library/std/tests/run-time-detect.rs index dcd5cd7f6b9..dd14c0266aa 100644 --- a/library/std/tests/run-time-detect.rs +++ b/library/std/tests/run-time-detect.rs @@ -82,6 +82,7 @@ fn aarch64_linux() { println!("sha2: {}", is_aarch64_feature_detected!("sha2")); println!("sha3: {}", is_aarch64_feature_detected!("sha3")); println!("sm4: {}", is_aarch64_feature_detected!("sm4")); + println!("sme-b16b16: {}", is_aarch64_feature_detected!("sme-b16b16")); println!("sme-f16f16: {}", is_aarch64_feature_detected!("sme-f16f16")); println!("sme-f64f64: {}", is_aarch64_feature_detected!("sme-f64f64")); println!("sme-f8f16: {}", is_aarch64_feature_detected!("sme-f8f16")); diff --git a/tests/ui/check-cfg/mix.stderr b/tests/ui/check-cfg/mix.stderr index 7726c2d52f5..c21016e9290 100644 --- a/tests/ui/check-cfg/mix.stderr +++ b/tests/ui/check-cfg/mix.stderr @@ -251,7 +251,7 @@ warning: unexpected `cfg` condition value: `zebra` LL | cfg!(target_feature = "zebra"); | ^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, and `avx512vpopcntdq` and 244 more + = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, and `avx512vpopcntdq` and 245 more = note: see for more information about checking conditional configuration warning: 27 warnings emitted diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr index c6d403104ea..da790bbd528 100644 --- a/tests/ui/check-cfg/well-known-values.stderr +++ b/tests/ui/check-cfg/well-known-values.stderr @@ -174,7 +174,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` LL | target_feature = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `avxifma`, `avxneconvert`, `avxvnni`, `avxvnniint16`, `avxvnniint8`, `backchain`, `bf16`, `bmi1`, `bmi2`, `bti`, `bulk-memory`, `c`, `cache`, `cmpxchg16b`, `crc`, `crt-static`, `cssc`, `d`, `d32`, `dit`, `doloop`, `dotprod`, `dpb`, `dpb2`, `dsp`, `dsp1e2`, `dspe60`, `e`, `e1`, `e2`, `ecv`, `edsp`, `elrw`, `ermsb`, `exception-handling`, `extended-const`, `f`, `f16c`, `f32mm`, `f64mm`, `faminmax`, `fcma`, `fdivdu`, `fhm`, `flagm`, `flagm2`, `float1e2`, `float1e3`, `float3e4`, `float7e60`, `floate1`, `fma`, `fp-armv8`, `fp16`, `fp64`, `fp8`, `fp8dot2`, `fp8dot4`, `fp8fma`, `fpuv2_df`, `fpuv2_sf`, `fpuv3_df`, `fpuv3_hf`, `fpuv3_hi`, `fpuv3_sf`, `frecipe`, `frintts`, `fxsr`, `gfni`, `hard-float`, `hard-float-abi`, `hard-tp`, `hbc`, `high-registers`, `hvx`, `hvx-length128b`, `hwdiv`, `i8mm`, `jsconv`, `lahfsahf`, `lasx`, `lbt`, `lor`, `lse`, `lse128`, `lse2`, `lsx`, `lut`, `lvz`, `lzcnt`, `m`, `mclass`, `mops`, `movbe`, `mp`, `mp1e2`, `msa`, `mte`, `multivalue`, `mutable-globals`, `neon`, `nontrapping-fptoint`, `nvic`, `paca`, `pacg`, `pan`, `partword-atomics`, `pclmulqdq`, `pmuv3`, `popcnt`, `power10-vector`, `power8-altivec`, `power8-vector`, `power9-altivec`, `power9-vector`, `prfchw`, `quadword-atomics`, `rand`, `ras`, `rclass`, `rcpc`, `rcpc2`, `rcpc3`, `rdm`, `rdrand`, `rdseed`, `reference-types`, `relax`, `relaxed-simd`, `rtm`, `sb`, `sha`, `sha2`, `sha3`, `sha512`, `sign-ext`, `simd128`, `sm3`, `sm4`, `sme`, `sme-f16f16`, `sme-f64f64`, `sme-f8f16`, `sme-f8f32`, `sme-fa64`, `sme-i16i64`, `sme-lutv2`, `sme2`, `sme2p1`, `spe`, `ssbs`, `sse`, `sse2`, `sse3`, `sse4.1`, `sse4.2`, `sse4a`, `ssse3`, `ssve-fp8dot2`, `ssve-fp8dot4`, `ssve-fp8fma`, `sve`, `sve-b16b16`, `sve2`, `sve2-aes`, `sve2-bitperm`, `sve2-sha3`, `sve2-sm4`, `sve2p1`, `tbm`, `thumb-mode`, `thumb2`, `tme`, `trust`, `trustzone`, `ual`, `unaligned-scalar-mem`, `v`, `v5te`, `v6`, `v6k`, `v6t2`, `v7`, `v8`, `v8.1a`, `v8.2a`, `v8.3a`, `v8.4a`, `v8.5a`, `v8.6a`, `v8.7a`, `v8.8a`, `v8.9a`, `v9.1a`, `v9.2a`, `v9.3a`, `v9.4a`, `v9.5a`, `v9a`, `vaes`, `vdsp2e60f`, `vdspv1`, `vdspv2`, `vector`, `vfp2`, `vfp3`, `vfp4`, `vh`, `virt`, `virtualization`, `vpclmulqdq`, `vsx`, `wfxt`, `xop`, `xsave`, `xsavec`, `xsaveopt`, `xsaves`, `zaamo`, `zabha`, `zalrsc`, `zba`, `zbb`, `zbc`, `zbkb`, `zbkc`, `zbkx`, `zbs`, `zdinx`, `zfh`, `zfhmin`, `zfinx`, `zhinx`, `zhinxmin`, `zk`, `zkn`, `zknd`, `zkne`, `zknh`, `zkr`, `zks`, `zksed`, `zksh`, and `zkt` + = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `avxifma`, `avxneconvert`, `avxvnni`, `avxvnniint16`, `avxvnniint8`, `backchain`, `bf16`, `bmi1`, `bmi2`, `bti`, `bulk-memory`, `c`, `cache`, `cmpxchg16b`, `crc`, `crt-static`, `cssc`, `d`, `d32`, `dit`, `doloop`, `dotprod`, `dpb`, `dpb2`, `dsp`, `dsp1e2`, `dspe60`, `e`, `e1`, `e2`, `ecv`, `edsp`, `elrw`, `ermsb`, `exception-handling`, `extended-const`, `f`, `f16c`, `f32mm`, `f64mm`, `faminmax`, `fcma`, `fdivdu`, `fhm`, `flagm`, `flagm2`, `float1e2`, `float1e3`, `float3e4`, `float7e60`, `floate1`, `fma`, `fp-armv8`, `fp16`, `fp64`, `fp8`, `fp8dot2`, `fp8dot4`, `fp8fma`, `fpuv2_df`, `fpuv2_sf`, `fpuv3_df`, `fpuv3_hf`, `fpuv3_hi`, `fpuv3_sf`, `frecipe`, `frintts`, `fxsr`, `gfni`, `hard-float`, `hard-float-abi`, `hard-tp`, `hbc`, `high-registers`, `hvx`, `hvx-length128b`, `hwdiv`, `i8mm`, `jsconv`, `lahfsahf`, `lasx`, `lbt`, `lor`, `lse`, `lse128`, `lse2`, `lsx`, `lut`, `lvz`, `lzcnt`, `m`, `mclass`, `mops`, `movbe`, `mp`, `mp1e2`, `msa`, `mte`, `multivalue`, `mutable-globals`, `neon`, `nontrapping-fptoint`, `nvic`, `paca`, `pacg`, `pan`, `partword-atomics`, `pclmulqdq`, `pmuv3`, `popcnt`, `power10-vector`, `power8-altivec`, `power8-vector`, `power9-altivec`, `power9-vector`, `prfchw`, `quadword-atomics`, `rand`, `ras`, `rclass`, `rcpc`, `rcpc2`, `rcpc3`, `rdm`, `rdrand`, `rdseed`, `reference-types`, `relax`, `relaxed-simd`, `rtm`, `sb`, `sha`, `sha2`, `sha3`, `sha512`, `sign-ext`, `simd128`, `sm3`, `sm4`, `sme`, `sme-b16b16`, `sme-f16f16`, `sme-f64f64`, `sme-f8f16`, `sme-f8f32`, `sme-fa64`, `sme-i16i64`, `sme-lutv2`, `sme2`, `sme2p1`, `spe`, `ssbs`, `sse`, `sse2`, `sse3`, `sse4.1`, `sse4.2`, `sse4a`, `ssse3`, `ssve-fp8dot2`, `ssve-fp8dot4`, `ssve-fp8fma`, `sve`, `sve-b16b16`, `sve2`, `sve2-aes`, `sve2-bitperm`, `sve2-sha3`, `sve2-sm4`, `sve2p1`, `tbm`, `thumb-mode`, `thumb2`, `tme`, `trust`, `trustzone`, `ual`, `unaligned-scalar-mem`, `v`, `v5te`, `v6`, `v6k`, `v6t2`, `v7`, `v8`, `v8.1a`, `v8.2a`, `v8.3a`, `v8.4a`, `v8.5a`, `v8.6a`, `v8.7a`, `v8.8a`, `v8.9a`, `v9.1a`, `v9.2a`, `v9.3a`, `v9.4a`, `v9.5a`, `v9a`, `vaes`, `vdsp2e60f`, `vdspv1`, `vdspv2`, `vector`, `vfp2`, `vfp3`, `vfp4`, `vh`, `virt`, `virtualization`, `vpclmulqdq`, `vsx`, `wfxt`, `xop`, `xsave`, `xsavec`, `xsaveopt`, `xsaves`, `zaamo`, `zabha`, `zalrsc`, `zba`, `zbb`, `zbc`, `zbkb`, `zbkc`, `zbkx`, `zbs`, `zdinx`, `zfh`, `zfhmin`, `zfinx`, `zhinx`, `zhinxmin`, `zk`, `zkn`, `zknd`, `zkne`, `zknh`, `zkr`, `zks`, `zksed`, `zksh`, and `zkt` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` From 57ae34ad3c2d733c8b272ed2c46f8d10a01d9ed7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= <39484203+jieyouxu@users.noreply.github.com> Date: Thu, 10 Oct 2024 19:02:58 +0800 Subject: [PATCH 166/357] Add myself to bootstrap review rotation --- triagebot.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/triagebot.toml b/triagebot.toml index d3e4af9b718..6c9cdc3223b 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -971,6 +971,7 @@ bootstrap = [ "@albertlarsan68", "@onur-ozkan", "@kobzol", + "@jieyouxu", ] infra-ci = [ "@Mark-Simulacrum", From 8a1462265f839607f96acea4bed183736598422d Mon Sep 17 00:00:00 2001 From: Joshua Wong Date: Wed, 9 Oct 2024 14:24:05 -0400 Subject: [PATCH 167/357] add initial tests for placement new changes --- tests/codegen/placement-new.rs | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 tests/codegen/placement-new.rs diff --git a/tests/codegen/placement-new.rs b/tests/codegen/placement-new.rs new file mode 100644 index 00000000000..68260a65a3f --- /dev/null +++ b/tests/codegen/placement-new.rs @@ -0,0 +1,27 @@ +//@ compile-flags: -O +#![crate_type = "lib"] + +// Test to check that types with "complex" destructors, but trivial `Default` impls +// are constructed directly into the allocation in `Box::default` and `Arc::default`. + +use std::sync::Arc; + +// CHECK-LABEL: @box_default_inplace +#[no_mangle] +pub fn box_default_inplace() -> Box<(String, String)> { + // CHECK: [[ALLOCA:%.*]] = alloca + // CHECK: [[BOX:%.*]] = {{.*}}call {{.*}}__rust_alloc( + // CHECK: call void @llvm.memcpy{{.*}}(ptr {{.*}}[[BOX]], ptr {{.*}}[[ALLOCA]] + // CHECK: ret ptr [[BOX]] + Box::default() +} + +// CHECK-LABEL: @arc_default_inplace +#[no_mangle] +pub fn arc_default_inplace() -> Arc<(String, String)> { + // CHECK: [[ALLOCA:%.*]] = alloca + // CHECK: [[ARC:%.*]] = {{.*}}call {{.*}}__rust_alloc( + // CHECK: call void @llvm.memcpy + // CHECK: ret ptr [[ARC]] + Arc::default() +} From dd0620b86721ae8cae86736443acd3f72ba6fc32 Mon Sep 17 00:00:00 2001 From: Joshua Wong Date: Wed, 9 Oct 2024 14:24:05 -0400 Subject: [PATCH 168/357] allocate before calling T::default in >::default() The `Box` impl currently calls `T::default()` before allocating the `Box`. Most `Default` impls are trivial, which should in theory allow LLVM to construct `T: Default` directly in the `Box` allocation when calling `>::default()`. However, the allocation may fail, which necessitates calling `T's` destructor if it has one. If the destructor is non-trivial, then LLVM has a hard time proving that it's sound to elide, which makes it construct `T` on the stack first, and then copy it into the allocation. Create an uninit `Box` first, and then write `T::default` into it, so that LLVM now only needs to prove that the `T::default` can't panic, which should be trivial for most `Default` impls. --- library/alloc/src/boxed.rs | 2 +- tests/codegen/placement-new.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 5f207295683..3e791416820 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -1688,7 +1688,7 @@ impl Default for Box { /// Creates a `Box`, with the `Default` value for T. #[inline] fn default() -> Self { - Box::new(T::default()) + Box::write(Box::new_uninit(), T::default()) } } diff --git a/tests/codegen/placement-new.rs b/tests/codegen/placement-new.rs index 68260a65a3f..d5c7969dd19 100644 --- a/tests/codegen/placement-new.rs +++ b/tests/codegen/placement-new.rs @@ -9,9 +9,9 @@ use std::sync::Arc; // CHECK-LABEL: @box_default_inplace #[no_mangle] pub fn box_default_inplace() -> Box<(String, String)> { - // CHECK: [[ALLOCA:%.*]] = alloca + // CHECK-NOT: alloca // CHECK: [[BOX:%.*]] = {{.*}}call {{.*}}__rust_alloc( - // CHECK: call void @llvm.memcpy{{.*}}(ptr {{.*}}[[BOX]], ptr {{.*}}[[ALLOCA]] + // CHECK-NOT: call void @llvm.memcpy // CHECK: ret ptr [[BOX]] Box::default() } From 5e474f7d83fc931f355cfdadf394313e57290050 Mon Sep 17 00:00:00 2001 From: Joshua Wong Date: Wed, 9 Oct 2024 14:24:05 -0400 Subject: [PATCH 169/357] allocate before calling T::default in >::default() Same rationale as in the previous commit. --- library/alloc/src/lib.rs | 1 + library/alloc/src/sync.rs | 8 +++++++- tests/codegen/placement-new.rs | 4 ++-- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index c60c0743c7e..dcfe96be755 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -104,6 +104,7 @@ #![feature(async_closure)] #![feature(async_fn_traits)] #![feature(async_iterator)] +#![feature(box_uninit_write)] #![feature(clone_to_uninit)] #![feature(coerce_unsized)] #![feature(const_align_of_val)] diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 5d099a49854..0038750d25d 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -3447,7 +3447,13 @@ impl Default for Arc { /// assert_eq!(*x, 0); /// ``` fn default() -> Arc { - Arc::new(Default::default()) + let x = Box::into_raw(Box::write(Box::new_uninit(), ArcInner { + strong: atomic::AtomicUsize::new(1), + weak: atomic::AtomicUsize::new(1), + data: T::default(), + })); + // SAFETY: `Box::into_raw` consumes the `Box` and never returns null + unsafe { Self::from_inner(NonNull::new_unchecked(x)) } } } diff --git a/tests/codegen/placement-new.rs b/tests/codegen/placement-new.rs index d5c7969dd19..edb25df5eb4 100644 --- a/tests/codegen/placement-new.rs +++ b/tests/codegen/placement-new.rs @@ -19,9 +19,9 @@ pub fn box_default_inplace() -> Box<(String, String)> { // CHECK-LABEL: @arc_default_inplace #[no_mangle] pub fn arc_default_inplace() -> Arc<(String, String)> { - // CHECK: [[ALLOCA:%.*]] = alloca + // CHECK-NOT: alloca // CHECK: [[ARC:%.*]] = {{.*}}call {{.*}}__rust_alloc( - // CHECK: call void @llvm.memcpy + // CHECK-NOT: call void @llvm.memcpy // CHECK: ret ptr [[ARC]] Arc::default() } From 00f98275990f4673641d5ae787bb4c1d2d4d3f78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20Bj=C3=B8rnager=20Jensen?= Date: Wed, 9 Oct 2024 22:15:38 +0200 Subject: [PATCH 170/357] Stabilise 'const_char_encode_utf8'; --- library/core/src/char/methods.rs | 7 +++++-- library/core/src/lib.rs | 1 - 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index 7f3c998aaa5..6bedb0d0dc4 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs @@ -674,8 +674,9 @@ impl char { /// 'ß'.encode_utf8(&mut b); /// ``` #[stable(feature = "unicode_encode_char", since = "1.15.0")] - #[rustc_const_unstable(feature = "const_char_encode_utf8", issue = "130512")] + #[rustc_const_stable(feature = "const_char_encode_utf8", since = "CURRENT_RUSTC_VERSION")] #[inline] + #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn encode_utf8(self, dst: &mut [u8]) -> &mut str { // SAFETY: `char` is not a surrogate, so this is valid UTF-8. unsafe { from_utf8_unchecked_mut(encode_utf8_raw(self as u32, dst)) } @@ -1770,9 +1771,11 @@ const fn len_utf16(code: u32) -> usize { /// Panics if the buffer is not large enough. /// A buffer of length four is large enough to encode any `char`. #[unstable(feature = "char_internals", reason = "exposed only for libstd", issue = "none")] -#[rustc_const_unstable(feature = "const_char_encode_utf8", issue = "130512")] +#[rustc_const_stable(feature = "const_char_encode_utf8", since = "CURRENT_RUSTC_VERSION")] #[doc(hidden)] #[inline] +#[rustc_allow_const_fn_unstable(const_eval_select)] +#[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn encode_utf8_raw(code: u32, dst: &mut [u8]) -> &mut [u8] { const fn panic_at_const(_code: u32, _len: usize, _dst_len: usize) { // Note that we cannot format in constant expressions. diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 817d9e3b962..ce5a1791f5e 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -119,7 +119,6 @@ #![feature(const_bigint_helper_methods)] #![feature(const_black_box)] #![feature(const_char_encode_utf16)] -#![feature(const_char_encode_utf8)] #![feature(const_eval_select)] #![feature(const_exact_div)] #![feature(const_float_classify)] From 203573701a186490db661f52bbf852906d45a2fb Mon Sep 17 00:00:00 2001 From: "Tim (Theemathas) Chirananthavat" Date: Thu, 10 Oct 2024 23:12:03 +0700 Subject: [PATCH 171/357] More clearly document Stdin::read_line These are common pitfalls for beginners, so I think it's worth making the subtleties more visible. --- library/std/src/io/stdio.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs index bf242e715bd..35b38ed783f 100644 --- a/library/std/src/io/stdio.rs +++ b/library/std/src/io/stdio.rs @@ -370,7 +370,12 @@ impl Stdin { /// Locks this handle and reads a line of input, appending it to the specified buffer. /// /// For detailed semantics of this method, see the documentation on - /// [`BufRead::read_line`]. + /// [`BufRead::read_line`]. In particular: + /// * Previous content of the buffer will be preserved. To avoid appending + /// to the buffer, you need to [`clear`] it first. + /// * The trailing newline character, if any, is included in the buffer. + /// + /// [`clear`]: String::clear /// /// # Examples /// From b7297ac4407e25f7872cd061246196cd4c8b485b Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 29 Sep 2024 13:08:48 -0400 Subject: [PATCH 172/357] Add gate for precise capturing in traits --- compiler/rustc_ast_lowering/src/lib.rs | 19 ++++++++++++++----- compiler/rustc_feature/src/unstable.rs | 2 ++ compiler/rustc_span/src/symbol.rs | 1 + ...eature-gate-precise_capturing_in_traits.rs | 6 ++++++ ...re-gate-precise_capturing_in_traits.stderr | 13 +++++++++++++ .../forgot-to-capture-type.stderr | 3 +++ .../precise-capturing/redundant.rpitit.stderr | 6 ++++++ ...itit-captures-more-method-lifetimes.stderr | 3 +++ .../precise-capturing/rpitit.stderr | 3 +++ .../precise-capturing/self-capture.stderr | 3 +++ 10 files changed, 54 insertions(+), 5 deletions(-) create mode 100644 tests/ui/feature-gates/feature-gate-precise_capturing_in_traits.rs create mode 100644 tests/ui/feature-gates/feature-gate-precise_capturing_in_traits.stderr diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index b26797f4203..35af4d63cc7 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1573,11 +1573,20 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Feature gate for RPITIT + use<..> match origin { rustc_hir::OpaqueTyOrigin::FnReturn { in_trait_or_impl: Some(_), .. } => { - if let Some(span) = bounds.iter().find_map(|bound| match *bound { - ast::GenericBound::Use(_, span) => Some(span), - _ => None, - }) { - self.tcx.dcx().emit_err(errors::NoPreciseCapturesOnRpitit { span }); + if !self.tcx.features().precise_capturing_in_traits + && let Some(span) = bounds.iter().find_map(|bound| match *bound { + ast::GenericBound::Use(_, span) => Some(span), + _ => None, + }) + { + let mut diag = + self.tcx.dcx().create_err(errors::NoPreciseCapturesOnRpitit { span }); + add_feature_diagnostics( + &mut diag, + self.tcx.sess, + sym::precise_capturing_in_traits, + ); + diag.emit(); } } _ => {} diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 380e36fe405..19a6960cf4d 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -565,6 +565,8 @@ declare_features! ( (incomplete, pin_ergonomics, "CURRENT_RUSTC_VERSION", Some(130494)), /// Allows postfix match `expr.match { ... }` (unstable, postfix_match, "1.79.0", Some(121618)), + /// Allows `use<..>` precise capturign on impl Trait in traits. + (unstable, precise_capturing_in_traits, "CURRENT_RUSTC_VERSION", Some(130044)), /// Allows macro attributes on expressions, statements and non-inline modules. (unstable, proc_macro_hygiene, "1.30.0", Some(54727)), /// Makes `&` and `&mut` patterns eat only one layer of references in Rust 2024. diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 1527600e764..683f59a8999 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1479,6 +1479,7 @@ symbols! { powif64, pre_dash_lto: "pre-lto", precise_capturing, + precise_capturing_in_traits, precise_pointer_size_matching, pref_align_of, prefetch_read_data, diff --git a/tests/ui/feature-gates/feature-gate-precise_capturing_in_traits.rs b/tests/ui/feature-gates/feature-gate-precise_capturing_in_traits.rs new file mode 100644 index 00000000000..308b41dfc68 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-precise_capturing_in_traits.rs @@ -0,0 +1,6 @@ +trait Foo { + fn test() -> impl Sized + use; + //~^ ERROR `use<...>` precise capturing syntax is currently not allowed in return-position +} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-precise_capturing_in_traits.stderr b/tests/ui/feature-gates/feature-gate-precise_capturing_in_traits.stderr new file mode 100644 index 00000000000..b2c6bf61124 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-precise_capturing_in_traits.stderr @@ -0,0 +1,13 @@ +error: `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits + --> $DIR/feature-gate-precise_capturing_in_traits.rs:2:31 + | +LL | fn test() -> impl Sized + use; + | ^^^^^^^^^ + | + = note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope + = note: see issue #130044 for more information + = help: add `#![feature(precise_capturing_in_traits)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 1 previous error + diff --git a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr index d9be9d543e4..23d6a3bd11e 100644 --- a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr +++ b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr @@ -5,6 +5,9 @@ LL | fn bar() -> impl Sized + use<>; | ^^^^^ | = note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope + = note: see issue #130044 for more information + = help: add `#![feature(precise_capturing_in_traits)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: `impl Trait` must mention all type parameters in scope in `use<...>` --> $DIR/forgot-to-capture-type.rs:1:23 diff --git a/tests/ui/impl-trait/precise-capturing/redundant.rpitit.stderr b/tests/ui/impl-trait/precise-capturing/redundant.rpitit.stderr index 213888356e5..27f8ff92d3e 100644 --- a/tests/ui/impl-trait/precise-capturing/redundant.rpitit.stderr +++ b/tests/ui/impl-trait/precise-capturing/redundant.rpitit.stderr @@ -5,6 +5,9 @@ LL | fn in_trait() -> impl Sized + use<'a, Self>; | ^^^^^^^^^^^^^ | = note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope + = note: see issue #130044 for more information + = help: add `#![feature(precise_capturing_in_traits)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits --> $DIR/redundant.rs:21:35 @@ -13,6 +16,9 @@ LL | fn in_trait() -> impl Sized + use<'a> {} | ^^^^^^^ | = note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope + = note: see issue #130044 for more information + = help: add `#![feature(precise_capturing_in_traits)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: aborting due to 2 previous errors diff --git a/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.stderr b/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.stderr index b390a23eef4..ffd9646a403 100644 --- a/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.stderr +++ b/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.stderr @@ -5,6 +5,9 @@ LL | fn bar<'tr: 'tr>(&'tr mut self) -> impl Sized + use; | ^^^^^^^^^ | = note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope + = note: see issue #130044 for more information + = help: add `#![feature(precise_capturing_in_traits)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: return type captures more lifetimes than trait definition --> $DIR/rpitit-captures-more-method-lifetimes.rs:11:40 diff --git a/tests/ui/impl-trait/precise-capturing/rpitit.stderr b/tests/ui/impl-trait/precise-capturing/rpitit.stderr index 5a120df9f04..c162875f327 100644 --- a/tests/ui/impl-trait/precise-capturing/rpitit.stderr +++ b/tests/ui/impl-trait/precise-capturing/rpitit.stderr @@ -5,6 +5,9 @@ LL | fn hello() -> impl PartialEq + use; | ^^^^^^^^^ | = note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope + = note: see issue #130044 for more information + = help: add `#![feature(precise_capturing_in_traits)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: `impl Trait` captures lifetime parameter, but it is not mentioned in `use<...>` precise captures list --> $DIR/rpitit.rs:9:19 diff --git a/tests/ui/impl-trait/precise-capturing/self-capture.stderr b/tests/ui/impl-trait/precise-capturing/self-capture.stderr index c1974600f30..45ebc429d88 100644 --- a/tests/ui/impl-trait/precise-capturing/self-capture.stderr +++ b/tests/ui/impl-trait/precise-capturing/self-capture.stderr @@ -5,6 +5,9 @@ LL | fn bar<'a>() -> impl Sized + use; | ^^^^^^^^^ | = note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope + = note: see issue #130044 for more information + = help: add `#![feature(precise_capturing_in_traits)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: aborting due to 1 previous error From a7dc98733da8b84cfc21a538541a41803c4529a0 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 29 Sep 2024 13:41:13 -0400 Subject: [PATCH 173/357] Add variances to RPITITs --- .../rustc_hir_analysis/src/variance/mod.rs | 49 +++++++++++++-- compiler/rustc_metadata/src/rmeta/encoder.rs | 5 +- compiler/rustc_middle/src/ty/context.rs | 4 ++ compiler/rustc_type_ir/src/interner.rs | 2 + compiler/rustc_type_ir/src/relate.rs | 10 ++++ tests/ui/impl-trait/in-trait/variance.rs | 23 ++++---- tests/ui/impl-trait/in-trait/variance.stderr | 34 +++++++---- .../forgot-to-capture-type.rs | 3 +- .../forgot-to-capture-type.stderr | 17 +----- .../precise-capturing/redundant.normal.stderr | 20 ------- .../precise-capturing/redundant.rpitit.stderr | 24 -------- .../impl-trait/precise-capturing/redundant.rs | 15 +++-- .../precise-capturing/redundant.stderr | 36 +++++++++++ .../rpitit-captures-more-method-lifetimes.rs | 5 +- ...itit-captures-more-method-lifetimes.stderr | 23 ++------ .../rpitit-impl-captures-too-much.rs | 14 +++++ .../rpitit-impl-captures-too-much.stderr | 17 ++++++ .../ui/impl-trait/precise-capturing/rpitit.rs | 33 ++++++++--- .../precise-capturing/rpitit.stderr | 59 ++++++++----------- .../precise-capturing/self-capture.rs | 5 +- .../precise-capturing/self-capture.stderr | 13 ---- 21 files changed, 242 insertions(+), 169 deletions(-) delete mode 100644 tests/ui/impl-trait/precise-capturing/redundant.normal.stderr delete mode 100644 tests/ui/impl-trait/precise-capturing/redundant.rpitit.stderr create mode 100644 tests/ui/impl-trait/precise-capturing/redundant.stderr create mode 100644 tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.rs create mode 100644 tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.stderr delete mode 100644 tests/ui/impl-trait/precise-capturing/self-capture.stderr diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs index 12bb9a3f9e0..02cfb57b836 100644 --- a/compiler/rustc_hir_analysis/src/variance/mod.rs +++ b/compiler/rustc_hir_analysis/src/variance/mod.rs @@ -5,6 +5,7 @@ use itertools::Itertools; use rustc_arena::DroplessArena; +use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::query::Providers; @@ -63,8 +64,29 @@ fn variances_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Variance] { let crate_map = tcx.crate_variances(()); return crate_map.variances.get(&item_def_id.to_def_id()).copied().unwrap_or(&[]); } + DefKind::AssocTy => match tcx.opt_rpitit_info(item_def_id.to_def_id()) { + Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) => { + return variance_of_opaque( + tcx, + opaque_def_id.expect_local(), + ForceCaptureTraitArgs::Yes, + ); + } + None | Some(ty::ImplTraitInTraitData::Impl { .. }) => {} + }, DefKind::OpaqueTy => { - return variance_of_opaque(tcx, item_def_id); + let force_capture_trait_args = if let hir::OpaqueTyOrigin::FnReturn { + parent: _, + in_trait_or_impl: Some(hir::RpitContext::Trait), + } = + tcx.hir_node_by_def_id(item_def_id).expect_opaque_ty().origin + { + ForceCaptureTraitArgs::Yes + } else { + ForceCaptureTraitArgs::No + }; + + return variance_of_opaque(tcx, item_def_id, force_capture_trait_args); } _ => {} } @@ -73,8 +95,18 @@ fn variances_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Variance] { span_bug!(tcx.def_span(item_def_id), "asked to compute variance for wrong kind of item"); } +#[derive(Debug, Copy, Clone)] +enum ForceCaptureTraitArgs { + Yes, + No, +} + #[instrument(level = "trace", skip(tcx), ret)] -fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Variance] { +fn variance_of_opaque( + tcx: TyCtxt<'_>, + item_def_id: LocalDefId, + force_capture_trait_args: ForceCaptureTraitArgs, +) -> &[ty::Variance] { let generics = tcx.generics_of(item_def_id); // Opaque types may only use regions that are bound. So for @@ -115,9 +147,7 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc #[instrument(level = "trace", skip(self), ret)] fn visit_ty(&mut self, t: Ty<'tcx>) { match t.kind() { - ty::Alias(_, ty::AliasTy { def_id, args, .. }) - if matches!(self.tcx.def_kind(*def_id), DefKind::OpaqueTy) => - { + ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => { self.visit_opaque(*def_id, args); } _ => t.super_visit_with(self), @@ -135,6 +165,15 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc let mut generics = generics; while let Some(def_id) = generics.parent { generics = tcx.generics_of(def_id); + + // Don't mark trait params generic if we're in an RPITIT. + if matches!(force_capture_trait_args, ForceCaptureTraitArgs::Yes) + && generics.parent.is_none() + { + debug_assert_eq!(tcx.def_kind(def_id), DefKind::Trait); + break; + } + for param in &generics.own_params { match param.kind { ty::GenericParamDefKind::Lifetime => { diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 610c682d3a4..afe03531861 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1100,9 +1100,12 @@ fn should_encode_variances<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, def_kind: Def | DefKind::Fn | DefKind::Ctor(..) | DefKind::AssocFn => true, + DefKind::AssocTy => { + // Only encode variances for RPITITs (for traits) + matches!(tcx.opt_rpitit_info(def_id), Some(ty::ImplTraitInTraitData::Trait { .. })) + } DefKind::Mod | DefKind::Field - | DefKind::AssocTy | DefKind::AssocConst | DefKind::TyParam | DefKind::ConstParam diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 90265f67bc1..590e1d336f3 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -539,6 +539,10 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self.trait_def(trait_def_id).implement_via_object } + fn is_impl_trait_in_trait(self, def_id: DefId) -> bool { + self.is_impl_trait_in_trait(def_id) + } + fn delay_bug(self, msg: impl ToString) -> ErrorGuaranteed { self.dcx().span_delayed_bug(DUMMY_SP, msg.to_string()) } diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index a72e7b482a6..f06017d7e5c 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -261,6 +261,8 @@ pub trait Interner: fn trait_may_be_implemented_via_object(self, trait_def_id: Self::DefId) -> bool; + fn is_impl_trait_in_trait(self, def_id: Self::DefId) -> bool; + fn delay_bug(self, msg: impl ToString) -> Self::ErrorGuaranteed; fn is_general_coroutine(self, coroutine_def_id: Self::DefId) -> bool; diff --git a/compiler/rustc_type_ir/src/relate.rs b/compiler/rustc_type_ir/src/relate.rs index 1302906adab..e1f3e493e36 100644 --- a/compiler/rustc_type_ir/src/relate.rs +++ b/compiler/rustc_type_ir/src/relate.rs @@ -254,6 +254,16 @@ impl Relate for ty::AliasTy { b.args, false, // do not fetch `type_of(a_def_id)`, as it will cause a cycle )?, + ty::Projection if relation.cx().is_impl_trait_in_trait(a.def_id) => { + relate_args_with_variances( + relation, + a.def_id, + relation.cx().variances_of(a.def_id), + a.args, + b.args, + false, // do not fetch `type_of(a_def_id)`, as it will cause a cycle + )? + } ty::Projection | ty::Weak | ty::Inherent => { relate_args_invariantly(relation, a.args, b.args)? } diff --git a/tests/ui/impl-trait/in-trait/variance.rs b/tests/ui/impl-trait/in-trait/variance.rs index 0ac44bf7546..19905c608e3 100644 --- a/tests/ui/impl-trait/in-trait/variance.rs +++ b/tests/ui/impl-trait/in-trait/variance.rs @@ -1,22 +1,25 @@ -#![feature(rustc_attrs)] +#![feature(rustc_attrs, precise_capturing_in_traits)] #![allow(internal_features)] #![rustc_variance_of_opaques] -trait Captures<'a> {} -impl Captures<'_> for T {} - trait Foo<'i> { fn implicit_capture_early<'a: 'a>() -> impl Sized {} - //~^ [Self: o, 'i: *, 'a: *, 'a: o, 'i: o] + //~^ [Self: o, 'i: o, 'a: *, 'a: o, 'i: o] - fn explicit_capture_early<'a: 'a>() -> impl Sized + Captures<'a> {} - //~^ [Self: o, 'i: *, 'a: *, 'a: o, 'i: o] + fn explicit_capture_early<'a: 'a>() -> impl Sized + use<'i, 'a, Self> {} + //~^ [Self: o, 'i: o, 'a: *, 'i: o, 'a: o] + + fn not_captured_early<'a: 'a>() -> impl Sized + use<'i, Self> {} + //~^ [Self: o, 'i: o, 'a: *, 'i: o] fn implicit_capture_late<'a>(_: &'a ()) -> impl Sized {} - //~^ [Self: o, 'i: *, 'a: o, 'i: o] + //~^ [Self: o, 'i: o, 'a: o, 'i: o] - fn explicit_capture_late<'a>(_: &'a ()) -> impl Sized + Captures<'a> {} - //~^ [Self: o, 'i: *, 'a: o, 'i: o] + fn explicit_capture_late<'a>(_: &'a ()) -> impl Sized + use<'i, 'a, Self> {} + //~^ [Self: o, 'i: o, 'i: o, 'a: o] + + fn not_cpatured_late<'a>(_: &'a ()) -> impl Sized + use<'i, Self> {} + //~^ [Self: o, 'i: o, 'i: o] } fn main() {} diff --git a/tests/ui/impl-trait/in-trait/variance.stderr b/tests/ui/impl-trait/in-trait/variance.stderr index 54e0afbaa95..f65174e1c35 100644 --- a/tests/ui/impl-trait/in-trait/variance.stderr +++ b/tests/ui/impl-trait/in-trait/variance.stderr @@ -1,26 +1,38 @@ -error: [Self: o, 'i: *, 'a: *, 'a: o, 'i: o] - --> $DIR/variance.rs:9:44 +error: [Self: o, 'i: o, 'a: *, 'a: o, 'i: o] + --> $DIR/variance.rs:6:44 | LL | fn implicit_capture_early<'a: 'a>() -> impl Sized {} | ^^^^^^^^^^ -error: [Self: o, 'i: *, 'a: *, 'a: o, 'i: o] - --> $DIR/variance.rs:12:44 +error: [Self: o, 'i: o, 'a: *, 'i: o, 'a: o] + --> $DIR/variance.rs:9:44 | -LL | fn explicit_capture_early<'a: 'a>() -> impl Sized + Captures<'a> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn explicit_capture_early<'a: 'a>() -> impl Sized + use<'i, 'a, Self> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [Self: o, 'i: *, 'a: o, 'i: o] +error: [Self: o, 'i: o, 'a: *, 'i: o] + --> $DIR/variance.rs:12:40 + | +LL | fn not_captured_early<'a: 'a>() -> impl Sized + use<'i, Self> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: [Self: o, 'i: o, 'a: o, 'i: o] --> $DIR/variance.rs:15:48 | LL | fn implicit_capture_late<'a>(_: &'a ()) -> impl Sized {} | ^^^^^^^^^^ -error: [Self: o, 'i: *, 'a: o, 'i: o] +error: [Self: o, 'i: o, 'i: o, 'a: o] --> $DIR/variance.rs:18:48 | -LL | fn explicit_capture_late<'a>(_: &'a ()) -> impl Sized + Captures<'a> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn explicit_capture_late<'a>(_: &'a ()) -> impl Sized + use<'i, 'a, Self> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 4 previous errors +error: [Self: o, 'i: o, 'i: o] + --> $DIR/variance.rs:21:44 + | +LL | fn not_cpatured_late<'a>(_: &'a ()) -> impl Sized + use<'i, Self> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 6 previous errors diff --git a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.rs b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.rs index 9d68819f657..6c2477c9744 100644 --- a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.rs +++ b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.rs @@ -1,10 +1,11 @@ +#![feature(precise_capturing_in_traits)] + fn type_param() -> impl Sized + use<> {} //~^ ERROR `impl Trait` must mention all type parameters in scope trait Foo { fn bar() -> impl Sized + use<>; //~^ ERROR `impl Trait` must mention the `Self` type of the trait - //~| ERROR `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits } fn main() {} diff --git a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr index 23d6a3bd11e..93b44a0c18c 100644 --- a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr +++ b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr @@ -1,16 +1,5 @@ -error: `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits - --> $DIR/forgot-to-capture-type.rs:5:30 - | -LL | fn bar() -> impl Sized + use<>; - | ^^^^^ - | - = note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope - = note: see issue #130044 for more information - = help: add `#![feature(precise_capturing_in_traits)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - error: `impl Trait` must mention all type parameters in scope in `use<...>` - --> $DIR/forgot-to-capture-type.rs:1:23 + --> $DIR/forgot-to-capture-type.rs:3:23 | LL | fn type_param() -> impl Sized + use<> {} | - ^^^^^^^^^^^^^^^^^^ @@ -20,7 +9,7 @@ LL | fn type_param() -> impl Sized + use<> {} = note: currently, all type parameters are required to be mentioned in the precise captures list error: `impl Trait` must mention the `Self` type of the trait in `use<...>` - --> $DIR/forgot-to-capture-type.rs:5:17 + --> $DIR/forgot-to-capture-type.rs:7:17 | LL | trait Foo { | --------- `Self` type parameter is implicitly captured by this `impl Trait` @@ -29,5 +18,5 @@ LL | fn bar() -> impl Sized + use<>; | = note: currently, all type parameters are required to be mentioned in the precise captures list -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors diff --git a/tests/ui/impl-trait/precise-capturing/redundant.normal.stderr b/tests/ui/impl-trait/precise-capturing/redundant.normal.stderr deleted file mode 100644 index d1bcbaa33ae..00000000000 --- a/tests/ui/impl-trait/precise-capturing/redundant.normal.stderr +++ /dev/null @@ -1,20 +0,0 @@ -warning: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant - --> $DIR/redundant.rs:5:19 - | -LL | fn hello<'a>() -> impl Sized + use<'a> {} - | ^^^^^^^^^^^^^------- - | | - | help: remove the `use<...>` syntax - | - = note: `#[warn(impl_trait_redundant_captures)]` on by default - -warning: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant - --> $DIR/redundant.rs:10:27 - | -LL | fn inherent(&self) -> impl Sized + use<'_> {} - | ^^^^^^^^^^^^^------- - | | - | help: remove the `use<...>` syntax - -warning: 2 warnings emitted - diff --git a/tests/ui/impl-trait/precise-capturing/redundant.rpitit.stderr b/tests/ui/impl-trait/precise-capturing/redundant.rpitit.stderr deleted file mode 100644 index 27f8ff92d3e..00000000000 --- a/tests/ui/impl-trait/precise-capturing/redundant.rpitit.stderr +++ /dev/null @@ -1,24 +0,0 @@ -error: `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits - --> $DIR/redundant.rs:16:35 - | -LL | fn in_trait() -> impl Sized + use<'a, Self>; - | ^^^^^^^^^^^^^ - | - = note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope - = note: see issue #130044 for more information - = help: add `#![feature(precise_capturing_in_traits)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits - --> $DIR/redundant.rs:21:35 - | -LL | fn in_trait() -> impl Sized + use<'a> {} - | ^^^^^^^ - | - = note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope - = note: see issue #130044 for more information - = help: add `#![feature(precise_capturing_in_traits)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: aborting due to 2 previous errors - diff --git a/tests/ui/impl-trait/precise-capturing/redundant.rs b/tests/ui/impl-trait/precise-capturing/redundant.rs index 4a08ffb61be..e19d935f5b0 100644 --- a/tests/ui/impl-trait/precise-capturing/redundant.rs +++ b/tests/ui/impl-trait/precise-capturing/redundant.rs @@ -1,25 +1,24 @@ //@ compile-flags: -Zunstable-options --edition=2024 -//@ revisions: normal rpitit -//@[normal] check-pass +//@ check-pass + +#![feature(precise_capturing_in_traits)] fn hello<'a>() -> impl Sized + use<'a> {} -//[normal]~^ WARN all possible in-scope parameters are already captured +//~^ WARN all possible in-scope parameters are already captured struct Inherent; impl Inherent { fn inherent(&self) -> impl Sized + use<'_> {} - //[normal]~^ WARN all possible in-scope parameters are already captured + //~^ WARN all possible in-scope parameters are already captured } -#[cfg(rpitit)] trait Test<'a> { fn in_trait() -> impl Sized + use<'a, Self>; - //[rpitit]~^ ERROR `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits + //~^ WARN all possible in-scope parameters are already captured } -#[cfg(rpitit)] impl<'a> Test<'a> for () { fn in_trait() -> impl Sized + use<'a> {} - //[rpitit]~^ ERROR `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits + //~^ WARN all possible in-scope parameters are already captured } fn main() {} diff --git a/tests/ui/impl-trait/precise-capturing/redundant.stderr b/tests/ui/impl-trait/precise-capturing/redundant.stderr new file mode 100644 index 00000000000..274d9d2375f --- /dev/null +++ b/tests/ui/impl-trait/precise-capturing/redundant.stderr @@ -0,0 +1,36 @@ +warning: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant + --> $DIR/redundant.rs:6:19 + | +LL | fn hello<'a>() -> impl Sized + use<'a> {} + | ^^^^^^^^^^^^^------- + | | + | help: remove the `use<...>` syntax + | + = note: `#[warn(impl_trait_redundant_captures)]` on by default + +warning: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant + --> $DIR/redundant.rs:11:27 + | +LL | fn inherent(&self) -> impl Sized + use<'_> {} + | ^^^^^^^^^^^^^------- + | | + | help: remove the `use<...>` syntax + +warning: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant + --> $DIR/redundant.rs:16:22 + | +LL | fn in_trait() -> impl Sized + use<'a, Self>; + | ^^^^^^^^^^^^^------------- + | | + | help: remove the `use<...>` syntax + +warning: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant + --> $DIR/redundant.rs:20:22 + | +LL | fn in_trait() -> impl Sized + use<'a> {} + | ^^^^^^^^^^^^^------- + | | + | help: remove the `use<...>` syntax + +warning: 4 warnings emitted + diff --git a/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.rs b/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.rs index 062351afecb..b39c1408c05 100644 --- a/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.rs +++ b/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.rs @@ -2,13 +2,14 @@ // trait definition, which is not allowed. Due to the default lifetime capture // rules of RPITITs, this is only doable if we use precise capturing. +#![feature(precise_capturing_in_traits)] + pub trait Foo { fn bar<'tr: 'tr>(&'tr mut self) -> impl Sized + use; - //~^ ERROR `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits } impl Foo for () { - fn bar<'im: 'im>(&'im mut self) -> impl Sized + 'im {} + fn bar<'im: 'im>(&'im mut self) -> impl Sized + use<'im> {} //~^ ERROR return type captures more lifetimes than trait definition } diff --git a/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.stderr b/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.stderr index ffd9646a403..45f755d3cc1 100644 --- a/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.stderr +++ b/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.stderr @@ -1,28 +1,17 @@ -error: `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits - --> $DIR/rpitit-captures-more-method-lifetimes.rs:6:53 - | -LL | fn bar<'tr: 'tr>(&'tr mut self) -> impl Sized + use; - | ^^^^^^^^^ - | - = note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope - = note: see issue #130044 for more information - = help: add `#![feature(precise_capturing_in_traits)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - error: return type captures more lifetimes than trait definition - --> $DIR/rpitit-captures-more-method-lifetimes.rs:11:40 + --> $DIR/rpitit-captures-more-method-lifetimes.rs:12:40 | -LL | fn bar<'im: 'im>(&'im mut self) -> impl Sized + 'im {} - | --- ^^^^^^^^^^^^^^^^ +LL | fn bar<'im: 'im>(&'im mut self) -> impl Sized + use<'im> {} + | --- ^^^^^^^^^^^^^^^^^^^^^ | | | this lifetime was captured | note: hidden type must only reference lifetimes captured by this impl trait - --> $DIR/rpitit-captures-more-method-lifetimes.rs:6:40 + --> $DIR/rpitit-captures-more-method-lifetimes.rs:8:40 | LL | fn bar<'tr: 'tr>(&'tr mut self) -> impl Sized + use; | ^^^^^^^^^^^^^^^^^^^^^^ - = note: hidden type inferred to be `impl Sized + 'im` + = note: hidden type inferred to be `impl Sized` -error: aborting due to 2 previous errors +error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.rs b/tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.rs new file mode 100644 index 00000000000..b16b0522d6e --- /dev/null +++ b/tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.rs @@ -0,0 +1,14 @@ +#![feature(precise_capturing_in_traits)] + +struct Invariant<'a>(&'a mut &'a mut ()); + +trait Trait { + fn hello(self_: Invariant<'_>) -> impl Sized + use; +} + +impl Trait for () { + fn hello(self_: Invariant<'_>) -> impl Sized + use<'_> {} + //~^ ERROR return type captures more lifetimes than trait definition +} + +fn main() {} diff --git a/tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.stderr b/tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.stderr new file mode 100644 index 00000000000..e1856b92910 --- /dev/null +++ b/tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.stderr @@ -0,0 +1,17 @@ +error: return type captures more lifetimes than trait definition + --> $DIR/rpitit-impl-captures-too-much.rs:10:39 + | +LL | fn hello(self_: Invariant<'_>) -> impl Sized + use<'_> {} + | -- ^^^^^^^^^^^^^^^^^^^^ + | | + | this lifetime was captured + | +note: hidden type must only reference lifetimes captured by this impl trait + --> $DIR/rpitit-impl-captures-too-much.rs:6:39 + | +LL | fn hello(self_: Invariant<'_>) -> impl Sized + use; + | ^^^^^^^^^^^^^^^^^^^^^^ + = note: hidden type inferred to be `impl Sized` + +error: aborting due to 1 previous error + diff --git a/tests/ui/impl-trait/precise-capturing/rpitit.rs b/tests/ui/impl-trait/precise-capturing/rpitit.rs index feeeb1461e8..3f887e8e47f 100644 --- a/tests/ui/impl-trait/precise-capturing/rpitit.rs +++ b/tests/ui/impl-trait/precise-capturing/rpitit.rs @@ -1,19 +1,34 @@ -//@ known-bug: unknown - // RPITITs don't have variances in their GATs, so they always relate invariantly // and act as if they capture all their args. // To fix this soundly, we need to make sure that all the trait header args // remain captured, since they affect trait selection. -trait Foo<'a> { - fn hello() -> impl PartialEq + use; -} +#![feature(precise_capturing_in_traits)] -fn test<'a, 'b, T: for<'r> Foo<'r>>() { - PartialEq::eq( - &>::hello(), - &>::hello(), +fn eq_types(_: T, _: T) {} + +trait TraitLt<'a: 'a> { + fn hello() -> impl Sized + use; + //~^ ERROR `impl Trait` captures lifetime parameter, but it is not mentioned in `use<...>` precise captures list +} +fn trait_lt<'a, 'b, T: for<'r> TraitLt<'r>> () { + eq_types( + //~^ ERROR lifetime may not live long enough + //~| ERROR lifetime may not live long enough + >::hello(), + >::hello(), ); } +trait MethodLt { + fn hello<'a: 'a>() -> impl Sized + use; +} +fn method_lt<'a, 'b, T: MethodLt> () { + eq_types( + T::hello::<'a>(), + T::hello::<'b>(), + ); + // Good! +} + fn main() {} diff --git a/tests/ui/impl-trait/precise-capturing/rpitit.stderr b/tests/ui/impl-trait/precise-capturing/rpitit.stderr index c162875f327..8c219bb04a2 100644 --- a/tests/ui/impl-trait/precise-capturing/rpitit.stderr +++ b/tests/ui/impl-trait/precise-capturing/rpitit.stderr @@ -1,47 +1,40 @@ -error: `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits - --> $DIR/rpitit.rs:9:36 - | -LL | fn hello() -> impl PartialEq + use; - | ^^^^^^^^^ - | - = note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope - = note: see issue #130044 for more information - = help: add `#![feature(precise_capturing_in_traits)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - error: `impl Trait` captures lifetime parameter, but it is not mentioned in `use<...>` precise captures list - --> $DIR/rpitit.rs:9:19 + --> $DIR/rpitit.rs:11:19 | -LL | trait Foo<'a> { - | -- this lifetime parameter is captured -LL | fn hello() -> impl PartialEq + use; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime captured due to being mentioned in the bounds of the `impl Trait` +LL | trait TraitLt<'a: 'a> { + | -- this lifetime parameter is captured +LL | fn hello() -> impl Sized + use; + | ^^^^^^^^^^^^^^^^^^^^^^ lifetime captured due to being mentioned in the bounds of the `impl Trait` error: lifetime may not live long enough - --> $DIR/rpitit.rs:13:5 + --> $DIR/rpitit.rs:15:5 | -LL | fn test<'a, 'b, T: for<'r> Foo<'r>>() { - | -- -- lifetime `'b` defined here - | | - | lifetime `'a` defined here -LL | / PartialEq::eq( -LL | | &>::hello(), -LL | | &>::hello(), +LL | fn trait_lt<'a, 'b, T: for<'r> TraitLt<'r>> () { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | / eq_types( +LL | | +LL | | +LL | | >::hello(), +LL | | >::hello(), LL | | ); | |_____^ argument requires that `'a` must outlive `'b` | = help: consider adding the following bound: `'a: 'b` error: lifetime may not live long enough - --> $DIR/rpitit.rs:13:5 + --> $DIR/rpitit.rs:15:5 | -LL | fn test<'a, 'b, T: for<'r> Foo<'r>>() { - | -- -- lifetime `'b` defined here - | | - | lifetime `'a` defined here -LL | / PartialEq::eq( -LL | | &>::hello(), -LL | | &>::hello(), +LL | fn trait_lt<'a, 'b, T: for<'r> TraitLt<'r>> () { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | / eq_types( +LL | | +LL | | +LL | | >::hello(), +LL | | >::hello(), LL | | ); | |_____^ argument requires that `'b` must outlive `'a` | @@ -49,5 +42,5 @@ LL | | ); help: `'a` and `'b` must be the same: replace one with the other -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors diff --git a/tests/ui/impl-trait/precise-capturing/self-capture.rs b/tests/ui/impl-trait/precise-capturing/self-capture.rs index a61a7f06edc..15985da50b5 100644 --- a/tests/ui/impl-trait/precise-capturing/self-capture.rs +++ b/tests/ui/impl-trait/precise-capturing/self-capture.rs @@ -1,6 +1,9 @@ +//@ check-pass + +#![feature(precise_capturing_in_traits)] + trait Foo { fn bar<'a>() -> impl Sized + use; - //~^ ERROR `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits } fn main() {} diff --git a/tests/ui/impl-trait/precise-capturing/self-capture.stderr b/tests/ui/impl-trait/precise-capturing/self-capture.stderr deleted file mode 100644 index 45ebc429d88..00000000000 --- a/tests/ui/impl-trait/precise-capturing/self-capture.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error: `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits - --> $DIR/self-capture.rs:2:34 - | -LL | fn bar<'a>() -> impl Sized + use; - | ^^^^^^^^^ - | - = note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope - = note: see issue #130044 for more information - = help: add `#![feature(precise_capturing_in_traits)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: aborting due to 1 previous error - From 36076ecdc726c4e1104e70df2d142f39501a4f48 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 29 Sep 2024 13:49:32 -0400 Subject: [PATCH 174/357] Clarify implicit captures for RPITIT --- compiler/rustc_hir_analysis/messages.ftl | 3 +++ .../rustc_hir_analysis/src/check/check.rs | 25 ++++++++++++------- .../src/errors/precise_captures.rs | 9 +++++++ .../precise-capturing/rpitit.stderr | 4 +-- 4 files changed, 30 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index c73826c489f..a80dc87c622 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -259,6 +259,9 @@ hir_analysis_late_bound_lifetime_in_apit = `impl Trait` can only mention lifetim hir_analysis_late_bound_type_in_apit = `impl Trait` can only mention type parameters from an fn or impl .label = type parameter declared here +hir_analysis_lifetime_implicitly_captured = `impl Trait` captures lifetime parameter, but it is not mentioned in `use<...>` precise captures list + .param_label = all lifetime parameters originating from a trait are captured implicitly + hir_analysis_lifetime_must_be_first = lifetime parameter `{$name}` must be listed before non-lifetime parameters .label = move the lifetime before this parameter diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index eb62ff86c71..d0063b449f8 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -589,15 +589,22 @@ fn check_opaque_precise_captures<'tcx>(tcx: TyCtxt<'tcx>, opaque_def_id: LocalDe param_span: tcx.def_span(def_id), }); } else { - // If the `use_span` is actually just the param itself, then we must - // have not duplicated the lifetime but captured the original. - // The "effective" `use_span` will be the span of the opaque itself, - // and the param span will be the def span of the param. - tcx.dcx().emit_err(errors::LifetimeNotCaptured { - opaque_span, - use_span: opaque_span, - param_span: use_span, - }); + if tcx.def_kind(tcx.parent(param.def_id)) == DefKind::Trait { + tcx.dcx().emit_err(errors::LifetimeImplicitlyCaptured { + opaque_span, + param_span: tcx.def_span(param.def_id), + }); + } else { + // If the `use_span` is actually just the param itself, then we must + // have not duplicated the lifetime but captured the original. + // The "effective" `use_span` will be the span of the opaque itself, + // and the param span will be the def span of the param. + tcx.dcx().emit_err(errors::LifetimeNotCaptured { + opaque_span, + use_span: opaque_span, + param_span: use_span, + }); + } } continue; } diff --git a/compiler/rustc_hir_analysis/src/errors/precise_captures.rs b/compiler/rustc_hir_analysis/src/errors/precise_captures.rs index b6cffb90805..8a83866b7fa 100644 --- a/compiler/rustc_hir_analysis/src/errors/precise_captures.rs +++ b/compiler/rustc_hir_analysis/src/errors/precise_captures.rs @@ -34,6 +34,15 @@ pub(crate) struct LifetimeNotCaptured { pub opaque_span: Span, } +#[derive(Diagnostic)] +#[diag(hir_analysis_lifetime_implicitly_captured)] +pub(crate) struct LifetimeImplicitlyCaptured { + #[primary_span] + pub opaque_span: Span, + #[label(hir_analysis_param_label)] + pub param_span: Span, +} + #[derive(Diagnostic)] #[diag(hir_analysis_bad_precise_capture)] pub(crate) struct BadPreciseCapture { diff --git a/tests/ui/impl-trait/precise-capturing/rpitit.stderr b/tests/ui/impl-trait/precise-capturing/rpitit.stderr index 8c219bb04a2..498eae54a1c 100644 --- a/tests/ui/impl-trait/precise-capturing/rpitit.stderr +++ b/tests/ui/impl-trait/precise-capturing/rpitit.stderr @@ -2,9 +2,9 @@ error: `impl Trait` captures lifetime parameter, but it is not mentioned in `use --> $DIR/rpitit.rs:11:19 | LL | trait TraitLt<'a: 'a> { - | -- this lifetime parameter is captured + | -- all lifetime parameters originating from a trait are captured implicitly LL | fn hello() -> impl Sized + use; - | ^^^^^^^^^^^^^^^^^^^^^^ lifetime captured due to being mentioned in the bounds of the `impl Trait` + | ^^^^^^^^^^^^^^^^^^^^^^ error: lifetime may not live long enough --> $DIR/rpitit.rs:15:5 From 322c4bdac595e7689dcf08b847d0bd4d82a4bad9 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 29 Sep 2024 13:49:53 -0400 Subject: [PATCH 175/357] Don't fire refinement lint if there are errors --- .../rustc_hir_analysis/src/check/compare_impl_item/refine.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs index 80334c6efe7..2d6b9813271 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs @@ -64,6 +64,10 @@ pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>( return; }; + if hidden_tys.items().any(|(_, &ty)| ty.skip_binder().references_error()) { + return; + } + let mut collector = ImplTraitInTraitCollector { tcx, types: FxIndexSet::default() }; trait_m_sig.visit_with(&mut collector); From 82433eeedf3d009262f1dc5d8f73d6c13acad7fc Mon Sep 17 00:00:00 2001 From: Julia Ryan Date: Thu, 10 Oct 2024 12:35:26 -0700 Subject: [PATCH 176/357] Update .mailmap --- .mailmap | 1 + 1 file changed, 1 insertion(+) diff --git a/.mailmap b/.mailmap index 0f58762e023..dc5bfe6d5fc 100644 --- a/.mailmap +++ b/.mailmap @@ -312,6 +312,7 @@ Josh Driver Josh Holmer Josh Stone Josh Stone +Julia Ryan Julian Knodt jumbatm <30644300+jumbatm@users.noreply.github.com> Junyoung Cho From 37698a9bf1fd5758cd8a2a344f1597d290854bf8 Mon Sep 17 00:00:00 2001 From: tiif Date: Thu, 10 Oct 2024 12:09:37 +0800 Subject: [PATCH 177/357] Pipe minor changes: diagnostics, flag support and comments --- .../miri/src/shims/unix/foreign_items.rs | 7 +++ .../miri/src/shims/unix/unnamed_socket.rs | 47 ++++++++++++------- .../libc/socketpair_read_blocking.stderr | 4 +- .../libc/socketpair_write_blocking.stderr | 4 +- .../pass-dep/libc/libc-epoll-blocking.rs | 2 +- .../miri/tests/pass-dep/libc/libc-pipe.rs | 21 +++++++++ 6 files changed, 64 insertions(+), 21 deletions(-) diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs index 908f91a3bd6..7ba98981920 100644 --- a/src/tools/miri/src/shims/unix/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/foreign_items.rs @@ -292,6 +292,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(result, dest)?; } "pipe2" => { + // Currently this function does not exist on all Unixes, e.g. on macOS. + if !matches!(&*this.tcx.sess.target.os, "linux" | "freebsd" | "solaris" | "illumos") { + throw_unsup_format!( + "`pipe2` is not supported on {}", + this.tcx.sess.target.os + ); + } let [pipefd, flags] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let result = this.pipe2(pipefd, Some(flags))?; diff --git a/src/tools/miri/src/shims/unix/unnamed_socket.rs b/src/tools/miri/src/shims/unix/unnamed_socket.rs index e83c0afb287..d0eba1eacd1 100644 --- a/src/tools/miri/src/shims/unix/unnamed_socket.rs +++ b/src/tools/miri/src/shims/unix/unnamed_socket.rs @@ -163,7 +163,7 @@ impl FileDescription for AnonSocket { } else { // Blocking socketpair with writer and empty buffer. // FIXME: blocking is currently not supported - throw_unsup_format!("socketpair read: blocking isn't supported yet"); + throw_unsup_format!("socketpair/pipe/pipe2 read: blocking isn't supported yet"); } } } @@ -230,7 +230,7 @@ impl FileDescription for AnonSocket { return ecx.set_last_error_and_return(ErrorKind::WouldBlock, dest); } else { // Blocking socketpair with a full buffer. - throw_unsup_format!("socketpair write: blocking isn't supported yet"); + throw_unsup_format!("socketpair/pipe/pipe2 write: blocking isn't supported yet"); } } // Remember this clock so `read` can synchronize with us. @@ -267,21 +267,24 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let this = self.eval_context_mut(); let domain = this.read_scalar(domain)?.to_i32()?; - let mut type_ = this.read_scalar(type_)?.to_i32()?; + let mut flags = this.read_scalar(type_)?.to_i32()?; let protocol = this.read_scalar(protocol)?.to_i32()?; let sv = this.deref_pointer(sv)?; let mut is_sock_nonblock = false; - // Parse and remove the type flags that we support. - // SOCK_NONBLOCK only exists on Linux. + // Interpret the flag. Every flag we recognize is "subtracted" from `flags`, so + // if there is anything left at the end, that's an unsupported flag. if this.tcx.sess.target.os == "linux" { - if type_ & this.eval_libc_i32("SOCK_NONBLOCK") == this.eval_libc_i32("SOCK_NONBLOCK") { + // SOCK_NONBLOCK only exists on Linux. + let sock_nonblock = this.eval_libc_i32("SOCK_NONBLOCK"); + let sock_cloexec = this.eval_libc_i32("SOCK_CLOEXEC"); + if flags & sock_nonblock == sock_nonblock { is_sock_nonblock = true; - type_ &= !(this.eval_libc_i32("SOCK_NONBLOCK")); + flags &= !sock_nonblock; } - if type_ & this.eval_libc_i32("SOCK_CLOEXEC") == this.eval_libc_i32("SOCK_CLOEXEC") { - type_ &= !(this.eval_libc_i32("SOCK_CLOEXEC")); + if flags & sock_cloexec == sock_cloexec { + flags &= !sock_cloexec; } } @@ -294,11 +297,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { and AF_LOCAL are allowed", domain ); - } else if type_ != this.eval_libc_i32("SOCK_STREAM") { + } else if flags != this.eval_libc_i32("SOCK_STREAM") { throw_unsup_format!( "socketpair: type {:#x} is unsupported, only SOCK_STREAM, \ SOCK_CLOEXEC and SOCK_NONBLOCK are allowed", - type_ + flags ); } else if protocol != 0 { throw_unsup_format!( @@ -347,14 +350,26 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let this = self.eval_context_mut(); let pipefd = this.deref_pointer_as(pipefd, this.machine.layouts.i32)?; - let flags = match flags { + let mut flags = match flags { Some(flags) => this.read_scalar(flags)?.to_i32()?, None => 0, }; - // As usual we ignore CLOEXEC. let cloexec = this.eval_libc_i32("O_CLOEXEC"); - if flags != 0 && flags != cloexec { + let o_nonblock = this.eval_libc_i32("O_NONBLOCK"); + + // Interpret the flag. Every flag we recognize is "subtracted" from `flags`, so + // if there is anything left at the end, that's an unsupported flag. + let mut is_nonblock = false; + if flags & o_nonblock == o_nonblock { + is_nonblock = true; + flags &= !o_nonblock; + } + // As usual we ignore CLOEXEC. + if flags & cloexec == cloexec { + flags &= !cloexec; + } + if flags != 0 { throw_unsup_format!("unsupported flags in `pipe2`"); } @@ -365,13 +380,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { readbuf: Some(RefCell::new(Buffer::new())), peer_fd: OnceCell::new(), peer_lost_data: Cell::new(false), - is_nonblock: false, + is_nonblock, }); let fd1 = fds.new_ref(AnonSocket { readbuf: None, peer_fd: OnceCell::new(), peer_lost_data: Cell::new(false), - is_nonblock: false, + is_nonblock, }); // Make the file descriptions point to each other. diff --git a/src/tools/miri/tests/fail-dep/libc/socketpair_read_blocking.stderr b/src/tools/miri/tests/fail-dep/libc/socketpair_read_blocking.stderr index dff332f9992..16892614c63 100644 --- a/src/tools/miri/tests/fail-dep/libc/socketpair_read_blocking.stderr +++ b/src/tools/miri/tests/fail-dep/libc/socketpair_read_blocking.stderr @@ -1,8 +1,8 @@ -error: unsupported operation: socketpair read: blocking isn't supported yet +error: unsupported operation: socketpair/pipe/pipe2 read: blocking isn't supported yet --> tests/fail-dep/libc/socketpair_read_blocking.rs:LL:CC | LL | let _res = unsafe { libc::read(fds[1], buf.as_mut_ptr().cast(), buf.len() as libc::size_t) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ socketpair read: blocking isn't supported yet + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ socketpair/pipe/pipe2 read: blocking isn't supported yet | = help: this is likely not a bug in the program; it indicates that the program performed an operation that Miri does not support = note: BACKTRACE: diff --git a/src/tools/miri/tests/fail-dep/libc/socketpair_write_blocking.stderr b/src/tools/miri/tests/fail-dep/libc/socketpair_write_blocking.stderr index 0dd89a15c7c..a2fcf87578a 100644 --- a/src/tools/miri/tests/fail-dep/libc/socketpair_write_blocking.stderr +++ b/src/tools/miri/tests/fail-dep/libc/socketpair_write_blocking.stderr @@ -1,8 +1,8 @@ -error: unsupported operation: socketpair write: blocking isn't supported yet +error: unsupported operation: socketpair/pipe/pipe2 write: blocking isn't supported yet --> tests/fail-dep/libc/socketpair_write_blocking.rs:LL:CC | LL | let _ = unsafe { libc::write(fds[0], data as *const libc::c_void, 3) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ socketpair write: blocking isn't supported yet + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ socketpair/pipe/pipe2 write: blocking isn't supported yet | = help: this is likely not a bug in the program; it indicates that the program performed an operation that Miri does not support = note: BACKTRACE: diff --git a/src/tools/miri/tests/pass-dep/libc/libc-epoll-blocking.rs b/src/tools/miri/tests/pass-dep/libc/libc-epoll-blocking.rs index d7675a40163..9bcc776e281 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-epoll-blocking.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-epoll-blocking.rs @@ -161,7 +161,7 @@ fn test_epoll_race() { // Write to the eventfd instance. let sized_8_data: [u8; 8] = 1_u64.to_ne_bytes(); let res = unsafe { libc::write(fd, sized_8_data.as_ptr() as *const libc::c_void, 8) }; - // read returns number of bytes that have been read, which is always 8. + // write returns number of bytes written, which is always 8. assert_eq!(res, 8); }); thread::yield_now(); diff --git a/src/tools/miri/tests/pass-dep/libc/libc-pipe.rs b/src/tools/miri/tests/pass-dep/libc/libc-pipe.rs index 76f883e5d8d..01433edf9a3 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-pipe.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-pipe.rs @@ -7,6 +7,14 @@ fn main() { test_pipe_threaded(); test_race(); test_pipe_array(); + #[cfg(any( + target_os = "linux", + target_os = "illumos", + target_os = "freebsd", + target_os = "solaris" + ))] + // `pipe2` only exists in some specific os. + test_pipe2(); } fn test_pipe() { @@ -110,3 +118,16 @@ fn test_pipe_array() { let mut fds: [i32; 2] = [0; 2]; assert_eq!(unsafe { pipe(&mut fds) }, 0); } + +/// Test if pipe2 (including the O_NONBLOCK flag) is supported. +#[cfg(any( + target_os = "linux", + target_os = "illumos", + target_os = "freebsd", + target_os = "solaris" +))] +fn test_pipe2() { + let mut fds = [-1, -1]; + let res = unsafe { libc::pipe2(fds.as_mut_ptr(), libc::O_NONBLOCK) }; + assert_eq!(res, 0); +} From 1df7a0ffb759d5347ebc547adc0755b1ab85478e Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 10 Oct 2024 22:05:05 +0200 Subject: [PATCH 178/357] add libc-pipe test to CI for freebsd, solarish --- src/tools/miri/ci/ci.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/tools/miri/ci/ci.sh b/src/tools/miri/ci/ci.sh index 689bc6d46fc..ad1b2f4d0c3 100755 --- a/src/tools/miri/ci/ci.sh +++ b/src/tools/miri/ci/ci.sh @@ -150,10 +150,10 @@ case $HOST_TARGET in # Partially supported targets (tier 2) BASIC="empty_main integer heap_alloc libc-mem vec string btreemap" # ensures we have the basics: pre-main code, system allocator UNIX="hello panic/panic panic/unwind concurrency/simple atomic libc-mem libc-misc libc-random env num_cpus" # the things that are very similar across all Unixes, and hence easily supported there - TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal $BASIC $UNIX time hashmap random threadname pthread fs - TEST_TARGET=i686-unknown-freebsd run_tests_minimal $BASIC $UNIX time hashmap random threadname pthread fs - TEST_TARGET=x86_64-unknown-illumos run_tests_minimal $BASIC $UNIX time hashmap random thread sync available-parallelism tls - TEST_TARGET=x86_64-pc-solaris run_tests_minimal $BASIC $UNIX time hashmap random thread sync available-parallelism tls + TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal $BASIC $UNIX time hashmap random threadname pthread fs libc-pipe + TEST_TARGET=i686-unknown-freebsd run_tests_minimal $BASIC $UNIX time hashmap random threadname pthread fs libc-pipe + TEST_TARGET=x86_64-unknown-illumos run_tests_minimal $BASIC $UNIX time hashmap random thread sync available-parallelism tls libc-pipe + TEST_TARGET=x86_64-pc-solaris run_tests_minimal $BASIC $UNIX time hashmap random thread sync available-parallelism tls libc-pipe TEST_TARGET=aarch64-linux-android run_tests_minimal $BASIC $UNIX time hashmap pthread --skip threadname TEST_TARGET=wasm32-wasip2 run_tests_minimal $BASIC wasm TEST_TARGET=wasm32-unknown-unknown run_tests_minimal no_std empty_main wasm # this target doesn't really have std From 8b754fbb4f4fa05f0e7550c8a3aa4c9e8bd95e11 Mon Sep 17 00:00:00 2001 From: Johnathan W <12262567+j7nw4r@users.noreply.github.com> Date: Thu, 10 Oct 2024 16:11:30 -0400 Subject: [PATCH 179/357] Fixing rustDoc for LayoutError. --- library/core/src/alloc/layout.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/core/src/alloc/layout.rs b/library/core/src/alloc/layout.rs index 107d82267e5..fca32b9d3c5 100644 --- a/library/core/src/alloc/layout.rs +++ b/library/core/src/alloc/layout.rs @@ -540,7 +540,8 @@ impl Layout { )] pub type LayoutErr = LayoutError; -/// The parameters given to `Layout::from_size_align` +/// The `LayoutError` is returned when the parameters given +/// to `Layout::from_size_align` /// or some other `Layout` constructor /// do not satisfy its documented constraints. #[stable(feature = "alloc_layout_error", since = "1.50.0")] From 8a9b67028cd9e3e580318007e7bc6391a7c6b86c Mon Sep 17 00:00:00 2001 From: Alona Enraght-Moony Date: Thu, 10 Oct 2024 20:53:57 +0000 Subject: [PATCH 180/357] rustdoc-json: Add tests for unsafe/safe extern blocks (RFC 3484) --- tests/rustdoc-json/fns/extern_safe.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 tests/rustdoc-json/fns/extern_safe.rs diff --git a/tests/rustdoc-json/fns/extern_safe.rs b/tests/rustdoc-json/fns/extern_safe.rs new file mode 100644 index 00000000000..a4a2d2c7f8c --- /dev/null +++ b/tests/rustdoc-json/fns/extern_safe.rs @@ -0,0 +1,17 @@ +extern "C" { + //@ is "$.index[*][?(@.name=='f1')].inner.function.header.is_unsafe" true + pub fn f1(); + + // items in unadorned `extern` blocks cannot have safety qualifiers +} + +unsafe extern "C" { + //@ is "$.index[*][?(@.name=='f4')].inner.function.header.is_unsafe" true + pub fn f4(); + + //@ is "$.index[*][?(@.name=='f5')].inner.function.header.is_unsafe" true + pub unsafe fn f5(); + + //@ is "$.index[*][?(@.name=='f6')].inner.function.header.is_unsafe" false + pub safe fn f6(); +} From 42c0494499b3ee271bafa68bbfe5eb5176442c4d Mon Sep 17 00:00:00 2001 From: David Lattimore Date: Fri, 11 Oct 2024 07:58:36 +1100 Subject: [PATCH 181/357] Use Default visibility for rustc-generated C symbol declarations Non-default visibilities should only be used for definitions, not declarations, otherwise linking can fail. Co-authored-by: Collin Baker --- compiler/rustc_codegen_llvm/src/declare.rs | 7 +++---- tests/codegen/default-visibility.rs | 16 ++++++++++++++++ 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/declare.rs b/compiler/rustc_codegen_llvm/src/declare.rs index 7be44dd51b5..33258cb46fa 100644 --- a/compiler/rustc_codegen_llvm/src/declare.rs +++ b/compiler/rustc_codegen_llvm/src/declare.rs @@ -84,10 +84,9 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { unnamed: llvm::UnnamedAddr, fn_type: &'ll Type, ) -> &'ll Value { - // Declare C ABI functions with the visibility used by C by default. - let visibility = Visibility::from_generic(self.tcx.sess.default_visibility()); - - declare_raw_fn(self, name, llvm::CCallConv, unnamed, visibility, fn_type) + // Visibility should always be default for declarations, otherwise the linker may report an + // error. + declare_raw_fn(self, name, llvm::CCallConv, unnamed, Visibility::Default, fn_type) } /// Declare an entry Function diff --git a/tests/codegen/default-visibility.rs b/tests/codegen/default-visibility.rs index 884d386ec20..88ff9fee254 100644 --- a/tests/codegen/default-visibility.rs +++ b/tests/codegen/default-visibility.rs @@ -31,3 +31,19 @@ pub static tested_symbol: [u8; 6] = *b"foobar"; // PROTECTED: @{{.*}}default_visibility{{.*}}tested_symbol{{.*}} = protected constant // INTERPOSABLE: @{{.*}}default_visibility{{.*}}tested_symbol{{.*}} = constant // DEFAULT: @{{.*}}default_visibility{{.*}}tested_symbol{{.*}} = constant + +pub fn do_memcmp(left: &[u8], right: &[u8]) -> i32 { + left.cmp(right) as i32 +} + +// CHECK: define {{.*}} @{{.*}}do_memcmp{{.*}} { +// CHECK: } + +// `do_memcmp` should invoke core::intrinsic::compare_bytes which emits a call +// to the C symbol `memcmp` (at least on x86_64-unknown-linux-gnu). This symbol +// should *not* be declared hidden or protected. + +// HIDDEN: declare i32 @memcmp +// PROTECTED: declare i32 @memcmp +// INTERPOSABLE: declare i32 @memcmp +// DEFAULT: declare i32 @memcmp From 159e67d44646621f157f07b61f7d78f231c452c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonathan=20D=C3=B6nszelmann?= Date: Fri, 11 Oct 2024 00:14:17 +0200 Subject: [PATCH 182/357] rename RcBox to RcInner for consistency --- library/alloc/src/rc.rs | 138 +++++++++++++++++++++------------------- 1 file changed, 71 insertions(+), 67 deletions(-) diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 0e2c35845e8..e6f27f53639 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -282,19 +282,19 @@ mod tests; // would interfere with otherwise safe [into|from]_raw() of transmutable // inner types. #[repr(C)] -struct RcBox { +struct RcInner { strong: Cell, weak: Cell, value: T, } -/// Calculate layout for `RcBox` using the inner value's layout +/// Calculate layout for `RcInner` using the inner value's layout fn rcbox_layout_for_value_layout(layout: Layout) -> Layout { // Calculate layout using the given value layout. // Previously, layout was calculated on the expression - // `&*(ptr as *const RcBox)`, but this created a misaligned + // `&*(ptr as *const RcInner)`, but this created a misaligned // reference (see #54908). - Layout::new::>().extend(layout).unwrap().0.pad_to_align() + Layout::new::>().extend(layout).unwrap().0.pad_to_align() } /// A single-threaded reference-counting pointer. 'Rc' stands for 'Reference @@ -314,8 +314,8 @@ pub struct Rc< T: ?Sized, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, > { - ptr: NonNull>, - phantom: PhantomData>, + ptr: NonNull>, + phantom: PhantomData>, alloc: A, } @@ -343,37 +343,37 @@ impl, U: ?Sized> DispatchFromDyn> for Rc {} impl Rc { #[inline] - unsafe fn from_inner(ptr: NonNull>) -> Self { + unsafe fn from_inner(ptr: NonNull>) -> Self { unsafe { Self::from_inner_in(ptr, Global) } } #[inline] - unsafe fn from_ptr(ptr: *mut RcBox) -> Self { + unsafe fn from_ptr(ptr: *mut RcInner) -> Self { unsafe { Self::from_inner(NonNull::new_unchecked(ptr)) } } } impl Rc { #[inline(always)] - fn inner(&self) -> &RcBox { + fn inner(&self) -> &RcInner { // This unsafety is ok because while this Rc is alive we're guaranteed // that the inner pointer is valid. unsafe { self.ptr.as_ref() } } #[inline] - fn into_inner_with_allocator(this: Self) -> (NonNull>, A) { + fn into_inner_with_allocator(this: Self) -> (NonNull>, A) { let this = mem::ManuallyDrop::new(this); (this.ptr, unsafe { ptr::read(&this.alloc) }) } #[inline] - unsafe fn from_inner_in(ptr: NonNull>, alloc: A) -> Self { + unsafe fn from_inner_in(ptr: NonNull>, alloc: A) -> Self { Self { ptr, phantom: PhantomData, alloc } } #[inline] - unsafe fn from_ptr_in(ptr: *mut RcBox, alloc: A) -> Self { + unsafe fn from_ptr_in(ptr: *mut RcInner, alloc: A) -> Self { unsafe { Self::from_inner_in(NonNull::new_unchecked(ptr), alloc) } } } @@ -397,7 +397,7 @@ impl Rc { // if the weak pointer is stored inside the strong one. unsafe { Self::from_inner( - Box::leak(Box::new(RcBox { strong: Cell::new(1), weak: Cell::new(1), value })) + Box::leak(Box::new(RcInner { strong: Cell::new(1), weak: Cell::new(1), value })) .into(), ) } @@ -546,8 +546,12 @@ impl Rc { // if the weak pointer is stored inside the strong one. unsafe { Ok(Self::from_inner( - Box::leak(Box::try_new(RcBox { strong: Cell::new(1), weak: Cell::new(1), value })?) - .into(), + Box::leak(Box::try_new(RcInner { + strong: Cell::new(1), + weak: Cell::new(1), + value, + })?) + .into(), )) } } @@ -646,7 +650,7 @@ impl Rc { // That would make code size bigger. match Self::try_new_in(value, alloc) { Ok(m) => m, - Err(_) => handle_alloc_error(Layout::new::>()), + Err(_) => handle_alloc_error(Layout::new::>()), } } @@ -765,7 +769,7 @@ impl Rc { // Construct the inner in the "uninitialized" state with a single // weak reference. let (uninit_raw_ptr, alloc) = Box::into_raw_with_allocator(Box::new_in( - RcBox { + RcInner { strong: Cell::new(0), weak: Cell::new(1), value: mem::MaybeUninit::::uninit(), @@ -773,7 +777,7 @@ impl Rc { alloc, )); let uninit_ptr: NonNull<_> = (unsafe { &mut *uninit_raw_ptr }).into(); - let init_ptr: NonNull> = uninit_ptr.cast(); + let init_ptr: NonNull> = uninit_ptr.cast(); let weak = Weak { ptr: init_ptr, alloc: alloc }; @@ -826,7 +830,7 @@ impl Rc { // the allocation while the strong destructor is running, even // if the weak pointer is stored inside the strong one. let (ptr, alloc) = Box::into_unique(Box::try_new_in( - RcBox { strong: Cell::new(1), weak: Cell::new(1), value }, + RcInner { strong: Cell::new(1), weak: Cell::new(1), value }, alloc, )?); Ok(unsafe { Self::from_inner_in(ptr.into(), alloc) }) @@ -1059,7 +1063,7 @@ impl Rc<[T]> { |layout| Global.allocate_zeroed(layout), |mem| { ptr::slice_from_raw_parts_mut(mem.cast::(), len) - as *mut RcBox<[mem::MaybeUninit]> + as *mut RcInner<[mem::MaybeUninit]> }, )) } @@ -1132,7 +1136,7 @@ impl Rc<[T], A> { |layout| alloc.allocate_zeroed(layout), |mem| { ptr::slice_from_raw_parts_mut(mem.cast::(), len) - as *mut RcBox<[mem::MaybeUninit]> + as *mut RcInner<[mem::MaybeUninit]> }, ), alloc, @@ -1437,7 +1441,7 @@ impl Rc { #[stable(feature = "weak_into_raw", since = "1.45.0")] #[rustc_never_returns_null_ptr] pub fn as_ptr(this: &Self) -> *const T { - let ptr: *mut RcBox = NonNull::as_ptr(this.ptr); + let ptr: *mut RcInner = NonNull::as_ptr(this.ptr); // SAFETY: This cannot go through Deref::deref or Rc::inner because // this is required to retain raw/mut provenance such that e.g. `get_mut` can @@ -1516,8 +1520,8 @@ impl Rc { pub unsafe fn from_raw_in(ptr: *const T, alloc: A) -> Self { let offset = unsafe { data_offset(ptr) }; - // Reverse the offset to find the original RcBox. - let rc_ptr = unsafe { ptr.byte_sub(offset) as *mut RcBox }; + // Reverse the offset to find the original RcInner. + let rc_ptr = unsafe { ptr.byte_sub(offset) as *mut RcInner }; unsafe { Self::from_ptr_in(rc_ptr, alloc) } } @@ -2002,17 +2006,17 @@ impl Rc { } impl Rc { - /// Allocates an `RcBox` with sufficient space for + /// Allocates an `RcInner` with sufficient space for /// a possibly-unsized inner value where the value has the layout provided. /// /// The function `mem_to_rcbox` is called with the data pointer - /// and must return back a (potentially fat)-pointer for the `RcBox`. + /// and must return back a (potentially fat)-pointer for the `RcInner`. #[cfg(not(no_global_oom_handling))] unsafe fn allocate_for_layout( value_layout: Layout, allocate: impl FnOnce(Layout) -> Result, AllocError>, - mem_to_rcbox: impl FnOnce(*mut u8) -> *mut RcBox, - ) -> *mut RcBox { + mem_to_rcbox: impl FnOnce(*mut u8) -> *mut RcInner, + ) -> *mut RcInner { let layout = rcbox_layout_for_value_layout(value_layout); unsafe { Rc::try_allocate_for_layout(value_layout, allocate, mem_to_rcbox) @@ -2020,24 +2024,24 @@ impl Rc { } } - /// Allocates an `RcBox` with sufficient space for + /// Allocates an `RcInner` with sufficient space for /// a possibly-unsized inner value where the value has the layout provided, /// returning an error if allocation fails. /// /// The function `mem_to_rcbox` is called with the data pointer - /// and must return back a (potentially fat)-pointer for the `RcBox`. + /// and must return back a (potentially fat)-pointer for the `RcInner`. #[inline] unsafe fn try_allocate_for_layout( value_layout: Layout, allocate: impl FnOnce(Layout) -> Result, AllocError>, - mem_to_rcbox: impl FnOnce(*mut u8) -> *mut RcBox, - ) -> Result<*mut RcBox, AllocError> { + mem_to_rcbox: impl FnOnce(*mut u8) -> *mut RcInner, + ) -> Result<*mut RcInner, AllocError> { let layout = rcbox_layout_for_value_layout(value_layout); // Allocate for the layout. let ptr = allocate(layout)?; - // Initialize the RcBox + // Initialize the RcInner let inner = mem_to_rcbox(ptr.as_non_null_ptr().as_ptr()); unsafe { debug_assert_eq!(Layout::for_value_raw(inner), layout); @@ -2051,15 +2055,15 @@ impl Rc { } impl Rc { - /// Allocates an `RcBox` with sufficient space for an unsized inner value + /// Allocates an `RcInner` with sufficient space for an unsized inner value #[cfg(not(no_global_oom_handling))] - unsafe fn allocate_for_ptr_in(ptr: *const T, alloc: &A) -> *mut RcBox { - // Allocate for the `RcBox` using the given value. + unsafe fn allocate_for_ptr_in(ptr: *const T, alloc: &A) -> *mut RcInner { + // Allocate for the `RcInner` using the given value. unsafe { Rc::::allocate_for_layout( Layout::for_value_raw(ptr), |layout| alloc.allocate(layout), - |mem| mem.with_metadata_of(ptr as *const RcBox), + |mem| mem.with_metadata_of(ptr as *const RcInner), ) } } @@ -2088,14 +2092,14 @@ impl Rc { } impl Rc<[T]> { - /// Allocates an `RcBox<[T]>` with the given length. + /// Allocates an `RcInner<[T]>` with the given length. #[cfg(not(no_global_oom_handling))] - unsafe fn allocate_for_slice(len: usize) -> *mut RcBox<[T]> { + unsafe fn allocate_for_slice(len: usize) -> *mut RcInner<[T]> { unsafe { Self::allocate_for_layout( Layout::array::(len).unwrap(), |layout| Global.allocate(layout), - |mem| ptr::slice_from_raw_parts_mut(mem.cast::(), len) as *mut RcBox<[T]>, + |mem| ptr::slice_from_raw_parts_mut(mem.cast::(), len) as *mut RcInner<[T]>, ) } } @@ -2119,7 +2123,7 @@ impl Rc<[T]> { unsafe fn from_iter_exact(iter: impl Iterator, len: usize) -> Rc<[T]> { // Panic guard while cloning T elements. // In the event of a panic, elements that have been written - // into the new RcBox will be dropped, then the memory freed. + // into the new RcInner will be dropped, then the memory freed. struct Guard { mem: NonNull, elems: *mut T, @@ -2154,7 +2158,7 @@ impl Rc<[T]> { guard.n_elems += 1; } - // All clear. Forget the guard so it doesn't free the new RcBox. + // All clear. Forget the guard so it doesn't free the new RcInner. mem::forget(guard); Self::from_ptr(ptr) @@ -2163,15 +2167,15 @@ impl Rc<[T]> { } impl Rc<[T], A> { - /// Allocates an `RcBox<[T]>` with the given length. + /// Allocates an `RcInner<[T]>` with the given length. #[inline] #[cfg(not(no_global_oom_handling))] - unsafe fn allocate_for_slice_in(len: usize, alloc: &A) -> *mut RcBox<[T]> { + unsafe fn allocate_for_slice_in(len: usize, alloc: &A) -> *mut RcInner<[T]> { unsafe { Rc::<[T]>::allocate_for_layout( Layout::array::(len).unwrap(), |layout| alloc.allocate(layout), - |mem| ptr::slice_from_raw_parts_mut(mem.cast::(), len) as *mut RcBox<[T]>, + |mem| ptr::slice_from_raw_parts_mut(mem.cast::(), len) as *mut RcInner<[T]>, ) } } @@ -2901,9 +2905,9 @@ pub struct Weak< // but it is not necessarily a valid pointer. // `Weak::new` sets this to `usize::MAX` so that it doesn’t need // to allocate space on the heap. That's not a value a real pointer - // will ever have because RcBox has alignment at least 2. + // will ever have because RcInner has alignment at least 2. // This is only possible when `T: Sized`; unsized `T` never dangle. - ptr: NonNull>, + ptr: NonNull>, alloc: A, } @@ -2939,7 +2943,7 @@ impl Weak { pub const fn new() -> Weak { Weak { ptr: unsafe { - NonNull::new_unchecked(ptr::without_provenance_mut::>(usize::MAX)) + NonNull::new_unchecked(ptr::without_provenance_mut::>(usize::MAX)) }, alloc: Global, } @@ -2966,7 +2970,7 @@ impl Weak { pub fn new_in(alloc: A) -> Weak { Weak { ptr: unsafe { - NonNull::new_unchecked(ptr::without_provenance_mut::>(usize::MAX)) + NonNull::new_unchecked(ptr::without_provenance_mut::>(usize::MAX)) }, alloc, } @@ -3070,11 +3074,11 @@ impl Weak { #[must_use] #[stable(feature = "rc_as_ptr", since = "1.45.0")] pub fn as_ptr(&self) -> *const T { - let ptr: *mut RcBox = NonNull::as_ptr(self.ptr); + let ptr: *mut RcInner = NonNull::as_ptr(self.ptr); if is_dangling(ptr) { // If the pointer is dangling, we return the sentinel directly. This cannot be - // a valid payload address, as the payload is at least as aligned as RcBox (usize). + // a valid payload address, as the payload is at least as aligned as RcInner (usize). ptr as *const T } else { // SAFETY: if is_dangling returns false, then the pointer is dereferenceable. @@ -3206,14 +3210,14 @@ impl Weak { let ptr = if is_dangling(ptr) { // This is a dangling Weak. - ptr as *mut RcBox + ptr as *mut RcInner } else { // Otherwise, we're guaranteed the pointer came from a nondangling Weak. // SAFETY: data_offset is safe to call, as ptr references a real (potentially dropped) T. let offset = unsafe { data_offset(ptr) }; - // Thus, we reverse the offset to get the whole RcBox. + // Thus, we reverse the offset to get the whole RcInner. // SAFETY: the pointer originated from a Weak, so this offset is safe. - unsafe { ptr.byte_sub(offset) as *mut RcBox } + unsafe { ptr.byte_sub(offset) as *mut RcInner } }; // SAFETY: we now have recovered the original Weak pointer, so can create the Weak. @@ -3288,7 +3292,7 @@ impl Weak { } } - /// Returns `None` when the pointer is dangling and there is no allocated `RcBox`, + /// Returns `None` when the pointer is dangling and there is no allocated `RcInner`, /// (i.e., when this `Weak` was created by `Weak::new`). #[inline] fn inner(&self) -> Option> { @@ -3522,7 +3526,7 @@ trait RcInnerPtr { } } -impl RcInnerPtr for RcBox { +impl RcInnerPtr for RcInner { #[inline(always)] fn weak_ref(&self) -> &Cell { &self.weak @@ -3563,15 +3567,15 @@ impl AsRef for Rc { #[stable(feature = "pin", since = "1.33.0")] impl Unpin for Rc {} -/// Gets the offset within an `RcBox` for the payload behind a pointer. +/// Gets the offset within an `RcInner` for the payload behind a pointer. /// /// # Safety /// /// The pointer must point to (and have valid metadata for) a previously /// valid instance of T, but the T is allowed to be dropped. unsafe fn data_offset(ptr: *const T) -> usize { - // Align the unsized value to the end of the RcBox. - // Because RcBox is repr(C), it will always be the last field in memory. + // Align the unsized value to the end of the RcInner. + // Because RcInner is repr(C), it will always be the last field in memory. // SAFETY: since the only unsized types possible are slices, trait objects, // and extern types, the input safety requirement is currently enough to // satisfy the requirements of align_of_val_raw; this is an implementation @@ -3581,7 +3585,7 @@ unsafe fn data_offset(ptr: *const T) -> usize { #[inline] fn data_offset_align(align: usize) -> usize { - let layout = Layout::new::>(); + let layout = Layout::new::>(); layout.size() + layout.padding_needed_for(align) } @@ -3627,8 +3631,8 @@ pub struct UniqueRc< T: ?Sized, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, > { - ptr: NonNull>, - phantom: PhantomData>, + ptr: NonNull>, + phantom: PhantomData>, alloc: A, } @@ -3664,7 +3668,7 @@ impl UniqueRc { #[unstable(feature = "unique_rc_arc", issue = "112566")] pub fn new_in(value: T, alloc: A) -> Self { let (ptr, alloc) = Box::into_unique(Box::new_in( - RcBox { + RcInner { strong: Cell::new(0), // keep one weak reference so if all the weak pointers that are created are dropped // the UniqueRc still stays valid. @@ -3759,7 +3763,7 @@ unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for UniqueRc { } } -/// A unique owning pointer to a [`RcBox`] **that does not imply the contents are initialized,** +/// A unique owning pointer to a [`RcInner`] **that does not imply the contents are initialized,** /// but will deallocate it (without dropping the value) when dropped. /// /// This is a helper for [`Rc::make_mut()`] to ensure correct cleanup on panic. @@ -3767,21 +3771,21 @@ unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for UniqueRc { /// which `MaybeUninit` does not. #[cfg(not(no_global_oom_handling))] struct UniqueRcUninit { - ptr: NonNull>, + ptr: NonNull>, layout_for_value: Layout, alloc: Option, } #[cfg(not(no_global_oom_handling))] impl UniqueRcUninit { - /// Allocates a RcBox with layout suitable to contain `for_value` or a clone of it. + /// Allocates a RcInner with layout suitable to contain `for_value` or a clone of it. fn new(for_value: &T, alloc: A) -> UniqueRcUninit { let layout = Layout::for_value(for_value); let ptr = unsafe { Rc::allocate_for_layout( layout, |layout_for_rcbox| alloc.allocate(layout_for_rcbox), - |mem| mem.with_metadata_of(ptr::from_ref(for_value) as *const RcBox), + |mem| mem.with_metadata_of(ptr::from_ref(for_value) as *const RcInner), ) }; Self { ptr: NonNull::new(ptr).unwrap(), layout_for_value: layout, alloc: Some(alloc) } From 96224d80ce94fe461088d6e6338627130625923d Mon Sep 17 00:00:00 2001 From: Zalathar Date: Fri, 11 Oct 2024 11:16:12 +1100 Subject: [PATCH 183/357] compiletest: Remove the magic hacks for finding output with `lto=thin` This hack was intended to handle the case where `-Clto=thin` causes the compiler to emit multiple output files (when producing LLVM-IR or assembly). The hack only affects 4 tests, of which 3 are just meta-tests for the hack itself. The one remaining test that motivated the hack currently doesn't even need it! (`tests/codegen/issues/issue-81408-dllimport-thinlto-windows.rs`) --- src/tools/compiletest/src/runtest.rs | 56 +++------------------------- tests/assembly/thin-lto.rs | 7 ---- tests/codegen/thin-lto.rs | 6 --- tests/coverage/thin-lto.cov-map | 8 ---- tests/coverage/thin-lto.coverage | 4 -- tests/coverage/thin-lto.rs | 3 -- 6 files changed, 6 insertions(+), 78 deletions(-) delete mode 100644 tests/assembly/thin-lto.rs delete mode 100644 tests/codegen/thin-lto.rs delete mode 100644 tests/coverage/thin-lto.cov-map delete mode 100644 tests/coverage/thin-lto.coverage delete mode 100644 tests/coverage/thin-lto.rs diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 256b88758f0..5e75a74a64c 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1780,58 +1780,14 @@ impl<'test> TestCx<'test> { proc_res.fatal(None, || on_failure(*self)); } - fn get_output_file(&self, extension: &str) -> TargetLocation { - let thin_lto = self.props.compile_flags.iter().any(|s| s.ends_with("lto=thin")); - if thin_lto { - TargetLocation::ThisDirectory(self.output_base_dir()) - } else { - // This works with both `--emit asm` (as default output name for the assembly) - // and `ptx-linker` because the latter can write output at requested location. - let output_path = self.output_base_name().with_extension(extension); - - TargetLocation::ThisFile(output_path.clone()) - } - } - - fn get_filecheck_file(&self, extension: &str) -> PathBuf { - let thin_lto = self.props.compile_flags.iter().any(|s| s.ends_with("lto=thin")); - if thin_lto { - let name = self.testpaths.file.file_stem().unwrap().to_str().unwrap(); - let canonical_name = name.replace('-', "_"); - let mut output_file = None; - for entry in self.output_base_dir().read_dir().unwrap() { - if let Ok(entry) = entry { - let entry_path = entry.path(); - let entry_file = entry_path.file_name().unwrap().to_str().unwrap(); - if entry_file.starts_with(&format!("{}.{}", name, canonical_name)) - && entry_file.ends_with(extension) - { - assert!( - output_file.is_none(), - "thinlto doesn't support multiple cgu tests" - ); - output_file = Some(entry_file.to_string()); - } - } - } - if let Some(output_file) = output_file { - self.output_base_dir().join(output_file) - } else { - self.output_base_name().with_extension(extension) - } - } else { - self.output_base_name().with_extension(extension) - } - } - // codegen tests (using FileCheck) fn compile_test_and_save_ir(&self) -> (ProcRes, PathBuf) { - let output_file = self.get_output_file("ll"); + let output_path = self.output_base_name().with_extension("ll"); let input_file = &self.testpaths.file; let rustc = self.make_compile_args( input_file, - output_file, + TargetLocation::ThisFile(output_path.clone()), Emit::LlvmIr, AllowUnused::No, LinkToAux::Yes, @@ -1839,12 +1795,13 @@ impl<'test> TestCx<'test> { ); let proc_res = self.compose_and_run_compiler(rustc, None, self.testpaths); - let output_path = self.get_filecheck_file("ll"); (proc_res, output_path) } fn compile_test_and_save_assembly(&self) -> (ProcRes, PathBuf) { - let output_file = self.get_output_file("s"); + // This works with both `--emit asm` (as default output name for the assembly) + // and `ptx-linker` because the latter can write output at requested location. + let output_path = self.output_base_name().with_extension("s"); let input_file = &self.testpaths.file; let mut emit = Emit::None; @@ -1867,7 +1824,7 @@ impl<'test> TestCx<'test> { let rustc = self.make_compile_args( input_file, - output_file, + TargetLocation::ThisFile(output_path.clone()), emit, AllowUnused::No, LinkToAux::Yes, @@ -1875,7 +1832,6 @@ impl<'test> TestCx<'test> { ); let proc_res = self.compose_and_run_compiler(rustc, None, self.testpaths); - let output_path = self.get_filecheck_file("s"); (proc_res, output_path) } diff --git a/tests/assembly/thin-lto.rs b/tests/assembly/thin-lto.rs deleted file mode 100644 index 7b67b2de1e6..00000000000 --- a/tests/assembly/thin-lto.rs +++ /dev/null @@ -1,7 +0,0 @@ -//@ compile-flags: -O -C lto=thin -C prefer-dynamic=no -//@ only-x86_64-unknown-linux-gnu -//@ assembly-output: emit-asm - -// CHECK: main - -pub fn main() {} diff --git a/tests/codegen/thin-lto.rs b/tests/codegen/thin-lto.rs deleted file mode 100644 index 4339d20532e..00000000000 --- a/tests/codegen/thin-lto.rs +++ /dev/null @@ -1,6 +0,0 @@ -//@ compile-flags: -O -C lto=thin -C prefer-dynamic=no -//@ only-x86_64-unknown-linux-gnu - -// CHECK: main - -pub fn main() {} diff --git a/tests/coverage/thin-lto.cov-map b/tests/coverage/thin-lto.cov-map deleted file mode 100644 index 1f61b805f62..00000000000 --- a/tests/coverage/thin-lto.cov-map +++ /dev/null @@ -1,8 +0,0 @@ -Function name: thin_lto::main -Raw bytes (9): 0x[01, 01, 00, 01, 01, 03, 01, 00, 11] -Number of files: 1 -- file 0 => global file 1 -Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 3, 1) to (start + 0, 17) - diff --git a/tests/coverage/thin-lto.coverage b/tests/coverage/thin-lto.coverage deleted file mode 100644 index 5255aa7f5a4..00000000000 --- a/tests/coverage/thin-lto.coverage +++ /dev/null @@ -1,4 +0,0 @@ - LL| |//@ compile-flags: -O -C lto=thin -C prefer-dynamic=no - LL| | - LL| 1|pub fn main() {} - diff --git a/tests/coverage/thin-lto.rs b/tests/coverage/thin-lto.rs deleted file mode 100644 index 08843ea32ee..00000000000 --- a/tests/coverage/thin-lto.rs +++ /dev/null @@ -1,3 +0,0 @@ -//@ compile-flags: -O -C lto=thin -C prefer-dynamic=no - -pub fn main() {} From 4637630ed7e64a5a3f56ff8e4f5d2552f0df455b Mon Sep 17 00:00:00 2001 From: Zalathar Date: Fri, 11 Oct 2024 11:50:43 +1100 Subject: [PATCH 184/357] Simplify the choice of `--emit` mode for assembly tests --- src/tools/compiletest/src/runtest.rs | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 256b88758f0..f3e7137967e 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1847,23 +1847,14 @@ impl<'test> TestCx<'test> { let output_file = self.get_output_file("s"); let input_file = &self.testpaths.file; - let mut emit = Emit::None; - match self.props.assembly_output.as_ref().map(AsRef::as_ref) { - Some("emit-asm") => { - emit = Emit::Asm; - } - - Some("bpf-linker") => { - emit = Emit::LinkArgsAsm; - } - - Some("ptx-linker") => { - // No extra flags needed. - } - - Some(header) => self.fatal(&format!("unknown 'assembly-output' header: {header}")), - None => self.fatal("missing 'assembly-output' header"), - } + // Use the `//@ assembly-output:` directive to determine how to emit assembly. + let emit = match self.props.assembly_output.as_deref() { + Some("emit-asm") => Emit::Asm, + Some("bpf-linker") => Emit::LinkArgsAsm, + Some("ptx-linker") => Emit::None, // No extra flags needed. + Some(other) => self.fatal(&format!("unknown 'assembly-output' directive: {other}")), + None => self.fatal("missing 'assembly-output' directive"), + }; let rustc = self.make_compile_args( input_file, From 1b5c05433a9e69f89183d121ab8c906623c981b8 Mon Sep 17 00:00:00 2001 From: m Date: Thu, 10 Oct 2024 20:59:28 -0700 Subject: [PATCH 185/357] fix typo in rustdoc-json-types comment --- src/rustdoc-json-types/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs index b3707cf6157..c8b54728d90 100644 --- a/src/rustdoc-json-types/lib.rs +++ b/src/rustdoc-json-types/lib.rs @@ -677,7 +677,7 @@ pub struct FunctionHeader { /// on unwinding for more info. #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum Abi { - // We only have a concrete listing here for stable ABI's because their are so many + // We only have a concrete listing here for stable ABI's because there are so many // See rustc_ast_passes::feature_gate::PostExpansionVisitor::check_abi for the list /// The default ABI, but that can also be written explicitly with `extern "Rust"`. Rust, From 2c38ecfc9077000db7de14bf501fa5294eeecedd Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Thu, 10 Oct 2024 23:53:29 -0700 Subject: [PATCH 186/357] emscripten: Use the latest emsdk 3.1.68 This should fix our precompiled std being unsound in `std::fs` code. --- src/ci/docker/scripts/emscripten.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ci/docker/scripts/emscripten.sh b/src/ci/docker/scripts/emscripten.sh index 3f5e2c6ff1d..8b2b39ee162 100644 --- a/src/ci/docker/scripts/emscripten.sh +++ b/src/ci/docker/scripts/emscripten.sh @@ -20,5 +20,5 @@ exit 1 git clone https://github.com/emscripten-core/emsdk.git /emsdk-portable cd /emsdk-portable -hide_output ./emsdk install 2.0.5 -./emsdk activate 2.0.5 +hide_output ./emsdk install 3.1.68 +./emsdk activate 3.1.68 From 7e05da8d42a730c15983bbd56dfbf744b32032d4 Mon Sep 17 00:00:00 2001 From: Urgau Date: Thu, 10 Oct 2024 14:22:20 +0200 Subject: [PATCH 187/357] Consider outermost const-anon in non_local_def lint --- compiler/rustc_lint/src/non_local_def.rs | 90 ++++++++++++------- tests/ui/lint/non-local-defs/consts.rs | 7 ++ tests/ui/lint/non-local-defs/consts.stderr | 20 ++++- .../convoluted-locals-131474-with-mods.rs | 34 +++++++ .../convoluted-locals-131474.rs | 24 +++++ tests/ui/lint/non-local-defs/local.rs | 7 ++ 6 files changed, 148 insertions(+), 34 deletions(-) create mode 100644 tests/ui/lint/non-local-defs/convoluted-locals-131474-with-mods.rs create mode 100644 tests/ui/lint/non-local-defs/convoluted-locals-131474.rs diff --git a/compiler/rustc_lint/src/non_local_def.rs b/compiler/rustc_lint/src/non_local_def.rs index 56f930ea7f6..6fecddb3319 100644 --- a/compiler/rustc_lint/src/non_local_def.rs +++ b/compiler/rustc_lint/src/non_local_def.rs @@ -124,16 +124,6 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions { // If that's the case this means that this impl block declaration // is using local items and so we don't lint on it. - // We also ignore anon-const in item by including the anon-const - // parent as well. - let parent_parent = if parent_def_kind == DefKind::Const - && parent_opt_item_name == Some(kw::Underscore) - { - Some(cx.tcx.parent(parent)) - } else { - None - }; - // 1. We collect all the `hir::Path` from the `Self` type and `Trait` ref // of the `impl` definition let mut collector = PathCollector { paths: Vec::new() }; @@ -148,13 +138,33 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions { |p| matches!(p.res, Res::Def(def_kind, _) if def_kind != DefKind::TyParam), ); - // 2. We check if any of path reference a "local" parent and if that the case - // we bail out as asked by T-lang, even though this isn't correct from a - // type-system point of view, as inference exists and could still leak the impl. + // 1.9. We retrieve the parent def id of the impl item, ... + // + // ... modulo const-anons items, for enhanced compatibility with the ecosystem + // as that pattern is common with `serde`, `bevy`, ... + // + // For this example we want the `DefId` parent of the outermost const-anon items. + // ``` + // const _: () = { // the parent of this const-anon + // const _: () = { + // impl Foo {} + // }; + // }; + // ``` + let outermost_impl_parent = peel_parent_while(cx.tcx, parent, |tcx, did| { + tcx.def_kind(did) == DefKind::Const + && tcx.opt_item_name(did) == Some(kw::Underscore) + }); + + // 2. We check if any of the paths reference a the `impl`-parent. + // + // If that the case we bail out, as was asked by T-lang, even though this isn't + // correct from a type-system point of view, as inference exists and one-impl-rule + // make its so that we could still leak the impl. if collector .paths .iter() - .any(|path| path_has_local_parent(path, cx, parent, parent_parent)) + .any(|path| path_has_local_parent(path, cx, parent, outermost_impl_parent)) { return; } @@ -253,8 +263,8 @@ impl<'tcx> Visitor<'tcx> for PathCollector<'tcx> { } } -/// Given a path and a parent impl def id, this checks if the if parent resolution -/// def id correspond to the def id of the parent impl definition. +/// Given a path, this checks if the if the parent resolution def id corresponds to +/// the def id of the parent impl definition (the direct one and the outermost one). /// /// Given this path, we will look at the path (and ignore any generic args): /// @@ -267,32 +277,50 @@ fn path_has_local_parent( path: &Path<'_>, cx: &LateContext<'_>, impl_parent: DefId, - impl_parent_parent: Option, + outermost_impl_parent: Option, ) -> bool { path.res .opt_def_id() - .is_some_and(|did| did_has_local_parent(did, cx.tcx, impl_parent, impl_parent_parent)) + .is_some_and(|did| did_has_local_parent(did, cx.tcx, impl_parent, outermost_impl_parent)) } -/// Given a def id and a parent impl def id, this checks if the parent -/// def id (modulo modules) correspond to the def id of the parent impl definition. +/// Given a def id this checks if the parent def id (modulo modules) correspond to +/// the def id of the parent impl definition (the direct one and the outermost one). #[inline] fn did_has_local_parent( did: DefId, tcx: TyCtxt<'_>, impl_parent: DefId, - impl_parent_parent: Option, + outermost_impl_parent: Option, ) -> bool { - did.is_local() - && if let Some(did_parent) = tcx.opt_parent(did) { - did_parent == impl_parent - || Some(did_parent) == impl_parent_parent - || !did_parent.is_crate_root() - && tcx.def_kind(did_parent) == DefKind::Mod - && did_has_local_parent(did_parent, tcx, impl_parent, impl_parent_parent) - } else { - false - } + if !did.is_local() { + return false; + } + + let Some(parent_did) = tcx.opt_parent(did) else { + return false; + }; + + peel_parent_while(tcx, parent_did, |tcx, did| tcx.def_kind(did) == DefKind::Mod) + .map(|parent_did| parent_did == impl_parent || Some(parent_did) == outermost_impl_parent) + .unwrap_or(false) +} + +/// Given a `DefId` checks if it satisfies `f` if it does check with it's parent and continue +/// until it doesn't satisfies `f` and return the last `DefId` checked. +/// +/// In other word this method return the first `DefId` that doesn't satisfies `f`. +#[inline] +fn peel_parent_while( + tcx: TyCtxt<'_>, + mut did: DefId, + mut f: impl FnMut(TyCtxt<'_>, DefId) -> bool, +) -> Option { + while !did.is_crate_root() && f(tcx, did) { + did = tcx.opt_parent(did).filter(|parent_did| parent_did.is_local())?; + } + + Some(did) } /// Return for a given `Path` the span until the last args diff --git a/tests/ui/lint/non-local-defs/consts.rs b/tests/ui/lint/non-local-defs/consts.rs index d8a497e43e5..5b9dab3cfd3 100644 --- a/tests/ui/lint/non-local-defs/consts.rs +++ b/tests/ui/lint/non-local-defs/consts.rs @@ -63,6 +63,13 @@ fn main() { 1 }; + + const _: () = { + const _: () = { + impl Test {} + //~^ WARN non-local `impl` definition + }; + }; } trait Uto9 {} diff --git a/tests/ui/lint/non-local-defs/consts.stderr b/tests/ui/lint/non-local-defs/consts.stderr index 7f76056c021..4bf50bae5ea 100644 --- a/tests/ui/lint/non-local-defs/consts.stderr +++ b/tests/ui/lint/non-local-defs/consts.stderr @@ -95,7 +95,21 @@ LL | impl Test { = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item - --> $DIR/consts.rs:72:9 + --> $DIR/consts.rs:69:13 + | +LL | const _: () = { + | ----------- move the `impl` block outside of this constant `_` and up 3 bodies +LL | impl Test {} + | ^^^^^---- + | | + | `Test` is not local + | + = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` + = note: items in an anonymous const item (`const _: () = { ... }`) are treated as in the same scope as the anonymous const's declaration for the purpose of this lint + = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue + +warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item + --> $DIR/consts.rs:79:9 | LL | let _a = || { | -- move the `impl` block outside of this closure `` and up 2 bodies @@ -109,7 +123,7 @@ LL | impl Uto9 for Test {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item - --> $DIR/consts.rs:79:9 + --> $DIR/consts.rs:86:9 | LL | type A = [u32; { | ____________________- @@ -126,5 +140,5 @@ LL | | }]; = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue -warning: 8 warnings emitted +warning: 9 warnings emitted diff --git a/tests/ui/lint/non-local-defs/convoluted-locals-131474-with-mods.rs b/tests/ui/lint/non-local-defs/convoluted-locals-131474-with-mods.rs new file mode 100644 index 00000000000..cef0f0205e8 --- /dev/null +++ b/tests/ui/lint/non-local-defs/convoluted-locals-131474-with-mods.rs @@ -0,0 +1,34 @@ +// This test check that no matter the nesting of const-anons and modules +// we consider them as transparent. +// +// Similar to https://github.com/rust-lang/rust/issues/131474 + +//@ check-pass + +pub mod tmp { + pub mod tmp { + pub struct Test; + } +} + +const _: () = { + const _: () = { + const _: () = { + const _: () = { + impl tmp::tmp::Test {} + }; + }; + }; +}; + +const _: () = { + const _: () = { + mod tmp { + pub(super) struct InnerTest; + } + + impl tmp::InnerTest {} + }; +}; + +fn main() {} diff --git a/tests/ui/lint/non-local-defs/convoluted-locals-131474.rs b/tests/ui/lint/non-local-defs/convoluted-locals-131474.rs new file mode 100644 index 00000000000..4881723f13b --- /dev/null +++ b/tests/ui/lint/non-local-defs/convoluted-locals-131474.rs @@ -0,0 +1,24 @@ +// This test check that no matter the nesting of const-anons we consider +// them as transparent. +// +// https://github.com/rust-lang/rust/issues/131474 + +//@ check-pass + +pub struct Test; + +const _: () = { + const _: () = { + impl Test {} + }; +}; + +const _: () = { + const _: () = { + struct InnerTest; + + impl InnerTest {} + }; +}; + +fn main() {} diff --git a/tests/ui/lint/non-local-defs/local.rs b/tests/ui/lint/non-local-defs/local.rs index 166ee88c021..f7ecd68f59e 100644 --- a/tests/ui/lint/non-local-defs/local.rs +++ b/tests/ui/lint/non-local-defs/local.rs @@ -51,3 +51,10 @@ fn bitflags() { impl Flags {} }; } + +fn bitflags_internal() { + const _: () = { + struct InternalFlags; + impl InternalFlags {} + }; +} From 0a9c87b1f5d871a3f2cc44c274a7bc72a486e69d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonathan=20D=C3=B6nszelmann?= Date: Fri, 11 Oct 2024 00:56:56 +0200 Subject: [PATCH 188/357] rename RcBox in other places too --- compiler/rustc_codegen_ssa/src/mir/block.rs | 4 ++-- compiler/rustc_ty_utils/src/abi.rs | 6 +++--- library/alloc/src/sync.rs | 8 ++++---- library/core/src/cell.rs | 14 +++++++------- src/etc/lldb_providers.py | 4 ++-- src/etc/natvis/liballoc.natvis | 2 +- src/tools/miri/tests/fail/memleak_rc.stderr | 4 ++-- tests/debuginfo/strings-and-strs.rs | 3 +-- tests/ui/abi/compatibility.rs | 6 +++--- 9 files changed, 25 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index be9a6d9a90e..e3553dc03e1 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -992,10 +992,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { match op.val { Pair(data_ptr, meta) => { // In the case of Rc, we need to explicitly pass a - // *mut RcBox with a Scalar (not ScalarPair) ABI. This is a hack + // *mut RcInner with a Scalar (not ScalarPair) ABI. This is a hack // that is understood elsewhere in the compiler as a method on // `dyn Trait`. - // To get a `*mut RcBox`, we just keep unwrapping newtypes until + // To get a `*mut RcInner`, we just keep unwrapping newtypes until // we get a value of a built-in pointer type. // // This is also relevant for `Pin<&mut Self>`, where we need to peel the diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index deda16b76b5..7354ea5fb6a 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -822,10 +822,10 @@ fn make_thin_self_ptr<'tcx>( _ => bug!("receiver type has unsupported layout: {:?}", layout), } - // In the case of Rc, we need to explicitly pass a *mut RcBox + // In the case of Rc, we need to explicitly pass a *mut RcInner // with a Scalar (not ScalarPair) ABI. This is a hack that is understood // elsewhere in the compiler as a method on a `dyn Trait`. - // To get the type `*mut RcBox`, we just keep unwrapping newtypes until we + // To get the type `*mut RcInner`, we just keep unwrapping newtypes until we // get a built-in pointer type let mut wide_pointer_layout = layout; while !wide_pointer_layout.ty.is_unsafe_ptr() && !wide_pointer_layout.ty.is_ref() { @@ -838,7 +838,7 @@ fn make_thin_self_ptr<'tcx>( wide_pointer_layout.ty }; - // we now have a type like `*mut RcBox` + // we now have a type like `*mut RcInner` // change its layout to that of `*mut ()`, a thin pointer, but keep the same type // this is understood as a special case elsewhere in the compiler let unit_ptr_ty = Ty::new_mut_ptr(tcx, tcx.types.unit); diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 5d099a49854..4632f995b82 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -319,7 +319,7 @@ pub struct Weak< // but it is not necessarily a valid pointer. // `Weak::new` sets this to `usize::MAX` so that it doesn’t need // to allocate space on the heap. That's not a value a real pointer - // will ever have because RcBox has alignment at least 2. + // will ever have because RcInner has alignment at least 2. // This is only possible when `T: Sized`; unsized `T` never dangle. ptr: NonNull>, alloc: A, @@ -1581,7 +1581,7 @@ impl Arc { pub fn as_ptr(this: &Self) -> *const T { let ptr: *mut ArcInner = NonNull::as_ptr(this.ptr); - // SAFETY: This cannot go through Deref::deref or RcBoxPtr::inner because + // SAFETY: This cannot go through Deref::deref or RcInnerPtr::inner because // this is required to retain raw/mut provenance such that e.g. `get_mut` can // write through the pointer after the Rc is recovered through `from_raw`. unsafe { &raw mut (*ptr).data } @@ -2936,7 +2936,7 @@ impl Weak { // Otherwise, we're guaranteed the pointer came from a nondangling Weak. // SAFETY: data_offset is safe to call, as ptr references a real (potentially dropped) T. let offset = unsafe { data_offset(ptr) }; - // Thus, we reverse the offset to get the whole RcBox. + // Thus, we reverse the offset to get the whole RcInner. // SAFETY: the pointer originated from a Weak, so this offset is safe. unsafe { ptr.byte_sub(offset) as *mut ArcInner } }; @@ -3861,7 +3861,7 @@ impl Unpin for Arc {} /// valid instance of T, but the T is allowed to be dropped. unsafe fn data_offset(ptr: *const T) -> usize { // Align the unsized value to the end of the ArcInner. - // Because RcBox is repr(C), it will always be the last field in memory. + // Because RcInner is repr(C), it will always be the last field in memory. // SAFETY: since the only unsized types possible are slices, trait objects, // and extern types, the input safety requirement is currently enough to // satisfy the requirements of align_of_val_raw; this is an implementation diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index 8ccd1a44ff1..513b9cbcefc 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -193,11 +193,11 @@ //! use std::marker::PhantomData; //! //! struct Rc { -//! ptr: NonNull>, -//! phantom: PhantomData>, +//! ptr: NonNull>, +//! phantom: PhantomData>, //! } //! -//! struct RcBox { +//! struct RcInner { //! strong: Cell, //! refcount: Cell, //! value: T, @@ -213,9 +213,9 @@ //! } //! } //! -//! trait RcBoxPtr { +//! trait RcInnerPtr { //! -//! fn inner(&self) -> &RcBox; +//! fn inner(&self) -> &RcInner; //! //! fn strong(&self) -> usize { //! self.inner().strong.get() @@ -230,8 +230,8 @@ //! } //! } //! -//! impl RcBoxPtr for Rc { -//! fn inner(&self) -> &RcBox { +//! impl RcInnerPtr for Rc { +//! fn inner(&self) -> &RcInner { //! unsafe { //! self.ptr.as_ref() //! } diff --git a/src/etc/lldb_providers.py b/src/etc/lldb_providers.py index 8750d7682d1..bace228454e 100644 --- a/src/etc/lldb_providers.py +++ b/src/etc/lldb_providers.py @@ -670,11 +670,11 @@ def StdRcSummaryProvider(valobj, dict): class StdRcSyntheticProvider: """Pretty-printer for alloc::rc::Rc and alloc::sync::Arc - struct Rc { ptr: NonNull>, ... } + struct Rc { ptr: NonNull>, ... } rust 1.31.1: struct NonNull { pointer: NonZero<*const T> } rust 1.33.0: struct NonNull { pointer: *const T } struct NonZero(T) - struct RcBox { strong: Cell, weak: Cell, value: T } + struct RcInner { strong: Cell, weak: Cell, value: T } struct Cell { value: UnsafeCell } struct UnsafeCell { value: T } diff --git a/src/etc/natvis/liballoc.natvis b/src/etc/natvis/liballoc.natvis index 49d82dfad82..1528a8b1226 100644 --- a/src/etc/natvis/liballoc.natvis +++ b/src/etc/natvis/liballoc.natvis @@ -95,7 +95,7 @@ ptr.pointer.data_ptr->weak ptr.pointer.length - + ($T1*)(((size_t*)ptr.pointer.data_ptr) + 2) diff --git a/src/tools/miri/tests/fail/memleak_rc.stderr b/src/tools/miri/tests/fail/memleak_rc.stderr index 820e10743bc..df12eeed6ac 100644 --- a/src/tools/miri/tests/fail/memleak_rc.stderr +++ b/src/tools/miri/tests/fail/memleak_rc.stderr @@ -1,8 +1,8 @@ error: memory leaked: ALLOC (Rust heap, SIZE, ALIGN), allocated here: --> RUSTLIB/alloc/src/rc.rs:LL:CC | -LL | Box::leak(Box::new(RcBox { strong: Cell::new(1), weak: Cell::new(1), value })) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | Box::leak(Box::new(RcInner { strong: Cell::new(1), weak: Cell::new(1), value })) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: BACKTRACE: = note: inside `std::rc::Rc::>>::new` at RUSTLIB/alloc/src/rc.rs:LL:CC diff --git a/tests/debuginfo/strings-and-strs.rs b/tests/debuginfo/strings-and-strs.rs index b7ee3312d13..3d6589db34b 100644 --- a/tests/debuginfo/strings-and-strs.rs +++ b/tests/debuginfo/strings-and-strs.rs @@ -19,8 +19,7 @@ // gdb-check:$4 = ("Hello", "World") // gdb-command:print str_in_rc -// gdb-check:$5 = alloc::rc::Rc<&str, alloc::alloc::Global> {ptr: core::ptr::non_null::NonNull> {pointer: 0x[...]}, phantom: core::marker::PhantomData>, alloc: alloc::alloc::Global} - +// gdb-check:$5 = alloc::rc::Rc<&str, alloc::alloc::Global> {ptr: core::ptr::non_null::NonNull> {pointer: 0x[...]}, phantom: core::marker::PhantomData>, alloc: alloc::alloc::Global} // === LLDB TESTS ================================================================================== // lldb-command:run diff --git a/tests/ui/abi/compatibility.rs b/tests/ui/abi/compatibility.rs index b439a4bcf86..28c8063a923 100644 --- a/tests/ui/abi/compatibility.rs +++ b/tests/ui/abi/compatibility.rs @@ -160,14 +160,14 @@ mod prelude { pub struct Box(Unique, A); #[repr(C)] - struct RcBox { + struct RcInner { strong: UnsafeCell, weak: UnsafeCell, value: T, } pub struct Rc { - ptr: NonNull>, - phantom: PhantomData>, + ptr: NonNull>, + phantom: PhantomData>, alloc: A, } From 599f95ecc26fb68cccbf79780dd1825a4cf73eb0 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 8 Oct 2024 13:13:05 +1100 Subject: [PATCH 189/357] coverage: Include the highest counter ID seen in `.cov-map` dumps When making changes that have a large impact on coverage counter creation, this makes it easier to see whether the number of physical counters has changed. (The highest counter ID seen in coverage maps is not necessarily the same as the number of physical counters actually used by the instrumented code, but it's the best approximation we can get from looking only at the coverage maps, and it should be reasonably accurate in most cases.) --- src/tools/coverage-dump/src/covfun.rs | 42 +++++++++++++++++++ tests/coverage/abort.cov-map | 2 + tests/coverage/assert-ne.cov-map | 1 + tests/coverage/assert.cov-map | 2 + tests/coverage/assert_not.cov-map | 1 + tests/coverage/async.cov-map | 25 +++++++++++ tests/coverage/async2.cov-map | 6 +++ tests/coverage/async_block.cov-map | 2 + tests/coverage/attr/impl.cov-map | 3 ++ tests/coverage/attr/module.cov-map | 3 ++ tests/coverage/attr/nested.cov-map | 2 + tests/coverage/attr/off-on-sandwich.cov-map | 3 ++ tests/coverage/await_ready.cov-map | 2 + tests/coverage/bad_counter_ids.cov-map | 8 ++++ tests/coverage/bench.cov-map | 1 + tests/coverage/branch/generics.cov-map | 3 ++ tests/coverage/branch/guard.cov-map | 1 + tests/coverage/branch/if-let.cov-map | 2 + tests/coverage/branch/if.cov-map | 4 ++ tests/coverage/branch/lazy-boolean.cov-map | 4 ++ tests/coverage/branch/let-else.cov-map | 1 + tests/coverage/branch/match-arms.cov-map | 3 ++ tests/coverage/branch/match-trivial.cov-map | 2 + tests/coverage/branch/no-mir-spans.cov-map | 4 ++ tests/coverage/branch/while.cov-map | 4 ++ tests/coverage/closure.cov-map | 21 ++++++++++ tests/coverage/closure_bug.cov-map | 5 +++ tests/coverage/closure_macro.cov-map | 3 ++ tests/coverage/closure_macro_async.cov-map | 4 ++ tests/coverage/closure_unit_return.cov-map | 4 ++ tests/coverage/condition/conditions.cov-map | 7 ++++ tests/coverage/conditions.cov-map | 1 + tests/coverage/continue.cov-map | 1 + tests/coverage/coroutine.cov-map | 3 ++ tests/coverage/coverage_attr_closure.cov-map | 4 ++ tests/coverage/dead_code.cov-map | 3 ++ tests/coverage/drop_trait.cov-map | 2 + tests/coverage/fn_sig_into_try.cov-map | 4 ++ tests/coverage/generics.cov-map | 5 +++ tests/coverage/holes.cov-map | 5 +++ tests/coverage/if.cov-map | 1 + tests/coverage/if_else.cov-map | 1 + tests/coverage/if_not.cov-map | 1 + tests/coverage/ignore_run.cov-map | 1 + tests/coverage/inline-dead.cov-map | 4 ++ tests/coverage/inline.cov-map | 7 ++++ tests/coverage/inner_items.cov-map | 4 ++ tests/coverage/issue-83601.cov-map | 1 + tests/coverage/issue-84561.cov-map | 6 +++ tests/coverage/issue-85461.cov-map | 1 + tests/coverage/issue-93054.cov-map | 3 ++ tests/coverage/lazy_boolean.cov-map | 1 + tests/coverage/let_else_loop.cov-map | 3 ++ tests/coverage/long_and_wide.cov-map | 4 ++ tests/coverage/loop-break.cov-map | 1 + tests/coverage/loop_break_value.cov-map | 1 + tests/coverage/loops_branches.cov-map | 3 ++ tests/coverage/macro_in_closure.cov-map | 2 + tests/coverage/macro_name_span.cov-map | 2 + tests/coverage/match_or_pattern.cov-map | 1 + tests/coverage/mcdc/condition-limit.cov-map | 1 + tests/coverage/mcdc/if.cov-map | 7 ++++ .../coverage/mcdc/inlined_expressions.cov-map | 1 + tests/coverage/mcdc/nested_if.cov-map | 4 ++ tests/coverage/mcdc/non_control_flow.cov-map | 7 ++++ tests/coverage/nested_loops.cov-map | 1 + tests/coverage/no_cov_crate.cov-map | 7 ++++ tests/coverage/no_spans.cov-map | 2 + tests/coverage/no_spans_if_not.cov-map | 2 + tests/coverage/overflow.cov-map | 2 + tests/coverage/panic_unwind.cov-map | 2 + tests/coverage/partial_eq.cov-map | 2 + tests/coverage/simple_loop.cov-map | 1 + tests/coverage/simple_match.cov-map | 1 + tests/coverage/sort_groups.cov-map | 6 +++ tests/coverage/test_harness.cov-map | 2 + tests/coverage/tight_inf_loop.cov-map | 1 + tests/coverage/trivial.cov-map | 1 + tests/coverage/try_error_result.cov-map | 6 +++ tests/coverage/unicode.cov-map | 3 ++ tests/coverage/unreachable.cov-map | 3 ++ tests/coverage/unused.cov-map | 7 ++++ tests/coverage/unused_mod.cov-map | 2 + tests/coverage/uses_crate.cov-map | 5 +++ tests/coverage/uses_inline_crate.cov-map | 6 +++ tests/coverage/while.cov-map | 1 + tests/coverage/while_early_ret.cov-map | 1 + tests/coverage/yield.cov-map | 3 ++ 88 files changed, 338 insertions(+) diff --git a/src/tools/coverage-dump/src/covfun.rs b/src/tools/coverage-dump/src/covfun.rs index c779dd0583c..33fac3edccd 100644 --- a/src/tools/coverage-dump/src/covfun.rs +++ b/src/tools/coverage-dump/src/covfun.rs @@ -56,6 +56,7 @@ pub(crate) fn dump_covfun_mappings( expression_resolver.push_operands(lhs, rhs); } + let mut max_counter = None; for i in 0..num_files { let num_mappings = parser.read_uleb128_u32()?; println!("Number of file {i} mappings: {num_mappings}"); @@ -63,6 +64,11 @@ pub(crate) fn dump_covfun_mappings( for _ in 0..num_mappings { let (kind, region) = parser.read_mapping_kind_and_region()?; println!("- {kind:?} at {region:?}"); + kind.for_each_term(|term| { + if let CovTerm::Counter(n) = term { + max_counter = max_counter.max(Some(n)); + } + }); match kind { // Also print expression mappings in resolved form. @@ -83,6 +89,16 @@ pub(crate) fn dump_covfun_mappings( } parser.ensure_empty()?; + + // Printing the highest counter ID seen in the functions mappings makes + // it easier to determine whether a change to coverage instrumentation + // has increased or decreased the number of physical counters needed. + // (It's possible for the generated code to have more counters that + // aren't used by any mappings, but that should hopefully be rare.) + println!("Highest counter ID seen: {}", match max_counter { + Some(id) => format!("c{id}"), + None => "(none)".to_owned(), + }); println!(); } Ok(()) @@ -271,6 +287,32 @@ enum MappingKind { }, } +impl MappingKind { + fn for_each_term(&self, mut callback: impl FnMut(CovTerm)) { + match *self { + Self::Code(term) => callback(term), + Self::Gap(term) => callback(term), + Self::Expansion(_id) => {} + Self::Skip => {} + Self::Branch { r#true, r#false } => { + callback(r#true); + callback(r#false); + } + Self::MCDCBranch { + r#true, + r#false, + condition_id: _, + true_next_id: _, + false_next_id: _, + } => { + callback(r#true); + callback(r#false); + } + Self::MCDCDecision { bitmap_idx: _, conditions_num: _ } => {} + } + } +} + struct MappingRegion { /// Offset of this region's start line, relative to the *start line* of /// the *previous mapping* (or 0). Line numbers are 1-based. diff --git a/tests/coverage/abort.cov-map b/tests/coverage/abort.cov-map index 15156ec9811..06dce43c3ca 100644 --- a/tests/coverage/abort.cov-map +++ b/tests/coverage/abort.cov-map @@ -34,6 +34,7 @@ Number of file 0 mappings: 13 - Code(Expression(9, Add)) at (prev + 1, 9) to (start + 0, 23) = (c1 + c2) - Code(Counter(3)) at (prev + 2, 5) to (start + 1, 2) +Highest counter ID seen: c5 Function name: abort::might_abort Raw bytes (21): 0x[01, 01, 01, 01, 05, 03, 01, 03, 01, 01, 14, 05, 02, 09, 01, 24, 02, 02, 0c, 03, 02] @@ -46,4 +47,5 @@ Number of file 0 mappings: 3 - Code(Counter(1)) at (prev + 2, 9) to (start + 1, 36) - Code(Expression(0, Sub)) at (prev + 2, 12) to (start + 3, 2) = (c0 - c1) +Highest counter ID seen: c1 diff --git a/tests/coverage/assert-ne.cov-map b/tests/coverage/assert-ne.cov-map index 6d9906fd7f5..906abcd3c2e 100644 --- a/tests/coverage/assert-ne.cov-map +++ b/tests/coverage/assert-ne.cov-map @@ -10,4 +10,5 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 2, 13) to (start + 0, 19) = (c0 - c1) - Code(Counter(2)) at (prev + 3, 5) to (start + 1, 2) +Highest counter ID seen: c2 diff --git a/tests/coverage/assert.cov-map b/tests/coverage/assert.cov-map index dd413123de7..018fcc2c3db 100644 --- a/tests/coverage/assert.cov-map +++ b/tests/coverage/assert.cov-map @@ -25,6 +25,7 @@ Number of file 0 mappings: 9 - Code(Expression(6, Add)) at (prev + 1, 9) to (start + 0, 23) = (c1 + (c2 + c3)) - Code(Counter(4)) at (prev + 2, 5) to (start + 1, 2) +Highest counter ID seen: c4 Function name: assert::might_fail_assert Raw bytes (21): 0x[01, 01, 01, 01, 05, 03, 01, 04, 01, 02, 0f, 02, 02, 25, 00, 3d, 05, 01, 01, 00, 02] @@ -37,4 +38,5 @@ Number of file 0 mappings: 3 - Code(Expression(0, Sub)) at (prev + 2, 37) to (start + 0, 61) = (c0 - c1) - Code(Counter(1)) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: c1 diff --git a/tests/coverage/assert_not.cov-map b/tests/coverage/assert_not.cov-map index 788bc5dbf58..401dd6450e9 100644 --- a/tests/coverage/assert_not.cov-map +++ b/tests/coverage/assert_not.cov-map @@ -13,4 +13,5 @@ Number of file 0 mappings: 5 - Code(Counter(3)) at (prev + 1, 5) to (start + 0, 22) - Code(Expression(1, Sub)) at (prev + 1, 1) to (start + 0, 2) = (c3 - Zero) +Highest counter ID seen: c3 diff --git a/tests/coverage/async.cov-map b/tests/coverage/async.cov-map index 43b497a1d3f..9a67cefcf98 100644 --- a/tests/coverage/async.cov-map +++ b/tests/coverage/async.cov-map @@ -5,6 +5,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 12, 1) to (start + 0, 25) +Highest counter ID seen: c0 Function name: async::c::{closure#0} Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 0c, 19, 01, 0e, 05, 02, 09, 00, 0a, 02, 02, 09, 00, 0a, 01, 02, 01, 00, 02] @@ -18,6 +19,7 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 10) = (c0 - c1) - Code(Counter(0)) at (prev + 2, 1) to (start + 0, 2) +Highest counter ID seen: c1 Function name: async::d Raw bytes (9): 0x[01, 01, 00, 01, 01, 14, 01, 00, 14] @@ -26,6 +28,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 20, 1) to (start + 0, 20) +Highest counter ID seen: c0 Function name: async::d::{closure#0} Raw bytes (9): 0x[01, 01, 00, 01, 01, 14, 14, 00, 19] @@ -34,6 +37,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 20, 20) to (start + 0, 25) +Highest counter ID seen: c0 Function name: async::e (unused) Raw bytes (9): 0x[01, 01, 00, 01, 00, 16, 01, 00, 14] @@ -42,6 +46,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 22, 1) to (start + 0, 20) +Highest counter ID seen: (none) Function name: async::e::{closure#0} (unused) Raw bytes (9): 0x[01, 01, 00, 01, 00, 16, 14, 00, 19] @@ -50,6 +55,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 22, 20) to (start + 0, 25) +Highest counter ID seen: (none) Function name: async::f Raw bytes (9): 0x[01, 01, 00, 01, 01, 18, 01, 00, 14] @@ -58,6 +64,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 24, 1) to (start + 0, 20) +Highest counter ID seen: c0 Function name: async::f::{closure#0} Raw bytes (9): 0x[01, 01, 00, 01, 01, 18, 14, 00, 19] @@ -66,6 +73,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 24, 20) to (start + 0, 25) +Highest counter ID seen: c0 Function name: async::foo (unused) Raw bytes (9): 0x[01, 01, 00, 01, 00, 1a, 01, 00, 1e] @@ -74,6 +82,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 26, 1) to (start + 0, 30) +Highest counter ID seen: (none) Function name: async::foo::{closure#0} (unused) Raw bytes (9): 0x[01, 01, 00, 01, 00, 1a, 1e, 00, 2d] @@ -82,6 +91,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 26, 30) to (start + 0, 45) +Highest counter ID seen: (none) Function name: async::g Raw bytes (9): 0x[01, 01, 00, 01, 01, 1c, 01, 00, 17] @@ -90,6 +100,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 28, 1) to (start + 0, 23) +Highest counter ID seen: c0 Function name: async::g::{closure#0} (unused) Raw bytes (59): 0x[01, 01, 00, 0b, 00, 1c, 17, 01, 0c, 00, 02, 09, 00, 0a, 00, 00, 0e, 00, 17, 00, 00, 1b, 00, 1c, 00, 00, 20, 00, 22, 00, 01, 09, 00, 0a, 00, 00, 0e, 00, 17, 00, 00, 1b, 00, 1c, 00, 00, 20, 00, 22, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02] @@ -108,6 +119,7 @@ Number of file 0 mappings: 11 - Code(Zero) at (prev + 0, 32) to (start + 0, 34) - Code(Zero) at (prev + 1, 14) to (start + 0, 16) - Code(Zero) at (prev + 2, 1) to (start + 0, 2) +Highest counter ID seen: (none) Function name: async::h Raw bytes (9): 0x[01, 01, 00, 01, 01, 24, 01, 00, 16] @@ -116,6 +128,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 36, 1) to (start + 0, 22) +Highest counter ID seen: c0 Function name: async::h::{closure#0} (unused) Raw bytes (39): 0x[01, 01, 00, 07, 00, 24, 16, 03, 0c, 00, 04, 09, 00, 0a, 00, 00, 0e, 00, 19, 00, 00, 1a, 00, 1b, 00, 00, 20, 00, 22, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02] @@ -130,6 +143,7 @@ Number of file 0 mappings: 7 - Code(Zero) at (prev + 0, 32) to (start + 0, 34) - Code(Zero) at (prev + 1, 14) to (start + 0, 16) - Code(Zero) at (prev + 2, 1) to (start + 0, 2) +Highest counter ID seen: (none) Function name: async::i Raw bytes (9): 0x[01, 01, 00, 01, 01, 2d, 01, 00, 13] @@ -138,6 +152,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 45, 1) to (start + 0, 19) +Highest counter ID seen: c0 Function name: async::i::{closure#0} Raw bytes (63): 0x[01, 01, 02, 07, 19, 11, 15, 0b, 01, 2d, 13, 04, 0c, 09, 05, 09, 00, 0a, 01, 00, 0e, 00, 18, 05, 00, 1c, 00, 21, 09, 00, 27, 00, 30, 15, 01, 09, 00, 0a, 0d, 00, 0e, 00, 17, 1d, 00, 1b, 00, 20, 15, 00, 24, 00, 26, 19, 01, 0e, 00, 10, 03, 02, 01, 00, 02] @@ -159,6 +174,7 @@ Number of file 0 mappings: 11 - Code(Counter(6)) at (prev + 1, 14) to (start + 0, 16) - Code(Expression(0, Add)) at (prev + 2, 1) to (start + 0, 2) = ((c4 + c5) + c6) +Highest counter ID seen: c7 Function name: async::j Raw bytes (58): 0x[01, 01, 02, 07, 0d, 05, 09, 0a, 01, 38, 01, 00, 0d, 01, 0b, 0b, 00, 0c, 05, 01, 09, 00, 0a, 01, 00, 0e, 00, 1b, 05, 00, 1f, 00, 27, 09, 01, 09, 00, 0a, 11, 00, 0e, 00, 1a, 09, 00, 1e, 00, 20, 0d, 01, 0e, 00, 10, 03, 02, 01, 00, 02] @@ -179,6 +195,7 @@ Number of file 0 mappings: 10 - Code(Counter(3)) at (prev + 1, 14) to (start + 0, 16) - Code(Expression(0, Add)) at (prev + 2, 1) to (start + 0, 2) = ((c1 + c2) + c3) +Highest counter ID seen: c4 Function name: async::j::c Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 3a, 05, 01, 12, 05, 02, 0d, 00, 0e, 02, 02, 0d, 00, 0e, 01, 02, 05, 00, 06] @@ -192,6 +209,7 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 2, 13) to (start + 0, 14) = (c0 - c1) - Code(Counter(0)) at (prev + 2, 5) to (start + 0, 6) +Highest counter ID seen: c1 Function name: async::j::d Raw bytes (9): 0x[01, 01, 00, 01, 01, 41, 05, 00, 17] @@ -200,6 +218,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 65, 5) to (start + 0, 23) +Highest counter ID seen: c0 Function name: async::j::f Raw bytes (9): 0x[01, 01, 00, 01, 01, 42, 05, 00, 17] @@ -208,6 +227,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 66, 5) to (start + 0, 23) +Highest counter ID seen: c0 Function name: async::k (unused) Raw bytes (29): 0x[01, 01, 00, 05, 00, 4a, 01, 01, 0c, 00, 02, 0e, 00, 10, 00, 01, 0e, 00, 10, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02] @@ -220,6 +240,7 @@ Number of file 0 mappings: 5 - Code(Zero) at (prev + 1, 14) to (start + 0, 16) - Code(Zero) at (prev + 1, 14) to (start + 0, 16) - Code(Zero) at (prev + 2, 1) to (start + 0, 2) +Highest counter ID seen: (none) Function name: async::l Raw bytes (37): 0x[01, 01, 04, 01, 07, 05, 09, 0f, 02, 09, 05, 05, 01, 52, 01, 01, 0c, 02, 02, 0e, 00, 10, 05, 01, 0e, 00, 10, 09, 01, 0e, 00, 10, 0b, 02, 01, 00, 02] @@ -238,6 +259,7 @@ Number of file 0 mappings: 5 - Code(Counter(2)) at (prev + 1, 14) to (start + 0, 16) - Code(Expression(2, Add)) at (prev + 2, 1) to (start + 0, 2) = ((c2 + c1) + (c0 - (c1 + c2))) +Highest counter ID seen: c2 Function name: async::m Raw bytes (9): 0x[01, 01, 00, 01, 01, 5a, 01, 00, 19] @@ -246,6 +268,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 90, 1) to (start + 0, 25) +Highest counter ID seen: c0 Function name: async::m::{closure#0} (unused) Raw bytes (9): 0x[01, 01, 00, 01, 00, 5a, 19, 00, 22] @@ -254,6 +277,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 90, 25) to (start + 0, 34) +Highest counter ID seen: (none) Function name: async::main Raw bytes (9): 0x[01, 01, 00, 01, 01, 5c, 01, 08, 02] @@ -262,4 +286,5 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 92, 1) to (start + 8, 2) +Highest counter ID seen: c0 diff --git a/tests/coverage/async2.cov-map b/tests/coverage/async2.cov-map index 3816401ac63..ed61e91efc2 100644 --- a/tests/coverage/async2.cov-map +++ b/tests/coverage/async2.cov-map @@ -5,6 +5,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 16, 1) to (start + 0, 23) +Highest counter ID seen: c0 Function name: async2::async_func::{closure#0} Raw bytes (24): 0x[01, 01, 00, 04, 01, 10, 17, 03, 09, 05, 03, 0a, 02, 06, 00, 02, 06, 00, 07, 01, 01, 01, 00, 02] @@ -16,6 +17,7 @@ Number of file 0 mappings: 4 - Code(Counter(1)) at (prev + 3, 10) to (start + 2, 6) - Code(Zero) at (prev + 2, 6) to (start + 0, 7) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: c1 Function name: async2::async_func_just_println Raw bytes (9): 0x[01, 01, 00, 01, 01, 18, 01, 00, 24] @@ -24,6 +26,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 24, 1) to (start + 0, 36) +Highest counter ID seen: c0 Function name: async2::async_func_just_println::{closure#0} Raw bytes (9): 0x[01, 01, 00, 01, 01, 18, 24, 02, 02] @@ -32,6 +35,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 24, 36) to (start + 2, 2) +Highest counter ID seen: c0 Function name: async2::main Raw bytes (9): 0x[01, 01, 00, 01, 01, 1c, 01, 07, 02] @@ -40,6 +44,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 28, 1) to (start + 7, 2) +Highest counter ID seen: c0 Function name: async2::non_async_func Raw bytes (24): 0x[01, 01, 00, 04, 01, 08, 01, 03, 09, 05, 03, 0a, 02, 06, 00, 02, 06, 00, 07, 01, 01, 01, 00, 02] @@ -51,4 +56,5 @@ Number of file 0 mappings: 4 - Code(Counter(1)) at (prev + 3, 10) to (start + 2, 6) - Code(Zero) at (prev + 2, 6) to (start + 0, 7) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: c1 diff --git a/tests/coverage/async_block.cov-map b/tests/coverage/async_block.cov-map index 65f3d821f6e..e3309bd51b4 100644 --- a/tests/coverage/async_block.cov-map +++ b/tests/coverage/async_block.cov-map @@ -12,6 +12,7 @@ Number of file 0 mappings: 6 - Code(Counter(1)) at (prev + 0, 20) to (start + 1, 22) - Code(Counter(1)) at (prev + 7, 10) to (start + 2, 6) - Code(Counter(0)) at (prev + 3, 1) to (start + 0, 2) +Highest counter ID seen: c1 Function name: async_block::main::{closure#0} Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 0a, 1c, 01, 17, 05, 01, 18, 02, 0e, 02, 02, 14, 02, 0e, 01, 03, 09, 00, 0a] @@ -25,4 +26,5 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 2, 20) to (start + 2, 14) = (c0 - c1) - Code(Counter(0)) at (prev + 3, 9) to (start + 0, 10) +Highest counter ID seen: c1 diff --git a/tests/coverage/attr/impl.cov-map b/tests/coverage/attr/impl.cov-map index 9b0deed8b64..4d068c290f4 100644 --- a/tests/coverage/attr/impl.cov-map +++ b/tests/coverage/attr/impl.cov-map @@ -5,6 +5,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 14, 5) to (start + 0, 19) +Highest counter ID seen: (none) Function name: ::on_inherit (unused) Raw bytes (9): 0x[01, 01, 00, 01, 00, 16, 05, 00, 17] @@ -13,6 +14,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 22, 5) to (start + 0, 23) +Highest counter ID seen: (none) Function name: ::on_on (unused) Raw bytes (9): 0x[01, 01, 00, 01, 00, 19, 05, 00, 12] @@ -21,4 +23,5 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 25, 5) to (start + 0, 18) +Highest counter ID seen: (none) diff --git a/tests/coverage/attr/module.cov-map b/tests/coverage/attr/module.cov-map index 34898eb4ca8..b318ac85a6c 100644 --- a/tests/coverage/attr/module.cov-map +++ b/tests/coverage/attr/module.cov-map @@ -5,6 +5,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 12, 5) to (start + 0, 15) +Highest counter ID seen: (none) Function name: module::on::inherit (unused) Raw bytes (9): 0x[01, 01, 00, 01, 00, 14, 05, 00, 14] @@ -13,6 +14,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 20, 5) to (start + 0, 20) +Highest counter ID seen: (none) Function name: module::on::on (unused) Raw bytes (9): 0x[01, 01, 00, 01, 00, 17, 05, 00, 0f] @@ -21,4 +23,5 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 23, 5) to (start + 0, 15) +Highest counter ID seen: (none) diff --git a/tests/coverage/attr/nested.cov-map b/tests/coverage/attr/nested.cov-map index 466aec8956e..2bd95325373 100644 --- a/tests/coverage/attr/nested.cov-map +++ b/tests/coverage/attr/nested.cov-map @@ -6,6 +6,7 @@ Number of expressions: 0 Number of file 0 mappings: 2 - Code(Counter(0)) at (prev + 63, 1) to (start + 1, 15) - Code(Counter(0)) at (prev + 11, 5) to (start + 1, 2) +Highest counter ID seen: c0 Function name: nested::closure_tail Raw bytes (14): 0x[01, 01, 00, 02, 01, 4e, 01, 01, 0f, 01, 11, 05, 01, 02] @@ -15,4 +16,5 @@ Number of expressions: 0 Number of file 0 mappings: 2 - Code(Counter(0)) at (prev + 78, 1) to (start + 1, 15) - Code(Counter(0)) at (prev + 17, 5) to (start + 1, 2) +Highest counter ID seen: c0 diff --git a/tests/coverage/attr/off-on-sandwich.cov-map b/tests/coverage/attr/off-on-sandwich.cov-map index d5fbac6ebf7..ae5c9bd19a2 100644 --- a/tests/coverage/attr/off-on-sandwich.cov-map +++ b/tests/coverage/attr/off-on-sandwich.cov-map @@ -6,6 +6,7 @@ Number of expressions: 0 Number of file 0 mappings: 2 - Code(Counter(0)) at (prev + 15, 5) to (start + 2, 18) - Code(Counter(0)) at (prev + 7, 5) to (start + 0, 6) +Highest counter ID seen: c0 Function name: off_on_sandwich::sparse_a::sparse_b::sparse_c Raw bytes (14): 0x[01, 01, 00, 02, 01, 21, 09, 02, 17, 01, 0b, 09, 00, 0a] @@ -15,6 +16,7 @@ Number of expressions: 0 Number of file 0 mappings: 2 - Code(Counter(0)) at (prev + 33, 9) to (start + 2, 23) - Code(Counter(0)) at (prev + 11, 9) to (start + 0, 10) +Highest counter ID seen: c0 Function name: off_on_sandwich::sparse_a::sparse_b::sparse_c::sparse_d Raw bytes (14): 0x[01, 01, 00, 02, 01, 24, 0d, 02, 1b, 01, 07, 0d, 00, 0e] @@ -24,4 +26,5 @@ Number of expressions: 0 Number of file 0 mappings: 2 - Code(Counter(0)) at (prev + 36, 13) to (start + 2, 27) - Code(Counter(0)) at (prev + 7, 13) to (start + 0, 14) +Highest counter ID seen: c0 diff --git a/tests/coverage/await_ready.cov-map b/tests/coverage/await_ready.cov-map index 38c2cf7b2d3..95dbf68a191 100644 --- a/tests/coverage/await_ready.cov-map +++ b/tests/coverage/await_ready.cov-map @@ -5,6 +5,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 15, 1) to (start + 0, 30) +Highest counter ID seen: c0 Function name: await_ready::await_ready::{closure#0} Raw bytes (14): 0x[01, 01, 00, 02, 01, 0f, 1e, 03, 0f, 05, 04, 01, 00, 02] @@ -14,4 +15,5 @@ Number of expressions: 0 Number of file 0 mappings: 2 - Code(Counter(0)) at (prev + 15, 30) to (start + 3, 15) - Code(Counter(1)) at (prev + 4, 1) to (start + 0, 2) +Highest counter ID seen: c1 diff --git a/tests/coverage/bad_counter_ids.cov-map b/tests/coverage/bad_counter_ids.cov-map index 7eff7f5f02f..2b5399f33bb 100644 --- a/tests/coverage/bad_counter_ids.cov-map +++ b/tests/coverage/bad_counter_ids.cov-map @@ -6,6 +6,7 @@ Number of expressions: 0 Number of file 0 mappings: 2 - Code(Counter(0)) at (prev + 36, 1) to (start + 2, 31) - Code(Zero) at (prev + 3, 1) to (start + 0, 2) +Highest counter ID seen: c0 Function name: bad_counter_ids::eq_bad_message Raw bytes (21): 0x[01, 01, 01, 01, 00, 03, 01, 29, 01, 02, 0f, 02, 02, 20, 00, 2b, 00, 01, 01, 00, 02] @@ -18,6 +19,7 @@ Number of file 0 mappings: 3 - Code(Expression(0, Sub)) at (prev + 2, 32) to (start + 0, 43) = (c0 - Zero) - Code(Zero) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: c0 Function name: bad_counter_ids::eq_good Raw bytes (14): 0x[01, 01, 00, 02, 01, 10, 01, 02, 1f, 05, 03, 01, 00, 02] @@ -27,6 +29,7 @@ Number of expressions: 0 Number of file 0 mappings: 2 - Code(Counter(0)) at (prev + 16, 1) to (start + 2, 31) - Code(Counter(1)) at (prev + 3, 1) to (start + 0, 2) +Highest counter ID seen: c1 Function name: bad_counter_ids::eq_good_message Raw bytes (19): 0x[01, 01, 00, 03, 01, 15, 01, 02, 0f, 00, 02, 20, 00, 2b, 05, 01, 01, 00, 02] @@ -37,6 +40,7 @@ Number of file 0 mappings: 3 - Code(Counter(0)) at (prev + 21, 1) to (start + 2, 15) - Code(Zero) at (prev + 2, 32) to (start + 0, 43) - Code(Counter(1)) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: c1 Function name: bad_counter_ids::ne_bad Raw bytes (14): 0x[01, 01, 00, 02, 01, 2e, 01, 02, 1f, 00, 03, 01, 00, 02] @@ -46,6 +50,7 @@ Number of expressions: 0 Number of file 0 mappings: 2 - Code(Counter(0)) at (prev + 46, 1) to (start + 2, 31) - Code(Zero) at (prev + 3, 1) to (start + 0, 2) +Highest counter ID seen: c0 Function name: bad_counter_ids::ne_bad_message Raw bytes (19): 0x[01, 01, 00, 03, 01, 33, 01, 02, 0f, 05, 02, 20, 00, 2b, 00, 01, 01, 00, 02] @@ -56,6 +61,7 @@ Number of file 0 mappings: 3 - Code(Counter(0)) at (prev + 51, 1) to (start + 2, 15) - Code(Counter(1)) at (prev + 2, 32) to (start + 0, 43) - Code(Zero) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: c1 Function name: bad_counter_ids::ne_good Raw bytes (16): 0x[01, 01, 01, 01, 00, 02, 01, 1a, 01, 02, 1f, 02, 03, 01, 00, 02] @@ -67,6 +73,7 @@ Number of file 0 mappings: 2 - Code(Counter(0)) at (prev + 26, 1) to (start + 2, 31) - Code(Expression(0, Sub)) at (prev + 3, 1) to (start + 0, 2) = (c0 - Zero) +Highest counter ID seen: c0 Function name: bad_counter_ids::ne_good_message Raw bytes (21): 0x[01, 01, 01, 01, 00, 03, 01, 1f, 01, 02, 0f, 00, 02, 20, 00, 2b, 02, 01, 01, 00, 02] @@ -79,4 +86,5 @@ Number of file 0 mappings: 3 - Code(Zero) at (prev + 2, 32) to (start + 0, 43) - Code(Expression(0, Sub)) at (prev + 1, 1) to (start + 0, 2) = (c0 - Zero) +Highest counter ID seen: c0 diff --git a/tests/coverage/bench.cov-map b/tests/coverage/bench.cov-map index aa702a48681..9ee6510f690 100644 --- a/tests/coverage/bench.cov-map +++ b/tests/coverage/bench.cov-map @@ -5,4 +5,5 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 8, 1) to (start + 0, 39) +Highest counter ID seen: c0 diff --git a/tests/coverage/branch/generics.cov-map b/tests/coverage/branch/generics.cov-map index 2e5668c8b56..656890634ff 100644 --- a/tests/coverage/branch/generics.cov-map +++ b/tests/coverage/branch/generics.cov-map @@ -13,6 +13,7 @@ Number of file 0 mappings: 5 - Code(Expression(0, Sub)) at (prev + 2, 12) to (start + 2, 6) = (c0 - c1) - Code(Counter(0)) at (prev + 3, 1) to (start + 0, 2) +Highest counter ID seen: c1 Function name: generics::print_size:: Raw bytes (33): 0x[01, 01, 01, 01, 05, 05, 01, 06, 01, 01, 24, 20, 05, 02, 01, 08, 00, 24, 05, 00, 25, 02, 06, 02, 02, 0c, 02, 06, 01, 03, 01, 00, 02] @@ -29,6 +30,7 @@ Number of file 0 mappings: 5 - Code(Expression(0, Sub)) at (prev + 2, 12) to (start + 2, 6) = (c0 - c1) - Code(Counter(0)) at (prev + 3, 1) to (start + 0, 2) +Highest counter ID seen: c1 Function name: generics::print_size:: Raw bytes (33): 0x[01, 01, 01, 01, 05, 05, 01, 06, 01, 01, 24, 20, 05, 02, 01, 08, 00, 24, 05, 00, 25, 02, 06, 02, 02, 0c, 02, 06, 01, 03, 01, 00, 02] @@ -45,4 +47,5 @@ Number of file 0 mappings: 5 - Code(Expression(0, Sub)) at (prev + 2, 12) to (start + 2, 6) = (c0 - c1) - Code(Counter(0)) at (prev + 3, 1) to (start + 0, 2) +Highest counter ID seen: c1 diff --git a/tests/coverage/branch/guard.cov-map b/tests/coverage/branch/guard.cov-map index d67c3d349a1..0f33ed17a0a 100644 --- a/tests/coverage/branch/guard.cov-map +++ b/tests/coverage/branch/guard.cov-map @@ -29,4 +29,5 @@ Number of file 0 mappings: 13 = (c1 + c2) - Code(Expression(2, Add)) at (prev + 4, 1) to (start + 0, 2) = ((((c1 + c2) + c3) + c4) + c5) +Highest counter ID seen: c7 diff --git a/tests/coverage/branch/if-let.cov-map b/tests/coverage/branch/if-let.cov-map index 0b098bc6497..380765c7af4 100644 --- a/tests/coverage/branch/if-let.cov-map +++ b/tests/coverage/branch/if-let.cov-map @@ -16,6 +16,7 @@ Number of file 0 mappings: 7 = (c1 - c2) - Code(Counter(2)) at (prev + 2, 12) to (start + 2, 6) - Code(Counter(1)) at (prev + 3, 5) to (start + 1, 2) +Highest counter ID seen: c2 Function name: if_let::if_let_chain Raw bytes (66): 0x[01, 01, 04, 01, 05, 05, 09, 0f, 0d, 05, 09, 0a, 01, 17, 01, 00, 33, 20, 02, 05, 01, 0c, 00, 13, 02, 00, 11, 00, 12, 01, 00, 16, 00, 17, 20, 0d, 09, 01, 10, 00, 17, 0d, 00, 15, 00, 16, 02, 00, 1a, 00, 1b, 0d, 01, 05, 03, 06, 0f, 03, 0c, 02, 06, 0b, 03, 05, 01, 02] @@ -45,4 +46,5 @@ Number of file 0 mappings: 10 = (c1 + c2) - Code(Expression(2, Add)) at (prev + 3, 5) to (start + 1, 2) = ((c1 + c2) + c3) +Highest counter ID seen: c3 diff --git a/tests/coverage/branch/if.cov-map b/tests/coverage/branch/if.cov-map index 7f4ee980e26..4a8cb664dd8 100644 --- a/tests/coverage/branch/if.cov-map +++ b/tests/coverage/branch/if.cov-map @@ -22,6 +22,7 @@ Number of file 0 mappings: 8 = (c3 + (c1 - c2)) - Code(Expression(2, Add)) at (prev + 3, 1) to (start + 0, 2) = (c4 + (c3 + (c1 - c2))) +Highest counter ID seen: c4 Function name: if::branch_not Raw bytes (116): 0x[01, 01, 07, 05, 09, 05, 0d, 05, 0d, 05, 11, 05, 11, 05, 15, 05, 15, 12, 01, 0c, 01, 01, 10, 05, 03, 08, 00, 09, 20, 09, 02, 00, 08, 00, 09, 09, 01, 09, 00, 11, 02, 01, 06, 00, 07, 05, 01, 08, 00, 0a, 20, 0a, 0d, 00, 08, 00, 0a, 0a, 00, 0b, 02, 06, 0d, 02, 06, 00, 07, 05, 01, 08, 00, 0b, 20, 11, 12, 00, 08, 00, 0b, 11, 00, 0c, 02, 06, 12, 02, 06, 00, 07, 05, 01, 08, 00, 0c, 20, 1a, 15, 00, 08, 00, 0c, 1a, 00, 0d, 02, 06, 15, 02, 06, 00, 07, 05, 01, 01, 00, 02] @@ -66,6 +67,7 @@ Number of file 0 mappings: 18 = (c1 - c5) - Code(Counter(5)) at (prev + 2, 6) to (start + 0, 7) - Code(Counter(1)) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: c5 Function name: if::branch_not_as Raw bytes (90): 0x[01, 01, 05, 05, 09, 05, 0d, 05, 0d, 05, 11, 05, 11, 0e, 01, 1d, 01, 01, 10, 05, 03, 08, 00, 14, 20, 02, 09, 00, 08, 00, 14, 02, 00, 15, 02, 06, 09, 02, 06, 00, 07, 05, 01, 08, 00, 15, 20, 0d, 0a, 00, 08, 00, 15, 0d, 00, 16, 02, 06, 0a, 02, 06, 00, 07, 05, 01, 08, 00, 16, 20, 12, 11, 00, 08, 00, 16, 12, 00, 17, 02, 06, 11, 02, 06, 00, 07, 05, 01, 01, 00, 02] @@ -101,6 +103,7 @@ Number of file 0 mappings: 14 = (c1 - c4) - Code(Counter(4)) at (prev + 2, 6) to (start + 0, 7) - Code(Counter(1)) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: c4 Function name: if::branch_or Raw bytes (56): 0x[01, 01, 04, 05, 09, 09, 0d, 0f, 11, 09, 0d, 08, 01, 35, 01, 01, 10, 05, 03, 08, 00, 09, 20, 09, 02, 00, 08, 00, 09, 02, 00, 0d, 00, 0e, 20, 0d, 11, 00, 0d, 00, 0e, 0f, 00, 0f, 02, 06, 11, 02, 0c, 02, 06, 0b, 03, 01, 00, 02] @@ -127,4 +130,5 @@ Number of file 0 mappings: 8 - Code(Counter(4)) at (prev + 2, 12) to (start + 2, 6) - Code(Expression(2, Add)) at (prev + 3, 1) to (start + 0, 2) = ((c2 + c3) + c4) +Highest counter ID seen: c4 diff --git a/tests/coverage/branch/lazy-boolean.cov-map b/tests/coverage/branch/lazy-boolean.cov-map index 09ce9137673..c2b6a5b8df2 100644 --- a/tests/coverage/branch/lazy-boolean.cov-map +++ b/tests/coverage/branch/lazy-boolean.cov-map @@ -13,6 +13,7 @@ Number of file 0 mappings: 6 false = (c1 - c2) - Code(Counter(2)) at (prev + 0, 18) to (start + 0, 19) - Code(Counter(1)) at (prev + 1, 5) to (start + 1, 2) +Highest counter ID seen: c2 Function name: lazy_boolean::branch_or Raw bytes (38): 0x[01, 01, 01, 05, 09, 06, 01, 1b, 01, 01, 10, 05, 04, 09, 00, 0a, 05, 00, 0d, 00, 0e, 20, 09, 02, 00, 0d, 00, 0e, 02, 00, 12, 00, 13, 05, 01, 05, 01, 02] @@ -30,6 +31,7 @@ Number of file 0 mappings: 6 - Code(Expression(0, Sub)) at (prev + 0, 18) to (start + 0, 19) = (c1 - c2) - Code(Counter(1)) at (prev + 1, 5) to (start + 1, 2) +Highest counter ID seen: c2 Function name: lazy_boolean::chain Raw bytes (149): 0x[01, 01, 13, 11, 07, 0b, 16, 15, 1a, 09, 0d, 05, 09, 05, 09, 09, 0d, 47, 25, 4b, 21, 19, 1d, 03, 19, 03, 19, 3e, 1d, 03, 19, 3e, 1d, 03, 19, 47, 25, 4b, 21, 19, 1d, 13, 01, 24, 01, 01, 10, 03, 04, 09, 00, 0a, 05, 00, 0d, 00, 12, 20, 09, 16, 00, 0d, 00, 12, 09, 00, 16, 00, 1b, 20, 0d, 1a, 00, 16, 00, 1b, 0d, 00, 1f, 00, 24, 20, 11, 15, 00, 1f, 00, 24, 11, 00, 28, 00, 2d, 03, 01, 05, 00, 11, 43, 03, 09, 00, 0a, 03, 00, 0d, 00, 12, 20, 19, 3e, 00, 0d, 00, 12, 3e, 00, 16, 00, 1b, 20, 1d, 3a, 00, 16, 00, 1b, 3a, 00, 1f, 00, 24, 20, 21, 25, 00, 1f, 00, 24, 25, 00, 28, 00, 2d, 43, 01, 05, 01, 02] @@ -94,6 +96,7 @@ Number of file 0 mappings: 19 - Code(Counter(9)) at (prev + 0, 40) to (start + 0, 45) - Code(Expression(16, Add)) at (prev + 1, 5) to (start + 1, 2) = (((c6 + c7) + c8) + c9) +Highest counter ID seen: c9 Function name: lazy_boolean::nested_mixed Raw bytes (155): 0x[01, 01, 16, 33, 1a, 09, 0d, 1e, 0d, 05, 09, 05, 09, 05, 09, 1e, 0d, 05, 09, 09, 0d, 33, 11, 09, 0d, 33, 11, 09, 0d, 19, 57, 1d, 21, 03, 15, 15, 19, 4a, 4e, 15, 19, 03, 15, 19, 57, 1d, 21, 13, 01, 31, 01, 01, 10, 03, 04, 09, 00, 0a, 05, 00, 0e, 00, 13, 20, 09, 1e, 00, 0e, 00, 13, 1e, 00, 17, 00, 1d, 20, 0d, 1a, 00, 17, 00, 1d, 33, 00, 23, 00, 28, 20, 11, 2e, 00, 23, 00, 28, 2e, 00, 2c, 00, 33, 03, 01, 05, 00, 11, 53, 03, 09, 00, 0a, 03, 00, 0e, 00, 13, 20, 15, 4e, 00, 0e, 00, 13, 15, 00, 17, 00, 1c, 20, 19, 4a, 00, 17, 00, 1c, 47, 00, 22, 00, 28, 20, 1d, 21, 00, 22, 00, 28, 1d, 00, 2c, 00, 33, 53, 01, 05, 01, 02] @@ -163,4 +166,5 @@ Number of file 0 mappings: 19 - Code(Counter(7)) at (prev + 0, 44) to (start + 0, 51) - Code(Expression(20, Add)) at (prev + 1, 5) to (start + 1, 2) = (c6 + (c7 + c8)) +Highest counter ID seen: c8 diff --git a/tests/coverage/branch/let-else.cov-map b/tests/coverage/branch/let-else.cov-map index 07079934464..e6bf7ed6a92 100644 --- a/tests/coverage/branch/let-else.cov-map +++ b/tests/coverage/branch/let-else.cov-map @@ -16,4 +16,5 @@ Number of file 0 mappings: 7 - Code(Expression(0, Sub)) at (prev + 4, 5) to (start + 0, 11) = (c1 - c2) - Code(Counter(1)) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: c2 diff --git a/tests/coverage/branch/match-arms.cov-map b/tests/coverage/branch/match-arms.cov-map index 1f17f11baaa..fd0366ee818 100644 --- a/tests/coverage/branch/match-arms.cov-map +++ b/tests/coverage/branch/match-arms.cov-map @@ -34,6 +34,7 @@ Number of file 0 mappings: 12 = ((((Zero + c2) + c3) + c4) + c5) - Code(Expression(4, Add)) at (prev + 3, 5) to (start + 1, 2) = ((((((((Zero + c2) + c3) + c4) + c5) + c6) + c7) + c8) + c9) +Highest counter ID seen: c10 Function name: match_arms::match_arms Raw bytes (51): 0x[01, 01, 06, 05, 07, 0b, 11, 09, 0d, 13, 02, 17, 09, 11, 0d, 07, 01, 18, 01, 01, 10, 05, 03, 0b, 00, 10, 11, 01, 11, 00, 21, 0d, 01, 11, 00, 21, 09, 01, 11, 00, 21, 02, 01, 11, 00, 21, 0f, 03, 05, 01, 02] @@ -56,6 +57,7 @@ Number of file 0 mappings: 7 = (c1 - ((c2 + c3) + c4)) - Code(Expression(3, Add)) at (prev + 3, 5) to (start + 1, 2) = (((c4 + c3) + c2) + (c1 - ((c2 + c3) + c4))) +Highest counter ID seen: c4 Function name: match_arms::or_patterns Raw bytes (75): 0x[01, 01, 0d, 11, 0d, 05, 2f, 33, 11, 09, 0d, 09, 2a, 05, 2f, 33, 11, 09, 0d, 03, 27, 09, 2a, 05, 2f, 33, 11, 09, 0d, 09, 01, 25, 01, 01, 10, 05, 03, 0b, 00, 10, 11, 01, 11, 00, 12, 0d, 00, 1e, 00, 1f, 03, 00, 24, 00, 2e, 09, 01, 11, 00, 12, 2a, 00, 1e, 00, 1f, 27, 00, 24, 00, 2e, 23, 03, 05, 01, 02] @@ -89,4 +91,5 @@ Number of file 0 mappings: 9 = (c2 + (c1 - ((c2 + c3) + c4))) - Code(Expression(8, Add)) at (prev + 3, 5) to (start + 1, 2) = ((c4 + c3) + (c2 + (c1 - ((c2 + c3) + c4)))) +Highest counter ID seen: c4 diff --git a/tests/coverage/branch/match-trivial.cov-map b/tests/coverage/branch/match-trivial.cov-map index 1136a529b25..6af8ce46f5f 100644 --- a/tests/coverage/branch/match-trivial.cov-map +++ b/tests/coverage/branch/match-trivial.cov-map @@ -5,6 +5,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 22, 1) to (start + 1, 16) +Highest counter ID seen: (none) Function name: match_trivial::trivial Raw bytes (14): 0x[01, 01, 00, 02, 01, 1e, 01, 01, 10, 05, 03, 0b, 05, 02] @@ -14,4 +15,5 @@ Number of expressions: 0 Number of file 0 mappings: 2 - Code(Counter(0)) at (prev + 30, 1) to (start + 1, 16) - Code(Counter(1)) at (prev + 3, 11) to (start + 5, 2) +Highest counter ID seen: c1 diff --git a/tests/coverage/branch/no-mir-spans.cov-map b/tests/coverage/branch/no-mir-spans.cov-map index cb19211913f..ab12732b1ed 100644 --- a/tests/coverage/branch/no-mir-spans.cov-map +++ b/tests/coverage/branch/no-mir-spans.cov-map @@ -8,6 +8,7 @@ Number of file 0 mappings: 2 - Branch { true: Counter(1), false: Counter(2) } at (prev + 4, 11) to (start + 0, 16) true = c1 false = c2 +Highest counter ID seen: c2 Function name: no_mir_spans::while_cond_not Raw bytes (16): 0x[01, 01, 00, 02, 01, 19, 01, 00, 15, 20, 09, 05, 04, 0b, 00, 14] @@ -19,6 +20,7 @@ Number of file 0 mappings: 2 - Branch { true: Counter(2), false: Counter(1) } at (prev + 4, 11) to (start + 0, 20) true = c2 false = c1 +Highest counter ID seen: c2 Function name: no_mir_spans::while_op_and Raw bytes (25): 0x[01, 01, 01, 09, 0d, 03, 01, 22, 01, 00, 13, 20, 09, 05, 05, 0b, 00, 10, 20, 02, 0d, 00, 14, 00, 19] @@ -34,6 +36,7 @@ Number of file 0 mappings: 3 - Branch { true: Expression(0, Sub), false: Counter(3) } at (prev + 0, 20) to (start + 0, 25) true = (c2 - c3) false = c3 +Highest counter ID seen: c3 Function name: no_mir_spans::while_op_or Raw bytes (25): 0x[01, 01, 01, 09, 0d, 03, 01, 2d, 01, 00, 12, 20, 05, 09, 05, 0b, 00, 10, 20, 0d, 02, 00, 14, 00, 19] @@ -49,4 +52,5 @@ Number of file 0 mappings: 3 - Branch { true: Counter(3), false: Expression(0, Sub) } at (prev + 0, 20) to (start + 0, 25) true = c3 false = (c2 - c3) +Highest counter ID seen: c3 diff --git a/tests/coverage/branch/while.cov-map b/tests/coverage/branch/while.cov-map index fd05bbb69a5..d5840a2c320 100644 --- a/tests/coverage/branch/while.cov-map +++ b/tests/coverage/branch/while.cov-map @@ -14,6 +14,7 @@ Number of file 0 mappings: 6 false = c1 - Code(Counter(2)) at (prev + 0, 17) to (start + 2, 6) - Code(Counter(1)) at (prev + 3, 1) to (start + 0, 2) +Highest counter ID seen: c2 Function name: while::while_cond_not Raw bytes (38): 0x[01, 01, 01, 05, 09, 06, 01, 15, 01, 01, 10, 05, 03, 09, 00, 12, 03, 01, 0b, 00, 14, 20, 09, 05, 00, 0b, 00, 14, 09, 00, 15, 02, 06, 05, 03, 01, 00, 02] @@ -31,6 +32,7 @@ Number of file 0 mappings: 6 false = c1 - Code(Counter(2)) at (prev + 0, 21) to (start + 2, 6) - Code(Counter(1)) at (prev + 3, 1) to (start + 0, 2) +Highest counter ID seen: c2 Function name: while::while_op_and Raw bytes (56): 0x[01, 01, 04, 05, 09, 03, 0d, 03, 0d, 11, 0d, 08, 01, 1e, 01, 01, 10, 05, 03, 09, 01, 12, 03, 02, 0b, 00, 10, 20, 0a, 0d, 00, 0b, 00, 10, 0a, 00, 14, 00, 19, 20, 09, 11, 00, 14, 00, 19, 09, 00, 1a, 03, 06, 0f, 04, 01, 00, 02] @@ -57,6 +59,7 @@ Number of file 0 mappings: 8 - Code(Counter(2)) at (prev + 0, 26) to (start + 3, 6) - Code(Expression(3, Add)) at (prev + 4, 1) to (start + 0, 2) = (c4 + c3) +Highest counter ID seen: c4 Function name: while::while_op_or Raw bytes (66): 0x[01, 01, 09, 05, 1b, 09, 0d, 03, 09, 03, 09, 22, 0d, 03, 09, 09, 0d, 22, 0d, 03, 09, 08, 01, 29, 01, 01, 10, 05, 03, 09, 01, 12, 03, 02, 0b, 00, 10, 20, 09, 22, 00, 0b, 00, 10, 22, 00, 14, 00, 19, 20, 0d, 1e, 00, 14, 00, 19, 1b, 00, 1a, 03, 06, 1e, 04, 01, 00, 02] @@ -89,4 +92,5 @@ Number of file 0 mappings: 8 = (c2 + c3) - Code(Expression(7, Sub)) at (prev + 4, 1) to (start + 0, 2) = (((c1 + (c2 + c3)) - c2) - c3) +Highest counter ID seen: c3 diff --git a/tests/coverage/closure.cov-map b/tests/coverage/closure.cov-map index 6edd35921fe..d50f9f8e7af 100644 --- a/tests/coverage/closure.cov-map +++ b/tests/coverage/closure.cov-map @@ -30,6 +30,7 @@ Number of file 0 mappings: 24 - Code(Expression(0, Sub)) at (prev + 4, 6) to (start + 0, 7) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 5) to (start + 3, 2) +Highest counter ID seen: c1 Function name: closure::main::{closure#0} Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 28, 05, 02, 14, 05, 02, 15, 02, 0a, 02, 02, 0a, 00, 0b, 01, 01, 09, 01, 06] @@ -43,6 +44,7 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 2, 10) to (start + 0, 11) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 9) to (start + 1, 6) +Highest counter ID seen: c1 Function name: closure::main::{closure#10} (unused) Raw bytes (10): 0x[01, 01, 00, 01, 00, 9b, 01, 07, 00, 21] @@ -51,6 +53,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 155, 7) to (start + 0, 33) +Highest counter ID seen: (none) Function name: closure::main::{closure#11} (unused) Raw bytes (10): 0x[01, 01, 00, 01, 00, 9f, 01, 07, 00, 21] @@ -59,6 +62,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 159, 7) to (start + 0, 33) +Highest counter ID seen: (none) Function name: closure::main::{closure#12} (unused) Raw bytes (10): 0x[01, 01, 00, 01, 00, a7, 01, 01, 00, 17] @@ -67,6 +71,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 167, 1) to (start + 0, 23) +Highest counter ID seen: (none) Function name: closure::main::{closure#13} (unused) Raw bytes (10): 0x[01, 01, 00, 01, 00, ac, 01, 0d, 02, 0e] @@ -75,6 +80,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 172, 13) to (start + 2, 14) +Highest counter ID seen: (none) Function name: closure::main::{closure#14} Raw bytes (27): 0x[01, 01, 01, 01, 05, 04, 01, b3, 01, 0d, 02, 1b, 05, 02, 1e, 00, 25, 02, 00, 2f, 00, 33, 01, 01, 0d, 00, 0e] @@ -88,6 +94,7 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 0, 47) to (start + 0, 51) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 13) to (start + 0, 14) +Highest counter ID seen: c1 Function name: closure::main::{closure#15} Raw bytes (37): 0x[01, 01, 01, 01, 05, 06, 01, bb, 01, 09, 00, 0a, 01, 01, 0d, 00, 15, 01, 01, 11, 01, 1b, 05, 01, 1e, 00, 25, 02, 00, 2f, 00, 33, 01, 02, 09, 00, 0a] @@ -103,6 +110,7 @@ Number of file 0 mappings: 6 - Code(Expression(0, Sub)) at (prev + 0, 47) to (start + 0, 51) = (c0 - c1) - Code(Counter(0)) at (prev + 2, 9) to (start + 0, 10) +Highest counter ID seen: c1 Function name: closure::main::{closure#16} Raw bytes (27): 0x[01, 01, 01, 01, 05, 04, 01, c5, 01, 0d, 02, 1b, 05, 02, 1e, 00, 25, 02, 00, 2f, 00, 33, 01, 01, 0d, 00, 0e] @@ -116,6 +124,7 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 0, 47) to (start + 0, 51) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 13) to (start + 0, 14) +Highest counter ID seen: c1 Function name: closure::main::{closure#17} Raw bytes (37): 0x[01, 01, 01, 01, 05, 06, 01, cd, 01, 09, 00, 0a, 01, 01, 0d, 00, 15, 01, 01, 11, 01, 1b, 05, 01, 1e, 00, 25, 02, 00, 2f, 00, 33, 01, 02, 09, 00, 0a] @@ -131,6 +140,7 @@ Number of file 0 mappings: 6 - Code(Expression(0, Sub)) at (prev + 0, 47) to (start + 0, 51) = (c0 - c1) - Code(Counter(0)) at (prev + 2, 9) to (start + 0, 10) +Highest counter ID seen: c1 Function name: closure::main::{closure#18} (unused) Raw bytes (24): 0x[01, 01, 00, 04, 00, 19, 0d, 02, 1c, 00, 02, 1d, 02, 12, 00, 02, 12, 00, 13, 00, 01, 11, 01, 0e] @@ -142,6 +152,7 @@ Number of file 0 mappings: 4 - Code(Zero) at (prev + 2, 29) to (start + 2, 18) - Code(Zero) at (prev + 2, 18) to (start + 0, 19) - Code(Zero) at (prev + 1, 17) to (start + 1, 14) +Highest counter ID seen: (none) Function name: closure::main::{closure#19} Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 43, 0d, 02, 1c, 05, 02, 1d, 02, 12, 02, 02, 12, 00, 13, 01, 01, 11, 01, 0e] @@ -155,6 +166,7 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 2, 18) to (start + 0, 19) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 17) to (start + 1, 14) +Highest counter ID seen: c1 Function name: closure::main::{closure#1} Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 52, 05, 02, 14, 05, 02, 15, 02, 0a, 02, 02, 0a, 00, 0b, 01, 01, 09, 01, 06] @@ -168,6 +180,7 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 2, 10) to (start + 0, 11) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 9) to (start + 1, 6) +Highest counter ID seen: c1 Function name: closure::main::{closure#2} Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 68, 05, 02, 14, 05, 02, 15, 02, 0a, 02, 02, 0a, 00, 0b, 01, 01, 09, 01, 06] @@ -181,6 +194,7 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 2, 10) to (start + 0, 11) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 9) to (start + 1, 6) +Highest counter ID seen: c1 Function name: closure::main::{closure#3} (unused) Raw bytes (25): 0x[01, 01, 00, 04, 00, 81, 01, 05, 01, 14, 00, 01, 15, 02, 0a, 00, 02, 0a, 00, 0b, 00, 01, 09, 01, 06] @@ -192,6 +206,7 @@ Number of file 0 mappings: 4 - Code(Zero) at (prev + 1, 21) to (start + 2, 10) - Code(Zero) at (prev + 2, 10) to (start + 0, 11) - Code(Zero) at (prev + 1, 9) to (start + 1, 6) +Highest counter ID seen: (none) Function name: closure::main::{closure#4} (unused) Raw bytes (10): 0x[01, 01, 00, 01, 00, 89, 01, 35, 00, 43] @@ -200,6 +215,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 137, 53) to (start + 0, 67) +Highest counter ID seen: (none) Function name: closure::main::{closure#5} Raw bytes (10): 0x[01, 01, 00, 01, 01, 8c, 01, 3d, 00, 4f] @@ -208,6 +224,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 140, 61) to (start + 0, 79) +Highest counter ID seen: c0 Function name: closure::main::{closure#6} Raw bytes (10): 0x[01, 01, 00, 01, 01, 8d, 01, 41, 00, 57] @@ -216,6 +233,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 141, 65) to (start + 0, 87) +Highest counter ID seen: c0 Function name: closure::main::{closure#7} (unused) Raw bytes (10): 0x[01, 01, 00, 01, 00, 8e, 01, 3b, 00, 51] @@ -224,6 +242,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 142, 59) to (start + 0, 81) +Highest counter ID seen: (none) Function name: closure::main::{closure#8} (unused) Raw bytes (10): 0x[01, 01, 00, 01, 00, 93, 01, 3b, 00, 55] @@ -232,6 +251,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 147, 59) to (start + 0, 85) +Highest counter ID seen: (none) Function name: closure::main::{closure#9} (unused) Raw bytes (10): 0x[01, 01, 00, 01, 00, 95, 01, 38, 02, 06] @@ -240,4 +260,5 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 149, 56) to (start + 2, 6) +Highest counter ID seen: (none) diff --git a/tests/coverage/closure_bug.cov-map b/tests/coverage/closure_bug.cov-map index 32e8db5fb2f..96e1e339e56 100644 --- a/tests/coverage/closure_bug.cov-map +++ b/tests/coverage/closure_bug.cov-map @@ -29,6 +29,7 @@ Number of file 0 mappings: 17 - Code(Expression(3, Sub)) at (prev + 0, 23) to (start + 0, 24) = (c0 - c4) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: c4 Function name: closure_bug::main::{closure#0} Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 0e, 09, 00, 12, 05, 00, 15, 00, 19, 02, 00, 23, 00, 28, 01, 00, 29, 00, 2a] @@ -42,6 +43,7 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 0, 35) to (start + 0, 40) = (c0 - c1) - Code(Counter(0)) at (prev + 0, 41) to (start + 0, 42) +Highest counter ID seen: c1 Function name: closure_bug::main::{closure#1} Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 17, 09, 00, 12, 05, 00, 15, 00, 19, 02, 00, 23, 00, 28, 01, 00, 29, 00, 2a] @@ -55,6 +57,7 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 0, 35) to (start + 0, 40) = (c0 - c1) - Code(Counter(0)) at (prev + 0, 41) to (start + 0, 42) +Highest counter ID seen: c1 Function name: closure_bug::main::{closure#2} Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 20, 09, 00, 12, 05, 00, 15, 00, 19, 02, 00, 23, 00, 28, 01, 00, 29, 00, 2a] @@ -68,6 +71,7 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 0, 35) to (start + 0, 40) = (c0 - c1) - Code(Counter(0)) at (prev + 0, 41) to (start + 0, 42) +Highest counter ID seen: c1 Function name: closure_bug::main::{closure#3} Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 29, 09, 00, 12, 05, 00, 15, 00, 19, 02, 00, 23, 00, 28, 01, 00, 29, 00, 2a] @@ -81,4 +85,5 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 0, 35) to (start + 0, 40) = (c0 - c1) - Code(Counter(0)) at (prev + 0, 41) to (start + 0, 42) +Highest counter ID seen: c1 diff --git a/tests/coverage/closure_macro.cov-map b/tests/coverage/closure_macro.cov-map index fb4a137d4c8..7c9d3292f98 100644 --- a/tests/coverage/closure_macro.cov-map +++ b/tests/coverage/closure_macro.cov-map @@ -5,6 +5,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 29, 1) to (start + 2, 2) +Highest counter ID seen: c0 Function name: closure_macro::main Raw bytes (36): 0x[01, 01, 01, 01, 05, 06, 01, 21, 01, 01, 21, 02, 02, 09, 00, 0f, 01, 00, 12, 00, 54, 05, 00, 54, 00, 55, 02, 02, 09, 02, 0b, 01, 03, 01, 00, 02] @@ -21,6 +22,7 @@ Number of file 0 mappings: 6 - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 2, 11) = (c0 - c1) - Code(Counter(0)) at (prev + 3, 1) to (start + 0, 2) +Highest counter ID seen: c1 Function name: closure_macro::main::{closure#0} Raw bytes (35): 0x[01, 01, 03, 01, 05, 05, 0b, 09, 0d, 05, 01, 10, 1c, 03, 21, 05, 04, 11, 01, 27, 02, 03, 11, 00, 16, 0d, 00, 17, 00, 1e, 07, 02, 09, 00, 0a] @@ -38,4 +40,5 @@ Number of file 0 mappings: 5 - Code(Counter(3)) at (prev + 0, 23) to (start + 0, 30) - Code(Expression(1, Add)) at (prev + 2, 9) to (start + 0, 10) = (c1 + (c2 + c3)) +Highest counter ID seen: c3 diff --git a/tests/coverage/closure_macro_async.cov-map b/tests/coverage/closure_macro_async.cov-map index 091e87909f9..e2a52e57015 100644 --- a/tests/coverage/closure_macro_async.cov-map +++ b/tests/coverage/closure_macro_async.cov-map @@ -5,6 +5,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 34, 1) to (start + 2, 2) +Highest counter ID seen: c0 Function name: closure_macro_async::test Raw bytes (9): 0x[01, 01, 00, 01, 01, 26, 01, 00, 2b] @@ -13,6 +14,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 38, 1) to (start + 0, 43) +Highest counter ID seen: c0 Function name: closure_macro_async::test::{closure#0} Raw bytes (36): 0x[01, 01, 01, 01, 05, 06, 01, 26, 2b, 01, 21, 02, 02, 09, 00, 0f, 01, 00, 12, 00, 54, 05, 00, 54, 00, 55, 02, 02, 09, 02, 0b, 01, 03, 01, 00, 02] @@ -29,6 +31,7 @@ Number of file 0 mappings: 6 - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 2, 11) = (c0 - c1) - Code(Counter(0)) at (prev + 3, 1) to (start + 0, 2) +Highest counter ID seen: c1 Function name: closure_macro_async::test::{closure#0}::{closure#0} Raw bytes (35): 0x[01, 01, 03, 01, 05, 05, 0b, 09, 0d, 05, 01, 15, 1c, 03, 21, 05, 04, 11, 01, 27, 02, 03, 11, 00, 16, 0d, 00, 17, 00, 1e, 07, 02, 09, 00, 0a] @@ -46,4 +49,5 @@ Number of file 0 mappings: 5 - Code(Counter(3)) at (prev + 0, 23) to (start + 0, 30) - Code(Expression(1, Add)) at (prev + 2, 9) to (start + 0, 10) = (c1 + (c2 + c3)) +Highest counter ID seen: c3 diff --git a/tests/coverage/closure_unit_return.cov-map b/tests/coverage/closure_unit_return.cov-map index c97b4a44dd6..9a66e0b0e77 100644 --- a/tests/coverage/closure_unit_return.cov-map +++ b/tests/coverage/closure_unit_return.cov-map @@ -6,6 +6,7 @@ Number of expressions: 0 Number of file 0 mappings: 2 - Code(Counter(0)) at (prev + 7, 1) to (start + 1, 16) - Code(Counter(0)) at (prev + 5, 5) to (start + 2, 2) +Highest counter ID seen: c0 Function name: closure_unit_return::explicit_unit::{closure#0} (unused) Raw bytes (9): 0x[01, 01, 00, 01, 00, 08, 16, 02, 06] @@ -14,6 +15,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 8, 22) to (start + 2, 6) +Highest counter ID seen: (none) Function name: closure_unit_return::implicit_unit Raw bytes (14): 0x[01, 01, 00, 02, 01, 10, 01, 01, 10, 01, 05, 05, 02, 02] @@ -23,6 +25,7 @@ Number of expressions: 0 Number of file 0 mappings: 2 - Code(Counter(0)) at (prev + 16, 1) to (start + 1, 16) - Code(Counter(0)) at (prev + 5, 5) to (start + 2, 2) +Highest counter ID seen: c0 Function name: closure_unit_return::implicit_unit::{closure#0} (unused) Raw bytes (9): 0x[01, 01, 00, 01, 00, 11, 16, 02, 06] @@ -31,4 +34,5 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 17, 22) to (start + 2, 6) +Highest counter ID seen: (none) diff --git a/tests/coverage/condition/conditions.cov-map b/tests/coverage/condition/conditions.cov-map index 74726e269fc..208d671919c 100644 --- a/tests/coverage/condition/conditions.cov-map +++ b/tests/coverage/condition/conditions.cov-map @@ -29,6 +29,7 @@ Number of file 0 mappings: 9 false = c4 - Code(Expression(0, Add)) at (prev + 1, 5) to (start + 1, 2) = ((c2 + c3) + c4) +Highest counter ID seen: c4 Function name: conditions::assign_3_or_and Raw bytes (73): 0x[01, 01, 09, 05, 07, 0b, 11, 09, 0d, 01, 05, 01, 05, 22, 11, 01, 05, 22, 11, 01, 05, 09, 01, 17, 01, 00, 2f, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 22, 00, 0d, 00, 0e, 22, 00, 12, 00, 13, 20, 1e, 11, 00, 12, 00, 13, 1e, 00, 17, 00, 18, 20, 09, 0d, 00, 17, 00, 18, 03, 01, 05, 01, 02] @@ -64,6 +65,7 @@ Number of file 0 mappings: 9 false = c3 - Code(Expression(0, Add)) at (prev + 1, 5) to (start + 1, 2) = (c1 + ((c2 + c3) + c4)) +Highest counter ID seen: c4 Function name: conditions::assign_and Raw bytes (51): 0x[01, 01, 04, 07, 0e, 09, 0d, 01, 05, 01, 05, 07, 01, 0d, 01, 00, 21, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 0e, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 20, 09, 0d, 00, 12, 00, 13, 03, 01, 05, 01, 02] @@ -88,6 +90,7 @@ Number of file 0 mappings: 7 false = c3 - Code(Expression(0, Add)) at (prev + 1, 5) to (start + 1, 2) = ((c2 + c3) + (c0 - c1)) +Highest counter ID seen: c3 Function name: conditions::assign_or Raw bytes (51): 0x[01, 01, 04, 07, 0d, 05, 09, 01, 05, 01, 05, 07, 01, 12, 01, 00, 20, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 0e, 00, 0d, 00, 0e, 0e, 00, 12, 00, 13, 20, 09, 0d, 00, 12, 00, 13, 03, 01, 05, 01, 02] @@ -113,6 +116,7 @@ Number of file 0 mappings: 7 false = c3 - Code(Expression(0, Add)) at (prev + 1, 5) to (start + 1, 2) = ((c1 + c2) + c3) +Highest counter ID seen: c3 Function name: conditions::foo Raw bytes (9): 0x[01, 01, 00, 01, 01, 21, 01, 02, 02] @@ -121,6 +125,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 33, 1) to (start + 2, 2) +Highest counter ID seen: c0 Function name: conditions::func_call Raw bytes (39): 0x[01, 01, 03, 01, 05, 0b, 02, 09, 0d, 05, 01, 25, 01, 01, 0a, 20, 05, 02, 01, 09, 00, 0a, 05, 00, 0e, 00, 0f, 20, 09, 0d, 00, 0e, 00, 0f, 07, 01, 01, 00, 02] @@ -141,6 +146,7 @@ Number of file 0 mappings: 5 false = c3 - Code(Expression(1, Add)) at (prev + 1, 1) to (start + 0, 2) = ((c2 + c3) + (c0 - c1)) +Highest counter ID seen: c3 Function name: conditions::simple_assign Raw bytes (9): 0x[01, 01, 00, 01, 01, 08, 01, 03, 02] @@ -149,4 +155,5 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 8, 1) to (start + 3, 2) +Highest counter ID seen: c0 diff --git a/tests/coverage/conditions.cov-map b/tests/coverage/conditions.cov-map index 17143775b7b..a392d1b7028 100644 --- a/tests/coverage/conditions.cov-map +++ b/tests/coverage/conditions.cov-map @@ -260,4 +260,5 @@ Number of file 0 mappings: 68 - Code(Counter(9)) at (prev + 2, 9) to (start + 0, 15) - Code(Expression(137, Add)) at (prev + 2, 1) to (start + 0, 2) = ((c4 + (((c5 + c6) + c7) + c8)) + ((((c9 + c10) + c11) + c12) + ((c0 - c2) - c3))) +Highest counter ID seen: c35 diff --git a/tests/coverage/continue.cov-map b/tests/coverage/continue.cov-map index 810694d7f66..7781d2d2544 100644 --- a/tests/coverage/continue.cov-map +++ b/tests/coverage/continue.cov-map @@ -76,4 +76,5 @@ Number of file 0 mappings: 30 - Code(Counter(16)) at (prev + 3, 9) to (start + 0, 14) - Code(Expression(27, Add)) at (prev + 2, 13) to (start + 1, 2) = (c18 + c17) +Highest counter ID seen: c18 diff --git a/tests/coverage/coroutine.cov-map b/tests/coverage/coroutine.cov-map index 6ff5ed74a96..2fdc3220c19 100644 --- a/tests/coverage/coroutine.cov-map +++ b/tests/coverage/coroutine.cov-map @@ -10,6 +10,7 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 40) = (c0 - c1) - Code(Counter(0)) at (prev + 2, 1) to (start + 0, 2) +Highest counter ID seen: c1 Function name: coroutine::main Raw bytes (65): 0x[01, 01, 08, 07, 0d, 05, 09, 11, 15, 1e, 19, 11, 15, 15, 19, 1e, 19, 11, 15, 09, 01, 13, 01, 02, 16, 01, 08, 0b, 00, 2e, 11, 01, 2b, 00, 2d, 03, 01, 0e, 00, 35, 11, 02, 0b, 00, 2e, 1e, 01, 22, 00, 27, 1a, 00, 2c, 00, 2e, 17, 01, 0e, 00, 35, 1a, 02, 01, 00, 02] @@ -39,6 +40,7 @@ Number of file 0 mappings: 9 = (c5 + c6) - Code(Expression(6, Sub)) at (prev + 2, 1) to (start + 0, 2) = ((c4 - c5) - c6) +Highest counter ID seen: c4 Function name: coroutine::main::{closure#0} Raw bytes (14): 0x[01, 01, 00, 02, 01, 16, 08, 01, 1f, 05, 02, 10, 01, 06] @@ -48,4 +50,5 @@ Number of expressions: 0 Number of file 0 mappings: 2 - Code(Counter(0)) at (prev + 22, 8) to (start + 1, 31) - Code(Counter(1)) at (prev + 2, 16) to (start + 1, 6) +Highest counter ID seen: c1 diff --git a/tests/coverage/coverage_attr_closure.cov-map b/tests/coverage/coverage_attr_closure.cov-map index 5d2c6b00b40..fb861996a0d 100644 --- a/tests/coverage/coverage_attr_closure.cov-map +++ b/tests/coverage/coverage_attr_closure.cov-map @@ -5,6 +5,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 6, 15) to (start + 2, 2) +Highest counter ID seen: c0 Function name: coverage_attr_closure::contains_closures_off::{closure#0} (unused) Raw bytes (9): 0x[01, 01, 00, 01, 00, 1d, 13, 02, 06] @@ -13,6 +14,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 29, 19) to (start + 2, 6) +Highest counter ID seen: (none) Function name: coverage_attr_closure::contains_closures_on Raw bytes (19): 0x[01, 01, 00, 03, 01, 0f, 01, 01, 1a, 01, 05, 09, 00, 1b, 01, 04, 01, 00, 02] @@ -23,6 +25,7 @@ Number of file 0 mappings: 3 - Code(Counter(0)) at (prev + 15, 1) to (start + 1, 26) - Code(Counter(0)) at (prev + 5, 9) to (start + 0, 27) - Code(Counter(0)) at (prev + 4, 1) to (start + 0, 2) +Highest counter ID seen: c0 Function name: coverage_attr_closure::contains_closures_on::{closure#0} (unused) Raw bytes (9): 0x[01, 01, 00, 01, 00, 11, 13, 02, 06] @@ -31,4 +34,5 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 17, 19) to (start + 2, 6) +Highest counter ID seen: (none) diff --git a/tests/coverage/dead_code.cov-map b/tests/coverage/dead_code.cov-map index 31599d9072c..b94c6e656ab 100644 --- a/tests/coverage/dead_code.cov-map +++ b/tests/coverage/dead_code.cov-map @@ -10,6 +10,7 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 0, 7) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: c1 Function name: dead_code::unused_fn (unused) Raw bytes (24): 0x[01, 01, 00, 04, 00, 0f, 01, 07, 0f, 00, 07, 10, 02, 06, 00, 02, 06, 00, 07, 00, 01, 01, 00, 02] @@ -21,6 +22,7 @@ Number of file 0 mappings: 4 - Code(Zero) at (prev + 7, 16) to (start + 2, 6) - Code(Zero) at (prev + 2, 6) to (start + 0, 7) - Code(Zero) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: (none) Function name: dead_code::unused_pub_fn_not_in_library (unused) Raw bytes (24): 0x[01, 01, 00, 04, 00, 03, 01, 07, 0f, 00, 07, 10, 02, 06, 00, 02, 06, 00, 07, 00, 01, 01, 00, 02] @@ -32,4 +34,5 @@ Number of file 0 mappings: 4 - Code(Zero) at (prev + 7, 16) to (start + 2, 6) - Code(Zero) at (prev + 2, 6) to (start + 0, 7) - Code(Zero) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: (none) diff --git a/tests/coverage/drop_trait.cov-map b/tests/coverage/drop_trait.cov-map index eb9d7d7acfd..a97c0f8794c 100644 --- a/tests/coverage/drop_trait.cov-map +++ b/tests/coverage/drop_trait.cov-map @@ -5,6 +5,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 9, 5) to (start + 2, 6) +Highest counter ID seen: c0 Function name: drop_trait::main Raw bytes (24): 0x[01, 01, 00, 04, 01, 0e, 01, 05, 0c, 05, 06, 09, 01, 16, 00, 02, 06, 04, 0b, 01, 05, 01, 00, 02] @@ -16,4 +17,5 @@ Number of file 0 mappings: 4 - Code(Counter(1)) at (prev + 6, 9) to (start + 1, 22) - Code(Zero) at (prev + 2, 6) to (start + 4, 11) - Code(Counter(0)) at (prev + 5, 1) to (start + 0, 2) +Highest counter ID seen: c1 diff --git a/tests/coverage/fn_sig_into_try.cov-map b/tests/coverage/fn_sig_into_try.cov-map index 49758954831..374811dba9e 100644 --- a/tests/coverage/fn_sig_into_try.cov-map +++ b/tests/coverage/fn_sig_into_try.cov-map @@ -5,6 +5,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 10, 1) to (start + 5, 2) +Highest counter ID seen: c0 Function name: fn_sig_into_try::b Raw bytes (26): 0x[01, 01, 01, 01, 00, 04, 01, 11, 01, 03, 0f, 00, 03, 0f, 00, 10, 02, 01, 05, 00, 0c, 01, 01, 01, 00, 02] @@ -18,6 +19,7 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 1, 5) to (start + 0, 12) = (c0 - Zero) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: c0 Function name: fn_sig_into_try::c Raw bytes (26): 0x[01, 01, 01, 01, 00, 04, 01, 18, 01, 03, 17, 00, 03, 17, 00, 18, 02, 01, 05, 00, 0c, 01, 01, 01, 00, 02] @@ -31,6 +33,7 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 1, 5) to (start + 0, 12) = (c0 - Zero) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: c0 Function name: fn_sig_into_try::d Raw bytes (26): 0x[01, 01, 01, 01, 00, 04, 01, 1f, 01, 04, 0f, 00, 04, 0f, 00, 10, 02, 01, 05, 00, 0c, 01, 01, 01, 00, 02] @@ -44,4 +47,5 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 1, 5) to (start + 0, 12) = (c0 - Zero) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: c0 diff --git a/tests/coverage/generics.cov-map b/tests/coverage/generics.cov-map index 48e191c1156..d082bd54493 100644 --- a/tests/coverage/generics.cov-map +++ b/tests/coverage/generics.cov-map @@ -5,6 +5,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 17, 5) to (start + 2, 6) +Highest counter ID seen: c0 Function name: >::set_strength Raw bytes (9): 0x[01, 01, 00, 01, 01, 0a, 05, 02, 06] @@ -13,6 +14,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 10, 5) to (start + 2, 6) +Highest counter ID seen: c0 Function name: as core::ops::drop::Drop>::drop Raw bytes (9): 0x[01, 01, 00, 01, 01, 11, 05, 02, 06] @@ -21,6 +23,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 17, 5) to (start + 2, 6) +Highest counter ID seen: c0 Function name: >::set_strength Raw bytes (9): 0x[01, 01, 00, 01, 01, 0a, 05, 02, 06] @@ -29,6 +32,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 10, 5) to (start + 2, 6) +Highest counter ID seen: c0 Function name: generics::main Raw bytes (24): 0x[01, 01, 00, 04, 01, 16, 01, 08, 0c, 05, 09, 09, 01, 16, 00, 02, 06, 04, 0b, 01, 05, 01, 00, 02] @@ -40,4 +44,5 @@ Number of file 0 mappings: 4 - Code(Counter(1)) at (prev + 9, 9) to (start + 1, 22) - Code(Zero) at (prev + 2, 6) to (start + 4, 11) - Code(Counter(0)) at (prev + 5, 1) to (start + 0, 2) +Highest counter ID seen: c1 diff --git a/tests/coverage/holes.cov-map b/tests/coverage/holes.cov-map index 9350bd9a405..3c740d80ea0 100644 --- a/tests/coverage/holes.cov-map +++ b/tests/coverage/holes.cov-map @@ -5,6 +5,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 37, 9) to (start + 0, 29) +Highest counter ID seen: (none) Function name: holes::main Raw bytes (44): 0x[01, 01, 00, 08, 01, 08, 01, 06, 11, 01, 0f, 05, 00, 12, 01, 04, 05, 00, 12, 01, 07, 05, 00, 12, 01, 06, 05, 00, 12, 01, 06, 05, 03, 0f, 01, 0a, 05, 03, 0f, 01, 0a, 05, 01, 02] @@ -20,6 +21,7 @@ Number of file 0 mappings: 8 - Code(Counter(0)) at (prev + 6, 5) to (start + 3, 15) - Code(Counter(0)) at (prev + 10, 5) to (start + 3, 15) - Code(Counter(0)) at (prev + 10, 5) to (start + 1, 2) +Highest counter ID seen: c0 Function name: holes::main::_unused_fn (unused) Raw bytes (9): 0x[01, 01, 00, 01, 00, 19, 05, 00, 17] @@ -28,6 +30,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 25, 5) to (start + 0, 23) +Highest counter ID seen: (none) Function name: holes::main::{closure#0} (unused) Raw bytes (9): 0x[01, 01, 00, 01, 00, 12, 09, 02, 0a] @@ -36,6 +39,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 18, 9) to (start + 2, 10) +Highest counter ID seen: (none) Function name: holes::main::{closure#1} (unused) Raw bytes (9): 0x[01, 01, 00, 01, 00, 3d, 09, 02, 0a] @@ -44,4 +48,5 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 61, 9) to (start + 2, 10) +Highest counter ID seen: (none) diff --git a/tests/coverage/if.cov-map b/tests/coverage/if.cov-map index 2b5ae97b406..8f12afac027 100644 --- a/tests/coverage/if.cov-map +++ b/tests/coverage/if.cov-map @@ -10,4 +10,5 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 5, 6) to (start + 0, 7) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: c1 diff --git a/tests/coverage/if_else.cov-map b/tests/coverage/if_else.cov-map index c2111917e55..194ad6ca71f 100644 --- a/tests/coverage/if_else.cov-map +++ b/tests/coverage/if_else.cov-map @@ -15,4 +15,5 @@ Number of file 0 mappings: 7 - Code(Expression(1, Sub)) at (prev + 7, 5) to (start + 5, 6) = (c0 - c2) - Code(Counter(0)) at (prev + 6, 1) to (start + 0, 2) +Highest counter ID seen: c2 diff --git a/tests/coverage/if_not.cov-map b/tests/coverage/if_not.cov-map index 9e11ed787a8..a2c276b7bb7 100644 --- a/tests/coverage/if_not.cov-map +++ b/tests/coverage/if_not.cov-map @@ -20,4 +20,5 @@ Number of file 0 mappings: 10 = (c0 - c3) - Code(Counter(3)) at (prev + 2, 12) to (start + 2, 6) - Code(Counter(0)) at (prev + 3, 1) to (start + 0, 2) +Highest counter ID seen: c3 diff --git a/tests/coverage/ignore_run.cov-map b/tests/coverage/ignore_run.cov-map index 9865efae0a1..c8ad3821e16 100644 --- a/tests/coverage/ignore_run.cov-map +++ b/tests/coverage/ignore_run.cov-map @@ -5,4 +5,5 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 3, 1) to (start + 0, 13) +Highest counter ID seen: c0 diff --git a/tests/coverage/inline-dead.cov-map b/tests/coverage/inline-dead.cov-map index 96b907cbe15..411f16725bb 100644 --- a/tests/coverage/inline-dead.cov-map +++ b/tests/coverage/inline-dead.cov-map @@ -5,6 +5,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 23, 1) to (start + 2, 2) +Highest counter ID seen: (none) Function name: inline_dead::live:: Raw bytes (26): 0x[01, 01, 01, 01, 00, 04, 01, 0e, 01, 01, 09, 00, 02, 09, 00, 0f, 02, 02, 09, 00, 0a, 01, 02, 01, 00, 02] @@ -18,6 +19,7 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 10) = (c0 - Zero) - Code(Counter(0)) at (prev + 2, 1) to (start + 0, 2) +Highest counter ID seen: c0 Function name: inline_dead::main Raw bytes (14): 0x[01, 01, 00, 02, 01, 04, 01, 03, 0a, 01, 06, 05, 01, 02] @@ -27,6 +29,7 @@ Number of expressions: 0 Number of file 0 mappings: 2 - Code(Counter(0)) at (prev + 4, 1) to (start + 3, 10) - Code(Counter(0)) at (prev + 6, 5) to (start + 1, 2) +Highest counter ID seen: c0 Function name: inline_dead::main::{closure#0} Raw bytes (23): 0x[01, 01, 02, 00, 06, 01, 00, 03, 01, 07, 17, 01, 16, 00, 01, 17, 00, 18, 03, 01, 05, 00, 06] @@ -40,4 +43,5 @@ Number of file 0 mappings: 3 - Code(Zero) at (prev + 1, 23) to (start + 0, 24) - Code(Expression(0, Add)) at (prev + 1, 5) to (start + 0, 6) = (Zero + (c0 - Zero)) +Highest counter ID seen: c0 diff --git a/tests/coverage/inline.cov-map b/tests/coverage/inline.cov-map index 2366a3bc534..ab3a505e925 100644 --- a/tests/coverage/inline.cov-map +++ b/tests/coverage/inline.cov-map @@ -11,6 +11,7 @@ Number of file 0 mappings: 5 = (c0 + c1) - Code(Counter(1)) at (prev + 0, 17) to (start + 2, 6) - Code(Counter(0)) at (prev + 3, 5) to (start + 1, 2) +Highest counter ID seen: c1 Function name: inline::error Raw bytes (9): 0x[01, 01, 00, 01, 01, 31, 01, 01, 14] @@ -19,6 +20,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 49, 1) to (start + 1, 20) +Highest counter ID seen: c0 Function name: inline::length:: Raw bytes (9): 0x[01, 01, 00, 01, 01, 1e, 01, 02, 02] @@ -27,6 +29,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 30, 1) to (start + 2, 2) +Highest counter ID seen: c0 Function name: inline::main Raw bytes (9): 0x[01, 01, 00, 01, 01, 05, 01, 02, 02] @@ -35,6 +38,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 5, 1) to (start + 2, 2) +Highest counter ID seen: c0 Function name: inline::permutate:: Raw bytes (52): 0x[01, 01, 04, 01, 05, 02, 0d, 05, 0f, 09, 0d, 08, 01, 0f, 01, 02, 0e, 05, 02, 0f, 02, 06, 02, 02, 0f, 00, 14, 11, 01, 0d, 00, 0e, 06, 00, 12, 00, 16, 11, 00, 17, 04, 0a, 0d, 05, 0c, 02, 06, 0b, 03, 01, 00, 02] @@ -57,6 +61,7 @@ Number of file 0 mappings: 8 - Code(Counter(3)) at (prev + 5, 12) to (start + 2, 6) - Code(Expression(2, Add)) at (prev + 3, 1) to (start + 0, 2) = (c1 + (c2 + c3)) +Highest counter ID seen: c4 Function name: inline::permutations:: Raw bytes (9): 0x[01, 01, 00, 01, 01, 0a, 01, 03, 02] @@ -65,6 +70,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 10, 1) to (start + 3, 2) +Highest counter ID seen: c0 Function name: inline::swap:: Raw bytes (9): 0x[01, 01, 00, 01, 01, 23, 01, 04, 02] @@ -73,4 +79,5 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 35, 1) to (start + 4, 2) +Highest counter ID seen: c0 diff --git a/tests/coverage/inner_items.cov-map b/tests/coverage/inner_items.cov-map index 6ccc3f0bafc..16e86b2cade 100644 --- a/tests/coverage/inner_items.cov-map +++ b/tests/coverage/inner_items.cov-map @@ -5,6 +5,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 33, 9) to (start + 3, 10) +Highest counter ID seen: c0 Function name: ::trait_func Raw bytes (9): 0x[01, 01, 00, 01, 01, 28, 09, 03, 0a] @@ -13,6 +14,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 40, 9) to (start + 3, 10) +Highest counter ID seen: c0 Function name: inner_items::main Raw bytes (43): 0x[01, 01, 02, 01, 05, 01, 09, 07, 01, 03, 01, 07, 0f, 05, 07, 10, 02, 06, 02, 02, 06, 00, 07, 01, 24, 08, 00, 0f, 09, 00, 10, 02, 06, 06, 02, 06, 00, 07, 01, 02, 09, 05, 02] @@ -31,6 +33,7 @@ Number of file 0 mappings: 7 - Code(Expression(1, Sub)) at (prev + 2, 6) to (start + 0, 7) = (c0 - c2) - Code(Counter(0)) at (prev + 2, 9) to (start + 5, 2) +Highest counter ID seen: c2 Function name: inner_items::main::in_func Raw bytes (9): 0x[01, 01, 00, 01, 01, 12, 05, 04, 06] @@ -39,4 +42,5 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 18, 5) to (start + 4, 6) +Highest counter ID seen: c0 diff --git a/tests/coverage/issue-83601.cov-map b/tests/coverage/issue-83601.cov-map index f2447e3c92c..c188cca1b51 100644 --- a/tests/coverage/issue-83601.cov-map +++ b/tests/coverage/issue-83601.cov-map @@ -9,4 +9,5 @@ Number of file 0 mappings: 3 - Code(Counter(1)) at (prev + 3, 9) to (start + 1, 28) - Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 3, 2) = (c1 - c2) +Highest counter ID seen: c1 diff --git a/tests/coverage/issue-84561.cov-map b/tests/coverage/issue-84561.cov-map index d3c4671e0ba..a8ad17574ba 100644 --- a/tests/coverage/issue-84561.cov-map +++ b/tests/coverage/issue-84561.cov-map @@ -10,6 +10,7 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 1, 9) to (start + 0, 15) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 5) to (start + 0, 6) +Highest counter ID seen: c1 Function name: issue_84561::main Raw bytes (10): 0x[01, 01, 00, 01, 01, b4, 01, 01, 04, 02] @@ -18,6 +19,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 180, 1) to (start + 4, 2) +Highest counter ID seen: c0 Function name: issue_84561::test1 Raw bytes (50): 0x[01, 01, 00, 09, 01, 9a, 01, 01, 01, 0b, 05, 01, 0c, 00, 1e, 01, 01, 05, 00, 0b, 09, 00, 0c, 00, 1e, 01, 01, 0d, 01, 0b, 0d, 01, 0c, 00, 1e, 01, 01, 05, 03, 0b, 11, 03, 0c, 00, 1e, 01, 01, 01, 00, 02] @@ -34,6 +36,7 @@ Number of file 0 mappings: 9 - Code(Counter(0)) at (prev + 1, 5) to (start + 3, 11) - Code(Counter(4)) at (prev + 3, 12) to (start + 0, 30) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: c4 Function name: issue_84561::test2 Raw bytes (20): 0x[01, 01, 00, 03, 01, b0, 01, 01, 01, 10, 05, 01, 11, 00, 23, 01, 01, 01, 00, 02] @@ -44,6 +47,7 @@ Number of file 0 mappings: 3 - Code(Counter(0)) at (prev + 176, 1) to (start + 1, 16) - Code(Counter(1)) at (prev + 1, 17) to (start + 0, 35) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: c1 Function name: issue_84561::test2::call_print Raw bytes (10): 0x[01, 01, 00, 01, 01, a7, 01, 09, 02, 0a] @@ -52,6 +56,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 167, 9) to (start + 2, 10) +Highest counter ID seen: c0 Function name: issue_84561::test3 Raw bytes (375): 0x[01, 01, 31, 05, 09, 0d, 00, 15, 19, 12, 00, 15, 19, 21, 00, 1e, 00, 21, 00, 31, 00, 3d, 00, 2e, 45, 3d, 00, 42, 49, 45, 00, 3f, 51, 42, 49, 45, 00, 7a, 55, 51, 00, 7a, 55, 51, 00, 77, 5d, 7a, 55, 51, 00, 77, 61, 7a, 55, 51, 00, 72, 65, 77, 61, 7a, 55, 51, 00, 75, be, 01, c2, 01, 79, 69, 6d, 69, 6d, 69, 6d, c2, 01, 00, 69, 6d, c2, 01, 79, 69, 6d, bb, 01, 7d, 75, be, 01, c2, 01, 79, 69, 6d, b6, 01, 00, bb, 01, 7d, 75, be, 01, c2, 01, 79, 69, 6d, 33, 01, 08, 01, 03, 1c, 05, 04, 09, 01, 1c, 02, 02, 05, 04, 1f, 0d, 05, 05, 00, 1f, 06, 01, 05, 00, 1f, 15, 01, 09, 01, 1c, 12, 02, 05, 00, 1f, 0e, 01, 05, 00, 0f, 00, 00, 20, 00, 30, 21, 01, 05, 03, 0f, 00, 03, 20, 00, 30, 00, 00, 33, 00, 41, 00, 00, 4b, 00, 5a, 1e, 01, 05, 00, 0f, 00, 05, 09, 03, 10, 00, 05, 0d, 00, 1b, 00, 02, 0d, 00, 1c, 1a, 04, 09, 05, 06, 31, 06, 05, 03, 06, 22, 04, 05, 03, 06, 3d, 04, 09, 04, 06, 2e, 05, 08, 00, 0f, 45, 01, 09, 03, 0a, 2a, 05, 09, 03, 0a, 3f, 05, 08, 00, 0f, 51, 01, 09, 00, 13, 00, 03, 0d, 00, 1d, 3a, 03, 09, 00, 13, 00, 03, 0d, 00, 1d, 77, 03, 05, 00, 0f, 77, 01, 0c, 00, 13, 5d, 01, 0d, 00, 13, 56, 02, 0d, 00, 13, 72, 04, 05, 02, 13, 65, 03, 0d, 00, 13, 6e, 02, 0d, 00, 13, bb, 01, 03, 05, 00, 0f, 69, 01, 0c, 00, 13, 6d, 01, 0d, 03, 0e, 75, 04, 0d, 00, 13, c2, 01, 02, 0d, 00, 17, c2, 01, 01, 14, 00, 1b, 00, 01, 15, 00, 1b, 92, 01, 02, 15, 00, 1b, be, 01, 04, 0d, 00, 13, 7d, 03, 09, 00, 19, b6, 01, 02, 05, 00, 0f, b2, 01, 03, 09, 00, 22, 00, 02, 05, 00, 0f, 00, 03, 09, 00, 2c, 00, 02, 01, 00, 02] @@ -182,4 +187,5 @@ Number of file 0 mappings: 51 - Code(Zero) at (prev + 2, 5) to (start + 0, 15) - Code(Zero) at (prev + 3, 9) to (start + 0, 44) - Code(Zero) at (prev + 2, 1) to (start + 0, 2) +Highest counter ID seen: c31 diff --git a/tests/coverage/issue-85461.cov-map b/tests/coverage/issue-85461.cov-map index d1c449b9a35..349bc2cab80 100644 --- a/tests/coverage/issue-85461.cov-map +++ b/tests/coverage/issue-85461.cov-map @@ -5,4 +5,5 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 8, 1) to (start + 3, 2) +Highest counter ID seen: c0 diff --git a/tests/coverage/issue-93054.cov-map b/tests/coverage/issue-93054.cov-map index 024ef519fcf..38cb70a3f97 100644 --- a/tests/coverage/issue-93054.cov-map +++ b/tests/coverage/issue-93054.cov-map @@ -5,6 +5,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 21, 1) to (start + 0, 29) +Highest counter ID seen: (none) Function name: issue_93054::main Raw bytes (9): 0x[01, 01, 00, 01, 01, 1d, 01, 00, 0d] @@ -13,6 +14,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 29, 1) to (start + 0, 13) +Highest counter ID seen: c0 Function name: issue_93054::make (unused) Raw bytes (9): 0x[01, 01, 00, 01, 00, 19, 01, 02, 02] @@ -21,4 +23,5 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 25, 1) to (start + 2, 2) +Highest counter ID seen: (none) diff --git a/tests/coverage/lazy_boolean.cov-map b/tests/coverage/lazy_boolean.cov-map index 8dca205d33f..fcb9d8f1ff5 100644 --- a/tests/coverage/lazy_boolean.cov-map +++ b/tests/coverage/lazy_boolean.cov-map @@ -46,4 +46,5 @@ Number of file 0 mappings: 28 - Code(Expression(6, Sub)) at (prev + 2, 12) to (start + 2, 6) = (c0 - c9) - Code(Counter(0)) at (prev + 3, 1) to (start + 0, 2) +Highest counter ID seen: c9 diff --git a/tests/coverage/let_else_loop.cov-map b/tests/coverage/let_else_loop.cov-map index 13d0d08adb1..04451596eae 100644 --- a/tests/coverage/let_else_loop.cov-map +++ b/tests/coverage/let_else_loop.cov-map @@ -7,6 +7,7 @@ Number of file 0 mappings: 3 - Code(Zero) at (prev + 22, 1) to (start + 1, 12) - Code(Zero) at (prev + 1, 15) to (start + 0, 22) - Code(Zero) at (prev + 0, 32) to (start + 0, 39) +Highest counter ID seen: (none) Function name: let_else_loop::_loop_either_way (unused) Raw bytes (19): 0x[01, 01, 00, 03, 00, 0f, 01, 01, 14, 00, 01, 1c, 00, 23, 00, 01, 05, 00, 0c] @@ -17,6 +18,7 @@ Number of file 0 mappings: 3 - Code(Zero) at (prev + 15, 1) to (start + 1, 20) - Code(Zero) at (prev + 1, 28) to (start + 0, 35) - Code(Zero) at (prev + 1, 5) to (start + 0, 12) +Highest counter ID seen: (none) Function name: let_else_loop::loopy Raw bytes (19): 0x[01, 01, 00, 03, 01, 09, 01, 01, 14, 00, 01, 1c, 00, 23, 05, 01, 01, 00, 02] @@ -27,4 +29,5 @@ Number of file 0 mappings: 3 - Code(Counter(0)) at (prev + 9, 1) to (start + 1, 20) - Code(Zero) at (prev + 1, 28) to (start + 0, 35) - Code(Counter(1)) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: c1 diff --git a/tests/coverage/long_and_wide.cov-map b/tests/coverage/long_and_wide.cov-map index 97aebf9b18a..032b7fe102e 100644 --- a/tests/coverage/long_and_wide.cov-map +++ b/tests/coverage/long_and_wide.cov-map @@ -5,6 +5,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 150, 1) to (start + 0, 21) +Highest counter ID seen: c0 Function name: long_and_wide::long_function Raw bytes (10): 0x[01, 01, 00, 01, 01, 10, 01, 84, 01, 02] @@ -13,6 +14,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 16, 1) to (start + 132, 2) +Highest counter ID seen: c0 Function name: long_and_wide::main Raw bytes (9): 0x[01, 01, 00, 01, 01, 07, 01, 04, 02] @@ -21,6 +23,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 7, 1) to (start + 4, 2) +Highest counter ID seen: c0 Function name: long_and_wide::wide_function Raw bytes (10): 0x[01, 01, 00, 01, 01, 0e, 01, 00, 8b, 01] @@ -29,4 +32,5 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 14, 1) to (start + 0, 139) +Highest counter ID seen: c0 diff --git a/tests/coverage/loop-break.cov-map b/tests/coverage/loop-break.cov-map index 890d5d84539..63280a0bf7c 100644 --- a/tests/coverage/loop-break.cov-map +++ b/tests/coverage/loop-break.cov-map @@ -11,4 +11,5 @@ Number of file 0 mappings: 5 - Code(Counter(0)) at (prev + 1, 13) to (start + 0, 18) - Code(Counter(1)) at (prev + 1, 10) to (start + 0, 11) - Code(Counter(0)) at (prev + 2, 1) to (start + 0, 2) +Highest counter ID seen: c1 diff --git a/tests/coverage/loop_break_value.cov-map b/tests/coverage/loop_break_value.cov-map index d8dca8a85c3..e48d078f672 100644 --- a/tests/coverage/loop_break_value.cov-map +++ b/tests/coverage/loop_break_value.cov-map @@ -5,4 +5,5 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 4, 1) to (start + 10, 2) +Highest counter ID seen: c0 diff --git a/tests/coverage/loops_branches.cov-map b/tests/coverage/loops_branches.cov-map index 9187dcbd865..1d263611a3a 100644 --- a/tests/coverage/loops_branches.cov-map +++ b/tests/coverage/loops_branches.cov-map @@ -75,6 +75,7 @@ Number of file 0 mappings: 20 - Code(Counter(6)) at (prev + 3, 9) to (start + 0, 15) - Code(Expression(34, Add)) at (prev + 1, 5) to (start + 0, 6) = ((c9 + (((((c3 + Zero) + (c4 + Zero)) - c6) - Zero) - c4)) + c6) +Highest counter ID seen: c9 Function name: ::fmt Raw bytes (230): 0x[01, 01, 2b, 01, 00, 02, 00, a3, 01, 19, a7, 01, ab, 01, 00, 0d, 00, 15, a7, 01, ab, 01, 00, 0d, 00, 15, a3, 01, 19, a7, 01, ab, 01, 00, 0d, 00, 15, 9e, 01, 00, a3, 01, 19, a7, 01, ab, 01, 00, 0d, 00, 15, 9a, 01, 00, 9e, 01, 00, a3, 01, 19, a7, 01, ab, 01, 00, 0d, 00, 15, 9e, 01, 00, a3, 01, 19, a7, 01, ab, 01, 00, 0d, 00, 15, 9a, 01, 15, 9e, 01, 00, a3, 01, 19, a7, 01, ab, 01, 00, 0d, 00, 15, 93, 01, 25, 96, 01, 19, 9a, 01, 15, 9e, 01, 00, a3, 01, 19, a7, 01, ab, 01, 00, 0d, 00, 15, 14, 01, 22, 05, 01, 11, 00, 01, 12, 01, 0a, 02, 02, 10, 00, 15, 00, 01, 17, 00, 1b, 00, 00, 1c, 00, 1e, 06, 01, 0e, 00, 0f, 02, 01, 0d, 00, 1e, 25, 00, 1e, 00, 1f, 9e, 01, 02, 0d, 00, 0e, a3, 01, 00, 12, 00, 17, 9e, 01, 01, 10, 00, 15, 00, 00, 16, 01, 0e, 9a, 01, 02, 14, 00, 19, 00, 01, 1b, 00, 1f, 00, 00, 20, 00, 22, 4a, 01, 12, 00, 13, 9a, 01, 01, 11, 00, 22, 96, 01, 00, 22, 00, 23, 19, 03, 09, 00, 0f, 8f, 01, 01, 05, 00, 06] @@ -156,6 +157,7 @@ Number of file 0 mappings: 20 - Code(Counter(6)) at (prev + 3, 9) to (start + 0, 15) - Code(Expression(35, Add)) at (prev + 1, 5) to (start + 0, 6) = (((((((Zero + c3) + (Zero + c5)) - c6) - Zero) - c5) + c6) + c9) +Highest counter ID seen: c9 Function name: loops_branches::main Raw bytes (9): 0x[01, 01, 00, 01, 01, 37, 01, 05, 02] @@ -164,4 +166,5 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 55, 1) to (start + 5, 2) +Highest counter ID seen: c0 diff --git a/tests/coverage/macro_in_closure.cov-map b/tests/coverage/macro_in_closure.cov-map index 2feaab717b5..9614154a366 100644 --- a/tests/coverage/macro_in_closure.cov-map +++ b/tests/coverage/macro_in_closure.cov-map @@ -5,6 +5,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 7, 28) to (start + 0, 45) +Highest counter ID seen: c0 Function name: macro_in_closure::WITH_BLOCK::{closure#0} Raw bytes (9): 0x[01, 01, 00, 01, 01, 09, 1e, 02, 02] @@ -13,4 +14,5 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 9, 30) to (start + 2, 2) +Highest counter ID seen: c0 diff --git a/tests/coverage/macro_name_span.cov-map b/tests/coverage/macro_name_span.cov-map index f3ee44d2a5a..58620452b2b 100644 --- a/tests/coverage/macro_name_span.cov-map +++ b/tests/coverage/macro_name_span.cov-map @@ -5,6 +5,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 22, 28) to (start + 1, 64) +Highest counter ID seen: c0 Function name: macro_name_span::main Raw bytes (9): 0x[01, 01, 00, 01, 01, 0b, 01, 02, 02] @@ -13,4 +14,5 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 11, 1) to (start + 2, 2) +Highest counter ID seen: c0 diff --git a/tests/coverage/match_or_pattern.cov-map b/tests/coverage/match_or_pattern.cov-map index 60b7024533d..f6491ea262d 100644 --- a/tests/coverage/match_or_pattern.cov-map +++ b/tests/coverage/match_or_pattern.cov-map @@ -72,4 +72,5 @@ Number of file 0 mappings: 25 = (c14 + c15) - Code(Expression(26, Add)) at (prev + 2, 1) to (start + 0, 2) = ((c14 + c15) + c16) +Highest counter ID seen: c16 diff --git a/tests/coverage/mcdc/condition-limit.cov-map b/tests/coverage/mcdc/condition-limit.cov-map index 9d1e7518f9e..a3e3b1d09c4 100644 --- a/tests/coverage/mcdc/condition-limit.cov-map +++ b/tests/coverage/mcdc/condition-limit.cov-map @@ -87,4 +87,5 @@ Number of file 0 mappings: 18 = ((((((c2 + c3) + c4) + c5) + c6) + c7) + (c0 - c1)) - Code(Expression(37, Add)) at (prev + 1, 1) to (start + 0, 2) = (c8 + ((((((c2 + c3) + c4) + c5) + c6) + c7) + (c0 - c1))) +Highest counter ID seen: c8 diff --git a/tests/coverage/mcdc/if.cov-map b/tests/coverage/mcdc/if.cov-map index 576c9b14ed1..46960d31c01 100644 --- a/tests/coverage/mcdc/if.cov-map +++ b/tests/coverage/mcdc/if.cov-map @@ -22,6 +22,7 @@ Number of file 0 mappings: 8 = (c2 + (c0 - c1)) - Code(Expression(2, Add)) at (prev + 3, 1) to (start + 0, 2) = (c3 + (c2 + (c0 - c1))) +Highest counter ID seen: c3 Function name: if::mcdc_check_b Raw bytes (64): 0x[01, 01, 04, 01, 05, 09, 02, 0d, 0f, 09, 02, 08, 01, 17, 01, 01, 09, 28, 03, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 0e, 0d, 00, 0f, 02, 06, 0f, 02, 0c, 02, 06, 0b, 03, 01, 00, 02] @@ -47,6 +48,7 @@ Number of file 0 mappings: 8 = (c2 + (c0 - c1)) - Code(Expression(2, Add)) at (prev + 3, 1) to (start + 0, 2) = (c3 + (c2 + (c0 - c1))) +Highest counter ID seen: c3 Function name: if::mcdc_check_both Raw bytes (64): 0x[01, 01, 04, 01, 05, 09, 02, 0d, 0f, 09, 02, 08, 01, 1f, 01, 01, 09, 28, 03, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 0e, 0d, 00, 0f, 02, 06, 0f, 02, 0c, 02, 06, 0b, 03, 01, 00, 02] @@ -72,6 +74,7 @@ Number of file 0 mappings: 8 = (c2 + (c0 - c1)) - Code(Expression(2, Add)) at (prev + 3, 1) to (start + 0, 2) = (c3 + (c2 + (c0 - c1))) +Highest counter ID seen: c3 Function name: if::mcdc_check_neither Raw bytes (64): 0x[01, 01, 04, 01, 05, 09, 02, 0d, 0f, 09, 02, 08, 01, 07, 01, 01, 09, 28, 03, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 0e, 0d, 00, 0f, 02, 06, 0f, 02, 0c, 02, 06, 0b, 03, 01, 00, 02] @@ -97,6 +100,7 @@ Number of file 0 mappings: 8 = (c2 + (c0 - c1)) - Code(Expression(2, Add)) at (prev + 3, 1) to (start + 0, 2) = (c3 + (c2 + (c0 - c1))) +Highest counter ID seen: c3 Function name: if::mcdc_check_not_tree_decision Raw bytes (87): 0x[01, 01, 08, 01, 05, 02, 09, 05, 09, 0d, 1e, 02, 09, 11, 1b, 0d, 1e, 02, 09, 0a, 01, 31, 01, 03, 0a, 28, 05, 03, 03, 08, 00, 15, 30, 05, 02, 01, 02, 03, 00, 09, 00, 0a, 02, 00, 0e, 00, 0f, 30, 09, 1e, 03, 02, 00, 00, 0e, 00, 0f, 0b, 00, 14, 00, 15, 30, 11, 0d, 02, 00, 00, 00, 14, 00, 15, 11, 00, 16, 02, 06, 1b, 02, 0c, 02, 06, 17, 03, 01, 00, 02] @@ -132,6 +136,7 @@ Number of file 0 mappings: 10 = (c3 + ((c0 - c1) - c2)) - Code(Expression(5, Add)) at (prev + 3, 1) to (start + 0, 2) = (c4 + (c3 + ((c0 - c1) - c2))) +Highest counter ID seen: c4 Function name: if::mcdc_check_tree_decision Raw bytes (87): 0x[01, 01, 08, 01, 05, 05, 0d, 05, 0d, 0d, 11, 09, 02, 1b, 1f, 0d, 11, 09, 02, 0a, 01, 27, 01, 03, 09, 28, 04, 03, 03, 08, 00, 15, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0e, 00, 0f, 30, 0d, 0a, 02, 00, 03, 00, 0e, 00, 0f, 0a, 00, 13, 00, 14, 30, 11, 09, 03, 00, 00, 00, 13, 00, 14, 1b, 00, 16, 02, 06, 1f, 02, 0c, 02, 06, 17, 03, 01, 00, 02] @@ -167,6 +172,7 @@ Number of file 0 mappings: 10 = (c2 + (c0 - c1)) - Code(Expression(5, Add)) at (prev + 3, 1) to (start + 0, 2) = ((c3 + c4) + (c2 + (c0 - c1))) +Highest counter ID seen: c4 Function name: if::mcdc_nested_if Raw bytes (124): 0x[01, 01, 0d, 01, 05, 02, 09, 05, 09, 1b, 15, 05, 09, 1b, 15, 05, 09, 11, 15, 02, 09, 2b, 32, 0d, 2f, 11, 15, 02, 09, 0e, 01, 3b, 01, 01, 09, 28, 03, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 00, 02, 00, 08, 00, 09, 02, 00, 0d, 00, 0e, 30, 09, 32, 02, 00, 00, 00, 0d, 00, 0e, 1b, 01, 09, 01, 0d, 28, 06, 02, 01, 0c, 00, 12, 30, 16, 15, 01, 02, 00, 00, 0c, 00, 0d, 16, 00, 11, 00, 12, 30, 0d, 11, 02, 00, 00, 00, 11, 00, 12, 0d, 00, 13, 02, 0a, 2f, 02, 0a, 00, 0b, 32, 01, 0c, 02, 06, 27, 03, 01, 00, 02] @@ -215,4 +221,5 @@ Number of file 0 mappings: 14 = ((c0 - c1) - c2) - Code(Expression(9, Add)) at (prev + 3, 1) to (start + 0, 2) = ((c3 + (c4 + c5)) + ((c0 - c1) - c2)) +Highest counter ID seen: c5 diff --git a/tests/coverage/mcdc/inlined_expressions.cov-map b/tests/coverage/mcdc/inlined_expressions.cov-map index bfde7d75d62..4f44e0f2b85 100644 --- a/tests/coverage/mcdc/inlined_expressions.cov-map +++ b/tests/coverage/mcdc/inlined_expressions.cov-map @@ -18,4 +18,5 @@ Number of file 0 mappings: 6 false = c3 - Code(Expression(1, Add)) at (prev + 1, 1) to (start + 0, 2) = ((c2 + c3) + (c0 - c1)) +Highest counter ID seen: c3 diff --git a/tests/coverage/mcdc/nested_if.cov-map b/tests/coverage/mcdc/nested_if.cov-map index 3da98ff4a51..3bed49e7a12 100644 --- a/tests/coverage/mcdc/nested_if.cov-map +++ b/tests/coverage/mcdc/nested_if.cov-map @@ -56,6 +56,7 @@ Number of file 0 mappings: 20 = (c2 + (c0 - c1)) - Code(Expression(12, Add)) at (prev + 3, 1) to (start + 0, 2) = (c3 + (c2 + (c0 - c1))) +Highest counter ID seen: c8 Function name: nested_if::nested_if_in_condition Raw bytes (120): 0x[01, 01, 0b, 01, 05, 05, 11, 05, 11, 1e, 15, 05, 11, 11, 15, 1e, 15, 05, 11, 09, 02, 0d, 2b, 09, 02, 0e, 01, 07, 01, 01, 09, 28, 06, 02, 01, 08, 00, 2e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 2e, 05, 00, 10, 00, 11, 28, 03, 02, 00, 10, 00, 16, 30, 11, 1e, 01, 00, 02, 00, 10, 00, 11, 1e, 00, 15, 00, 16, 30, 15, 1a, 02, 00, 00, 00, 15, 00, 16, 17, 00, 19, 00, 1d, 1a, 00, 27, 00, 2c, 0d, 00, 2f, 02, 06, 2b, 02, 0c, 02, 06, 27, 03, 01, 00, 02] @@ -101,6 +102,7 @@ Number of file 0 mappings: 14 = (c2 + (c0 - c1)) - Code(Expression(9, Add)) at (prev + 3, 1) to (start + 0, 2) = (c3 + (c2 + (c0 - c1))) +Highest counter ID seen: c5 Function name: nested_if::nested_in_then_block_in_condition Raw bytes (176): 0x[01, 01, 12, 01, 05, 05, 11, 05, 11, 3a, 15, 05, 11, 11, 15, 33, 19, 11, 15, 19, 1d, 19, 1d, 1d, 2e, 33, 19, 11, 15, 3a, 15, 05, 11, 09, 02, 0d, 47, 09, 02, 14, 01, 22, 01, 01, 09, 28, 09, 02, 01, 08, 00, 4b, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 4b, 05, 00, 10, 00, 11, 28, 03, 02, 00, 10, 00, 16, 30, 11, 3a, 01, 00, 02, 00, 10, 00, 11, 3a, 00, 15, 00, 16, 30, 15, 36, 02, 00, 00, 00, 15, 00, 16, 33, 00, 1c, 00, 1d, 28, 06, 02, 00, 1c, 00, 22, 30, 19, 2e, 01, 02, 00, 00, 1c, 00, 1d, 19, 00, 21, 00, 22, 30, 26, 1d, 02, 00, 00, 00, 21, 00, 22, 26, 00, 25, 00, 29, 2b, 00, 33, 00, 38, 36, 00, 44, 00, 49, 0d, 00, 4c, 02, 06, 47, 02, 0c, 02, 06, 43, 03, 01, 00, 02] @@ -165,6 +167,7 @@ Number of file 0 mappings: 20 = (c2 + (c0 - c1)) - Code(Expression(16, Add)) at (prev + 3, 1) to (start + 0, 2) = (c3 + (c2 + (c0 - c1))) +Highest counter ID seen: c7 Function name: nested_if::nested_single_condition_decision Raw bytes (85): 0x[01, 01, 06, 01, 05, 05, 11, 05, 11, 09, 02, 0d, 17, 09, 02, 0b, 01, 17, 01, 04, 09, 28, 03, 02, 04, 08, 00, 29, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 29, 05, 00, 10, 00, 11, 20, 11, 0a, 00, 10, 00, 11, 11, 00, 14, 00, 19, 0a, 00, 23, 00, 27, 0d, 00, 2a, 02, 06, 17, 02, 0c, 02, 06, 13, 03, 01, 00, 02] @@ -198,4 +201,5 @@ Number of file 0 mappings: 11 = (c2 + (c0 - c1)) - Code(Expression(4, Add)) at (prev + 3, 1) to (start + 0, 2) = (c3 + (c2 + (c0 - c1))) +Highest counter ID seen: c4 diff --git a/tests/coverage/mcdc/non_control_flow.cov-map b/tests/coverage/mcdc/non_control_flow.cov-map index d5383a19761..677e31e404e 100644 --- a/tests/coverage/mcdc/non_control_flow.cov-map +++ b/tests/coverage/mcdc/non_control_flow.cov-map @@ -33,6 +33,7 @@ Number of file 0 mappings: 10 false = c3 - Code(Expression(0, Add)) at (prev + 1, 5) to (start + 1, 2) = (c1 + ((c2 + c3) + c4)) +Highest counter ID seen: c4 Function name: non_control_flow::assign_3_bis Raw bytes (85): 0x[01, 01, 07, 07, 11, 09, 0d, 01, 05, 05, 09, 16, 1a, 05, 09, 01, 05, 0a, 01, 1b, 01, 00, 2c, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 05, 03, 00, 0d, 00, 18, 30, 05, 1a, 01, 03, 02, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 30, 09, 16, 03, 00, 02, 00, 12, 00, 13, 13, 00, 17, 00, 18, 30, 0d, 11, 02, 00, 00, 00, 17, 00, 18, 03, 01, 05, 01, 02] @@ -66,6 +67,7 @@ Number of file 0 mappings: 10 false = c4 - Code(Expression(0, Add)) at (prev + 1, 5) to (start + 1, 2) = ((c2 + c3) + c4) +Highest counter ID seen: c4 Function name: non_control_flow::assign_and Raw bytes (64): 0x[01, 01, 04, 07, 0e, 09, 0d, 01, 05, 01, 05, 08, 01, 0c, 01, 00, 21, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 03, 02, 00, 0d, 00, 13, 30, 05, 0e, 01, 02, 00, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 30, 09, 0d, 02, 00, 00, 00, 12, 00, 13, 03, 01, 05, 01, 02] @@ -91,6 +93,7 @@ Number of file 0 mappings: 8 false = c3 - Code(Expression(0, Add)) at (prev + 1, 5) to (start + 1, 2) = ((c2 + c3) + (c0 - c1)) +Highest counter ID seen: c3 Function name: non_control_flow::assign_or Raw bytes (64): 0x[01, 01, 04, 07, 0d, 05, 09, 01, 05, 01, 05, 08, 01, 11, 01, 00, 20, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 03, 02, 00, 0d, 00, 13, 30, 05, 0e, 01, 00, 02, 00, 0d, 00, 0e, 0e, 00, 12, 00, 13, 30, 09, 0d, 02, 00, 00, 00, 12, 00, 13, 03, 01, 05, 01, 02] @@ -117,6 +120,7 @@ Number of file 0 mappings: 8 false = c3 - Code(Expression(0, Add)) at (prev + 1, 5) to (start + 1, 2) = ((c1 + c2) + c3) +Highest counter ID seen: c3 Function name: non_control_flow::foo Raw bytes (9): 0x[01, 01, 00, 01, 01, 25, 01, 02, 02] @@ -125,6 +129,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 37, 1) to (start + 2, 2) +Highest counter ID seen: c0 Function name: non_control_flow::func_call Raw bytes (52): 0x[01, 01, 03, 01, 05, 0b, 02, 09, 0d, 06, 01, 29, 01, 01, 0a, 28, 03, 02, 01, 09, 00, 0f, 30, 05, 02, 01, 02, 00, 00, 09, 00, 0a, 05, 00, 0e, 00, 0f, 30, 09, 0d, 02, 00, 00, 00, 0e, 00, 0f, 07, 01, 01, 00, 02] @@ -146,6 +151,7 @@ Number of file 0 mappings: 6 false = c3 - Code(Expression(1, Add)) at (prev + 1, 1) to (start + 0, 2) = ((c2 + c3) + (c0 - c1)) +Highest counter ID seen: c3 Function name: non_control_flow::right_comb_tree Raw bytes (139): 0x[01, 01, 13, 07, 1a, 0b, 19, 0f, 15, 13, 11, 09, 0d, 01, 05, 01, 05, 05, 19, 05, 19, 4a, 15, 05, 19, 4a, 15, 05, 19, 46, 11, 4a, 15, 05, 19, 46, 11, 4a, 15, 05, 19, 0e, 01, 20, 01, 00, 41, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 06, 05, 00, 0d, 00, 2a, 30, 05, 1a, 01, 02, 00, 00, 0d, 00, 0e, 05, 00, 13, 00, 14, 30, 4a, 19, 02, 03, 00, 00, 13, 00, 14, 4a, 00, 19, 00, 1a, 30, 46, 15, 03, 04, 00, 00, 19, 00, 1a, 46, 00, 1f, 00, 20, 30, 42, 11, 04, 05, 00, 00, 1f, 00, 20, 42, 00, 24, 00, 27, 30, 09, 0d, 05, 00, 00, 00, 24, 00, 27, 03, 01, 05, 01, 02] @@ -201,4 +207,5 @@ Number of file 0 mappings: 14 false = c3 - Code(Expression(0, Add)) at (prev + 1, 5) to (start + 1, 2) = (((((c2 + c3) + c4) + c5) + c6) + (c0 - c1)) +Highest counter ID seen: c6 diff --git a/tests/coverage/nested_loops.cov-map b/tests/coverage/nested_loops.cov-map index 35d92594e75..c145d4c5843 100644 --- a/tests/coverage/nested_loops.cov-map +++ b/tests/coverage/nested_loops.cov-map @@ -48,4 +48,5 @@ Number of file 0 mappings: 13 = (c1 + c2) - Code(Expression(22, Add)) at (prev + 2, 1) to (start + 0, 2) = (c4 + c3) +Highest counter ID seen: c6 diff --git a/tests/coverage/no_cov_crate.cov-map b/tests/coverage/no_cov_crate.cov-map index 75234f6c3b7..28d0d9ff8ab 100644 --- a/tests/coverage/no_cov_crate.cov-map +++ b/tests/coverage/no_cov_crate.cov-map @@ -5,6 +5,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 20, 1) to (start + 2, 2) +Highest counter ID seen: c0 Function name: no_cov_crate::add_coverage_2 Raw bytes (9): 0x[01, 01, 00, 01, 01, 18, 01, 02, 02] @@ -13,6 +14,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 24, 1) to (start + 2, 2) +Highest counter ID seen: c0 Function name: no_cov_crate::add_coverage_not_called (unused) Raw bytes (9): 0x[01, 01, 00, 01, 00, 1d, 01, 02, 02] @@ -21,6 +23,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 29, 1) to (start + 2, 2) +Highest counter ID seen: (none) Function name: no_cov_crate::main Raw bytes (9): 0x[01, 01, 00, 01, 01, 4d, 01, 0b, 02] @@ -29,6 +32,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 77, 1) to (start + 11, 2) +Highest counter ID seen: c0 Function name: no_cov_crate::nested_fns::outer Raw bytes (14): 0x[01, 01, 00, 02, 01, 31, 05, 02, 23, 01, 0c, 05, 00, 06] @@ -38,6 +42,7 @@ Number of expressions: 0 Number of file 0 mappings: 2 - Code(Counter(0)) at (prev + 49, 5) to (start + 2, 35) - Code(Counter(0)) at (prev + 12, 5) to (start + 0, 6) +Highest counter ID seen: c0 Function name: no_cov_crate::nested_fns::outer_both_covered Raw bytes (14): 0x[01, 01, 00, 02, 01, 3f, 05, 02, 17, 01, 0b, 05, 00, 06] @@ -47,6 +52,7 @@ Number of expressions: 0 Number of file 0 mappings: 2 - Code(Counter(0)) at (prev + 63, 5) to (start + 2, 23) - Code(Counter(0)) at (prev + 11, 5) to (start + 0, 6) +Highest counter ID seen: c0 Function name: no_cov_crate::nested_fns::outer_both_covered::inner Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 43, 09, 01, 17, 05, 01, 18, 02, 0e, 02, 02, 14, 02, 0e, 01, 03, 09, 00, 0a] @@ -60,4 +66,5 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 2, 20) to (start + 2, 14) = (c0 - c1) - Code(Counter(0)) at (prev + 3, 9) to (start + 0, 10) +Highest counter ID seen: c1 diff --git a/tests/coverage/no_spans.cov-map b/tests/coverage/no_spans.cov-map index 30171c3f319..7f43b68fa90 100644 --- a/tests/coverage/no_spans.cov-map +++ b/tests/coverage/no_spans.cov-map @@ -5,6 +5,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 26, 28) to (start + 0, 29) +Highest counter ID seen: c0 Function name: no_spans::affected_function::{closure#0} Raw bytes (9): 0x[01, 01, 00, 01, 01, 1b, 0c, 00, 0e] @@ -13,4 +14,5 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 27, 12) to (start + 0, 14) +Highest counter ID seen: c0 diff --git a/tests/coverage/no_spans_if_not.cov-map b/tests/coverage/no_spans_if_not.cov-map index bc3e14eddd5..9cb7e6a6cff 100644 --- a/tests/coverage/no_spans_if_not.cov-map +++ b/tests/coverage/no_spans_if_not.cov-map @@ -9,6 +9,7 @@ Number of file 0 mappings: 3 - Code(Expression(0, Sub)) at (prev + 2, 13) to (start + 0, 15) = (c0 - Zero) - Code(Zero) at (prev + 2, 13) to (start + 0, 15) +Highest counter ID seen: c0 Function name: no_spans_if_not::main Raw bytes (9): 0x[01, 01, 00, 01, 01, 0b, 01, 02, 02] @@ -17,4 +18,5 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 11, 1) to (start + 2, 2) +Highest counter ID seen: c0 diff --git a/tests/coverage/overflow.cov-map b/tests/coverage/overflow.cov-map index cb31f3d1f3e..f842ce3e896 100644 --- a/tests/coverage/overflow.cov-map +++ b/tests/coverage/overflow.cov-map @@ -25,6 +25,7 @@ Number of file 0 mappings: 9 - Code(Expression(6, Add)) at (prev + 1, 9) to (start + 0, 23) = (c1 + (c2 + c3)) - Code(Counter(4)) at (prev + 2, 5) to (start + 1, 2) +Highest counter ID seen: c4 Function name: overflow::might_overflow Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 05, 01, 01, 12, 05, 01, 13, 02, 06, 02, 02, 06, 00, 07, 01, 01, 09, 05, 02] @@ -38,4 +39,5 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 0, 7) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 9) to (start + 5, 2) +Highest counter ID seen: c1 diff --git a/tests/coverage/panic_unwind.cov-map b/tests/coverage/panic_unwind.cov-map index f6089ce55ae..f4a7894cc1c 100644 --- a/tests/coverage/panic_unwind.cov-map +++ b/tests/coverage/panic_unwind.cov-map @@ -25,6 +25,7 @@ Number of file 0 mappings: 9 - Code(Expression(6, Add)) at (prev + 1, 9) to (start + 0, 23) = (c1 + (c2 + c3)) - Code(Counter(4)) at (prev + 2, 5) to (start + 1, 2) +Highest counter ID seen: c4 Function name: panic_unwind::might_panic Raw bytes (21): 0x[01, 01, 01, 01, 05, 03, 01, 04, 01, 01, 14, 05, 02, 09, 01, 19, 02, 02, 0c, 03, 02] @@ -37,4 +38,5 @@ Number of file 0 mappings: 3 - Code(Counter(1)) at (prev + 2, 9) to (start + 1, 25) - Code(Expression(0, Sub)) at (prev + 2, 12) to (start + 3, 2) = (c0 - c1) +Highest counter ID seen: c1 diff --git a/tests/coverage/partial_eq.cov-map b/tests/coverage/partial_eq.cov-map index 6c39ac0e378..21c8714ac99 100644 --- a/tests/coverage/partial_eq.cov-map +++ b/tests/coverage/partial_eq.cov-map @@ -5,6 +5,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 12, 5) to (start + 2, 6) +Highest counter ID seen: c0 Function name: partial_eq::main Raw bytes (9): 0x[01, 01, 00, 01, 01, 11, 01, 0a, 02] @@ -13,4 +14,5 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 17, 1) to (start + 10, 2) +Highest counter ID seen: c0 diff --git a/tests/coverage/simple_loop.cov-map b/tests/coverage/simple_loop.cov-map index 541f7bf8fbd..b6f1e8f6afe 100644 --- a/tests/coverage/simple_loop.cov-map +++ b/tests/coverage/simple_loop.cov-map @@ -15,4 +15,5 @@ Number of file 0 mappings: 7 - Code(Counter(0)) at (prev + 4, 13) to (start + 0, 18) - Code(Counter(2)) at (prev + 2, 10) to (start + 3, 10) - Code(Counter(0)) at (prev + 6, 1) to (start + 0, 2) +Highest counter ID seen: c2 diff --git a/tests/coverage/simple_match.cov-map b/tests/coverage/simple_match.cov-map index 49819b23482..b62edf12650 100644 --- a/tests/coverage/simple_match.cov-map +++ b/tests/coverage/simple_match.cov-map @@ -27,4 +27,5 @@ Number of file 0 mappings: 10 - Code(Counter(2)) at (prev + 4, 13) to (start + 7, 14) - Code(Counter(3)) at (prev + 10, 13) to (start + 0, 15) - Code(Counter(4)) at (prev + 3, 1) to (start + 0, 2) +Highest counter ID seen: c4 diff --git a/tests/coverage/sort_groups.cov-map b/tests/coverage/sort_groups.cov-map index 361b70fb74f..4e7ed059c87 100644 --- a/tests/coverage/sort_groups.cov-map +++ b/tests/coverage/sort_groups.cov-map @@ -10,6 +10,7 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 0, 7) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: c1 Function name: sort_groups::generic_fn::<()> Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 11, 01, 01, 0c, 05, 01, 0d, 02, 06, 02, 02, 06, 00, 07, 01, 01, 01, 00, 02] @@ -23,6 +24,7 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 0, 7) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: c1 Function name: sort_groups::generic_fn:: Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 11, 01, 01, 0c, 05, 01, 0d, 02, 06, 02, 02, 06, 00, 07, 01, 01, 01, 00, 02] @@ -36,6 +38,7 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 0, 7) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: c1 Function name: sort_groups::generic_fn:: Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 11, 01, 01, 0c, 05, 01, 0d, 02, 06, 02, 02, 06, 00, 07, 01, 01, 01, 00, 02] @@ -49,6 +52,7 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 0, 7) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: c1 Function name: sort_groups::main Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 06, 01, 04, 23, 05, 04, 24, 02, 06, 02, 02, 06, 00, 07, 01, 01, 05, 02, 02] @@ -62,6 +66,7 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 0, 7) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 5) to (start + 2, 2) +Highest counter ID seen: c1 Function name: sort_groups::other_fn Raw bytes (9): 0x[01, 01, 00, 01, 01, 17, 01, 00, 11] @@ -70,4 +75,5 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 23, 1) to (start + 0, 17) +Highest counter ID seen: c0 diff --git a/tests/coverage/test_harness.cov-map b/tests/coverage/test_harness.cov-map index f75328b11c9..b513b3d0549 100644 --- a/tests/coverage/test_harness.cov-map +++ b/tests/coverage/test_harness.cov-map @@ -5,6 +5,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 10, 1) to (start + 0, 16) +Highest counter ID seen: c0 Function name: test_harness::unused (unused) Raw bytes (9): 0x[01, 01, 00, 01, 00, 07, 01, 00, 0f] @@ -13,4 +14,5 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 7, 1) to (start + 0, 15) +Highest counter ID seen: (none) diff --git a/tests/coverage/tight_inf_loop.cov-map b/tests/coverage/tight_inf_loop.cov-map index 7fe3146b080..2d2d59bf013 100644 --- a/tests/coverage/tight_inf_loop.cov-map +++ b/tests/coverage/tight_inf_loop.cov-map @@ -9,4 +9,5 @@ Number of file 0 mappings: 3 - Code(Zero) at (prev + 2, 9) to (start + 0, 16) - Code(Expression(0, Sub)) at (prev + 1, 6) to (start + 1, 2) = (c0 - Zero) +Highest counter ID seen: c0 diff --git a/tests/coverage/trivial.cov-map b/tests/coverage/trivial.cov-map index 874e294a1c4..05f64896d9e 100644 --- a/tests/coverage/trivial.cov-map +++ b/tests/coverage/trivial.cov-map @@ -5,4 +5,5 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 3, 1) to (start + 0, 13) +Highest counter ID seen: c0 diff --git a/tests/coverage/try_error_result.cov-map b/tests/coverage/try_error_result.cov-map index 11a99f5395e..246a1ba738b 100644 --- a/tests/coverage/try_error_result.cov-map +++ b/tests/coverage/try_error_result.cov-map @@ -10,6 +10,7 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 2, 13) to (start + 0, 26) = (c0 - c1) - Code(Counter(0)) at (prev + 2, 5) to (start + 0, 6) +Highest counter ID seen: c1 Function name: ::call Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 34, 05, 01, 18, 05, 02, 0d, 00, 14, 02, 02, 0d, 00, 13, 01, 02, 05, 00, 06] @@ -23,6 +24,7 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 2, 13) to (start + 0, 19) = (c0 - c1) - Code(Counter(0)) at (prev + 2, 5) to (start + 0, 6) +Highest counter ID seen: c1 Function name: try_error_result::call Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 05, 01, 01, 14, 05, 02, 09, 00, 10, 02, 02, 09, 00, 0f, 01, 02, 01, 00, 02] @@ -36,6 +38,7 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 15) = (c0 - c1) - Code(Counter(0)) at (prev + 2, 1) to (start + 0, 2) +Highest counter ID seen: c1 Function name: try_error_result::main Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 71, 01, 02, 0c, 05, 03, 05, 00, 06, 02, 02, 05, 00, 0b, 01, 01, 01, 00, 02] @@ -49,6 +52,7 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 0, 11) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: c1 Function name: try_error_result::test1 Raw bytes (75): 0x[01, 01, 08, 01, 07, 00, 09, 03, 0d, 12, 1d, 03, 0d, 1b, 0d, 1f, 00, 11, 00, 0b, 01, 0d, 01, 02, 17, 03, 07, 09, 00, 0e, 12, 02, 09, 04, 1a, 1d, 06, 0d, 00, 29, 11, 00, 29, 00, 2a, 00, 01, 0d, 00, 2a, 00, 00, 2a, 00, 2b, 0e, 04, 0d, 00, 2a, 00, 00, 2a, 00, 2b, 0d, 03, 05, 00, 0b, 17, 01, 01, 00, 02] @@ -79,6 +83,7 @@ Number of file 0 mappings: 11 - Code(Counter(3)) at (prev + 3, 5) to (start + 0, 11) - Code(Expression(5, Add)) at (prev + 1, 1) to (start + 0, 2) = (((c4 + Zero) + Zero) + c3) +Highest counter ID seen: c7 Function name: try_error_result::test2 Raw bytes (358): 0x[01, 01, 3b, 01, 07, 05, 09, 03, 0d, 41, 11, 4a, 15, 41, 11, 42, 1d, 46, 19, 4a, 15, 41, 11, 4a, 15, 41, 11, 46, 19, 4a, 15, 41, 11, 42, 1d, 46, 19, 4a, 15, 41, 11, 5e, 25, 49, 21, 49, 21, 5e, 25, 49, 21, 8a, 01, 2d, 8e, 01, 29, 92, 01, 41, 03, 0d, 92, 01, 41, 03, 0d, 8e, 01, 29, 92, 01, 41, 03, 0d, 8a, 01, 2d, 8e, 01, 29, 92, 01, 41, 03, 0d, a6, 01, 35, 45, 31, 45, 31, a6, 01, 35, 45, 31, ba, 01, 3d, 4d, 39, 4d, 39, ba, 01, 3d, 4d, 39, c3, 01, 0d, c7, 01, db, 01, cb, 01, cf, 01, 11, 15, d3, 01, d7, 01, 19, 1d, 21, 25, df, 01, e3, 01, 29, 2d, e7, 01, eb, 01, 31, 35, 39, 3d, 28, 01, 3d, 01, 03, 17, 03, 08, 09, 00, 0e, 92, 01, 02, 09, 04, 1a, 41, 06, 0d, 00, 2f, 11, 00, 2f, 00, 30, 4a, 00, 31, 03, 35, 15, 04, 11, 00, 12, 46, 02, 11, 04, 12, 3e, 05, 11, 00, 14, 46, 00, 17, 00, 41, 19, 00, 41, 00, 42, 42, 00, 43, 00, 5f, 1d, 00, 5f, 00, 60, 3e, 01, 0d, 00, 20, 5a, 01, 11, 00, 14, 49, 00, 17, 00, 41, 21, 00, 41, 00, 42, 5e, 00, 43, 00, 60, 25, 00, 60, 00, 61, 5a, 01, 0d, 00, 20, 86, 01, 04, 11, 00, 14, 8e, 01, 00, 17, 00, 42, 29, 00, 42, 00, 43, 8a, 01, 00, 44, 00, 61, 2d, 00, 61, 00, 62, 86, 01, 01, 0d, 00, 20, a2, 01, 01, 11, 00, 14, 45, 00, 17, 01, 36, 31, 01, 36, 00, 37, a6, 01, 01, 12, 00, 2f, 35, 00, 2f, 00, 30, a2, 01, 01, 0d, 00, 20, b6, 01, 01, 11, 00, 14, 4d, 00, 17, 01, 36, 39, 02, 11, 00, 12, ba, 01, 01, 12, 00, 2f, 3d, 01, 11, 00, 12, b6, 01, 02, 0d, 00, 20, 0d, 03, 05, 00, 0b, bf, 01, 01, 01, 00, 02] @@ -207,4 +212,5 @@ Number of file 0 mappings: 40 - Code(Counter(3)) at (prev + 3, 5) to (start + 0, 11) - Code(Expression(47, Add)) at (prev + 1, 1) to (start + 0, 2) = ((((c4 + c5) + ((c6 + c7) + (c8 + c9))) + ((c10 + c11) + ((c12 + c13) + (c14 + c15)))) + c3) +Highest counter ID seen: c19 diff --git a/tests/coverage/unicode.cov-map b/tests/coverage/unicode.cov-map index 06a2c930498..ac4e691ea7a 100644 --- a/tests/coverage/unicode.cov-map +++ b/tests/coverage/unicode.cov-map @@ -22,6 +22,7 @@ Number of file 0 mappings: 9 = ((c0 - c2) + c3) - Code(Expression(3, Add)) at (prev + 2, 5) to (start + 1, 2) = (c4 + ((c0 - c2) + c3)) +Highest counter ID seen: c4 Function name: unicode::他 (unused) Raw bytes (9): 0x[01, 01, 00, 01, 00, 1e, 19, 00, 25] @@ -30,6 +31,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 30, 25) to (start + 0, 37) +Highest counter ID seen: (none) Function name: unicode::申し訳ございません Raw bytes (9): 0x[01, 01, 00, 01, 01, 18, 01, 02, 02] @@ -38,4 +40,5 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 24, 1) to (start + 2, 2) +Highest counter ID seen: c0 diff --git a/tests/coverage/unreachable.cov-map b/tests/coverage/unreachable.cov-map index 09d3b234543..d4a5936a784 100644 --- a/tests/coverage/unreachable.cov-map +++ b/tests/coverage/unreachable.cov-map @@ -5,6 +5,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 15, 39) to (start + 0, 71) +Highest counter ID seen: (none) Function name: unreachable::unreachable_function (unused) Raw bytes (9): 0x[01, 01, 00, 01, 00, 11, 01, 01, 25] @@ -13,6 +14,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 17, 1) to (start + 1, 37) +Highest counter ID seen: (none) Function name: unreachable::unreachable_intrinsic (unused) Raw bytes (9): 0x[01, 01, 00, 01, 00, 16, 01, 01, 2c] @@ -21,4 +23,5 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 22, 1) to (start + 1, 44) +Highest counter ID seen: (none) diff --git a/tests/coverage/unused.cov-map b/tests/coverage/unused.cov-map index 9383d1e90ac..9f1ad59ce83 100644 --- a/tests/coverage/unused.cov-map +++ b/tests/coverage/unused.cov-map @@ -17,6 +17,7 @@ Number of file 0 mappings: 6 - Code(Expression(3, Add)) at (prev + 1, 9) to (start + 0, 15) = (c1 + c2) - Code(Counter(3)) at (prev + 2, 1) to (start + 0, 2) +Highest counter ID seen: c3 Function name: unused::foo:: Raw bytes (42): 0x[01, 01, 04, 01, 0f, 05, 09, 03, 0d, 05, 09, 06, 01, 03, 01, 01, 12, 03, 02, 0b, 00, 11, 0a, 01, 09, 00, 0f, 09, 00, 13, 00, 19, 0f, 01, 09, 00, 0f, 0d, 02, 01, 00, 02] @@ -37,6 +38,7 @@ Number of file 0 mappings: 6 - Code(Expression(3, Add)) at (prev + 1, 9) to (start + 0, 15) = (c1 + c2) - Code(Counter(3)) at (prev + 2, 1) to (start + 0, 2) +Highest counter ID seen: c3 Function name: unused::main Raw bytes (9): 0x[01, 01, 00, 01, 01, 25, 01, 04, 02] @@ -45,6 +47,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 37, 1) to (start + 4, 2) +Highest counter ID seen: c0 Function name: unused::unused_func (unused) Raw bytes (24): 0x[01, 01, 00, 04, 00, 13, 01, 01, 0e, 00, 01, 0f, 02, 06, 00, 02, 06, 00, 07, 00, 01, 01, 00, 02] @@ -56,6 +59,7 @@ Number of file 0 mappings: 4 - Code(Zero) at (prev + 1, 15) to (start + 2, 6) - Code(Zero) at (prev + 2, 6) to (start + 0, 7) - Code(Zero) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: (none) Function name: unused::unused_func2 (unused) Raw bytes (24): 0x[01, 01, 00, 04, 00, 19, 01, 01, 0e, 00, 01, 0f, 02, 06, 00, 02, 06, 00, 07, 00, 01, 01, 00, 02] @@ -67,6 +71,7 @@ Number of file 0 mappings: 4 - Code(Zero) at (prev + 1, 15) to (start + 2, 6) - Code(Zero) at (prev + 2, 6) to (start + 0, 7) - Code(Zero) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: (none) Function name: unused::unused_func3 (unused) Raw bytes (24): 0x[01, 01, 00, 04, 00, 1f, 01, 01, 0e, 00, 01, 0f, 02, 06, 00, 02, 06, 00, 07, 00, 01, 01, 00, 02] @@ -78,6 +83,7 @@ Number of file 0 mappings: 4 - Code(Zero) at (prev + 1, 15) to (start + 2, 6) - Code(Zero) at (prev + 2, 6) to (start + 0, 7) - Code(Zero) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: (none) Function name: unused::unused_template_func::<_> (unused) Raw bytes (34): 0x[01, 01, 00, 06, 00, 0b, 01, 01, 12, 00, 02, 0b, 00, 11, 00, 01, 09, 00, 0f, 00, 00, 13, 00, 19, 00, 01, 09, 00, 0f, 00, 02, 01, 00, 02] @@ -91,4 +97,5 @@ Number of file 0 mappings: 6 - Code(Zero) at (prev + 0, 19) to (start + 0, 25) - Code(Zero) at (prev + 1, 9) to (start + 0, 15) - Code(Zero) at (prev + 2, 1) to (start + 0, 2) +Highest counter ID seen: (none) diff --git a/tests/coverage/unused_mod.cov-map b/tests/coverage/unused_mod.cov-map index 241cb2610ff..af10906fa3c 100644 --- a/tests/coverage/unused_mod.cov-map +++ b/tests/coverage/unused_mod.cov-map @@ -5,6 +5,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 4, 1) to (start + 2, 2) +Highest counter ID seen: c0 Function name: unused_mod::unused_module::never_called_function (unused) Raw bytes (9): 0x[01, 01, 00, 01, 00, 02, 01, 02, 02] @@ -13,4 +14,5 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 2, 1) to (start + 2, 2) +Highest counter ID seen: (none) diff --git a/tests/coverage/uses_crate.cov-map b/tests/coverage/uses_crate.cov-map index 9c06eab7005..5c23f882697 100644 --- a/tests/coverage/uses_crate.cov-map +++ b/tests/coverage/uses_crate.cov-map @@ -5,6 +5,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 27, 1) to (start + 2, 2) +Highest counter ID seen: c0 Function name: used_crate::used_only_from_bin_crate_generic_function::<&alloc::vec::Vec> Raw bytes (9): 0x[01, 01, 00, 01, 01, 13, 01, 02, 02] @@ -13,6 +14,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 19, 1) to (start + 2, 2) +Highest counter ID seen: c0 Function name: used_crate::used_only_from_bin_crate_generic_function::<&str> Raw bytes (9): 0x[01, 01, 00, 01, 01, 13, 01, 02, 02] @@ -21,6 +23,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 19, 1) to (start + 2, 2) +Highest counter ID seen: c0 Function name: used_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function::<&str> Raw bytes (9): 0x[01, 01, 00, 01, 01, 1f, 01, 02, 02] @@ -29,6 +32,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 31, 1) to (start + 2, 2) +Highest counter ID seen: c0 Function name: uses_crate::main Raw bytes (9): 0x[01, 02, 00, 01, 01, 0c, 01, 07, 02] @@ -37,4 +41,5 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 12, 1) to (start + 7, 2) +Highest counter ID seen: c0 diff --git a/tests/coverage/uses_inline_crate.cov-map b/tests/coverage/uses_inline_crate.cov-map index 55ceb46b060..a6909768162 100644 --- a/tests/coverage/uses_inline_crate.cov-map +++ b/tests/coverage/uses_inline_crate.cov-map @@ -5,6 +5,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 44, 1) to (start + 2, 2) +Highest counter ID seen: c0 Function name: used_inline_crate::used_inline_function Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 14, 01, 06, 0f, 05, 06, 10, 02, 06, 02, 02, 06, 00, 07, 01, 01, 05, 01, 02] @@ -18,6 +19,7 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 0, 7) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 5) to (start + 1, 2) +Highest counter ID seen: c1 Function name: used_inline_crate::used_only_from_bin_crate_generic_function::<&alloc::vec::Vec> Raw bytes (9): 0x[01, 01, 00, 01, 01, 21, 01, 02, 02] @@ -26,6 +28,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 33, 1) to (start + 2, 2) +Highest counter ID seen: c0 Function name: used_inline_crate::used_only_from_bin_crate_generic_function::<&str> Raw bytes (9): 0x[01, 01, 00, 01, 01, 21, 01, 02, 02] @@ -34,6 +37,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 33, 1) to (start + 2, 2) +Highest counter ID seen: c0 Function name: used_inline_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function::<&str> Raw bytes (9): 0x[01, 01, 00, 01, 01, 31, 01, 02, 02] @@ -42,6 +46,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 49, 1) to (start + 2, 2) +Highest counter ID seen: c0 Function name: uses_inline_crate::main Raw bytes (9): 0x[01, 02, 00, 01, 01, 0c, 01, 0a, 02] @@ -50,4 +55,5 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 12, 1) to (start + 10, 2) +Highest counter ID seen: c0 diff --git a/tests/coverage/while.cov-map b/tests/coverage/while.cov-map index 4d813a935a0..29493a651dc 100644 --- a/tests/coverage/while.cov-map +++ b/tests/coverage/while.cov-map @@ -10,4 +10,5 @@ Number of file 0 mappings: 4 = (c0 + Zero) - Code(Zero) at (prev + 0, 21) to (start + 2, 6) - Code(Counter(0)) at (prev + 3, 1) to (start + 0, 2) +Highest counter ID seen: c0 diff --git a/tests/coverage/while_early_ret.cov-map b/tests/coverage/while_early_ret.cov-map index c883eb4baf2..6254dfbcf01 100644 --- a/tests/coverage/while_early_ret.cov-map +++ b/tests/coverage/while_early_ret.cov-map @@ -23,4 +23,5 @@ Number of file 0 mappings: 9 - Code(Counter(2)) at (prev + 6, 5) to (start + 0, 11) - Code(Expression(4, Add)) at (prev + 1, 1) to (start + 0, 2) = ((c3 + c4) + c2) +Highest counter ID seen: c4 diff --git a/tests/coverage/yield.cov-map b/tests/coverage/yield.cov-map index a273c688e24..578994a4530 100644 --- a/tests/coverage/yield.cov-map +++ b/tests/coverage/yield.cov-map @@ -39,6 +39,7 @@ Number of file 0 mappings: 16 - Code(Expression(10, Add)) at (prev + 1, 14) to (start + 0, 52) = (c9 + c10) - Code(Counter(11)) at (prev + 2, 1) to (start + 0, 2) +Highest counter ID seen: c11 Function name: yield::main::{closure#0} Raw bytes (14): 0x[01, 01, 00, 02, 01, 09, 08, 01, 10, 05, 02, 10, 01, 06] @@ -48,6 +49,7 @@ Number of expressions: 0 Number of file 0 mappings: 2 - Code(Counter(0)) at (prev + 9, 8) to (start + 1, 16) - Code(Counter(1)) at (prev + 2, 16) to (start + 1, 6) +Highest counter ID seen: c1 Function name: yield::main::{closure#1} Raw bytes (24): 0x[01, 01, 00, 04, 01, 18, 08, 01, 10, 05, 02, 09, 00, 10, 09, 01, 09, 00, 10, 0d, 01, 10, 01, 06] @@ -59,4 +61,5 @@ Number of file 0 mappings: 4 - Code(Counter(1)) at (prev + 2, 9) to (start + 0, 16) - Code(Counter(2)) at (prev + 1, 9) to (start + 0, 16) - Code(Counter(3)) at (prev + 1, 16) to (start + 1, 6) +Highest counter ID seen: c3 From 78fd3b53190857d851fbdab06b3b9fa9bd638292 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Fri, 11 Oct 2024 13:13:24 +1100 Subject: [PATCH 190/357] Extract auxiliary-crate properties to their own module/struct --- src/tools/compiletest/src/header.rs | 40 ++++------------- src/tools/compiletest/src/header/auxiliary.rs | 44 +++++++++++++++++++ src/tools/compiletest/src/runtest.rs | 18 ++++---- 3 files changed, 62 insertions(+), 40 deletions(-) create mode 100644 src/tools/compiletest/src/header/auxiliary.rs diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index bd0ed6321bc..caae87393ff 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -9,11 +9,13 @@ use std::process::Command; use tracing::*; use crate::common::{Config, Debugger, FailMode, Mode, PassMode}; +use crate::header::auxiliary::{AuxProps, parse_and_update_aux}; use crate::header::cfg::{MatchOutcome, parse_cfg_name_directive}; use crate::header::needs::CachedNeedsConditions; use crate::util::static_regex; use crate::{extract_cdb_version, extract_gdb_version}; +pub(crate) mod auxiliary; mod cfg; mod needs; #[cfg(test)] @@ -98,18 +100,8 @@ pub struct TestProps { // If present, the name of a file that this test should match when // pretty-printed pub pp_exact: Option, - // Other crates that should be compiled (typically from the same - // directory as the test, but for backwards compatibility reasons - // we also check the auxiliary directory) - pub aux_builds: Vec, - // Auxiliary crates that should be compiled as `#![crate_type = "bin"]`. - pub aux_bins: Vec, - // Similar to `aux_builds`, but a list of NAME=somelib.rs of dependencies - // to build and pass with the `--extern` flag. - pub aux_crates: Vec<(String, String)>, - /// Similar to `aux_builds`, but also passes the resulting dylib path to - /// `-Zcodegen-backend`. - pub aux_codegen_backend: Option, + /// Auxiliary crates that should be built and made available to this test. + pub(crate) aux: AuxProps, // Environment settings to use for compiling pub rustc_env: Vec<(String, String)>, // Environment variables to unset prior to compiling. @@ -276,10 +268,7 @@ impl TestProps { run_flags: vec![], doc_flags: vec![], pp_exact: None, - aux_builds: vec![], - aux_bins: vec![], - aux_crates: vec![], - aux_codegen_backend: None, + aux: Default::default(), revisions: vec![], rustc_env: vec![ ("RUSTC_ICE".to_string(), "0".to_string()), @@ -454,21 +443,10 @@ impl TestProps { PRETTY_COMPARE_ONLY, &mut self.pretty_compare_only, ); - config.push_name_value_directive(ln, AUX_BUILD, &mut self.aux_builds, |r| { - r.trim().to_string() - }); - config.push_name_value_directive(ln, AUX_BIN, &mut self.aux_bins, |r| { - r.trim().to_string() - }); - config.push_name_value_directive( - ln, - AUX_CRATE, - &mut self.aux_crates, - Config::parse_aux_crate, - ); - if let Some(r) = config.parse_name_value_directive(ln, AUX_CODEGEN_BACKEND) { - self.aux_codegen_backend = Some(r.trim().to_owned()); - } + + // Call a helper method to deal with aux-related directives. + parse_and_update_aux(config, ln, &mut self.aux); + config.push_name_value_directive( ln, EXEC_ENV, diff --git a/src/tools/compiletest/src/header/auxiliary.rs b/src/tools/compiletest/src/header/auxiliary.rs new file mode 100644 index 00000000000..2a94622264a --- /dev/null +++ b/src/tools/compiletest/src/header/auxiliary.rs @@ -0,0 +1,44 @@ +//! Code for dealing with test directives that request an "auxiliary" crate to +//! be built and made available to the test in some way. + +use crate::common::Config; +use crate::header::directives::{AUX_BIN, AUX_BUILD, AUX_CODEGEN_BACKEND, AUX_CRATE}; + +/// Properties parsed from `aux-*` test directives. +#[derive(Clone, Debug, Default)] +pub(crate) struct AuxProps { + /// Other crates that should be built and made available to this test. + /// These are filenames relative to `./auxiliary/` in the test's directory. + pub(crate) builds: Vec, + /// Auxiliary crates that should be compiled as `#![crate_type = "bin"]`. + pub(crate) bins: Vec, + /// Similar to `builds`, but a list of NAME=somelib.rs of dependencies + /// to build and pass with the `--extern` flag. + pub(crate) crates: Vec<(String, String)>, + /// Similar to `builds`, but also uses the resulting dylib as a + /// `-Zcodegen-backend` when compiling the test file. + pub(crate) codegen_backend: Option, +} + +/// If the given test directive line contains an `aux-*` directive, parse it +/// and update [`AuxProps`] accordingly. +pub(super) fn parse_and_update_aux(config: &Config, ln: &str, aux: &mut AuxProps) { + if !ln.starts_with("aux-") { + return; + } + + config.push_name_value_directive(ln, AUX_BUILD, &mut aux.builds, |r| r.trim().to_string()); + config.push_name_value_directive(ln, AUX_BIN, &mut aux.bins, |r| r.trim().to_string()); + config.push_name_value_directive(ln, AUX_CRATE, &mut aux.crates, parse_aux_crate); + if let Some(r) = config.parse_name_value_directive(ln, AUX_CODEGEN_BACKEND) { + aux.codegen_backend = Some(r.trim().to_owned()); + } +} + +fn parse_aux_crate(r: String) -> (String, String) { + let mut parts = r.trim().splitn(2, '='); + ( + parts.next().expect("missing aux-crate name (e.g. log=log.rs)").to_string(), + parts.next().expect("missing aux-crate value (e.g. log=log.rs)").to_string(), + ) +} diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 1baf0c56e37..46f7b9c0e7d 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -841,13 +841,13 @@ impl<'test> TestCx<'test> { /// Auxiliaries, no matter how deep, have the same root_out_dir and root_testpaths. fn document(&self, root_out_dir: &Path, root_testpaths: &TestPaths) -> ProcRes { if self.props.build_aux_docs { - for rel_ab in &self.props.aux_builds { + for rel_ab in &self.props.aux.builds { let aux_testpaths = self.compute_aux_test_paths(root_testpaths, rel_ab); - let aux_props = + let props_for_aux = self.props.from_aux_file(&aux_testpaths.file, self.revision, self.config); let aux_cx = TestCx { config: self.config, - props: &aux_props, + props: &props_for_aux, testpaths: &aux_testpaths, revision: self.revision, }; @@ -1059,11 +1059,11 @@ impl<'test> TestCx<'test> { fn aux_output_dir(&self) -> PathBuf { let aux_dir = self.aux_output_dir_name(); - if !self.props.aux_builds.is_empty() { + if !self.props.aux.builds.is_empty() { remove_and_create_dir_all(&aux_dir); } - if !self.props.aux_bins.is_empty() { + if !self.props.aux.bins.is_empty() { let aux_bin_dir = self.aux_bin_output_dir_name(); remove_and_create_dir_all(&aux_dir); remove_and_create_dir_all(&aux_bin_dir); @@ -1073,15 +1073,15 @@ impl<'test> TestCx<'test> { } fn build_all_auxiliary(&self, of: &TestPaths, aux_dir: &Path, rustc: &mut Command) { - for rel_ab in &self.props.aux_builds { + for rel_ab in &self.props.aux.builds { self.build_auxiliary(of, rel_ab, &aux_dir, false /* is_bin */); } - for rel_ab in &self.props.aux_bins { + for rel_ab in &self.props.aux.bins { self.build_auxiliary(of, rel_ab, &aux_dir, true /* is_bin */); } - for (aux_name, aux_path) in &self.props.aux_crates { + for (aux_name, aux_path) in &self.props.aux.crates { let aux_type = self.build_auxiliary(of, &aux_path, &aux_dir, false /* is_bin */); let lib_name = get_lib_name(&aux_path.trim_end_matches(".rs").replace('-', "_"), aux_type); @@ -1097,7 +1097,7 @@ impl<'test> TestCx<'test> { // Build any `//@ aux-codegen-backend`, and pass the resulting library // to `-Zcodegen-backend` when compiling the test file. - if let Some(aux_file) = &self.props.aux_codegen_backend { + if let Some(aux_file) = &self.props.aux.codegen_backend { let aux_type = self.build_auxiliary(of, aux_file, aux_dir, false); if let Some(lib_name) = get_lib_name(aux_file.trim_end_matches(".rs"), aux_type) { let lib_path = aux_dir.join(&lib_name); From 188f7ce91b2a69988846a6af5adb7807434940b6 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Fri, 11 Oct 2024 13:19:08 +1100 Subject: [PATCH 191/357] Use the same `AuxProps` parser for `EarlyProps` --- src/tools/compiletest/src/header.rs | 31 ++++------------------- src/tools/compiletest/src/header/tests.rs | 3 ++- src/tools/compiletest/src/lib.rs | 3 ++- 3 files changed, 9 insertions(+), 28 deletions(-) diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index caae87393ff..63d05886166 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -35,9 +35,10 @@ impl HeadersCache { /// the test. #[derive(Default)] pub struct EarlyProps { - pub aux: Vec, - pub aux_bin: Vec, - pub aux_crate: Vec<(String, String)>, + /// Auxiliary crates that should be built and made available to this test. + /// Included in [`EarlyProps`] so that the indicated files can participate + /// in up-to-date checking. Building happens via [`TestProps::aux`] instead. + pub(crate) aux: AuxProps, pub revisions: Vec, } @@ -57,21 +58,7 @@ impl EarlyProps { testfile, rdr, &mut |HeaderLine { directive: ln, .. }| { - config.push_name_value_directive(ln, directives::AUX_BUILD, &mut props.aux, |r| { - r.trim().to_string() - }); - config.push_name_value_directive( - ln, - directives::AUX_BIN, - &mut props.aux_bin, - |r| r.trim().to_string(), - ); - config.push_name_value_directive( - ln, - directives::AUX_CRATE, - &mut props.aux_crate, - Config::parse_aux_crate, - ); + parse_and_update_aux(config, ln, &mut props.aux); config.parse_and_update_revisions(ln, &mut props.revisions); }, ); @@ -920,14 +907,6 @@ fn iter_header( } impl Config { - fn parse_aux_crate(r: String) -> (String, String) { - let mut parts = r.trim().splitn(2, '='); - ( - parts.next().expect("missing aux-crate name (e.g. log=log.rs)").to_string(), - parts.next().expect("missing aux-crate value (e.g. log=log.rs)").to_string(), - ) - } - fn parse_and_update_revisions(&self, line: &str, existing: &mut Vec) { if let Some(raw) = self.parse_name_value_directive(line, "revisions") { let mut duplicates: HashSet<_> = existing.iter().cloned().collect(); diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs index 10ec2a1806f..22dfa349e2b 100644 --- a/src/tools/compiletest/src/header/tests.rs +++ b/src/tools/compiletest/src/header/tests.rs @@ -242,7 +242,8 @@ fn aux_build() { //@ aux-build: b.rs " ) - .aux, + .aux + .builds, vec!["a.rs", "b.rs"], ); } diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index 98375a21b04..30215c0bbe6 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -862,7 +862,8 @@ fn files_related_to_test( related.push(testpaths.file.clone()); } - for aux in &props.aux { + for aux in &props.aux.builds { + // FIXME(Zalathar): Perform all `auxiliary` path resolution in one place. let path = testpaths.file.parent().unwrap().join("auxiliary").join(aux); related.push(path); } From ec662b9c09ce9f472613a066dd42ae7bd7242e00 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Fri, 11 Oct 2024 20:05:12 +1100 Subject: [PATCH 192/357] Include all kinds of auxiliary crates in the up-to-date timestamp This was previously only including ordinary `aux-build` crates, and not files associated with the other three kinds of auxiliary crate. --- src/tools/compiletest/src/header/auxiliary.rs | 16 ++++++++++++++++ src/tools/compiletest/src/lib.rs | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/tools/compiletest/src/header/auxiliary.rs b/src/tools/compiletest/src/header/auxiliary.rs index 2a94622264a..6f6538ce196 100644 --- a/src/tools/compiletest/src/header/auxiliary.rs +++ b/src/tools/compiletest/src/header/auxiliary.rs @@ -1,6 +1,8 @@ //! Code for dealing with test directives that request an "auxiliary" crate to //! be built and made available to the test in some way. +use std::iter; + use crate::common::Config; use crate::header::directives::{AUX_BIN, AUX_BUILD, AUX_CODEGEN_BACKEND, AUX_CRATE}; @@ -20,6 +22,20 @@ pub(crate) struct AuxProps { pub(crate) codegen_backend: Option, } +impl AuxProps { + /// Yields all of the paths (relative to `./auxiliary/`) that have been + /// specified in `aux-*` directives for this test. + pub(crate) fn all_aux_path_strings(&self) -> impl Iterator { + let Self { builds, bins, crates, codegen_backend } = self; + + iter::empty() + .chain(builds.iter().map(String::as_str)) + .chain(bins.iter().map(String::as_str)) + .chain(crates.iter().map(|(_, path)| path.as_str())) + .chain(codegen_backend.iter().map(String::as_str)) + } +} + /// If the given test directive line contains an `aux-*` directive, parse it /// and update [`AuxProps`] accordingly. pub(super) fn parse_and_update_aux(config: &Config, ln: &str, aux: &mut AuxProps) { diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index 30215c0bbe6..30d1644b148 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -862,7 +862,7 @@ fn files_related_to_test( related.push(testpaths.file.clone()); } - for aux in &props.aux.builds { + for aux in props.aux.all_aux_path_strings() { // FIXME(Zalathar): Perform all `auxiliary` path resolution in one place. let path = testpaths.file.parent().unwrap().join("auxiliary").join(aux); related.push(path); From ccdea3ee363ad579923ad33bf3fb027a78ed46c5 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 11 Oct 2024 12:38:58 +0200 Subject: [PATCH 193/357] simplify Tree Borrows write-during-2phase example --- .../fail/tree_borrows/write-during-2phase.rs | 13 ++++++++----- .../fail/tree_borrows/write-during-2phase.stderr | 15 +++++++-------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/tools/miri/tests/fail/tree_borrows/write-during-2phase.rs b/src/tools/miri/tests/fail/tree_borrows/write-during-2phase.rs index 3f8c9b6219a..a47bb671e32 100644 --- a/src/tools/miri/tests/fail/tree_borrows/write-during-2phase.rs +++ b/src/tools/miri/tests/fail/tree_borrows/write-during-2phase.rs @@ -16,12 +16,15 @@ impl Foo { pub fn main() { let mut f = Foo(0); - let inner = &mut f.0 as *mut u64; - let _res = f.add(unsafe { - let n = f.0; + let alias = &mut f.0 as *mut u64; + let res = f.add(unsafe { // This is the access at fault, but it's not immediately apparent because // the reference that got invalidated is not under a Protector. - *inner = 42; - n + *alias = 42; + 0 }); + // `res` could be optimized to be `0`, since at the time the reference for the `self` argument + // is created, it has value `0`, and then later we add `0` to that. But turns out there is + // a sneaky alias that's used to change the value of `*self` before it is read... + assert_eq!(res, 42); } diff --git a/src/tools/miri/tests/fail/tree_borrows/write-during-2phase.stderr b/src/tools/miri/tests/fail/tree_borrows/write-during-2phase.stderr index b85aac7db76..21178dad050 100644 --- a/src/tools/miri/tests/fail/tree_borrows/write-during-2phase.stderr +++ b/src/tools/miri/tests/fail/tree_borrows/write-during-2phase.stderr @@ -9,12 +9,12 @@ LL | fn add(&mut self, n: u64) -> u64 { help: the accessed tag was created here, in the initial state Reserved --> tests/fail/tree_borrows/write-during-2phase.rs:LL:CC | -LL | let _res = f.add(unsafe { - | ^ +LL | let res = f.add(unsafe { + | ^ help: the accessed tag later transitioned to Disabled due to a foreign write access at offsets [0x0..0x8] --> tests/fail/tree_borrows/write-during-2phase.rs:LL:CC | -LL | *inner = 42; +LL | *alias = 42; | ^^^^^^^^^^^ = help: this transition corresponds to a loss of read and write permissions = note: BACKTRACE (of the first span): @@ -22,13 +22,12 @@ LL | *inner = 42; note: inside `main` --> tests/fail/tree_borrows/write-during-2phase.rs:LL:CC | -LL | let _res = f.add(unsafe { - | ________________^ -LL | | let n = f.0; +LL | let res = f.add(unsafe { + | _______________^ LL | | // This is the access at fault, but it's not immediately apparent because LL | | // the reference that got invalidated is not under a Protector. -LL | | *inner = 42; -LL | | n +LL | | *alias = 42; +LL | | 0 LL | | }); | |______^ From 5fd7be97e97cb41170c9bbc7f5359886374bea01 Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 11 Oct 2024 10:40:36 +0000 Subject: [PATCH 194/357] remove outdated FIXMEs --- .../src/solve/eval_ctxt/canonical.rs | 1 - .../src/solve/eval_ctxt/mod.rs | 2 +- compiler/rustc_next_trait_solver/src/solve/mod.rs | 3 --- .../src/solve/normalizes_to/mod.rs | 2 +- .../rustc_next_trait_solver/src/solve/trait_goals.rs | 11 ++--------- compiler/rustc_trait_selection/src/solve/delegate.rs | 2 ++ 6 files changed, 6 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs index 3b6197c6759..fdefec33eeb 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs @@ -444,7 +444,6 @@ where for &arg in &state.value.var_values.var_values.as_slice() [orig_values.len()..state.value.var_values.len()] { - // FIXME: This is so ugly. let unconstrained = delegate.fresh_var_for_kind_with_span(arg, span); orig_values.push(unconstrained); } diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index 8391cdb2ca1..458edf920ab 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -92,7 +92,6 @@ where #[derive_where(Clone, Debug, Default; I: Interner)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] #[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] -// FIXME: This can be made crate-private once `EvalCtxt` also lives in this crate. struct NestedGoals { /// These normalizes-to goals are treated specially during the evaluation /// loop. In each iteration we take the RHS of the projection, replace it with @@ -421,6 +420,7 @@ where let (normalization_nested_goals, certainty) = self.instantiate_and_apply_query_response(goal.param_env, orig_values, response); self.inspect.goal_evaluation(goal_evaluation); + // FIXME: We previously had an assert here that checked that recomputing // a goal after applying its constraints did not change its response. // diff --git a/compiler/rustc_next_trait_solver/src/solve/mod.rs b/compiler/rustc_next_trait_solver/src/solve/mod.rs index 97f7c71f3fc..8fe39bb4ee1 100644 --- a/compiler/rustc_next_trait_solver/src/solve/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/mod.rs @@ -10,9 +10,6 @@ //! //! For a high-level overview of how this solver works, check out the relevant //! section of the rustc-dev-guide. -//! -//! FIXME(@lcnr): Write that section. If you read this before then ask me -//! about it on zulip. mod alias_relate; mod assembly; diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs index fc9c634942b..005b293621a 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs @@ -899,7 +899,7 @@ where for ty in types.iter() { // We can't find the intersection if the types used are generic. // - // FIXME(effects) do we want to look at where clauses to get some + // FIXME(effects): do we want to look at where clauses to get some // clue for the case where generic types are being used? let Some(kind) = ty::EffectKind::try_from_ty(cx, ty) else { return Err(NoSolution); diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index 2074bdec485..5828b2ecf34 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -108,7 +108,6 @@ where ecx: &mut EvalCtxt<'_, D>, _guar: I::ErrorGuaranteed, ) -> Result, NoSolution> { - // FIXME: don't need to enter a probe here. ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc) .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)) } @@ -463,7 +462,6 @@ where // Async coroutine unconditionally implement `Future` // Technically, we need to check that the future output type is Sized, // but that's already proven by the coroutine being WF. - // FIXME: use `consider_implied` ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc) .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)) } @@ -489,7 +487,6 @@ where // Gen coroutines unconditionally implement `Iterator` // Technically, we need to check that the iterator output type is Sized, // but that's already proven by the coroutines being WF. - // FIXME: use `consider_implied` ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc) .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)) } @@ -512,8 +509,7 @@ where return Err(NoSolution); } - // Gen coroutines unconditionally implement `FusedIterator` - // FIXME: use `consider_implied` + // Gen coroutines unconditionally implement `FusedIterator`. ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc) .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)) } @@ -539,7 +535,6 @@ where // Gen coroutines unconditionally implement `Iterator` // Technically, we need to check that the iterator output type is Sized, // but that's already proven by the coroutines being WF. - // FIXME: use `consider_implied` ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc) .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)) } @@ -610,7 +605,7 @@ where return Err(NoSolution); } - // FIXME(-Znext-solver): Implement this when we get const working in the new solver + // FIXME(effects): Implement this when we get const working in the new solver // `Destruct` is automatically implemented for every type in // non-const environments. @@ -631,8 +626,6 @@ where return Err(NoSolution); } - // FIXME: This actually should destructure the `Result` we get from transmutability and - // register candidates. We probably need to register >1 since we may have an OR of ANDs. ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| { let certainty = ecx.is_transmutable( goal.param_env, diff --git a/compiler/rustc_trait_selection/src/solve/delegate.rs b/compiler/rustc_trait_selection/src/solve/delegate.rs index 5c344930314..df9ac2b80fd 100644 --- a/compiler/rustc_trait_selection/src/solve/delegate.rs +++ b/compiler/rustc_trait_selection/src/solve/delegate.rs @@ -223,6 +223,8 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate< if eligible { Ok(Some(node_item.item.def_id)) } else { Ok(None) } } + // FIXME: This actually should destructure the `Result` we get from transmutability and + // register candidates. We probably need to register >1 since we may have an OR of ANDs. fn is_transmutable( &self, param_env: ty::ParamEnv<'tcx>, From 9357277de7d452fb542abd0264e9d71bb2403c20 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Fri, 11 Oct 2024 21:44:36 +1100 Subject: [PATCH 195/357] coverage: Remove code related to LLVM 17 --- .../src/coverageinfo/mapgen.rs | 21 ++++++------------- .../llvm-wrapper/CoverageMappingWrapper.cpp | 2 +- 2 files changed, 7 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index 267a2244916..c2c261da79b 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -14,29 +14,20 @@ use crate::coverageinfo::ffi::CounterMappingRegion; use crate::coverageinfo::map_data::{FunctionCoverage, FunctionCoverageCollector}; use crate::{coverageinfo, llvm}; -/// Generates and exports the Coverage Map. +/// Generates and exports the coverage map, which is embedded in special +/// linker sections in the final binary. /// -/// Rust Coverage Map generation supports LLVM Coverage Mapping Format versions -/// 6 and 7 (encoded as 5 and 6 respectively), as described at -/// [LLVM Code Coverage Mapping Format](https://github.com/rust-lang/llvm-project/blob/rustc/18.0-2024-02-13/llvm/docs/CoverageMappingFormat.rst). -/// These versions are supported by the LLVM coverage tools (`llvm-profdata` and `llvm-cov`) -/// distributed in the `llvm-tools-preview` rustup component. -/// -/// Consequently, Rust's bundled version of Clang also generates Coverage Maps compliant with -/// the same version. Clang's implementation of Coverage Map generation was referenced when -/// implementing this Rust version, and though the format documentation is very explicit and -/// detailed, some undocumented details in Clang's implementation (that may or may not be important) -/// were also replicated for Rust's Coverage Map. +/// Those sections are then read and understood by LLVM's `llvm-cov` tool, +/// which is distributed in the `llvm-tools` rustup component. pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) { let tcx = cx.tcx; // Ensure that LLVM is using a version of the coverage mapping format that // agrees with our Rust-side code. Expected versions (encoded as n-1) are: - // - `CovMapVersion::Version6` (5) used by LLVM 13-17 - // - `CovMapVersion::Version7` (6) used by LLVM 18 + // - `CovMapVersion::Version7` (6) used by LLVM 18-19 let covmap_version = { let llvm_covmap_version = coverageinfo::mapping_version(); - let expected_versions = 5..=6; + let expected_versions = 6..=6; assert!( expected_versions.contains(&llvm_covmap_version), "Coverage mapping version exposed by `llvm-wrapper` is out of sync; \ diff --git a/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp index 8ee05977320..cda81d4a9b5 100644 --- a/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp @@ -183,7 +183,7 @@ extern "C" void LLVMRustCoverageWriteMappingToBuffer( RustMappingRegions, NumMappingRegions)) { MappingRegions.emplace_back( fromRust(Region.Count), fromRust(Region.FalseCount), -#if LLVM_VERSION_GE(18, 0) && LLVM_VERSION_LT(19, 0) +#if LLVM_VERSION_LT(19, 0) coverage::CounterMappingRegion::MCDCParameters{}, #endif Region.FileID, Region.ExpandedFileID, // File IDs, then region info. From b72dbd56caa4b5919bb1fc92fd915c9e9b4e952c Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Fri, 11 Oct 2024 09:39:06 +0300 Subject: [PATCH 196/357] move dummy commit logic into x86_64-gnu-llvm-18 Signed-off-by: onur-ozkan --- src/ci/docker/host-x86_64/mingw-check/Dockerfile | 12 ------------ src/ci/docker/scripts/x86_64-gnu-llvm.sh | 16 ++++++++++++++++ src/ci/github-actions/jobs.yml | 8 +++----- 3 files changed, 19 insertions(+), 17 deletions(-) diff --git a/src/ci/docker/host-x86_64/mingw-check/Dockerfile b/src/ci/docker/host-x86_64/mingw-check/Dockerfile index 467ca1dac67..0f8ebb987c3 100644 --- a/src/ci/docker/host-x86_64/mingw-check/Dockerfile +++ b/src/ci/docker/host-x86_64/mingw-check/Dockerfile @@ -47,18 +47,6 @@ ENV RUN_CHECK_WITH_PARALLEL_QUERIES 1 # We disable optimized compiler built-ins because that requires a C toolchain for the target. # We also skip the x86_64-unknown-linux-gnu target as it is well-tested by other jobs. ENV SCRIPT \ - # `core::builder::tests::ci_rustc_if_unchanged_logic` bootstrap test covers the `rust.download-rustc=if-unchanged` logic. - # Here we are adding a dummy commit on compiler and running that test to ensure when there is a change on the compiler, - # we never download ci rustc with `rust.download-rustc=if-unchanged` option. - echo \"\" >> ../compiler/rustc/src/main.rs && \ - git config --global user.email \"dummy@dummy.com\" && \ - git config --global user.name \"dummy\" && \ - git add ../compiler/rustc/src/main.rs && \ - git commit -m \"test commit for rust.download-rustc=if-unchanged logic\" && \ - DISABLE_CI_RUSTC_IF_INCOMPATIBLE=0 python3 ../x.py test bootstrap -- core::builder::tests::ci_rustc_if_unchanged_logic && \ - # Revert the dummy commit - git reset --hard HEAD~1 && \ - python3 ../x.py check --stage 0 --set build.optimized-compiler-builtins=false core alloc std --target=aarch64-unknown-linux-gnu,i686-pc-windows-msvc,i686-unknown-linux-gnu,x86_64-apple-darwin,x86_64-pc-windows-gnu,x86_64-pc-windows-msvc && \ /scripts/check-default-config-profiles.sh && \ python3 ../x.py check --target=i686-pc-windows-gnu --host=i686-pc-windows-gnu && \ diff --git a/src/ci/docker/scripts/x86_64-gnu-llvm.sh b/src/ci/docker/scripts/x86_64-gnu-llvm.sh index 98290f5a72c..dea38b6fd2a 100755 --- a/src/ci/docker/scripts/x86_64-gnu-llvm.sh +++ b/src/ci/docker/scripts/x86_64-gnu-llvm.sh @@ -2,6 +2,22 @@ set -ex +if [ "$READ_ONLY_SRC" = "0" ]; then + # `core::builder::tests::ci_rustc_if_unchanged_logic` bootstrap test ensures that + # "download-rustc=if-unchanged" logic don't use CI rustc while there are changes on + # compiler and/or library. Here we are adding a dummy commit on compiler and running + # that test to make sure we never download CI rustc with a change on the compiler tree. + echo "" >> ../compiler/rustc/src/main.rs + git config --global user.email "dummy@dummy.com" + git config --global user.name "dummy" + git add ../compiler/rustc/src/main.rs + git commit -m "test commit for rust.download-rustc=if-unchanged logic" + DISABLE_CI_RUSTC_IF_INCOMPATIBLE=0 ../x.py test bootstrap \ + -- core::builder::tests::ci_rustc_if_unchanged_logic + # Revert the dummy commit + git reset --hard HEAD~1 +fi + # Only run the stage 1 tests on merges, not on PR CI jobs. if [[ -z "${PR_CI_JOB}" ]]; then ../x.py --stage 1 test --skip src/tools/tidy diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index 4bbebbc4697..8f49f623afa 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -85,9 +85,6 @@ envs: # it in each job definition. pr: - image: mingw-check - env: - # We are adding (temporarily) a dummy commit on the compiler - READ_ONLY_SRC: "0" <<: *job-linux-4c - image: mingw-check-tidy continue_on_error: true @@ -95,6 +92,8 @@ pr: - image: x86_64-gnu-llvm-18 env: ENABLE_GCC_CODEGEN: "1" + # We are adding (temporarily) a dummy commit on the compiler + READ_ONLY_SRC: "0" <<: *job-linux-16c - image: x86_64-gnu-tools <<: *job-linux-16c @@ -210,8 +209,6 @@ auto: <<: *job-linux-8c - image: mingw-check - env: - READ_ONLY_SRC: 0 <<: *job-linux-4c - image: test-various @@ -264,6 +261,7 @@ auto: - image: x86_64-gnu-llvm-18 env: RUST_BACKTRACE: 1 + READ_ONLY_SRC: "0" <<: *job-linux-8c - image: x86_64-gnu-nopt From c085071631bd26227994fefeb4c34aa33e4d4cef Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 11 Oct 2024 11:24:14 -0400 Subject: [PATCH 197/357] Remove unadorned --- compiler/rustc_ast_passes/messages.ftl | 4 ++-- tests/rustdoc-json/fns/extern_safe.rs | 2 +- tests/ui/parser/fn-header-semantic-fail.rs | 4 ++-- tests/ui/parser/fn-header-semantic-fail.stderr | 8 ++++---- tests/ui/parser/no-const-fn-in-extern-block.rs | 2 +- tests/ui/parser/no-const-fn-in-extern-block.stderr | 4 ++-- ...fe-unsafe-on-unadorned-extern-block.edition2021.stderr | 8 ++++---- ...fe-unsafe-on-unadorned-extern-block.edition2024.stderr | 8 ++++---- .../safe-unsafe-on-unadorned-extern-block.rs | 4 ++-- .../unsafe-on-extern-block-issue-126756.fixed | 2 +- .../unsafe-on-extern-block-issue-126756.rs | 2 +- .../unsafe-on-extern-block-issue-126756.stderr | 4 ++-- 12 files changed, 26 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl index c361c35b723..f826e71b574 100644 --- a/compiler/rustc_ast_passes/messages.ftl +++ b/compiler/rustc_ast_passes/messages.ftl @@ -70,8 +70,8 @@ ast_passes_extern_fn_qualifiers = functions in `extern` blocks cannot have quali .label = in this `extern` block .suggestion = remove this qualifier -ast_passes_extern_invalid_safety = items in unadorned `extern` blocks cannot have safety qualifiers - .suggestion = add unsafe to this `extern` block +ast_passes_extern_invalid_safety = items in `extern` blocks without an `unsafe` qualifier cannot have safety qualifiers + .suggestion = add `unsafe` to this `extern` block ast_passes_extern_item_ascii = items in `extern` blocks cannot use non-ascii identifiers .label = in this `extern` block diff --git a/tests/rustdoc-json/fns/extern_safe.rs b/tests/rustdoc-json/fns/extern_safe.rs index a4a2d2c7f8c..b00f9f50bd2 100644 --- a/tests/rustdoc-json/fns/extern_safe.rs +++ b/tests/rustdoc-json/fns/extern_safe.rs @@ -2,7 +2,7 @@ extern "C" { //@ is "$.index[*][?(@.name=='f1')].inner.function.header.is_unsafe" true pub fn f1(); - // items in unadorned `extern` blocks cannot have safety qualifiers + // items in `extern` blocks without an `unsafe` qualifier cannot have safety qualifiers } unsafe extern "C" { diff --git a/tests/ui/parser/fn-header-semantic-fail.rs b/tests/ui/parser/fn-header-semantic-fail.rs index 972e52d75da..f3d834549a8 100644 --- a/tests/ui/parser/fn-header-semantic-fail.rs +++ b/tests/ui/parser/fn-header-semantic-fail.rs @@ -42,7 +42,7 @@ fn main() { extern "C" { async fn fe1(); //~ ERROR functions in `extern` blocks cannot have qualifiers - unsafe fn fe2(); //~ ERROR items in unadorned `extern` blocks cannot have safety qualifiers + unsafe fn fe2(); //~ ERROR items in `extern` blocks without an `unsafe` qualifier cannot have safety qualifiers const fn fe3(); //~ ERROR functions in `extern` blocks cannot have qualifiers extern "C" fn fe4(); //~ ERROR functions in `extern` blocks cannot have qualifiers const async unsafe extern "C" fn fe5(); @@ -50,6 +50,6 @@ fn main() { //~| ERROR functions in `extern` blocks //~| ERROR functions in `extern` blocks //~| ERROR functions cannot be both `const` and `async` - //~| ERROR items in unadorned `extern` blocks cannot have safety qualifiers + //~| ERROR items in `extern` blocks without an `unsafe` qualifier cannot have safety qualifiers } } diff --git a/tests/ui/parser/fn-header-semantic-fail.stderr b/tests/ui/parser/fn-header-semantic-fail.stderr index dda42f24b32..894e03157c1 100644 --- a/tests/ui/parser/fn-header-semantic-fail.stderr +++ b/tests/ui/parser/fn-header-semantic-fail.stderr @@ -78,13 +78,13 @@ LL | extern "C" { LL | async fn fe1(); | ^^^^^ help: remove this qualifier -error: items in unadorned `extern` blocks cannot have safety qualifiers +error: items in `extern` blocks without an `unsafe` qualifier cannot have safety qualifiers --> $DIR/fn-header-semantic-fail.rs:45:9 | LL | unsafe fn fe2(); | ^^^^^^^^^^^^^^^^ | -help: add unsafe to this `extern` block +help: add `unsafe` to this `extern` block | LL | unsafe extern "C" { | ++++++ @@ -134,13 +134,13 @@ LL | extern "C" { LL | const async unsafe extern "C" fn fe5(); | ^^^^^^^^^^ help: remove this qualifier -error: items in unadorned `extern` blocks cannot have safety qualifiers +error: items in `extern` blocks without an `unsafe` qualifier cannot have safety qualifiers --> $DIR/fn-header-semantic-fail.rs:48:9 | LL | const async unsafe extern "C" fn fe5(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: add unsafe to this `extern` block +help: add `unsafe` to this `extern` block | LL | unsafe extern "C" { | ++++++ diff --git a/tests/ui/parser/no-const-fn-in-extern-block.rs b/tests/ui/parser/no-const-fn-in-extern-block.rs index 3ad9ba006d3..1d389108494 100644 --- a/tests/ui/parser/no-const-fn-in-extern-block.rs +++ b/tests/ui/parser/no-const-fn-in-extern-block.rs @@ -3,7 +3,7 @@ extern "C" { //~^ ERROR functions in `extern` blocks cannot have qualifiers const unsafe fn bar(); //~^ ERROR functions in `extern` blocks cannot have qualifiers - //~| ERROR items in unadorned `extern` blocks cannot have safety qualifiers + //~| ERROR items in `extern` blocks without an `unsafe` qualifier cannot have safety qualifiers } fn main() {} diff --git a/tests/ui/parser/no-const-fn-in-extern-block.stderr b/tests/ui/parser/no-const-fn-in-extern-block.stderr index 8c23824a708..d4428d3cb81 100644 --- a/tests/ui/parser/no-const-fn-in-extern-block.stderr +++ b/tests/ui/parser/no-const-fn-in-extern-block.stderr @@ -15,13 +15,13 @@ LL | extern "C" { LL | const unsafe fn bar(); | ^^^^^ help: remove this qualifier -error: items in unadorned `extern` blocks cannot have safety qualifiers +error: items in `extern` blocks without an `unsafe` qualifier cannot have safety qualifiers --> $DIR/no-const-fn-in-extern-block.rs:4:5 | LL | const unsafe fn bar(); | ^^^^^^^^^^^^^^^^^^^^^^ | -help: add unsafe to this `extern` block +help: add `unsafe` to this `extern` block | LL | unsafe extern "C" { | ++++++ diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2021.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2021.stderr index 93797987286..ddc5477116f 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2021.stderr +++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2021.stderr @@ -1,21 +1,21 @@ -error: items in unadorned `extern` blocks cannot have safety qualifiers +error: items in `extern` blocks without an `unsafe` qualifier cannot have safety qualifiers --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:8:5 | LL | safe static TEST1: i32; | ^^^^^^^^^^^^^^^^^^^^^^^ | -help: add unsafe to this `extern` block +help: add `unsafe` to this `extern` block | LL | unsafe extern "C" { | ++++++ -error: items in unadorned `extern` blocks cannot have safety qualifiers +error: items in `extern` blocks without an `unsafe` qualifier cannot have safety qualifiers --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:10:5 | LL | safe fn test1(i: i32); | ^^^^^^^^^^^^^^^^^^^^^^ | -help: add unsafe to this `extern` block +help: add `unsafe` to this `extern` block | LL | unsafe extern "C" { | ++++++ diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2024.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2024.stderr index e9db6006c0b..ae7b4cd47c0 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2024.stderr +++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2024.stderr @@ -10,24 +10,24 @@ LL | | LL | | } | |_^ -error: items in unadorned `extern` blocks cannot have safety qualifiers +error: items in `extern` blocks without an `unsafe` qualifier cannot have safety qualifiers --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:8:5 | LL | safe static TEST1: i32; | ^^^^^^^^^^^^^^^^^^^^^^^ | -help: add unsafe to this `extern` block +help: add `unsafe` to this `extern` block | LL | unsafe extern "C" { | ++++++ -error: items in unadorned `extern` blocks cannot have safety qualifiers +error: items in `extern` blocks without an `unsafe` qualifier cannot have safety qualifiers --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:10:5 | LL | safe fn test1(i: i32); | ^^^^^^^^^^^^^^^^^^^^^^ | -help: add unsafe to this `extern` block +help: add `unsafe` to this `extern` block | LL | unsafe extern "C" { | ++++++ diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.rs b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.rs index 4badb50b267..89415a69f08 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.rs +++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.rs @@ -6,9 +6,9 @@ extern "C" { //[edition2024]~^ ERROR extern blocks must be unsafe safe static TEST1: i32; - //~^ ERROR items in unadorned `extern` blocks cannot have safety qualifiers + //~^ ERROR items in `extern` blocks without an `unsafe` qualifier cannot have safety qualifiers safe fn test1(i: i32); - //~^ ERROR items in unadorned `extern` blocks cannot have safety qualifiers + //~^ ERROR items in `extern` blocks without an `unsafe` qualifier cannot have safety qualifiers } fn test2() { diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.fixed b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.fixed index 857d34eef85..79983a64c2b 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.fixed +++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.fixed @@ -3,7 +3,7 @@ #![allow(dead_code)] unsafe extern "C" { - unsafe fn foo(); //~ ERROR items in unadorned `extern` blocks cannot have safety qualifiers + unsafe fn foo(); //~ ERROR items in `extern` blocks without an `unsafe` qualifier cannot have safety qualifiers } fn main() {} diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.rs b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.rs index edab9850d79..cb84d3d1411 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.rs +++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.rs @@ -3,7 +3,7 @@ #![allow(dead_code)] extern "C" { - unsafe fn foo(); //~ ERROR items in unadorned `extern` blocks cannot have safety qualifiers + unsafe fn foo(); //~ ERROR items in `extern` blocks without an `unsafe` qualifier cannot have safety qualifiers } fn main() {} diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.stderr index 073245e650b..cf1c0012f4d 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.stderr +++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.stderr @@ -1,10 +1,10 @@ -error: items in unadorned `extern` blocks cannot have safety qualifiers +error: items in `extern` blocks without an `unsafe` qualifier cannot have safety qualifiers --> $DIR/unsafe-on-extern-block-issue-126756.rs:6:5 | LL | unsafe fn foo(); | ^^^^^^^^^^^^^^^^ | -help: add unsafe to this `extern` block +help: add `unsafe` to this `extern` block | LL | unsafe extern "C" { | ++++++ From d6391d5d4d1fa20da66e6a58a593b9cb29fa4b1c Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 11 Oct 2024 11:30:03 -0400 Subject: [PATCH 198/357] Note what qualifier --- compiler/rustc_ast_passes/messages.ftl | 4 ++-- .../rustc_ast_passes/src/ast_validation.rs | 15 +++++++----- compiler/rustc_ast_passes/src/errors.rs | 1 + tests/ui/extern/issue-95829.rs | 2 +- tests/ui/extern/issue-95829.stderr | 4 ++-- tests/ui/parser/fn-header-semantic-fail.rs | 10 ++++---- .../ui/parser/fn-header-semantic-fail.stderr | 24 +++++++++---------- .../ui/parser/no-const-fn-in-extern-block.rs | 6 ++--- .../parser/no-const-fn-in-extern-block.stderr | 8 +++---- 9 files changed, 39 insertions(+), 35 deletions(-) diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl index f826e71b574..3ea17cbc279 100644 --- a/compiler/rustc_ast_passes/messages.ftl +++ b/compiler/rustc_ast_passes/messages.ftl @@ -66,9 +66,9 @@ ast_passes_equality_in_where = equality constraints are not yet supported in `wh ast_passes_extern_block_suggestion = if you meant to declare an externally defined function, use an `extern` block -ast_passes_extern_fn_qualifiers = functions in `extern` blocks cannot have qualifiers +ast_passes_extern_fn_qualifiers = functions in `extern` blocks cannot have `{$kw}` qualifier .label = in this `extern` block - .suggestion = remove this qualifier + .suggestion = remove the `{$kw}` qualifier ast_passes_extern_invalid_safety = items in `extern` blocks without an `unsafe` qualifier cannot have safety qualifiers .suggestion = add `unsafe` to this `extern` block diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 5bdd9b6eda8..cd296d39770 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -561,21 +561,24 @@ impl<'a> AstValidator<'a> { // Deconstruct to ensure exhaustiveness FnHeader { safety: _, coroutine_kind, constness, ext }: FnHeader, ) { - let report_err = |span| { - self.dcx() - .emit_err(errors::FnQualifierInExtern { span, block: self.current_extern_span() }); + let report_err = |span, kw| { + self.dcx().emit_err(errors::FnQualifierInExtern { + span, + kw, + block: self.current_extern_span(), + }); }; match coroutine_kind { - Some(knd) => report_err(knd.span()), + Some(kind) => report_err(kind.span(), kind.as_str()), None => (), } match constness { - Const::Yes(span) => report_err(span), + Const::Yes(span) => report_err(span, "const"), Const::No => (), } match ext { Extern::None => (), - Extern::Implicit(span) | Extern::Explicit(_, span) => report_err(span), + Extern::Implicit(span) | Extern::Explicit(_, span) => report_err(span, "extern"), } } diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index 5cce47ce7bd..712bb4b9ba5 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -295,6 +295,7 @@ pub(crate) struct FnQualifierInExtern { pub span: Span, #[label] pub block: Span, + pub kw: &'static str, } #[derive(Diagnostic)] diff --git a/tests/ui/extern/issue-95829.rs b/tests/ui/extern/issue-95829.rs index ad4e04f7c3a..c5ae4c68265 100644 --- a/tests/ui/extern/issue-95829.rs +++ b/tests/ui/extern/issue-95829.rs @@ -2,7 +2,7 @@ extern { async fn L() { //~ ERROR: incorrect function inside `extern` block - //~^ ERROR: functions in `extern` blocks cannot have qualifiers + //~^ ERROR: functions in `extern` blocks cannot have `async` qualifier async fn M() {} } } diff --git a/tests/ui/extern/issue-95829.stderr b/tests/ui/extern/issue-95829.stderr index 16504d1f0c9..2f396b8cc04 100644 --- a/tests/ui/extern/issue-95829.stderr +++ b/tests/ui/extern/issue-95829.stderr @@ -15,13 +15,13 @@ LL | | } = help: you might have meant to write a function accessible through FFI, which can be done by writing `extern fn` outside of the `extern` block = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html -error: functions in `extern` blocks cannot have qualifiers +error: functions in `extern` blocks cannot have `async` qualifier --> $DIR/issue-95829.rs:4:5 | LL | extern { | ------ in this `extern` block LL | async fn L() { - | ^^^^^ help: remove this qualifier + | ^^^^^ help: remove the `async` qualifier error: aborting due to 2 previous errors diff --git a/tests/ui/parser/fn-header-semantic-fail.rs b/tests/ui/parser/fn-header-semantic-fail.rs index f3d834549a8..202f362c81c 100644 --- a/tests/ui/parser/fn-header-semantic-fail.rs +++ b/tests/ui/parser/fn-header-semantic-fail.rs @@ -41,15 +41,15 @@ fn main() { } extern "C" { - async fn fe1(); //~ ERROR functions in `extern` blocks cannot have qualifiers - unsafe fn fe2(); //~ ERROR items in `extern` blocks without an `unsafe` qualifier cannot have safety qualifiers - const fn fe3(); //~ ERROR functions in `extern` blocks cannot have qualifiers - extern "C" fn fe4(); //~ ERROR functions in `extern` blocks cannot have qualifiers + async fn fe1(); //~ ERROR functions in `extern` blocks cannot + unsafe fn fe2(); //~ ERROR items in `extern` blocks without an `unsafe` qualifier cannot + const fn fe3(); //~ ERROR functions in `extern` blocks cannot + extern "C" fn fe4(); //~ ERROR functions in `extern` blocks cannot const async unsafe extern "C" fn fe5(); //~^ ERROR functions in `extern` blocks //~| ERROR functions in `extern` blocks //~| ERROR functions in `extern` blocks //~| ERROR functions cannot be both `const` and `async` - //~| ERROR items in `extern` blocks without an `unsafe` qualifier cannot have safety qualifiers + //~| ERROR items in `extern` blocks without an `unsafe` qualifier cannot have } } diff --git a/tests/ui/parser/fn-header-semantic-fail.stderr b/tests/ui/parser/fn-header-semantic-fail.stderr index 894e03157c1..17e880c3a79 100644 --- a/tests/ui/parser/fn-header-semantic-fail.stderr +++ b/tests/ui/parser/fn-header-semantic-fail.stderr @@ -70,13 +70,13 @@ LL | const async unsafe extern "C" fn fi5() {} | | `async` because of this | `const` because of this -error: functions in `extern` blocks cannot have qualifiers +error: functions in `extern` blocks cannot have `async` qualifier --> $DIR/fn-header-semantic-fail.rs:44:9 | LL | extern "C" { | ---------- in this `extern` block LL | async fn fe1(); - | ^^^^^ help: remove this qualifier + | ^^^^^ help: remove the `async` qualifier error: items in `extern` blocks without an `unsafe` qualifier cannot have safety qualifiers --> $DIR/fn-header-semantic-fail.rs:45:9 @@ -89,50 +89,50 @@ help: add `unsafe` to this `extern` block LL | unsafe extern "C" { | ++++++ -error: functions in `extern` blocks cannot have qualifiers +error: functions in `extern` blocks cannot have `const` qualifier --> $DIR/fn-header-semantic-fail.rs:46:9 | LL | extern "C" { | ---------- in this `extern` block ... LL | const fn fe3(); - | ^^^^^ help: remove this qualifier + | ^^^^^ help: remove the `const` qualifier -error: functions in `extern` blocks cannot have qualifiers +error: functions in `extern` blocks cannot have `extern` qualifier --> $DIR/fn-header-semantic-fail.rs:47:9 | LL | extern "C" { | ---------- in this `extern` block ... LL | extern "C" fn fe4(); - | ^^^^^^^^^^ help: remove this qualifier + | ^^^^^^^^^^ help: remove the `extern` qualifier -error: functions in `extern` blocks cannot have qualifiers +error: functions in `extern` blocks cannot have `async` qualifier --> $DIR/fn-header-semantic-fail.rs:48:15 | LL | extern "C" { | ---------- in this `extern` block ... LL | const async unsafe extern "C" fn fe5(); - | ^^^^^ help: remove this qualifier + | ^^^^^ help: remove the `async` qualifier -error: functions in `extern` blocks cannot have qualifiers +error: functions in `extern` blocks cannot have `const` qualifier --> $DIR/fn-header-semantic-fail.rs:48:9 | LL | extern "C" { | ---------- in this `extern` block ... LL | const async unsafe extern "C" fn fe5(); - | ^^^^^ help: remove this qualifier + | ^^^^^ help: remove the `const` qualifier -error: functions in `extern` blocks cannot have qualifiers +error: functions in `extern` blocks cannot have `extern` qualifier --> $DIR/fn-header-semantic-fail.rs:48:28 | LL | extern "C" { | ---------- in this `extern` block ... LL | const async unsafe extern "C" fn fe5(); - | ^^^^^^^^^^ help: remove this qualifier + | ^^^^^^^^^^ help: remove the `extern` qualifier error: items in `extern` blocks without an `unsafe` qualifier cannot have safety qualifiers --> $DIR/fn-header-semantic-fail.rs:48:9 diff --git a/tests/ui/parser/no-const-fn-in-extern-block.rs b/tests/ui/parser/no-const-fn-in-extern-block.rs index 1d389108494..0f1e44ced10 100644 --- a/tests/ui/parser/no-const-fn-in-extern-block.rs +++ b/tests/ui/parser/no-const-fn-in-extern-block.rs @@ -1,9 +1,9 @@ extern "C" { const fn foo(); - //~^ ERROR functions in `extern` blocks cannot have qualifiers + //~^ ERROR functions in `extern` blocks cannot const unsafe fn bar(); - //~^ ERROR functions in `extern` blocks cannot have qualifiers - //~| ERROR items in `extern` blocks without an `unsafe` qualifier cannot have safety qualifiers + //~^ ERROR functions in `extern` blocks cannot + //~| ERROR items in `extern` blocks without an `unsafe` qualifier cannot } fn main() {} diff --git a/tests/ui/parser/no-const-fn-in-extern-block.stderr b/tests/ui/parser/no-const-fn-in-extern-block.stderr index d4428d3cb81..46f845e85c2 100644 --- a/tests/ui/parser/no-const-fn-in-extern-block.stderr +++ b/tests/ui/parser/no-const-fn-in-extern-block.stderr @@ -1,19 +1,19 @@ -error: functions in `extern` blocks cannot have qualifiers +error: functions in `extern` blocks cannot have `const` qualifier --> $DIR/no-const-fn-in-extern-block.rs:2:5 | LL | extern "C" { | ---------- in this `extern` block LL | const fn foo(); - | ^^^^^ help: remove this qualifier + | ^^^^^ help: remove the `const` qualifier -error: functions in `extern` blocks cannot have qualifiers +error: functions in `extern` blocks cannot have `const` qualifier --> $DIR/no-const-fn-in-extern-block.rs:4:5 | LL | extern "C" { | ---------- in this `extern` block ... LL | const unsafe fn bar(); - | ^^^^^ help: remove this qualifier + | ^^^^^ help: remove the `const` qualifier error: items in `extern` blocks without an `unsafe` qualifier cannot have safety qualifiers --> $DIR/no-const-fn-in-extern-block.rs:4:5 From 9a2772e1c2d6e770e13716d4691bc0a943cd7d61 Mon Sep 17 00:00:00 2001 From: VulnBandit <183613941+VulnBandit@users.noreply.github.com> Date: Fri, 4 Oct 2024 16:10:28 +0200 Subject: [PATCH 199/357] Don't assume traits used as type are trait objs --- .../src/hir_ty_lowering/lint.rs | 53 ++++--- .../src/hir_ty_lowering/mod.rs | 19 ++- tests/crashes/120241-2.rs | 10 -- tests/crashes/120241.rs | 13 -- tests/crashes/120482.rs | 13 -- tests/crashes/125512.rs | 10 -- .../suggest-assoc-ty-bound-on-eq-bound.rs | 20 +-- .../suggest-assoc-ty-bound-on-eq-bound.stderr | 58 ++----- ...to-be-a-closure-or-coroutine-ice-113776.rs | 4 +- ...e-a-closure-or-coroutine-ice-113776.stderr | 39 +---- .../const-generics/not_wf_param_in_rpitit.rs | 3 +- .../not_wf_param_in_rpitit.stderr | 55 +++---- .../avoid-ice-on-warning-2.new.stderr | 40 ++--- .../avoid-ice-on-warning-2.old.stderr | 2 +- .../avoid-ice-on-warning-2.rs | 7 +- .../avoid-ice-on-warning-3.new.stderr | 78 +++++----- .../avoid-ice-on-warning-3.old.stderr | 10 +- .../avoid-ice-on-warning-3.rs | 8 +- .../avoid-ice-on-warning.new.stderr | 16 +- .../dyn-compatibility/avoid-ice-on-warning.rs | 1 + .../bare-trait-dont-suggest-dyn.new.fixed | 3 +- .../bare-trait-dont-suggest-dyn.new.stderr | 15 +- .../bare-trait-dont-suggest-dyn.rs | 3 +- ...t-in-fn-inputs-and-outputs-issue-125139.rs | 57 ++++--- ...-fn-inputs-and-outputs-issue-125139.stderr | 141 +++++++----------- .../ui/dyn-keyword/dyn-2021-edition-error.rs | 6 +- .../dyn-keyword/dyn-2021-edition-error.stderr | 10 +- .../suggest-dyn-on-bare-trait-in-pat.rs | 3 +- .../suggest-dyn-on-bare-trait-in-pat.stderr | 4 +- tests/ui/editions/dyn-trait-sugg-2021.rs | 2 +- tests/ui/editions/dyn-trait-sugg-2021.stderr | 4 +- ...plicit-hrtb-without-dyn.edition2021.stderr | 15 +- .../generic-with-implicit-hrtb-without-dyn.rs | 3 +- tests/ui/resolve/issue-111312.rs | 3 +- tests/ui/resolve/issue-111312.stderr | 21 +-- tests/ui/resolve/issue-111727.rs | 3 +- tests/ui/resolve/issue-111727.stderr | 15 +- .../ice-return-unsized-can-impl-2.rs | 15 ++ .../ice-return-unsized-can-impl-2.stderr | 57 +++++++ .../rust-2021/ice-return-unsized-can-impl.rs | 16 ++ .../ice-return-unsized-can-impl.stderr | 30 ++++ tests/ui/rust-2021/ice-unsized-fn-params-2.rs | 12 ++ .../rust-2021/ice-unsized-fn-params-2.stderr | 19 +++ tests/ui/rust-2021/ice-unsized-fn-params.rs | 18 +++ .../ui/rust-2021/ice-unsized-fn-params.stderr | 57 +++++++ ...-trait-should-use-self-2021-without-dyn.rs | 15 +- ...it-should-use-self-2021-without-dyn.stderr | 81 ++-------- tests/ui/suggestions/issue-116434-2021.rs | 6 +- tests/ui/suggestions/issue-116434-2021.stderr | 27 ++-- .../suggest-blanket-impl-local-trait.rs | 28 ++-- .../suggest-blanket-impl-local-trait.stderr | 28 ++-- ...swapping-self-ty-and-trait-edition-2021.rs | 6 +- ...ping-self-ty-and-trait-edition-2021.stderr | 12 +- .../ui/traits/bound/not-on-bare-trait-2021.rs | 8 +- .../bound/not-on-bare-trait-2021.stderr | 49 +----- tests/ui/traits/issue-106072.rs | 4 +- tests/ui/traits/issue-106072.stderr | 29 +--- .../missing-for-type-in-impl.e2021.stderr | 4 +- tests/ui/traits/missing-for-type-in-impl.rs | 2 +- 59 files changed, 609 insertions(+), 681 deletions(-) delete mode 100644 tests/crashes/120241-2.rs delete mode 100644 tests/crashes/120241.rs delete mode 100644 tests/crashes/120482.rs delete mode 100644 tests/crashes/125512.rs create mode 100644 tests/ui/rust-2021/ice-return-unsized-can-impl-2.rs create mode 100644 tests/ui/rust-2021/ice-return-unsized-can-impl-2.stderr create mode 100644 tests/ui/rust-2021/ice-return-unsized-can-impl.rs create mode 100644 tests/ui/rust-2021/ice-return-unsized-can-impl.stderr create mode 100644 tests/ui/rust-2021/ice-unsized-fn-params-2.rs create mode 100644 tests/ui/rust-2021/ice-unsized-fn-params-2.stderr create mode 100644 tests/ui/rust-2021/ice-unsized-fn-params.rs create mode 100644 tests/ui/rust-2021/ice-unsized-fn-params.stderr diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs index 5607fe873f6..11c0450bfe2 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs @@ -1,6 +1,6 @@ use rustc_ast::TraitObjectSyntax; use rustc_errors::codes::*; -use rustc_errors::{Diag, EmissionGuarantee, StashKey}; +use rustc_errors::{Diag, EmissionGuarantee, ErrorGuaranteed, StashKey, Suggestions}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_lint_defs::Applicability; @@ -15,13 +15,16 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { /// /// *Bare* trait object types are ones that aren't preceded by the keyword `dyn`. /// In edition 2021 and onward we emit a hard error for them. - pub(super) fn prohibit_or_lint_bare_trait_object_ty(&self, self_ty: &hir::Ty<'_>) { + pub(super) fn prohibit_or_lint_bare_trait_object_ty( + &self, + self_ty: &hir::Ty<'_>, + ) -> Option { let tcx = self.tcx(); let hir::TyKind::TraitObject([poly_trait_ref, ..], _, TraitObjectSyntax::None) = self_ty.kind else { - return; + return None; }; let in_path = match tcx.parent_hir_node(self_ty.hir_id) { @@ -70,8 +73,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } if self_ty.span.edition().at_least_rust_2021() { - let msg = "trait objects must include the `dyn` keyword"; - let label = "add `dyn` keyword before this trait"; + let msg = "expected a type, found a trait"; + let label = "you can add the `dyn` keyword if you want a trait object"; let mut diag = rustc_errors::struct_span_code_err!(self.dcx(), self_ty.span, E0782, "{}", msg); if self_ty.span.can_be_used_for_suggestions() @@ -83,7 +86,17 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // Check if the impl trait that we are considering is an impl of a local trait. self.maybe_suggest_blanket_trait_impl(self_ty, &mut diag); self.maybe_suggest_assoc_ty_bound(self_ty, &mut diag); - diag.stash(self_ty.span, StashKey::TraitMissingMethod); + // In case there is an associate type with the same name + // Add the suggestion to this error + if let Some(mut sugg) = + tcx.dcx().steal_non_err(self_ty.span, StashKey::AssociatedTypeSuggestion) + && let Suggestions::Enabled(ref mut s1) = diag.suggestions + && let Suggestions::Enabled(ref mut s2) = sugg.suggestions + { + s1.append(s2); + sugg.cancel(); + } + diag.stash(self_ty.span, StashKey::TraitMissingMethod) } else { tcx.node_span_lint(BARE_TRAIT_OBJECTS, self_ty.hir_id, self_ty.span, |lint| { lint.primary_message("trait objects without an explicit `dyn` are deprecated"); @@ -96,6 +109,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } self.maybe_suggest_blanket_trait_impl(self_ty, lint); }); + None } } @@ -174,41 +188,31 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // 1. Independent functions // 2. Functions inside trait blocks // 3. Functions inside impl blocks - let (sig, generics, owner) = match tcx.hir_node_by_def_id(parent_id) { + let (sig, generics) = match tcx.hir_node_by_def_id(parent_id) { hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, generics, _), .. }) => { - (sig, generics, None) + (sig, generics) } hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Fn(sig, _), generics, - owner_id, .. - }) => (sig, generics, Some(tcx.parent(owner_id.to_def_id()))), + }) => (sig, generics), hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(sig, _), generics, - owner_id, .. - }) => (sig, generics, Some(tcx.parent(owner_id.to_def_id()))), + }) => (sig, generics), _ => return false, }; let Ok(trait_name) = tcx.sess.source_map().span_to_snippet(self_ty.span) else { return false; }; let impl_sugg = vec![(self_ty.span.shrink_to_lo(), "impl ".to_string())]; - let mut is_downgradable = true; - // Check if trait object is safe for suggesting dynamic dispatch. let is_dyn_compatible = match self_ty.kind { hir::TyKind::TraitObject(objects, ..) => { objects.iter().all(|(o, _)| match o.trait_ref.path.res { - Res::Def(DefKind::Trait, id) => { - if Some(id) == owner { - // For recursive traits, don't downgrade the error. (#119652) - is_downgradable = false; - } - tcx.is_dyn_compatible(id) - } + Res::Def(DefKind::Trait, id) => tcx.is_dyn_compatible(id), _ => false, }) } @@ -255,9 +259,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { suggestion, Applicability::MachineApplicable, ); - } else if is_downgradable { - // We'll emit the dyn-compatibility error already, with a structured suggestion. - diag.downgrade_to_delayed_bug(); } return true; } @@ -281,10 +282,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ); if !is_dyn_compatible { diag.note(format!("`{trait_name}` it is dyn-incompatible, so it can't be `dyn`")); - if is_downgradable { - // We'll emit the dyn-compatibility error already, with a structured suggestion. - diag.downgrade_to_delayed_bug(); - } } else { // No ampersand in suggestion if it's borrowed already let (dyn_str, paren_dyn_str) = diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 28a1fc88741..682d29e6e82 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -2063,13 +2063,18 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ) } hir::TyKind::TraitObject(bounds, lifetime, repr) => { - self.prohibit_or_lint_bare_trait_object_ty(hir_ty); - - let repr = match repr { - TraitObjectSyntax::Dyn | TraitObjectSyntax::None => ty::Dyn, - TraitObjectSyntax::DynStar => ty::DynStar, - }; - self.lower_trait_object_ty(hir_ty.span, hir_ty.hir_id, bounds, lifetime, repr) + if let Some(guar) = self.prohibit_or_lint_bare_trait_object_ty(hir_ty) { + // Don't continue with type analysis if the `dyn` keyword is missing + // It generates confusing errors, especially if the user meant to use another + // keyword like `impl` + Ty::new_error(tcx, guar) + } else { + let repr = match repr { + TraitObjectSyntax::Dyn | TraitObjectSyntax::None => ty::Dyn, + TraitObjectSyntax::DynStar => ty::DynStar, + }; + self.lower_trait_object_ty(hir_ty.span, hir_ty.hir_id, bounds, lifetime, repr) + } } // If we encounter a fully qualified path with RTN generics, then it must have // *not* gone through `lower_ty_maybe_return_type_notation`, and therefore diff --git a/tests/crashes/120241-2.rs b/tests/crashes/120241-2.rs deleted file mode 100644 index 91ec3362090..00000000000 --- a/tests/crashes/120241-2.rs +++ /dev/null @@ -1,10 +0,0 @@ -//@ known-bug: #120241 -//@ edition:2021 -#![feature(dyn_compatible_for_dispatch)] -#![feature(unsized_fn_params)] - -fn guard(_s: Copy) -> bool { - panic!() -} - -fn main() {} diff --git a/tests/crashes/120241.rs b/tests/crashes/120241.rs deleted file mode 100644 index b4fcb903714..00000000000 --- a/tests/crashes/120241.rs +++ /dev/null @@ -1,13 +0,0 @@ -//@ known-bug: #120241 -//@ edition:2021 -#![feature(dyn_compatible_for_dispatch)] - -trait B { - fn f(a: A) -> A; -} - -trait A { - fn g(b: B) -> B; -} - -fn main() {} diff --git a/tests/crashes/120482.rs b/tests/crashes/120482.rs deleted file mode 100644 index a395855d796..00000000000 --- a/tests/crashes/120482.rs +++ /dev/null @@ -1,13 +0,0 @@ -//@ known-bug: #120482 -//@ edition:2021 -#![feature(dyn_compatible_for_dispatch)] - -trait B { - fn bar(&self, x: &Self); -} - -trait A { - fn g(new: B) -> B; -} - -fn main() {} diff --git a/tests/crashes/125512.rs b/tests/crashes/125512.rs deleted file mode 100644 index 37dbdf2f32f..00000000000 --- a/tests/crashes/125512.rs +++ /dev/null @@ -1,10 +0,0 @@ -//@ known-bug: rust-lang/rust#125512 -//@ edition:2021 -#![feature(dyn_compatible_for_dispatch)] -trait B { - fn f(a: A) -> A; -} -trait A { - fn concrete(b: B) -> B; -} -fn main() {} diff --git a/tests/ui/associated-type-bounds/suggest-assoc-ty-bound-on-eq-bound.rs b/tests/ui/associated-type-bounds/suggest-assoc-ty-bound-on-eq-bound.rs index 7df042d5f88..c8bb0ebd574 100644 --- a/tests/ui/associated-type-bounds/suggest-assoc-ty-bound-on-eq-bound.rs +++ b/tests/ui/associated-type-bounds/suggest-assoc-ty-bound-on-eq-bound.rs @@ -2,28 +2,24 @@ //@ edition: 2021 fn f(_: impl Trait) {} -//~^ ERROR trait objects must include the `dyn` keyword -//~| HELP add `dyn` keyword before this trait +//~^ ERROR expected a type, found a trait +//~| HELP you can add the `dyn` keyword if you want a trait object //~| HELP you might have meant to write a bound here -//~| ERROR the trait `Copy` cannot be made into an object fn g(_: impl Trait) {} -//~^ ERROR trait objects must include the `dyn` keyword -//~| HELP add `dyn` keyword before this trait +//~^ ERROR expected a type, found a trait +//~| HELP you can add the `dyn` keyword if you want a trait object //~| HELP you might have meant to write a bound here -//~| ERROR only auto traits can be used as additional traits in a trait object -//~| HELP consider creating a new trait -//~| ERROR the trait `Eq` cannot be made into an object fn h(_: impl Trait = 'static + for<'a> Fn(&'a ())>) {} -//~^ ERROR trait objects must include the `dyn` keyword -//~| HELP add `dyn` keyword before this trait +//~^ ERROR expected a type, found a trait +//~| HELP you can add the `dyn` keyword if you want a trait object //~| HELP you might have meant to write a bound here // Don't suggest assoc ty bound in trait object types, that's not valid: type Obj = dyn Trait; -//~^ ERROR trait objects must include the `dyn` keyword -//~| HELP add `dyn` keyword before this trait +//~^ ERROR expected a type, found a trait +//~| HELP you can add the `dyn` keyword if you want a trait object trait Trait { type T; } diff --git a/tests/ui/associated-type-bounds/suggest-assoc-ty-bound-on-eq-bound.stderr b/tests/ui/associated-type-bounds/suggest-assoc-ty-bound-on-eq-bound.stderr index bec60187e42..dbe285c5310 100644 --- a/tests/ui/associated-type-bounds/suggest-assoc-ty-bound-on-eq-bound.stderr +++ b/tests/ui/associated-type-bounds/suggest-assoc-ty-bound-on-eq-bound.stderr @@ -1,41 +1,10 @@ -error[E0038]: the trait `Copy` cannot be made into an object - --> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:4:20 - | -LL | fn f(_: impl Trait) {} - | ^^^^^^^^ `Copy` cannot be made into an object - | - = note: the trait cannot be made into an object because it requires `Self: Sized` - = note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - -error[E0225]: only auto traits can be used as additional traits in a trait object - --> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:10:42 - | -LL | fn g(_: impl Trait) {} - | --------------- ^^ additional non-auto trait - | | - | first non-auto trait - | - = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Debug + Eq {}` - = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit - -error[E0038]: the trait `Eq` cannot be made into an object - --> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:10:24 - | -LL | fn g(_: impl Trait) {} - | ^^^^^^^^^^^^^^^^^^^^ `Eq` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $SRC_DIR/core/src/cmp.rs:LL:COL - | - = note: the trait cannot be made into an object because it uses `Self` as a type parameter - -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:4:24 | LL | fn f(_: impl Trait) {} | ^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | fn f(_: impl Trait) {} | +++ @@ -44,13 +13,13 @@ help: you might have meant to write a bound here LL | fn f(_: impl Trait) {} | ~ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:10:24 +error[E0782]: expected a type, found a trait + --> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:9:24 | LL | fn g(_: impl Trait) {} | ^^^^^^^^^^^^^^^^^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | fn g(_: impl Trait) {} | +++ @@ -59,13 +28,13 @@ help: you might have meant to write a bound here LL | fn g(_: impl Trait) {} | ~ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:18:26 +error[E0782]: expected a type, found a trait + --> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:14:26 | LL | fn h(_: impl Trait = 'static + for<'a> Fn(&'a ())>) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | fn h(_: impl Trait = dyn 'static + for<'a> Fn(&'a ())>) {} | +++ @@ -74,18 +43,17 @@ help: you might have meant to write a bound here LL | fn h(_: impl Trait: 'static + for<'a> Fn(&'a ())>) {} | ~ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:24:26 +error[E0782]: expected a type, found a trait + --> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:20:26 | LL | type Obj = dyn Trait; | ^^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | type Obj = dyn Trait; | +++ -error: aborting due to 7 previous errors +error: aborting due to 4 previous errors -Some errors have detailed explanations: E0038, E0225, E0782. -For more information about an error, try `rustc --explain E0038`. +For more information about this error, try `rustc --explain E0782`. diff --git a/tests/ui/const-generics/generic_const_exprs/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.rs b/tests/ui/const-generics/generic_const_exprs/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.rs index 4bea3ad87f5..c1d3321f840 100644 --- a/tests/ui/const-generics/generic_const_exprs/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.rs +++ b/tests/ui/const-generics/generic_const_exprs/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.rs @@ -14,10 +14,8 @@ fn f( 1 }], ) -> impl Iterator { -//~^ ERROR the type parameter `Rhs` must be explicitly specified +//~^ ERROR expected a type, found a trait //~| ERROR `()` is not an iterator -//~| ERROR trait objects must include the `dyn` keyword -//~| ERROR the type parameter `Rhs` must be explicitly specified [E0393] } pub fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.stderr b/tests/ui/const-generics/generic_const_exprs/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.stderr index 416a9381124..5c4d643a28e 100644 --- a/tests/ui/const-generics/generic_const_exprs/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.stderr +++ b/tests/ui/const-generics/generic_const_exprs/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.stderr @@ -16,37 +16,6 @@ help: you might be missing a type parameter LL | fn f( | +++ -error[E0393]: the type parameter `Rhs` must be explicitly specified - --> $DIR/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.rs:16:27 - | -LL | ) -> impl Iterator { - | ^^^^^^^^^ - --> $SRC_DIR/core/src/ops/arith.rs:LL:COL - | - = note: type parameter `Rhs` must be specified for this - | - = note: because of the default `Self` reference, type parameters must be specified on object types -help: set the type parameter to the desired type - | -LL | ) -> impl Iterator> { - | +++++ - -error[E0393]: the type parameter `Rhs` must be explicitly specified - --> $DIR/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.rs:16:27 - | -LL | ) -> impl Iterator { - | ^^^^^^^^^ - --> $SRC_DIR/core/src/ops/arith.rs:LL:COL - | - = note: type parameter `Rhs` must be specified for this - | - = note: because of the default `Self` reference, type parameters must be specified on object types - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: set the type parameter to the desired type - | -LL | ) -> impl Iterator> { - | +++++ - error[E0277]: `()` is not an iterator --> $DIR/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.rs:16:6 | @@ -55,13 +24,13 @@ LL | ) -> impl Iterator { | = help: the trait `Iterator` is not implemented for `()` -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.rs:16:27 | LL | ) -> impl Iterator { | ^^^^^^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | ) -> impl Iterator { | +++ @@ -70,7 +39,7 @@ help: you might have meant to write a bound here LL | ) -> impl Iterator { | ~ -error: aborting due to 5 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0277, E0393, E0412, E0782. +Some errors have detailed explanations: E0277, E0412, E0782. For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/const-generics/not_wf_param_in_rpitit.rs b/tests/ui/const-generics/not_wf_param_in_rpitit.rs index eb672194340..b454562ad49 100644 --- a/tests/ui/const-generics/not_wf_param_in_rpitit.rs +++ b/tests/ui/const-generics/not_wf_param_in_rpitit.rs @@ -1,12 +1,11 @@ //@ edition:2021 -trait Trait { +trait Trait { //~^ ERROR: cannot find value `bar` in this scope //~| ERROR: cycle detected when computing type of `Trait::N` //~| ERROR: the trait `Trait` cannot be made into an object //~| ERROR: the trait `Trait` cannot be made into an object //~| ERROR: the trait `Trait` cannot be made into an object - //~| ERROR: trait objects must include the `dyn` keyword async fn a() {} } diff --git a/tests/ui/const-generics/not_wf_param_in_rpitit.stderr b/tests/ui/const-generics/not_wf_param_in_rpitit.stderr index ade40550c73..2500409e828 100644 --- a/tests/ui/const-generics/not_wf_param_in_rpitit.stderr +++ b/tests/ui/const-generics/not_wf_param_in_rpitit.stderr @@ -1,33 +1,33 @@ error[E0425]: cannot find value `bar` in this scope - --> $DIR/not_wf_param_in_rpitit.rs:3:30 + --> $DIR/not_wf_param_in_rpitit.rs:3:34 | -LL | trait Trait { - | ^^^ not found in this scope +LL | trait Trait { + | ^^^ not found in this scope error[E0391]: cycle detected when computing type of `Trait::N` - --> $DIR/not_wf_param_in_rpitit.rs:3:22 + --> $DIR/not_wf_param_in_rpitit.rs:3:26 | -LL | trait Trait { - | ^^^^^ +LL | trait Trait { + | ^^^^^ | = note: ...which immediately requires computing type of `Trait::N` again note: cycle used when computing explicit predicates of trait `Trait` --> $DIR/not_wf_param_in_rpitit.rs:3:1 | -LL | trait Trait { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | trait Trait { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information error[E0038]: the trait `Trait` cannot be made into an object --> $DIR/not_wf_param_in_rpitit.rs:3:22 | -LL | trait Trait { - | ^^^^^ `Trait` cannot be made into an object +LL | trait Trait { + | ^^^^^^^^^ `Trait` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/not_wf_param_in_rpitit.rs:10:14 + --> $DIR/not_wf_param_in_rpitit.rs:9:14 | -LL | trait Trait { +LL | trait Trait { | ----- this trait cannot be made into an object... ... LL | async fn a() {} @@ -44,13 +44,13 @@ LL | async fn a() where Self: Sized {} error[E0038]: the trait `Trait` cannot be made into an object --> $DIR/not_wf_param_in_rpitit.rs:3:13 | -LL | trait Trait { - | ^^^^^^^^^^^^^^^^^^^^ `Trait` cannot be made into an object +LL | trait Trait { + | ^^^^^^^^^^^^^^^^^^^^^^^^ `Trait` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/not_wf_param_in_rpitit.rs:10:14 + --> $DIR/not_wf_param_in_rpitit.rs:9:14 | -LL | trait Trait { +LL | trait Trait { | ----- this trait cannot be made into an object... ... LL | async fn a() {} @@ -67,13 +67,13 @@ LL | async fn a() where Self: Sized {} error[E0038]: the trait `Trait` cannot be made into an object --> $DIR/not_wf_param_in_rpitit.rs:3:13 | -LL | trait Trait { - | ^^^^^^^^^^^^^^^^^^^^ `Trait` cannot be made into an object +LL | trait Trait { + | ^^^^^^^^^^^^^^^^^^^^^^^^ `Trait` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/not_wf_param_in_rpitit.rs:10:14 + --> $DIR/not_wf_param_in_rpitit.rs:9:14 | -LL | trait Trait { +LL | trait Trait { | ----- this trait cannot be made into an object... ... LL | async fn a() {} @@ -88,18 +88,7 @@ help: alternatively, consider constraining `a` so it does not apply to trait obj LL | async fn a() where Self: Sized {} | +++++++++++++++++ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/not_wf_param_in_rpitit.rs:3:22 - | -LL | trait Trait { - | ^^^^^ - | -help: add `dyn` keyword before this trait - | -LL | trait Trait { - | +++ +error: aborting due to 5 previous errors -error: aborting due to 6 previous errors - -Some errors have detailed explanations: E0038, E0391, E0425, E0782. +Some errors have detailed explanations: E0038, E0391, E0425. For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.new.stderr b/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.new.stderr index 4e3d2ebebad..83795f3128e 100644 --- a/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.new.stderr +++ b/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.new.stderr @@ -1,41 +1,19 @@ -error[E0038]: the trait `Copy` cannot be made into an object +error[E0782]: expected a type, found a trait --> $DIR/avoid-ice-on-warning-2.rs:4:13 | LL | fn id(f: Copy) -> usize { - | ^^^^ `Copy` cannot be made into an object + | ^^^^ | - = note: the trait cannot be made into an object because it requires `Self: Sized` - = note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - -error[E0618]: expected function, found `(dyn Copy + 'static)` - --> $DIR/avoid-ice-on-warning-2.rs:11:5 + = note: `Copy` it is dyn-incompatible, so it can't be `dyn` +help: use a new generic type parameter, constrained by `Copy` | -LL | fn id(f: Copy) -> usize { - | - `f` has type `(dyn Copy + 'static)` -... -LL | f() - | ^-- - | | - | call expression requires function - -error[E0277]: the size for values of type `(dyn Copy + 'static)` cannot be known at compilation time - --> $DIR/avoid-ice-on-warning-2.rs:4:13 - | -LL | fn id(f: Copy) -> usize { - | ^^^^ doesn't have a size known at compile-time - | - = help: the trait `Sized` is not implemented for `(dyn Copy + 'static)` - = help: unsized fn params are gated as an unstable feature -help: you can use `impl Trait` as the argument type +LL | fn id(f: T) -> usize { + | +++++++++ ~ +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference | LL | fn id(f: impl Copy) -> usize { | ++++ -help: function arguments must have a statically known size, borrowed types always have a known size - | -LL | fn id(f: &dyn Copy) -> usize { - | ++++ -error: aborting due to 3 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0038, E0277, E0618. -For more information about an error, try `rustc --explain E0038`. +For more information about this error, try `rustc --explain E0782`. diff --git a/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.old.stderr b/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.old.stderr index 180cd679dea..54daefea31c 100644 --- a/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.old.stderr +++ b/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.old.stderr @@ -36,7 +36,7 @@ LL | fn id(f: Copy) -> usize { = note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit error[E0618]: expected function, found `(dyn Copy + 'static)` - --> $DIR/avoid-ice-on-warning-2.rs:11:5 + --> $DIR/avoid-ice-on-warning-2.rs:12:5 | LL | fn id(f: Copy) -> usize { | - `f` has type `(dyn Copy + 'static)` diff --git a/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.rs b/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.rs index db2f4aea05b..3c2da667b39 100644 --- a/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.rs +++ b/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.rs @@ -2,13 +2,14 @@ //@[old] edition:2015 //@[new] edition:2021 fn id(f: Copy) -> usize { -//~^ ERROR the trait `Copy` cannot be made into an object -//~| ERROR: the size for values of type `(dyn Copy + 'static)` +//[new]~^ ERROR expected a type, found a trait +//[old]~^^ ERROR the trait `Copy` cannot be made into an object +//[old]~| ERROR the size for values of type `(dyn Copy + 'static)` //[old]~| WARN trait objects without an explicit `dyn` are deprecated //[old]~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! //[old]~| WARN trait objects without an explicit `dyn` are deprecated //[old]~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! f() - //~^ ERROR: expected function, found `(dyn Copy + 'static)` + //[old]~^ ERROR: expected function, found `(dyn Copy + 'static)` } fn main() {} diff --git a/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.new.stderr b/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.new.stderr index fdd3e8ab507..813b5863738 100644 --- a/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.new.stderr +++ b/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.new.stderr @@ -1,47 +1,57 @@ -error[E0038]: the trait `A` cannot be made into an object +error[E0782]: expected a type, found a trait + --> $DIR/avoid-ice-on-warning-3.rs:14:19 + | +LL | trait A { fn g(b: B) -> B; } + | ^ + | + = note: `B` it is dyn-incompatible, so it can't be `dyn` +help: use a new generic type parameter, constrained by `B` + | +LL | trait A { fn g(b: T) -> B; } + | ++++++ ~ +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference + | +LL | trait A { fn g(b: impl B) -> B; } + | ++++ + +error[E0782]: expected a type, found a trait + --> $DIR/avoid-ice-on-warning-3.rs:14:25 + | +LL | trait A { fn g(b: B) -> B; } + | ^ + | +help: `B` is dyn-incompatible, use `impl B` to return an opaque type, as long as you return a single underlying type + | +LL | trait A { fn g(b: B) -> impl B; } + | ++++ + +error[E0782]: expected a type, found a trait --> $DIR/avoid-ice-on-warning-3.rs:4:19 | LL | trait B { fn f(a: A) -> A; } - | ^ `A` cannot be made into an object + | ^ | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/avoid-ice-on-warning-3.rs:12:14 + = note: `A` it is dyn-incompatible, so it can't be `dyn` +help: use a new generic type parameter, constrained by `A` | -LL | trait A { fn g(b: B) -> B; } - | - ^ ...because associated function `g` has no `self` parameter - | | - | this trait cannot be made into an object... -help: consider turning `g` into a method by giving it a `&self` argument +LL | trait B { fn f(a: T) -> A; } + | ++++++ ~ +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference | -LL | trait A { fn g(&self, b: B) -> B; } - | ++++++ -help: alternatively, consider constraining `g` so it does not apply to trait objects - | -LL | trait A { fn g(b: B) -> B where Self: Sized; } - | +++++++++++++++++ +LL | trait B { fn f(a: impl A) -> A; } + | ++++ -error[E0038]: the trait `B` cannot be made into an object - --> $DIR/avoid-ice-on-warning-3.rs:12:19 - | -LL | trait A { fn g(b: B) -> B; } - | ^ `B` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/avoid-ice-on-warning-3.rs:4:14 +error[E0782]: expected a type, found a trait + --> $DIR/avoid-ice-on-warning-3.rs:4:25 | LL | trait B { fn f(a: A) -> A; } - | - ^ ...because associated function `f` has no `self` parameter - | | - | this trait cannot be made into an object... -help: consider turning `f` into a method by giving it a `&self` argument + | ^ | -LL | trait B { fn f(&self, a: A) -> A; } - | ++++++ -help: alternatively, consider constraining `f` so it does not apply to trait objects +help: `A` is dyn-incompatible, use `impl A` to return an opaque type, as long as you return a single underlying type | -LL | trait B { fn f(a: A) -> A where Self: Sized; } - | +++++++++++++++++ +LL | trait B { fn f(a: A) -> impl A; } + | ++++ -error: aborting due to 2 previous errors +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0038`. +For more information about this error, try `rustc --explain E0782`. diff --git a/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.old.stderr b/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.old.stderr index bd362abb355..6bc2d73a0d0 100644 --- a/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.old.stderr +++ b/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.old.stderr @@ -26,7 +26,7 @@ LL | trait B { fn f(a: A) -> dyn A; } | +++ warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/avoid-ice-on-warning-3.rs:12:19 + --> $DIR/avoid-ice-on-warning-3.rs:14:19 | LL | trait A { fn g(b: B) -> B; } | ^ @@ -39,7 +39,7 @@ LL | trait A { fn g(b: dyn B) -> B; } | +++ warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/avoid-ice-on-warning-3.rs:12:25 + --> $DIR/avoid-ice-on-warning-3.rs:14:25 | LL | trait A { fn g(b: B) -> B; } | ^ @@ -72,7 +72,7 @@ LL | trait B { fn f(a: A) -> A; } | ^ `A` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/avoid-ice-on-warning-3.rs:12:14 + --> $DIR/avoid-ice-on-warning-3.rs:14:14 | LL | trait A { fn g(b: B) -> B; } | - ^ ...because associated function `g` has no `self` parameter @@ -88,7 +88,7 @@ LL | trait A { fn g(b: B) -> B where Self: Sized; } | +++++++++++++++++ warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/avoid-ice-on-warning-3.rs:12:19 + --> $DIR/avoid-ice-on-warning-3.rs:14:19 | LL | trait A { fn g(b: B) -> B; } | ^ @@ -102,7 +102,7 @@ LL | trait A { fn g(b: dyn B) -> B; } | +++ error[E0038]: the trait `B` cannot be made into an object - --> $DIR/avoid-ice-on-warning-3.rs:12:19 + --> $DIR/avoid-ice-on-warning-3.rs:14:19 | LL | trait A { fn g(b: B) -> B; } | ^ `B` cannot be made into an object diff --git a/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.rs b/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.rs index 38bee8142bb..00d47225e92 100644 --- a/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.rs +++ b/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.rs @@ -2,7 +2,9 @@ //@[old] edition:2015 //@[new] edition:2021 trait B { fn f(a: A) -> A; } -//~^ ERROR the trait `A` cannot be made into an object +//[new]~^ ERROR expected a type, found a trait +//[new]~| ERROR expected a type, found a trait +//[old]~^^^ ERROR the trait `A` cannot be made into an object //[old]~| WARN trait objects without an explicit `dyn` are deprecated //[old]~| WARN trait objects without an explicit `dyn` are deprecated //[old]~| WARN trait objects without an explicit `dyn` are deprecated @@ -10,7 +12,9 @@ trait B { fn f(a: A) -> A; } //[old]~| WARN this is accepted in the current edition //[old]~| WARN this is accepted in the current edition trait A { fn g(b: B) -> B; } -//~^ ERROR the trait `B` cannot be made into an object +//[new]~^ ERROR expected a type, found a trait +//[new]~| ERROR expected a type, found a trait +//[old]~^^^ ERROR the trait `B` cannot be made into an object //[old]~| WARN trait objects without an explicit `dyn` are deprecated //[old]~| WARN trait objects without an explicit `dyn` are deprecated //[old]~| WARN trait objects without an explicit `dyn` are deprecated diff --git a/tests/ui/dyn-compatibility/avoid-ice-on-warning.new.stderr b/tests/ui/dyn-compatibility/avoid-ice-on-warning.new.stderr index 4ff45d7a848..e9eb1cdd0c2 100644 --- a/tests/ui/dyn-compatibility/avoid-ice-on-warning.new.stderr +++ b/tests/ui/dyn-compatibility/avoid-ice-on-warning.new.stderr @@ -15,6 +15,18 @@ error[E0405]: cannot find trait `call_that` in this scope LL | fn call_this(f: F) : Fn(&str) + call_that {} | ^^^^^^^^^ not found in this scope -error: aborting due to 2 previous errors +error[E0782]: expected a type, found a trait + --> $DIR/avoid-ice-on-warning.rs:4:25 + | +LL | fn call_this(f: F) : Fn(&str) + call_that {} + | ^^^^^^^^^^^^^^^^^^^^ + | +help: `Fn(&str) + call_that` is dyn-incompatible, use `impl Fn(&str) + call_that` to return an opaque type, as long as you return a single underlying type + | +LL | fn call_this(f: F) : impl Fn(&str) + call_that {} + | ++++ -For more information about this error, try `rustc --explain E0405`. +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0405, E0782. +For more information about an error, try `rustc --explain E0405`. diff --git a/tests/ui/dyn-compatibility/avoid-ice-on-warning.rs b/tests/ui/dyn-compatibility/avoid-ice-on-warning.rs index b90d8911d50..ef82321df0e 100644 --- a/tests/ui/dyn-compatibility/avoid-ice-on-warning.rs +++ b/tests/ui/dyn-compatibility/avoid-ice-on-warning.rs @@ -4,6 +4,7 @@ fn call_this(f: F) : Fn(&str) + call_that {} //~^ ERROR return types are denoted using `->` //~| ERROR cannot find trait `call_that` in this scope +//[new]~| ERROR expected a type, found a trait //[old]~| WARN trait objects without an explicit `dyn` are deprecated //[old]~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! fn main() {} diff --git a/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.new.fixed b/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.new.fixed index 4f5310082e1..a54892afd3e 100644 --- a/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.new.fixed +++ b/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.new.fixed @@ -4,7 +4,8 @@ //@[new] run-rustfix #![deny(bare_trait_objects)] fn ord_prefer_dot(s: String) -> impl Ord { - //~^ ERROR the trait `Ord` cannot be made into an object + //[new]~^ ERROR expected a type, found a trait + //[old]~^^ ERROR the trait `Ord` cannot be made into an object //[old]~| ERROR trait objects without an explicit `dyn` are deprecated //[old]~| WARNING this is accepted in the current edition (Rust 2015) (s.starts_with("."), s) diff --git a/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.new.stderr b/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.new.stderr index bb2bf6ddcda..52168261a64 100644 --- a/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.new.stderr +++ b/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.new.stderr @@ -1,21 +1,14 @@ -error[E0038]: the trait `Ord` cannot be made into an object +error[E0782]: expected a type, found a trait --> $DIR/bare-trait-dont-suggest-dyn.rs:6:33 | LL | fn ord_prefer_dot(s: String) -> Ord { - | ^^^ `Ord` cannot be made into an object + | ^^^ | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $SRC_DIR/core/src/cmp.rs:LL:COL - | - = note: the trait cannot be made into an object because it uses `Self` as a type parameter - ::: $SRC_DIR/core/src/cmp.rs:LL:COL - | - = note: the trait cannot be made into an object because it uses `Self` as a type parameter -help: consider using an opaque type instead +help: `Ord` is dyn-incompatible, use `impl Ord` to return an opaque type, as long as you return a single underlying type | LL | fn ord_prefer_dot(s: String) -> impl Ord { | ++++ error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0038`. +For more information about this error, try `rustc --explain E0782`. diff --git a/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.rs b/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.rs index cb5a305eab0..cf9be612d2e 100644 --- a/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.rs +++ b/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.rs @@ -4,7 +4,8 @@ //@[new] run-rustfix #![deny(bare_trait_objects)] fn ord_prefer_dot(s: String) -> Ord { - //~^ ERROR the trait `Ord` cannot be made into an object + //[new]~^ ERROR expected a type, found a trait + //[old]~^^ ERROR the trait `Ord` cannot be made into an object //[old]~| ERROR trait objects without an explicit `dyn` are deprecated //[old]~| WARNING this is accepted in the current edition (Rust 2015) (s.starts_with("."), s) diff --git a/tests/ui/dyn-compatibility/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs b/tests/ui/dyn-compatibility/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs index dabaa309c16..7bc2af463cb 100644 --- a/tests/ui/dyn-compatibility/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs +++ b/tests/ui/dyn-compatibility/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs @@ -6,104 +6,102 @@ struct IceCream; impl IceCream { fn foo(_: &Trait) {} - //~^ ERROR: trait objects must include the `dyn` keyword + //~^ ERROR: expected a type, found a trait fn bar(self, _: &'a Trait) {} - //~^ ERROR: trait objects must include the `dyn` keyword + //~^ ERROR: expected a type, found a trait //~| ERROR: use of undeclared lifetime name fn alice<'a>(&self, _: &Trait) {} - //~^ ERROR: trait objects must include the `dyn` keyword + //~^ ERROR: expected a type, found a trait fn bob<'a>(_: &'a Trait) {} - //~^ ERROR: trait objects must include the `dyn` keyword + //~^ ERROR: expected a type, found a trait fn cat() -> &Trait { //~^ ERROR: missing lifetime specifier - //~| ERROR: trait objects must include the `dyn` keyword + //~| ERROR: expected a type, found a trait &Type } fn dog<'a>() -> &Trait { //~^ ERROR: missing lifetime specifier - //~| ERROR: trait objects must include the `dyn` keyword + //~| ERROR: expected a type, found a trait &Type } fn kitten() -> &'a Trait { //~^ ERROR: use of undeclared lifetime name - //~| ERROR: trait objects must include the `dyn` keyword + //~| ERROR: expected a type, found a trait &Type } fn puppy<'a>() -> &'a Trait { - //~^ ERROR: trait objects must include the `dyn` keyword + //~^ ERROR: expected a type, found a trait &Type } fn parrot() -> &mut Trait { //~^ ERROR: missing lifetime specifier - //~| ERROR: trait objects must include the `dyn` keyword + //~| ERROR: expected a type, found a trait &mut Type - //~^ ERROR: cannot return reference to temporary value } } trait Sing { fn foo(_: &Trait); - //~^ ERROR: trait objects must include the `dyn` keyword + //~^ ERROR: expected a type, found a trait fn bar(_: &'a Trait); - //~^ ERROR: trait objects must include the `dyn` keyword + //~^ ERROR: expected a type, found a trait //~| ERROR: use of undeclared lifetime name fn alice<'a>(_: &Trait); - //~^ ERROR: trait objects must include the `dyn` keyword + //~^ ERROR: expected a type, found a trait fn bob<'a>(_: &'a Trait); - //~^ ERROR: trait objects must include the `dyn` keyword + //~^ ERROR: expected a type, found a trait fn cat() -> &Trait; //~^ ERROR: missing lifetime specifier - //~| ERROR: trait objects must include the `dyn` keyword + //~| ERROR: expected a type, found a trait fn dog<'a>() -> &Trait { //~^ ERROR: missing lifetime specifier - //~| ERROR: trait objects must include the `dyn` keyword + //~| ERROR: expected a type, found a trait &Type } fn kitten() -> &'a Trait { //~^ ERROR: use of undeclared lifetime name - //~| ERROR: trait objects must include the `dyn` keyword + //~| ERROR: expected a type, found a trait &Type } fn puppy<'a>() -> &'a Trait { - //~^ ERROR: trait objects must include the `dyn` keyword + //~^ ERROR: expected a type, found a trait &Type } fn parrot() -> &mut Trait { //~^ ERROR: missing lifetime specifier - //~| ERROR: trait objects must include the `dyn` keyword + //~| ERROR: expected a type, found a trait &mut Type - //~^ ERROR: cannot return reference to temporary value } } fn foo(_: &Trait) {} -//~^ ERROR: trait objects must include the `dyn` keyword +//~^ ERROR: expected a type, found a trait fn bar(_: &'a Trait) {} -//~^ ERROR: trait objects must include the `dyn` keyword +//~^ ERROR: expected a type, found a trait //~| ERROR: use of undeclared lifetime name fn alice<'a>(_: &Trait) {} -//~^ ERROR: trait objects must include the `dyn` keyword +//~^ ERROR: expected a type, found a trait fn bob<'a>(_: &'a Trait) {} -//~^ ERROR: trait objects must include the `dyn` keyword +//~^ ERROR: expected a type, found a trait struct Type; @@ -111,32 +109,31 @@ impl Trait for Type {} fn cat() -> &Trait { //~^ ERROR: missing lifetime specifier -//~| ERROR: trait objects must include the `dyn` keyword +//~| ERROR: expected a type, found a trait &Type } fn dog<'a>() -> &Trait { //~^ ERROR: missing lifetime specifier -//~| ERROR: trait objects must include the `dyn` keyword +//~| ERROR: expected a type, found a trait &Type } fn kitten() -> &'a Trait { //~^ ERROR: use of undeclared lifetime name -//~| ERROR: trait objects must include the `dyn` keyword +//~| ERROR: expected a type, found a trait &Type } fn puppy<'a>() -> &'a Trait { -//~^ ERROR: trait objects must include the `dyn` keyword +//~^ ERROR: expected a type, found a trait &Type } fn parrot() -> &mut Trait { //~^ ERROR: missing lifetime specifier - //~| ERROR: trait objects must include the `dyn` keyword + //~| ERROR: expected a type, found a trait &mut Type - //~^ ERROR: cannot return reference to temporary value } fn main() {} diff --git a/tests/ui/dyn-compatibility/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.stderr b/tests/ui/dyn-compatibility/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.stderr index 8bdfea7766e..4c6d84f0534 100644 --- a/tests/ui/dyn-compatibility/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.stderr +++ b/tests/ui/dyn-compatibility/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.stderr @@ -65,7 +65,7 @@ LL | fn parrot() -> &'static mut Trait { | +++++++ error[E0261]: use of undeclared lifetime name `'a` - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:56:16 + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:55:16 | LL | fn bar(_: &'a Trait); | ^^ undeclared lifetime @@ -80,7 +80,7 @@ LL | trait Sing<'a> { | ++++ error[E0106]: missing lifetime specifier - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:66:17 + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:65:17 | LL | fn cat() -> &Trait; | ^ expected named lifetime parameter @@ -97,7 +97,7 @@ LL + fn cat() -> Trait; | error[E0106]: missing lifetime specifier - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:70:21 + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:69:21 | LL | fn dog<'a>() -> &Trait { | ^ expected named lifetime parameter @@ -109,7 +109,7 @@ LL | fn dog<'a>() -> &'a Trait { | ++ error[E0261]: use of undeclared lifetime name `'a` - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:76:21 + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:75:21 | LL | fn kitten() -> &'a Trait { | ^^ undeclared lifetime @@ -124,7 +124,7 @@ LL | trait Sing<'a> { | ++++ error[E0106]: missing lifetime specifier - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:87:20 + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:86:20 | LL | fn parrot() -> &mut Trait { | ^ expected named lifetime parameter @@ -136,7 +136,7 @@ LL | fn parrot() -> &'static mut Trait { | +++++++ error[E0261]: use of undeclared lifetime name `'a` - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:98:12 + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:96:12 | LL | fn bar(_: &'a Trait) {} | - ^^ undeclared lifetime @@ -144,7 +144,7 @@ LL | fn bar(_: &'a Trait) {} | help: consider introducing lifetime `'a` here: `<'a>` error[E0106]: missing lifetime specifier - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:112:13 + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:110:13 | LL | fn cat() -> &Trait { | ^ expected named lifetime parameter @@ -156,7 +156,7 @@ LL | fn cat() -> &'static Trait { | +++++++ error[E0106]: missing lifetime specifier - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:118:17 + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:116:17 | LL | fn dog<'a>() -> &Trait { | ^ expected named lifetime parameter @@ -168,7 +168,7 @@ LL | fn dog<'a>() -> &'a Trait { | ++ error[E0261]: use of undeclared lifetime name `'a` - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:124:17 + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:122:17 | LL | fn kitten() -> &'a Trait { | - ^^ undeclared lifetime @@ -176,7 +176,7 @@ LL | fn kitten() -> &'a Trait { | help: consider introducing lifetime `'a` here: `<'a>` error[E0106]: missing lifetime specifier - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:135:16 + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:133:16 | LL | fn parrot() -> &mut Trait { | ^ expected named lifetime parameter @@ -187,35 +187,8 @@ help: consider using the `'static` lifetime, but this is uncommon unless you're LL | fn parrot() -> &'static mut Trait { | +++++++ -error[E0515]: cannot return reference to temporary value - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:47:9 - | -LL | &mut Type - | ^^^^^---- - | | | - | | temporary value created here - | returns a reference to data owned by the current function - -error[E0515]: cannot return reference to temporary value - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:90:9 - | -LL | &mut Type - | ^^^^^---- - | | | - | | temporary value created here - | returns a reference to data owned by the current function - -error[E0515]: cannot return reference to temporary value - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:138:5 - | -LL | &mut Type - | ^^^^^---- - | | | - | | temporary value created here - | returns a reference to data owned by the current function - -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:53:16 +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:52:16 | LL | fn foo(_: &Trait); | ^^^^^ @@ -233,8 +206,8 @@ help: alternatively, use a trait object to accept any type that implements `Trai LL | fn foo(_: &dyn Trait); | +++ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:56:19 +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:55:19 | LL | fn bar(_: &'a Trait); | ^^^^^ @@ -252,8 +225,8 @@ help: alternatively, use a trait object to accept any type that implements `Trai LL | fn bar(_: &'a dyn Trait); | +++ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:60:22 +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:59:22 | LL | fn alice<'a>(_: &Trait); | ^^^^^ @@ -271,8 +244,8 @@ help: alternatively, use a trait object to accept any type that implements `Trai LL | fn alice<'a>(_: &dyn Trait); | +++ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:63:23 +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:62:23 | LL | fn bob<'a>(_: &'a Trait); | ^^^^^ @@ -290,8 +263,8 @@ help: alternatively, use a trait object to accept any type that implements `Trai LL | fn bob<'a>(_: &'a dyn Trait); | +++ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:66:18 +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:65:18 | LL | fn cat() -> &Trait; | ^^^^^ @@ -305,8 +278,8 @@ help: alternatively, you can return an owned trait object LL | fn cat() -> Box; | ~~~~~~~~~~~~~~ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:70:22 +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:69:22 | LL | fn dog<'a>() -> &Trait { | ^^^^^ @@ -320,8 +293,8 @@ help: alternatively, you can return an owned trait object LL | fn dog<'a>() -> Box { | ~~~~~~~~~~~~~~ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:76:24 +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:75:24 | LL | fn kitten() -> &'a Trait { | ^^^^^ @@ -335,8 +308,8 @@ help: alternatively, you can return an owned trait object LL | fn kitten() -> Box { | ~~~~~~~~~~~~~~ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:82:27 +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:81:27 | LL | fn puppy<'a>() -> &'a Trait { | ^^^^^ @@ -350,8 +323,8 @@ help: alternatively, you can return an owned trait object LL | fn puppy<'a>() -> Box { | ~~~~~~~~~~~~~~ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:87:25 +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:86:25 | LL | fn parrot() -> &mut Trait { | ^^^^^ @@ -365,8 +338,8 @@ help: alternatively, you can return an owned trait object LL | fn parrot() -> Box { | ~~~~~~~~~~~~~~ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:95:12 +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:93:12 | LL | fn foo(_: &Trait) {} | ^^^^^ @@ -384,8 +357,8 @@ help: alternatively, use a trait object to accept any type that implements `Trai LL | fn foo(_: &dyn Trait) {} | +++ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:98:15 +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:96:15 | LL | fn bar(_: &'a Trait) {} | ^^^^^ @@ -403,8 +376,8 @@ help: alternatively, use a trait object to accept any type that implements `Trai LL | fn bar(_: &'a dyn Trait) {} | +++ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:102:18 +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:100:18 | LL | fn alice<'a>(_: &Trait) {} | ^^^^^ @@ -422,8 +395,8 @@ help: alternatively, use a trait object to accept any type that implements `Trai LL | fn alice<'a>(_: &dyn Trait) {} | +++ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:105:19 +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:103:19 | LL | fn bob<'a>(_: &'a Trait) {} | ^^^^^ @@ -441,8 +414,8 @@ help: alternatively, use a trait object to accept any type that implements `Trai LL | fn bob<'a>(_: &'a dyn Trait) {} | +++ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:112:14 +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:110:14 | LL | fn cat() -> &Trait { | ^^^^^ @@ -456,8 +429,8 @@ help: alternatively, you can return an owned trait object LL | fn cat() -> Box { | ~~~~~~~~~~~~~~ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:118:18 +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:116:18 | LL | fn dog<'a>() -> &Trait { | ^^^^^ @@ -471,8 +444,8 @@ help: alternatively, you can return an owned trait object LL | fn dog<'a>() -> Box { | ~~~~~~~~~~~~~~ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:124:20 +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:122:20 | LL | fn kitten() -> &'a Trait { | ^^^^^ @@ -486,8 +459,8 @@ help: alternatively, you can return an owned trait object LL | fn kitten() -> Box { | ~~~~~~~~~~~~~~ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:130:23 +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:128:23 | LL | fn puppy<'a>() -> &'a Trait { | ^^^^^ @@ -501,8 +474,8 @@ help: alternatively, you can return an owned trait object LL | fn puppy<'a>() -> Box { | ~~~~~~~~~~~~~~ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:135:21 +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:133:21 | LL | fn parrot() -> &mut Trait { | ^^^^^ @@ -516,7 +489,7 @@ help: alternatively, you can return an owned trait object LL | fn parrot() -> Box { | ~~~~~~~~~~~~~~ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:8:16 | LL | fn foo(_: &Trait) {} @@ -535,7 +508,7 @@ help: alternatively, use a trait object to accept any type that implements `Trai LL | fn foo(_: &dyn Trait) {} | +++ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:11:25 | LL | fn bar(self, _: &'a Trait) {} @@ -554,7 +527,7 @@ help: alternatively, use a trait object to accept any type that implements `Trai LL | fn bar(self, _: &'a dyn Trait) {} | +++ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:15:29 | LL | fn alice<'a>(&self, _: &Trait) {} @@ -573,7 +546,7 @@ help: alternatively, use a trait object to accept any type that implements `Trai LL | fn alice<'a>(&self, _: &dyn Trait) {} | +++ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:18:23 | LL | fn bob<'a>(_: &'a Trait) {} @@ -592,7 +565,7 @@ help: alternatively, use a trait object to accept any type that implements `Trai LL | fn bob<'a>(_: &'a dyn Trait) {} | +++ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:21:18 | LL | fn cat() -> &Trait { @@ -607,7 +580,7 @@ help: alternatively, you can return an owned trait object LL | fn cat() -> Box { | ~~~~~~~~~~~~~~ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:27:22 | LL | fn dog<'a>() -> &Trait { @@ -622,7 +595,7 @@ help: alternatively, you can return an owned trait object LL | fn dog<'a>() -> Box { | ~~~~~~~~~~~~~~ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:33:24 | LL | fn kitten() -> &'a Trait { @@ -637,7 +610,7 @@ help: alternatively, you can return an owned trait object LL | fn kitten() -> Box { | ~~~~~~~~~~~~~~ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:39:27 | LL | fn puppy<'a>() -> &'a Trait { @@ -652,7 +625,7 @@ help: alternatively, you can return an owned trait object LL | fn puppy<'a>() -> Box { | ~~~~~~~~~~~~~~ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:44:25 | LL | fn parrot() -> &mut Trait { @@ -667,7 +640,7 @@ help: alternatively, you can return an owned trait object LL | fn parrot() -> Box { | ~~~~~~~~~~~~~~ -error: aborting due to 45 previous errors +error: aborting due to 42 previous errors -Some errors have detailed explanations: E0106, E0261, E0515, E0782. +Some errors have detailed explanations: E0106, E0261, E0782. For more information about an error, try `rustc --explain E0106`. diff --git a/tests/ui/dyn-keyword/dyn-2021-edition-error.rs b/tests/ui/dyn-keyword/dyn-2021-edition-error.rs index f98bf4ef5d1..5d607d82ea1 100644 --- a/tests/ui/dyn-keyword/dyn-2021-edition-error.rs +++ b/tests/ui/dyn-keyword/dyn-2021-edition-error.rs @@ -1,10 +1,10 @@ //@ edition:2021 fn function(x: &SomeTrait, y: Box) { - //~^ ERROR trait objects must include the `dyn` keyword - //~| ERROR trait objects must include the `dyn` keyword + //~^ ERROR expected a type, found a trait + //~| ERROR expected a type, found a trait let _x: &SomeTrait = todo!(); - //~^ ERROR trait objects must include the `dyn` keyword + //~^ ERROR expected a type, found a trait } trait SomeTrait {} diff --git a/tests/ui/dyn-keyword/dyn-2021-edition-error.stderr b/tests/ui/dyn-keyword/dyn-2021-edition-error.stderr index 52ee6c81ab7..6d1a1618ac0 100644 --- a/tests/ui/dyn-keyword/dyn-2021-edition-error.stderr +++ b/tests/ui/dyn-keyword/dyn-2021-edition-error.stderr @@ -1,4 +1,4 @@ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/dyn-2021-edition-error.rs:3:17 | LL | fn function(x: &SomeTrait, y: Box) { @@ -17,24 +17,24 @@ help: alternatively, use a trait object to accept any type that implements `Some LL | fn function(x: &dyn SomeTrait, y: Box) { | +++ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/dyn-2021-edition-error.rs:3:35 | LL | fn function(x: &SomeTrait, y: Box) { | ^^^^^^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | fn function(x: &SomeTrait, y: Box) { | +++ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/dyn-2021-edition-error.rs:6:14 | LL | let _x: &SomeTrait = todo!(); | ^^^^^^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | let _x: &dyn SomeTrait = todo!(); | +++ diff --git a/tests/ui/dyn-keyword/suggest-dyn-on-bare-trait-in-pat.rs b/tests/ui/dyn-keyword/suggest-dyn-on-bare-trait-in-pat.rs index 19b5edb620f..bee15788da9 100644 --- a/tests/ui/dyn-keyword/suggest-dyn-on-bare-trait-in-pat.rs +++ b/tests/ui/dyn-keyword/suggest-dyn-on-bare-trait-in-pat.rs @@ -9,6 +9,7 @@ impl dyn Trait { fn main() { match () { Trait::CONST => {} - //~^ ERROR trait objects must include the `dyn` keyword + //~^ ERROR expected a type, found a trait + //~| HELP you can add the `dyn` keyword if you want a trait object } } diff --git a/tests/ui/dyn-keyword/suggest-dyn-on-bare-trait-in-pat.stderr b/tests/ui/dyn-keyword/suggest-dyn-on-bare-trait-in-pat.stderr index 4446a89b63b..6a2bb3ec09a 100644 --- a/tests/ui/dyn-keyword/suggest-dyn-on-bare-trait-in-pat.stderr +++ b/tests/ui/dyn-keyword/suggest-dyn-on-bare-trait-in-pat.stderr @@ -1,10 +1,10 @@ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/suggest-dyn-on-bare-trait-in-pat.rs:11:9 | LL | Trait::CONST => {} | ^^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | ::CONST => {} | ++++ + diff --git a/tests/ui/editions/dyn-trait-sugg-2021.rs b/tests/ui/editions/dyn-trait-sugg-2021.rs index d702bfb2f88..a5364662600 100644 --- a/tests/ui/editions/dyn-trait-sugg-2021.rs +++ b/tests/ui/editions/dyn-trait-sugg-2021.rs @@ -8,5 +8,5 @@ impl dyn Foo { fn main() { Foo::hi(123); - //~^ ERROR trait objects must include the `dyn` keyword + //~^ ERROR expected a type, found a trait } diff --git a/tests/ui/editions/dyn-trait-sugg-2021.stderr b/tests/ui/editions/dyn-trait-sugg-2021.stderr index 8a65fea11c9..3aea8ac491d 100644 --- a/tests/ui/editions/dyn-trait-sugg-2021.stderr +++ b/tests/ui/editions/dyn-trait-sugg-2021.stderr @@ -1,10 +1,10 @@ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/dyn-trait-sugg-2021.rs:10:5 | LL | Foo::hi(123); | ^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | ::hi(123); | ++++ + diff --git a/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2021.stderr b/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2021.stderr index 7917fa991ee..1e268bc7f49 100644 --- a/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2021.stderr +++ b/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2021.stderr @@ -1,21 +1,14 @@ -error[E0277]: the trait bound `(): AsRef<(dyn for<'a> Fn(&'a ()) + 'static)>` is not satisfied - --> $DIR/generic-with-implicit-hrtb-without-dyn.rs:6:13 - | -LL | fn ice() -> impl AsRef { - | ^^^^^^^^^^^^^^^^^^^ the trait `AsRef<(dyn for<'a> Fn(&'a ()) + 'static)>` is not implemented for `()` - -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/generic-with-implicit-hrtb-without-dyn.rs:6:24 | LL | fn ice() -> impl AsRef { | ^^^^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | fn ice() -> impl AsRef { | +++ -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0277, E0782. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0782`. diff --git a/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.rs b/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.rs index 582386aa759..c71f794d5d1 100644 --- a/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.rs +++ b/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.rs @@ -5,8 +5,7 @@ fn ice() -> impl AsRef { //[edition2015]~^ ERROR: the trait bound `(): AsRef<(dyn for<'a> Fn(&'a ()) + 'static)>` is not satisfied [E0277] - //[edition2021]~^^ ERROR: trait objects must include the `dyn` keyword [E0782] - //[edition2021]~| ERROR: the trait bound `(): AsRef<(dyn for<'a> Fn(&'a ()) + 'static)>` is not satisfied [E0277] + //[edition2021]~^^ ERROR: expected a type, found a trait [E0782] todo!() } diff --git a/tests/ui/resolve/issue-111312.rs b/tests/ui/resolve/issue-111312.rs index 79c6f67dadd..574e9870cd2 100644 --- a/tests/ui/resolve/issue-111312.rs +++ b/tests/ui/resolve/issue-111312.rs @@ -8,6 +8,5 @@ trait HasNot {} fn main() { HasNot::has(); - //~^ ERROR trait objects must include the `dyn` keyword - //~| ERROR no function or associated item named `has` found for trait `HasNot` + //~^ ERROR expected a type, found a trait } diff --git a/tests/ui/resolve/issue-111312.stderr b/tests/ui/resolve/issue-111312.stderr index 431802ead30..a1f8d6bc46c 100644 --- a/tests/ui/resolve/issue-111312.stderr +++ b/tests/ui/resolve/issue-111312.stderr @@ -1,27 +1,14 @@ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/issue-111312.rs:10:5 | LL | HasNot::has(); | ^^^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | ::has(); | ++++ + -error[E0599]: no function or associated item named `has` found for trait `HasNot` - --> $DIR/issue-111312.rs:10:13 - | -LL | HasNot::has(); - | ^^^ function or associated item not found in `HasNot` - | -note: `Has` defines an item `has` - --> $DIR/issue-111312.rs:3:1 - | -LL | trait Has { - | ^^^^^^^^^ +error: aborting due to 1 previous error -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0599, E0782. -For more information about an error, try `rustc --explain E0599`. +For more information about this error, try `rustc --explain E0782`. diff --git a/tests/ui/resolve/issue-111727.rs b/tests/ui/resolve/issue-111727.rs index fcab924b809..a5c2c0ca8c6 100644 --- a/tests/ui/resolve/issue-111727.rs +++ b/tests/ui/resolve/issue-111727.rs @@ -2,6 +2,5 @@ fn main() { std::any::Any::create(); - //~^ ERROR trait objects must include the `dyn` keyword - //~| ERROR no function or associated item named `create` found for trait `Any` + //~^ ERROR expected a type, found a trait } diff --git a/tests/ui/resolve/issue-111727.stderr b/tests/ui/resolve/issue-111727.stderr index 1ef5a1a1d5e..71ea989ac34 100644 --- a/tests/ui/resolve/issue-111727.stderr +++ b/tests/ui/resolve/issue-111727.stderr @@ -1,21 +1,14 @@ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/issue-111727.rs:4:5 | LL | std::any::Any::create(); | ^^^^^^^^^^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | ::create(); | ++++ + -error[E0599]: no function or associated item named `create` found for trait `Any` - --> $DIR/issue-111727.rs:4:20 - | -LL | std::any::Any::create(); - | ^^^^^^ function or associated item not found in `Any` +error: aborting due to 1 previous error -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0599, E0782. -For more information about an error, try `rustc --explain E0599`. +For more information about this error, try `rustc --explain E0782`. diff --git a/tests/ui/rust-2021/ice-return-unsized-can-impl-2.rs b/tests/ui/rust-2021/ice-return-unsized-can-impl-2.rs new file mode 100644 index 00000000000..e57e9ce4844 --- /dev/null +++ b/tests/ui/rust-2021/ice-return-unsized-can-impl-2.rs @@ -0,0 +1,15 @@ +// Doesn't trigger ICE when returning unsized trait that can be impl +// issue https://github.com/rust-lang/rust/issues/125512 +//@ edition:2021 +#![feature(dyn_compatible_for_dispatch)] +trait B { + fn f(a: A) -> A; + //~^ ERROR: expected a type, found a trait + //~| ERROR: expected a type, found a trait +} +trait A { + fn concrete(b: B) -> B; + //~^ ERROR: expected a type, found a trait + //~| ERROR: expected a type, found a trait +} +fn main() {} diff --git a/tests/ui/rust-2021/ice-return-unsized-can-impl-2.stderr b/tests/ui/rust-2021/ice-return-unsized-can-impl-2.stderr new file mode 100644 index 00000000000..b8a9a5c8129 --- /dev/null +++ b/tests/ui/rust-2021/ice-return-unsized-can-impl-2.stderr @@ -0,0 +1,57 @@ +error[E0782]: expected a type, found a trait + --> $DIR/ice-return-unsized-can-impl-2.rs:11:20 + | +LL | fn concrete(b: B) -> B; + | ^ + | + = note: `B` it is dyn-incompatible, so it can't be `dyn` +help: use a new generic type parameter, constrained by `B` + | +LL | fn concrete(b: T) -> B; + | ++++++ ~ +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference + | +LL | fn concrete(b: impl B) -> B; + | ++++ + +error[E0782]: expected a type, found a trait + --> $DIR/ice-return-unsized-can-impl-2.rs:11:26 + | +LL | fn concrete(b: B) -> B; + | ^ + | +help: `B` is dyn-incompatible, use `impl B` to return an opaque type, as long as you return a single underlying type + | +LL | fn concrete(b: B) -> impl B; + | ++++ + +error[E0782]: expected a type, found a trait + --> $DIR/ice-return-unsized-can-impl-2.rs:6:13 + | +LL | fn f(a: A) -> A; + | ^ + | + = note: `A` it is dyn-incompatible, so it can't be `dyn` +help: use a new generic type parameter, constrained by `A` + | +LL | fn f(a: T) -> A; + | ++++++ ~ +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference + | +LL | fn f(a: impl A) -> A; + | ++++ + +error[E0782]: expected a type, found a trait + --> $DIR/ice-return-unsized-can-impl-2.rs:6:19 + | +LL | fn f(a: A) -> A; + | ^ + | +help: `A` is dyn-incompatible, use `impl A` to return an opaque type, as long as you return a single underlying type + | +LL | fn f(a: A) -> impl A; + | ++++ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0782`. diff --git a/tests/ui/rust-2021/ice-return-unsized-can-impl.rs b/tests/ui/rust-2021/ice-return-unsized-can-impl.rs new file mode 100644 index 00000000000..055b11b4424 --- /dev/null +++ b/tests/ui/rust-2021/ice-return-unsized-can-impl.rs @@ -0,0 +1,16 @@ +// Doesn't trigger ICE when returning unsized trait that can be impl +// issue https://github.com/rust-lang/rust/issues/120482 +//@ edition:2021 +#![feature(dyn_compatible_for_dispatch)] + +trait B { + fn bar(&self, x: &Self); +} + +trait A { + fn g(new: B) -> B; + //~^ ERROR: expected a type, found a trait + //~| ERROR: expected a type, found a trait +} + +fn main() {} diff --git a/tests/ui/rust-2021/ice-return-unsized-can-impl.stderr b/tests/ui/rust-2021/ice-return-unsized-can-impl.stderr new file mode 100644 index 00000000000..c0969570e92 --- /dev/null +++ b/tests/ui/rust-2021/ice-return-unsized-can-impl.stderr @@ -0,0 +1,30 @@ +error[E0782]: expected a type, found a trait + --> $DIR/ice-return-unsized-can-impl.rs:11:15 + | +LL | fn g(new: B) -> B; + | ^ + | + = note: `B` it is dyn-incompatible, so it can't be `dyn` +help: use a new generic type parameter, constrained by `B` + | +LL | fn g(new: T) -> B; + | ++++++ ~ +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference + | +LL | fn g(new: impl B) -> B; + | ++++ + +error[E0782]: expected a type, found a trait + --> $DIR/ice-return-unsized-can-impl.rs:11:21 + | +LL | fn g(new: B) -> B; + | ^ + | +help: `B` is dyn-incompatible, use `impl B` to return an opaque type, as long as you return a single underlying type + | +LL | fn g(new: B) -> impl B; + | ++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0782`. diff --git a/tests/ui/rust-2021/ice-unsized-fn-params-2.rs b/tests/ui/rust-2021/ice-unsized-fn-params-2.rs new file mode 100644 index 00000000000..2b4f7bd088f --- /dev/null +++ b/tests/ui/rust-2021/ice-unsized-fn-params-2.rs @@ -0,0 +1,12 @@ +//@ edition:2021 +// Test that it doesn't trigger an ICE when using an unsized fn params. +// https://github.com/rust-lang/rust/issues/120241 +#![feature(dyn_compatible_for_dispatch)] +#![feature(unsized_fn_params)] + +fn guard(_s: Copy) -> bool { + //~^ ERROR: expected a type, found a trait + panic!() +} + +fn main() {} diff --git a/tests/ui/rust-2021/ice-unsized-fn-params-2.stderr b/tests/ui/rust-2021/ice-unsized-fn-params-2.stderr new file mode 100644 index 00000000000..d35c8ab3e42 --- /dev/null +++ b/tests/ui/rust-2021/ice-unsized-fn-params-2.stderr @@ -0,0 +1,19 @@ +error[E0782]: expected a type, found a trait + --> $DIR/ice-unsized-fn-params-2.rs:7:14 + | +LL | fn guard(_s: Copy) -> bool { + | ^^^^ + | + = note: `Copy` it is dyn-incompatible, so it can't be `dyn` +help: use a new generic type parameter, constrained by `Copy` + | +LL | fn guard(_s: T) -> bool { + | +++++++++ ~ +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference + | +LL | fn guard(_s: impl Copy) -> bool { + | ++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0782`. diff --git a/tests/ui/rust-2021/ice-unsized-fn-params.rs b/tests/ui/rust-2021/ice-unsized-fn-params.rs new file mode 100644 index 00000000000..6d8c1c3f152 --- /dev/null +++ b/tests/ui/rust-2021/ice-unsized-fn-params.rs @@ -0,0 +1,18 @@ +//@ edition:2021 +// Test that it doesn't trigger an ICE when using an unsized fn params. +// https://github.com/rust-lang/rust/issues/120241 +#![feature(dyn_compatible_for_dispatch)] + +trait B { + fn f(a: A) -> A; + //~^ ERROR: expected a type, found a trait + //~| ERROR: expected a type, found a trait +} + +trait A { + fn g(b: B) -> B; + //~^ ERROR: expected a type, found a trait + //~| ERROR: expected a type, found a trait +} + +fn main() {} diff --git a/tests/ui/rust-2021/ice-unsized-fn-params.stderr b/tests/ui/rust-2021/ice-unsized-fn-params.stderr new file mode 100644 index 00000000000..d56e9981a28 --- /dev/null +++ b/tests/ui/rust-2021/ice-unsized-fn-params.stderr @@ -0,0 +1,57 @@ +error[E0782]: expected a type, found a trait + --> $DIR/ice-unsized-fn-params.rs:13:13 + | +LL | fn g(b: B) -> B; + | ^ + | + = note: `B` it is dyn-incompatible, so it can't be `dyn` +help: use a new generic type parameter, constrained by `B` + | +LL | fn g(b: T) -> B; + | ++++++ ~ +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference + | +LL | fn g(b: impl B) -> B; + | ++++ + +error[E0782]: expected a type, found a trait + --> $DIR/ice-unsized-fn-params.rs:13:19 + | +LL | fn g(b: B) -> B; + | ^ + | +help: `B` is dyn-incompatible, use `impl B` to return an opaque type, as long as you return a single underlying type + | +LL | fn g(b: B) -> impl B; + | ++++ + +error[E0782]: expected a type, found a trait + --> $DIR/ice-unsized-fn-params.rs:7:13 + | +LL | fn f(a: A) -> A; + | ^ + | + = note: `A` it is dyn-incompatible, so it can't be `dyn` +help: use a new generic type parameter, constrained by `A` + | +LL | fn f(a: T) -> A; + | ++++++ ~ +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference + | +LL | fn f(a: impl A) -> A; + | ++++ + +error[E0782]: expected a type, found a trait + --> $DIR/ice-unsized-fn-params.rs:7:19 + | +LL | fn f(a: A) -> A; + | ^ + | +help: `A` is dyn-incompatible, use `impl A` to return an opaque type, as long as you return a single underlying type + | +LL | fn f(a: A) -> impl A; + | ++++ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0782`. diff --git a/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs index 37afab6b643..10b4781eb04 100644 --- a/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs +++ b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs @@ -2,24 +2,21 @@ #![allow(bare_trait_objects)] trait A: Sized { fn f(a: A) -> A; - //~^ ERROR trait objects must include the `dyn` keyword - //~| ERROR trait objects must include the `dyn` keyword + //~^ ERROR expected a type, found a trait + //~| ERROR expected a type, found a trait //~| ERROR associated item referring to unboxed trait object for its own trait - //~| ERROR the trait `A` cannot be made into an object } trait B { fn f(b: B) -> B; - //~^ ERROR trait objects must include the `dyn` keyword - //~| ERROR trait objects must include the `dyn` keyword + //~^ ERROR expected a type, found a trait + //~| ERROR expected a type, found a trait //~| ERROR associated item referring to unboxed trait object for its own trait - //~| ERROR the trait `B` cannot be made into an object } trait C { fn f(&self, c: C) -> C; - //~^ ERROR trait objects must include the `dyn` keyword - //~| ERROR trait objects must include the `dyn` keyword + //~^ ERROR expected a type, found a trait + //~| ERROR expected a type, found a trait //~| ERROR associated item referring to unboxed trait object for its own trait - //~| ERROR the trait `C` cannot be made into an object } fn main() {} diff --git a/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021-without-dyn.stderr b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021-without-dyn.stderr index 53304382584..c0cfb18955c 100644 --- a/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021-without-dyn.stderr +++ b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021-without-dyn.stderr @@ -11,22 +11,8 @@ help: you might have meant to use `Self` to refer to the implementing type LL | fn f(a: Self) -> Self; | ~~~~ ~~~~ -error[E0038]: the trait `A` cannot be made into an object - --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:4:13 - | -LL | fn f(a: A) -> A; - | ^ `A` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:3:10 - | -LL | trait A: Sized { - | - ^^^^^ ...because it requires `Self: Sized` - | | - | this trait cannot be made into an object... - error: associated item referring to unboxed trait object for its own trait - --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:11:13 + --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:10:13 | LL | trait B { | - in this trait @@ -38,30 +24,8 @@ help: you might have meant to use `Self` to refer to the implementing type LL | fn f(b: Self) -> Self; | ~~~~ ~~~~ -error[E0038]: the trait `B` cannot be made into an object - --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:11:13 - | -LL | fn f(b: B) -> B; - | ^ `B` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:11:8 - | -LL | trait B { - | - this trait cannot be made into an object... -LL | fn f(b: B) -> B; - | ^ ...because associated function `f` has no `self` parameter -help: consider turning `f` into a method by giving it a `&self` argument - | -LL | fn f(&self, b: B) -> B; - | ++++++ -help: alternatively, consider constraining `f` so it does not apply to trait objects - | -LL | fn f(b: B) -> B where Self: Sized; - | +++++++++++++++++ - error: associated item referring to unboxed trait object for its own trait - --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:18:20 + --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:16:20 | LL | trait C { | - in this trait @@ -73,23 +37,7 @@ help: you might have meant to use `Self` to refer to the implementing type LL | fn f(&self, c: Self) -> Self; | ~~~~ ~~~~ -error[E0038]: the trait `C` cannot be made into an object - --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:18:20 - | -LL | fn f(&self, c: C) -> C; - | ----- ^ `C` cannot be made into an object - | | - | help: consider changing method `f`'s `self` parameter to be `&self` (notice the capitalization): `&Self` - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:18:10 - | -LL | trait C { - | - this trait cannot be made into an object... -LL | fn f(&self, c: C) -> C; - | ^^^^^ ...because method `f`'s `self` parameter cannot be dispatched on - -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:4:13 | LL | fn f(a: A) -> A; @@ -105,7 +53,7 @@ help: you can also use an opaque type, but users won't be able to specify the ty LL | fn f(a: impl A) -> A; | ++++ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:4:19 | LL | fn f(a: A) -> A; @@ -116,8 +64,8 @@ help: `A` is dyn-incompatible, use `impl A` to return an opaque type, as long as LL | fn f(a: A) -> impl A; | ++++ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:11:13 +error[E0782]: expected a type, found a trait + --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:10:13 | LL | fn f(b: B) -> B; | ^ @@ -132,8 +80,8 @@ help: you can also use an opaque type, but users won't be able to specify the ty LL | fn f(b: impl B) -> B; | ++++ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:11:19 +error[E0782]: expected a type, found a trait + --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:10:19 | LL | fn f(b: B) -> B; | ^ @@ -143,8 +91,8 @@ help: `B` is dyn-incompatible, use `impl B` to return an opaque type, as long as LL | fn f(b: B) -> impl B; | ++++ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:18:20 +error[E0782]: expected a type, found a trait + --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:16:20 | LL | fn f(&self, c: C) -> C; | ^ @@ -159,8 +107,8 @@ help: you can also use an opaque type, but users won't be able to specify the ty LL | fn f(&self, c: impl C) -> C; | ++++ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:18:26 +error[E0782]: expected a type, found a trait + --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:16:26 | LL | fn f(&self, c: C) -> C; | ^ @@ -170,7 +118,6 @@ help: `C` is dyn-incompatible, use `impl C` to return an opaque type, as long as LL | fn f(&self, c: C) -> impl C; | ++++ -error: aborting due to 12 previous errors +error: aborting due to 9 previous errors -Some errors have detailed explanations: E0038, E0782. -For more information about an error, try `rustc --explain E0038`. +For more information about this error, try `rustc --explain E0782`. diff --git a/tests/ui/suggestions/issue-116434-2021.rs b/tests/ui/suggestions/issue-116434-2021.rs index 6feba3dc6c1..77cdfb8b614 100644 --- a/tests/ui/suggestions/issue-116434-2021.rs +++ b/tests/ui/suggestions/issue-116434-2021.rs @@ -3,7 +3,8 @@ trait Foo { type Clone; fn foo() -> Clone; - //~^ ERROR the trait `Clone` cannot be made into an object [E0038] + //~^ ERROR expected a type, found a trait + //~| HELP `Clone` is dyn-incompatible, use `impl Clone` to return an opaque type, as long as you return a single underlying type //~| HELP there is an associated type with the same name } @@ -12,7 +13,8 @@ trait DbHandle: Sized {} trait DbInterface { type DbHandle; fn handle() -> DbHandle; - //~^ ERROR the trait `DbHandle` cannot be made into an object [E0038] + //~^ ERROR expected a type, found a trait + //~| HELP `DbHandle` is dyn-incompatible, use `impl DbHandle` to return an opaque type, as long as you return a single underlying type //~| HELP there is an associated type with the same name } diff --git a/tests/ui/suggestions/issue-116434-2021.stderr b/tests/ui/suggestions/issue-116434-2021.stderr index 7f8cc147210..3853f03f1db 100644 --- a/tests/ui/suggestions/issue-116434-2021.stderr +++ b/tests/ui/suggestions/issue-116434-2021.stderr @@ -1,29 +1,28 @@ -error[E0038]: the trait `Clone` cannot be made into an object +error[E0782]: expected a type, found a trait --> $DIR/issue-116434-2021.rs:5:17 | LL | fn foo() -> Clone; - | ^^^^^ `Clone` cannot be made into an object + | ^^^^^ | - = note: the trait cannot be made into an object because it requires `Self: Sized` - = note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit +help: `Clone` is dyn-incompatible, use `impl Clone` to return an opaque type, as long as you return a single underlying type + | +LL | fn foo() -> impl Clone; + | ++++ help: there is an associated type with the same name | LL | fn foo() -> Self::Clone; | ++++++ -error[E0038]: the trait `DbHandle` cannot be made into an object - --> $DIR/issue-116434-2021.rs:14:20 +error[E0782]: expected a type, found a trait + --> $DIR/issue-116434-2021.rs:15:20 | LL | fn handle() -> DbHandle; - | ^^^^^^^^ `DbHandle` cannot be made into an object + | ^^^^^^^^ | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/issue-116434-2021.rs:10:17 +help: `DbHandle` is dyn-incompatible, use `impl DbHandle` to return an opaque type, as long as you return a single underlying type | -LL | trait DbHandle: Sized {} - | -------- ^^^^^ ...because it requires `Self: Sized` - | | - | this trait cannot be made into an object... +LL | fn handle() -> impl DbHandle; + | ++++ help: there is an associated type with the same name | LL | fn handle() -> Self::DbHandle; @@ -31,4 +30,4 @@ LL | fn handle() -> Self::DbHandle; error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0038`. +For more information about this error, try `rustc --explain E0782`. diff --git a/tests/ui/suggestions/suggest-blanket-impl-local-trait.rs b/tests/ui/suggestions/suggest-blanket-impl-local-trait.rs index 76300c6a3f4..dd7e203abd7 100644 --- a/tests/ui/suggestions/suggest-blanket-impl-local-trait.rs +++ b/tests/ui/suggestions/suggest-blanket-impl-local-trait.rs @@ -11,48 +11,48 @@ trait LocalTraitTwo { } trait GenericTrait {} impl LocalTraitTwo for LocalTraitOne {} -//~^ ERROR trait objects must include the `dyn` keyword -//~| HELP add `dyn` keyword before this trait +//~^ ERROR expected a type, found a trait +//~| HELP you can add the `dyn` keyword if you want a trait object //~| HELP alternatively use a blanket implementation to implement `LocalTraitTwo` for all types that also implement `LocalTraitOne` impl fmt::Display for LocalTraitOne { -//~^ ERROR trait objects must include the `dyn` keyword -//~| HELP add `dyn` keyword before this trait +//~^ ERROR expected a type, found a trait +//~| HELP you can add the `dyn` keyword if you want a trait object fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { todo!(); } } impl fmt::Display for LocalTraitTwo + Send { -//~^ ERROR trait objects must include the `dyn` keyword -//~| HELP add `dyn` keyword before this trait +//~^ ERROR expected a type, found a trait +//~| HELP you can add the `dyn` keyword if you want a trait object fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { todo!(); } } impl LocalTraitOne for fmt::Display {} -//~^ ERROR trait objects must include the `dyn` keyword -//~| HELP add `dyn` keyword before this trait +//~^ ERROR expected a type, found a trait +//~| HELP you can add the `dyn` keyword if you want a trait object //~| HELP alternatively use a blanket implementation to implement `LocalTraitOne` for all types that also implement `fmt::Display` impl LocalTraitOne for fmt::Display + Send {} -//~^ ERROR trait objects must include the `dyn` keyword -//~| HELP add `dyn` keyword before this trait +//~^ ERROR expected a type, found a trait +//~| HELP you can add the `dyn` keyword if you want a trait object //~| HELP alternatively use a blanket implementation to implement `LocalTraitOne` for all types that also implement `fmt::Display + Send` impl GenericTrait for LocalTraitOne {} -//~^ ERROR trait objects must include the `dyn` keyword -//~| HELP add `dyn` keyword before this trait +//~^ ERROR expected a type, found a trait +//~| HELP you can add the `dyn` keyword if you want a trait object //~| HELP alternatively use a blanket implementation to implement `GenericTrait` for all types that also implement `LocalTraitOne` trait GenericTraitTwo {} impl GenericTraitTwo for GenericTrait {} -//~^ ERROR trait objects must include the `dyn` keyword -//~| HELP add `dyn` keyword before this trait +//~^ ERROR expected a type, found a trait +//~| HELP you can add the `dyn` keyword if you want a trait object //~| HELP alternatively use a blanket implementation to implement `GenericTraitTwo` for all types that also implement `GenericTrait` fn main() {} diff --git a/tests/ui/suggestions/suggest-blanket-impl-local-trait.stderr b/tests/ui/suggestions/suggest-blanket-impl-local-trait.stderr index 769f3bd64f3..102438e1ec5 100644 --- a/tests/ui/suggestions/suggest-blanket-impl-local-trait.stderr +++ b/tests/ui/suggestions/suggest-blanket-impl-local-trait.stderr @@ -1,10 +1,10 @@ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/suggest-blanket-impl-local-trait.rs:34:24 | LL | impl LocalTraitOne for fmt::Display {} | ^^^^^^^^^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | impl LocalTraitOne for dyn fmt::Display {} | +++ @@ -13,13 +13,13 @@ help: alternatively use a blanket implementation to implement `LocalTraitOne` fo LL | impl LocalTraitOne for T {} | +++++++++++++++++ ~ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/suggest-blanket-impl-local-trait.rs:40:24 | LL | impl LocalTraitOne for fmt::Display + Send {} | ^^^^^^^^^^^^^^^^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | impl LocalTraitOne for dyn fmt::Display + Send {} | +++ @@ -28,13 +28,13 @@ help: alternatively use a blanket implementation to implement `LocalTraitOne` fo LL | impl LocalTraitOne for T {} | ++++++++++++++++++++++++ ~ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/suggest-blanket-impl-local-trait.rs:13:24 | LL | impl LocalTraitTwo for LocalTraitOne {} | ^^^^^^^^^^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | impl LocalTraitTwo for dyn LocalTraitOne {} | +++ @@ -43,13 +43,13 @@ help: alternatively use a blanket implementation to implement `LocalTraitTwo` fo LL | impl LocalTraitTwo for T {} | ++++++++++++++++++ ~ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/suggest-blanket-impl-local-trait.rs:46:29 | LL | impl GenericTrait for LocalTraitOne {} | ^^^^^^^^^^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | impl GenericTrait for dyn LocalTraitOne {} | +++ @@ -58,35 +58,35 @@ help: alternatively use a blanket implementation to implement `GenericTrait` LL | impl GenericTrait for T {} | ++++++++++++++++++ ~ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/suggest-blanket-impl-local-trait.rs:18:23 | LL | impl fmt::Display for LocalTraitOne { | ^^^^^^^^^^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | impl fmt::Display for dyn LocalTraitOne { | +++ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/suggest-blanket-impl-local-trait.rs:26:23 | LL | impl fmt::Display for LocalTraitTwo + Send { | ^^^^^^^^^^^^^^^^^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | impl fmt::Display for dyn LocalTraitTwo + Send { | +++ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/suggest-blanket-impl-local-trait.rs:53:35 | LL | impl GenericTraitTwo for GenericTrait {} | ^^^^^^^^^^^^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | impl GenericTraitTwo for dyn GenericTrait {} | +++ diff --git a/tests/ui/suggestions/suggest-swapping-self-ty-and-trait-edition-2021.rs b/tests/ui/suggestions/suggest-swapping-self-ty-and-trait-edition-2021.rs index a5ab8be7f45..fe36d093430 100644 --- a/tests/ui/suggestions/suggest-swapping-self-ty-and-trait-edition-2021.rs +++ b/tests/ui/suggestions/suggest-swapping-self-ty-and-trait-edition-2021.rs @@ -14,14 +14,14 @@ pub union Union { impl<'a, T> Struct for Trait<'a, T> {} //~^ ERROR expected trait, found struct `Struct` -//~| ERROR trait objects must include the `dyn` keyword +//~| ERROR expected a type, found a trait impl<'a, T> Enum for Trait<'a, T> {} //~^ ERROR expected trait, found enum `Enum` -//~| ERROR trait objects must include the `dyn` keyword +//~| ERROR expected a type, found a trait impl<'a, T> Union for Trait<'a, T> {} //~^ ERROR expected trait, found union `Union` -//~| ERROR trait objects must include the `dyn` keyword +//~| ERROR expected a type, found a trait fn main() {} diff --git a/tests/ui/suggestions/suggest-swapping-self-ty-and-trait-edition-2021.stderr b/tests/ui/suggestions/suggest-swapping-self-ty-and-trait-edition-2021.stderr index 2893370570d..0bd601e2170 100644 --- a/tests/ui/suggestions/suggest-swapping-self-ty-and-trait-edition-2021.stderr +++ b/tests/ui/suggestions/suggest-swapping-self-ty-and-trait-edition-2021.stderr @@ -58,35 +58,35 @@ LL | pub union Union { = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/suggest-swapping-self-ty-and-trait-edition-2021.rs:15:27 | LL | impl<'a, T> Struct for Trait<'a, T> {} | ^^^^^^^^^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | impl<'a, T> Struct for dyn Trait<'a, T> {} | +++ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/suggest-swapping-self-ty-and-trait-edition-2021.rs:19:25 | LL | impl<'a, T> Enum for Trait<'a, T> {} | ^^^^^^^^^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | impl<'a, T> Enum for dyn Trait<'a, T> {} | +++ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/suggest-swapping-self-ty-and-trait-edition-2021.rs:23:26 | LL | impl<'a, T> Union for Trait<'a, T> {} | ^^^^^^^^^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | impl<'a, T> Union for dyn Trait<'a, T> {} | +++ diff --git a/tests/ui/traits/bound/not-on-bare-trait-2021.rs b/tests/ui/traits/bound/not-on-bare-trait-2021.rs index 07b866cb4a6..93d2f04b54e 100644 --- a/tests/ui/traits/bound/not-on-bare-trait-2021.rs +++ b/tests/ui/traits/bound/not-on-bare-trait-2021.rs @@ -6,13 +6,11 @@ trait Foo { // This should emit the less confusing error, not the more confusing one. fn foo(_x: Foo + Send) { - //~^ ERROR trait objects must include the `dyn` keyword - //~| ERROR size for values of type + //~^ ERROR expected a type, found a trait } fn bar(x: Foo) -> Foo { - //~^ ERROR trait objects must include the `dyn` keyword - //~| ERROR trait objects must include the `dyn` keyword - //~| ERROR size for values of type + //~^ ERROR expected a type, found a trait + //~| ERROR expected a type, found a trait x } diff --git a/tests/ui/traits/bound/not-on-bare-trait-2021.stderr b/tests/ui/traits/bound/not-on-bare-trait-2021.stderr index e05ae8e5267..e50186aff7e 100644 --- a/tests/ui/traits/bound/not-on-bare-trait-2021.stderr +++ b/tests/ui/traits/bound/not-on-bare-trait-2021.stderr @@ -1,38 +1,4 @@ -error[E0277]: the size for values of type `(dyn Foo + Send + 'static)` cannot be known at compilation time - --> $DIR/not-on-bare-trait-2021.rs:8:12 - | -LL | fn foo(_x: Foo + Send) { - | ^^^^^^^^^^ doesn't have a size known at compile-time - | - = help: the trait `Sized` is not implemented for `(dyn Foo + Send + 'static)` - = help: unsized fn params are gated as an unstable feature -help: you can use `impl Trait` as the argument type - | -LL | fn foo(_x: impl Foo + Send) { - | ++++ -help: function arguments must have a statically known size, borrowed types always have a known size - | -LL | fn foo(_x: &(dyn Foo + Send)) { - | +++++ + - -error[E0277]: the size for values of type `(dyn Foo + 'static)` cannot be known at compilation time - --> $DIR/not-on-bare-trait-2021.rs:12:11 - | -LL | fn bar(x: Foo) -> Foo { - | ^^^ doesn't have a size known at compile-time - | - = help: the trait `Sized` is not implemented for `(dyn Foo + 'static)` - = help: unsized fn params are gated as an unstable feature -help: you can use `impl Trait` as the argument type - | -LL | fn bar(x: impl Foo) -> Foo { - | ++++ -help: function arguments must have a statically known size, borrowed types always have a known size - | -LL | fn bar(x: &dyn Foo) -> Foo { - | ++++ - -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/not-on-bare-trait-2021.rs:8:12 | LL | fn foo(_x: Foo + Send) { @@ -51,8 +17,8 @@ help: alternatively, use a trait object to accept any type that implements `Foo LL | fn foo(_x: &(dyn Foo + Send)) { | +++++ + -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/not-on-bare-trait-2021.rs:12:11 +error[E0782]: expected a type, found a trait + --> $DIR/not-on-bare-trait-2021.rs:11:11 | LL | fn bar(x: Foo) -> Foo { | ^^^ @@ -70,8 +36,8 @@ help: alternatively, use a trait object to accept any type that implements `Foo` LL | fn bar(x: &dyn Foo) -> Foo { | ++++ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/not-on-bare-trait-2021.rs:12:19 +error[E0782]: expected a type, found a trait + --> $DIR/not-on-bare-trait-2021.rs:11:19 | LL | fn bar(x: Foo) -> Foo { | ^^^ @@ -85,7 +51,6 @@ help: alternatively, you can return an owned trait object LL | fn bar(x: Foo) -> Box { | +++++++ + -error: aborting due to 5 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0277, E0782. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0782`. diff --git a/tests/ui/traits/issue-106072.rs b/tests/ui/traits/issue-106072.rs index 8adbac46a5b..696bd765ebc 100644 --- a/tests/ui/traits/issue-106072.rs +++ b/tests/ui/traits/issue-106072.rs @@ -1,6 +1,4 @@ -#[derive(Clone)] //~ trait objects must include the `dyn` keyword -//~^ ERROR: the size for values of type `(dyn Foo + 'static)` cannot be known -//~| ERROR: return type cannot have an unboxed trait object +#[derive(Clone)] //~ expected a type, found a trait struct Foo; trait Foo {} //~ the name `Foo` is defined multiple times fn main() {} diff --git a/tests/ui/traits/issue-106072.stderr b/tests/ui/traits/issue-106072.stderr index 6476c8b3237..4a48e4e898d 100644 --- a/tests/ui/traits/issue-106072.stderr +++ b/tests/ui/traits/issue-106072.stderr @@ -1,5 +1,5 @@ error[E0428]: the name `Foo` is defined multiple times - --> $DIR/issue-106072.rs:5:1 + --> $DIR/issue-106072.rs:3:1 | LL | struct Foo; | ----------- previous definition of the type `Foo` here @@ -8,26 +8,7 @@ LL | trait Foo {} | = note: `Foo` must be defined only once in the type namespace of this module -error[E0277]: the size for values of type `(dyn Foo + 'static)` cannot be known at compilation time - --> $DIR/issue-106072.rs:1:10 - | -LL | #[derive(Clone)] - | ^^^^^ doesn't have a size known at compile-time - | - = help: the trait `Sized` is not implemented for `(dyn Foo + 'static)` -note: required by a bound in `Clone` - --> $SRC_DIR/core/src/clone.rs:LL:COL - = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) - -error[E0746]: return type cannot have an unboxed trait object - --> $DIR/issue-106072.rs:1:10 - | -LL | #[derive(Clone)] - | ^^^^^ doesn't have a size known at compile-time - | - = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) - -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/issue-106072.rs:1:10 | LL | #[derive(Clone)] @@ -35,7 +16,7 @@ LL | #[derive(Clone)] | = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0277, E0428, E0746, E0782. -For more information about an error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0428, E0782. +For more information about an error, try `rustc --explain E0428`. diff --git a/tests/ui/traits/missing-for-type-in-impl.e2021.stderr b/tests/ui/traits/missing-for-type-in-impl.e2021.stderr index b5a607a54cb..a49c5d9d45b 100644 --- a/tests/ui/traits/missing-for-type-in-impl.e2021.stderr +++ b/tests/ui/traits/missing-for-type-in-impl.e2021.stderr @@ -10,13 +10,13 @@ help: this trait has no implementations, consider adding one LL | trait Foo { | ^^^^^^^^^^^^ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/missing-for-type-in-impl.rs:8:6 | LL | impl Foo { | ^^^^^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | impl dyn Foo { | +++ diff --git a/tests/ui/traits/missing-for-type-in-impl.rs b/tests/ui/traits/missing-for-type-in-impl.rs index 7d4ad479e77..e5dd3651609 100644 --- a/tests/ui/traits/missing-for-type-in-impl.rs +++ b/tests/ui/traits/missing-for-type-in-impl.rs @@ -6,7 +6,7 @@ trait Foo { /* note the "missing" for ... (in this case for i64, in order for this to compile) */ impl Foo { -//[e2021]~^ ERROR trait objects must include the `dyn` keyword +//[e2021]~^ ERROR expected a type, found a trait //[e2015]~^^ WARNING trait objects without an explicit `dyn` are deprecated //[e2015]~| WARNING trait objects without an explicit `dyn` are deprecated //[e2015]~| WARNING this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! From 181e667626c7b4174555b8b400b989d0cfc06599 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 5 Oct 2024 13:20:22 +0200 Subject: [PATCH 200/357] stabilize duration_consts_float --- library/core/src/lib.rs | 1 - library/core/src/time.rs | 12 ++++++------ library/core/tests/lib.rs | 1 - 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index e323e88f261..5b75273087d 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -156,7 +156,6 @@ #![feature(const_unicode_case_lookup)] #![feature(coverage_attribute)] #![feature(do_not_recommend)] -#![feature(duration_consts_float)] #![feature(internal_impls_macro)] #![feature(ip)] #![feature(is_ascii_octdigit)] diff --git a/library/core/src/time.rs b/library/core/src/time.rs index 65560dfcf9d..a997874dd9c 100644 --- a/library/core/src/time.rs +++ b/library/core/src/time.rs @@ -847,7 +847,7 @@ impl Duration { #[stable(feature = "duration_float", since = "1.38.0")] #[must_use] #[inline] - #[rustc_const_unstable(feature = "duration_consts_float", issue = "72440")] + #[rustc_const_stable(feature = "duration_consts_float", since = "CURRENT_RUSTC_VERSION")] pub const fn as_secs_f64(&self) -> f64 { (self.secs as f64) + (self.nanos.0 as f64) / (NANOS_PER_SEC as f64) } @@ -866,7 +866,7 @@ impl Duration { #[stable(feature = "duration_float", since = "1.38.0")] #[must_use] #[inline] - #[rustc_const_unstable(feature = "duration_consts_float", issue = "72440")] + #[rustc_const_stable(feature = "duration_consts_float", since = "CURRENT_RUSTC_VERSION")] pub const fn as_secs_f32(&self) -> f32 { (self.secs as f32) + (self.nanos.0 as f32) / (NANOS_PER_SEC as f32) } @@ -886,7 +886,7 @@ impl Duration { #[unstable(feature = "duration_millis_float", issue = "122451")] #[must_use] #[inline] - #[rustc_const_unstable(feature = "duration_consts_float", issue = "72440")] + #[rustc_const_unstable(feature = "duration_millis_float", issue = "122451")] pub const fn as_millis_f64(&self) -> f64 { (self.secs as f64) * (MILLIS_PER_SEC as f64) + (self.nanos.0 as f64) / (NANOS_PER_MILLI as f64) @@ -907,7 +907,7 @@ impl Duration { #[unstable(feature = "duration_millis_float", issue = "122451")] #[must_use] #[inline] - #[rustc_const_unstable(feature = "duration_consts_float", issue = "72440")] + #[rustc_const_unstable(feature = "duration_millis_float", issue = "122451")] pub const fn as_millis_f32(&self) -> f32 { (self.secs as f32) * (MILLIS_PER_SEC as f32) + (self.nanos.0 as f32) / (NANOS_PER_MILLI as f32) @@ -1087,7 +1087,7 @@ impl Duration { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - #[rustc_const_unstable(feature = "duration_consts_float", issue = "72440")] + #[rustc_const_stable(feature = "duration_consts_float", since = "CURRENT_RUSTC_VERSION")] pub const fn div_duration_f64(self, rhs: Duration) -> f64 { let self_nanos = (self.secs as f64) * (NANOS_PER_SEC as f64) + (self.nanos.0 as f64); let rhs_nanos = (rhs.secs as f64) * (NANOS_PER_SEC as f64) + (rhs.nanos.0 as f64); @@ -1108,7 +1108,7 @@ impl Duration { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - #[rustc_const_unstable(feature = "duration_consts_float", issue = "72440")] + #[rustc_const_stable(feature = "duration_consts_float", since = "CURRENT_RUSTC_VERSION")] pub const fn div_duration_f32(self, rhs: Duration) -> f32 { let self_nanos = (self.secs as f32) * (NANOS_PER_SEC as f32) + (self.nanos.0 as f32); let rhs_nanos = (rhs.secs as f32) * (NANOS_PER_SEC as f32) + (rhs.nanos.0 as f32); diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 196e91ee3e9..e2d3d86f632 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -42,7 +42,6 @@ #![feature(dec2flt)] #![feature(duration_constants)] #![feature(duration_constructors)] -#![feature(duration_consts_float)] #![feature(error_generic_member_access)] #![feature(exact_size_is_empty)] #![feature(extern_types)] From 19345d5c6ec522e6037c76c52fccd83860515313 Mon Sep 17 00:00:00 2001 From: Augie Fackler Date: Fri, 11 Oct 2024 11:29:37 -0400 Subject: [PATCH 201/357] RustWrapper: adapt for rename of Intrinsic::getDeclaration llvm/llvm-project@fa789dffb1e12c2aece0187aeacc48dfb1768340 renamed getDeclaration to getOrInsertDeclaration. @rustbot label: +llvm-main --- .../rustc_llvm/llvm-wrapper/RustWrapper.cpp | 25 ++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index 8faa5212408..72b03fa0560 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -1533,27 +1533,40 @@ extern "C" LLVMValueRef LLVMRustBuildCall(LLVMBuilderRef B, LLVMTypeRef Ty, extern "C" LLVMValueRef LLVMRustGetInstrProfIncrementIntrinsic(LLVMModuleRef M) { +#if LLVM_VERSION_GE(20, 0) + return wrap(llvm::Intrinsic::getOrInsertDeclaration( + unwrap(M), llvm::Intrinsic::instrprof_increment)); +#else return wrap(llvm::Intrinsic::getDeclaration( unwrap(M), llvm::Intrinsic::instrprof_increment)); +#endif } extern "C" LLVMValueRef LLVMRustGetInstrProfMCDCParametersIntrinsic(LLVMModuleRef M) { -#if LLVM_VERSION_GE(19, 0) - return wrap(llvm::Intrinsic::getDeclaration( +#if LLVM_VERSION_LT(19, 0) + report_fatal_error("LLVM 19.0 is required for mcdc intrinsic functions"); +#endif +#if LLVM_VERSION_GE(20, 0) + return wrap(llvm::Intrinsic::getOrInsertDeclaration( unwrap(M), llvm::Intrinsic::instrprof_mcdc_parameters)); #else - report_fatal_error("LLVM 19.0 is required for mcdc intrinsic functions"); + return wrap(llvm::Intrinsic::getDeclaration( + unwrap(M), llvm::Intrinsic::instrprof_mcdc_parameters)); #endif } extern "C" LLVMValueRef LLVMRustGetInstrProfMCDCTVBitmapUpdateIntrinsic(LLVMModuleRef M) { -#if LLVM_VERSION_GE(19, 0) - return wrap(llvm::Intrinsic::getDeclaration( +#if LLVM_VERSION_LT(19, 0) + report_fatal_error("LLVM 19.0 is required for mcdc intrinsic functions"); +#endif +#if LLVM_VERSION_GE(20, 0) + return wrap(llvm::Intrinsic::getOrInsertDeclaration( unwrap(M), llvm::Intrinsic::instrprof_mcdc_tvbitmap_update)); #else - report_fatal_error("LLVM 19.0 is required for mcdc intrinsic functions"); + return wrap(llvm::Intrinsic::getDeclaration( + unwrap(M), llvm::Intrinsic::instrprof_mcdc_tvbitmap_update)); #endif } From 92f65684a8433ade29d8fea8c258dd7eed22ea3f Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 5 Oct 2024 13:04:18 +0200 Subject: [PATCH 202/357] stabilize const_result --- library/core/src/result.rs | 13 +++++++++---- library/core/tests/lib.rs | 1 - 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 610edae48d3..95faacbf96d 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -734,7 +734,8 @@ impl Result { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_result", issue = "82814")] + #[rustc_const_stable(feature = "const_result", since = "CURRENT_RUSTC_VERSION")] + #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn as_mut(&mut self) -> Result<&mut T, &mut E> { match *self { Ok(ref mut x) => Ok(x), @@ -1536,7 +1537,8 @@ impl Result<&T, E> { /// ``` #[inline] #[stable(feature = "result_copied", since = "1.59.0")] - #[rustc_const_unstable(feature = "const_result", issue = "82814")] + #[rustc_const_stable(feature = "const_result", since = "CURRENT_RUSTC_VERSION")] + #[rustc_allow_const_fn_unstable(const_precise_live_drops)] pub const fn copied(self) -> Result where T: Copy, @@ -1586,7 +1588,9 @@ impl Result<&mut T, E> { /// ``` #[inline] #[stable(feature = "result_copied", since = "1.59.0")] - #[rustc_const_unstable(feature = "const_result", issue = "82814")] + #[rustc_const_stable(feature = "const_result", since = "CURRENT_RUSTC_VERSION")] + #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] + #[rustc_allow_const_fn_unstable(const_precise_live_drops)] pub const fn copied(self) -> Result where T: Copy, @@ -1639,7 +1643,8 @@ impl Result, E> { /// ``` #[inline] #[stable(feature = "transpose_result", since = "1.33.0")] - #[rustc_const_unstable(feature = "const_result", issue = "82814")] + #[rustc_const_stable(feature = "const_result", since = "CURRENT_RUSTC_VERSION")] + #[rustc_allow_const_fn_unstable(const_precise_live_drops)] pub const fn transpose(self) -> Option> { match self { Ok(Some(x)) => Some(Ok(x)), diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 0d4ec96f842..d5f7010343e 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -29,7 +29,6 @@ #![feature(const_pin)] #![feature(const_pointer_is_aligned)] #![feature(const_ptr_write)] -#![feature(const_result)] #![feature(const_three_way_compare)] #![feature(const_trait_impl)] #![feature(core_intrinsics)] From 734481cbdc178c58cd21a28fd07563abcceef9d2 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 11 Oct 2024 09:55:11 -0700 Subject: [PATCH 203/357] Bump to 1.84 --- src/version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/version b/src/version index 6b4de0a42b0..bd0f9e6c28f 100644 --- a/src/version +++ b/src/version @@ -1 +1 @@ -1.83.0 +1.84.0 From 624c071b997f3bab0ef086af24f59ebc95f37c59 Mon Sep 17 00:00:00 2001 From: Manuel Drehwald Date: Fri, 11 Oct 2024 19:13:31 +0200 Subject: [PATCH 204/357] Single commit implementing the enzyme/autodiff frontend Co-authored-by: Lorenz Schmidt --- .../rustc_ast/src/expand/autodiff_attrs.rs | 283 ++++++ compiler/rustc_ast/src/expand/mod.rs | 2 + compiler/rustc_ast/src/expand/typetree.rs | 90 ++ compiler/rustc_builtin_macros/Cargo.toml | 4 + compiler/rustc_builtin_macros/messages.ftl | 9 + compiler/rustc_builtin_macros/src/autodiff.rs | 820 ++++++++++++++++++ compiler/rustc_builtin_macros/src/errors.rs | 72 ++ compiler/rustc_builtin_macros/src/lib.rs | 3 + compiler/rustc_expand/src/build.rs | 29 + compiler/rustc_feature/src/builtin_attrs.rs | 5 + compiler/rustc_passes/messages.ftl | 4 + compiler/rustc_passes/src/check_attr.rs | 15 + compiler/rustc_passes/src/errors.rs | 8 + compiler/rustc_span/src/symbol.rs | 5 + library/core/src/lib.rs | 9 + library/core/src/macros/mod.rs | 18 + library/std/src/lib.rs | 9 +- 17 files changed, 1384 insertions(+), 1 deletion(-) create mode 100644 compiler/rustc_ast/src/expand/autodiff_attrs.rs create mode 100644 compiler/rustc_ast/src/expand/typetree.rs create mode 100644 compiler/rustc_builtin_macros/src/autodiff.rs diff --git a/compiler/rustc_ast/src/expand/autodiff_attrs.rs b/compiler/rustc_ast/src/expand/autodiff_attrs.rs new file mode 100644 index 00000000000..05714731b9d --- /dev/null +++ b/compiler/rustc_ast/src/expand/autodiff_attrs.rs @@ -0,0 +1,283 @@ +//! This crate handles the user facing autodiff macro. For each `#[autodiff(...)]` attribute, +//! we create an [`AutoDiffItem`] which contains the source and target function names. The source +//! is the function to which the autodiff attribute is applied, and the target is the function +//! getting generated by us (with a name given by the user as the first autodiff arg). + +use std::fmt::{self, Display, Formatter}; +use std::str::FromStr; + +use crate::expand::typetree::TypeTree; +use crate::expand::{Decodable, Encodable, HashStable_Generic}; +use crate::ptr::P; +use crate::{Ty, TyKind}; + +/// Forward and Reverse Mode are well known names for automatic differentiation implementations. +/// Enzyme does support both, but with different semantics, see DiffActivity. The First variants +/// are a hack to support higher order derivatives. We need to compute first order derivatives +/// before we compute second order derivatives, otherwise we would differentiate our placeholder +/// functions. The proper solution is to recognize and resolve this DAG of autodiff invocations, +/// as it's already done in the C++ and Julia frontend of Enzyme. +/// +/// (FIXME) remove *First variants. +/// Documentation for using [reverse](https://enzyme.mit.edu/rust/rev.html) and +/// [forward](https://enzyme.mit.edu/rust/fwd.html) mode is available online. +#[derive(Clone, Copy, Eq, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)] +pub enum DiffMode { + /// No autodiff is applied (used during error handling). + Error, + /// The primal function which we will differentiate. + Source, + /// The target function, to be created using forward mode AD. + Forward, + /// The target function, to be created using reverse mode AD. + Reverse, + /// The target function, to be created using forward mode AD. + /// This target function will also be used as a source for higher order derivatives, + /// so compute it before all Forward/Reverse targets and optimize it through llvm. + ForwardFirst, + /// The target function, to be created using reverse mode AD. + /// This target function will also be used as a source for higher order derivatives, + /// so compute it before all Forward/Reverse targets and optimize it through llvm. + ReverseFirst, +} + +/// Dual and Duplicated (and their Only variants) are getting lowered to the same Enzyme Activity. +/// However, under forward mode we overwrite the previous shadow value, while for reverse mode +/// we add to the previous shadow value. To not surprise users, we picked different names. +/// Dual numbers is also a quite well known name for forward mode AD types. +#[derive(Clone, Copy, Eq, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)] +pub enum DiffActivity { + /// Implicit or Explicit () return type, so a special case of Const. + None, + /// Don't compute derivatives with respect to this input/output. + Const, + /// Reverse Mode, Compute derivatives for this scalar input/output. + Active, + /// Reverse Mode, Compute derivatives for this scalar output, but don't compute + /// the original return value. + ActiveOnly, + /// Forward Mode, Compute derivatives for this input/output and *overwrite* the shadow argument + /// with it. + Dual, + /// Forward Mode, Compute derivatives for this input/output and *overwrite* the shadow argument + /// with it. Drop the code which updates the original input/output for maximum performance. + DualOnly, + /// Reverse Mode, Compute derivatives for this &T or *T input and *add* it to the shadow argument. + Duplicated, + /// Reverse Mode, Compute derivatives for this &T or *T input and *add* it to the shadow argument. + /// Drop the code which updates the original input for maximum performance. + DuplicatedOnly, + /// All Integers must be Const, but these are used to mark the integer which represents the + /// length of a slice/vec. This is used for safety checks on slices. + FakeActivitySize, +} +/// We generate one of these structs for each `#[autodiff(...)]` attribute. +#[derive(Clone, Eq, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)] +pub struct AutoDiffItem { + /// The name of the function getting differentiated + pub source: String, + /// The name of the function being generated + pub target: String, + pub attrs: AutoDiffAttrs, + /// Describe the memory layout of input types + pub inputs: Vec, + /// Describe the memory layout of the output type + pub output: TypeTree, +} +#[derive(Clone, Eq, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)] +pub struct AutoDiffAttrs { + /// Conceptually either forward or reverse mode AD, as described in various autodiff papers and + /// e.g. in the [JAX + /// Documentation](https://jax.readthedocs.io/en/latest/_tutorials/advanced-autodiff.html#how-it-s-made-two-foundational-autodiff-functions). + pub mode: DiffMode, + pub ret_activity: DiffActivity, + pub input_activity: Vec, +} + +impl DiffMode { + pub fn is_rev(&self) -> bool { + matches!(self, DiffMode::Reverse | DiffMode::ReverseFirst) + } + pub fn is_fwd(&self) -> bool { + matches!(self, DiffMode::Forward | DiffMode::ForwardFirst) + } +} + +impl Display for DiffMode { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + match self { + DiffMode::Error => write!(f, "Error"), + DiffMode::Source => write!(f, "Source"), + DiffMode::Forward => write!(f, "Forward"), + DiffMode::Reverse => write!(f, "Reverse"), + DiffMode::ForwardFirst => write!(f, "ForwardFirst"), + DiffMode::ReverseFirst => write!(f, "ReverseFirst"), + } + } +} + +/// Active(Only) is valid in reverse-mode AD for scalar float returns (f16/f32/...). +/// Dual(Only) is valid in forward-mode AD for scalar float returns (f16/f32/...). +/// Const is valid for all cases and means that we don't compute derivatives wrt. this output. +/// That usually means we have a &mut or *mut T output and compute derivatives wrt. that arg, +/// but this is too complex to verify here. Also it's just a logic error if users get this wrong. +pub fn valid_ret_activity(mode: DiffMode, activity: DiffActivity) -> bool { + if activity == DiffActivity::None { + // Only valid if primal returns (), but we can't check that here. + return true; + } + match mode { + DiffMode::Error => false, + DiffMode::Source => false, + DiffMode::Forward | DiffMode::ForwardFirst => { + activity == DiffActivity::Dual + || activity == DiffActivity::DualOnly + || activity == DiffActivity::Const + } + DiffMode::Reverse | DiffMode::ReverseFirst => { + activity == DiffActivity::Const + || activity == DiffActivity::Active + || activity == DiffActivity::ActiveOnly + } + } +} + +/// For indirections (ptr/ref) we can't use Active, since Active allocates a shadow value +/// for the given argument, but we generally can't know the size of such a type. +/// For scalar types (f16/f32/f64/f128) we can use Active and we can't use Duplicated, +/// since Duplicated expects a mutable ref/ptr and we would thus end up with a shadow value +/// who is an indirect type, which doesn't match the primal scalar type. We can't prevent +/// users here from marking scalars as Duplicated, due to type aliases. +pub fn valid_ty_for_activity(ty: &P, activity: DiffActivity) -> bool { + use DiffActivity::*; + // It's always allowed to mark something as Const, since we won't compute derivatives wrt. it. + if matches!(activity, Const) { + return true; + } + if matches!(activity, Dual | DualOnly) { + return true; + } + // FIXME(ZuseZ4) We should make this more robust to also + // handle type aliases. Once that is done, we can be more restrictive here. + if matches!(activity, Active | ActiveOnly) { + return true; + } + matches!(ty.kind, TyKind::Ptr(_) | TyKind::Ref(..)) + && matches!(activity, Duplicated | DuplicatedOnly) +} +pub fn valid_input_activity(mode: DiffMode, activity: DiffActivity) -> bool { + use DiffActivity::*; + return match mode { + DiffMode::Error => false, + DiffMode::Source => false, + DiffMode::Forward | DiffMode::ForwardFirst => { + matches!(activity, Dual | DualOnly | Const) + } + DiffMode::Reverse | DiffMode::ReverseFirst => { + matches!(activity, Active | ActiveOnly | Duplicated | DuplicatedOnly | Const) + } + }; +} + +impl Display for DiffActivity { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + DiffActivity::None => write!(f, "None"), + DiffActivity::Const => write!(f, "Const"), + DiffActivity::Active => write!(f, "Active"), + DiffActivity::ActiveOnly => write!(f, "ActiveOnly"), + DiffActivity::Dual => write!(f, "Dual"), + DiffActivity::DualOnly => write!(f, "DualOnly"), + DiffActivity::Duplicated => write!(f, "Duplicated"), + DiffActivity::DuplicatedOnly => write!(f, "DuplicatedOnly"), + DiffActivity::FakeActivitySize => write!(f, "FakeActivitySize"), + } + } +} + +impl FromStr for DiffMode { + type Err = (); + + fn from_str(s: &str) -> Result { + match s { + "Error" => Ok(DiffMode::Error), + "Source" => Ok(DiffMode::Source), + "Forward" => Ok(DiffMode::Forward), + "Reverse" => Ok(DiffMode::Reverse), + "ForwardFirst" => Ok(DiffMode::ForwardFirst), + "ReverseFirst" => Ok(DiffMode::ReverseFirst), + _ => Err(()), + } + } +} +impl FromStr for DiffActivity { + type Err = (); + + fn from_str(s: &str) -> Result { + match s { + "None" => Ok(DiffActivity::None), + "Active" => Ok(DiffActivity::Active), + "ActiveOnly" => Ok(DiffActivity::ActiveOnly), + "Const" => Ok(DiffActivity::Const), + "Dual" => Ok(DiffActivity::Dual), + "DualOnly" => Ok(DiffActivity::DualOnly), + "Duplicated" => Ok(DiffActivity::Duplicated), + "DuplicatedOnly" => Ok(DiffActivity::DuplicatedOnly), + _ => Err(()), + } + } +} + +impl AutoDiffAttrs { + pub fn has_ret_activity(&self) -> bool { + self.ret_activity != DiffActivity::None + } + pub fn has_active_only_ret(&self) -> bool { + self.ret_activity == DiffActivity::ActiveOnly + } + + pub fn error() -> Self { + AutoDiffAttrs { + mode: DiffMode::Error, + ret_activity: DiffActivity::None, + input_activity: Vec::new(), + } + } + pub fn source() -> Self { + AutoDiffAttrs { + mode: DiffMode::Source, + ret_activity: DiffActivity::None, + input_activity: Vec::new(), + } + } + + pub fn is_active(&self) -> bool { + self.mode != DiffMode::Error + } + + pub fn is_source(&self) -> bool { + self.mode == DiffMode::Source + } + pub fn apply_autodiff(&self) -> bool { + !matches!(self.mode, DiffMode::Error | DiffMode::Source) + } + + pub fn into_item( + self, + source: String, + target: String, + inputs: Vec, + output: TypeTree, + ) -> AutoDiffItem { + AutoDiffItem { source, target, inputs, output, attrs: self } + } +} + +impl fmt::Display for AutoDiffItem { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "Differentiating {} -> {}", self.source, self.target)?; + write!(f, " with attributes: {:?}", self.attrs)?; + write!(f, " with inputs: {:?}", self.inputs)?; + write!(f, " with output: {:?}", self.output) + } +} diff --git a/compiler/rustc_ast/src/expand/mod.rs b/compiler/rustc_ast/src/expand/mod.rs index 13413281bc7..d259677e98e 100644 --- a/compiler/rustc_ast/src/expand/mod.rs +++ b/compiler/rustc_ast/src/expand/mod.rs @@ -7,6 +7,8 @@ use rustc_span::symbol::Ident; use crate::MetaItem; pub mod allocator; +pub mod autodiff_attrs; +pub mod typetree; #[derive(Debug, Clone, Encodable, Decodable, HashStable_Generic)] pub struct StrippedCfgItem { diff --git a/compiler/rustc_ast/src/expand/typetree.rs b/compiler/rustc_ast/src/expand/typetree.rs new file mode 100644 index 00000000000..9a2dd2e85e0 --- /dev/null +++ b/compiler/rustc_ast/src/expand/typetree.rs @@ -0,0 +1,90 @@ +//! This module contains the definition of the `TypeTree` and `Type` structs. +//! They are thin Rust wrappers around the TypeTrees used by Enzyme as the LLVM based autodiff +//! backend. The Enzyme TypeTrees currently have various limitations and should be rewritten, so the +//! Rust frontend obviously has the same limitations. The main motivation of TypeTrees is to +//! represent how a type looks like "in memory". Enzyme can deduce this based on usage patterns in +//! the user code, but this is extremely slow and not even always sufficient. As such we lower some +//! information from rustc to help Enzyme. For a full explanation of their design it is necessary to +//! analyze the implementation in Enzyme core itself. As a rough summary, `-1` in Enzyme speech means +//! everywhere. That is `{0:-1: Float}` means at index 0 you have a ptr, if you dereference it it +//! will be floats everywhere. Thus `* f32`. If you have `{-1:int}` it means int's everywhere, +//! e.g. [i32; N]. `{0:-1:-1 float}` then means one pointer at offset 0, if you dereference it there +//! will be only pointers, if you dereference these new pointers they will point to array of floats. +//! Generally, it allows byte-specific descriptions. +//! FIXME: This description might be partly inaccurate and should be extended, along with +//! adding documentation to the corresponding Enzyme core code. +//! FIXME: Rewrite the TypeTree logic in Enzyme core to reduce the need for the rustc frontend to +//! provide typetree information. +//! FIXME: We should also re-evaluate where we create TypeTrees from Rust types, since MIR +//! representations of some types might not be accurate. For example a vector of floats might be +//! represented as a vector of u8s in MIR in some cases. + +use std::fmt; + +use crate::expand::{Decodable, Encodable, HashStable_Generic}; + +#[derive(Clone, Copy, Eq, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)] +pub enum Kind { + Anything, + Integer, + Pointer, + Half, + Float, + Double, + Unknown, +} + +#[derive(Clone, Eq, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)] +pub struct TypeTree(pub Vec); + +impl TypeTree { + pub fn new() -> Self { + Self(Vec::new()) + } + pub fn all_ints() -> Self { + Self(vec![Type { offset: -1, size: 1, kind: Kind::Integer, child: TypeTree::new() }]) + } + pub fn int(size: usize) -> Self { + let mut ints = Vec::with_capacity(size); + for i in 0..size { + ints.push(Type { + offset: i as isize, + size: 1, + kind: Kind::Integer, + child: TypeTree::new(), + }); + } + Self(ints) + } +} + +#[derive(Clone, Eq, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)] +pub struct FncTree { + pub args: Vec, + pub ret: TypeTree, +} + +#[derive(Clone, Eq, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)] +pub struct Type { + pub offset: isize, + pub size: usize, + pub kind: Kind, + pub child: TypeTree, +} + +impl Type { + pub fn add_offset(self, add: isize) -> Self { + let offset = match self.offset { + -1 => add, + x => add + x, + }; + + Self { size: self.size, kind: self.kind, child: self.child, offset } + } +} + +impl fmt::Display for Type { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + ::fmt(self, f) + } +} diff --git a/compiler/rustc_builtin_macros/Cargo.toml b/compiler/rustc_builtin_macros/Cargo.toml index 21b87be4b81..ef48486f6f1 100644 --- a/compiler/rustc_builtin_macros/Cargo.toml +++ b/compiler/rustc_builtin_macros/Cargo.toml @@ -3,6 +3,10 @@ name = "rustc_builtin_macros" version = "0.0.0" edition = "2021" + +[lints.rust] +unexpected_cfgs = { level = "warn", check-cfg = ['cfg(llvm_enzyme)'] } + [lib] doctest = false diff --git a/compiler/rustc_builtin_macros/messages.ftl b/compiler/rustc_builtin_macros/messages.ftl index 77cb8dc63c4..6ebc2fd870c 100644 --- a/compiler/rustc_builtin_macros/messages.ftl +++ b/compiler/rustc_builtin_macros/messages.ftl @@ -69,6 +69,15 @@ builtin_macros_assert_requires_boolean = macro requires a boolean expression as builtin_macros_assert_requires_expression = macro requires an expression as an argument .suggestion = try removing semicolon +builtin_macros_autodiff = autodiff must be applied to function +builtin_macros_autodiff_missing_config = autodiff requires at least a name and mode +builtin_macros_autodiff_mode = unknown Mode: `{$mode}`. Use `Forward` or `Reverse` +builtin_macros_autodiff_mode_activity = {$act} can not be used in {$mode} Mode +builtin_macros_autodiff_not_build = this rustc version does not support autodiff +builtin_macros_autodiff_number_activities = expected {$expected} activities, but found {$found} +builtin_macros_autodiff_ty_activity = {$act} can not be used for this type + +builtin_macros_autodiff_unknown_activity = did not recognize Activity: `{$act}` builtin_macros_bad_derive_target = `derive` may only be applied to `struct`s, `enum`s and `union`s .label = not applicable here .label2 = not a `struct`, `enum` or `union` diff --git a/compiler/rustc_builtin_macros/src/autodiff.rs b/compiler/rustc_builtin_macros/src/autodiff.rs new file mode 100644 index 00000000000..66bb11ca522 --- /dev/null +++ b/compiler/rustc_builtin_macros/src/autodiff.rs @@ -0,0 +1,820 @@ +//! This module contains the implementation of the `#[autodiff]` attribute. +//! Currently our linter isn't smart enough to see that each import is used in one of the two +//! configs (autodiff enabled or disabled), so we have to add cfg's to each import. +//! FIXME(ZuseZ4): Remove this once we have a smarter linter. + +#[cfg(llvm_enzyme)] +mod llvm_enzyme { + use std::str::FromStr; + use std::string::String; + + use rustc_ast::expand::autodiff_attrs::{ + AutoDiffAttrs, DiffActivity, DiffMode, valid_input_activity, valid_ty_for_activity, + }; + use rustc_ast::ptr::P; + use rustc_ast::token::{Token, TokenKind}; + use rustc_ast::tokenstream::*; + use rustc_ast::visit::AssocCtxt::*; + use rustc_ast::{ + self as ast, AssocItemKind, BindingMode, FnRetTy, FnSig, Generics, ItemKind, MetaItemInner, + PatKind, TyKind, + }; + use rustc_expand::base::{Annotatable, ExtCtxt}; + use rustc_span::symbol::{Ident, kw, sym}; + use rustc_span::{Span, Symbol}; + use thin_vec::{ThinVec, thin_vec}; + use tracing::{debug, trace}; + + use crate::errors; + + // If we have a default `()` return type or explicitley `()` return type, + // then we often can skip doing some work. + fn has_ret(ty: &FnRetTy) -> bool { + match ty { + FnRetTy::Ty(ty) => !ty.kind.is_unit(), + FnRetTy::Default(_) => false, + } + } + fn first_ident(x: &MetaItemInner) -> rustc_span::symbol::Ident { + let segments = &x.meta_item().unwrap().path.segments; + assert!(segments.len() == 1); + segments[0].ident + } + + fn name(x: &MetaItemInner) -> String { + first_ident(x).name.to_string() + } + + pub(crate) fn from_ast( + ecx: &mut ExtCtxt<'_>, + meta_item: &ThinVec, + has_ret: bool, + ) -> AutoDiffAttrs { + let dcx = ecx.sess.dcx(); + let mode = name(&meta_item[1]); + let Ok(mode) = DiffMode::from_str(&mode) else { + dcx.emit_err(errors::AutoDiffInvalidMode { span: meta_item[1].span(), mode }); + return AutoDiffAttrs::error(); + }; + let mut activities: Vec = vec![]; + let mut errors = false; + for x in &meta_item[2..] { + let activity_str = name(&x); + let res = DiffActivity::from_str(&activity_str); + match res { + Ok(x) => activities.push(x), + Err(_) => { + dcx.emit_err(errors::AutoDiffUnknownActivity { + span: x.span(), + act: activity_str, + }); + errors = true; + } + }; + } + if errors { + return AutoDiffAttrs::error(); + } + + // If a return type exist, we need to split the last activity, + // otherwise we return None as placeholder. + let (ret_activity, input_activity) = if has_ret { + let Some((last, rest)) = activities.split_last() else { + unreachable!( + "should not be reachable because we counted the number of activities previously" + ); + }; + (last, rest) + } else { + (&DiffActivity::None, activities.as_slice()) + }; + + AutoDiffAttrs { mode, ret_activity: *ret_activity, input_activity: input_activity.to_vec() } + } + + /// We expand the autodiff macro to generate a new placeholder function which passes + /// type-checking and can be called by users. The function body of the placeholder function will + /// later be replaced on LLVM-IR level, so the design of the body is less important and for now + /// should just prevent early inlining and optimizations which alter the function signature. + /// The exact signature of the generated function depends on the configuration provided by the + /// user, but here is an example: + /// + /// ``` + /// #[autodiff(cos_box, Reverse, Duplicated, Active)] + /// fn sin(x: &Box) -> f32 { + /// f32::sin(**x) + /// } + /// ``` + /// which becomes expanded to: + /// ``` + /// #[rustc_autodiff] + /// #[inline(never)] + /// fn sin(x: &Box) -> f32 { + /// f32::sin(**x) + /// } + /// #[rustc_autodiff(Reverse, Duplicated, Active)] + /// #[inline(never)] + /// fn cos_box(x: &Box, dx: &mut Box, dret: f32) -> f32 { + /// unsafe { + /// asm!("NOP"); + /// }; + /// ::core::hint::black_box(sin(x)); + /// ::core::hint::black_box((dx, dret)); + /// ::core::hint::black_box(sin(x)) + /// } + /// ``` + /// FIXME(ZuseZ4): Once autodiff is enabled by default, make this a doc comment which is checked + /// in CI. + pub(crate) fn expand( + ecx: &mut ExtCtxt<'_>, + expand_span: Span, + meta_item: &ast::MetaItem, + mut item: Annotatable, + ) -> Vec { + let dcx = ecx.sess.dcx(); + // first get the annotable item: + let (sig, is_impl): (FnSig, bool) = match &item { + Annotatable::Item(ref iitem) => { + let sig = match &iitem.kind { + ItemKind::Fn(box ast::Fn { sig, .. }) => sig, + _ => { + dcx.emit_err(errors::AutoDiffInvalidApplication { span: item.span() }); + return vec![item]; + } + }; + (sig.clone(), false) + } + Annotatable::AssocItem(ref assoc_item, _) => { + let sig = match &assoc_item.kind { + ast::AssocItemKind::Fn(box ast::Fn { sig, .. }) => sig, + _ => { + dcx.emit_err(errors::AutoDiffInvalidApplication { span: item.span() }); + return vec![item]; + } + }; + (sig.clone(), true) + } + _ => { + dcx.emit_err(errors::AutoDiffInvalidApplication { span: item.span() }); + return vec![item]; + } + }; + + let meta_item_vec: ThinVec = match meta_item.kind { + ast::MetaItemKind::List(ref vec) => vec.clone(), + _ => { + dcx.emit_err(errors::AutoDiffInvalidApplication { span: item.span() }); + return vec![item]; + } + }; + + let has_ret = has_ret(&sig.decl.output); + let sig_span = ecx.with_call_site_ctxt(sig.span); + + let (vis, primal) = match &item { + Annotatable::Item(ref iitem) => (iitem.vis.clone(), iitem.ident.clone()), + Annotatable::AssocItem(ref assoc_item, _) => { + (assoc_item.vis.clone(), assoc_item.ident.clone()) + } + _ => { + dcx.emit_err(errors::AutoDiffInvalidApplication { span: item.span() }); + return vec![item]; + } + }; + + // create TokenStream from vec elemtents: + // meta_item doesn't have a .tokens field + let comma: Token = Token::new(TokenKind::Comma, Span::default()); + let mut ts: Vec = vec![]; + if meta_item_vec.len() < 2 { + // At the bare minimum, we need a fnc name and a mode, even for a dummy function with no + // input and output args. + dcx.emit_err(errors::AutoDiffMissingConfig { span: item.span() }); + return vec![item]; + } else { + for t in meta_item_vec.clone()[1..].iter() { + let val = first_ident(t); + let t = Token::from_ast_ident(val); + ts.push(TokenTree::Token(t, Spacing::Joint)); + ts.push(TokenTree::Token(comma.clone(), Spacing::Alone)); + } + } + if !has_ret { + // We don't want users to provide a return activity if the function doesn't return anything. + // For simplicity, we just add a dummy token to the end of the list. + let t = Token::new(TokenKind::Ident(sym::None, false.into()), Span::default()); + ts.push(TokenTree::Token(t, Spacing::Joint)); + } + let ts: TokenStream = TokenStream::from_iter(ts); + + let x: AutoDiffAttrs = from_ast(ecx, &meta_item_vec, has_ret); + if !x.is_active() { + // We encountered an error, so we return the original item. + // This allows us to potentially parse other attributes. + return vec![item]; + } + let span = ecx.with_def_site_ctxt(expand_span); + + let n_active: u32 = x + .input_activity + .iter() + .filter(|a| **a == DiffActivity::Active || **a == DiffActivity::ActiveOnly) + .count() as u32; + let (d_sig, new_args, idents, errored) = gen_enzyme_decl(ecx, &sig, &x, span); + let new_decl_span = d_sig.span; + let d_body = gen_enzyme_body( + ecx, + &x, + n_active, + &sig, + &d_sig, + primal, + &new_args, + span, + sig_span, + new_decl_span, + idents, + errored, + ); + let d_ident = first_ident(&meta_item_vec[0]); + + // The first element of it is the name of the function to be generated + let asdf = Box::new(ast::Fn { + defaultness: ast::Defaultness::Final, + sig: d_sig, + generics: Generics::default(), + body: Some(d_body), + }); + let mut rustc_ad_attr = + P(ast::NormalAttr::from_ident(Ident::with_dummy_span(sym::rustc_autodiff))); + + let ts2: Vec = vec![TokenTree::Token( + Token::new(TokenKind::Ident(sym::never, false.into()), span), + Spacing::Joint, + )]; + let never_arg = ast::DelimArgs { + dspan: ast::tokenstream::DelimSpan::from_single(span), + delim: ast::token::Delimiter::Parenthesis, + tokens: ast::tokenstream::TokenStream::from_iter(ts2), + }; + let inline_item = ast::AttrItem { + unsafety: ast::Safety::Default, + path: ast::Path::from_ident(Ident::with_dummy_span(sym::inline)), + args: ast::AttrArgs::Delimited(never_arg), + tokens: None, + }; + let inline_never_attr = P(ast::NormalAttr { item: inline_item, tokens: None }); + let new_id = ecx.sess.psess.attr_id_generator.mk_attr_id(); + let attr: ast::Attribute = ast::Attribute { + kind: ast::AttrKind::Normal(rustc_ad_attr.clone()), + id: new_id, + style: ast::AttrStyle::Outer, + span, + }; + let new_id = ecx.sess.psess.attr_id_generator.mk_attr_id(); + let inline_never: ast::Attribute = ast::Attribute { + kind: ast::AttrKind::Normal(inline_never_attr), + id: new_id, + style: ast::AttrStyle::Outer, + span, + }; + + // Don't add it multiple times: + let orig_annotatable: Annotatable = match item { + Annotatable::Item(ref mut iitem) => { + if !iitem.attrs.iter().any(|a| a.id == attr.id) { + iitem.attrs.push(attr.clone()); + } + if !iitem.attrs.iter().any(|a| a.id == inline_never.id) { + iitem.attrs.push(inline_never.clone()); + } + Annotatable::Item(iitem.clone()) + } + Annotatable::AssocItem(ref mut assoc_item, i @ Impl) => { + if !assoc_item.attrs.iter().any(|a| a.id == attr.id) { + assoc_item.attrs.push(attr.clone()); + } + if !assoc_item.attrs.iter().any(|a| a.id == inline_never.id) { + assoc_item.attrs.push(inline_never.clone()); + } + Annotatable::AssocItem(assoc_item.clone(), i) + } + _ => { + unreachable!("annotatable kind checked previously") + } + }; + // Now update for d_fn + rustc_ad_attr.item.args = rustc_ast::AttrArgs::Delimited(rustc_ast::DelimArgs { + dspan: DelimSpan::dummy(), + delim: rustc_ast::token::Delimiter::Parenthesis, + tokens: ts, + }); + let d_attr: ast::Attribute = ast::Attribute { + kind: ast::AttrKind::Normal(rustc_ad_attr.clone()), + id: new_id, + style: ast::AttrStyle::Outer, + span, + }; + + let d_annotatable = if is_impl { + let assoc_item: AssocItemKind = ast::AssocItemKind::Fn(asdf); + let d_fn = P(ast::AssocItem { + attrs: thin_vec![d_attr.clone(), inline_never], + id: ast::DUMMY_NODE_ID, + span, + vis, + ident: d_ident, + kind: assoc_item, + tokens: None, + }); + Annotatable::AssocItem(d_fn, Impl) + } else { + let mut d_fn = ecx.item( + span, + d_ident, + thin_vec![d_attr.clone(), inline_never], + ItemKind::Fn(asdf), + ); + d_fn.vis = vis; + Annotatable::Item(d_fn) + }; + + return vec![orig_annotatable, d_annotatable]; + } + + // shadow arguments (the extra ones which were not in the original (primal) function), in reverse mode must be + // mutable references or ptrs, because Enzyme will write into them. + fn assure_mut_ref(ty: &ast::Ty) -> ast::Ty { + let mut ty = ty.clone(); + match ty.kind { + TyKind::Ptr(ref mut mut_ty) => { + mut_ty.mutbl = ast::Mutability::Mut; + } + TyKind::Ref(_, ref mut mut_ty) => { + mut_ty.mutbl = ast::Mutability::Mut; + } + _ => { + panic!("unsupported type: {:?}", ty); + } + } + ty + } + + /// We only want this function to type-check, since we will replace the body + /// later on llvm level. Using `loop {}` does not cover all return types anymore, + /// so instead we build something that should pass. We also add a inline_asm + /// line, as one more barrier for rustc to prevent inlining of this function. + /// FIXME(ZuseZ4): We still have cases of incorrect inlining across modules, see + /// , so this isn't sufficient. + /// It also triggers an Enzyme crash if we due to a bug ever try to differentiate + /// this function (which should never happen, since it is only a placeholder). + /// Finally, we also add back_box usages of all input arguments, to prevent rustc + /// from optimizing any arguments away. + fn gen_enzyme_body( + ecx: &ExtCtxt<'_>, + x: &AutoDiffAttrs, + n_active: u32, + sig: &ast::FnSig, + d_sig: &ast::FnSig, + primal: Ident, + new_names: &[String], + span: Span, + sig_span: Span, + new_decl_span: Span, + idents: Vec, + errored: bool, + ) -> P { + let blackbox_path = ecx.std_path(&[sym::hint, sym::black_box]); + let noop = ast::InlineAsm { + asm_macro: ast::AsmMacro::Asm, + template: vec![ast::InlineAsmTemplatePiece::String("NOP".into())], + template_strs: Box::new([]), + operands: vec![], + clobber_abis: vec![], + options: ast::InlineAsmOptions::PURE | ast::InlineAsmOptions::NOMEM, + line_spans: vec![], + }; + let noop_expr = ecx.expr_asm(span, P(noop)); + let unsf = ast::BlockCheckMode::Unsafe(ast::UnsafeSource::CompilerGenerated); + let unsf_block = ast::Block { + stmts: thin_vec![ecx.stmt_semi(noop_expr)], + id: ast::DUMMY_NODE_ID, + tokens: None, + rules: unsf, + span, + could_be_bare_literal: false, + }; + let unsf_expr = ecx.expr_block(P(unsf_block)); + let blackbox_call_expr = ecx.expr_path(ecx.path(span, blackbox_path)); + let primal_call = gen_primal_call(ecx, span, primal, idents); + let black_box_primal_call = + ecx.expr_call(new_decl_span, blackbox_call_expr.clone(), thin_vec![ + primal_call.clone() + ]); + let tup_args = new_names + .iter() + .map(|arg| ecx.expr_path(ecx.path_ident(span, Ident::from_str(arg)))) + .collect(); + + let black_box_remaining_args = + ecx.expr_call(sig_span, blackbox_call_expr.clone(), thin_vec![ + ecx.expr_tuple(sig_span, tup_args) + ]); + + let mut body = ecx.block(span, ThinVec::new()); + body.stmts.push(ecx.stmt_semi(unsf_expr)); + + // This uses primal args which won't be available if we errored before + if !errored { + body.stmts.push(ecx.stmt_semi(black_box_primal_call.clone())); + } + body.stmts.push(ecx.stmt_semi(black_box_remaining_args)); + + if !has_ret(&d_sig.decl.output) { + // there is no return type that we have to match, () works fine. + return body; + } + + // having an active-only return means we'll drop the original return type. + // So that can be treated identical to not having one in the first place. + let primal_ret = has_ret(&sig.decl.output) && !x.has_active_only_ret(); + + if primal_ret && n_active == 0 && x.mode.is_rev() { + // We only have the primal ret. + body.stmts.push(ecx.stmt_expr(black_box_primal_call.clone())); + return body; + } + + if !primal_ret && n_active == 1 { + // Again no tuple return, so return default float val. + let ty = match d_sig.decl.output { + FnRetTy::Ty(ref ty) => ty.clone(), + FnRetTy::Default(span) => { + panic!("Did not expect Default ret ty: {:?}", span); + } + }; + let arg = ty.kind.is_simple_path().unwrap(); + let sl: Vec = vec![arg, kw::Default]; + let tmp = ecx.def_site_path(&sl); + let default_call_expr = ecx.expr_path(ecx.path(span, tmp)); + let default_call_expr = ecx.expr_call(new_decl_span, default_call_expr, thin_vec![]); + body.stmts.push(ecx.stmt_expr(default_call_expr)); + return body; + } + + let mut exprs = ThinVec::>::new(); + if primal_ret { + // We have both primal ret and active floats. + // primal ret is first, by construction. + exprs.push(primal_call.clone()); + } + + // Now construct default placeholder for each active float. + // Is there something nicer than f32::default() and f64::default()? + let d_ret_ty = match d_sig.decl.output { + FnRetTy::Ty(ref ty) => ty.clone(), + FnRetTy::Default(span) => { + panic!("Did not expect Default ret ty: {:?}", span); + } + }; + let mut d_ret_ty = match d_ret_ty.kind.clone() { + TyKind::Tup(ref tys) => tys.clone(), + TyKind::Path(_, rustc_ast::Path { segments, .. }) => { + if let [segment] = &segments[..] + && segment.args.is_none() + { + let id = vec![segments[0].ident]; + let kind = TyKind::Path(None, ecx.path(span, id)); + let ty = P(rustc_ast::Ty { kind, id: ast::DUMMY_NODE_ID, span, tokens: None }); + thin_vec![ty] + } else { + panic!("Expected tuple or simple path return type"); + } + } + _ => { + // We messed up construction of d_sig + panic!("Did not expect non-tuple ret ty: {:?}", d_ret_ty); + } + }; + + if x.mode.is_fwd() && x.ret_activity == DiffActivity::Dual { + assert!(d_ret_ty.len() == 2); + // both should be identical, by construction + let arg = d_ret_ty[0].kind.is_simple_path().unwrap(); + let arg2 = d_ret_ty[1].kind.is_simple_path().unwrap(); + assert!(arg == arg2); + let sl: Vec = vec![arg, kw::Default]; + let tmp = ecx.def_site_path(&sl); + let default_call_expr = ecx.expr_path(ecx.path(span, tmp)); + let default_call_expr = ecx.expr_call(new_decl_span, default_call_expr, thin_vec![]); + exprs.push(default_call_expr); + } else if x.mode.is_rev() { + if primal_ret { + // We have extra handling above for the primal ret + d_ret_ty = d_ret_ty[1..].to_vec().into(); + } + + for arg in d_ret_ty.iter() { + let arg = arg.kind.is_simple_path().unwrap(); + let sl: Vec = vec![arg, kw::Default]; + let tmp = ecx.def_site_path(&sl); + let default_call_expr = ecx.expr_path(ecx.path(span, tmp)); + let default_call_expr = + ecx.expr_call(new_decl_span, default_call_expr, thin_vec![]); + exprs.push(default_call_expr); + } + } + + let ret: P; + match &exprs[..] { + [] => { + assert!(!has_ret(&d_sig.decl.output)); + // We don't have to match the return type. + return body; + } + [arg] => { + ret = ecx + .expr_call(new_decl_span, blackbox_call_expr.clone(), thin_vec![arg.clone()]); + } + args => { + let ret_tuple: P = ecx.expr_tuple(span, args.into()); + ret = + ecx.expr_call(new_decl_span, blackbox_call_expr.clone(), thin_vec![ret_tuple]); + } + } + assert!(has_ret(&d_sig.decl.output)); + body.stmts.push(ecx.stmt_expr(ret)); + + body + } + + fn gen_primal_call( + ecx: &ExtCtxt<'_>, + span: Span, + primal: Ident, + idents: Vec, + ) -> P { + let has_self = idents.len() > 0 && idents[0].name == kw::SelfLower; + if has_self { + let args: ThinVec<_> = + idents[1..].iter().map(|arg| ecx.expr_path(ecx.path_ident(span, *arg))).collect(); + let self_expr = ecx.expr_self(span); + ecx.expr_method_call(span, self_expr, primal, args.clone()) + } else { + let args: ThinVec<_> = + idents.iter().map(|arg| ecx.expr_path(ecx.path_ident(span, *arg))).collect(); + let primal_call_expr = ecx.expr_path(ecx.path_ident(span, primal)); + ecx.expr_call(span, primal_call_expr, args) + } + } + + // Generate the new function declaration. Const arguments are kept as is. Duplicated arguments must + // be pointers or references. Those receive a shadow argument, which is a mutable reference/pointer. + // Active arguments must be scalars. Their shadow argument is added to the return type (and will be + // zero-initialized by Enzyme). + // Each argument of the primal function (and the return type if existing) must be annotated with an + // activity. + // + // Error handling: If the user provides an invalid configuration (incorrect numbers, types, or + // both), we emit an error and return the original signature. This allows us to continue parsing. + fn gen_enzyme_decl( + ecx: &ExtCtxt<'_>, + sig: &ast::FnSig, + x: &AutoDiffAttrs, + span: Span, + ) -> (ast::FnSig, Vec, Vec, bool) { + let dcx = ecx.sess.dcx(); + let has_ret = has_ret(&sig.decl.output); + let sig_args = sig.decl.inputs.len() + if has_ret { 1 } else { 0 }; + let num_activities = x.input_activity.len() + if x.has_ret_activity() { 1 } else { 0 }; + if sig_args != num_activities { + dcx.emit_err(errors::AutoDiffInvalidNumberActivities { + span, + expected: sig_args, + found: num_activities, + }); + // This is not the right signature, but we can continue parsing. + return (sig.clone(), vec![], vec![], true); + } + assert!(sig.decl.inputs.len() == x.input_activity.len()); + assert!(has_ret == x.has_ret_activity()); + let mut d_decl = sig.decl.clone(); + let mut d_inputs = Vec::new(); + let mut new_inputs = Vec::new(); + let mut idents = Vec::new(); + let mut act_ret = ThinVec::new(); + + // We have two loops, a first one just to check the activities and types and possibly report + // multiple errors in one compilation session. + let mut errors = false; + for (arg, activity) in sig.decl.inputs.iter().zip(x.input_activity.iter()) { + if !valid_input_activity(x.mode, *activity) { + dcx.emit_err(errors::AutoDiffInvalidApplicationModeAct { + span, + mode: x.mode.to_string(), + act: activity.to_string(), + }); + errors = true; + } + if !valid_ty_for_activity(&arg.ty, *activity) { + dcx.emit_err(errors::AutoDiffInvalidTypeForActivity { + span: arg.ty.span, + act: activity.to_string(), + }); + errors = true; + } + } + if errors { + // This is not the right signature, but we can continue parsing. + return (sig.clone(), new_inputs, idents, true); + } + let unsafe_activities = x + .input_activity + .iter() + .any(|&act| matches!(act, DiffActivity::DuplicatedOnly | DiffActivity::DualOnly)); + for (arg, activity) in sig.decl.inputs.iter().zip(x.input_activity.iter()) { + d_inputs.push(arg.clone()); + match activity { + DiffActivity::Active => { + act_ret.push(arg.ty.clone()); + } + DiffActivity::ActiveOnly => { + // We will add the active scalar to the return type. + // This is handled later. + } + DiffActivity::Duplicated | DiffActivity::DuplicatedOnly => { + let mut shadow_arg = arg.clone(); + // We += into the shadow in reverse mode. + shadow_arg.ty = P(assure_mut_ref(&arg.ty)); + let old_name = if let PatKind::Ident(_, ident, _) = arg.pat.kind { + ident.name + } else { + debug!("{:#?}", &shadow_arg.pat); + panic!("not an ident?"); + }; + let name: String = format!("d{}", old_name); + new_inputs.push(name.clone()); + let ident = Ident::from_str_and_span(&name, shadow_arg.pat.span); + shadow_arg.pat = P(ast::Pat { + id: ast::DUMMY_NODE_ID, + kind: PatKind::Ident(BindingMode::NONE, ident, None), + span: shadow_arg.pat.span, + tokens: shadow_arg.pat.tokens.clone(), + }); + d_inputs.push(shadow_arg); + } + DiffActivity::Dual | DiffActivity::DualOnly => { + let mut shadow_arg = arg.clone(); + let old_name = if let PatKind::Ident(_, ident, _) = arg.pat.kind { + ident.name + } else { + debug!("{:#?}", &shadow_arg.pat); + panic!("not an ident?"); + }; + let name: String = format!("b{}", old_name); + new_inputs.push(name.clone()); + let ident = Ident::from_str_and_span(&name, shadow_arg.pat.span); + shadow_arg.pat = P(ast::Pat { + id: ast::DUMMY_NODE_ID, + kind: PatKind::Ident(BindingMode::NONE, ident, None), + span: shadow_arg.pat.span, + tokens: shadow_arg.pat.tokens.clone(), + }); + d_inputs.push(shadow_arg); + } + DiffActivity::Const => { + // Nothing to do here. + } + DiffActivity::None | DiffActivity::FakeActivitySize => { + panic!("Should not happen"); + } + } + if let PatKind::Ident(_, ident, _) = arg.pat.kind { + idents.push(ident.clone()); + } else { + panic!("not an ident?"); + } + } + + let active_only_ret = x.ret_activity == DiffActivity::ActiveOnly; + if active_only_ret { + assert!(x.mode.is_rev()); + } + + // If we return a scalar in the primal and the scalar is active, + // then add it as last arg to the inputs. + if x.mode.is_rev() { + match x.ret_activity { + DiffActivity::Active | DiffActivity::ActiveOnly => { + let ty = match d_decl.output { + FnRetTy::Ty(ref ty) => ty.clone(), + FnRetTy::Default(span) => { + panic!("Did not expect Default ret ty: {:?}", span); + } + }; + let name = "dret".to_string(); + let ident = Ident::from_str_and_span(&name, ty.span); + let shadow_arg = ast::Param { + attrs: ThinVec::new(), + ty: ty.clone(), + pat: P(ast::Pat { + id: ast::DUMMY_NODE_ID, + kind: PatKind::Ident(BindingMode::NONE, ident, None), + span: ty.span, + tokens: None, + }), + id: ast::DUMMY_NODE_ID, + span: ty.span, + is_placeholder: false, + }; + d_inputs.push(shadow_arg); + new_inputs.push(name); + } + _ => {} + } + } + d_decl.inputs = d_inputs.into(); + + if x.mode.is_fwd() { + if let DiffActivity::Dual = x.ret_activity { + let ty = match d_decl.output { + FnRetTy::Ty(ref ty) => ty.clone(), + FnRetTy::Default(span) => { + panic!("Did not expect Default ret ty: {:?}", span); + } + }; + // Dual can only be used for f32/f64 ret. + // In that case we return now a tuple with two floats. + let kind = TyKind::Tup(thin_vec![ty.clone(), ty.clone()]); + let ty = P(rustc_ast::Ty { kind, id: ty.id, span: ty.span, tokens: None }); + d_decl.output = FnRetTy::Ty(ty); + } + if let DiffActivity::DualOnly = x.ret_activity { + // No need to change the return type, + // we will just return the shadow in place + // of the primal return. + } + } + + // If we use ActiveOnly, drop the original return value. + d_decl.output = + if active_only_ret { FnRetTy::Default(span) } else { d_decl.output.clone() }; + + trace!("act_ret: {:?}", act_ret); + + // If we have an active input scalar, add it's gradient to the + // return type. This might require changing the return type to a + // tuple. + if act_ret.len() > 0 { + let ret_ty = match d_decl.output { + FnRetTy::Ty(ref ty) => { + if !active_only_ret { + act_ret.insert(0, ty.clone()); + } + let kind = TyKind::Tup(act_ret); + P(rustc_ast::Ty { kind, id: ty.id, span: ty.span, tokens: None }) + } + FnRetTy::Default(span) => { + if act_ret.len() == 1 { + act_ret[0].clone() + } else { + let kind = TyKind::Tup(act_ret.iter().map(|arg| arg.clone()).collect()); + P(rustc_ast::Ty { kind, id: ast::DUMMY_NODE_ID, span, tokens: None }) + } + } + }; + d_decl.output = FnRetTy::Ty(ret_ty); + } + + let mut d_header = sig.header.clone(); + if unsafe_activities { + d_header.safety = rustc_ast::Safety::Unsafe(span); + } + let d_sig = FnSig { header: d_header, decl: d_decl, span }; + trace!("Generated signature: {:?}", d_sig); + (d_sig, new_inputs, idents, false) + } +} + +#[cfg(not(llvm_enzyme))] +mod ad_fallback { + use rustc_ast::ast; + use rustc_expand::base::{Annotatable, ExtCtxt}; + use rustc_span::Span; + + use crate::errors; + pub(crate) fn expand( + ecx: &mut ExtCtxt<'_>, + _expand_span: Span, + meta_item: &ast::MetaItem, + item: Annotatable, + ) -> Vec { + ecx.sess.dcx().emit_err(errors::AutoDiffSupportNotBuild { span: meta_item.span }); + return vec![item]; + } +} + +#[cfg(not(llvm_enzyme))] +pub(crate) use ad_fallback::expand; +#[cfg(llvm_enzyme)] +pub(crate) use llvm_enzyme::expand; diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs index 639c2aa231c..f8e65661e52 100644 --- a/compiler/rustc_builtin_macros/src/errors.rs +++ b/compiler/rustc_builtin_macros/src/errors.rs @@ -145,6 +145,78 @@ pub(crate) struct AllocMustStatics { pub(crate) span: Span, } +#[cfg(llvm_enzyme)] +pub(crate) use autodiff::*; + +#[cfg(llvm_enzyme)] +mod autodiff { + use super::*; + #[derive(Diagnostic)] + #[diag(builtin_macros_autodiff_missing_config)] + pub(crate) struct AutoDiffMissingConfig { + #[primary_span] + pub(crate) span: Span, + } + #[derive(Diagnostic)] + #[diag(builtin_macros_autodiff_unknown_activity)] + pub(crate) struct AutoDiffUnknownActivity { + #[primary_span] + pub(crate) span: Span, + pub(crate) act: String, + } + #[derive(Diagnostic)] + #[diag(builtin_macros_autodiff_ty_activity)] + pub(crate) struct AutoDiffInvalidTypeForActivity { + #[primary_span] + pub(crate) span: Span, + pub(crate) act: String, + } + #[derive(Diagnostic)] + #[diag(builtin_macros_autodiff_number_activities)] + pub(crate) struct AutoDiffInvalidNumberActivities { + #[primary_span] + pub(crate) span: Span, + pub(crate) expected: usize, + pub(crate) found: usize, + } + #[derive(Diagnostic)] + #[diag(builtin_macros_autodiff_mode_activity)] + pub(crate) struct AutoDiffInvalidApplicationModeAct { + #[primary_span] + pub(crate) span: Span, + pub(crate) mode: String, + pub(crate) act: String, + } + + #[derive(Diagnostic)] + #[diag(builtin_macros_autodiff_mode)] + pub(crate) struct AutoDiffInvalidMode { + #[primary_span] + pub(crate) span: Span, + pub(crate) mode: String, + } + + #[derive(Diagnostic)] + #[diag(builtin_macros_autodiff)] + pub(crate) struct AutoDiffInvalidApplication { + #[primary_span] + pub(crate) span: Span, + } +} + +#[cfg(not(llvm_enzyme))] +pub(crate) use ad_fallback::*; +#[cfg(not(llvm_enzyme))] +mod ad_fallback { + use super::*; + #[derive(Diagnostic)] + #[diag(builtin_macros_autodiff_not_build)] + pub(crate) struct AutoDiffSupportNotBuild { + #[primary_span] + pub(crate) span: Span, + } +} + #[derive(Diagnostic)] #[diag(builtin_macros_concat_bytes_invalid)] pub(crate) struct ConcatBytesInvalid { diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs index ebe5e2b5442..377d7f542cf 100644 --- a/compiler/rustc_builtin_macros/src/lib.rs +++ b/compiler/rustc_builtin_macros/src/lib.rs @@ -5,6 +5,7 @@ #![allow(internal_features)] #![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::untranslatable_diagnostic)] +#![cfg_attr(not(bootstrap), feature(autodiff))] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(assert_matches)] @@ -29,6 +30,7 @@ use crate::deriving::*; mod alloc_error_handler; mod assert; +mod autodiff; mod cfg; mod cfg_accessible; mod cfg_eval; @@ -106,6 +108,7 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) { register_attr! { alloc_error_handler: alloc_error_handler::expand, + autodiff: autodiff::expand, bench: test::expand_bench, cfg_accessible: cfg_accessible::Expander, cfg_eval: cfg_eval::expand, diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs index b5945759d43..743a9854f79 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -220,6 +220,10 @@ impl<'a> ExtCtxt<'a> { self.stmt_local(local, span) } + pub fn stmt_semi(&self, expr: P) -> ast::Stmt { + ast::Stmt { id: ast::DUMMY_NODE_ID, span: expr.span, kind: ast::StmtKind::Semi(expr) } + } + pub fn stmt_local(&self, local: P, span: Span) -> ast::Stmt { ast::Stmt { id: ast::DUMMY_NODE_ID, kind: ast::StmtKind::Let(local), span } } @@ -287,6 +291,25 @@ impl<'a> ExtCtxt<'a> { self.expr(sp, ast::ExprKind::Paren(e)) } + pub fn expr_method_call( + &self, + span: Span, + expr: P, + ident: Ident, + args: ThinVec>, + ) -> P { + let seg = ast::PathSegment::from_ident(ident); + self.expr( + span, + ast::ExprKind::MethodCall(Box::new(ast::MethodCall { + seg, + receiver: expr, + args, + span, + })), + ) + } + pub fn expr_call( &self, span: Span, @@ -295,6 +318,12 @@ impl<'a> ExtCtxt<'a> { ) -> P { self.expr(span, ast::ExprKind::Call(expr, args)) } + pub fn expr_loop(&self, sp: Span, block: P) -> P { + self.expr(sp, ast::ExprKind::Loop(block, None, sp)) + } + pub fn expr_asm(&self, sp: Span, expr: P) -> P { + self.expr(sp, ast::ExprKind::InlineAsm(expr)) + } pub fn expr_call_ident( &self, span: Span, diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 17827b4e43b..477760a4597 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -752,6 +752,11 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ template!(NameValueStr: "transparent|semitransparent|opaque"), ErrorFollowing, EncodeCrossCrate::Yes, "used internally for testing macro hygiene", ), + rustc_attr!( + rustc_autodiff, Normal, + template!(Word, List: r#""...""#), DuplicatesOk, + EncodeCrossCrate::No, INTERNAL_UNSTABLE + ), // ========================================================================== // Internal attributes, Diagnostics related: diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index be76d6cef2b..d60d7e00d4b 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -49,6 +49,10 @@ passes_attr_crate_level = passes_attr_only_in_functions = `{$attr}` attribute can only be used on functions +passes_autodiff_attr = + `#[autodiff]` should be applied to a function + .label = not a function + passes_both_ffi_const_and_pure = `#[ffi_const]` function cannot be `#[ffi_pure]` diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 44a62383e6e..7ce29260e36 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -243,6 +243,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> { self.check_generic_attr(hir_id, attr, target, Target::Fn); self.check_proc_macro(hir_id, target, ProcMacroKind::Derive) } + [sym::autodiff, ..] => { + self.check_autodiff(hir_id, attr, span, target) + } [sym::coroutine, ..] => { self.check_coroutine(attr, target); } @@ -2345,6 +2348,18 @@ impl<'tcx> CheckAttrVisitor<'tcx> { self.dcx().emit_err(errors::RustcPubTransparent { span, attr_span }); } } + + /// Checks if `#[autodiff]` is applied to an item other than a function item. + fn check_autodiff(&self, _hir_id: HirId, _attr: &Attribute, span: Span, target: Target) { + debug!("check_autodiff"); + match target { + Target::Fn => {} + _ => { + self.dcx().emit_err(errors::AutoDiffAttr { attr_span: span }); + self.abort.set(true); + } + } + } } impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> { diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 4f00c90fa3b..70f525ec0e8 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -20,6 +20,14 @@ use crate::lang_items::Duplicate; #[diag(passes_incorrect_do_not_recommend_location)] pub(crate) struct IncorrectDoNotRecommendLocation; +#[derive(Diagnostic)] +#[diag(passes_autodiff_attr)] +pub(crate) struct AutoDiffAttr { + #[primary_span] + #[label] + pub attr_span: Span, +} + #[derive(LintDiagnostic)] #[diag(passes_outer_crate_level_attr)] pub(crate) struct OuterCrateLevelAttr; diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 8e0009695db..92946ef5262 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -481,6 +481,8 @@ symbols! { audit_that, augmented_assignments, auto_traits, + autodiff, + autodiff_fallback, automatically_derived, avx, avx512_target_feature, @@ -544,6 +546,7 @@ symbols! { cfg_accessible, cfg_attr, cfg_attr_multi, + cfg_autodiff_fallback, cfg_boolean_literals, cfg_doctest, cfg_eval, @@ -998,6 +1001,7 @@ symbols! { hashset_iter_ty, hexagon_target_feature, hidden, + hint, homogeneous_aggregate, host, html_favicon_url, @@ -1650,6 +1654,7 @@ symbols! { rustc_allow_incoherent_impl, rustc_allowed_through_unstable_modules, rustc_attrs, + rustc_autodiff, rustc_box, rustc_builtin_macro, rustc_capture_analysis, diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 96ab5755328..f69a33bca84 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -278,6 +278,15 @@ pub mod assert_matches { pub use crate::macros::{assert_matches, debug_assert_matches}; } +// We don't export this through #[macro_export] for now, to avoid breakage. +#[cfg(not(bootstrap))] +#[unstable(feature = "autodiff", issue = "124509")] +/// Unstable module containing the unstable `autodiff` macro. +pub mod autodiff { + #[unstable(feature = "autodiff", issue = "124509")] + pub use crate::macros::builtin::autodiff; +} + #[unstable(feature = "cfg_match", issue = "115585")] pub use crate::macros::cfg_match; diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index aa0646846e4..b5e5b58f705 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -1539,6 +1539,24 @@ pub(crate) mod builtin { ($file:expr $(,)?) => {{ /* compiler built-in */ }}; } + /// Automatic Differentiation macro which allows generating a new function to compute + /// the derivative of a given function. It may only be applied to a function. + /// The expected usage syntax is + /// `#[autodiff(NAME, MODE, INPUT_ACTIVITIES, OUTPUT_ACTIVITY)]` + /// where: + /// NAME is a string that represents a valid function name. + /// MODE is any of Forward, Reverse, ForwardFirst, ReverseFirst. + /// INPUT_ACTIVITIES consists of one valid activity for each input parameter. + /// OUTPUT_ACTIVITY must not be set if we implicitely return nothing (or explicitely return + /// `-> ()`. Otherwise it must be set to one of the allowed activities. + #[unstable(feature = "autodiff", issue = "124509")] + #[allow_internal_unstable(rustc_attrs)] + #[rustc_builtin_macro] + #[cfg(not(bootstrap))] + pub macro autodiff($item:item) { + /* compiler built-in */ + } + /// Asserts that a boolean expression is `true` at runtime. /// /// This will invoke the [`panic!`] macro if the provided expression cannot be diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 65a9aa66c7c..35ed761759b 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -267,6 +267,7 @@ #![allow(unused_features)] // // Features: +#![cfg_attr(not(bootstrap), feature(autodiff))] #![cfg_attr(test, feature(internal_output_capture, print_internals, update_panic_count, rt))] #![cfg_attr( all(target_vendor = "fortanix", target_env = "sgx"), @@ -627,7 +628,13 @@ pub mod simd { #[doc(inline)] pub use crate::std_float::StdFloat; } - +#[cfg(not(bootstrap))] +#[unstable(feature = "autodiff", issue = "124509")] +/// This module provides support for automatic differentiation. +pub mod autodiff { + /// This macro handles automatic differentiation. + pub use core::autodiff::autodiff; +} #[stable(feature = "futures_api", since = "1.36.0")] pub mod task { //! Types and Traits for working with asynchronous tasks. From 7c37d2db98ec28b633ddc69ca0cf0ca651ae00b3 Mon Sep 17 00:00:00 2001 From: Manuel Drehwald Date: Fri, 11 Oct 2024 20:38:43 +0200 Subject: [PATCH 205/357] Add pretty, ui, and feature-gate tests for the enzyme/autodiff frontend --- tests/pretty/autodiff_forward.pp | 107 ++++++++++++ tests/pretty/autodiff_forward.rs | 39 +++++ tests/pretty/autodiff_reverse.pp | 86 ++++++++++ tests/pretty/autodiff_reverse.rs | 40 +++++ tests/ui/autodiff/autodiff_illegal.rs | 160 ++++++++++++++++++ tests/ui/autodiff/autodiff_illegal.stderr | 152 +++++++++++++++++ tests/ui/autodiff/auxiliary/my_macro.rs | 12 ++ tests/ui/autodiff/visibility.rs | 17 ++ .../autodiff/visibility.std_autodiff.stderr | 24 +++ ...ature-gate-autodiff-use.has_support.stderr | 23 +++ ...eature-gate-autodiff-use.no_support.stderr | 29 ++++ .../feature-gate-autodiff-use.rs | 17 ++ .../feature-gate-autodiff.has_support.stderr | 13 ++ .../feature-gate-autodiff.no_support.stderr | 13 ++ .../ui/feature-gates/feature-gate-autodiff.rs | 12 ++ 15 files changed, 744 insertions(+) create mode 100644 tests/pretty/autodiff_forward.pp create mode 100644 tests/pretty/autodiff_forward.rs create mode 100644 tests/pretty/autodiff_reverse.pp create mode 100644 tests/pretty/autodiff_reverse.rs create mode 100644 tests/ui/autodiff/autodiff_illegal.rs create mode 100644 tests/ui/autodiff/autodiff_illegal.stderr create mode 100644 tests/ui/autodiff/auxiliary/my_macro.rs create mode 100644 tests/ui/autodiff/visibility.rs create mode 100644 tests/ui/autodiff/visibility.std_autodiff.stderr create mode 100644 tests/ui/feature-gates/feature-gate-autodiff-use.has_support.stderr create mode 100644 tests/ui/feature-gates/feature-gate-autodiff-use.no_support.stderr create mode 100644 tests/ui/feature-gates/feature-gate-autodiff-use.rs create mode 100644 tests/ui/feature-gates/feature-gate-autodiff.has_support.stderr create mode 100644 tests/ui/feature-gates/feature-gate-autodiff.no_support.stderr create mode 100644 tests/ui/feature-gates/feature-gate-autodiff.rs diff --git a/tests/pretty/autodiff_forward.pp b/tests/pretty/autodiff_forward.pp new file mode 100644 index 00000000000..23c3b5b34a8 --- /dev/null +++ b/tests/pretty/autodiff_forward.pp @@ -0,0 +1,107 @@ +#![feature(prelude_import)] +#![no_std] +//@ needs-enzyme + +#![feature(autodiff)] +#[prelude_import] +use ::std::prelude::rust_2015::*; +#[macro_use] +extern crate std; +//@ pretty-mode:expanded +//@ pretty-compare-only +//@ pp-exact:autodiff_forward.pp + +// Test that forward mode ad macros are expanded correctly. + +use std::autodiff::autodiff; + +#[rustc_autodiff] +#[inline(never)] +pub fn f1(x: &[f64], y: f64) -> f64 { + + + + // Not the most interesting derivative, but who are we to judge + + // We want to be sure that the same function can be differentiated in different ways + + ::core::panicking::panic("not implemented") +} +#[rustc_autodiff(Forward, Dual, Const, Dual,)] +#[inline(never)] +pub fn df1(x: &[f64], bx: &[f64], y: f64) -> (f64, f64) { + unsafe { asm!("NOP", options(pure, nomem)); }; + ::core::hint::black_box(f1(x, y)); + ::core::hint::black_box((bx,)); + ::core::hint::black_box((f1(x, y), f64::default())) +} +#[rustc_autodiff] +#[inline(never)] +pub fn f2(x: &[f64], y: f64) -> f64 { + ::core::panicking::panic("not implemented") +} +#[rustc_autodiff(Forward, Dual, Const, Const,)] +#[inline(never)] +pub fn df2(x: &[f64], bx: &[f64], y: f64) -> f64 { + unsafe { asm!("NOP", options(pure, nomem)); }; + ::core::hint::black_box(f2(x, y)); + ::core::hint::black_box((bx,)); + ::core::hint::black_box(f2(x, y)) +} +#[rustc_autodiff] +#[inline(never)] +pub fn f3(x: &[f64], y: f64) -> f64 { + ::core::panicking::panic("not implemented") +} +#[rustc_autodiff(ForwardFirst, Dual, Const, Const,)] +#[inline(never)] +pub fn df3(x: &[f64], bx: &[f64], y: f64) -> f64 { + unsafe { asm!("NOP", options(pure, nomem)); }; + ::core::hint::black_box(f3(x, y)); + ::core::hint::black_box((bx,)); + ::core::hint::black_box(f3(x, y)) +} +#[rustc_autodiff] +#[inline(never)] +pub fn f4() {} +#[rustc_autodiff(Forward, None)] +#[inline(never)] +pub fn df4() { + unsafe { asm!("NOP", options(pure, nomem)); }; + ::core::hint::black_box(f4()); + ::core::hint::black_box(()); +} +#[rustc_autodiff] +#[inline(never)] +#[rustc_autodiff] +#[inline(never)] +#[rustc_autodiff] +#[inline(never)] +pub fn f5(x: &[f64], y: f64) -> f64 { + ::core::panicking::panic("not implemented") +} +#[rustc_autodiff(Forward, Const, Dual, Const,)] +#[inline(never)] +pub fn df5_y(x: &[f64], y: f64, by: f64) -> f64 { + unsafe { asm!("NOP", options(pure, nomem)); }; + ::core::hint::black_box(f5(x, y)); + ::core::hint::black_box((by,)); + ::core::hint::black_box(f5(x, y)) +} +#[rustc_autodiff(Forward, Dual, Const, Const,)] +#[inline(never)] +pub fn df5_x(x: &[f64], bx: &[f64], y: f64) -> f64 { + unsafe { asm!("NOP", options(pure, nomem)); }; + ::core::hint::black_box(f5(x, y)); + ::core::hint::black_box((bx,)); + ::core::hint::black_box(f5(x, y)) +} +#[rustc_autodiff(Reverse, Duplicated, Const, Active,)] +#[inline(never)] +pub fn df5_rev(x: &[f64], dx: &mut [f64], y: f64, dret: f64) -> f64 { + unsafe { asm!("NOP", options(pure, nomem)); }; + ::core::hint::black_box(f5(x, y)); + ::core::hint::black_box((dx, dret)); + ::core::hint::black_box(f5(x, y)) +} +fn main() {} diff --git a/tests/pretty/autodiff_forward.rs b/tests/pretty/autodiff_forward.rs new file mode 100644 index 00000000000..35108d0d6f1 --- /dev/null +++ b/tests/pretty/autodiff_forward.rs @@ -0,0 +1,39 @@ +//@ needs-enzyme + +#![feature(autodiff)] +//@ pretty-mode:expanded +//@ pretty-compare-only +//@ pp-exact:autodiff_forward.pp + +// Test that forward mode ad macros are expanded correctly. + +use std::autodiff::autodiff; + +#[autodiff(df1, Forward, Dual, Const, Dual)] +pub fn f1(x: &[f64], y: f64) -> f64 { + unimplemented!() +} + +#[autodiff(df2, Forward, Dual, Const, Const)] +pub fn f2(x: &[f64], y: f64) -> f64 { + unimplemented!() +} + +#[autodiff(df3, ForwardFirst, Dual, Const, Const)] +pub fn f3(x: &[f64], y: f64) -> f64 { + unimplemented!() +} + +// Not the most interesting derivative, but who are we to judge +#[autodiff(df4, Forward)] +pub fn f4() {} + +// We want to be sure that the same function can be differentiated in different ways +#[autodiff(df5_rev, Reverse, Duplicated, Const, Active)] +#[autodiff(df5_x, Forward, Dual, Const, Const)] +#[autodiff(df5_y, Forward, Const, Dual, Const)] +pub fn f5(x: &[f64], y: f64) -> f64 { + unimplemented!() +} + +fn main() {} diff --git a/tests/pretty/autodiff_reverse.pp b/tests/pretty/autodiff_reverse.pp new file mode 100644 index 00000000000..a98d3782c70 --- /dev/null +++ b/tests/pretty/autodiff_reverse.pp @@ -0,0 +1,86 @@ +#![feature(prelude_import)] +#![no_std] +//@ needs-enzyme + +#![feature(autodiff)] +#[prelude_import] +use ::std::prelude::rust_2015::*; +#[macro_use] +extern crate std; +//@ pretty-mode:expanded +//@ pretty-compare-only +//@ pp-exact:autodiff_reverse.pp + +// Test that reverse mode ad macros are expanded correctly. + +use std::autodiff::autodiff; + +#[rustc_autodiff] +#[inline(never)] +pub fn f1(x: &[f64], y: f64) -> f64 { + + // Not the most interesting derivative, but who are we to judge + + + // What happens if we already have Reverse in type (enum variant decl) and value (enum variant + // constructor) namespace? > It's expected to work normally. + + + ::core::panicking::panic("not implemented") +} +#[rustc_autodiff(Reverse, Duplicated, Const, Active,)] +#[inline(never)] +pub fn df1(x: &[f64], dx: &mut [f64], y: f64, dret: f64) -> f64 { + unsafe { asm!("NOP", options(pure, nomem)); }; + ::core::hint::black_box(f1(x, y)); + ::core::hint::black_box((dx, dret)); + ::core::hint::black_box(f1(x, y)) +} +#[rustc_autodiff] +#[inline(never)] +pub fn f2() {} +#[rustc_autodiff(Reverse, None)] +#[inline(never)] +pub fn df2() { + unsafe { asm!("NOP", options(pure, nomem)); }; + ::core::hint::black_box(f2()); + ::core::hint::black_box(()); +} +#[rustc_autodiff] +#[inline(never)] +pub fn f3(x: &[f64], y: f64) -> f64 { + ::core::panicking::panic("not implemented") +} +#[rustc_autodiff(ReverseFirst, Duplicated, Const, Active,)] +#[inline(never)] +pub fn df3(x: &[f64], dx: &mut [f64], y: f64, dret: f64) -> f64 { + unsafe { asm!("NOP", options(pure, nomem)); }; + ::core::hint::black_box(f3(x, y)); + ::core::hint::black_box((dx, dret)); + ::core::hint::black_box(f3(x, y)) +} +enum Foo { Reverse, } +use Foo::Reverse; +#[rustc_autodiff] +#[inline(never)] +pub fn f4(x: f32) { ::core::panicking::panic("not implemented") } +#[rustc_autodiff(Reverse, Const, None)] +#[inline(never)] +pub fn df4(x: f32) { + unsafe { asm!("NOP", options(pure, nomem)); }; + ::core::hint::black_box(f4(x)); + ::core::hint::black_box(()); +} +#[rustc_autodiff] +#[inline(never)] +pub fn f5(x: *const f32, y: &f32) { + ::core::panicking::panic("not implemented") +} +#[rustc_autodiff(Reverse, DuplicatedOnly, Duplicated, None)] +#[inline(never)] +pub unsafe fn df5(x: *const f32, dx: *mut f32, y: &f32, dy: &mut f32) { + unsafe { asm!("NOP", options(pure, nomem)); }; + ::core::hint::black_box(f5(x, y)); + ::core::hint::black_box((dx, dy)); +} +fn main() {} diff --git a/tests/pretty/autodiff_reverse.rs b/tests/pretty/autodiff_reverse.rs new file mode 100644 index 00000000000..657201caa94 --- /dev/null +++ b/tests/pretty/autodiff_reverse.rs @@ -0,0 +1,40 @@ +//@ needs-enzyme + +#![feature(autodiff)] +//@ pretty-mode:expanded +//@ pretty-compare-only +//@ pp-exact:autodiff_reverse.pp + +// Test that reverse mode ad macros are expanded correctly. + +use std::autodiff::autodiff; + +#[autodiff(df1, Reverse, Duplicated, Const, Active)] +pub fn f1(x: &[f64], y: f64) -> f64 { + unimplemented!() +} + +// Not the most interesting derivative, but who are we to judge +#[autodiff(df2, Reverse)] +pub fn f2() {} + +#[autodiff(df3, ReverseFirst, Duplicated, Const, Active)] +pub fn f3(x: &[f64], y: f64) -> f64 { + unimplemented!() +} + +enum Foo { Reverse } +use Foo::Reverse; +// What happens if we already have Reverse in type (enum variant decl) and value (enum variant +// constructor) namespace? > It's expected to work normally. +#[autodiff(df4, Reverse, Const)] +pub fn f4(x: f32) { + unimplemented!() +} + +#[autodiff(df5, Reverse, DuplicatedOnly, Duplicated)] +pub fn f5(x: *const f32, y: &f32) { + unimplemented!() +} + +fn main() {} diff --git a/tests/ui/autodiff/autodiff_illegal.rs b/tests/ui/autodiff/autodiff_illegal.rs new file mode 100644 index 00000000000..c0548d2bbb8 --- /dev/null +++ b/tests/ui/autodiff/autodiff_illegal.rs @@ -0,0 +1,160 @@ +//@ needs-enzyme + +#![feature(autodiff)] +//@ pretty-mode:expanded +//@ pretty-compare-only +//@ pp-exact:autodiff_illegal.pp + +// Test that invalid ad macros give nice errors and don't ICE. + +use std::autodiff::autodiff; + +// We can't use Duplicated on scalars +#[autodiff(df1, Reverse, Duplicated)] +pub fn f1(x: f64) { +//~^ ERROR Duplicated can not be used for this type + unimplemented!() +} + +// Too many activities +#[autodiff(df3, Reverse, Duplicated, Const)] +pub fn f3(x: f64) { +//~^^ ERROR expected 1 activities, but found 2 + unimplemented!() +} + +// To few activities +#[autodiff(df4, Reverse)] +pub fn f4(x: f64) { +//~^^ ERROR expected 1 activities, but found 0 + unimplemented!() +} + +// We can't use Dual in Reverse mode +#[autodiff(df5, Reverse, Dual)] +pub fn f5(x: f64) { +//~^^ ERROR Dual can not be used in Reverse Mode + unimplemented!() +} + +// We can't use Duplicated in Forward mode +#[autodiff(df6, Forward, Duplicated)] +pub fn f6(x: f64) { +//~^^ ERROR Duplicated can not be used in Forward Mode +//~^^ ERROR Duplicated can not be used for this type + unimplemented!() +} + +fn dummy() { + + #[autodiff(df7, Forward, Dual)] + let mut x = 5; + //~^ ERROR autodiff must be applied to function + + #[autodiff(df7, Forward, Dual)] + x = x + 3; + //~^^ ERROR attributes on expressions are experimental [E0658] + //~^^ ERROR autodiff must be applied to function + + #[autodiff(df7, Forward, Dual)] + let add_one_v2 = |x: u32| -> u32 { x + 1 }; + //~^ ERROR autodiff must be applied to function +} + +// Malformed, where args? +#[autodiff] +pub fn f7(x: f64) { +//~^ ERROR autodiff must be applied to function + unimplemented!() +} + +// Malformed, where args? +#[autodiff()] +pub fn f8(x: f64) { +//~^ ERROR autodiff requires at least a name and mode + unimplemented!() +} + +// Invalid attribute syntax +#[autodiff = ""] +pub fn f9(x: f64) { +//~^ ERROR autodiff must be applied to function + unimplemented!() +} + +fn fn_exists() {} + +// We colide with an already existing function +#[autodiff(fn_exists, Reverse, Active)] +pub fn f10(x: f64) { +//~^^ ERROR the name `fn_exists` is defined multiple times [E0428] + unimplemented!() +} + +// Malformed, missing a mode +#[autodiff(df11)] +pub fn f11() { +//~^ ERROR autodiff requires at least a name and mode + unimplemented!() +} + +// Invalid Mode +#[autodiff(df12, Debug)] +pub fn f12() { +//~^^ ERROR unknown Mode: `Debug`. Use `Forward` or `Reverse` + unimplemented!() +} + +// Invalid, please pick one Mode +// or use two autodiff macros. +#[autodiff(df13, Forward, Reverse)] +pub fn f13() { +//~^^ ERROR did not recognize Activity: `Reverse` + unimplemented!() +} + +struct Foo {} + +// We can't handle Active structs, because that would mean (in the general case), that we would +// need to allocate and initialize arbitrary user types. We have Duplicated/Dual input args for +// that. FIXME: Give a nicer error and suggest to the user to have a `&mut Foo` input instead. +#[autodiff(df14, Reverse, Active, Active)] +fn f14(x: f32) -> Foo { + unimplemented!() +} + +type MyFloat = f32; + +// We would like to support type alias to f32/f64 in argument type in the future, +// but that requires us to implement our checks at a later stage +// like THIR which has type information available. +#[autodiff(df15, Reverse, Active, Active)] +fn f15(x: MyFloat) -> f32 { +//~^^ ERROR failed to resolve: use of undeclared type `MyFloat` [E0433] + unimplemented!() +} + +// We would like to support type alias to f32/f64 in return type in the future +#[autodiff(df16, Reverse, Active, Active)] +fn f16(x: f32) -> MyFloat { + unimplemented!() +} + +#[repr(transparent)] +struct F64Trans { inner: f64 } + +// We would like to support `#[repr(transparent)]` f32/f64 wrapper in return type in the future +#[autodiff(df17, Reverse, Active, Active)] +fn f17(x: f64) -> F64Trans { + unimplemented!() +} + +// We would like to support `#[repr(transparent)]` f32/f64 wrapper in argument type in the future +#[autodiff(df18, Reverse, Active, Active)] +fn f18(x: F64Trans) -> f64 { + //~^^ ERROR failed to resolve: use of undeclared type `F64Trans` [E0433] + unimplemented!() +} + + +fn main() {} diff --git a/tests/ui/autodiff/autodiff_illegal.stderr b/tests/ui/autodiff/autodiff_illegal.stderr new file mode 100644 index 00000000000..3a7242b2f5d --- /dev/null +++ b/tests/ui/autodiff/autodiff_illegal.stderr @@ -0,0 +1,152 @@ +error[E0658]: attributes on expressions are experimental + --> $DIR/autodiff_illegal.rs:54:5 + | +LL | #[autodiff(df7, Forward, Dual)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: Duplicated can not be used for this type + --> $DIR/autodiff_illegal.rs:14:14 + | +LL | pub fn f1(x: f64) { + | ^^^ + +error: expected 1 activities, but found 2 + --> $DIR/autodiff_illegal.rs:20:1 + | +LL | #[autodiff(df3, Reverse, Duplicated, Const)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in the attribute macro `autodiff` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: expected 1 activities, but found 0 + --> $DIR/autodiff_illegal.rs:27:1 + | +LL | #[autodiff(df4, Reverse)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in the attribute macro `autodiff` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: Dual can not be used in Reverse Mode + --> $DIR/autodiff_illegal.rs:34:1 + | +LL | #[autodiff(df5, Reverse, Dual)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in the attribute macro `autodiff` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: Duplicated can not be used in Forward Mode + --> $DIR/autodiff_illegal.rs:41:1 + | +LL | #[autodiff(df6, Forward, Duplicated)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in the attribute macro `autodiff` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: Duplicated can not be used for this type + --> $DIR/autodiff_illegal.rs:42:14 + | +LL | pub fn f6(x: f64) { + | ^^^ + +error: autodiff must be applied to function + --> $DIR/autodiff_illegal.rs:51:5 + | +LL | let mut x = 5; + | ^^^^^^^^^^^^^^ + +error: autodiff must be applied to function + --> $DIR/autodiff_illegal.rs:55:5 + | +LL | x = x + 3; + | ^ + +error: autodiff must be applied to function + --> $DIR/autodiff_illegal.rs:60:5 + | +LL | let add_one_v2 = |x: u32| -> u32 { x + 1 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: autodiff must be applied to function + --> $DIR/autodiff_illegal.rs:66:1 + | +LL | / pub fn f7(x: f64) { +LL | | +LL | | unimplemented!() +LL | | } + | |_^ + +error: autodiff requires at least a name and mode + --> $DIR/autodiff_illegal.rs:73:1 + | +LL | / pub fn f8(x: f64) { +LL | | +LL | | unimplemented!() +LL | | } + | |_^ + +error: autodiff must be applied to function + --> $DIR/autodiff_illegal.rs:80:1 + | +LL | / pub fn f9(x: f64) { +LL | | +LL | | unimplemented!() +LL | | } + | |_^ + +error[E0428]: the name `fn_exists` is defined multiple times + --> $DIR/autodiff_illegal.rs:88:1 + | +LL | fn fn_exists() {} + | -------------- previous definition of the value `fn_exists` here +... +LL | #[autodiff(fn_exists, Reverse, Active)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `fn_exists` redefined here + | + = note: `fn_exists` must be defined only once in the value namespace of this module + = note: this error originates in the attribute macro `autodiff` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: autodiff requires at least a name and mode + --> $DIR/autodiff_illegal.rs:96:1 + | +LL | / pub fn f11() { +LL | | +LL | | unimplemented!() +LL | | } + | |_^ + +error: unknown Mode: `Debug`. Use `Forward` or `Reverse` + --> $DIR/autodiff_illegal.rs:102:18 + | +LL | #[autodiff(df12, Debug)] + | ^^^^^ + +error: did not recognize Activity: `Reverse` + --> $DIR/autodiff_illegal.rs:110:27 + | +LL | #[autodiff(df13, Forward, Reverse)] + | ^^^^^^^ + +error[E0433]: failed to resolve: use of undeclared type `MyFloat` + --> $DIR/autodiff_illegal.rs:131:1 + | +LL | #[autodiff(df15, Reverse, Active, Active)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ use of undeclared type `MyFloat` + | + = note: this error originates in the attribute macro `autodiff` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0433]: failed to resolve: use of undeclared type `F64Trans` + --> $DIR/autodiff_illegal.rs:153:1 + | +LL | #[autodiff(df18, Reverse, Active, Active)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ use of undeclared type `F64Trans` + | + = note: this error originates in the attribute macro `autodiff` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 19 previous errors + +Some errors have detailed explanations: E0428, E0433, E0658. +For more information about an error, try `rustc --explain E0428`. diff --git a/tests/ui/autodiff/auxiliary/my_macro.rs b/tests/ui/autodiff/auxiliary/my_macro.rs new file mode 100644 index 00000000000..417199611cc --- /dev/null +++ b/tests/ui/autodiff/auxiliary/my_macro.rs @@ -0,0 +1,12 @@ +//@ force-host +//@ no-prefer-dynamic +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::TokenStream; + +#[proc_macro_attribute] +#[macro_use] +pub fn autodiff(_attr: TokenStream, item: TokenStream) -> TokenStream { + item // identity proc-macro +} diff --git a/tests/ui/autodiff/visibility.rs b/tests/ui/autodiff/visibility.rs new file mode 100644 index 00000000000..6a4851de2dc --- /dev/null +++ b/tests/ui/autodiff/visibility.rs @@ -0,0 +1,17 @@ +//@ ignore-enzyme +//@ revisions: std_autodiff no_std_autodiff +//@[no_std_autodiff] check-pass +//@ aux-build: my_macro.rs +#![crate_type = "lib"] +#![feature(autodiff)] + +#[cfg(std_autodiff)] +use std::autodiff::autodiff; + +extern crate my_macro; +use my_macro::autodiff; // bring `autodiff` in scope + +#[autodiff] +//[std_autodiff]~^^^ ERROR the name `autodiff` is defined multiple times +//[std_autodiff]~^^ ERROR this rustc version does not support autodiff +fn foo() {} diff --git a/tests/ui/autodiff/visibility.std_autodiff.stderr b/tests/ui/autodiff/visibility.std_autodiff.stderr new file mode 100644 index 00000000000..720c9a00170 --- /dev/null +++ b/tests/ui/autodiff/visibility.std_autodiff.stderr @@ -0,0 +1,24 @@ +error[E0252]: the name `autodiff` is defined multiple times + --> $DIR/visibility.rs:12:5 + | +LL | use std::autodiff::autodiff; + | ----------------------- previous import of the macro `autodiff` here +... +LL | use my_macro::autodiff; // bring `autodiff` in scope + | ^^^^^^^^^^^^^^^^^^ `autodiff` reimported here + | + = note: `autodiff` must be defined only once in the macro namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | use my_macro::autodiff as other_autodiff; // bring `autodiff` in scope + | +++++++++++++++++ + +error: this rustc version does not support autodiff + --> $DIR/visibility.rs:14:1 + | +LL | #[autodiff] + | ^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0252`. diff --git a/tests/ui/feature-gates/feature-gate-autodiff-use.has_support.stderr b/tests/ui/feature-gates/feature-gate-autodiff-use.has_support.stderr new file mode 100644 index 00000000000..36a017dd53c --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-autodiff-use.has_support.stderr @@ -0,0 +1,23 @@ +error[E0658]: use of unstable library feature 'autodiff' + --> $DIR/feature-gate-autodiff-use.rs:13:3 + | +LL | #[autodiff(dfoo, Reverse)] + | ^^^^^^^^ + | + = note: see issue #124509 for more information + = help: add `#![feature(autodiff)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: use of unstable library feature 'autodiff' + --> $DIR/feature-gate-autodiff-use.rs:9:5 + | +LL | use std::autodiff::autodiff; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #124509 for more information + = help: add `#![feature(autodiff)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-autodiff-use.no_support.stderr b/tests/ui/feature-gates/feature-gate-autodiff-use.no_support.stderr new file mode 100644 index 00000000000..4b767f824c8 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-autodiff-use.no_support.stderr @@ -0,0 +1,29 @@ +error[E0658]: use of unstable library feature 'autodiff' + --> $DIR/feature-gate-autodiff-use.rs:13:3 + | +LL | #[autodiff(dfoo, Reverse)] + | ^^^^^^^^ + | + = note: see issue #124509 for more information + = help: add `#![feature(autodiff)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: this rustc version does not support autodiff + --> $DIR/feature-gate-autodiff-use.rs:13:1 + | +LL | #[autodiff(dfoo, Reverse)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0658]: use of unstable library feature 'autodiff' + --> $DIR/feature-gate-autodiff-use.rs:9:5 + | +LL | use std::autodiff::autodiff; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #124509 for more information + = help: add `#![feature(autodiff)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-autodiff-use.rs b/tests/ui/feature-gates/feature-gate-autodiff-use.rs new file mode 100644 index 00000000000..2276a79d6e2 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-autodiff-use.rs @@ -0,0 +1,17 @@ +//@ revisions: has_support no_support +//@[no_support] ignore-enzyme +//@[has_support] needs-enzyme + +// This checks that without enabling the autodiff feature, we can't import std::autodiff::autodiff; + +#![crate_type = "lib"] + +use std::autodiff::autodiff; +//[has_support]~^ ERROR use of unstable library feature 'autodiff' +//[no_support]~^^ ERROR use of unstable library feature 'autodiff' + +#[autodiff(dfoo, Reverse)] +//[has_support]~^ ERROR use of unstable library feature 'autodiff' [E0658] +//[no_support]~^^ ERROR use of unstable library feature 'autodiff' [E0658] +//[no_support]~| ERROR this rustc version does not support autodiff +fn foo() {} diff --git a/tests/ui/feature-gates/feature-gate-autodiff.has_support.stderr b/tests/ui/feature-gates/feature-gate-autodiff.has_support.stderr new file mode 100644 index 00000000000..c25cf7d3373 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-autodiff.has_support.stderr @@ -0,0 +1,13 @@ +error: cannot find attribute `autodiff` in this scope + --> $DIR/feature-gate-autodiff.rs:9:3 + | +LL | #[autodiff(dfoo, Reverse)] + | ^^^^^^^^ + | +help: consider importing this attribute macro + | +LL + use std::autodiff::autodiff; + | + +error: aborting due to 1 previous error + diff --git a/tests/ui/feature-gates/feature-gate-autodiff.no_support.stderr b/tests/ui/feature-gates/feature-gate-autodiff.no_support.stderr new file mode 100644 index 00000000000..c25cf7d3373 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-autodiff.no_support.stderr @@ -0,0 +1,13 @@ +error: cannot find attribute `autodiff` in this scope + --> $DIR/feature-gate-autodiff.rs:9:3 + | +LL | #[autodiff(dfoo, Reverse)] + | ^^^^^^^^ + | +help: consider importing this attribute macro + | +LL + use std::autodiff::autodiff; + | + +error: aborting due to 1 previous error + diff --git a/tests/ui/feature-gates/feature-gate-autodiff.rs b/tests/ui/feature-gates/feature-gate-autodiff.rs new file mode 100644 index 00000000000..4249b229a69 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-autodiff.rs @@ -0,0 +1,12 @@ +//@ revisions: has_support no_support +//@[no_support] ignore-enzyme +//@[has_support] needs-enzyme + +#![crate_type = "lib"] + +// This checks that without the autodiff feature enabled, we can't use it. + +#[autodiff(dfoo, Reverse)] +//[has_support]~^ ERROR cannot find attribute `autodiff` in this scope +//[no_support]~^^ ERROR cannot find attribute `autodiff` in this scope +fn foo() {} From 77b3065ed242c497af14afdf18467cf6b8b44b1e Mon Sep 17 00:00:00 2001 From: Urgau Date: Fri, 11 Oct 2024 21:21:32 +0200 Subject: [PATCH 206/357] Remove deprecation note in the `non_local_definitions` warning --- compiler/rustc_lint/messages.ftl | 2 -- compiler/rustc_lint/src/lints.rs | 3 --- .../rustdoc-ui/doctest/non-local-defs-impl.stdout | 1 - tests/rustdoc-ui/doctest/non_local_defs.stderr | 1 - tests/ui/lint/non-local-defs/cargo-update.stderr | 1 - tests/ui/lint/non-local-defs/consts.stderr | 9 --------- .../ui/lint/non-local-defs/exhaustive-trait.stderr | 6 ------ tests/ui/lint/non-local-defs/exhaustive.stderr | 14 -------------- .../non-local-defs/from-local-for-global.stderr | 1 - tests/ui/lint/non-local-defs/generics.stderr | 3 --- .../lint/non-local-defs/inside-macro_rules.stderr | 1 - tests/ui/lint/non-local-defs/macro_rules.stderr | 4 ---- tests/ui/lint/non-local-defs/weird-exprs.stderr | 6 ------ tests/ui/proc-macro/nested-macro-rules.stderr | 1 - 14 files changed, 53 deletions(-) diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index e733e92c7cb..c4d709aa1f9 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -581,8 +581,6 @@ lint_non_glob_import_type_ir_inherent = non-glob import of `rustc_type_ir::inher lint_non_local_definitions_cargo_update = the {$macro_kind} `{$macro_name}` may come from an old version of the `{$crate_name}` crate, try updating your dependency with `cargo update -p {$crate_name}` -lint_non_local_definitions_deprecation = this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue - lint_non_local_definitions_impl = non-local `impl` definition, `impl` blocks should be written at the same level as their item .non_local = an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` .doctest = make this doc-test a standalone test with its own `fn main() {"{"} ... {"}"}` diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 87afeca0b28..16cfae17d40 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -1430,8 +1430,6 @@ impl<'a> LintDiagnostic<'a, ()> for NonLocalDefinitionsDiag { ); } } - - diag.note(fluent::lint_non_local_definitions_deprecation); } NonLocalDefinitionsDiag::MacroRules { depth, @@ -1452,7 +1450,6 @@ impl<'a> LintDiagnostic<'a, ()> for NonLocalDefinitionsDiag { } diag.note(fluent::lint_non_local); - diag.note(fluent::lint_non_local_definitions_deprecation); if let Some(cargo_update) = cargo_update { diag.subdiagnostic(cargo_update); diff --git a/tests/rustdoc-ui/doctest/non-local-defs-impl.stdout b/tests/rustdoc-ui/doctest/non-local-defs-impl.stdout index f39d2c2608b..c1f750017e7 100644 --- a/tests/rustdoc-ui/doctest/non-local-defs-impl.stdout +++ b/tests/rustdoc-ui/doctest/non-local-defs-impl.stdout @@ -18,7 +18,6 @@ LL | impl Trait for &Local {} | `Trait` is not local | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue note: the lint level is defined here --> $DIR/non-local-defs-impl.rs:11:9 | diff --git a/tests/rustdoc-ui/doctest/non_local_defs.stderr b/tests/rustdoc-ui/doctest/non_local_defs.stderr index 2b47e6b5bc4..e39dc4d5ee0 100644 --- a/tests/rustdoc-ui/doctest/non_local_defs.stderr +++ b/tests/rustdoc-ui/doctest/non_local_defs.stderr @@ -6,7 +6,6 @@ LL | macro_rules! a_macro { () => {} } | = help: remove the `#[macro_export]` or make this doc-test a standalone test with its own `fn main() { ... }` = note: a `macro_rules!` definition is non-local if it is nested inside an item and has a `#[macro_export]` attribute - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue = note: `#[warn(non_local_definitions)]` on by default warning: 1 warning emitted diff --git a/tests/ui/lint/non-local-defs/cargo-update.stderr b/tests/ui/lint/non-local-defs/cargo-update.stderr index 77ee28b48cc..d579fa391fc 100644 --- a/tests/ui/lint/non-local-defs/cargo-update.stderr +++ b/tests/ui/lint/non-local-defs/cargo-update.stderr @@ -12,7 +12,6 @@ LL | non_local_macro::non_local_impl!(LocalStruct); = note: the macro `non_local_macro::non_local_impl` may come from an old version of the `non_local_macro` crate, try updating your dependency with `cargo update -p non_local_macro` = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: items in an anonymous const item (`const _: () = { ... }`) are treated as in the same scope as the anonymous const's declaration for the purpose of this lint - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue = note: `#[warn(non_local_definitions)]` on by default = note: this warning originates in the macro `non_local_macro::non_local_impl` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/lint/non-local-defs/consts.stderr b/tests/ui/lint/non-local-defs/consts.stderr index 4bf50bae5ea..20fb4a6432e 100644 --- a/tests/ui/lint/non-local-defs/consts.stderr +++ b/tests/ui/lint/non-local-defs/consts.stderr @@ -15,7 +15,6 @@ LL | impl Uto for &Test {} | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: items in an anonymous const item (`const _: () = { ... }`) are treated as in the same scope as the anonymous const's declaration for the purpose of this lint - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue = note: `#[warn(non_local_definitions)]` on by default warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -31,7 +30,6 @@ LL | impl Uto2 for Test {} | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: items in an anonymous const item (`const _: () = { ... }`) are treated as in the same scope as the anonymous const's declaration for the purpose of this lint - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/consts.rs:32:5 @@ -46,7 +44,6 @@ LL | impl Uto3 for Test {} | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: items in an anonymous const item (`const _: () = { ... }`) are treated as in the same scope as the anonymous const's declaration for the purpose of this lint - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/consts.rs:43:5 @@ -59,7 +56,6 @@ LL | impl Test { | `Test` is not local | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/consts.rs:50:9 @@ -78,7 +74,6 @@ LL | | }; | |_____- move the `impl` block outside of this inline constant `` and up 2 bodies | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/consts.rs:59:9 @@ -92,7 +87,6 @@ LL | impl Test { | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: items in an anonymous const item (`const _: () = { ... }`) are treated as in the same scope as the anonymous const's declaration for the purpose of this lint - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/consts.rs:69:13 @@ -106,7 +100,6 @@ LL | impl Test {} | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: items in an anonymous const item (`const _: () = { ... }`) are treated as in the same scope as the anonymous const's declaration for the purpose of this lint - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/consts.rs:79:9 @@ -120,7 +113,6 @@ LL | impl Uto9 for Test {} | `Uto9` is not local | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/consts.rs:86:9 @@ -138,7 +130,6 @@ LL | | }]; | |_____- move the `impl` block outside of this constant expression `` and up 2 bodies | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: 9 warnings emitted diff --git a/tests/ui/lint/non-local-defs/exhaustive-trait.stderr b/tests/ui/lint/non-local-defs/exhaustive-trait.stderr index c58ec12aaac..83e46df185d 100644 --- a/tests/ui/lint/non-local-defs/exhaustive-trait.stderr +++ b/tests/ui/lint/non-local-defs/exhaustive-trait.stderr @@ -10,7 +10,6 @@ LL | impl PartialEq<()> for Dog { | `PartialEq` is not local | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue = note: `#[warn(non_local_definitions)]` on by default warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -26,7 +25,6 @@ LL | impl PartialEq<()> for &Dog { | `PartialEq` is not local | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive-trait.rs:21:5 @@ -41,7 +39,6 @@ LL | impl PartialEq for () { | `PartialEq` is not local | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive-trait.rs:28:5 @@ -56,7 +53,6 @@ LL | impl PartialEq<&Dog> for () { | `PartialEq` is not local | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive-trait.rs:35:5 @@ -72,7 +68,6 @@ LL | impl PartialEq for &Dog { | `PartialEq` is not local | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive-trait.rs:42:5 @@ -88,7 +83,6 @@ LL | impl PartialEq<&Dog> for &Dog { | `PartialEq` is not local | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: 6 warnings emitted diff --git a/tests/ui/lint/non-local-defs/exhaustive.stderr b/tests/ui/lint/non-local-defs/exhaustive.stderr index dd41b2206d8..1e6fc910621 100644 --- a/tests/ui/lint/non-local-defs/exhaustive.stderr +++ b/tests/ui/lint/non-local-defs/exhaustive.stderr @@ -9,7 +9,6 @@ LL | impl Test { | `Test` is not local | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue = note: `#[warn(non_local_definitions)]` on by default warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -25,7 +24,6 @@ LL | impl Display for Test { | `Display` is not local | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive.rs:22:5 @@ -39,7 +37,6 @@ LL | impl dyn Trait {} | `Trait` is not local | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive.rs:25:5 @@ -54,7 +51,6 @@ LL | impl Trait for Vec { } | `Trait` is not local | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive.rs:28:5 @@ -69,7 +65,6 @@ LL | impl Trait for &dyn Trait {} | `Trait` is not local | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive.rs:31:5 @@ -84,7 +79,6 @@ LL | impl Trait for *mut Test {} | `Trait` is not local | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive.rs:34:5 @@ -99,7 +93,6 @@ LL | impl Trait for *mut [Test] {} | `Trait` is not local | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive.rs:37:5 @@ -114,7 +107,6 @@ LL | impl Trait for [Test; 8] {} | `Trait` is not local | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive.rs:40:5 @@ -129,7 +121,6 @@ LL | impl Trait for (Test,) {} | `Trait` is not local | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive.rs:43:5 @@ -144,7 +135,6 @@ LL | impl Trait for fn(Test) -> () {} | `Trait` is not local | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive.rs:46:5 @@ -159,7 +149,6 @@ LL | impl Trait for fn() -> Test {} | `Trait` is not local | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive.rs:50:9 @@ -173,7 +162,6 @@ LL | impl Trait for Test {} | `Trait` is not local | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive.rs:67:9 @@ -187,7 +175,6 @@ LL | impl Display for InsideMain { | `Display` is not local | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive.rs:74:9 @@ -201,7 +188,6 @@ LL | impl InsideMain { | `InsideMain` is not local | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: 14 warnings emitted diff --git a/tests/ui/lint/non-local-defs/from-local-for-global.stderr b/tests/ui/lint/non-local-defs/from-local-for-global.stderr index 6839ebd2c8a..f173c054e78 100644 --- a/tests/ui/lint/non-local-defs/from-local-for-global.stderr +++ b/tests/ui/lint/non-local-defs/from-local-for-global.stderr @@ -10,7 +10,6 @@ LL | impl From for () { | `From` is not local | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue = note: `#[warn(non_local_definitions)]` on by default warning: 1 warning emitted diff --git a/tests/ui/lint/non-local-defs/generics.stderr b/tests/ui/lint/non-local-defs/generics.stderr index aefe8921fe2..66769cc1e0b 100644 --- a/tests/ui/lint/non-local-defs/generics.stderr +++ b/tests/ui/lint/non-local-defs/generics.stderr @@ -11,7 +11,6 @@ LL | impl Global for Vec { } | `Global` is not local | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue = note: `#[warn(non_local_definitions)]` on by default warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -27,7 +26,6 @@ LL | impl Uto7 for Test where Local: std::any::Any {} | `Uto7` is not local | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/generics.rs:23:5 @@ -41,7 +39,6 @@ LL | impl Uto8 for T {} | `Uto8` is not local | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: 3 warnings emitted diff --git a/tests/ui/lint/non-local-defs/inside-macro_rules.stderr b/tests/ui/lint/non-local-defs/inside-macro_rules.stderr index faab6aea2b3..b6fe1a921d7 100644 --- a/tests/ui/lint/non-local-defs/inside-macro_rules.stderr +++ b/tests/ui/lint/non-local-defs/inside-macro_rules.stderr @@ -14,7 +14,6 @@ LL | m!(); | = note: the macro `m` defines the non-local `impl`, and may need to be changed = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue = note: `#[warn(non_local_definitions)]` on by default = note: this warning originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/lint/non-local-defs/macro_rules.stderr b/tests/ui/lint/non-local-defs/macro_rules.stderr index 4e86fc7b987..28779a78066 100644 --- a/tests/ui/lint/non-local-defs/macro_rules.stderr +++ b/tests/ui/lint/non-local-defs/macro_rules.stderr @@ -6,7 +6,6 @@ LL | macro_rules! m0 { () => { } }; | = help: remove the `#[macro_export]` or move this `macro_rules!` outside the of the current constant `B` = note: a `macro_rules!` definition is non-local if it is nested inside an item and has a `#[macro_export]` attribute - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue = note: `#[warn(non_local_definitions)]` on by default warning: non-local `macro_rules!` definition, `#[macro_export]` macro should be written at top level module @@ -17,7 +16,6 @@ LL | non_local_macro::non_local_macro_rules!(my_macro); | = help: remove the `#[macro_export]` or move this `macro_rules!` outside the of the current constant `_MACRO_EXPORT` = note: a `macro_rules!` definition is non-local if it is nested inside an item and has a `#[macro_export]` attribute - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue = note: the macro `non_local_macro::non_local_macro_rules` may come from an old version of the `non_local_macro` crate, try updating your dependency with `cargo update -p non_local_macro` = note: this warning originates in the macro `non_local_macro::non_local_macro_rules` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -29,7 +27,6 @@ LL | macro_rules! m { () => { } }; | = help: remove the `#[macro_export]` or move this `macro_rules!` outside the of the current function `main` = note: a `macro_rules!` definition is non-local if it is nested inside an item and has a `#[macro_export]` attribute - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `macro_rules!` definition, `#[macro_export]` macro should be written at top level module --> $DIR/macro_rules.rs:29:13 @@ -39,7 +36,6 @@ LL | macro_rules! m2 { () => { } }; | = help: remove the `#[macro_export]` or move this `macro_rules!` outside the of the current associated function `bar` and up 2 bodies = note: a `macro_rules!` definition is non-local if it is nested inside an item and has a `#[macro_export]` attribute - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: 4 warnings emitted diff --git a/tests/ui/lint/non-local-defs/weird-exprs.stderr b/tests/ui/lint/non-local-defs/weird-exprs.stderr index f6ce063929e..ec3517140ef 100644 --- a/tests/ui/lint/non-local-defs/weird-exprs.stderr +++ b/tests/ui/lint/non-local-defs/weird-exprs.stderr @@ -14,7 +14,6 @@ LL | | }]; | |_- move the `impl` block outside of this constant expression `` | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue = note: `#[warn(non_local_definitions)]` on by default warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -33,7 +32,6 @@ LL | | } | |_____- move the `impl` block outside of this constant expression `` | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/weird-exprs.rs:25:9 @@ -52,7 +50,6 @@ LL | | }]; | |_____- move the `impl` block outside of this constant expression `` and up 2 bodies | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/weird-exprs.rs:34:9 @@ -70,7 +67,6 @@ LL | | }]; | |_____- move the `impl` block outside of this constant expression `` and up 2 bodies | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/weird-exprs.rs:41:9 @@ -88,7 +84,6 @@ LL | | }]) {} | |_____- move the `impl` block outside of this constant expression `` and up 2 bodies | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/weird-exprs.rs:48:9 @@ -107,7 +102,6 @@ LL | | }] { todo!() } | |_____- move the `impl` block outside of this constant expression `` and up 2 bodies | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: 6 warnings emitted diff --git a/tests/ui/proc-macro/nested-macro-rules.stderr b/tests/ui/proc-macro/nested-macro-rules.stderr index 8fe041d61b8..439297d87ca 100644 --- a/tests/ui/proc-macro/nested-macro-rules.stderr +++ b/tests/ui/proc-macro/nested-macro-rules.stderr @@ -19,7 +19,6 @@ LL | nested_macro_rules::outer_macro!(SecondStruct, SecondAttrStruct); | = help: remove the `#[macro_export]` or move this `macro_rules!` outside the of the current function `main` = note: a `macro_rules!` definition is non-local if it is nested inside an item and has a `#[macro_export]` attribute - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue note: the lint level is defined here --> $DIR/nested-macro-rules.rs:8:9 | From 0d8a978e8a55b08778ec6ee861c2c5ed6703eb6c Mon Sep 17 00:00:00 2001 From: Jed Brown Date: Fri, 5 Jan 2024 21:04:41 -0700 Subject: [PATCH 207/357] intrinsics.fmuladdf{16,32,64,128}: expose llvm.fmuladd.* semantics Add intrinsics `fmuladd{f16,f32,f64,f128}`. This computes `(a * b) + c`, to be fused if the code generator determines that (i) the target instruction set has support for a fused operation, and (ii) that the fused operation is more efficient than the equivalent, separate pair of `mul` and `add` instructions. https://llvm.org/docs/LangRef.html#llvm-fmuladd-intrinsic MIRI support is included for f32 and f64. The codegen_cranelift uses the `fma` function from libc, which is a correct implementation, but without the desired performance semantic. I think this requires an update to cranelift to expose a suitable instruction in its IR. I have not tested with codegen_gcc, but it should behave the same way (using `fma` from libc). --- .../src/intrinsics/mod.rs | 5 +- .../rustc_codegen_gcc/src/intrinsic/mod.rs | 3 ++ compiler/rustc_codegen_llvm/src/context.rs | 5 ++ compiler/rustc_codegen_llvm/src/intrinsic.rs | 5 ++ .../rustc_hir_analysis/src/check/intrinsic.rs | 13 +++++ compiler/rustc_span/src/symbol.rs | 4 ++ library/core/src/intrinsics.rs | 53 +++++++++++++++++++ src/tools/miri/src/intrinsics/mod.rs | 31 +++++++++++ src/tools/miri/tests/pass/float.rs | 18 +++++++ .../intrinsics/fmuladd_nondeterministic.rs | 44 +++++++++++++++ tests/ui/intrinsics/intrinsic-fmuladd.rs | 42 +++++++++++++++ 11 files changed, 222 insertions(+), 1 deletion(-) create mode 100644 src/tools/miri/tests/pass/intrinsics/fmuladd_nondeterministic.rs create mode 100644 tests/ui/intrinsics/intrinsic-fmuladd.rs diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs index 19e5adc2538..35f0ccff3f9 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs @@ -328,6 +328,9 @@ fn codegen_float_intrinsic_call<'tcx>( sym::fabsf64 => ("fabs", 1, fx.tcx.types.f64, types::F64), sym::fmaf32 => ("fmaf", 3, fx.tcx.types.f32, types::F32), sym::fmaf64 => ("fma", 3, fx.tcx.types.f64, types::F64), + // FIXME: calling `fma` from libc without FMA target feature uses expensive sofware emulation + sym::fmuladdf32 => ("fmaf", 3, fx.tcx.types.f32, types::F32), // TODO: use cranelift intrinsic analogous to llvm.fmuladd.f32 + sym::fmuladdf64 => ("fma", 3, fx.tcx.types.f64, types::F64), // TODO: use cranelift intrinsic analogous to llvm.fmuladd.f64 sym::copysignf32 => ("copysignf", 2, fx.tcx.types.f32, types::F32), sym::copysignf64 => ("copysign", 2, fx.tcx.types.f64, types::F64), sym::floorf32 => ("floorf", 1, fx.tcx.types.f32, types::F32), @@ -381,7 +384,7 @@ fn codegen_float_intrinsic_call<'tcx>( let layout = fx.layout_of(ty); let res = match intrinsic { - sym::fmaf32 | sym::fmaf64 => { + sym::fmaf32 | sym::fmaf64 | sym::fmuladdf32 | sym::fmuladdf64 => { CValue::by_val(fx.bcx.ins().fma(args[0], args[1], args[2]), layout) } sym::copysignf32 | sym::copysignf64 => { diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs index 945eedf5556..972d6632140 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs @@ -66,6 +66,9 @@ fn get_simple_intrinsic<'gcc, 'tcx>( sym::log2f64 => "log2", sym::fmaf32 => "fmaf", sym::fmaf64 => "fma", + // FIXME: calling `fma` from libc without FMA target feature uses expensive sofware emulation + sym::fmuladdf32 => "fmaf", // TODO: use gcc intrinsic analogous to llvm.fmuladd.f32 + sym::fmuladdf64 => "fma", // TODO: use gcc intrinsic analogous to llvm.fmuladd.f64 sym::fabsf32 => "fabsf", sym::fabsf64 => "fabs", sym::minnumf32 => "fminf", diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 0a116971e07..c836dd5473f 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -884,6 +884,11 @@ impl<'ll> CodegenCx<'ll, '_> { ifn!("llvm.fma.f64", fn(t_f64, t_f64, t_f64) -> t_f64); ifn!("llvm.fma.f128", fn(t_f128, t_f128, t_f128) -> t_f128); + ifn!("llvm.fmuladd.f16", fn(t_f16, t_f16, t_f16) -> t_f16); + ifn!("llvm.fmuladd.f32", fn(t_f32, t_f32, t_f32) -> t_f32); + ifn!("llvm.fmuladd.f64", fn(t_f64, t_f64, t_f64) -> t_f64); + ifn!("llvm.fmuladd.f128", fn(t_f128, t_f128, t_f128) -> t_f128); + ifn!("llvm.fabs.f16", fn(t_f16) -> t_f16); ifn!("llvm.fabs.f32", fn(t_f32) -> t_f32); ifn!("llvm.fabs.f64", fn(t_f64) -> t_f64); diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 30c6f08e894..bfe623e7fc3 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -86,6 +86,11 @@ fn get_simple_intrinsic<'ll>( sym::fmaf64 => "llvm.fma.f64", sym::fmaf128 => "llvm.fma.f128", + sym::fmuladdf16 => "llvm.fmuladd.f16", + sym::fmuladdf32 => "llvm.fmuladd.f32", + sym::fmuladdf64 => "llvm.fmuladd.f64", + sym::fmuladdf128 => "llvm.fmuladd.f128", + sym::fabsf16 => "llvm.fabs.f16", sym::fabsf32 => "llvm.fabs.f32", sym::fabsf64 => "llvm.fabs.f64", diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 25e219ef3f2..06317a3b304 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -357,6 +357,19 @@ pub fn check_intrinsic_type( (0, 0, vec![tcx.types.f128, tcx.types.f128, tcx.types.f128], tcx.types.f128) } + sym::fmuladdf16 => { + (0, 0, vec![tcx.types.f16, tcx.types.f16, tcx.types.f16], tcx.types.f16) + } + sym::fmuladdf32 => { + (0, 0, vec![tcx.types.f32, tcx.types.f32, tcx.types.f32], tcx.types.f32) + } + sym::fmuladdf64 => { + (0, 0, vec![tcx.types.f64, tcx.types.f64, tcx.types.f64], tcx.types.f64) + } + sym::fmuladdf128 => { + (0, 0, vec![tcx.types.f128, tcx.types.f128, tcx.types.f128], tcx.types.f128) + } + sym::fabsf16 => (0, 0, vec![tcx.types.f16], tcx.types.f16), sym::fabsf32 => (0, 0, vec![tcx.types.f32], tcx.types.f32), sym::fabsf64 => (0, 0, vec![tcx.types.f64], tcx.types.f64), diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 8e0009695db..cc3bda99a11 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -914,6 +914,10 @@ symbols! { fmt_debug, fmul_algebraic, fmul_fast, + fmuladdf128, + fmuladdf16, + fmuladdf32, + fmuladdf64, fn_align, fn_delegation, fn_must_use, diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index d7a2f1909ca..061fba9a1f7 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -1795,6 +1795,59 @@ extern "rust-intrinsic" { #[rustc_nounwind] pub fn fmaf128(a: f128, b: f128, c: f128) -> f128; + /// Returns `a * b + c` for `f16` values, non-deterministically executing + /// either a fused multiply-add or two operations with rounding of the + /// intermediate result. + /// + /// The operation is fused if the code generator determines that target + /// instruction set has support for a fused operation, and that the fused + /// operation is more efficient than the equivalent, separate pair of mul + /// and add instructions. It is unspecified whether or not a fused operation + /// is selected, and that may depend on optimization level and context, for + /// example. + #[rustc_nounwind] + #[cfg(not(bootstrap))] + pub fn fmuladdf16(a: f16, b: f16, c: f16) -> f16; + /// Returns `a * b + c` for `f32` values, non-deterministically executing + /// either a fused multiply-add or two operations with rounding of the + /// intermediate result. + /// + /// The operation is fused if the code generator determines that target + /// instruction set has support for a fused operation, and that the fused + /// operation is more efficient than the equivalent, separate pair of mul + /// and add instructions. It is unspecified whether or not a fused operation + /// is selected, and that may depend on optimization level and context, for + /// example. + #[rustc_nounwind] + #[cfg(not(bootstrap))] + pub fn fmuladdf32(a: f32, b: f32, c: f32) -> f32; + /// Returns `a * b + c` for `f64` values, non-deterministically executing + /// either a fused multiply-add or two operations with rounding of the + /// intermediate result. + /// + /// The operation is fused if the code generator determines that target + /// instruction set has support for a fused operation, and that the fused + /// operation is more efficient than the equivalent, separate pair of mul + /// and add instructions. It is unspecified whether or not a fused operation + /// is selected, and that may depend on optimization level and context, for + /// example. + #[rustc_nounwind] + #[cfg(not(bootstrap))] + pub fn fmuladdf64(a: f64, b: f64, c: f64) -> f64; + /// Returns `a * b + c` for `f128` values, non-deterministically executing + /// either a fused multiply-add or two operations with rounding of the + /// intermediate result. + /// + /// The operation is fused if the code generator determines that target + /// instruction set has support for a fused operation, and that the fused + /// operation is more efficient than the equivalent, separate pair of mul + /// and add instructions. It is unspecified whether or not a fused operation + /// is selected, and that may depend on optimization level and context, for + /// example. + #[rustc_nounwind] + #[cfg(not(bootstrap))] + pub fn fmuladdf128(a: f128, b: f128, c: f128) -> f128; + /// Returns the absolute value of an `f16`. /// /// The stabilized version of this intrinsic is diff --git a/src/tools/miri/src/intrinsics/mod.rs b/src/tools/miri/src/intrinsics/mod.rs index 665dd7c441a..9f772cfa982 100644 --- a/src/tools/miri/src/intrinsics/mod.rs +++ b/src/tools/miri/src/intrinsics/mod.rs @@ -295,6 +295,37 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(res, dest)?; } + "fmuladdf32" => { + let [a, b, c] = check_arg_count(args)?; + let a = this.read_scalar(a)?.to_f32()?; + let b = this.read_scalar(b)?.to_f32()?; + let c = this.read_scalar(c)?.to_f32()?; + let fuse: bool = this.machine.rng.get_mut().gen(); + let res = if fuse { + // FIXME: Using host floats, to work around https://github.com/rust-lang/rustc_apfloat/issues/11 + a.to_host().mul_add(b.to_host(), c.to_host()).to_soft() + } else { + ((a * b).value + c).value + }; + let res = this.adjust_nan(res, &[a, b, c]); + this.write_scalar(res, dest)?; + } + "fmuladdf64" => { + let [a, b, c] = check_arg_count(args)?; + let a = this.read_scalar(a)?.to_f64()?; + let b = this.read_scalar(b)?.to_f64()?; + let c = this.read_scalar(c)?.to_f64()?; + let fuse: bool = this.machine.rng.get_mut().gen(); + let res = if fuse { + // FIXME: Using host floats, to work around https://github.com/rust-lang/rustc_apfloat/issues/11 + a.to_host().mul_add(b.to_host(), c.to_host()).to_soft() + } else { + ((a * b).value + c).value + }; + let res = this.adjust_nan(res, &[a, b, c]); + this.write_scalar(res, dest)?; + } + "powf32" => { let [f1, f2] = check_arg_count(args)?; let f1 = this.read_scalar(f1)?.to_f32()?; diff --git a/src/tools/miri/tests/pass/float.rs b/src/tools/miri/tests/pass/float.rs index 6ab18a5345e..853d3e80517 100644 --- a/src/tools/miri/tests/pass/float.rs +++ b/src/tools/miri/tests/pass/float.rs @@ -30,6 +30,7 @@ fn main() { libm(); test_fast(); test_algebraic(); + test_fmuladd(); } trait Float: Copy + PartialEq + Debug { @@ -1041,3 +1042,20 @@ fn test_algebraic() { test_operations_f32(11., 2.); test_operations_f32(10., 15.); } + +fn test_fmuladd() { + use std::intrinsics::{fmuladdf32, fmuladdf64}; + + #[inline(never)] + pub fn test_operations_f32(a: f32, b: f32, c: f32) { + assert_approx_eq!(unsafe { fmuladdf32(a, b, c) }, a * b + c); + } + + #[inline(never)] + pub fn test_operations_f64(a: f64, b: f64, c: f64) { + assert_approx_eq!(unsafe { fmuladdf64(a, b, c) }, a * b + c); + } + + test_operations_f32(0.1, 0.2, 0.3); + test_operations_f64(1.1, 1.2, 1.3); +} diff --git a/src/tools/miri/tests/pass/intrinsics/fmuladd_nondeterministic.rs b/src/tools/miri/tests/pass/intrinsics/fmuladd_nondeterministic.rs new file mode 100644 index 00000000000..b46cf1ddf65 --- /dev/null +++ b/src/tools/miri/tests/pass/intrinsics/fmuladd_nondeterministic.rs @@ -0,0 +1,44 @@ +#![feature(core_intrinsics)] +use std::intrinsics::{fmuladdf32, fmuladdf64}; + +fn main() { + let mut saw_zero = false; + let mut saw_nonzero = false; + for _ in 0..50 { + let a = std::hint::black_box(0.1_f64); + let b = std::hint::black_box(0.2); + let c = std::hint::black_box(-a * b); + // It is unspecified whether the following operation is fused or not. The + // following evaluates to 0.0 if unfused, and nonzero (-1.66e-18) if fused. + let x = unsafe { fmuladdf64(a, b, c) }; + if x == 0.0 { + saw_zero = true; + } else { + saw_nonzero = true; + } + } + assert!( + saw_zero && saw_nonzero, + "`fmuladdf64` failed to be evaluated as both fused and unfused" + ); + + let mut saw_zero = false; + let mut saw_nonzero = false; + for _ in 0..50 { + let a = std::hint::black_box(0.1_f32); + let b = std::hint::black_box(0.2); + let c = std::hint::black_box(-a * b); + // It is unspecified whether the following operation is fused or not. The + // following evaluates to 0.0 if unfused, and nonzero (-8.1956386e-10) if fused. + let x = unsafe { fmuladdf32(a, b, c) }; + if x == 0.0 { + saw_zero = true; + } else { + saw_nonzero = true; + } + } + assert!( + saw_zero && saw_nonzero, + "`fmuladdf32` failed to be evaluated as both fused and unfused" + ); +} diff --git a/tests/ui/intrinsics/intrinsic-fmuladd.rs b/tests/ui/intrinsics/intrinsic-fmuladd.rs new file mode 100644 index 00000000000..d03297884f7 --- /dev/null +++ b/tests/ui/intrinsics/intrinsic-fmuladd.rs @@ -0,0 +1,42 @@ +//@ run-pass +#![feature(core_intrinsics)] + +use std::intrinsics::*; + +macro_rules! assert_approx_eq { + ($a:expr, $b:expr) => {{ + let (a, b) = (&$a, &$b); + assert!((*a - *b).abs() < 1.0e-6, "{} is not approximately equal to {}", *a, *b); + }}; +} + +fn main() { + unsafe { + let nan: f32 = f32::NAN; + let inf: f32 = f32::INFINITY; + let neg_inf: f32 = f32::NEG_INFINITY; + assert_approx_eq!(fmuladdf32(1.23, 4.5, 0.67), 6.205); + assert_approx_eq!(fmuladdf32(-1.23, -4.5, -0.67), 4.865); + assert_approx_eq!(fmuladdf32(0.0, 8.9, 1.2), 1.2); + assert_approx_eq!(fmuladdf32(3.4, -0.0, 5.6), 5.6); + assert!(fmuladdf32(nan, 7.8, 9.0).is_nan()); + assert_eq!(fmuladdf32(inf, 7.8, 9.0), inf); + assert_eq!(fmuladdf32(neg_inf, 7.8, 9.0), neg_inf); + assert_eq!(fmuladdf32(8.9, inf, 3.2), inf); + assert_eq!(fmuladdf32(-3.2, 2.4, neg_inf), neg_inf); + } + unsafe { + let nan: f64 = f64::NAN; + let inf: f64 = f64::INFINITY; + let neg_inf: f64 = f64::NEG_INFINITY; + assert_approx_eq!(fmuladdf64(1.23, 4.5, 0.67), 6.205); + assert_approx_eq!(fmuladdf64(-1.23, -4.5, -0.67), 4.865); + assert_approx_eq!(fmuladdf64(0.0, 8.9, 1.2), 1.2); + assert_approx_eq!(fmuladdf64(3.4, -0.0, 5.6), 5.6); + assert!(fmuladdf64(nan, 7.8, 9.0).is_nan()); + assert_eq!(fmuladdf64(inf, 7.8, 9.0), inf); + assert_eq!(fmuladdf64(neg_inf, 7.8, 9.0), neg_inf); + assert_eq!(fmuladdf64(8.9, inf, 3.2), inf); + assert_eq!(fmuladdf64(-3.2, 2.4, neg_inf), neg_inf); + } +} From 559de745626901cf1fba5aaa5a2b96fbc92e09ff Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Tue, 8 Oct 2024 19:07:43 -0700 Subject: [PATCH 208/357] compiler: Move impl of ToJson for abi::Endian --- compiler/rustc_target/src/abi/mod.rs | 8 -------- compiler/rustc_target/src/json.rs | 6 ++++++ 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_target/src/abi/mod.rs b/compiler/rustc_target/src/abi/mod.rs index b744d5ad4ed..9f26c98df86 100644 --- a/compiler/rustc_target/src/abi/mod.rs +++ b/compiler/rustc_target/src/abi/mod.rs @@ -6,19 +6,11 @@ use Primitive::*; use rustc_data_structures::intern::Interned; use rustc_macros::HashStable_Generic; -use crate::json::{Json, ToJson}; - pub mod call; // Explicitly import `Float` to avoid ambiguity with `Primitive::Float`. pub use rustc_abi::{Float, *}; -impl ToJson for Endian { - fn to_json(&self) -> Json { - self.as_str().to_json() - } -} - rustc_index::newtype_index! { /// The *source-order* index of a field in a variant. /// diff --git a/compiler/rustc_target/src/json.rs b/compiler/rustc_target/src/json.rs index 2c367defe7b..b09d8d724ef 100644 --- a/compiler/rustc_target/src/json.rs +++ b/compiler/rustc_target/src/json.rs @@ -134,3 +134,9 @@ impl ToJson for TargetMetadata { }) } } + +impl ToJson for rustc_abi::Endian { + fn to_json(&self) -> Json { + self.as_str().to_json() + } +} From 255bdd2f24de119d85073e0c48acdebca25af551 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Wed, 9 Oct 2024 11:07:22 -0700 Subject: [PATCH 209/357] compiler: Empty out rustc_target::abi --- .../{rustc_target/src/abi/mod.rs => rustc_abi/src/layout/ty.rs} | 0 compiler/rustc_target/src/{abi/call => callconv}/aarch64.rs | 0 compiler/rustc_target/src/{abi/call => callconv}/amdgpu.rs | 0 compiler/rustc_target/src/{abi/call => callconv}/arm.rs | 0 compiler/rustc_target/src/{abi/call => callconv}/avr.rs | 0 compiler/rustc_target/src/{abi/call => callconv}/bpf.rs | 0 compiler/rustc_target/src/{abi/call => callconv}/csky.rs | 0 compiler/rustc_target/src/{abi/call => callconv}/hexagon.rs | 0 compiler/rustc_target/src/{abi/call => callconv}/loongarch.rs | 0 compiler/rustc_target/src/{abi/call => callconv}/m68k.rs | 0 compiler/rustc_target/src/{abi/call => callconv}/mips.rs | 0 compiler/rustc_target/src/{abi/call => callconv}/mips64.rs | 0 compiler/rustc_target/src/{abi/call => callconv}/mod.rs | 0 compiler/rustc_target/src/{abi/call => callconv}/msp430.rs | 0 compiler/rustc_target/src/{abi/call => callconv}/nvptx64.rs | 0 compiler/rustc_target/src/{abi/call => callconv}/powerpc.rs | 0 compiler/rustc_target/src/{abi/call => callconv}/powerpc64.rs | 0 compiler/rustc_target/src/{abi/call => callconv}/riscv.rs | 0 compiler/rustc_target/src/{abi/call => callconv}/s390x.rs | 0 compiler/rustc_target/src/{abi/call => callconv}/sparc.rs | 0 compiler/rustc_target/src/{abi/call => callconv}/sparc64.rs | 0 compiler/rustc_target/src/{abi/call => callconv}/wasm.rs | 0 compiler/rustc_target/src/{abi/call => callconv}/x86.rs | 0 compiler/rustc_target/src/{abi/call => callconv}/x86_64.rs | 0 compiler/rustc_target/src/{abi/call => callconv}/x86_win64.rs | 0 compiler/rustc_target/src/{abi/call => callconv}/xtensa.rs | 0 26 files changed, 0 insertions(+), 0 deletions(-) rename compiler/{rustc_target/src/abi/mod.rs => rustc_abi/src/layout/ty.rs} (100%) rename compiler/rustc_target/src/{abi/call => callconv}/aarch64.rs (100%) rename compiler/rustc_target/src/{abi/call => callconv}/amdgpu.rs (100%) rename compiler/rustc_target/src/{abi/call => callconv}/arm.rs (100%) rename compiler/rustc_target/src/{abi/call => callconv}/avr.rs (100%) rename compiler/rustc_target/src/{abi/call => callconv}/bpf.rs (100%) rename compiler/rustc_target/src/{abi/call => callconv}/csky.rs (100%) rename compiler/rustc_target/src/{abi/call => callconv}/hexagon.rs (100%) rename compiler/rustc_target/src/{abi/call => callconv}/loongarch.rs (100%) rename compiler/rustc_target/src/{abi/call => callconv}/m68k.rs (100%) rename compiler/rustc_target/src/{abi/call => callconv}/mips.rs (100%) rename compiler/rustc_target/src/{abi/call => callconv}/mips64.rs (100%) rename compiler/rustc_target/src/{abi/call => callconv}/mod.rs (100%) rename compiler/rustc_target/src/{abi/call => callconv}/msp430.rs (100%) rename compiler/rustc_target/src/{abi/call => callconv}/nvptx64.rs (100%) rename compiler/rustc_target/src/{abi/call => callconv}/powerpc.rs (100%) rename compiler/rustc_target/src/{abi/call => callconv}/powerpc64.rs (100%) rename compiler/rustc_target/src/{abi/call => callconv}/riscv.rs (100%) rename compiler/rustc_target/src/{abi/call => callconv}/s390x.rs (100%) rename compiler/rustc_target/src/{abi/call => callconv}/sparc.rs (100%) rename compiler/rustc_target/src/{abi/call => callconv}/sparc64.rs (100%) rename compiler/rustc_target/src/{abi/call => callconv}/wasm.rs (100%) rename compiler/rustc_target/src/{abi/call => callconv}/x86.rs (100%) rename compiler/rustc_target/src/{abi/call => callconv}/x86_64.rs (100%) rename compiler/rustc_target/src/{abi/call => callconv}/x86_win64.rs (100%) rename compiler/rustc_target/src/{abi/call => callconv}/xtensa.rs (100%) diff --git a/compiler/rustc_target/src/abi/mod.rs b/compiler/rustc_abi/src/layout/ty.rs similarity index 100% rename from compiler/rustc_target/src/abi/mod.rs rename to compiler/rustc_abi/src/layout/ty.rs diff --git a/compiler/rustc_target/src/abi/call/aarch64.rs b/compiler/rustc_target/src/callconv/aarch64.rs similarity index 100% rename from compiler/rustc_target/src/abi/call/aarch64.rs rename to compiler/rustc_target/src/callconv/aarch64.rs diff --git a/compiler/rustc_target/src/abi/call/amdgpu.rs b/compiler/rustc_target/src/callconv/amdgpu.rs similarity index 100% rename from compiler/rustc_target/src/abi/call/amdgpu.rs rename to compiler/rustc_target/src/callconv/amdgpu.rs diff --git a/compiler/rustc_target/src/abi/call/arm.rs b/compiler/rustc_target/src/callconv/arm.rs similarity index 100% rename from compiler/rustc_target/src/abi/call/arm.rs rename to compiler/rustc_target/src/callconv/arm.rs diff --git a/compiler/rustc_target/src/abi/call/avr.rs b/compiler/rustc_target/src/callconv/avr.rs similarity index 100% rename from compiler/rustc_target/src/abi/call/avr.rs rename to compiler/rustc_target/src/callconv/avr.rs diff --git a/compiler/rustc_target/src/abi/call/bpf.rs b/compiler/rustc_target/src/callconv/bpf.rs similarity index 100% rename from compiler/rustc_target/src/abi/call/bpf.rs rename to compiler/rustc_target/src/callconv/bpf.rs diff --git a/compiler/rustc_target/src/abi/call/csky.rs b/compiler/rustc_target/src/callconv/csky.rs similarity index 100% rename from compiler/rustc_target/src/abi/call/csky.rs rename to compiler/rustc_target/src/callconv/csky.rs diff --git a/compiler/rustc_target/src/abi/call/hexagon.rs b/compiler/rustc_target/src/callconv/hexagon.rs similarity index 100% rename from compiler/rustc_target/src/abi/call/hexagon.rs rename to compiler/rustc_target/src/callconv/hexagon.rs diff --git a/compiler/rustc_target/src/abi/call/loongarch.rs b/compiler/rustc_target/src/callconv/loongarch.rs similarity index 100% rename from compiler/rustc_target/src/abi/call/loongarch.rs rename to compiler/rustc_target/src/callconv/loongarch.rs diff --git a/compiler/rustc_target/src/abi/call/m68k.rs b/compiler/rustc_target/src/callconv/m68k.rs similarity index 100% rename from compiler/rustc_target/src/abi/call/m68k.rs rename to compiler/rustc_target/src/callconv/m68k.rs diff --git a/compiler/rustc_target/src/abi/call/mips.rs b/compiler/rustc_target/src/callconv/mips.rs similarity index 100% rename from compiler/rustc_target/src/abi/call/mips.rs rename to compiler/rustc_target/src/callconv/mips.rs diff --git a/compiler/rustc_target/src/abi/call/mips64.rs b/compiler/rustc_target/src/callconv/mips64.rs similarity index 100% rename from compiler/rustc_target/src/abi/call/mips64.rs rename to compiler/rustc_target/src/callconv/mips64.rs diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/callconv/mod.rs similarity index 100% rename from compiler/rustc_target/src/abi/call/mod.rs rename to compiler/rustc_target/src/callconv/mod.rs diff --git a/compiler/rustc_target/src/abi/call/msp430.rs b/compiler/rustc_target/src/callconv/msp430.rs similarity index 100% rename from compiler/rustc_target/src/abi/call/msp430.rs rename to compiler/rustc_target/src/callconv/msp430.rs diff --git a/compiler/rustc_target/src/abi/call/nvptx64.rs b/compiler/rustc_target/src/callconv/nvptx64.rs similarity index 100% rename from compiler/rustc_target/src/abi/call/nvptx64.rs rename to compiler/rustc_target/src/callconv/nvptx64.rs diff --git a/compiler/rustc_target/src/abi/call/powerpc.rs b/compiler/rustc_target/src/callconv/powerpc.rs similarity index 100% rename from compiler/rustc_target/src/abi/call/powerpc.rs rename to compiler/rustc_target/src/callconv/powerpc.rs diff --git a/compiler/rustc_target/src/abi/call/powerpc64.rs b/compiler/rustc_target/src/callconv/powerpc64.rs similarity index 100% rename from compiler/rustc_target/src/abi/call/powerpc64.rs rename to compiler/rustc_target/src/callconv/powerpc64.rs diff --git a/compiler/rustc_target/src/abi/call/riscv.rs b/compiler/rustc_target/src/callconv/riscv.rs similarity index 100% rename from compiler/rustc_target/src/abi/call/riscv.rs rename to compiler/rustc_target/src/callconv/riscv.rs diff --git a/compiler/rustc_target/src/abi/call/s390x.rs b/compiler/rustc_target/src/callconv/s390x.rs similarity index 100% rename from compiler/rustc_target/src/abi/call/s390x.rs rename to compiler/rustc_target/src/callconv/s390x.rs diff --git a/compiler/rustc_target/src/abi/call/sparc.rs b/compiler/rustc_target/src/callconv/sparc.rs similarity index 100% rename from compiler/rustc_target/src/abi/call/sparc.rs rename to compiler/rustc_target/src/callconv/sparc.rs diff --git a/compiler/rustc_target/src/abi/call/sparc64.rs b/compiler/rustc_target/src/callconv/sparc64.rs similarity index 100% rename from compiler/rustc_target/src/abi/call/sparc64.rs rename to compiler/rustc_target/src/callconv/sparc64.rs diff --git a/compiler/rustc_target/src/abi/call/wasm.rs b/compiler/rustc_target/src/callconv/wasm.rs similarity index 100% rename from compiler/rustc_target/src/abi/call/wasm.rs rename to compiler/rustc_target/src/callconv/wasm.rs diff --git a/compiler/rustc_target/src/abi/call/x86.rs b/compiler/rustc_target/src/callconv/x86.rs similarity index 100% rename from compiler/rustc_target/src/abi/call/x86.rs rename to compiler/rustc_target/src/callconv/x86.rs diff --git a/compiler/rustc_target/src/abi/call/x86_64.rs b/compiler/rustc_target/src/callconv/x86_64.rs similarity index 100% rename from compiler/rustc_target/src/abi/call/x86_64.rs rename to compiler/rustc_target/src/callconv/x86_64.rs diff --git a/compiler/rustc_target/src/abi/call/x86_win64.rs b/compiler/rustc_target/src/callconv/x86_win64.rs similarity index 100% rename from compiler/rustc_target/src/abi/call/x86_win64.rs rename to compiler/rustc_target/src/callconv/x86_win64.rs diff --git a/compiler/rustc_target/src/abi/call/xtensa.rs b/compiler/rustc_target/src/callconv/xtensa.rs similarity index 100% rename from compiler/rustc_target/src/abi/call/xtensa.rs rename to compiler/rustc_target/src/callconv/xtensa.rs From 10721909f29024ba56a9ce667da8652a99a04784 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Wed, 9 Oct 2024 12:20:28 -0700 Subject: [PATCH 210/357] compiler: Wire `{TyAnd,}Layout` into `rustc_abi` This finally unites TyAndLayout, Layout, and LayoutS into the same crate, as one might imagine they would be placed. No functional changes. --- compiler/rustc_abi/src/callconv.rs | 254 ++++++++++++++++++++++ compiler/rustc_abi/src/layout.rs | 4 + compiler/rustc_abi/src/layout/ty.rs | 4 +- compiler/rustc_abi/src/lib.rs | 8 +- compiler/rustc_middle/src/ty/context.rs | 2 +- compiler/rustc_target/src/callconv/mod.rs | 249 +-------------------- compiler/rustc_target/src/lib.rs | 11 +- 7 files changed, 279 insertions(+), 253 deletions(-) create mode 100644 compiler/rustc_abi/src/callconv.rs diff --git a/compiler/rustc_abi/src/callconv.rs b/compiler/rustc_abi/src/callconv.rs new file mode 100644 index 00000000000..2ecac8a9df1 --- /dev/null +++ b/compiler/rustc_abi/src/callconv.rs @@ -0,0 +1,254 @@ +mod abi { + pub(crate) use crate::Primitive::*; + pub(crate) use crate::Variants; +} + +use rustc_macros::HashStable_Generic; + +use crate::{Abi, Align, FieldsShape, HasDataLayout, Size, TyAbiInterface, TyAndLayout}; + +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)] +pub enum RegKind { + Integer, + Float, + Vector, +} + +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)] +pub struct Reg { + pub kind: RegKind, + pub size: Size, +} + +macro_rules! reg_ctor { + ($name:ident, $kind:ident, $bits:expr) => { + pub fn $name() -> Reg { + Reg { kind: RegKind::$kind, size: Size::from_bits($bits) } + } + }; +} + +impl Reg { + reg_ctor!(i8, Integer, 8); + reg_ctor!(i16, Integer, 16); + reg_ctor!(i32, Integer, 32); + reg_ctor!(i64, Integer, 64); + reg_ctor!(i128, Integer, 128); + + reg_ctor!(f32, Float, 32); + reg_ctor!(f64, Float, 64); +} + +impl Reg { + pub fn align(&self, cx: &C) -> Align { + let dl = cx.data_layout(); + match self.kind { + RegKind::Integer => match self.size.bits() { + 1 => dl.i1_align.abi, + 2..=8 => dl.i8_align.abi, + 9..=16 => dl.i16_align.abi, + 17..=32 => dl.i32_align.abi, + 33..=64 => dl.i64_align.abi, + 65..=128 => dl.i128_align.abi, + _ => panic!("unsupported integer: {self:?}"), + }, + RegKind::Float => match self.size.bits() { + 16 => dl.f16_align.abi, + 32 => dl.f32_align.abi, + 64 => dl.f64_align.abi, + 128 => dl.f128_align.abi, + _ => panic!("unsupported float: {self:?}"), + }, + RegKind::Vector => dl.vector_align(self.size).abi, + } + } +} + +/// Return value from the `homogeneous_aggregate` test function. +#[derive(Copy, Clone, Debug)] +pub enum HomogeneousAggregate { + /// Yes, all the "leaf fields" of this struct are passed in the + /// same way (specified in the `Reg` value). + Homogeneous(Reg), + + /// There are no leaf fields at all. + NoData, +} + +/// Error from the `homogeneous_aggregate` test function, indicating +/// there are distinct leaf fields passed in different ways, +/// or this is uninhabited. +#[derive(Copy, Clone, Debug)] +pub struct Heterogeneous; + +impl HomogeneousAggregate { + /// If this is a homogeneous aggregate, returns the homogeneous + /// unit, else `None`. + pub fn unit(self) -> Option { + match self { + HomogeneousAggregate::Homogeneous(reg) => Some(reg), + HomogeneousAggregate::NoData => None, + } + } + + /// Try to combine two `HomogeneousAggregate`s, e.g. from two fields in + /// the same `struct`. Only succeeds if only one of them has any data, + /// or both units are identical. + fn merge(self, other: HomogeneousAggregate) -> Result { + match (self, other) { + (x, HomogeneousAggregate::NoData) | (HomogeneousAggregate::NoData, x) => Ok(x), + + (HomogeneousAggregate::Homogeneous(a), HomogeneousAggregate::Homogeneous(b)) => { + if a != b { + return Err(Heterogeneous); + } + Ok(self) + } + } + } +} + +impl<'a, Ty> TyAndLayout<'a, Ty> { + /// Returns `true` if this is an aggregate type (including a ScalarPair!) + pub fn is_aggregate(&self) -> bool { + match self.abi { + Abi::Uninhabited | Abi::Scalar(_) | Abi::Vector { .. } => false, + Abi::ScalarPair(..) | Abi::Aggregate { .. } => true, + } + } + + /// Returns `Homogeneous` if this layout is an aggregate containing fields of + /// only a single type (e.g., `(u32, u32)`). Such aggregates are often + /// special-cased in ABIs. + /// + /// Note: We generally ignore 1-ZST fields when computing this value (see #56877). + /// + /// This is public so that it can be used in unit tests, but + /// should generally only be relevant to the ABI details of + /// specific targets. + pub fn homogeneous_aggregate(&self, cx: &C) -> Result + where + Ty: TyAbiInterface<'a, C> + Copy, + { + match self.abi { + Abi::Uninhabited => Err(Heterogeneous), + + // The primitive for this algorithm. + Abi::Scalar(scalar) => { + let kind = match scalar.primitive() { + abi::Int(..) | abi::Pointer(_) => RegKind::Integer, + abi::Float(_) => RegKind::Float, + }; + Ok(HomogeneousAggregate::Homogeneous(Reg { kind, size: self.size })) + } + + Abi::Vector { .. } => { + assert!(!self.is_zst()); + Ok(HomogeneousAggregate::Homogeneous(Reg { + kind: RegKind::Vector, + size: self.size, + })) + } + + Abi::ScalarPair(..) | Abi::Aggregate { sized: true } => { + // Helper for computing `homogeneous_aggregate`, allowing a custom + // starting offset (used below for handling variants). + let from_fields_at = + |layout: Self, + start: Size| + -> Result<(HomogeneousAggregate, Size), Heterogeneous> { + let is_union = match layout.fields { + FieldsShape::Primitive => { + unreachable!("aggregates can't have `FieldsShape::Primitive`") + } + FieldsShape::Array { count, .. } => { + assert_eq!(start, Size::ZERO); + + let result = if count > 0 { + layout.field(cx, 0).homogeneous_aggregate(cx)? + } else { + HomogeneousAggregate::NoData + }; + return Ok((result, layout.size)); + } + FieldsShape::Union(_) => true, + FieldsShape::Arbitrary { .. } => false, + }; + + let mut result = HomogeneousAggregate::NoData; + let mut total = start; + + for i in 0..layout.fields.count() { + let field = layout.field(cx, i); + if field.is_1zst() { + // No data here and no impact on layout, can be ignored. + // (We might be able to also ignore all aligned ZST but that's less clear.) + continue; + } + + if !is_union && total != layout.fields.offset(i) { + // This field isn't just after the previous one we considered, abort. + return Err(Heterogeneous); + } + + result = result.merge(field.homogeneous_aggregate(cx)?)?; + + // Keep track of the offset (without padding). + let size = field.size; + if is_union { + total = total.max(size); + } else { + total += size; + } + } + + Ok((result, total)) + }; + + let (mut result, mut total) = from_fields_at(*self, Size::ZERO)?; + + match &self.variants { + abi::Variants::Single { .. } => {} + abi::Variants::Multiple { variants, .. } => { + // Treat enum variants like union members. + // HACK(eddyb) pretend the `enum` field (discriminant) + // is at the start of every variant (otherwise the gap + // at the start of all variants would disqualify them). + // + // NB: for all tagged `enum`s (which include all non-C-like + // `enum`s with defined FFI representation), this will + // match the homogeneous computation on the equivalent + // `struct { tag; union { variant1; ... } }` and/or + // `union { struct { tag; variant1; } ... }` + // (the offsets of variant fields should be identical + // between the two for either to be a homogeneous aggregate). + let variant_start = total; + for variant_idx in variants.indices() { + let (variant_result, variant_total) = + from_fields_at(self.for_variant(cx, variant_idx), variant_start)?; + + result = result.merge(variant_result)?; + total = total.max(variant_total); + } + } + } + + // There needs to be no padding. + if total != self.size { + Err(Heterogeneous) + } else { + match result { + HomogeneousAggregate::Homogeneous(_) => { + assert_ne!(total, Size::ZERO); + } + HomogeneousAggregate::NoData => { + assert_eq!(total, Size::ZERO); + } + } + Ok(result) + } + } + Abi::Aggregate { sized: false } => Err(Heterogeneous), + } + } +} diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs index 620a051eeb7..6e1299944a0 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -11,6 +11,10 @@ use crate::{ Variants, WrappingRange, }; +mod ty; + +pub use ty::{FIRST_VARIANT, FieldIdx, Layout, TyAbiInterface, TyAndLayout, VariantIdx}; + // A variant is absent if it's uninhabited and only has ZST fields. // Present uninhabited variants only require space for their fields, // but *not* an encoding of the discriminant (e.g., a tag value). diff --git a/compiler/rustc_abi/src/layout/ty.rs b/compiler/rustc_abi/src/layout/ty.rs index 9f26c98df86..c6812c4d4c0 100644 --- a/compiler/rustc_abi/src/layout/ty.rs +++ b/compiler/rustc_abi/src/layout/ty.rs @@ -6,10 +6,8 @@ use Primitive::*; use rustc_data_structures::intern::Interned; use rustc_macros::HashStable_Generic; -pub mod call; - // Explicitly import `Float` to avoid ambiguity with `Primitive::Float`. -pub use rustc_abi::{Float, *}; +use crate::{Float, *}; rustc_index::newtype_index! { /// The *source-order* index of a field in a variant. diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index fa7c98a7fa0..84d756b6d51 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -1,6 +1,7 @@ // tidy-alphabetical-start #![cfg_attr(feature = "nightly", allow(internal_features))] #![cfg_attr(feature = "nightly", doc(rust_logo))] +#![cfg_attr(feature = "nightly", feature(rustc_attrs))] #![cfg_attr(feature = "nightly", feature(rustdoc_internals))] #![cfg_attr(feature = "nightly", feature(step_trait))] #![warn(unreachable_pub)] @@ -22,11 +23,16 @@ use rustc_macros::HashStable_Generic; #[cfg(feature = "nightly")] use rustc_macros::{Decodable_Generic, Encodable_Generic}; +mod callconv; mod layout; #[cfg(test)] mod tests; -pub use layout::{LayoutCalculator, LayoutCalculatorError}; +pub use callconv::{Heterogeneous, HomogeneousAggregate, Reg, RegKind}; +pub use layout::{ + FIRST_VARIANT, FieldIdx, Layout, LayoutCalculator, LayoutCalculatorError, TyAbiInterface, + TyAndLayout, VariantIdx, +}; /// Requirements for a `StableHashingContext` to be used in this crate. /// This is a hack to allow using the `HashStable_Generic` derive macro diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 50e7be82a79..1bdcae4dfb4 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -12,6 +12,7 @@ use std::marker::PhantomData; use std::ops::{Bound, Deref}; use std::{fmt, iter, mem}; +use rustc_abi::{FieldIdx, Layout, LayoutS, TargetDataLayout, VariantIdx}; use rustc_ast::{self as ast, attr}; use rustc_data_structures::defer; use rustc_data_structures::fingerprint::Fingerprint; @@ -48,7 +49,6 @@ use rustc_session::{Limit, MetadataKind, Session}; use rustc_span::def_id::{CRATE_DEF_ID, DefPathHash, StableCrateId}; use rustc_span::symbol::{Ident, Symbol, kw, sym}; use rustc_span::{DUMMY_SP, Span}; -use rustc_target::abi::{FieldIdx, Layout, LayoutS, TargetDataLayout, VariantIdx}; use rustc_target::spec::abi; use rustc_type_ir::TyKind::*; use rustc_type_ir::fold::TypeFoldable; diff --git a/compiler/rustc_target/src/callconv/mod.rs b/compiler/rustc_target/src/callconv/mod.rs index 352861c5ccb..832246495bc 100644 --- a/compiler/rustc_target/src/callconv/mod.rs +++ b/compiler/rustc_target/src/callconv/mod.rs @@ -1,10 +1,11 @@ use std::fmt; use std::str::FromStr; +pub use rustc_abi::{Reg, RegKind}; use rustc_macros::HashStable_Generic; use rustc_span::Symbol; -use crate::abi::{self, Abi, Align, FieldsShape, HasDataLayout, Size, TyAbiInterface, TyAndLayout}; +use crate::abi::{self, Abi, Align, HasDataLayout, Size, TyAbiInterface, TyAndLayout}; use crate::spec::{self, HasTargetSpec, HasWasmCAbiOpt, WasmCAbi}; mod aarch64; @@ -192,63 +193,6 @@ impl ArgAttributes { } } -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)] -pub enum RegKind { - Integer, - Float, - Vector, -} - -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)] -pub struct Reg { - pub kind: RegKind, - pub size: Size, -} - -macro_rules! reg_ctor { - ($name:ident, $kind:ident, $bits:expr) => { - pub fn $name() -> Reg { - Reg { kind: RegKind::$kind, size: Size::from_bits($bits) } - } - }; -} - -impl Reg { - reg_ctor!(i8, Integer, 8); - reg_ctor!(i16, Integer, 16); - reg_ctor!(i32, Integer, 32); - reg_ctor!(i64, Integer, 64); - reg_ctor!(i128, Integer, 128); - - reg_ctor!(f32, Float, 32); - reg_ctor!(f64, Float, 64); -} - -impl Reg { - pub fn align(&self, cx: &C) -> Align { - let dl = cx.data_layout(); - match self.kind { - RegKind::Integer => match self.size.bits() { - 1 => dl.i1_align.abi, - 2..=8 => dl.i8_align.abi, - 9..=16 => dl.i16_align.abi, - 17..=32 => dl.i32_align.abi, - 33..=64 => dl.i64_align.abi, - 65..=128 => dl.i128_align.abi, - _ => panic!("unsupported integer: {self:?}"), - }, - RegKind::Float => match self.size.bits() { - 16 => dl.f16_align.abi, - 32 => dl.f32_align.abi, - 64 => dl.f64_align.abi, - 128 => dl.f128_align.abi, - _ => panic!("unsupported float: {self:?}"), - }, - RegKind::Vector => dl.vector_align(self.size).abi, - } - } -} - /// An argument passed entirely registers with the /// same kind (e.g., HFA / HVA on PPC64 and AArch64). #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable_Generic)] @@ -380,195 +324,6 @@ impl CastTarget { } } -/// Return value from the `homogeneous_aggregate` test function. -#[derive(Copy, Clone, Debug)] -pub enum HomogeneousAggregate { - /// Yes, all the "leaf fields" of this struct are passed in the - /// same way (specified in the `Reg` value). - Homogeneous(Reg), - - /// There are no leaf fields at all. - NoData, -} - -/// Error from the `homogeneous_aggregate` test function, indicating -/// there are distinct leaf fields passed in different ways, -/// or this is uninhabited. -#[derive(Copy, Clone, Debug)] -pub struct Heterogeneous; - -impl HomogeneousAggregate { - /// If this is a homogeneous aggregate, returns the homogeneous - /// unit, else `None`. - pub fn unit(self) -> Option { - match self { - HomogeneousAggregate::Homogeneous(reg) => Some(reg), - HomogeneousAggregate::NoData => None, - } - } - - /// Try to combine two `HomogeneousAggregate`s, e.g. from two fields in - /// the same `struct`. Only succeeds if only one of them has any data, - /// or both units are identical. - fn merge(self, other: HomogeneousAggregate) -> Result { - match (self, other) { - (x, HomogeneousAggregate::NoData) | (HomogeneousAggregate::NoData, x) => Ok(x), - - (HomogeneousAggregate::Homogeneous(a), HomogeneousAggregate::Homogeneous(b)) => { - if a != b { - return Err(Heterogeneous); - } - Ok(self) - } - } - } -} - -impl<'a, Ty> TyAndLayout<'a, Ty> { - /// Returns `true` if this is an aggregate type (including a ScalarPair!) - fn is_aggregate(&self) -> bool { - match self.abi { - Abi::Uninhabited | Abi::Scalar(_) | Abi::Vector { .. } => false, - Abi::ScalarPair(..) | Abi::Aggregate { .. } => true, - } - } - - /// Returns `Homogeneous` if this layout is an aggregate containing fields of - /// only a single type (e.g., `(u32, u32)`). Such aggregates are often - /// special-cased in ABIs. - /// - /// Note: We generally ignore 1-ZST fields when computing this value (see #56877). - /// - /// This is public so that it can be used in unit tests, but - /// should generally only be relevant to the ABI details of - /// specific targets. - pub fn homogeneous_aggregate(&self, cx: &C) -> Result - where - Ty: TyAbiInterface<'a, C> + Copy, - { - match self.abi { - Abi::Uninhabited => Err(Heterogeneous), - - // The primitive for this algorithm. - Abi::Scalar(scalar) => { - let kind = match scalar.primitive() { - abi::Int(..) | abi::Pointer(_) => RegKind::Integer, - abi::Float(_) => RegKind::Float, - }; - Ok(HomogeneousAggregate::Homogeneous(Reg { kind, size: self.size })) - } - - Abi::Vector { .. } => { - assert!(!self.is_zst()); - Ok(HomogeneousAggregate::Homogeneous(Reg { - kind: RegKind::Vector, - size: self.size, - })) - } - - Abi::ScalarPair(..) | Abi::Aggregate { sized: true } => { - // Helper for computing `homogeneous_aggregate`, allowing a custom - // starting offset (used below for handling variants). - let from_fields_at = - |layout: Self, - start: Size| - -> Result<(HomogeneousAggregate, Size), Heterogeneous> { - let is_union = match layout.fields { - FieldsShape::Primitive => { - unreachable!("aggregates can't have `FieldsShape::Primitive`") - } - FieldsShape::Array { count, .. } => { - assert_eq!(start, Size::ZERO); - - let result = if count > 0 { - layout.field(cx, 0).homogeneous_aggregate(cx)? - } else { - HomogeneousAggregate::NoData - }; - return Ok((result, layout.size)); - } - FieldsShape::Union(_) => true, - FieldsShape::Arbitrary { .. } => false, - }; - - let mut result = HomogeneousAggregate::NoData; - let mut total = start; - - for i in 0..layout.fields.count() { - let field = layout.field(cx, i); - if field.is_1zst() { - // No data here and no impact on layout, can be ignored. - // (We might be able to also ignore all aligned ZST but that's less clear.) - continue; - } - - if !is_union && total != layout.fields.offset(i) { - // This field isn't just after the previous one we considered, abort. - return Err(Heterogeneous); - } - - result = result.merge(field.homogeneous_aggregate(cx)?)?; - - // Keep track of the offset (without padding). - let size = field.size; - if is_union { - total = total.max(size); - } else { - total += size; - } - } - - Ok((result, total)) - }; - - let (mut result, mut total) = from_fields_at(*self, Size::ZERO)?; - - match &self.variants { - abi::Variants::Single { .. } => {} - abi::Variants::Multiple { variants, .. } => { - // Treat enum variants like union members. - // HACK(eddyb) pretend the `enum` field (discriminant) - // is at the start of every variant (otherwise the gap - // at the start of all variants would disqualify them). - // - // NB: for all tagged `enum`s (which include all non-C-like - // `enum`s with defined FFI representation), this will - // match the homogeneous computation on the equivalent - // `struct { tag; union { variant1; ... } }` and/or - // `union { struct { tag; variant1; } ... }` - // (the offsets of variant fields should be identical - // between the two for either to be a homogeneous aggregate). - let variant_start = total; - for variant_idx in variants.indices() { - let (variant_result, variant_total) = - from_fields_at(self.for_variant(cx, variant_idx), variant_start)?; - - result = result.merge(variant_result)?; - total = total.max(variant_total); - } - } - } - - // There needs to be no padding. - if total != self.size { - Err(Heterogeneous) - } else { - match result { - HomogeneousAggregate::Homogeneous(_) => { - assert_ne!(total, Size::ZERO); - } - HomogeneousAggregate::NoData => { - assert_eq!(total, Size::ZERO); - } - } - Ok(result) - } - } - Abi::Aggregate { sized: false } => Err(Heterogeneous), - } - } -} - /// Information about how to pass an argument to, /// or return a value from, a function, under some ABI. #[derive(Clone, PartialEq, Eq, Hash, HashStable_Generic)] diff --git a/compiler/rustc_target/src/lib.rs b/compiler/rustc_target/src/lib.rs index 2121c4110dd..50679ab8cc8 100644 --- a/compiler/rustc_target/src/lib.rs +++ b/compiler/rustc_target/src/lib.rs @@ -21,8 +21,8 @@ use std::path::{Path, PathBuf}; -pub mod abi; pub mod asm; +pub mod callconv; pub mod json; pub mod spec; pub mod target_features; @@ -30,6 +30,15 @@ pub mod target_features; #[cfg(test)] mod tests; +pub mod abi { + pub(crate) use Float::*; + pub(crate) use Primitive::*; + // Explicitly import `Float` to avoid ambiguity with `Primitive::Float`. + pub use rustc_abi::{Float, *}; + + pub use crate::callconv as call; +} + pub use rustc_abi::HashStableContext; /// The name of rustc's own place to organize libraries. From 395b0787d454a21638ae94e7799fcefdb4591696 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sat, 17 Aug 2024 17:04:29 +1000 Subject: [PATCH 211/357] Flatten redundant test module `run_make_support::diff::tests::tests` --- src/tools/run-make-support/src/diff/tests.rs | 62 +++++++++----------- 1 file changed, 28 insertions(+), 34 deletions(-) diff --git a/src/tools/run-make-support/src/diff/tests.rs b/src/tools/run-make-support/src/diff/tests.rs index 286548bef61..c629519690e 100644 --- a/src/tools/run-make-support/src/diff/tests.rs +++ b/src/tools/run-make-support/src/diff/tests.rs @@ -1,28 +1,23 @@ -#[cfg(test)] -mod tests { - use crate::*; +use crate::*; - #[test] - fn test_diff() { - let expected = "foo\nbar\nbaz\n"; - let actual = "foo\nbar\nbaz\n"; +#[test] +fn test_diff() { + let expected = "foo\nbar\nbaz\n"; + let actual = "foo\nbar\nbaz\n"; + diff().expected_text("EXPECTED_TEXT", expected).actual_text("ACTUAL_TEXT", actual).run(); +} + +#[test] +fn test_should_panic() { + let expected = "foo\nbar\nbaz\n"; + let actual = "foo\nbaz\nbar\n"; + + let output = std::panic::catch_unwind(|| { diff().expected_text("EXPECTED_TEXT", expected).actual_text("ACTUAL_TEXT", actual).run(); - } + }) + .unwrap_err(); - #[test] - fn test_should_panic() { - let expected = "foo\nbar\nbaz\n"; - let actual = "foo\nbaz\nbar\n"; - - let output = std::panic::catch_unwind(|| { - diff() - .expected_text("EXPECTED_TEXT", expected) - .actual_text("ACTUAL_TEXT", actual) - .run(); - }) - .unwrap_err(); - - let expected_output = "\ + let expected_output = "\ test failed: `EXPECTED_TEXT` is different from `ACTUAL_TEXT` --- EXPECTED_TEXT @@ -34,28 +29,27 @@ test failed: `EXPECTED_TEXT` is different from `ACTUAL_TEXT` -baz "; - assert_eq!(output.downcast_ref::().unwrap(), expected_output); - } + assert_eq!(output.downcast_ref::().unwrap(), expected_output); +} - #[test] - fn test_normalize() { - let expected = " +#[test] +fn test_normalize() { + let expected = " running 2 tests .. test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME "; - let actual = " + let actual = " running 2 tests .. test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.02s "; - diff() - .expected_text("EXPECTED_TEXT", expected) - .actual_text("ACTUAL_TEXT", actual) - .normalize(r#"finished in \d+\.\d+s"#, "finished in $$TIME") - .run(); - } + diff() + .expected_text("EXPECTED_TEXT", expected) + .actual_text("ACTUAL_TEXT", actual) + .normalize(r#"finished in \d+\.\d+s"#, "finished in $$TIME") + .run(); } From f4376c426b9315472d09c15daed72efbce0342b9 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sat, 12 Oct 2024 11:59:57 +1100 Subject: [PATCH 212/357] Avoid cross-file glob import --- src/tools/run-make-support/src/diff/tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/run-make-support/src/diff/tests.rs b/src/tools/run-make-support/src/diff/tests.rs index c629519690e..6096560ca52 100644 --- a/src/tools/run-make-support/src/diff/tests.rs +++ b/src/tools/run-make-support/src/diff/tests.rs @@ -1,4 +1,4 @@ -use crate::*; +use crate::diff; #[test] fn test_diff() { From 1e8d6d1ec3cad6bc7d88c0a8a993f69835e8422f Mon Sep 17 00:00:00 2001 From: surechen Date: Fri, 11 Oct 2024 20:27:46 +0800 Subject: [PATCH 213/357] Make unused_parens's suggestion considering expr's attributes For the expr with attributes, like `let _ = (#[inline] || println!("Hello!"));`, the suggestion's span should contains the attributes, or the suggestion will remove them. fixes #129833 --- compiler/rustc_lint/src/unused.rs | 10 +++++- ...or-stmt-expr-attributes-issue-129833.fixed | 15 +++++++++ ...s-for-stmt-expr-attributes-issue-129833.rs | 15 +++++++++ ...r-stmt-expr-attributes-issue-129833.stderr | 31 +++++++++++++++++++ 4 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 tests/ui/lint/unused/unused-parens-for-stmt-expr-attributes-issue-129833.fixed create mode 100644 tests/ui/lint/unused/unused-parens-for-stmt-expr-attributes-issue-129833.rs create mode 100644 tests/ui/lint/unused/unused-parens-for-stmt-expr-attributes-issue-129833.stderr diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 12d5b5cf979..1a007250961 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -804,7 +804,15 @@ trait UnusedDelimLint { .find_ancestor_inside(value.span) .map(|span| (value.span.with_hi(span.lo()), value.span.with_lo(span.hi()))), ast::ExprKind::Paren(ref expr) => { - expr.span.find_ancestor_inside(value.span).map(|expr_span| { + // For the expr with attributes, like `let _ = (#[inline] || println!("Hello!"));`, + // the span should contains the attributes, or the suggestion will remove them. + let expr_span_with_attrs = + if let Some(attr_lo) = expr.attrs.iter().map(|attr| attr.span.lo()).min() { + expr.span.with_lo(attr_lo) + } else { + expr.span + }; + expr_span_with_attrs.find_ancestor_inside(value.span).map(|expr_span| { (value.span.with_hi(expr_span.lo()), value.span.with_lo(expr_span.hi())) }) } diff --git a/tests/ui/lint/unused/unused-parens-for-stmt-expr-attributes-issue-129833.fixed b/tests/ui/lint/unused/unused-parens-for-stmt-expr-attributes-issue-129833.fixed new file mode 100644 index 00000000000..8287b3d3ac7 --- /dev/null +++ b/tests/ui/lint/unused/unused-parens-for-stmt-expr-attributes-issue-129833.fixed @@ -0,0 +1,15 @@ +//@ run-rustfix +// Check the `unused_parens` suggestion for paren_expr with attributes. +// The suggestion should retain attributes in the front. + +#![feature(stmt_expr_attributes)] +#![deny(unused_parens)] + +pub fn foo() -> impl Fn() { + let _ = #[inline] #[allow(dead_code)] || println!("Hello!"); //~ERROR unnecessary parentheses + #[inline] #[allow(dead_code)] || println!("Hello!") //~ERROR unnecessary parentheses +} + +fn main() { + let _ = foo(); +} diff --git a/tests/ui/lint/unused/unused-parens-for-stmt-expr-attributes-issue-129833.rs b/tests/ui/lint/unused/unused-parens-for-stmt-expr-attributes-issue-129833.rs new file mode 100644 index 00000000000..0b6edae30e7 --- /dev/null +++ b/tests/ui/lint/unused/unused-parens-for-stmt-expr-attributes-issue-129833.rs @@ -0,0 +1,15 @@ +//@ run-rustfix +// Check the `unused_parens` suggestion for paren_expr with attributes. +// The suggestion should retain attributes in the front. + +#![feature(stmt_expr_attributes)] +#![deny(unused_parens)] + +pub fn foo() -> impl Fn() { + let _ = (#[inline] #[allow(dead_code)] || println!("Hello!")); //~ERROR unnecessary parentheses + (#[inline] #[allow(dead_code)] || println!("Hello!")) //~ERROR unnecessary parentheses +} + +fn main() { + let _ = foo(); +} diff --git a/tests/ui/lint/unused/unused-parens-for-stmt-expr-attributes-issue-129833.stderr b/tests/ui/lint/unused/unused-parens-for-stmt-expr-attributes-issue-129833.stderr new file mode 100644 index 00000000000..65513553f7e --- /dev/null +++ b/tests/ui/lint/unused/unused-parens-for-stmt-expr-attributes-issue-129833.stderr @@ -0,0 +1,31 @@ +error: unnecessary parentheses around assigned value + --> $DIR/unused-parens-for-stmt-expr-attributes-issue-129833.rs:9:13 + | +LL | let _ = (#[inline] #[allow(dead_code)] || println!("Hello!")); + | ^ ^ + | +note: the lint level is defined here + --> $DIR/unused-parens-for-stmt-expr-attributes-issue-129833.rs:6:9 + | +LL | #![deny(unused_parens)] + | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - let _ = (#[inline] #[allow(dead_code)] || println!("Hello!")); +LL + let _ = #[inline] #[allow(dead_code)] || println!("Hello!"); + | + +error: unnecessary parentheses around block return value + --> $DIR/unused-parens-for-stmt-expr-attributes-issue-129833.rs:10:5 + | +LL | (#[inline] #[allow(dead_code)] || println!("Hello!")) + | ^ ^ + | +help: remove these parentheses + | +LL - (#[inline] #[allow(dead_code)] || println!("Hello!")) +LL + #[inline] #[allow(dead_code)] || println!("Hello!") + | + +error: aborting due to 2 previous errors + From 1fe079bd62e68d94d5eff51cea94014a7e3c4625 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= <39484203+jieyouxu@users.noreply.github.com> Date: Sat, 12 Oct 2024 09:41:42 +0800 Subject: [PATCH 214/357] Remap path refix in the panic message Otherwise `error-pattern` on the test run stderr can incorrectly match if e.g. the paths in panic backtrace has a matching substring (like if we look for `bar` in the error pattern but username is `baron`). --- tests/ui/meta/revision-bad.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/ui/meta/revision-bad.rs b/tests/ui/meta/revision-bad.rs index c5193b19d9e..0af5624ff9c 100644 --- a/tests/ui/meta/revision-bad.rs +++ b/tests/ui/meta/revision-bad.rs @@ -5,6 +5,7 @@ //@ revisions: foo bar //@ should-fail //@ needs-run-enabled +//@ compile-flags: --remap-path-prefix={{src-base}}=remapped //@[foo] error-pattern:bar //@[bar] error-pattern:foo From 33ac202904e7820268b71b3280a7d2590378e3b9 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Thu, 10 Oct 2024 09:38:57 +0300 Subject: [PATCH 215/357] force "HEAD" for non-CI and `git_upstream_merge_base` for CI environment When rust-lang/rust is configured as remote, some of the git logic (for tracking changed files) that uses get_closest_merge_commit starts to produce annoying results as the upstream branch becomes outdated quickly (since it isn't updated with git pull). We can rely on HEAD for non-CI environments as we specifically treat bors commits as merge commits, which also exist on upstream. As for CI environments, we should use `git_upstream_merge_base` to correctly track modified files as bors commits may be in `HEAD` but not yet on the upstream remote. Signed-off-by: onur-ozkan --- src/tools/build_helper/src/git.rs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/tools/build_helper/src/git.rs b/src/tools/build_helper/src/git.rs index 10c5476cd8f..cac5a990a73 100644 --- a/src/tools/build_helper/src/git.rs +++ b/src/tools/build_helper/src/git.rs @@ -1,6 +1,8 @@ use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; +use crate::ci::CiEnv; + pub struct GitConfig<'a> { pub git_repository: &'a str, pub nightly_branch: &'a str, @@ -114,8 +116,8 @@ fn git_upstream_merge_base( /// Searches for the nearest merge commit in the repository that also exists upstream. /// -/// If it fails to find the upstream remote, it then looks for the most recent commit made -/// by the merge bot by matching the author's email address with the merge bot's email. +/// It looks for the most recent commit made by the merge bot by matching the author's email +/// address with the merge bot's email. pub fn get_closest_merge_commit( git_dir: Option<&Path>, config: &GitConfig<'_>, @@ -127,7 +129,15 @@ pub fn get_closest_merge_commit( git.current_dir(git_dir); } - let merge_base = git_upstream_merge_base(config, git_dir).unwrap_or_else(|_| "HEAD".into()); + let merge_base = { + if CiEnv::is_ci() { + git_upstream_merge_base(config, git_dir).unwrap() + } else { + // For non-CI environments, ignore rust-lang/rust upstream as it usually gets + // outdated very quickly. + "HEAD".to_string() + } + }; git.args([ "rev-list", From 4454fa998c9da1f1eee1602c8e8cd2732505c104 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Sat, 12 Oct 2024 07:41:39 +0300 Subject: [PATCH 216/357] add new CI step: "setup upstream remote" Signed-off-by: onur-ozkan --- .github/workflows/ci.yml | 3 +++ src/ci/scripts/setup-upstream-remote.sh | 24 ++++++++++++++++++++++++ src/ci/shared.sh | 12 ++++++++++++ 3 files changed, 39 insertions(+) create mode 100755 src/ci/scripts/setup-upstream-remote.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b6dc27f1234..003c1e5d7eb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -122,6 +122,9 @@ jobs: # which then uses log commands to actually set them. EXTRA_VARIABLES: ${{ toJson(matrix.env) }} + - name: setup upstream remote + run: src/ci/scripts/setup-upstream-remote.sh + - name: ensure the channel matches the target branch run: src/ci/scripts/verify-channel.sh diff --git a/src/ci/scripts/setup-upstream-remote.sh b/src/ci/scripts/setup-upstream-remote.sh new file mode 100755 index 00000000000..52b4c98a890 --- /dev/null +++ b/src/ci/scripts/setup-upstream-remote.sh @@ -0,0 +1,24 @@ +#!/bin/bash +# In CI environments, bootstrap is forced to use the remote upstream based +# on "git_repository" and "nightly_branch" values from src/stage0 file. +# This script configures the remote as it may not exist by default. + +set -euo pipefail +IFS=$'\n\t' + +ci_dir=$(cd $(dirname $0) && pwd)/.. +source "$ci_dir/shared.sh" + +git_repository=$(parse_stage0_file_by_key "git_repository") +nightly_branch=$(parse_stage0_file_by_key "nightly_branch") + +# Configure "rust-lang/rust" upstream remote only when it's not origin. +if [ -z "$(git config remote.origin.url | grep $git_repository)" ]; then + echo "Configuring https://github.com/$git_repository remote as upstream." + git remote add upstream "https://github.com/$git_repository" + REMOTE_NAME="upstream" +else + REMOTE_NAME="origin" +fi + +git fetch $REMOTE_NAME $nightly_branch diff --git a/src/ci/shared.sh b/src/ci/shared.sh index 2b0a10e4d08..1e6a008a5de 100644 --- a/src/ci/shared.sh +++ b/src/ci/shared.sh @@ -136,3 +136,15 @@ function releaseChannel { echo $RUST_CI_OVERRIDE_RELEASE_CHANNEL fi } + +# Parse values from src/stage0 file by key +function parse_stage0_file_by_key { + local key="$1" + local file="$ci_dir/../stage0" + local value=$(awk -F= '{a[$1]=$2} END {print(a["'$key'"])}' $file) + if [ -z "$value" ]; then + echo "ERROR: Key '$key' not found in '$file'." + exit 1 + fi + echo "$value" +} From 9a523001e3c245f8f547720a176005cf5bdee4f0 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Thu, 26 Sep 2024 10:36:59 -0700 Subject: [PATCH 217/357] library: Stabilize `const_intrinsic_forget` This is an implicit requirement of stabilizing `const_ptr_write`. Const-stabilizes the internal `core::intrinsics`: - `forget` --- library/core/src/intrinsics.rs | 2 +- library/core/src/lib.rs | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index d7a2f1909ca..3be07654432 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -1084,7 +1084,7 @@ extern "rust-intrinsic" { /// it does not require an `unsafe` block. /// Therefore, implementations must not require the user to uphold /// any safety invariants. - #[rustc_const_unstable(feature = "const_intrinsic_forget", issue = "none")] + #[rustc_const_stable(feature = "const_intrinsic_forget", since = "CURRENT_RUSTC_VERSION")] #[rustc_safe_intrinsic] #[rustc_nounwind] pub fn forget(_: T); diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index f68f19ec6a4..3eacf7261a5 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -124,7 +124,6 @@ #![feature(const_hash)] #![feature(const_heap)] #![feature(const_index_range_slice_index)] -#![feature(const_intrinsic_forget)] #![feature(const_ipv4)] #![feature(const_ipv6)] #![feature(const_likely)] From ddc367ded70b3145ffa92216bb4aaf178233c4ee Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Thu, 26 Sep 2024 09:30:17 -0700 Subject: [PATCH 218/357] library: Stabilize `const_ptr_write` Const-stabilizes: - `write` - `write_bytes` - `write_unaligned` In the following paths: - `core::ptr` - `core::ptr::NonNull` - pointer `<*mut T>` Const-stabilizes the internal `core::intrinsics`: - `write_bytes` - `write_via_move` --- library/alloc/src/lib.rs | 1 - library/alloc/tests/lib.rs | 1 - library/core/src/intrinsics.rs | 6 +++--- library/core/src/lib.rs | 1 - library/core/src/ptr/mod.rs | 5 +++-- library/core/src/ptr/mut_ptr.rs | 6 +++--- library/core/src/ptr/non_null.rs | 6 +++--- library/core/tests/lib.rs | 1 - tests/ui/consts/load-preserves-partial-init.rs | 1 - 9 files changed, 12 insertions(+), 16 deletions(-) diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index c60c0743c7e..1d7b7a03454 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -173,7 +173,6 @@ #![feature(allow_internal_unstable)] #![feature(cfg_sanitize)] #![feature(const_precise_live_drops)] -#![feature(const_ptr_write)] #![feature(const_try)] #![feature(decl_macro)] #![feature(dropck_eyepatch)] diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs index f43143c6cef..4d146f1f5fd 100644 --- a/library/alloc/tests/lib.rs +++ b/library/alloc/tests/lib.rs @@ -7,7 +7,6 @@ #![feature(const_cow_is_borrowed)] #![feature(const_heap)] #![cfg_attr(bootstrap, feature(const_mut_refs))] -#![feature(const_ptr_write)] #![feature(const_try)] #![feature(core_intrinsics)] #![feature(extract_if)] diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 3be07654432..f61b675ac4e 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -2635,7 +2635,7 @@ extern "rust-intrinsic" { /// This intrinsic can *only* be called where the pointer is a local without /// projections (`write_via_move(ptr, x)`, not `write_via_move(*ptr, x)`) so /// that it trivially obeys runtime-MIR rules about derefs in operands. - #[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")] + #[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")] #[rustc_nounwind] pub fn write_via_move(ptr: *mut T, value: T); @@ -3472,13 +3472,13 @@ pub const unsafe fn copy(src: *const T, dst: *mut T, count: usize) { #[doc(alias = "memset")] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_allowed_through_unstable_modules] -#[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")] +#[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_diagnostic_item = "ptr_write_bytes"] pub const unsafe fn write_bytes(dst: *mut T, val: u8, count: usize) { extern "rust-intrinsic" { - #[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")] + #[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")] #[rustc_nounwind] fn write_bytes(dst: *mut T, val: u8, count: usize); } diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 3eacf7261a5..97df6ccfa5e 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -137,7 +137,6 @@ #![feature(const_pointer_is_aligned)] #![feature(const_ptr_is_null)] #![feature(const_ptr_sub_ptr)] -#![feature(const_ptr_write)] #![feature(const_raw_ptr_comparison)] #![feature(const_replace)] #![feature(const_size_of_val)] diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 67f1b0cd16d..6f076caf533 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -1611,7 +1611,7 @@ pub const unsafe fn read_unaligned(src: *const T) -> T { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")] +#[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")] #[rustc_diagnostic_item = "ptr_write"] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn write(dst: *mut T, src: T) { @@ -1719,7 +1719,8 @@ pub const unsafe fn write(dst: *mut T, src: T) { /// ``` #[inline] #[stable(feature = "ptr_unaligned", since = "1.17.0")] -#[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")] +#[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_refs_to_cell))] +#[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")] #[rustc_diagnostic_item = "ptr_write_unaligned"] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn write_unaligned(dst: *mut T, src: T) { diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index e458bb4642f..ced6cb7d520 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -1449,7 +1449,7 @@ impl *mut T { /// /// [`ptr::write`]: crate::ptr::write() #[stable(feature = "pointer_methods", since = "1.26.0")] - #[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")] + #[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn write(self, val: T) @@ -1468,7 +1468,7 @@ impl *mut T { /// [`ptr::write_bytes`]: crate::ptr::write_bytes() #[doc(alias = "memset")] #[stable(feature = "pointer_methods", since = "1.26.0")] - #[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")] + #[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn write_bytes(self, val: u8, count: usize) @@ -1509,7 +1509,7 @@ impl *mut T { /// /// [`ptr::write_unaligned`]: crate::ptr::write_unaligned() #[stable(feature = "pointer_methods", since = "1.26.0")] - #[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")] + #[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn write_unaligned(self, val: T) diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index 6c5834a1ece..dc1a7c6220e 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -1013,7 +1013,7 @@ impl NonNull { #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[stable(feature = "non_null_convenience", since = "1.80.0")] - #[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")] + #[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")] pub const unsafe fn write(self, val: T) where T: Sized, @@ -1032,7 +1032,7 @@ impl NonNull { #[doc(alias = "memset")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[stable(feature = "non_null_convenience", since = "1.80.0")] - #[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")] + #[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")] pub const unsafe fn write_bytes(self, val: u8, count: usize) where T: Sized, @@ -1073,7 +1073,7 @@ impl NonNull { #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[stable(feature = "non_null_convenience", since = "1.80.0")] - #[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")] + #[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")] pub const unsafe fn write_unaligned(self, val: T) where T: Sized, diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 8ee98de2a7b..5ec1b311a50 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -28,7 +28,6 @@ #![feature(const_option_ext)] #![feature(const_pin)] #![feature(const_pointer_is_aligned)] -#![feature(const_ptr_write)] #![feature(const_three_way_compare)] #![feature(const_trait_impl)] #![feature(core_intrinsics)] diff --git a/tests/ui/consts/load-preserves-partial-init.rs b/tests/ui/consts/load-preserves-partial-init.rs index d97e9cb3d9d..2a8adbd5e16 100644 --- a/tests/ui/consts/load-preserves-partial-init.rs +++ b/tests/ui/consts/load-preserves-partial-init.rs @@ -1,6 +1,5 @@ //@ run-pass -#![feature(const_ptr_write)] // issue: https://github.com/rust-lang/rust/issues/69488 // Loads of partially-initialized data could produce completely-uninitialized results. // Test to make sure that we no longer do such a "deinitializing" load. From 187c8b0ce90eb3a446aa6bd838d6984764479a5a Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Thu, 26 Sep 2024 11:49:53 -0700 Subject: [PATCH 219/357] library: Stabilize `const_replace` Depends on stabilizing `const_ptr_write`. Const-stabilizes: - `core::mem::replace` - `core::ptr::replace` --- library/core/src/lib.rs | 1 - library/core/src/mem/mod.rs | 3 ++- library/core/src/ptr/mod.rs | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 97df6ccfa5e..d407efa069b 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -138,7 +138,6 @@ #![feature(const_ptr_is_null)] #![feature(const_ptr_sub_ptr)] #![feature(const_raw_ptr_comparison)] -#![feature(const_replace)] #![feature(const_size_of_val)] #![feature(const_size_of_val_raw)] #![feature(const_strict_overflow_ops)] diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index 414262fcf5a..9bf2aa594c0 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -857,7 +857,8 @@ pub fn take(dest: &mut T) -> T { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[must_use = "if you don't need the old value, you can just assign the new value directly"] -#[rustc_const_unstable(feature = "const_replace", issue = "83164")] +#[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] +#[rustc_const_stable(feature = "const_replace", since = "CURRENT_RUSTC_VERSION")] #[cfg_attr(not(test), rustc_diagnostic_item = "mem_replace")] pub const fn replace(dest: &mut T, src: T) -> T { // It may be tempting to use `swap` to avoid `unsafe` here. Don't! diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 6f076caf533..6b074492924 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -1263,7 +1263,8 @@ const unsafe fn swap_nonoverlapping_simple_untyped(x: *mut T, y: *mut T, coun /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_replace", issue = "83164")] +#[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] +#[rustc_const_stable(feature = "const_replace", since = "CURRENT_RUSTC_VERSION")] #[rustc_diagnostic_item = "ptr_replace"] pub const unsafe fn replace(dst: *mut T, src: T) -> T { // SAFETY: the caller must guarantee that `dst` is valid to be From 497100a13c72d290a167ae6eb5566fca653ba99f Mon Sep 17 00:00:00 2001 From: CastilloDel Date: Fri, 11 Oct 2024 22:05:58 +0200 Subject: [PATCH 220/357] Emit an error for unstable attributes that reference already stable features Add missing error annotations and .stderr file Acknowledge comments --- compiler/rustc_passes/messages.ftl | 6 ++++ compiler/rustc_passes/src/errors.rs | 11 +++++++ compiler/rustc_passes/src/stability.rs | 16 ++++++++++ ...tribute-rejects-already-stable-features.rs | 10 ++++++ ...ute-rejects-already-stable-features.stderr | 31 +++++++++++++++++++ 5 files changed, 74 insertions(+) create mode 100644 tests/ui/feature-gates/unstable-attribute-rejects-already-stable-features.rs create mode 100644 tests/ui/feature-gates/unstable-attribute-rejects-already-stable-features.stderr diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index 5369f54afb9..b5e1dc9a4ce 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -745,6 +745,12 @@ passes_unrecognized_repr_hint = unrecognized representation hint .help = valid reprs are `Rust` (default), `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` +passes_unstable_attr_for_already_stable_feature = + can't mark as unstable using an already stable feature + .label = this feature is already stable + .item = the stability attribute annotates this item + .help = consider removing the attribute + passes_unused = unused attribute .suggestion = remove this attribute diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 29a087bf759..021145aff7c 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -1496,6 +1496,17 @@ pub(crate) struct CannotStabilizeDeprecated { pub item_sp: Span, } +#[derive(Diagnostic)] +#[diag(passes_unstable_attr_for_already_stable_feature)] +pub(crate) struct UnstableAttrForAlreadyStableFeature { + #[primary_span] + #[label] + #[help] + pub span: Span, + #[label(passes_item)] + pub item_sp: Span, +} + #[derive(Diagnostic)] #[diag(passes_missing_stability_attr)] pub(crate) struct MissingStabilityAttr<'a> { diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 46b67e930d5..751c87a9fe5 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -10,6 +10,7 @@ use rustc_attr::{ }; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::unord::{ExtendUnord, UnordMap, UnordSet}; +use rustc_feature::ACCEPTED_FEATURES; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId, LocalModDefId}; @@ -246,12 +247,27 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> { } } + if let Stability { level: Unstable { .. }, feature } = stab { + if ACCEPTED_FEATURES.iter().find(|f| f.name == feature).is_some() { + self.tcx + .dcx() + .emit_err(errors::UnstableAttrForAlreadyStableFeature { span, item_sp }); + } + } if let Stability { level: Unstable { implied_by: Some(implied_by), .. }, feature } = stab { self.index.implications.insert(implied_by, feature); } + if let Some(ConstStability { level: Unstable { .. }, feature, .. }) = const_stab { + if ACCEPTED_FEATURES.iter().find(|f| f.name == feature).is_some() { + self.tcx.dcx().emit_err(errors::UnstableAttrForAlreadyStableFeature { + span: const_span.unwrap(), // If const_stab contains Some(..), same is true for const_span + item_sp, + }); + } + } if let Some(ConstStability { level: Unstable { implied_by: Some(implied_by), .. }, feature, diff --git a/tests/ui/feature-gates/unstable-attribute-rejects-already-stable-features.rs b/tests/ui/feature-gates/unstable-attribute-rejects-already-stable-features.rs new file mode 100644 index 00000000000..9e697aaa0dc --- /dev/null +++ b/tests/ui/feature-gates/unstable-attribute-rejects-already-stable-features.rs @@ -0,0 +1,10 @@ +//! Ensure #[unstable] doesn't accept already stable features + +#![feature(staged_api)] +#![stable(feature = "rust_test", since = "1.0.0")] + +#[unstable(feature = "arbitrary_enum_discriminant", issue = "42")] //~ ERROR can't mark as unstable using an already stable feature +#[rustc_const_unstable(feature = "arbitrary_enum_discriminant", issue = "42")] //~ ERROR can't mark as unstable using an already stable feature +const fn my_fun() {} + +fn main() {} diff --git a/tests/ui/feature-gates/unstable-attribute-rejects-already-stable-features.stderr b/tests/ui/feature-gates/unstable-attribute-rejects-already-stable-features.stderr new file mode 100644 index 00000000000..319056a9c88 --- /dev/null +++ b/tests/ui/feature-gates/unstable-attribute-rejects-already-stable-features.stderr @@ -0,0 +1,31 @@ +error: can't mark as unstable using an already stable feature + --> $DIR/unstable-attribute-rejects-already-stable-features.rs:6:1 + | +LL | #[unstable(feature = "arbitrary_enum_discriminant", issue = "42")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this feature is already stable +LL | #[rustc_const_unstable(feature = "arbitrary_enum_discriminant", issue = "42")] +LL | const fn my_fun() {} + | -------------------- the stability attribute annotates this item + | +help: consider removing the attribute + --> $DIR/unstable-attribute-rejects-already-stable-features.rs:6:1 + | +LL | #[unstable(feature = "arbitrary_enum_discriminant", issue = "42")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: can't mark as unstable using an already stable feature + --> $DIR/unstable-attribute-rejects-already-stable-features.rs:7:1 + | +LL | #[rustc_const_unstable(feature = "arbitrary_enum_discriminant", issue = "42")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this feature is already stable +LL | const fn my_fun() {} + | -------------------- the stability attribute annotates this item + | +help: consider removing the attribute + --> $DIR/unstable-attribute-rejects-already-stable-features.rs:7:1 + | +LL | #[rustc_const_unstable(feature = "arbitrary_enum_discriminant", issue = "42")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + From e5906e1591c0aa787003f89e3f3c9236c22f4832 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sat, 12 Oct 2024 10:59:12 +0200 Subject: [PATCH 221/357] yeet some clones --- compiler/rustc_borrowck/src/nll.rs | 2 +- compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index f3207c26bfc..3674053409b 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -165,7 +165,7 @@ pub(crate) fn compute_regions<'a, 'tcx>( universe_causes, type_tests, liveness_constraints, - elements.clone(), + elements, ); // If requested: dump NLL facts, and run legacy polonius analysis. diff --git a/compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs b/compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs index fab1906eecd..e3878d90e41 100644 --- a/compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs +++ b/compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs @@ -312,7 +312,7 @@ pub(crate) fn expand_deriving_smart_ptr( impl_generics.params.insert(pointee_param_idx + 1, extra_param); // Add the impl blocks for `DispatchFromDyn` and `CoerceUnsized`. - let gen_args = vec![GenericArg::Type(alt_self_type.clone())]; + let gen_args = vec![GenericArg::Type(alt_self_type)]; add_impl_block(impl_generics.clone(), sym::DispatchFromDyn, gen_args.clone()); add_impl_block(impl_generics.clone(), sym::CoerceUnsized, gen_args); } From bcd71624d5f5c7a55477dfb05404b30d439d9674 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sat, 12 Oct 2024 11:29:38 +0200 Subject: [PATCH 222/357] add latest crash tests --- tests/crashes/131507.rs | 10 ++++++++++ tests/crashes/131534.rs | 5 +++++ tests/crashes/131535.rs | 4 ++++ tests/crashes/131538.rs | 13 +++++++++++++ 4 files changed, 32 insertions(+) create mode 100644 tests/crashes/131507.rs create mode 100644 tests/crashes/131534.rs create mode 100644 tests/crashes/131535.rs create mode 100644 tests/crashes/131538.rs diff --git a/tests/crashes/131507.rs b/tests/crashes/131507.rs new file mode 100644 index 00000000000..d402fb8afc3 --- /dev/null +++ b/tests/crashes/131507.rs @@ -0,0 +1,10 @@ +//@ known-bug: #131507 +//@ compile-flags: -Zmir-opt-level=5 -Zvalidate-mir +#![feature(non_lifetime_binders)] + +fn brick() +where + for T: Copy, +{ + || format_args!(""); +} diff --git a/tests/crashes/131534.rs b/tests/crashes/131534.rs new file mode 100644 index 00000000000..545b3e68fe8 --- /dev/null +++ b/tests/crashes/131534.rs @@ -0,0 +1,5 @@ +//@ known-bug: #131534 +#![feature(generic_const_exprs)] +type Value<'v> = &[[u8; SIZE]]; + +trait Trait: Fn(Value) -> Value {} diff --git a/tests/crashes/131535.rs b/tests/crashes/131535.rs new file mode 100644 index 00000000000..47ccdf87f2d --- /dev/null +++ b/tests/crashes/131535.rs @@ -0,0 +1,4 @@ +//@ known-bug: #131535 +#![feature(non_lifetime_binders)] +trait v0<> {} +fn kind :(v0<'_, > impl for v0<'_, v2 = impl v0 + '_>) {} diff --git a/tests/crashes/131538.rs b/tests/crashes/131538.rs new file mode 100644 index 00000000000..f971d8b7791 --- /dev/null +++ b/tests/crashes/131538.rs @@ -0,0 +1,13 @@ +//@ known-bug: #131538 +#![feature(generic_associated_types_extended)] +#![feature(trivial_bounds)] + +trait HealthCheck { + async fn check(); +} + +fn do_health_check_par() +where + HealthCheck: HealthCheck, +{ +} From bc4366b099e7a4d115650dcfec4aeeb62bfc3c54 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 12 Oct 2024 12:14:28 +0200 Subject: [PATCH 223/357] miri: avoid cloning AllocExtra --- .../src/const_eval/machine.rs | 2 +- .../rustc_const_eval/src/interpret/memory.rs | 31 +++++++++++-------- src/tools/miri/src/diagnostics.rs | 4 +-- src/tools/miri/src/eval.rs | 2 +- src/tools/miri/src/machine.rs | 10 +++++- 5 files changed, 31 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 4aec74595bc..2db43a0f787 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -140,7 +140,7 @@ impl interpret::AllocMap for FxIndexMap { #[inline(always)] fn filter_map_collect(&self, mut f: impl FnMut(&K, &V) -> Option) -> Vec { - self.iter().filter_map(move |(k, v)| f(k, &*v)).collect() + self.iter().filter_map(move |(k, v)| f(k, v)).collect() } #[inline(always)] diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index e6ab8ca12a8..7700eb792ef 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -993,11 +993,14 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { bytes } - /// Find leaked allocations. Allocations reachable from `static_roots` or a `Global` allocation - /// are not considered leaked, as well as leaks whose kind's `may_leak()` returns true. - pub fn find_leaked_allocations( - &self, - static_roots: &[AllocId], + /// Find leaked allocations, remove them from memory and return them. Allocations reachable from + /// `static_roots` or a `Global` allocation are not considered leaked, as well as leaks whose + /// kind's `may_leak()` returns true. + /// + /// This is highly destructive, no more execution can happen after this! + pub fn take_leaked_allocations( + &mut self, + static_roots: impl FnOnce(&Self) -> &[AllocId], ) -> Vec<(AllocId, MemoryKind, Allocation)> { // Collect the set of allocations that are *reachable* from `Global` allocations. @@ -1008,7 +1011,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { self.memory.alloc_map.filter_map_collect(move |&id, &(kind, _)| { if Some(kind) == global_kind { Some(id) } else { None } }); - todo.extend(static_roots); + todo.extend(static_roots(self)); while let Some(id) = todo.pop() { if reachable.insert(id) { // This is a new allocation, add the allocation it points to `todo`. @@ -1023,13 +1026,15 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { }; // All allocations that are *not* `reachable` and *not* `may_leak` are considered leaking. - self.memory.alloc_map.filter_map_collect(|id, (kind, alloc)| { - if kind.may_leak() || reachable.contains(id) { - None - } else { - Some((*id, *kind, alloc.clone())) - } - }) + let leaked: Vec<_> = self.memory.alloc_map.filter_map_collect(|&id, &(kind, _)| { + if kind.may_leak() || reachable.contains(&id) { None } else { Some(id) } + }); + let mut result = Vec::new(); + for &id in leaked.iter() { + let (kind, alloc) = self.memory.alloc_map.remove(&id).unwrap(); + result.push((id, kind, alloc)); + } + result } /// Runs the closure in "validation" mode, which means the machine's memory read hooks will be diff --git a/src/tools/miri/src/diagnostics.rs b/src/tools/miri/src/diagnostics.rs index 5b1bad28c07..475139a3b51 100644 --- a/src/tools/miri/src/diagnostics.rs +++ b/src/tools/miri/src/diagnostics.rs @@ -473,14 +473,14 @@ pub fn report_leaks<'tcx>( leaks: Vec<(AllocId, MemoryKind, Allocation, MiriAllocBytes>)>, ) { let mut any_pruned = false; - for (id, kind, mut alloc) in leaks { + for (id, kind, alloc) in leaks { let mut title = format!( "memory leaked: {id:?} ({}, size: {:?}, align: {:?})", kind, alloc.size().bytes(), alloc.align.bytes() ); - let Some(backtrace) = alloc.extra.backtrace.take() else { + let Some(backtrace) = alloc.extra.backtrace else { ecx.tcx.dcx().err(title); continue; }; diff --git a/src/tools/miri/src/eval.rs b/src/tools/miri/src/eval.rs index ece76e581f2..57b226de28c 100644 --- a/src/tools/miri/src/eval.rs +++ b/src/tools/miri/src/eval.rs @@ -476,7 +476,7 @@ pub fn eval_entry<'tcx>( } // Check for memory leaks. info!("Additional static roots: {:?}", ecx.machine.static_roots); - let leaks = ecx.find_leaked_allocations(&ecx.machine.static_roots); + let leaks = ecx.take_leaked_allocations(|ecx| &ecx.machine.static_roots); if !leaks.is_empty() { report_leaks(&ecx, leaks); tcx.dcx().note("set `MIRIFLAGS=-Zmiri-ignore-leaks` to disable this check"); diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index b9cebcfe9cd..d346cd7b03e 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -321,7 +321,7 @@ impl ProvenanceExtra { } /// Extra per-allocation data -#[derive(Debug, Clone)] +#[derive(Debug)] pub struct AllocExtra<'tcx> { /// Global state of the borrow tracker, if enabled. pub borrow_tracker: Option, @@ -338,6 +338,14 @@ pub struct AllocExtra<'tcx> { pub backtrace: Option>>, } +// We need a `Clone` impl because the machine passes `Allocation` through `Cow`... +// but that should never end up actually cloning our `AllocExtra`. +impl<'tcx> Clone for AllocExtra<'tcx> { + fn clone(&self) -> Self { + panic!("our allocations should never be cloned"); + } +} + impl VisitProvenance for AllocExtra<'_> { fn visit_provenance(&self, visit: &mut VisitWith<'_>) { let AllocExtra { borrow_tracker, data_race, weak_memory, backtrace: _ } = self; From 9f91c5099fb7261cf8c85cc638d2692a317060ec Mon Sep 17 00:00:00 2001 From: joboet Date: Sat, 12 Oct 2024 13:01:36 +0200 Subject: [PATCH 224/357] std: fix stdout-before-main Fixes #130210. Since #124881, `ReentrantLock` uses `ThreadId` to identify threads. This has the unfortunate consequence of breaking uses of `Stdout` before main: Locking the `ReentrantLock` that synchronizes the output will initialize the thread ID before the handle for the main thread is set in `rt::init`. But since that would overwrite the current thread ID, `thread::set_current` triggers an abort. This PR fixes the problem by using the already initialized thread ID for constructing the main thread handle and allowing `set_current` calls that do not change the thread's ID. --- library/std/src/rt.rs | 21 +++++++++++++--- library/std/src/thread/current.rs | 20 +++++++++------- library/std/src/thread/mod.rs | 24 ++++++++++--------- tests/ui/runtime/stdout-before-main.rs | 24 +++++++++++++++++++ .../ui/runtime/stdout-before-main.run.stdout | 1 + 5 files changed, 67 insertions(+), 23 deletions(-) create mode 100644 tests/ui/runtime/stdout-before-main.rs create mode 100644 tests/ui/runtime/stdout-before-main.run.stdout diff --git a/library/std/src/rt.rs b/library/std/src/rt.rs index 0a841f07e3b..80e7c3c026b 100644 --- a/library/std/src/rt.rs +++ b/library/std/src/rt.rs @@ -102,9 +102,24 @@ unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) { sys::init(argc, argv, sigpipe) }; - // Set up the current thread to give it the right name. - let thread = Thread::new_main(); - thread::set_current(thread); + // Set up the current thread handle to give it the right name. + // + // When code running before main uses `ReentrantLock` (for example by + // using `println!`), the thread ID can become initialized before we + // create this handle. Since `set_current` fails when the ID of the + // handle does not match the current ID, we should attempt to use the + // current thread ID here instead of unconditionally creating a new + // one. Also see #130210. + let thread = Thread::new_main(thread::current_id()); + if let Err(_thread) = thread::set_current(thread) { + // `thread::current` will create a new handle if none has been set yet. + // Thus, if someone uses it before main, this call will fail. That's a + // bad idea though, as we then cannot set the main thread name here. + // + // FIXME: detect the main thread in `thread::current` and use the + // correct name there. + rtabort!("code running before main must not use thread::current"); + } } /// Clean up the thread-local runtime state. This *should* be run after all other diff --git a/library/std/src/thread/current.rs b/library/std/src/thread/current.rs index b38149a0da7..e6eb90c4c30 100644 --- a/library/std/src/thread/current.rs +++ b/library/std/src/thread/current.rs @@ -110,22 +110,24 @@ mod id { } } -/// Sets the thread handle for the current thread. -/// -/// Aborts if the handle or the ID has been set already. -pub(crate) fn set_current(thread: Thread) { - if CURRENT.get() != NONE || id::get().is_some() { - // Using `panic` here can add ~3kB to the binary size. We have complete - // control over where this is called, so just abort if there is a bug. - rtabort!("thread::set_current should only be called once per thread"); +/// Tries to set the thread handle for the current thread. Fails if a handle was +/// already set or if the thread ID of `thread` would change an already-set ID. +pub(crate) fn set_current(thread: Thread) -> Result<(), Thread> { + if CURRENT.get() != NONE { + return Err(thread); } - id::set(thread.id()); + match id::get() { + Some(id) if id == thread.id() => {} + None => id::set(thread.id()), + _ => return Err(thread), + } // Make sure that `crate::rt::thread_cleanup` will be run, which will // call `drop_current`. crate::sys::thread_local::guard::enable(); CURRENT.set(thread.into_raw().cast_mut()); + Ok(()) } /// Gets the id of the thread that invokes it. diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index d1d4eabb9bd..39753888509 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -519,9 +519,14 @@ impl Builder { let f = MaybeDangling::new(f); let main = move || { - // Immediately store the thread handle to avoid setting it or its ID - // twice, which would cause an abort. - set_current(their_thread.clone()); + if let Err(_thread) = set_current(their_thread.clone()) { + // Both the current thread handle and the ID should not be + // initialized yet. Since only the C runtime and some of our + // platform code run before this, this point shouldn't be + // reachable. Use an abort to save binary size (see #123356). + rtabort!("something here is badly broken!"); + } + if let Some(name) = their_thread.cname() { imp::Thread::set_name(name); } @@ -1159,9 +1164,6 @@ pub fn park_timeout(dur: Duration) { pub struct ThreadId(NonZero); impl ThreadId { - // DO NOT rely on this value. - const MAIN_THREAD: ThreadId = ThreadId(unsafe { NonZero::new_unchecked(1) }); - // Generate a new unique thread ID. pub(crate) fn new() -> ThreadId { #[cold] @@ -1173,7 +1175,7 @@ impl ThreadId { if #[cfg(target_has_atomic = "64")] { use crate::sync::atomic::AtomicU64; - static COUNTER: AtomicU64 = AtomicU64::new(1); + static COUNTER: AtomicU64 = AtomicU64::new(0); let mut last = COUNTER.load(Ordering::Relaxed); loop { @@ -1189,7 +1191,7 @@ impl ThreadId { } else { use crate::sync::{Mutex, PoisonError}; - static COUNTER: Mutex = Mutex::new(1); + static COUNTER: Mutex = Mutex::new(0); let mut counter = COUNTER.lock().unwrap_or_else(PoisonError::into_inner); let Some(id) = counter.checked_add(1) else { @@ -1326,9 +1328,9 @@ impl Thread { Self::new_inner(id, ThreadName::Unnamed) } - // Used in runtime to construct main thread - pub(crate) fn new_main() -> Thread { - Self::new_inner(ThreadId::MAIN_THREAD, ThreadName::Main) + /// Constructs the thread handle for the main thread. + pub(crate) fn new_main(id: ThreadId) -> Thread { + Self::new_inner(id, ThreadName::Main) } fn new_inner(id: ThreadId, name: ThreadName) -> Thread { diff --git a/tests/ui/runtime/stdout-before-main.rs b/tests/ui/runtime/stdout-before-main.rs new file mode 100644 index 00000000000..26c734d3e9e --- /dev/null +++ b/tests/ui/runtime/stdout-before-main.rs @@ -0,0 +1,24 @@ +//@ run-pass +//@ check-run-results +//@ only-gnu +//@ only-linux +// +// Regression test for #130210. +// .init_array doesn't work everywhere, so we limit the test to just GNU/Linux. + +use std::ffi::c_int; +use std::thread; + +#[used] +#[link_section = ".init_array"] +static INIT: extern "C" fn(c_int, *const *const u8, *const *const u8) = { + extern "C" fn init(_argc: c_int, _argv: *const *const u8, _envp: *const *const u8) { + print!("Hello from before "); + } + + init +}; + +fn main() { + println!("{}!", thread::current().name().unwrap()); +} diff --git a/tests/ui/runtime/stdout-before-main.run.stdout b/tests/ui/runtime/stdout-before-main.run.stdout new file mode 100644 index 00000000000..d7a3a4389ec --- /dev/null +++ b/tests/ui/runtime/stdout-before-main.run.stdout @@ -0,0 +1 @@ +Hello from before main! From 52090f071524263fbe48be2e9eec51635f573f64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= <39484203+jieyouxu@users.noreply.github.com> Date: Sat, 12 Oct 2024 19:12:19 +0800 Subject: [PATCH 225/357] Take a display name for `tool_check_step!` --- src/bootstrap/src/core/build_steps/check.rs | 39 +++++++++++++++------ 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/check.rs b/src/bootstrap/src/core/build_steps/check.rs index 7671fc7e013..f419bebdc12 100644 --- a/src/bootstrap/src/core/build_steps/check.rs +++ b/src/bootstrap/src/core/build_steps/check.rs @@ -398,7 +398,14 @@ impl Step for RustAnalyzer { } macro_rules! tool_check_step { - ($name:ident, $path:literal, $($alias:literal, )* $source_type:path $(, $default:literal )?) => { + ( + $name:ident, + $display_name:literal, + $path:literal, + $($alias:literal, )* + $source_type:path + $(, $default:literal )? + ) => { #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct $name { pub target: TargetSelection, @@ -441,7 +448,7 @@ macro_rules! tool_check_step { cargo.arg("--all-targets"); } - let _guard = builder.msg_check(&concat!(stringify!($name), " artifacts").to_lowercase(), target); + let _guard = builder.msg_check(&format!("{} artifacts", $display_name), target); run_cargo( builder, cargo, @@ -468,20 +475,30 @@ macro_rules! tool_check_step { }; } -tool_check_step!(Rustdoc, "src/tools/rustdoc", "src/librustdoc", SourceType::InTree); +tool_check_step!(Rustdoc, "rustdoc", "src/tools/rustdoc", "src/librustdoc", SourceType::InTree); // Clippy, miri and Rustfmt are hybrids. They are external tools, but use a git subtree instead // of a submodule. Since the SourceType only drives the deny-warnings // behavior, treat it as in-tree so that any new warnings in clippy will be // rejected. -tool_check_step!(Clippy, "src/tools/clippy", SourceType::InTree); -tool_check_step!(Miri, "src/tools/miri", SourceType::InTree); -tool_check_step!(CargoMiri, "src/tools/miri/cargo-miri", SourceType::InTree); -tool_check_step!(Rls, "src/tools/rls", SourceType::InTree); -tool_check_step!(Rustfmt, "src/tools/rustfmt", SourceType::InTree); -tool_check_step!(MiroptTestTools, "src/tools/miropt-test-tools", SourceType::InTree); -tool_check_step!(TestFloatParse, "src/etc/test-float-parse", SourceType::InTree); +tool_check_step!(Clippy, "clippy", "src/tools/clippy", SourceType::InTree); +tool_check_step!(Miri, "miri", "src/tools/miri", SourceType::InTree); +tool_check_step!(CargoMiri, "cargo-miri", "src/tools/miri/cargo-miri", SourceType::InTree); +tool_check_step!(Rls, "rls", "src/tools/rls", SourceType::InTree); +tool_check_step!(Rustfmt, "rustfmt", "src/tools/rustfmt", SourceType::InTree); +tool_check_step!( + MiroptTestTools, + "miropt-test-tools", + "src/tools/miropt-test-tools", + SourceType::InTree +); +tool_check_step!( + TestFloatParse, + "test-float-parse", + "src/etc/test-float-parse", + SourceType::InTree +); -tool_check_step!(Bootstrap, "src/bootstrap", SourceType::InTree, false); +tool_check_step!(Bootstrap, "bootstrap", "src/bootstrap", SourceType::InTree, false); /// Cargo's output path for the standard library in a given stage, compiled /// by a particular compiler for the specified target. From 89623439f73d5a744ba5c8a911274b3802d79b86 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 12 Oct 2024 13:13:50 +0200 Subject: [PATCH 226/357] mark InterpResult as must_use --- compiler/rustc_middle/src/mir/interpret/error.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index 431043b0431..fcb87e19435 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -754,6 +754,7 @@ impl Drop for Guard { /// /// We also make things panic if this type is ever implicitly dropped. #[derive(Debug)] +#[must_use] pub struct InterpResult_<'tcx, T> { res: Result>, guard: Guard, From 470e9fa1af3e0ec36768e57cdb63bde46af8ee6d Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 12 Oct 2024 09:10:04 -0400 Subject: [PATCH 227/357] Shallowly match opaque key in storage --- .../src/solve/eval_ctxt/mod.rs | 51 +++++++------------ .../src/solve/normalizes_to/opaque_types.rs | 34 +++++++++---- 2 files changed, 42 insertions(+), 43 deletions(-) diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index 458edf920ab..daacc669118 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -4,6 +4,7 @@ use derive_where::derive_where; #[cfg(feature = "nightly")] use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable}; use rustc_type_ir::data_structures::{HashMap, HashSet, ensure_sufficient_stack}; +use rustc_type_ir::fast_reject::DeepRejectCtxt; use rustc_type_ir::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; use rustc_type_ir::inherent::*; use rustc_type_ir::relate::Relate; @@ -18,9 +19,9 @@ use crate::delegate::SolverDelegate; use crate::solve::inspect::{self, ProofTreeBuilder}; use crate::solve::search_graph::SearchGraph; use crate::solve::{ - CanonicalInput, CanonicalResponse, Certainty, FIXPOINT_STEP_LIMIT, Goal, GoalEvaluationKind, - GoalSource, HasChanged, NestedNormalizationGoals, NoSolution, PredefinedOpaquesData, - QueryResult, SolverMode, + CanonicalInput, Certainty, FIXPOINT_STEP_LIMIT, Goal, GoalEvaluationKind, GoalSource, + HasChanged, NestedNormalizationGoals, NoSolution, PredefinedOpaquesData, QueryResult, + SolverMode, }; pub(super) mod canonical; @@ -987,40 +988,22 @@ where // Do something for each opaque/hidden pair defined with `def_id` in the // current inference context. - pub(super) fn unify_existing_opaque_tys( + pub(super) fn probe_existing_opaque_ty( &mut self, - param_env: I::ParamEnv, key: ty::OpaqueTypeKey, - ty: I::Ty, - ) -> Vec> { - // FIXME: Super inefficient to be cloning this... - let opaques = self.delegate.clone_opaque_types_for_query_response(); - - let mut values = vec![]; - for (candidate_key, candidate_ty) in opaques { - if candidate_key.def_id != key.def_id { - continue; - } - values.extend( - self.probe(|result| inspect::ProbeKind::OpaqueTypeStorageLookup { - result: *result, - }) - .enter(|ecx| { - for (a, b) in std::iter::zip(candidate_key.args.iter(), key.args.iter()) { - ecx.eq(param_env, a, b)?; - } - ecx.eq(param_env, candidate_ty, ty)?; - ecx.add_item_bounds_for_hidden_type( - candidate_key.def_id.into(), - candidate_key.args, - param_env, - candidate_ty, - ); - ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) - }), + ) -> Option<(ty::OpaqueTypeKey, I::Ty)> { + let mut matching = + self.delegate.clone_opaque_types_for_query_response().into_iter().filter( + |(candidate_key, _)| { + candidate_key.def_id == key.def_id + && DeepRejectCtxt::relate_rigid_rigid(self.cx()) + .args_may_unify(candidate_key.args, key.args) + }, ); - } - values + let first = matching.next(); + let second = matching.next(); + assert_eq!(second, None); + first } // Try to evaluate a const, or return `None` if the const is too generic. diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs index 6a0703c5313..f8d51f304f3 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs @@ -7,7 +7,9 @@ use rustc_type_ir::inherent::*; use rustc_type_ir::{self as ty, Interner}; use crate::delegate::SolverDelegate; -use crate::solve::{Certainty, EvalCtxt, Goal, NoSolution, QueryResult, Reveal, SolverMode}; +use crate::solve::{ + Certainty, EvalCtxt, Goal, NoSolution, QueryResult, Reveal, SolverMode, inspect, +}; impl EvalCtxt<'_, D> where @@ -52,14 +54,28 @@ where // // If that fails, we insert `expected` as a new hidden type instead of // eagerly emitting an error. - let matches = - self.unify_existing_opaque_tys(goal.param_env, opaque_type_key, expected); - if !matches.is_empty() { - if let Some(response) = self.try_merge_responses(&matches) { - return Ok(response); - } else { - return self.flounder(&matches); - } + let existing = self.probe_existing_opaque_ty(opaque_type_key); + if let Some((candidate_key, candidate_ty)) = existing { + return self + .probe(|result| inspect::ProbeKind::OpaqueTypeStorageLookup { + result: *result, + }) + .enter(|ecx| { + for (a, b) in std::iter::zip( + candidate_key.args.iter(), + opaque_type_key.args.iter(), + ) { + ecx.eq(goal.param_env, a, b)?; + } + ecx.eq(goal.param_env, candidate_ty, expected)?; + ecx.add_item_bounds_for_hidden_type( + candidate_key.def_id.into(), + candidate_key.args, + goal.param_env, + candidate_ty, + ); + ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + }); } // Otherwise, define a new opaque type From 49202c7b479c0f9727b303985a7a6e45ae5379d3 Mon Sep 17 00:00:00 2001 From: DianQK Date: Sat, 12 Oct 2024 21:41:44 +0800 Subject: [PATCH 228/357] Ignore the `download_ci_llvm` test --- src/bootstrap/src/core/config/tests.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/bootstrap/src/core/config/tests.rs b/src/bootstrap/src/core/config/tests.rs index ed89112de90..57d66a49afd 100644 --- a/src/bootstrap/src/core/config/tests.rs +++ b/src/bootstrap/src/core/config/tests.rs @@ -19,6 +19,8 @@ pub(crate) fn parse(config: &str) -> Config { ) } +// FIXME: Resume this test after establishing a stabilized change tracking logic. +#[ignore] #[test] fn download_ci_llvm() { if crate::core::build_steps::llvm::is_ci_llvm_modified(&parse("")) { From 4441a8975096217d877d4a11afb4695ec1c560a2 Mon Sep 17 00:00:00 2001 From: DianQK Date: Wed, 9 Oct 2024 21:54:43 +0800 Subject: [PATCH 229/357] Update LLVM submodule --- src/llvm-project | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/llvm-project b/src/llvm-project index dd46457da78..3a17f74904a 160000 --- a/src/llvm-project +++ b/src/llvm-project @@ -1 +1 @@ -Subproject commit dd46457da782554454106d48ecd4f6b4c2f9af73 +Subproject commit 3a17f74904a74565c54cfac0d67026362d038698 From 1ac72b94bc5e8536e61232125b99dd052ac74b38 Mon Sep 17 00:00:00 2001 From: GnomedDev Date: Sat, 12 Oct 2024 13:43:17 +0100 Subject: [PATCH 230/357] Add ExtractIf for ThinVec --- compiler/rustc_data_structures/src/lib.rs | 1 + compiler/rustc_data_structures/src/thinvec.rs | 92 +++++++++++++++++++ 2 files changed, 93 insertions(+) create mode 100644 compiler/rustc_data_structures/src/thinvec.rs diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index f225684d99f..fba2707922b 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -76,6 +76,7 @@ pub mod svh; pub mod sync; pub mod tagged_ptr; pub mod temp_dir; +pub mod thinvec; pub mod transitive_relation; pub mod unhash; pub mod unord; diff --git a/compiler/rustc_data_structures/src/thinvec.rs b/compiler/rustc_data_structures/src/thinvec.rs new file mode 100644 index 00000000000..e60ac2cbc8b --- /dev/null +++ b/compiler/rustc_data_structures/src/thinvec.rs @@ -0,0 +1,92 @@ +//! This is a copy-paste of `Vec::extract_if` for `ThinVec`. +//! +//! FIXME: is merged, this can be removed. + +use std::{ptr, slice}; + +use thin_vec::ThinVec; + +/// An iterator for [`ThinVec`] which uses a closure to determine if an element should be removed. +#[must_use = "iterators are lazy and do nothing unless consumed"] +pub struct ExtractIf<'a, T, F> { + vec: &'a mut ThinVec, + /// The index of the item that will be inspected by the next call to `next`. + idx: usize, + /// The number of items that have been drained (removed) thus far. + del: usize, + /// The original length of `vec` prior to draining. + old_len: usize, + /// The filter test predicate. + pred: F, +} + +impl<'a, T, F> ExtractIf<'a, T, F> +where + F: FnMut(&mut T) -> bool, +{ + pub fn new(vec: &'a mut ThinVec, filter: F) -> Self { + let old_len = vec.len(); + + // Guard against us getting leaked (leak amplification) + unsafe { + vec.set_len(0); + } + + ExtractIf { vec, idx: 0, del: 0, old_len, pred: filter } + } +} + +impl Iterator for ExtractIf<'_, T, F> +where + F: FnMut(&mut T) -> bool, +{ + type Item = T; + fn next(&mut self) -> Option { + unsafe { + while self.idx < self.old_len { + let i = self.idx; + let v = slice::from_raw_parts_mut(self.vec.as_mut_ptr(), self.old_len); + let drained = (self.pred)(&mut v[i]); + // Update the index *after* the predicate is called. If the index + // is updated prior and the predicate panics, the element at this + // index would be leaked. + self.idx += 1; + if drained { + self.del += 1; + return Some(ptr::read(&v[i])); + } else if self.del > 0 { + let del = self.del; + let src: *const T = &v[i]; + let dst: *mut T = &mut v[i - del]; + ptr::copy_nonoverlapping(src, dst, 1); + } + } + None + } + } + + fn size_hint(&self) -> (usize, Option) { + (0, Some(self.old_len - self.idx)) + } +} + +impl Drop for ExtractIf<'_, A, F> { + fn drop(&mut self) { + unsafe { + if self.idx < self.old_len && self.del > 0 { + // This is a pretty messed up state, and there isn't really an + // obviously right thing to do. We don't want to keep trying + // to execute `pred`, so we just backshift all the unprocessed + // elements and tell the vec that they still exist. The backshift + // is required to prevent a double-drop of the last successfully + // drained item prior to a panic in the predicate. + let ptr = self.vec.as_mut_ptr(); + let src = ptr.add(self.idx); + let dst = src.sub(self.del); + let tail_len = self.old_len - self.idx; + src.copy_to(dst, tail_len); + } + self.vec.set_len(self.old_len - self.del); + } + } +} From 7ec06b0d1d08cbcc6ed2f7e6ae87fe18056f69ef Mon Sep 17 00:00:00 2001 From: GnomedDev Date: Wed, 9 Oct 2024 01:02:55 +0100 Subject: [PATCH 231/357] Swap Vec to type alias --- compiler/rustc_borrowck/src/type_check/mod.rs | 4 +- .../src/obligation_forest/mod.rs | 3 +- compiler/rustc_hir_analysis/src/autoderef.rs | 11 ++-- compiler/rustc_hir_typeck/src/autoderef.rs | 5 +- compiler/rustc_hir_typeck/src/closure.rs | 4 +- compiler/rustc_hir_typeck/src/coercion.rs | 33 +++++----- .../src/fn_ctxt/inspect_obligations.rs | 13 ++-- compiler/rustc_hir_typeck/src/method/mod.rs | 3 +- .../src/infer/canonical/query_response.rs | 7 +- compiler/rustc_infer/src/infer/mod.rs | 10 +-- .../rustc_infer/src/infer/opaque_types/mod.rs | 8 +-- compiler/rustc_infer/src/infer/projection.rs | 4 +- .../rustc_infer/src/infer/relate/lattice.rs | 8 +-- .../src/infer/relate/type_relating.rs | 8 +-- compiler/rustc_infer/src/traits/engine.rs | 10 +-- compiler/rustc_infer/src/traits/mod.rs | 2 + compiler/rustc_infer/src/traits/project.rs | 6 +- .../src/error_reporting/mod.rs | 7 +- .../src/solve/fulfill.rs | 17 ++--- .../src/traits/coherence.rs | 9 +-- .../src/traits/engine.rs | 3 +- .../src/traits/fulfill.rs | 54 +++++++++------ .../rustc_trait_selection/src/traits/mod.rs | 2 +- .../src/traits/normalize.rs | 14 ++-- .../src/traits/outlives_bounds.rs | 2 +- .../src/traits/project.rs | 63 +++++++++--------- .../src/traits/query/normalize.rs | 14 ++-- .../src/traits/query/type_op/mod.rs | 6 +- .../src/traits/select/candidate_assembly.rs | 6 +- .../src/traits/select/confirmation.rs | 65 ++++++++++--------- .../src/traits/select/mod.rs | 20 +++--- .../rustc_trait_selection/src/traits/wf.rs | 39 ++++++----- .../src/normalize_projection_ty.rs | 5 +- 33 files changed, 250 insertions(+), 215 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 82aeca66693..238d7d0749a 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -18,6 +18,7 @@ use rustc_infer::infer::region_constraints::RegionConstraintData; use rustc_infer::infer::{ BoundRegion, BoundRegionConversionTime, InferCtxt, NllRegionVariableOrigin, }; +use rustc_infer::traits::PredicateObligations; use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; @@ -40,7 +41,6 @@ use rustc_span::source_map::Spanned; use rustc_span::symbol::sym; use rustc_span::{DUMMY_SP, Span}; use rustc_target::abi::{FIRST_VARIANT, FieldIdx}; -use rustc_trait_selection::traits::PredicateObligation; use rustc_trait_selection::traits::query::type_op::custom::{ CustomTypeOp, scrape_region_constraints, }; @@ -2940,7 +2940,7 @@ impl NormalizeLocation for Location { pub(super) struct InstantiateOpaqueType<'tcx> { pub base_universe: Option, pub region_constraints: Option>, - pub obligations: Vec>, + pub obligations: PredicateObligations<'tcx>, } impl<'tcx> TypeOp<'tcx> for InstantiateOpaqueType<'tcx> { diff --git a/compiler/rustc_data_structures/src/obligation_forest/mod.rs b/compiler/rustc_data_structures/src/obligation_forest/mod.rs index cfe7dd13e80..aca99b9fab1 100644 --- a/compiler/rustc_data_structures/src/obligation_forest/mod.rs +++ b/compiler/rustc_data_structures/src/obligation_forest/mod.rs @@ -402,9 +402,10 @@ impl ObligationForest { } /// Returns the set of obligations that are in a pending state. - pub fn map_pending_obligations(&self, f: F) -> Vec