From: bors Date: Thu, 31 Dec 2020 09:07:52 +0000 (+0000) Subject: Auto merge of #80267 - 0urobor0s:ouro/61592, r=jyn514 X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=a6bd5246da7806786b5c1f61d05a957c9ae68903;hp=cb4553bdae56b41c295137ab694fab0050f7c29d;p=rust.git Auto merge of #80267 - 0urobor0s:ouro/61592, r=jyn514 Rustdoc render public underscore_imports as Re-exports Fixes #61592 --- diff --git a/.github/ISSUE_TEMPLATE/library_tracking_issue.md b/.github/ISSUE_TEMPLATE/library_tracking_issue.md index b8544e6a4e0..3e42594c828 100644 --- a/.github/ISSUE_TEMPLATE/library_tracking_issue.md +++ b/.github/ISSUE_TEMPLATE/library_tracking_issue.md @@ -2,7 +2,7 @@ name: Library Tracking Issue about: A tracking issue for an unstable library feature. title: Tracking Issue for XXX -labels: C-tracking-issue T-libs +labels: C-tracking-issue, T-libs --- +SpecFromIterNested | -/// |where I: | | |where I: | -/// | Iterator (default)----------+ | | Iterator (default) | -/// | vec::IntoIter | | | TrustedLen | -/// | SourceIterMarker---fallback-+ | | | -/// | slice::Iter | | | -/// | Iterator | +---------------------+ -/// +---------------------------------+ -/// ``` -trait SpecFromIter { - fn from_iter(iter: I) -> Self; -} - -/// Another specialization trait for Vec::from_iter -/// necessary to manually prioritize overlapping specializations -/// see [`SpecFromIter`] for details. -trait SpecFromIterNested { - fn from_iter(iter: I) -> Self; -} - -impl SpecFromIterNested for Vec -where - I: Iterator, -{ - 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 - // empty, but the loop in extend_desugared() is not going to see the - // vector being full in the few subsequent loop iterations. - // So we get better branch prediction. - let mut vector = match iterator.next() { - None => return Vec::new(), - Some(element) => { - let (lower, _) = iterator.size_hint(); - let mut vector = Vec::with_capacity(lower.saturating_add(1)); - unsafe { - ptr::write(vector.as_mut_ptr(), element); - vector.set_len(1); - } - vector - } - }; - // must delegate to spec_extend() since extend() itself delegates - // to spec_from for empty Vecs - as SpecExtend>::spec_extend(&mut vector, iterator); - vector - } -} - -impl SpecFromIterNested for Vec -where - I: TrustedLen, -{ - fn from_iter(iterator: I) -> Self { - let mut vector = match iterator.size_hint() { - (_, Some(upper)) => Vec::with_capacity(upper), - _ => Vec::new(), - }; - // must delegate to spec_extend() since extend() itself delegates - // to spec_from for empty Vecs - vector.spec_extend(iterator); - vector - } -} - -impl SpecFromIter for Vec -where - I: Iterator, -{ - default fn from_iter(iterator: I) -> Self { - SpecFromIterNested::from_iter(iterator) - } -} - -// A helper struct for in-place iteration that drops the destination slice of iteration, -// i.e. the head. The source slice (the tail) is dropped by IntoIter. -struct InPlaceDrop { - inner: *mut T, - dst: *mut T, -} - -impl InPlaceDrop { - fn len(&self) -> usize { - unsafe { self.dst.offset_from(self.inner) as usize } - } -} - -impl Drop for InPlaceDrop { - #[inline] - fn drop(&mut self) { - unsafe { - ptr::drop_in_place(slice::from_raw_parts_mut(self.inner, self.len())); - } - } -} - -impl SpecFromIter> for Vec { - 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 - // has not been advanced at all. - // When it has been advanced We can also reuse the memory and move the data to the front. - // But we only do so when the resulting Vec wouldn't have more unused capacity - // than creating it through the generic FromIterator implementation would. That limitation - // is not strictly necessary as Vec's allocation behavior is intentionally unspecified. - // But it is a conservative choice. - let has_advanced = iterator.buf.as_ptr() as *const _ != iterator.ptr; - if !has_advanced || iterator.len() >= iterator.cap / 2 { - unsafe { - let it = ManuallyDrop::new(iterator); - if has_advanced { - ptr::copy(it.ptr, it.buf.as_ptr(), it.len()); - } - return Vec::from_raw_parts(it.buf.as_ptr(), it.len(), it.cap); - } - } - - let mut vec = Vec::new(); - // must delegate to spec_extend() since extend() itself delegates - // to spec_from for empty Vecs - vec.spec_extend(iterator); - vec - } -} - -fn write_in_place_with_drop( - src_end: *const T, -) -> impl FnMut(InPlaceDrop, T) -> Result, !> { - move |mut sink, item| { - unsafe { - // the InPlaceIterable contract cannot be verified precisely here since - // try_fold has an exclusive reference to the source pointer - // all we can do is check if it's still in range - debug_assert!(sink.dst as *const _ <= src_end, "InPlaceIterable contract violation"); - ptr::write(sink.dst, item); - sink.dst = sink.dst.add(1); - } - Ok(sink) - } -} - -/// Specialization marker for collecting an iterator pipeline into a Vec while reusing the -/// source allocation, i.e. executing the pipeline in place. -/// -/// The SourceIter parent trait is necessary for the specializing function to access the allocation -/// which is to be reused. But it is not sufficient for the specialization to be valid. See -/// additional bounds on the impl. -#[rustc_unsafe_specialization_marker] -trait SourceIterMarker: SourceIter {} - -// The std-internal SourceIter/InPlaceIterable traits are only implemented by chains of -// Adapter>> (all owned by core/std). Additional bounds -// on the adapter implementations (beyond `impl Trait for Adapter`) only depend on other -// traits already marked as specialization traits (Copy, TrustedRandomAccess, FusedIterator). -// I.e. the marker does not depend on lifetimes of user-supplied types. Modulo the Copy hole, which -// several other specializations already depend on. -impl SourceIterMarker for T where T: SourceIter + InPlaceIterable {} - -impl SpecFromIter for Vec -where - I: Iterator + SourceIterMarker, -{ - default fn from_iter(mut iterator: I) -> Self { - // Additional requirements which cannot expressed via trait bounds. We rely on const eval - // instead: - // a) no ZSTs as there would be no allocation to reuse and pointer arithmetic would panic - // b) size match as required by Alloc contract - // c) alignments match as required by Alloc contract - if mem::size_of::() == 0 - || mem::size_of::() - != mem::size_of::<<::Source as AsIntoIter>::Item>() - || mem::align_of::() - != mem::align_of::<<::Source as AsIntoIter>::Item>() - { - // fallback to more generic implementations - return SpecFromIterNested::from_iter(iterator); - } - - let (src_buf, src_ptr, dst_buf, dst_end, cap) = unsafe { - let inner = iterator.as_inner().as_into_iter(); - ( - inner.buf.as_ptr(), - inner.ptr, - inner.buf.as_ptr() as *mut T, - inner.end as *const T, - inner.cap, - ) - }; - - // use try-fold since - // - it vectorizes better for some iterator adapters - // - unlike most internal iteration methods, it only takes a &mut self - // - it lets us thread the write pointer through its innards and get it back in the end - let sink = InPlaceDrop { inner: dst_buf, dst: dst_buf }; - let sink = iterator - .try_fold::<_, _, Result<_, !>>(sink, write_in_place_with_drop(dst_end)) - .unwrap(); - // iteration succeeded, don't drop head - let dst = ManuallyDrop::new(sink).dst; - - let src = unsafe { iterator.as_inner().as_into_iter() }; - // check if SourceIter contract was upheld - // caveat: if they weren't we may not even make it to this point - debug_assert_eq!(src_buf, src.buf.as_ptr()); - // check InPlaceIterable contract. This is only possible if the iterator advanced the - // source pointer at all. If it uses unchecked access via TrustedRandomAccess - // then the source pointer will stay in its initial position and we can't use it as reference - if src.ptr != src_ptr { - debug_assert!( - dst as *const _ <= src.ptr, - "InPlaceIterable contract violation, write pointer advanced beyond read pointer" - ); - } - - // drop any remaining values at the tail of the source - src.drop_remaining(); - // but prevent drop of the allocation itself once IntoIter goes out of scope - src.forget_allocation(); - - let vec = unsafe { - let len = dst.offset_from(dst_buf) as usize; - Vec::from_raw_parts(dst_buf, len, cap) - }; - - vec - } -} - -impl<'a, T: 'a, I> SpecFromIter<&'a T, I> for Vec -where - I: Iterator, - T: Clone, -{ - default fn from_iter(iterator: I) -> Self { - SpecFromIter::from_iter(iterator.cloned()) - } -} - -// This utilizes `iterator.as_slice().to_vec()` since spec_extend -// must take more steps to reason about the final capacity + length -// and thus do more work. `to_vec()` directly allocates the correct amount -// and fills it exactly. -impl<'a, T: 'a + Clone> SpecFromIter<&'a T, slice::Iter<'a, T>> for Vec { - #[cfg(not(test))] - fn from_iter(iterator: slice::Iter<'a, T>) -> Self { - iterator.as_slice().to_vec() - } - - // HACK(japaric): with cfg(test) the inherent `[T]::to_vec` method, which is - // required for this method definition, is not available. Instead use the - // `slice::to_vec` function which is only available with cfg(test) - // NB see the slice::hack module in slice.rs for more information - #[cfg(test)] - fn from_iter(iterator: slice::Iter<'a, T>) -> Self { - crate::slice::to_vec(iterator.as_slice(), Global) - } -} - -// Specialization trait used for Vec::extend -trait SpecExtend { - fn spec_extend(&mut self, iter: I); -} - -impl SpecExtend for Vec -where - I: Iterator, -{ - default fn spec_extend(&mut self, iter: I) { - self.extend_desugared(iter) - } -} - -impl SpecExtend for Vec -where - I: TrustedLen, -{ - default fn spec_extend(&mut self, iterator: I) { - // This is the case for a TrustedLen iterator. - let (low, high) = iterator.size_hint(); - if let Some(high_value) = high { - debug_assert_eq!( - low, - high_value, - "TrustedLen iterator's size hint is not exact: {:?}", - (low, high) - ); - } - if let Some(additional) = high { - self.reserve(additional); - unsafe { - let mut ptr = self.as_mut_ptr().add(self.len()); - let mut local_len = SetLenOnDrop::new(&mut self.len); - iterator.for_each(move |element| { - ptr::write(ptr, element); - ptr = ptr.offset(1); - // NB can't overflow since we would have had to alloc the address space - local_len.increment_len(1); - }); - } - } else { - self.extend_desugared(iterator) - } - } -} - -impl SpecExtend> for Vec { - fn spec_extend(&mut self, mut iterator: IntoIter) { - unsafe { - self.append_elements(iterator.as_slice() as _); - } - iterator.ptr = iterator.end; - } -} - -impl<'a, T: 'a, I, A: Allocator + 'a> SpecExtend<&'a T, I> for Vec -where - I: Iterator, - T: Clone, -{ - default fn spec_extend(&mut self, iterator: I) { - self.spec_extend(iterator.cloned()) - } -} - -impl<'a, T: 'a, A: Allocator + 'a> SpecExtend<&'a T, slice::Iter<'a, T>> for Vec -where - T: Copy, -{ - fn spec_extend(&mut self, iterator: slice::Iter<'a, T>) { - let slice = iterator.as_slice(); - unsafe { self.append_elements(slice) }; - } -} - -impl Vec { - // leaf method to which various SpecFrom/SpecExtend implementations delegate when - // they have no further optimizations to apply - fn extend_desugared>(&mut self, mut iterator: I) { - // This is the case for a general iterator. - // - // This function should be the moral equivalent of: - // - // for item in iterator { - // self.push(item); - // } - while let Some(element) = iterator.next() { - let len = self.len(); - if len == self.capacity() { - let (lower, _) = iterator.size_hint(); - self.reserve(lower.saturating_add(1)); - } - unsafe { - ptr::write(self.as_mut_ptr().add(len), element); - // NB can't overflow since we would have had to alloc the address space - self.set_len(len + 1); - } - } - } - - /// Creates a splicing iterator that replaces the specified range in the vector - /// with the given `replace_with` iterator and yields the removed items. - /// `replace_with` does not need to be the same length as `range`. - /// - /// `range` is removed even if the iterator is not consumed until the end. - /// - /// It is unspecified how many elements are removed from the vector - /// if the `Splice` value is leaked. - /// - /// The input iterator `replace_with` is only consumed when the `Splice` value is dropped. - /// - /// This is optimal if: - /// - /// * The tail (elements in the vector after `range`) is empty, - /// * or `replace_with` yields fewer elements than `range`’s length - /// * or the lower bound of its `size_hint()` is exact. - /// - /// Otherwise, a temporary vector is allocated and the tail is moved twice. - /// - /// # Panics - /// - /// Panics if the starting point is greater than the end point or if - /// the end point is greater than the length of the vector. - /// - /// # Examples - /// - /// ``` - /// let mut v = vec![1, 2, 3]; - /// let new = [7, 8]; - /// let u: Vec<_> = v.splice(..2, new.iter().cloned()).collect(); - /// assert_eq!(v, &[7, 8, 3]); - /// assert_eq!(u, &[1, 2]); - /// ``` - #[inline] - #[stable(feature = "vec_splice", since = "1.21.0")] - pub fn splice(&mut self, range: R, replace_with: I) -> Splice<'_, I::IntoIter, A> - where - R: RangeBounds, - I: IntoIterator, - { - Splice { drain: self.drain(range), replace_with: replace_with.into_iter() } - } - - /// Creates an iterator which uses a closure to determine if an element should be removed. - /// - /// If the closure returns true, then the element is removed and yielded. - /// If the closure returns false, the element will remain in the vector and will not be yielded - /// by the iterator. - /// - /// Using this method is equivalent to the following code: - /// - /// ``` - /// # let some_predicate = |x: &mut i32| { *x == 2 || *x == 3 || *x == 6 }; - /// # let mut vec = vec![1, 2, 3, 4, 5, 6]; - /// let mut i = 0; - /// while i != vec.len() { - /// if some_predicate(&mut vec[i]) { - /// let val = vec.remove(i); - /// // your code here - /// } else { - /// i += 1; - /// } - /// } - /// - /// # assert_eq!(vec, vec![1, 4, 5]); - /// ``` - /// - /// But `drain_filter` is easier to use. `drain_filter` is also more efficient, - /// because it can backshift the elements of the array in bulk. - /// - /// Note that `drain_filter` also lets you mutate every element in the filter closure, - /// regardless of whether you choose to keep or remove it. - /// - /// # Examples - /// - /// Splitting an array into evens and odds, reusing the original allocation: - /// - /// ``` - /// #![feature(drain_filter)] - /// let mut numbers = vec![1, 2, 3, 4, 5, 6, 8, 9, 11, 13, 14, 15]; - /// - /// let evens = numbers.drain_filter(|x| *x % 2 == 0).collect::>(); - /// let odds = numbers; - /// - /// assert_eq!(evens, vec![2, 4, 6, 8, 14]); - /// assert_eq!(odds, vec![1, 3, 5, 9, 11, 13, 15]); - /// ``` - #[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] - pub fn drain_filter(&mut self, filter: F) -> DrainFilter<'_, T, F, A> - where - F: FnMut(&mut T) -> bool, - { - let old_len = self.len(); - - // Guard against us getting leaked (leak amplification) - unsafe { - self.set_len(0); - } - - DrainFilter { vec: self, idx: 0, del: 0, old_len, pred: filter, panic_flag: false } - } -} - -/// Extend implementation that copies elements out of references before pushing them onto the Vec. -/// -/// This implementation is specialized for slice iterators, where it uses [`copy_from_slice`] to -/// append the entire slice at once. -/// -/// [`copy_from_slice`]: ../../std/primitive.slice.html#method.copy_from_slice -#[stable(feature = "extend_ref", since = "1.2.0")] -impl<'a, T: Copy + 'a, A: Allocator + 'a> Extend<&'a T> for Vec { - fn extend>(&mut self, iter: I) { - self.spec_extend(iter.into_iter()) - } - - #[inline] - fn extend_one(&mut self, &item: &'a T) { - self.push(item); - } - - #[inline] - fn extend_reserve(&mut self, additional: usize) { - self.reserve(additional); - } -} - -macro_rules! __impl_slice_eq1 { - ([$($vars:tt)*] $lhs:ty, $rhs:ty $(where $ty:ty: $bound:ident)?, #[$stability:meta]) => { - #[$stability] - impl PartialEq<$rhs> for $lhs - where - T: PartialEq, - $($ty: $bound)? - { - #[inline] - fn eq(&self, other: &$rhs) -> bool { self[..] == other[..] } - #[inline] - fn ne(&self, other: &$rhs) -> bool { self[..] != other[..] } - } - } -} - -__impl_slice_eq1! { [A: Allocator] Vec, Vec, #[stable(feature = "rust1", since = "1.0.0")] } -__impl_slice_eq1! { [A: Allocator] Vec, &[U], #[stable(feature = "rust1", since = "1.0.0")] } -__impl_slice_eq1! { [A: Allocator] Vec, &mut [U], #[stable(feature = "rust1", since = "1.0.0")] } -__impl_slice_eq1! { [A: Allocator] &[T], Vec, #[stable(feature = "partialeq_vec_for_ref_slice", since = "1.46.0")] } -__impl_slice_eq1! { [A: Allocator] &mut [T], Vec, #[stable(feature = "partialeq_vec_for_ref_slice", since = "1.46.0")] } -__impl_slice_eq1! { [A: Allocator] Vec, [U], #[stable(feature = "partialeq_vec_for_slice", since = "1.48.0")] } -__impl_slice_eq1! { [A: Allocator] [T], Vec, #[stable(feature = "partialeq_vec_for_slice", since = "1.48.0")] } -__impl_slice_eq1! { [A: Allocator] Cow<'_, [T]>, Vec where T: Clone, #[stable(feature = "rust1", since = "1.0.0")] } -__impl_slice_eq1! { [] Cow<'_, [T]>, &[U] where T: Clone, #[stable(feature = "rust1", since = "1.0.0")] } -__impl_slice_eq1! { [] Cow<'_, [T]>, &mut [U] where T: Clone, #[stable(feature = "rust1", since = "1.0.0")] } -__impl_slice_eq1! { [A: Allocator, const N: usize] Vec, [U; N], #[stable(feature = "rust1", since = "1.0.0")] } -__impl_slice_eq1! { [A: Allocator, const N: usize] Vec, &[U; N], #[stable(feature = "rust1", since = "1.0.0")] } - -// NOTE: some less important impls are omitted to reduce code bloat -// FIXME(Centril): Reconsider this? -//__impl_slice_eq1! { [const N: usize] Vec, &mut [B; N], } -//__impl_slice_eq1! { [const N: usize] [A; N], Vec, } -//__impl_slice_eq1! { [const N: usize] &[A; N], Vec, } -//__impl_slice_eq1! { [const N: usize] &mut [A; N], Vec, } -//__impl_slice_eq1! { [const N: usize] Cow<'a, [A]>, [B; N], } -//__impl_slice_eq1! { [const N: usize] Cow<'a, [A]>, &[B; N], } -//__impl_slice_eq1! { [const N: usize] Cow<'a, [A]>, &mut [B; N], } - -/// Implements comparison of vectors, [lexicographically](core::cmp::Ord#lexicographical-comparison). -#[stable(feature = "rust1", since = "1.0.0")] -impl PartialOrd for Vec { - #[inline] - fn partial_cmp(&self, other: &Self) -> Option { - PartialOrd::partial_cmp(&**self, &**other) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl Eq for Vec {} - -/// Implements ordering of vectors, [lexicographically](core::cmp::Ord#lexicographical-comparison). -#[stable(feature = "rust1", since = "1.0.0")] -impl Ord for Vec { - #[inline] - fn cmp(&self, other: &Self) -> Ordering { - Ord::cmp(&**self, &**other) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -unsafe impl<#[may_dangle] T, A: Allocator> Drop for Vec { - fn drop(&mut self) { - unsafe { - // use drop for [T] - // use a raw slice to refer to the elements of the vector as weakest necessary type; - // could avoid questions of validity in certain cases - ptr::drop_in_place(ptr::slice_from_raw_parts_mut(self.as_mut_ptr(), self.len)) - } - // RawVec handles deallocation - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl Default for Vec { - /// Creates an empty `Vec`. - fn default() -> Vec { - Vec::new() - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Debug for Vec { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Debug::fmt(&**self, f) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl AsRef> for Vec { - fn as_ref(&self) -> &Vec { - self - } -} - -#[stable(feature = "vec_as_mut", since = "1.5.0")] -impl AsMut> for Vec { - fn as_mut(&mut self) -> &mut Vec { - self - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl AsRef<[T]> for Vec { - fn as_ref(&self) -> &[T] { - self - } -} - -#[stable(feature = "vec_as_mut", since = "1.5.0")] -impl AsMut<[T]> for Vec { - fn as_mut(&mut self) -> &mut [T] { - self - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl From<&[T]> for Vec { - #[cfg(not(test))] - fn from(s: &[T]) -> Vec { - s.to_vec() - } - #[cfg(test)] - fn from(s: &[T]) -> Vec { - crate::slice::to_vec(s, Global) - } -} - -#[stable(feature = "vec_from_mut", since = "1.19.0")] -impl From<&mut [T]> for Vec { - #[cfg(not(test))] - fn from(s: &mut [T]) -> Vec { - s.to_vec() - } - #[cfg(test)] - fn from(s: &mut [T]) -> Vec { - crate::slice::to_vec(s, Global) - } -} - -#[stable(feature = "vec_from_array", since = "1.44.0")] -impl From<[T; N]> for Vec { - #[cfg(not(test))] - fn from(s: [T; N]) -> Vec { - <[T]>::into_vec(box s) - } - #[cfg(test)] - fn from(s: [T; N]) -> Vec { - crate::slice::into_vec(box s) - } -} - -#[stable(feature = "vec_from_cow_slice", since = "1.14.0")] -impl<'a, T> From> for Vec -where - [T]: ToOwned>, -{ - fn from(s: Cow<'a, [T]>) -> Vec { - s.into_owned() - } -} - -// note: test pulls in libstd, which causes errors here -#[cfg(not(test))] -#[stable(feature = "vec_from_box", since = "1.18.0")] -impl From> for Vec { - fn from(s: Box<[T], A>) -> Self { - let len = s.len(); - Self { buf: RawVec::from_box(s), len } - } -} - -// note: test pulls in libstd, which causes errors here -#[cfg(not(test))] -#[stable(feature = "box_from_vec", since = "1.20.0")] -impl From> for Box<[T], A> { - fn from(v: Vec) -> Self { - v.into_boxed_slice() - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl From<&str> for Vec { - fn from(s: &str) -> Vec { - From::from(s.as_bytes()) - } -} - -#[stable(feature = "array_try_from_vec", since = "1.48.0")] -impl TryFrom> for [T; N] { - type Error = Vec; - - /// Gets the entire contents of the `Vec` as an array, - /// if its size exactly matches that of the requested array. - /// - /// # Examples - /// - /// ``` - /// use std::convert::TryInto; - /// assert_eq!(vec![1, 2, 3].try_into(), Ok([1, 2, 3])); - /// assert_eq!(>::new().try_into(), Ok([])); - /// ``` - /// - /// If the length doesn't match, the input comes back in `Err`: - /// ``` - /// use std::convert::TryInto; - /// let r: Result<[i32; 4], _> = (0..10).collect::>().try_into(); - /// assert_eq!(r, Err(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9])); - /// ``` - /// - /// If you're fine with just getting a prefix of the `Vec`, - /// you can call [`.truncate(N)`](Vec::truncate) first. - /// ``` - /// use std::convert::TryInto; - /// let mut v = String::from("hello world").into_bytes(); - /// v.sort(); - /// v.truncate(2); - /// let [a, b]: [_; 2] = v.try_into().unwrap(); - /// assert_eq!(a, b' '); - /// assert_eq!(b, b'd'); - /// ``` - fn try_from(mut vec: Vec) -> Result<[T; N], Vec> { - if vec.len() != N { - return Err(vec); - } - - // SAFETY: `.set_len(0)` is always sound. - unsafe { vec.set_len(0) }; - - // SAFETY: A `Vec`'s pointer is always aligned properly, and - // the alignment the array needs is the same as the items. - // We checked earlier that we have sufficient items. - // The items will not double-drop as the `set_len` - // tells the `Vec` not to also drop them. - let array = unsafe { ptr::read(vec.as_ptr() as *const [T; N]) }; - Ok(array) - } -} - -//////////////////////////////////////////////////////////////////////////////// -// Clone-on-write -//////////////////////////////////////////////////////////////////////////////// - -#[stable(feature = "cow_from_vec", since = "1.8.0")] -impl<'a, T: Clone> From<&'a [T]> for Cow<'a, [T]> { - fn from(s: &'a [T]) -> Cow<'a, [T]> { - Cow::Borrowed(s) - } -} - -#[stable(feature = "cow_from_vec", since = "1.8.0")] -impl<'a, T: Clone> From> for Cow<'a, [T]> { - fn from(v: Vec) -> Cow<'a, [T]> { - Cow::Owned(v) - } -} - -#[stable(feature = "cow_from_vec_ref", since = "1.28.0")] -impl<'a, T: Clone> From<&'a Vec> for Cow<'a, [T]> { - fn from(v: &'a Vec) -> Cow<'a, [T]> { - Cow::Borrowed(v.as_slice()) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T> FromIterator for Cow<'a, [T]> -where - T: Clone, -{ - fn from_iter>(it: I) -> Cow<'a, [T]> { - Cow::Owned(FromIterator::from_iter(it)) - } -} - -//////////////////////////////////////////////////////////////////////////////// -// Iterators -//////////////////////////////////////////////////////////////////////////////// - -/// An iterator that moves out of a vector. -/// -/// This `struct` is created by the `into_iter` method on [`Vec`] (provided -/// by the [`IntoIterator`] trait). -/// -/// # Example -/// -/// ``` -/// let v = vec![0, 1, 2]; -/// let iter: std::vec::IntoIter<_> = v.into_iter(); -/// ``` -#[stable(feature = "rust1", since = "1.0.0")] -pub struct IntoIter< - T, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, -> { - buf: NonNull, - phantom: PhantomData, - cap: usize, - alloc: A, - ptr: *const T, - end: *const T, -} - -#[stable(feature = "vec_intoiter_debug", since = "1.13.0")] -impl fmt::Debug for IntoIter { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_tuple("IntoIter").field(&self.as_slice()).finish() - } -} - -impl IntoIter { - /// Returns the remaining items of this iterator as a slice. - /// - /// # Examples - /// - /// ``` - /// let vec = vec!['a', 'b', 'c']; - /// let mut into_iter = vec.into_iter(); - /// assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']); - /// let _ = into_iter.next().unwrap(); - /// assert_eq!(into_iter.as_slice(), &['b', 'c']); - /// ``` - #[stable(feature = "vec_into_iter_as_slice", since = "1.15.0")] - pub fn as_slice(&self) -> &[T] { - unsafe { slice::from_raw_parts(self.ptr, self.len()) } - } - - /// Returns the remaining items of this iterator as a mutable slice. - /// - /// # Examples - /// - /// ``` - /// let vec = vec!['a', 'b', 'c']; - /// let mut into_iter = vec.into_iter(); - /// assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']); - /// into_iter.as_mut_slice()[2] = 'z'; - /// assert_eq!(into_iter.next().unwrap(), 'a'); - /// assert_eq!(into_iter.next().unwrap(), 'b'); - /// assert_eq!(into_iter.next().unwrap(), 'z'); - /// ``` - #[stable(feature = "vec_into_iter_as_slice", since = "1.15.0")] - pub fn as_mut_slice(&mut self) -> &mut [T] { - unsafe { &mut *self.as_raw_mut_slice() } - } - - /// Returns a reference to the underlying allocator. - #[unstable(feature = "allocator_api", issue = "32838")] - #[inline] - pub fn allocator(&self) -> &A { - &self.alloc - } - - fn as_raw_mut_slice(&mut self) -> *mut [T] { - ptr::slice_from_raw_parts_mut(self.ptr as *mut T, self.len()) - } - - fn drop_remaining(&mut self) { - unsafe { - ptr::drop_in_place(self.as_mut_slice()); - } - self.ptr = self.end; - } - - /// Relinquishes the backing allocation, equivalent to - /// `ptr::write(&mut self, Vec::new().into_iter())` - fn forget_allocation(&mut self) { - self.cap = 0; - self.buf = unsafe { NonNull::new_unchecked(RawVec::NEW.ptr()) }; - self.ptr = self.buf.as_ptr(); - self.end = self.buf.as_ptr(); - } -} - -#[stable(feature = "vec_intoiter_as_ref", since = "1.46.0")] -impl AsRef<[T]> for IntoIter { - fn as_ref(&self) -> &[T] { - self.as_slice() - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -unsafe impl Send for IntoIter {} -#[stable(feature = "rust1", since = "1.0.0")] -unsafe impl Sync for IntoIter {} - -#[stable(feature = "rust1", since = "1.0.0")] -impl Iterator for IntoIter { - type Item = T; - - #[inline] - fn next(&mut self) -> Option { - if self.ptr as *const _ == self.end { - None - } else if mem::size_of::() == 0 { - // purposefully don't use 'ptr.offset' because for - // vectors with 0-size elements this would return the - // same pointer. - self.ptr = unsafe { arith_offset(self.ptr as *const i8, 1) as *mut T }; - - // Make up a value of this ZST. - Some(unsafe { mem::zeroed() }) - } else { - let old = self.ptr; - self.ptr = unsafe { self.ptr.offset(1) }; - - Some(unsafe { ptr::read(old) }) - } - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - let exact = if mem::size_of::() == 0 { - (self.end as usize).wrapping_sub(self.ptr as usize) - } else { - unsafe { self.end.offset_from(self.ptr) as usize } - }; - (exact, Some(exact)) - } - - #[inline] - fn count(self) -> usize { - self.len() - } - - unsafe fn __iterator_get_unchecked(&mut self, i: usize) -> Self::Item - where - Self: TrustedRandomAccess, - { - // SAFETY: the caller must guarantee that `i` is in bounds of the - // `Vec`, so `i` cannot overflow an `isize`, and the `self.ptr.add(i)` - // is guaranteed to pointer to an element of the `Vec` and - // thus guaranteed to be valid to dereference. - // - // Also note the implementation of `Self: TrustedRandomAccess` requires - // that `T: Copy` so reading elements from the buffer doesn't invalidate - // them for `Drop`. - unsafe { - if mem::size_of::() == 0 { mem::zeroed() } else { ptr::read(self.ptr.add(i)) } - } - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl DoubleEndedIterator for IntoIter { - #[inline] - fn next_back(&mut self) -> Option { - if self.end == self.ptr { - None - } else if mem::size_of::() == 0 { - // See above for why 'ptr.offset' isn't used - self.end = unsafe { arith_offset(self.end as *const i8, -1) as *mut T }; - - // Make up a value of this ZST. - Some(unsafe { mem::zeroed() }) - } else { - self.end = unsafe { self.end.offset(-1) }; - - Some(unsafe { ptr::read(self.end) }) - } - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for IntoIter { - fn is_empty(&self) -> bool { - self.ptr == self.end - } -} - -#[stable(feature = "fused", since = "1.26.0")] -impl FusedIterator for IntoIter {} - -#[unstable(feature = "trusted_len", issue = "37572")] -unsafe impl TrustedLen for IntoIter {} - -#[doc(hidden)] -#[unstable(issue = "none", feature = "std_internals")] -// T: Copy as approximation for !Drop since get_unchecked does not advance self.ptr -// and thus we can't implement drop-handling -unsafe impl TrustedRandomAccess for IntoIter -where - T: Copy, -{ - fn may_have_side_effect() -> bool { - false - } -} - -#[stable(feature = "vec_into_iter_clone", since = "1.8.0")] -impl Clone for IntoIter { - #[cfg(not(test))] - fn clone(&self) -> Self { - self.as_slice().to_vec_in(self.alloc.clone()).into_iter() - } - #[cfg(test)] - fn clone(&self) -> Self { - crate::slice::to_vec(self.as_slice(), self.alloc.clone()).into_iter() - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -unsafe impl<#[may_dangle] T, A: Allocator> Drop for IntoIter { - fn drop(&mut self) { - struct DropGuard<'a, T, A: Allocator>(&'a mut IntoIter); - - impl Drop for DropGuard<'_, T, A> { - fn drop(&mut self) { - unsafe { - // `IntoIter::alloc` is not used anymore after this - let alloc = ptr::read(&self.0.alloc); - // RawVec handles deallocation - let _ = RawVec::from_raw_parts_in(self.0.buf.as_ptr(), self.0.cap, alloc); - } - } - } - - let guard = DropGuard(self); - // destroy the remaining elements - unsafe { - ptr::drop_in_place(guard.0.as_raw_mut_slice()); - } - // now `guard` will be dropped and do the rest - } -} - -#[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl InPlaceIterable for IntoIter {} - -#[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl SourceIter for IntoIter { - type Source = Self; - - #[inline] - unsafe fn as_inner(&mut self) -> &mut Self::Source { - self - } -} - -// internal helper trait for in-place iteration specialization. -#[rustc_specialization_trait] -pub(crate) trait AsIntoIter { - type Item; - fn as_into_iter(&mut self) -> &mut IntoIter; -} - -impl AsIntoIter for IntoIter { - type Item = T; - - fn as_into_iter(&mut self) -> &mut IntoIter { - self - } -} - -/// A draining iterator for `Vec`. -/// -/// This `struct` is created by [`Vec::drain`]. -/// See its documentation for more. -/// -/// # Example -/// -/// ``` -/// let mut v = vec![0, 1, 2]; -/// let iter: std::vec::Drain<_> = v.drain(..); -/// ``` -#[stable(feature = "drain", since = "1.6.0")] -pub struct Drain< - 'a, - T: 'a, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + 'a = Global, -> { - /// Index of tail to preserve - tail_start: usize, - /// Length of tail - tail_len: usize, - /// Current remaining range to remove - iter: slice::Iter<'a, T>, - vec: NonNull>, -} - -#[stable(feature = "collection_debug", since = "1.17.0")] -impl fmt::Debug for Drain<'_, T, A> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_tuple("Drain").field(&self.iter.as_slice()).finish() - } -} - -impl<'a, T, A: Allocator> Drain<'a, T, A> { - /// Returns the remaining items of this iterator as a slice. - /// - /// # Examples - /// - /// ``` - /// let mut vec = vec!['a', 'b', 'c']; - /// let mut drain = vec.drain(..); - /// assert_eq!(drain.as_slice(), &['a', 'b', 'c']); - /// let _ = drain.next().unwrap(); - /// assert_eq!(drain.as_slice(), &['b', 'c']); - /// ``` - #[stable(feature = "vec_drain_as_slice", since = "1.46.0")] - pub fn as_slice(&self) -> &[T] { - self.iter.as_slice() - } - - /// Returns a reference to the underlying allocator. - #[unstable(feature = "allocator_api", issue = "32838")] - #[inline] - pub fn allocator(&self) -> &A { - unsafe { self.vec.as_ref().allocator() } - } -} - -#[stable(feature = "vec_drain_as_slice", since = "1.46.0")] -impl<'a, T, A: Allocator> AsRef<[T]> for Drain<'a, T, A> { - fn as_ref(&self) -> &[T] { - self.as_slice() - } -} - -#[stable(feature = "drain", since = "1.6.0")] -unsafe impl Sync for Drain<'_, T, A> {} -#[stable(feature = "drain", since = "1.6.0")] -unsafe impl Send for Drain<'_, T, A> {} - -#[stable(feature = "drain", since = "1.6.0")] -impl Iterator for Drain<'_, T, A> { - type Item = T; - - #[inline] - fn next(&mut self) -> Option { - self.iter.next().map(|elt| unsafe { ptr::read(elt as *const _) }) - } - - fn size_hint(&self) -> (usize, Option) { - self.iter.size_hint() - } -} - -#[stable(feature = "drain", since = "1.6.0")] -impl DoubleEndedIterator for Drain<'_, T, A> { - #[inline] - fn next_back(&mut self) -> Option { - self.iter.next_back().map(|elt| unsafe { ptr::read(elt as *const _) }) - } -} - -#[stable(feature = "drain", since = "1.6.0")] -impl Drop for Drain<'_, T, A> { - fn drop(&mut self) { - /// Continues dropping the remaining elements in the `Drain`, then moves back the - /// un-`Drain`ed elements to restore the original `Vec`. - struct DropGuard<'r, 'a, T, A: Allocator>(&'r mut Drain<'a, T, A>); - - impl<'r, 'a, T, A: Allocator> Drop for DropGuard<'r, 'a, T, A> { - fn drop(&mut self) { - // Continue the same loop we have below. If the loop already finished, this does - // nothing. - self.0.for_each(drop); - - if self.0.tail_len > 0 { - unsafe { - let source_vec = self.0.vec.as_mut(); - // memmove back untouched tail, update to new length - let start = source_vec.len(); - let tail = self.0.tail_start; - if tail != start { - let src = source_vec.as_ptr().add(tail); - let dst = source_vec.as_mut_ptr().add(start); - ptr::copy(src, dst, self.0.tail_len); - } - source_vec.set_len(start + self.0.tail_len); - } - } - } - } - - // exhaust self first - while let Some(item) = self.next() { - let guard = DropGuard(self); - drop(item); - mem::forget(guard); - } - - // Drop a `DropGuard` to move back the non-drained tail of `self`. - DropGuard(self); - } -} - -#[stable(feature = "drain", since = "1.6.0")] -impl ExactSizeIterator for Drain<'_, T, A> { - fn is_empty(&self) -> bool { - self.iter.is_empty() - } -} - -#[unstable(feature = "trusted_len", issue = "37572")] -unsafe impl TrustedLen for Drain<'_, T, A> {} - -#[stable(feature = "fused", since = "1.26.0")] -impl FusedIterator for Drain<'_, T, A> {} - -/// A splicing iterator for `Vec`. -/// -/// This struct is created by [`Vec::splice()`]. -/// See its documentation for more. -/// -/// # Example -/// -/// ``` -/// let mut v = vec![0, 1, 2]; -/// let new = [7, 8]; -/// let iter: std::vec::Splice<_> = v.splice(1.., new.iter().cloned()); -/// ``` -#[derive(Debug)] -#[stable(feature = "vec_splice", since = "1.21.0")] -pub struct Splice< - 'a, - I: Iterator + 'a, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + 'a = Global, -> { - drain: Drain<'a, I::Item, A>, - replace_with: I, -} - -#[stable(feature = "vec_splice", since = "1.21.0")] -impl Iterator for Splice<'_, I, A> { - type Item = I::Item; - - fn next(&mut self) -> Option { - self.drain.next() - } - - fn size_hint(&self) -> (usize, Option) { - self.drain.size_hint() - } -} - -#[stable(feature = "vec_splice", since = "1.21.0")] -impl DoubleEndedIterator for Splice<'_, I, A> { - fn next_back(&mut self) -> Option { - self.drain.next_back() - } -} - -#[stable(feature = "vec_splice", since = "1.21.0")] -impl ExactSizeIterator for Splice<'_, I, A> {} - -#[stable(feature = "vec_splice", since = "1.21.0")] -impl Drop for Splice<'_, I, A> { - fn drop(&mut self) { - self.drain.by_ref().for_each(drop); - - unsafe { - if self.drain.tail_len == 0 { - self.drain.vec.as_mut().extend(self.replace_with.by_ref()); - return; - } - - // First fill the range left by drain(). - if !self.drain.fill(&mut self.replace_with) { - return; - } - - // There may be more elements. Use the lower bound as an estimate. - // FIXME: Is the upper bound a better guess? Or something else? - let (lower_bound, _upper_bound) = self.replace_with.size_hint(); - if lower_bound > 0 { - self.drain.move_tail(lower_bound); - if !self.drain.fill(&mut self.replace_with) { - return; - } - } - - // Collect any remaining elements. - // This is a zero-length vector which does not allocate if `lower_bound` was exact. - let mut collected = self.replace_with.by_ref().collect::>().into_iter(); - // Now we have an exact count. - if collected.len() > 0 { - self.drain.move_tail(collected.len()); - let filled = self.drain.fill(&mut collected); - debug_assert!(filled); - debug_assert_eq!(collected.len(), 0); - } - } - // Let `Drain::drop` move the tail back if necessary and restore `vec.len`. - } -} - -/// Private helper methods for `Splice::drop` -impl Drain<'_, T, A> { - /// The range from `self.vec.len` to `self.tail_start` contains elements - /// that have been moved out. - /// Fill that range as much as possible with new elements from the `replace_with` iterator. - /// Returns `true` if we filled the entire range. (`replace_with.next()` didn’t return `None`.) - unsafe fn fill>(&mut self, replace_with: &mut I) -> bool { - let vec = unsafe { self.vec.as_mut() }; - let range_start = vec.len; - let range_end = self.tail_start; - let range_slice = unsafe { - slice::from_raw_parts_mut(vec.as_mut_ptr().add(range_start), range_end - range_start) - }; - - for place in range_slice { - if let Some(new_item) = replace_with.next() { - unsafe { ptr::write(place, new_item) }; - vec.len += 1; - } else { - return false; - } - } - true - } - - /// Makes room for inserting more elements before the tail. - unsafe fn move_tail(&mut self, additional: usize) { - let vec = unsafe { self.vec.as_mut() }; - let len = self.tail_start + self.tail_len; - vec.buf.reserve(len, additional); - - let new_tail_start = self.tail_start + additional; - unsafe { - let src = vec.as_ptr().add(self.tail_start); - let dst = vec.as_mut_ptr().add(new_tail_start); - ptr::copy(src, dst, self.tail_len); - } - self.tail_start = new_tail_start; - } -} - -/// An iterator which uses a closure to determine if an element should be removed. -/// -/// This struct is created by [`Vec::drain_filter`]. -/// See its documentation for more. -/// -/// # Example -/// -/// ``` -/// #![feature(drain_filter)] -/// -/// let mut v = vec![0, 1, 2]; -/// let iter: std::vec::DrainFilter<_, _> = v.drain_filter(|x| *x % 2 == 0); -/// ``` -#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] -#[derive(Debug)] -pub struct DrainFilter< - 'a, - T, - F, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, -> where - F: FnMut(&mut T) -> bool, -{ - vec: &'a mut Vec, - /// 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, - /// A flag that indicates a panic has occurred in the filter test predicate. - /// This is used as a hint in the drop implementation to prevent consumption - /// of the remainder of the `DrainFilter`. Any unprocessed items will be - /// backshifted in the `vec`, but no further items will be dropped or - /// tested by the filter predicate. - panic_flag: bool, -} - -impl DrainFilter<'_, T, F, A> -where - F: FnMut(&mut T) -> bool, -{ - /// Returns a reference to the underlying allocator. - #[unstable(feature = "allocator_api", issue = "32838")] - #[inline] - pub fn allocator(&self) -> &A { - self.vec.allocator() - } -} - -#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] -impl Iterator for DrainFilter<'_, T, F, A> -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); - self.panic_flag = true; - let drained = (self.pred)(&mut v[i]); - self.panic_flag = false; - // 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)) - } -} - -#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] -impl Drop for DrainFilter<'_, T, F, A> -where - F: FnMut(&mut T) -> bool, -{ - fn drop(&mut self) { - struct BackshiftOnDrop<'a, 'b, T, F, A: Allocator> - where - F: FnMut(&mut T) -> bool, - { - drain: &'b mut DrainFilter<'a, T, F, A>, - } - - impl<'a, 'b, T, F, A: Allocator> Drop for BackshiftOnDrop<'a, 'b, T, F, A> - where - F: FnMut(&mut T) -> bool, - { - fn drop(&mut self) { - unsafe { - if self.drain.idx < self.drain.old_len && self.drain.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.drain.vec.as_mut_ptr(); - let src = ptr.add(self.drain.idx); - let dst = src.sub(self.drain.del); - let tail_len = self.drain.old_len - self.drain.idx; - src.copy_to(dst, tail_len); - } - self.drain.vec.set_len(self.drain.old_len - self.drain.del); - } - } - } - - let backshift = BackshiftOnDrop { drain: self }; - - // Attempt to consume any remaining elements if the filter predicate - // has not yet panicked. We'll backshift any remaining elements - // whether we've already panicked or if the consumption here panics. - if !backshift.drain.panic_flag { - backshift.drain.for_each(drop); - } - } -} diff --git a/library/alloc/src/vec/cow.rs b/library/alloc/src/vec/cow.rs new file mode 100644 index 00000000000..73d15d30647 --- /dev/null +++ b/library/alloc/src/vec/cow.rs @@ -0,0 +1,35 @@ +use crate::borrow::Cow; +use core::iter::FromIterator; + +use super::Vec; + +#[stable(feature = "cow_from_vec", since = "1.8.0")] +impl<'a, T: Clone> From<&'a [T]> for Cow<'a, [T]> { + fn from(s: &'a [T]) -> Cow<'a, [T]> { + Cow::Borrowed(s) + } +} + +#[stable(feature = "cow_from_vec", since = "1.8.0")] +impl<'a, T: Clone> From> for Cow<'a, [T]> { + fn from(v: Vec) -> Cow<'a, [T]> { + Cow::Owned(v) + } +} + +#[stable(feature = "cow_from_vec_ref", since = "1.28.0")] +impl<'a, T: Clone> From<&'a Vec> for Cow<'a, [T]> { + fn from(v: &'a Vec) -> Cow<'a, [T]> { + Cow::Borrowed(v.as_slice()) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T> FromIterator for Cow<'a, [T]> +where + T: Clone, +{ + fn from_iter>(it: I) -> Cow<'a, [T]> { + Cow::Owned(FromIterator::from_iter(it)) + } +} diff --git a/library/alloc/src/vec/drain.rs b/library/alloc/src/vec/drain.rs new file mode 100644 index 00000000000..fb32d144f87 --- /dev/null +++ b/library/alloc/src/vec/drain.rs @@ -0,0 +1,155 @@ +use crate::alloc::{Allocator, Global}; +use core::fmt; +use core::iter::{FusedIterator, TrustedLen}; +use core::mem::{self}; +use core::ptr::{self, NonNull}; +use core::slice::{self}; + +use super::Vec; + +/// A draining iterator for `Vec`. +/// +/// This `struct` is created by [`Vec::drain`]. +/// See its documentation for more. +/// +/// # Example +/// +/// ``` +/// let mut v = vec![0, 1, 2]; +/// let iter: std::vec::Drain<_> = v.drain(..); +/// ``` +#[stable(feature = "drain", since = "1.6.0")] +pub struct Drain< + 'a, + T: 'a, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + 'a = Global, +> { + /// Index of tail to preserve + pub(super) tail_start: usize, + /// Length of tail + pub(super) tail_len: usize, + /// Current remaining range to remove + pub(super) iter: slice::Iter<'a, T>, + pub(super) vec: NonNull>, +} + +#[stable(feature = "collection_debug", since = "1.17.0")] +impl fmt::Debug for Drain<'_, T, A> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("Drain").field(&self.iter.as_slice()).finish() + } +} + +impl<'a, T, A: Allocator> Drain<'a, T, A> { + /// Returns the remaining items of this iterator as a slice. + /// + /// # Examples + /// + /// ``` + /// let mut vec = vec!['a', 'b', 'c']; + /// let mut drain = vec.drain(..); + /// assert_eq!(drain.as_slice(), &['a', 'b', 'c']); + /// let _ = drain.next().unwrap(); + /// assert_eq!(drain.as_slice(), &['b', 'c']); + /// ``` + #[stable(feature = "vec_drain_as_slice", since = "1.46.0")] + pub fn as_slice(&self) -> &[T] { + self.iter.as_slice() + } + + /// Returns a reference to the underlying allocator. + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline] + pub fn allocator(&self) -> &A { + unsafe { self.vec.as_ref().allocator() } + } +} + +#[stable(feature = "vec_drain_as_slice", since = "1.46.0")] +impl<'a, T, A: Allocator> AsRef<[T]> for Drain<'a, T, A> { + fn as_ref(&self) -> &[T] { + self.as_slice() + } +} + +#[stable(feature = "drain", since = "1.6.0")] +unsafe impl Sync for Drain<'_, T, A> {} +#[stable(feature = "drain", since = "1.6.0")] +unsafe impl Send for Drain<'_, T, A> {} + +#[stable(feature = "drain", since = "1.6.0")] +impl Iterator for Drain<'_, T, A> { + type Item = T; + + #[inline] + fn next(&mut self) -> Option { + self.iter.next().map(|elt| unsafe { ptr::read(elt as *const _) }) + } + + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} + +#[stable(feature = "drain", since = "1.6.0")] +impl DoubleEndedIterator for Drain<'_, T, A> { + #[inline] + fn next_back(&mut self) -> Option { + self.iter.next_back().map(|elt| unsafe { ptr::read(elt as *const _) }) + } +} + +#[stable(feature = "drain", since = "1.6.0")] +impl Drop for Drain<'_, T, A> { + fn drop(&mut self) { + /// Continues dropping the remaining elements in the `Drain`, then moves back the + /// un-`Drain`ed elements to restore the original `Vec`. + struct DropGuard<'r, 'a, T, A: Allocator>(&'r mut Drain<'a, T, A>); + + impl<'r, 'a, T, A: Allocator> Drop for DropGuard<'r, 'a, T, A> { + fn drop(&mut self) { + // Continue the same loop we have below. If the loop already finished, this does + // nothing. + self.0.for_each(drop); + + if self.0.tail_len > 0 { + unsafe { + let source_vec = self.0.vec.as_mut(); + // memmove back untouched tail, update to new length + let start = source_vec.len(); + let tail = self.0.tail_start; + if tail != start { + let src = source_vec.as_ptr().add(tail); + let dst = source_vec.as_mut_ptr().add(start); + ptr::copy(src, dst, self.0.tail_len); + } + source_vec.set_len(start + self.0.tail_len); + } + } + } + } + + // exhaust self first + while let Some(item) = self.next() { + let guard = DropGuard(self); + drop(item); + mem::forget(guard); + } + + // Drop a `DropGuard` to move back the non-drained tail of `self`. + DropGuard(self); + } +} + +#[stable(feature = "drain", since = "1.6.0")] +impl ExactSizeIterator for Drain<'_, T, A> { + fn is_empty(&self) -> bool { + self.iter.is_empty() + } +} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for Drain<'_, T, A> {} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Drain<'_, T, A> {} diff --git a/library/alloc/src/vec/drain_filter.rs b/library/alloc/src/vec/drain_filter.rs new file mode 100644 index 00000000000..3c37c92ae44 --- /dev/null +++ b/library/alloc/src/vec/drain_filter.rs @@ -0,0 +1,143 @@ +use crate::alloc::{Allocator, Global}; +use core::ptr::{self}; +use core::slice::{self}; + +use super::Vec; + +/// An iterator which uses a closure to determine if an element should be removed. +/// +/// This struct is created by [`Vec::drain_filter`]. +/// See its documentation for more. +/// +/// # Example +/// +/// ``` +/// #![feature(drain_filter)] +/// +/// let mut v = vec![0, 1, 2]; +/// let iter: std::vec::DrainFilter<_, _> = v.drain_filter(|x| *x % 2 == 0); +/// ``` +#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] +#[derive(Debug)] +pub struct DrainFilter< + 'a, + T, + F, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, +> where + F: FnMut(&mut T) -> bool, +{ + pub(super) vec: &'a mut Vec, + /// The index of the item that will be inspected by the next call to `next`. + pub(super) idx: usize, + /// The number of items that have been drained (removed) thus far. + pub(super) del: usize, + /// The original length of `vec` prior to draining. + pub(super) old_len: usize, + /// The filter test predicate. + pub(super) pred: F, + /// A flag that indicates a panic has occurred in the filter test predicate. + /// This is used as a hint in the drop implementation to prevent consumption + /// of the remainder of the `DrainFilter`. Any unprocessed items will be + /// backshifted in the `vec`, but no further items will be dropped or + /// tested by the filter predicate. + pub(super) panic_flag: bool, +} + +impl DrainFilter<'_, T, F, A> +where + F: FnMut(&mut T) -> bool, +{ + /// Returns a reference to the underlying allocator. + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline] + pub fn allocator(&self) -> &A { + self.vec.allocator() + } +} + +#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] +impl Iterator for DrainFilter<'_, T, F, A> +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); + self.panic_flag = true; + let drained = (self.pred)(&mut v[i]); + self.panic_flag = false; + // 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)) + } +} + +#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] +impl Drop for DrainFilter<'_, T, F, A> +where + F: FnMut(&mut T) -> bool, +{ + fn drop(&mut self) { + struct BackshiftOnDrop<'a, 'b, T, F, A: Allocator> + where + F: FnMut(&mut T) -> bool, + { + drain: &'b mut DrainFilter<'a, T, F, A>, + } + + impl<'a, 'b, T, F, A: Allocator> Drop for BackshiftOnDrop<'a, 'b, T, F, A> + where + F: FnMut(&mut T) -> bool, + { + fn drop(&mut self) { + unsafe { + if self.drain.idx < self.drain.old_len && self.drain.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.drain.vec.as_mut_ptr(); + let src = ptr.add(self.drain.idx); + let dst = src.sub(self.drain.del); + let tail_len = self.drain.old_len - self.drain.idx; + src.copy_to(dst, tail_len); + } + self.drain.vec.set_len(self.drain.old_len - self.drain.del); + } + } + } + + let backshift = BackshiftOnDrop { drain: self }; + + // Attempt to consume any remaining elements if the filter predicate + // has not yet panicked. We'll backshift any remaining elements + // whether we've already panicked or if the consumption here panics. + if !backshift.drain.panic_flag { + backshift.drain.for_each(drop); + } + } +} diff --git a/library/alloc/src/vec/in_place_drop.rs b/library/alloc/src/vec/in_place_drop.rs new file mode 100644 index 00000000000..354d25c2389 --- /dev/null +++ b/library/alloc/src/vec/in_place_drop.rs @@ -0,0 +1,24 @@ +use core::ptr::{self}; +use core::slice::{self}; + +// A helper struct for in-place iteration that drops the destination slice of iteration, +// i.e. the head. The source slice (the tail) is dropped by IntoIter. +pub(super) struct InPlaceDrop { + pub(super) inner: *mut T, + pub(super) dst: *mut T, +} + +impl InPlaceDrop { + fn len(&self) -> usize { + unsafe { self.dst.offset_from(self.inner) as usize } + } +} + +impl Drop for InPlaceDrop { + #[inline] + fn drop(&mut self) { + unsafe { + ptr::drop_in_place(slice::from_raw_parts_mut(self.inner, self.len())); + } + } +} diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs new file mode 100644 index 00000000000..f131d06bb18 --- /dev/null +++ b/library/alloc/src/vec/into_iter.rs @@ -0,0 +1,283 @@ +use crate::alloc::{Allocator, Global}; +use crate::raw_vec::RawVec; +use core::fmt; +use core::intrinsics::arith_offset; +use core::iter::{FusedIterator, InPlaceIterable, SourceIter, TrustedLen, TrustedRandomAccess}; +use core::marker::PhantomData; +use core::mem::{self}; +use core::ptr::{self, NonNull}; +use core::slice::{self}; + +/// An iterator that moves out of a vector. +/// +/// This `struct` is created by the `into_iter` method on [`Vec`](super::Vec) +/// (provided by the [`IntoIterator`] trait). +/// +/// # Example +/// +/// ``` +/// let v = vec![0, 1, 2]; +/// let iter: std::vec::IntoIter<_> = v.into_iter(); +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +pub struct IntoIter< + T, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, +> { + pub(super) buf: NonNull, + pub(super) phantom: PhantomData, + pub(super) cap: usize, + pub(super) alloc: A, + pub(super) ptr: *const T, + pub(super) end: *const T, +} + +#[stable(feature = "vec_intoiter_debug", since = "1.13.0")] +impl fmt::Debug for IntoIter { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("IntoIter").field(&self.as_slice()).finish() + } +} + +impl IntoIter { + /// Returns the remaining items of this iterator as a slice. + /// + /// # Examples + /// + /// ``` + /// let vec = vec!['a', 'b', 'c']; + /// let mut into_iter = vec.into_iter(); + /// assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']); + /// let _ = into_iter.next().unwrap(); + /// assert_eq!(into_iter.as_slice(), &['b', 'c']); + /// ``` + #[stable(feature = "vec_into_iter_as_slice", since = "1.15.0")] + pub fn as_slice(&self) -> &[T] { + unsafe { slice::from_raw_parts(self.ptr, self.len()) } + } + + /// Returns the remaining items of this iterator as a mutable slice. + /// + /// # Examples + /// + /// ``` + /// let vec = vec!['a', 'b', 'c']; + /// let mut into_iter = vec.into_iter(); + /// assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']); + /// into_iter.as_mut_slice()[2] = 'z'; + /// assert_eq!(into_iter.next().unwrap(), 'a'); + /// assert_eq!(into_iter.next().unwrap(), 'b'); + /// assert_eq!(into_iter.next().unwrap(), 'z'); + /// ``` + #[stable(feature = "vec_into_iter_as_slice", since = "1.15.0")] + pub fn as_mut_slice(&mut self) -> &mut [T] { + unsafe { &mut *self.as_raw_mut_slice() } + } + + /// Returns a reference to the underlying allocator. + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline] + pub fn allocator(&self) -> &A { + &self.alloc + } + + fn as_raw_mut_slice(&mut self) -> *mut [T] { + ptr::slice_from_raw_parts_mut(self.ptr as *mut T, self.len()) + } + + pub(super) fn drop_remaining(&mut self) { + unsafe { + ptr::drop_in_place(self.as_mut_slice()); + } + self.ptr = self.end; + } + + /// Relinquishes the backing allocation, equivalent to + /// `ptr::write(&mut self, Vec::new().into_iter())` + pub(super) fn forget_allocation(&mut self) { + self.cap = 0; + self.buf = unsafe { NonNull::new_unchecked(RawVec::NEW.ptr()) }; + self.ptr = self.buf.as_ptr(); + self.end = self.buf.as_ptr(); + } +} + +#[stable(feature = "vec_intoiter_as_ref", since = "1.46.0")] +impl AsRef<[T]> for IntoIter { + fn as_ref(&self) -> &[T] { + self.as_slice() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl Send for IntoIter {} +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl Sync for IntoIter {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Iterator for IntoIter { + type Item = T; + + #[inline] + fn next(&mut self) -> Option { + if self.ptr as *const _ == self.end { + None + } else if mem::size_of::() == 0 { + // purposefully don't use 'ptr.offset' because for + // vectors with 0-size elements this would return the + // same pointer. + self.ptr = unsafe { arith_offset(self.ptr as *const i8, 1) as *mut T }; + + // Make up a value of this ZST. + Some(unsafe { mem::zeroed() }) + } else { + let old = self.ptr; + self.ptr = unsafe { self.ptr.offset(1) }; + + Some(unsafe { ptr::read(old) }) + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let exact = if mem::size_of::() == 0 { + (self.end as usize).wrapping_sub(self.ptr as usize) + } else { + unsafe { self.end.offset_from(self.ptr) as usize } + }; + (exact, Some(exact)) + } + + #[inline] + fn count(self) -> usize { + self.len() + } + + unsafe fn __iterator_get_unchecked(&mut self, i: usize) -> Self::Item + where + Self: TrustedRandomAccess, + { + // SAFETY: the caller must guarantee that `i` is in bounds of the + // `Vec`, so `i` cannot overflow an `isize`, and the `self.ptr.add(i)` + // is guaranteed to pointer to an element of the `Vec` and + // thus guaranteed to be valid to dereference. + // + // Also note the implementation of `Self: TrustedRandomAccess` requires + // that `T: Copy` so reading elements from the buffer doesn't invalidate + // them for `Drop`. + unsafe { + if mem::size_of::() == 0 { mem::zeroed() } else { ptr::read(self.ptr.add(i)) } + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl DoubleEndedIterator for IntoIter { + #[inline] + fn next_back(&mut self) -> Option { + if self.end == self.ptr { + None + } else if mem::size_of::() == 0 { + // See above for why 'ptr.offset' isn't used + self.end = unsafe { arith_offset(self.end as *const i8, -1) as *mut T }; + + // Make up a value of this ZST. + Some(unsafe { mem::zeroed() }) + } else { + self.end = unsafe { self.end.offset(-1) }; + + Some(unsafe { ptr::read(self.end) }) + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for IntoIter { + fn is_empty(&self) -> bool { + self.ptr == self.end + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for IntoIter {} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for IntoIter {} + +#[doc(hidden)] +#[unstable(issue = "none", feature = "std_internals")] +// T: Copy as approximation for !Drop since get_unchecked does not advance self.ptr +// and thus we can't implement drop-handling +unsafe impl TrustedRandomAccess for IntoIter +where + T: Copy, +{ + fn may_have_side_effect() -> bool { + false + } +} + +#[stable(feature = "vec_into_iter_clone", since = "1.8.0")] +impl Clone for IntoIter { + #[cfg(not(test))] + fn clone(&self) -> Self { + self.as_slice().to_vec_in(self.alloc.clone()).into_iter() + } + #[cfg(test)] + fn clone(&self) -> Self { + crate::slice::to_vec(self.as_slice(), self.alloc.clone()).into_iter() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl<#[may_dangle] T, A: Allocator> Drop for IntoIter { + fn drop(&mut self) { + struct DropGuard<'a, T, A: Allocator>(&'a mut IntoIter); + + impl Drop for DropGuard<'_, T, A> { + fn drop(&mut self) { + unsafe { + // `IntoIter::alloc` is not used anymore after this + let alloc = ptr::read(&self.0.alloc); + // RawVec handles deallocation + let _ = RawVec::from_raw_parts_in(self.0.buf.as_ptr(), self.0.cap, alloc); + } + } + } + + let guard = DropGuard(self); + // destroy the remaining elements + unsafe { + ptr::drop_in_place(guard.0.as_raw_mut_slice()); + } + // now `guard` will be dropped and do the rest + } +} + +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl InPlaceIterable for IntoIter {} + +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl SourceIter for IntoIter { + type Source = Self; + + #[inline] + unsafe fn as_inner(&mut self) -> &mut Self::Source { + self + } +} + +// internal helper trait for in-place iteration specialization. +#[rustc_specialization_trait] +pub(crate) trait AsIntoIter { + type Item; + fn as_into_iter(&mut self) -> &mut IntoIter; +} + +impl AsIntoIter for IntoIter { + type Item = T; + + fn as_into_iter(&mut self) -> &mut IntoIter { + self + } +} diff --git a/library/alloc/src/vec/is_zero.rs b/library/alloc/src/vec/is_zero.rs new file mode 100644 index 00000000000..b5739970b6e --- /dev/null +++ b/library/alloc/src/vec/is_zero.rs @@ -0,0 +1,71 @@ +use crate::boxed::Box; + +#[rustc_specialization_trait] +pub(super) unsafe trait IsZero { + /// Whether this value is zero + fn is_zero(&self) -> bool; +} + +macro_rules! impl_is_zero { + ($t:ty, $is_zero:expr) => { + unsafe impl IsZero for $t { + #[inline] + fn is_zero(&self) -> bool { + $is_zero(*self) + } + } + }; +} + +impl_is_zero!(i16, |x| x == 0); +impl_is_zero!(i32, |x| x == 0); +impl_is_zero!(i64, |x| x == 0); +impl_is_zero!(i128, |x| x == 0); +impl_is_zero!(isize, |x| x == 0); + +impl_is_zero!(u16, |x| x == 0); +impl_is_zero!(u32, |x| x == 0); +impl_is_zero!(u64, |x| x == 0); +impl_is_zero!(u128, |x| x == 0); +impl_is_zero!(usize, |x| x == 0); + +impl_is_zero!(bool, |x| x == false); +impl_is_zero!(char, |x| x == '\0'); + +impl_is_zero!(f32, |x: f32| x.to_bits() == 0); +impl_is_zero!(f64, |x: f64| x.to_bits() == 0); + +unsafe impl IsZero for *const T { + #[inline] + fn is_zero(&self) -> bool { + (*self).is_null() + } +} + +unsafe impl IsZero for *mut T { + #[inline] + fn is_zero(&self) -> bool { + (*self).is_null() + } +} + +// `Option<&T>` and `Option>` are guaranteed to represent `None` as null. +// For fat pointers, the bytes that would be the pointer metadata in the `Some` +// variant are padding in the `None` variant, so ignoring them and +// zero-initializing instead is ok. +// `Option<&mut T>` never implements `Clone`, so there's no need for an impl of +// `SpecFromElem`. + +unsafe impl IsZero for Option<&T> { + #[inline] + fn is_zero(&self) -> bool { + self.is_none() + } +} + +unsafe impl IsZero for Option> { + #[inline] + fn is_zero(&self) -> bool { + self.is_none() + } +} diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs new file mode 100644 index 00000000000..2a83eb33fe3 --- /dev/null +++ b/library/alloc/src/vec/mod.rs @@ -0,0 +1,2513 @@ +//! A contiguous growable array type with heap-allocated contents, written +//! `Vec`. +//! +//! Vectors have `O(1)` indexing, amortized `O(1)` push (to the end) and +//! `O(1)` pop (from the end). +//! +//! Vectors ensure they never allocate more than `isize::MAX` bytes. +//! +//! # Examples +//! +//! You can explicitly create a [`Vec`] with [`Vec::new`]: +//! +//! ``` +//! let v: Vec = Vec::new(); +//! ``` +//! +//! ...or by using the [`vec!`] macro: +//! +//! ``` +//! let v: Vec = vec![]; +//! +//! let v = vec![1, 2, 3, 4, 5]; +//! +//! let v = vec![0; 10]; // ten zeroes +//! ``` +//! +//! You can [`push`] values onto the end of a vector (which will grow the vector +//! as needed): +//! +//! ``` +//! let mut v = vec![1, 2]; +//! +//! v.push(3); +//! ``` +//! +//! Popping values works in much the same way: +//! +//! ``` +//! let mut v = vec![1, 2]; +//! +//! let two = v.pop(); +//! ``` +//! +//! Vectors also support indexing (through the [`Index`] and [`IndexMut`] traits): +//! +//! ``` +//! let mut v = vec![1, 2, 3]; +//! let three = v[2]; +//! v[1] = v[1] + 5; +//! ``` +//! +//! [`push`]: Vec::push + +#![stable(feature = "rust1", since = "1.0.0")] + +use core::cmp::{self, Ordering}; +use core::convert::TryFrom; +use core::fmt; +use core::hash::{Hash, Hasher}; +use core::intrinsics::{arith_offset, assume}; +use core::iter::FromIterator; +use core::marker::PhantomData; +use core::mem::{self, ManuallyDrop, MaybeUninit}; +use core::ops::{self, Index, IndexMut, Range, RangeBounds}; +use core::ptr::{self, NonNull}; +use core::slice::{self, SliceIndex}; + +use crate::alloc::{Allocator, Global}; +use crate::borrow::{Cow, ToOwned}; +use crate::boxed::Box; +use crate::collections::TryReserveError; +use crate::raw_vec::RawVec; + +#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] +pub use self::drain_filter::DrainFilter; + +mod drain_filter; + +#[stable(feature = "vec_splice", since = "1.21.0")] +pub use self::splice::Splice; + +mod splice; + +#[stable(feature = "drain", since = "1.6.0")] +pub use self::drain::Drain; + +mod drain; + +mod cow; + +pub(crate) use self::into_iter::AsIntoIter; +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::into_iter::IntoIter; + +mod into_iter; + +use self::is_zero::IsZero; + +mod is_zero; + +mod source_iter_marker; + +mod partial_eq; + +use self::spec_from_elem::SpecFromElem; + +mod spec_from_elem; + +use self::set_len_on_drop::SetLenOnDrop; + +mod set_len_on_drop; + +use self::in_place_drop::InPlaceDrop; + +mod in_place_drop; + +use self::spec_from_iter_nested::SpecFromIterNested; + +mod spec_from_iter_nested; + +use self::spec_from_iter::SpecFromIter; + +mod spec_from_iter; + +use self::spec_extend::SpecExtend; + +mod spec_extend; + +/// A contiguous growable array type, written `Vec` but pronounced 'vector'. +/// +/// # Examples +/// +/// ``` +/// let mut vec = Vec::new(); +/// vec.push(1); +/// vec.push(2); +/// +/// assert_eq!(vec.len(), 2); +/// assert_eq!(vec[0], 1); +/// +/// assert_eq!(vec.pop(), Some(2)); +/// assert_eq!(vec.len(), 1); +/// +/// vec[0] = 7; +/// assert_eq!(vec[0], 7); +/// +/// vec.extend([1, 2, 3].iter().copied()); +/// +/// for x in &vec { +/// println!("{}", x); +/// } +/// assert_eq!(vec, [7, 1, 2, 3]); +/// ``` +/// +/// The [`vec!`] macro is provided to make initialization more convenient: +/// +/// ``` +/// let mut vec = vec![1, 2, 3]; +/// vec.push(4); +/// assert_eq!(vec, [1, 2, 3, 4]); +/// ``` +/// +/// It can also initialize each element of a `Vec` with a given value. +/// This may be more efficient than performing allocation and initialization +/// in separate steps, especially when initializing a vector of zeros: +/// +/// ``` +/// let vec = vec![0; 5]; +/// assert_eq!(vec, [0, 0, 0, 0, 0]); +/// +/// // The following is equivalent, but potentially slower: +/// let mut vec = Vec::with_capacity(5); +/// vec.resize(5, 0); +/// assert_eq!(vec, [0, 0, 0, 0, 0]); +/// ``` +/// +/// For more information, see +/// [Capacity and Reallocation](#capacity-and-reallocation). +/// +/// Use a `Vec` as an efficient stack: +/// +/// ``` +/// let mut stack = Vec::new(); +/// +/// stack.push(1); +/// stack.push(2); +/// stack.push(3); +/// +/// while let Some(top) = stack.pop() { +/// // Prints 3, 2, 1 +/// println!("{}", top); +/// } +/// ``` +/// +/// # Indexing +/// +/// The `Vec` type allows to access values by index, because it implements the +/// [`Index`] trait. An example will be more explicit: +/// +/// ``` +/// let v = vec![0, 2, 4, 6]; +/// println!("{}", v[1]); // it will display '2' +/// ``` +/// +/// However be careful: if you try to access an index which isn't in the `Vec`, +/// your software will panic! You cannot do this: +/// +/// ```should_panic +/// let v = vec![0, 2, 4, 6]; +/// println!("{}", v[6]); // it will panic! +/// ``` +/// +/// Use [`get`] and [`get_mut`] if you want to check whether the index is in +/// the `Vec`. +/// +/// # Slicing +/// +/// A `Vec` can be mutable. Slices, on the other hand, are read-only objects. +/// To get a [slice], use [`&`]. Example: +/// +/// ``` +/// fn read_slice(slice: &[usize]) { +/// // ... +/// } +/// +/// let v = vec![0, 1]; +/// read_slice(&v); +/// +/// // ... and that's all! +/// // you can also do it like this: +/// let u: &[usize] = &v; +/// // or like this: +/// let u: &[_] = &v; +/// ``` +/// +/// In Rust, it's more common to pass slices as arguments rather than vectors +/// when you just want to provide read access. The same goes for [`String`] and +/// [`&str`]. +/// +/// # Capacity and reallocation +/// +/// The capacity of a vector is the amount of space allocated for any future +/// elements that will be added onto the vector. This is not to be confused with +/// the *length* of a vector, which specifies the number of actual elements +/// within the vector. If a vector's length exceeds its capacity, its capacity +/// will automatically be increased, but its elements will have to be +/// reallocated. +/// +/// For example, a vector with capacity 10 and length 0 would be an empty vector +/// with space for 10 more elements. Pushing 10 or fewer elements onto the +/// vector will not change its capacity or cause reallocation to occur. However, +/// if the vector's length is increased to 11, it will have to reallocate, which +/// can be slow. For this reason, it is recommended to use [`Vec::with_capacity`] +/// whenever possible to specify how big the vector is expected to get. +/// +/// # Guarantees +/// +/// Due to its incredibly fundamental nature, `Vec` makes a lot of guarantees +/// about its design. This ensures that it's as low-overhead as possible in +/// the general case, and can be correctly manipulated in primitive ways +/// by unsafe code. Note that these guarantees refer to an unqualified `Vec`. +/// If additional type parameters are added (e.g., to support custom allocators), +/// overriding their defaults may change the behavior. +/// +/// Most fundamentally, `Vec` is and always will be a (pointer, capacity, length) +/// triplet. No more, no less. The order of these fields is completely +/// unspecified, and you should use the appropriate methods to modify these. +/// The pointer will never be null, so this type is null-pointer-optimized. +/// +/// However, the pointer may not actually point to allocated memory. In particular, +/// if you construct a `Vec` with capacity 0 via [`Vec::new`], [`vec![]`][`vec!`], +/// [`Vec::with_capacity(0)`][`Vec::with_capacity`], or by calling [`shrink_to_fit`] +/// on an empty Vec, it will not allocate memory. Similarly, if you store zero-sized +/// types inside a `Vec`, it will not allocate space for them. *Note that in this case +/// the `Vec` may not report a [`capacity`] of 0*. `Vec` will allocate if and only +/// if [`mem::size_of::`]`() * capacity() > 0`. In general, `Vec`'s allocation +/// details are very subtle — if you intend to allocate memory using a `Vec` +/// and use it for something else (either to pass to unsafe code, or to build your +/// own memory-backed collection), be sure to deallocate this memory by using +/// `from_raw_parts` to recover the `Vec` and then dropping it. +/// +/// If a `Vec` *has* allocated memory, then the memory it points to is on the heap +/// (as defined by the allocator Rust is configured to use by default), and its +/// pointer points to [`len`] initialized, contiguous elements in order (what +/// you would see if you coerced it to a slice), followed by [`capacity`]` - +/// `[`len`] logically uninitialized, contiguous elements. +/// +/// `Vec` will never perform a "small optimization" where elements are actually +/// stored on the stack for two reasons: +/// +/// * It would make it more difficult for unsafe code to correctly manipulate +/// a `Vec`. The contents of a `Vec` wouldn't have a stable address if it were +/// only moved, and it would be more difficult to determine if a `Vec` had +/// actually allocated memory. +/// +/// * It would penalize the general case, incurring an additional branch +/// on every access. +/// +/// `Vec` will never automatically shrink itself, even if completely empty. This +/// ensures no unnecessary allocations or deallocations occur. Emptying a `Vec` +/// and then filling it back up to the same [`len`] should incur no calls to +/// the allocator. If you wish to free up unused memory, use +/// [`shrink_to_fit`]. +/// +/// [`push`] and [`insert`] will never (re)allocate if the reported capacity is +/// sufficient. [`push`] and [`insert`] *will* (re)allocate if +/// [`len`]` == `[`capacity`]. That is, the reported capacity is completely +/// accurate, and can be relied on. It can even be used to manually free the memory +/// allocated by a `Vec` if desired. Bulk insertion methods *may* reallocate, even +/// when not necessary. +/// +/// `Vec` does not guarantee any particular growth strategy when reallocating +/// when full, nor when [`reserve`] is called. The current strategy is basic +/// and it may prove desirable to use a non-constant growth factor. Whatever +/// strategy is used will of course guarantee *O*(1) amortized [`push`]. +/// +/// `vec![x; n]`, `vec![a, b, c, d]`, and +/// [`Vec::with_capacity(n)`][`Vec::with_capacity`], will all produce a `Vec` +/// with exactly the requested capacity. If [`len`]` == `[`capacity`], +/// (as is the case for the [`vec!`] macro), then a `Vec` can be converted to +/// and from a [`Box<[T]>`][owned slice] without reallocating or moving the elements. +/// +/// `Vec` will not specifically overwrite any data that is removed from it, +/// but also won't specifically preserve it. Its uninitialized memory is +/// scratch space that it may use however it wants. It will generally just do +/// whatever is most efficient or otherwise easy to implement. Do not rely on +/// removed data to be erased for security purposes. Even if you drop a `Vec`, its +/// buffer may simply be reused by another `Vec`. Even if you zero a `Vec`'s memory +/// first, that may not actually happen because the optimizer does not consider +/// this a side-effect that must be preserved. There is one case which we will +/// not break, however: using `unsafe` code to write to the excess capacity, +/// and then increasing the length to match, is always valid. +/// +/// `Vec` does not currently guarantee the order in which elements are dropped. +/// The order has changed in the past and may change again. +/// +/// [`get`]: ../../std/vec/struct.Vec.html#method.get +/// [`get_mut`]: ../../std/vec/struct.Vec.html#method.get_mut +/// [`String`]: crate::string::String +/// [`&str`]: type@str +/// [`shrink_to_fit`]: Vec::shrink_to_fit +/// [`capacity`]: Vec::capacity +/// [`mem::size_of::`]: core::mem::size_of +/// [`len`]: Vec::len +/// [`push`]: Vec::push +/// [`insert`]: Vec::insert +/// [`reserve`]: Vec::reserve +/// [owned slice]: Box +/// [slice]: ../../std/primitive.slice.html +/// [`&`]: ../../std/primitive.reference.html +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "vec_type")] +pub struct Vec { + buf: RawVec, + len: usize, +} + +//////////////////////////////////////////////////////////////////////////////// +// Inherent methods +//////////////////////////////////////////////////////////////////////////////// + +impl Vec { + /// Constructs a new, empty `Vec`. + /// + /// The vector will not allocate until elements are pushed onto it. + /// + /// # Examples + /// + /// ``` + /// # #![allow(unused_mut)] + /// let mut vec: Vec = Vec::new(); + /// ``` + #[inline] + #[rustc_const_stable(feature = "const_vec_new", since = "1.39.0")] + #[stable(feature = "rust1", since = "1.0.0")] + pub const fn new() -> Self { + Vec { buf: RawVec::NEW, len: 0 } + } + + /// Constructs a new, empty `Vec` with the specified capacity. + /// + /// The vector will be able to hold exactly `capacity` elements without + /// reallocating. If `capacity` is 0, the vector will not allocate. + /// + /// It is important to note that although the returned vector has the + /// *capacity* specified, the vector will have a zero *length*. For an + /// explanation of the difference between length and capacity, see + /// *[Capacity and reallocation]*. + /// + /// [Capacity and reallocation]: #capacity-and-reallocation + /// + /// # Examples + /// + /// ``` + /// let mut vec = Vec::with_capacity(10); + /// + /// // The vector contains no items, even though it has capacity for more + /// assert_eq!(vec.len(), 0); + /// assert_eq!(vec.capacity(), 10); + /// + /// // These are all done without reallocating... + /// for i in 0..10 { + /// vec.push(i); + /// } + /// assert_eq!(vec.len(), 10); + /// assert_eq!(vec.capacity(), 10); + /// + /// // ...but this may make the vector reallocate + /// vec.push(11); + /// assert_eq!(vec.len(), 11); + /// assert!(vec.capacity() >= 11); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn with_capacity(capacity: usize) -> Self { + Self::with_capacity_in(capacity, Global) + } + + /// Creates a `Vec` directly from the raw components of another vector. + /// + /// # Safety + /// + /// This is highly unsafe, due to the number of invariants that aren't + /// checked: + /// + /// * `ptr` needs to have been previously allocated via [`String`]/`Vec` + /// (at least, it's highly likely to be incorrect if it wasn't). + /// * `T` needs to have the same size and alignment as what `ptr` was allocated with. + /// (`T` having a less strict alignment is not sufficient, the alignment really + /// needs to be equal to satisfy the [`dealloc`] requirement that memory must be + /// allocated and deallocated with the same layout.) + /// * `length` needs to be less than or equal to `capacity`. + /// * `capacity` needs to be the capacity that the pointer was allocated with. + /// + /// Violating these may cause problems like corrupting the allocator's + /// internal data structures. For example it is **not** safe + /// to build a `Vec` from a pointer to a C `char` array with length `size_t`. + /// It's also not safe to build one from a `Vec` and its length, because + /// the allocator cares about the alignment, and these two types have different + /// alignments. The buffer was allocated with alignment 2 (for `u16`), but after + /// turning it into a `Vec` it'll be deallocated with alignment 1. + /// + /// The ownership of `ptr` is effectively transferred to the + /// `Vec` which may then deallocate, reallocate or change the + /// contents of memory pointed to by the pointer at will. Ensure + /// that nothing else uses the pointer after calling this + /// function. + /// + /// [`String`]: crate::string::String + /// [`dealloc`]: crate::alloc::GlobalAlloc::dealloc + /// + /// # Examples + /// + /// ``` + /// use std::ptr; + /// use std::mem; + /// + /// let v = vec![1, 2, 3]; + /// + // FIXME Update this when vec_into_raw_parts is stabilized + /// // Prevent running `v`'s destructor so we are in complete control + /// // of the allocation. + /// let mut v = mem::ManuallyDrop::new(v); + /// + /// // Pull out the various important pieces of information about `v` + /// let p = v.as_mut_ptr(); + /// let len = v.len(); + /// let cap = v.capacity(); + /// + /// unsafe { + /// // Overwrite memory with 4, 5, 6 + /// for i in 0..len as isize { + /// ptr::write(p.offset(i), 4 + i); + /// } + /// + /// // Put everything back together into a Vec + /// let rebuilt = Vec::from_raw_parts(p, len, cap); + /// assert_eq!(rebuilt, [4, 5, 6]); + /// } + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub unsafe fn from_raw_parts(ptr: *mut T, length: usize, capacity: usize) -> Self { + unsafe { Self::from_raw_parts_in(ptr, length, capacity, Global) } + } +} + +impl Vec { + /// Constructs a new, empty `Vec`. + /// + /// The vector will not allocate until elements are pushed onto it. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::alloc::System; + /// + /// # #[allow(unused_mut)] + /// let mut vec: Vec = Vec::new_in(System); + /// ``` + #[inline] + #[unstable(feature = "allocator_api", issue = "32838")] + pub const fn new_in(alloc: A) -> Self { + Vec { buf: RawVec::new_in(alloc), len: 0 } + } + + /// Constructs a new, empty `Vec` with the specified capacity with the provided + /// allocator. + /// + /// The vector will be able to hold exactly `capacity` elements without + /// reallocating. If `capacity` is 0, the vector will not allocate. + /// + /// It is important to note that although the returned vector has the + /// *capacity* specified, the vector will have a zero *length*. For an + /// explanation of the difference between length and capacity, see + /// *[Capacity and reallocation]*. + /// + /// [Capacity and reallocation]: #capacity-and-reallocation + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::alloc::System; + /// + /// let mut vec = Vec::with_capacity_in(10, System); + /// + /// // The vector contains no items, even though it has capacity for more + /// assert_eq!(vec.len(), 0); + /// assert_eq!(vec.capacity(), 10); + /// + /// // These are all done without reallocating... + /// for i in 0..10 { + /// vec.push(i); + /// } + /// assert_eq!(vec.len(), 10); + /// assert_eq!(vec.capacity(), 10); + /// + /// // ...but this may make the vector reallocate + /// vec.push(11); + /// assert_eq!(vec.len(), 11); + /// assert!(vec.capacity() >= 11); + /// ``` + #[inline] + #[unstable(feature = "allocator_api", issue = "32838")] + pub fn with_capacity_in(capacity: usize, alloc: A) -> Self { + Vec { buf: RawVec::with_capacity_in(capacity, alloc), len: 0 } + } + + /// Creates a `Vec` directly from the raw components of another vector. + /// + /// # Safety + /// + /// This is highly unsafe, due to the number of invariants that aren't + /// checked: + /// + /// * `ptr` needs to have been previously allocated via [`String`]/`Vec` + /// (at least, it's highly likely to be incorrect if it wasn't). + /// * `T` needs to have the same size and alignment as what `ptr` was allocated with. + /// (`T` having a less strict alignment is not sufficient, the alignment really + /// needs to be equal to satisfy the [`dealloc`] requirement that memory must be + /// allocated and deallocated with the same layout.) + /// * `length` needs to be less than or equal to `capacity`. + /// * `capacity` needs to be the capacity that the pointer was allocated with. + /// + /// Violating these may cause problems like corrupting the allocator's + /// internal data structures. For example it is **not** safe + /// to build a `Vec` from a pointer to a C `char` array with length `size_t`. + /// It's also not safe to build one from a `Vec` and its length, because + /// the allocator cares about the alignment, and these two types have different + /// alignments. The buffer was allocated with alignment 2 (for `u16`), but after + /// turning it into a `Vec` it'll be deallocated with alignment 1. + /// + /// The ownership of `ptr` is effectively transferred to the + /// `Vec` which may then deallocate, reallocate or change the + /// contents of memory pointed to by the pointer at will. Ensure + /// that nothing else uses the pointer after calling this + /// function. + /// + /// [`String`]: crate::string::String + /// [`dealloc`]: crate::alloc::GlobalAlloc::dealloc + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::alloc::System; + /// + /// use std::ptr; + /// use std::mem; + /// + /// let mut v = Vec::with_capacity_in(3, System); + /// v.push(1); + /// v.push(2); + /// v.push(3); + /// + // FIXME Update this when vec_into_raw_parts is stabilized + /// // Prevent running `v`'s destructor so we are in complete control + /// // of the allocation. + /// let mut v = mem::ManuallyDrop::new(v); + /// + /// // Pull out the various important pieces of information about `v` + /// let p = v.as_mut_ptr(); + /// let len = v.len(); + /// let cap = v.capacity(); + /// let alloc = v.allocator(); + /// + /// unsafe { + /// // Overwrite memory with 4, 5, 6 + /// for i in 0..len as isize { + /// ptr::write(p.offset(i), 4 + i); + /// } + /// + /// // Put everything back together into a Vec + /// let rebuilt = Vec::from_raw_parts_in(p, len, cap, alloc.clone()); + /// assert_eq!(rebuilt, [4, 5, 6]); + /// } + /// ``` + #[inline] + #[unstable(feature = "allocator_api", issue = "32838")] + pub unsafe fn from_raw_parts_in(ptr: *mut T, length: usize, capacity: usize, alloc: A) -> Self { + unsafe { Vec { buf: RawVec::from_raw_parts_in(ptr, capacity, alloc), len: length } } + } + + /// Decomposes a `Vec` into its raw components. + /// + /// Returns the raw pointer to the underlying data, the length of + /// the vector (in elements), and the allocated capacity of the + /// data (in elements). These are the same arguments in the same + /// order as the arguments to [`from_raw_parts`]. + /// + /// After calling this function, the caller is responsible for the + /// memory previously managed by the `Vec`. The only way to do + /// this is to convert the raw pointer, length, and capacity back + /// into a `Vec` with the [`from_raw_parts`] function, allowing + /// the destructor to perform the cleanup. + /// + /// [`from_raw_parts`]: Vec::from_raw_parts + /// + /// # Examples + /// + /// ``` + /// #![feature(vec_into_raw_parts)] + /// let v: Vec = vec![-1, 0, 1]; + /// + /// let (ptr, len, cap) = v.into_raw_parts(); + /// + /// let rebuilt = unsafe { + /// // We can now make changes to the components, such as + /// // transmuting the raw pointer to a compatible type. + /// let ptr = ptr as *mut u32; + /// + /// Vec::from_raw_parts(ptr, len, cap) + /// }; + /// assert_eq!(rebuilt, [4294967295, 0, 1]); + /// ``` + #[unstable(feature = "vec_into_raw_parts", reason = "new API", issue = "65816")] + pub fn into_raw_parts(self) -> (*mut T, usize, usize) { + let mut me = ManuallyDrop::new(self); + (me.as_mut_ptr(), me.len(), me.capacity()) + } + + /// Decomposes a `Vec` into its raw components. + /// + /// Returns the raw pointer to the underlying data, the length of the vector (in elements), + /// the allocated capacity of the data (in elements), and the allocator. These are the same + /// arguments in the same order as the arguments to [`from_raw_parts_in`]. + /// + /// After calling this function, the caller is responsible for the + /// memory previously managed by the `Vec`. The only way to do + /// this is to convert the raw pointer, length, and capacity back + /// into a `Vec` with the [`from_raw_parts_in`] function, allowing + /// the destructor to perform the cleanup. + /// + /// [`from_raw_parts_in`]: Vec::from_raw_parts_in + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api, vec_into_raw_parts)] + /// + /// use std::alloc::System; + /// + /// let mut v: Vec = Vec::new_in(System); + /// v.push(-1); + /// v.push(0); + /// v.push(1); + /// + /// let (ptr, len, cap, alloc) = v.into_raw_parts_with_alloc(); + /// + /// let rebuilt = unsafe { + /// // We can now make changes to the components, such as + /// // transmuting the raw pointer to a compatible type. + /// let ptr = ptr as *mut u32; + /// + /// Vec::from_raw_parts_in(ptr, len, cap, alloc) + /// }; + /// assert_eq!(rebuilt, [4294967295, 0, 1]); + /// ``` + #[unstable(feature = "allocator_api", issue = "32838")] + // #[unstable(feature = "vec_into_raw_parts", reason = "new API", issue = "65816")] + pub fn into_raw_parts_with_alloc(self) -> (*mut T, usize, usize, A) { + let mut me = ManuallyDrop::new(self); + let len = me.len(); + let capacity = me.capacity(); + let ptr = me.as_mut_ptr(); + let alloc = unsafe { ptr::read(me.allocator()) }; + (ptr, len, capacity, alloc) + } + + /// Returns the number of elements the vector can hold without + /// reallocating. + /// + /// # Examples + /// + /// ``` + /// let vec: Vec = Vec::with_capacity(10); + /// assert_eq!(vec.capacity(), 10); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn capacity(&self) -> usize { + self.buf.capacity() + } + + /// Reserves capacity for at least `additional` more elements to be inserted + /// in the given `Vec`. The collection may reserve more space to avoid + /// frequent reallocations. After calling `reserve`, capacity will be + /// greater than or equal to `self.len() + additional`. Does nothing if + /// capacity is already sufficient. + /// + /// # Panics + /// + /// Panics if the new capacity exceeds `isize::MAX` bytes. + /// + /// # Examples + /// + /// ``` + /// let mut vec = vec![1]; + /// vec.reserve(10); + /// assert!(vec.capacity() >= 11); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn reserve(&mut self, additional: usize) { + self.buf.reserve(self.len, additional); + } + + /// Reserves the minimum capacity for exactly `additional` more elements to + /// be inserted in the given `Vec`. After calling `reserve_exact`, + /// capacity will be greater than or equal to `self.len() + additional`. + /// Does nothing if the capacity is already sufficient. + /// + /// Note that the allocator may give the collection more space than it + /// requests. Therefore, capacity can not be relied upon to be precisely + /// minimal. Prefer `reserve` if future insertions are expected. + /// + /// # Panics + /// + /// Panics if the new capacity overflows `usize`. + /// + /// # Examples + /// + /// ``` + /// let mut vec = vec![1]; + /// vec.reserve_exact(10); + /// assert!(vec.capacity() >= 11); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn reserve_exact(&mut self, additional: usize) { + self.buf.reserve_exact(self.len, additional); + } + + /// Tries to reserve capacity for at least `additional` more elements to be inserted + /// in the given `Vec`. The collection may reserve more space to avoid + /// frequent reallocations. After calling `try_reserve`, capacity will be + /// greater than or equal to `self.len() + additional`. Does nothing if + /// capacity is already sufficient. + /// + /// # Errors + /// + /// If the capacity overflows, or the allocator reports a failure, then an error + /// is returned. + /// + /// # Examples + /// + /// ``` + /// #![feature(try_reserve)] + /// use std::collections::TryReserveError; + /// + /// fn process_data(data: &[u32]) -> Result, TryReserveError> { + /// let mut output = Vec::new(); + /// + /// // Pre-reserve the memory, exiting if we can't + /// output.try_reserve(data.len())?; + /// + /// // Now we know this can't OOM in the middle of our complex work + /// output.extend(data.iter().map(|&val| { + /// val * 2 + 5 // very complicated + /// })); + /// + /// Ok(output) + /// } + /// # process_data(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?"); + /// ``` + #[unstable(feature = "try_reserve", reason = "new API", issue = "48043")] + pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { + self.buf.try_reserve(self.len, additional) + } + + /// Tries to reserve the minimum capacity for exactly `additional` + /// elements to be inserted in the given `Vec`. After calling + /// `try_reserve_exact`, capacity will be greater than or equal to + /// `self.len() + additional` if it returns `Ok(())`. + /// Does nothing if the capacity is already sufficient. + /// + /// Note that the allocator may give the collection more space than it + /// requests. Therefore, capacity can not be relied upon to be precisely + /// minimal. Prefer `reserve` if future insertions are expected. + /// + /// # Errors + /// + /// If the capacity overflows, or the allocator reports a failure, then an error + /// is returned. + /// + /// # Examples + /// + /// ``` + /// #![feature(try_reserve)] + /// use std::collections::TryReserveError; + /// + /// fn process_data(data: &[u32]) -> Result, TryReserveError> { + /// let mut output = Vec::new(); + /// + /// // Pre-reserve the memory, exiting if we can't + /// output.try_reserve_exact(data.len())?; + /// + /// // Now we know this can't OOM in the middle of our complex work + /// output.extend(data.iter().map(|&val| { + /// val * 2 + 5 // very complicated + /// })); + /// + /// Ok(output) + /// } + /// # process_data(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?"); + /// ``` + #[unstable(feature = "try_reserve", reason = "new API", issue = "48043")] + pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> { + self.buf.try_reserve_exact(self.len, additional) + } + + /// Shrinks the capacity of the vector as much as possible. + /// + /// It will drop down as close as possible to the length but the allocator + /// may still inform the vector that there is space for a few more elements. + /// + /// # Examples + /// + /// ``` + /// let mut vec = Vec::with_capacity(10); + /// vec.extend([1, 2, 3].iter().cloned()); + /// assert_eq!(vec.capacity(), 10); + /// vec.shrink_to_fit(); + /// assert!(vec.capacity() >= 3); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn shrink_to_fit(&mut self) { + // The capacity is never less than the length, and there's nothing to do when + // they are equal, so we can avoid the panic case in `RawVec::shrink_to_fit` + // by only calling it with a greater capacity. + if self.capacity() > self.len { + self.buf.shrink_to_fit(self.len); + } + } + + /// Shrinks the capacity of the vector with a lower bound. + /// + /// The capacity will remain at least as large as both the length + /// and the supplied value. + /// + /// # Panics + /// + /// Panics if the current capacity is smaller than the supplied + /// minimum capacity. + /// + /// # Examples + /// + /// ``` + /// #![feature(shrink_to)] + /// let mut vec = Vec::with_capacity(10); + /// vec.extend([1, 2, 3].iter().cloned()); + /// assert_eq!(vec.capacity(), 10); + /// vec.shrink_to(4); + /// assert!(vec.capacity() >= 4); + /// vec.shrink_to(0); + /// assert!(vec.capacity() >= 3); + /// ``` + #[unstable(feature = "shrink_to", reason = "new API", issue = "56431")] + pub fn shrink_to(&mut self, min_capacity: usize) { + self.buf.shrink_to_fit(cmp::max(self.len, min_capacity)); + } + + /// Converts the vector into [`Box<[T]>`][owned slice]. + /// + /// Note that this will drop any excess capacity. + /// + /// [owned slice]: Box + /// + /// # Examples + /// + /// ``` + /// let v = vec![1, 2, 3]; + /// + /// let slice = v.into_boxed_slice(); + /// ``` + /// + /// Any excess capacity is removed: + /// + /// ``` + /// let mut vec = Vec::with_capacity(10); + /// vec.extend([1, 2, 3].iter().cloned()); + /// + /// assert_eq!(vec.capacity(), 10); + /// let slice = vec.into_boxed_slice(); + /// assert_eq!(slice.into_vec().capacity(), 3); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn into_boxed_slice(mut self) -> Box<[T], A> { + unsafe { + self.shrink_to_fit(); + let me = ManuallyDrop::new(self); + let buf = ptr::read(&me.buf); + let len = me.len(); + buf.into_box(len).assume_init() + } + } + + /// Shortens the vector, keeping the first `len` elements and dropping + /// the rest. + /// + /// If `len` is greater than the vector's current length, this has no + /// effect. + /// + /// The [`drain`] method can emulate `truncate`, but causes the excess + /// elements to be returned instead of dropped. + /// + /// Note that this method has no effect on the allocated capacity + /// of the vector. + /// + /// # Examples + /// + /// Truncating a five element vector to two elements: + /// + /// ``` + /// let mut vec = vec![1, 2, 3, 4, 5]; + /// vec.truncate(2); + /// assert_eq!(vec, [1, 2]); + /// ``` + /// + /// No truncation occurs when `len` is greater than the vector's current + /// length: + /// + /// ``` + /// let mut vec = vec![1, 2, 3]; + /// vec.truncate(8); + /// assert_eq!(vec, [1, 2, 3]); + /// ``` + /// + /// Truncating when `len == 0` is equivalent to calling the [`clear`] + /// method. + /// + /// ``` + /// let mut vec = vec![1, 2, 3]; + /// vec.truncate(0); + /// assert_eq!(vec, []); + /// ``` + /// + /// [`clear`]: Vec::clear + /// [`drain`]: Vec::drain + #[stable(feature = "rust1", since = "1.0.0")] + pub fn truncate(&mut self, len: usize) { + // This is safe because: + // + // * the slice passed to `drop_in_place` is valid; the `len > self.len` + // case avoids creating an invalid slice, and + // * the `len` of the vector is shrunk before calling `drop_in_place`, + // such that no value will be dropped twice in case `drop_in_place` + // were to panic once (if it panics twice, the program aborts). + unsafe { + if len > self.len { + return; + } + let remaining_len = self.len - len; + let s = ptr::slice_from_raw_parts_mut(self.as_mut_ptr().add(len), remaining_len); + self.len = len; + ptr::drop_in_place(s); + } + } + + /// Extracts a slice containing the entire vector. + /// + /// Equivalent to `&s[..]`. + /// + /// # Examples + /// + /// ``` + /// use std::io::{self, Write}; + /// let buffer = vec![1, 2, 3, 5, 8]; + /// io::sink().write(buffer.as_slice()).unwrap(); + /// ``` + #[inline] + #[stable(feature = "vec_as_slice", since = "1.7.0")] + pub fn as_slice(&self) -> &[T] { + self + } + + /// Extracts a mutable slice of the entire vector. + /// + /// Equivalent to `&mut s[..]`. + /// + /// # Examples + /// + /// ``` + /// use std::io::{self, Read}; + /// let mut buffer = vec![0; 3]; + /// io::repeat(0b101).read_exact(buffer.as_mut_slice()).unwrap(); + /// ``` + #[inline] + #[stable(feature = "vec_as_slice", since = "1.7.0")] + pub fn as_mut_slice(&mut self) -> &mut [T] { + self + } + + /// Returns a raw pointer to the vector's buffer. + /// + /// The caller must ensure that the vector outlives the pointer this + /// function returns, or else it will end up pointing to garbage. + /// Modifying the vector may cause its buffer to be reallocated, + /// which would also make any pointers to it invalid. + /// + /// The caller must also ensure that the memory the pointer (non-transitively) points to + /// is never written to (except inside an `UnsafeCell`) using this pointer or any pointer + /// derived from it. If you need to mutate the contents of the slice, use [`as_mut_ptr`]. + /// + /// # Examples + /// + /// ``` + /// let x = vec![1, 2, 4]; + /// let x_ptr = x.as_ptr(); + /// + /// unsafe { + /// for i in 0..x.len() { + /// assert_eq!(*x_ptr.add(i), 1 << i); + /// } + /// } + /// ``` + /// + /// [`as_mut_ptr`]: Vec::as_mut_ptr + #[stable(feature = "vec_as_ptr", since = "1.37.0")] + #[inline] + pub fn as_ptr(&self) -> *const T { + // We shadow the slice method of the same name to avoid going through + // `deref`, which creates an intermediate reference. + let ptr = self.buf.ptr(); + unsafe { + assume(!ptr.is_null()); + } + ptr + } + + /// Returns an unsafe mutable pointer to the vector's buffer. + /// + /// The caller must ensure that the vector outlives the pointer this + /// function returns, or else it will end up pointing to garbage. + /// Modifying the vector may cause its buffer to be reallocated, + /// which would also make any pointers to it invalid. + /// + /// # Examples + /// + /// ``` + /// // Allocate vector big enough for 4 elements. + /// let size = 4; + /// let mut x: Vec = Vec::with_capacity(size); + /// let x_ptr = x.as_mut_ptr(); + /// + /// // Initialize elements via raw pointer writes, then set length. + /// unsafe { + /// for i in 0..size { + /// *x_ptr.add(i) = i as i32; + /// } + /// x.set_len(size); + /// } + /// assert_eq!(&*x, &[0, 1, 2, 3]); + /// ``` + #[stable(feature = "vec_as_ptr", since = "1.37.0")] + #[inline] + pub fn as_mut_ptr(&mut self) -> *mut T { + // We shadow the slice method of the same name to avoid going through + // `deref_mut`, which creates an intermediate reference. + let ptr = self.buf.ptr(); + unsafe { + assume(!ptr.is_null()); + } + ptr + } + + /// Returns a reference to the underlying allocator. + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline] + pub fn allocator(&self) -> &A { + self.buf.allocator() + } + + /// Forces the length of the vector to `new_len`. + /// + /// This is a low-level operation that maintains none of the normal + /// invariants of the type. Normally changing the length of a vector + /// is done using one of the safe operations instead, such as + /// [`truncate`], [`resize`], [`extend`], or [`clear`]. + /// + /// [`truncate`]: Vec::truncate + /// [`resize`]: Vec::resize + /// [`extend`]: Extend::extend + /// [`clear`]: Vec::clear + /// + /// # Safety + /// + /// - `new_len` must be less than or equal to [`capacity()`]. + /// - The elements at `old_len..new_len` must be initialized. + /// + /// [`capacity()`]: Vec::capacity + /// + /// # Examples + /// + /// This method can be useful for situations in which the vector + /// is serving as a buffer for other code, particularly over FFI: + /// + /// ```no_run + /// # #![allow(dead_code)] + /// # // This is just a minimal skeleton for the doc example; + /// # // don't use this as a starting point for a real library. + /// # pub struct StreamWrapper { strm: *mut std::ffi::c_void } + /// # const Z_OK: i32 = 0; + /// # extern "C" { + /// # fn deflateGetDictionary( + /// # strm: *mut std::ffi::c_void, + /// # dictionary: *mut u8, + /// # dictLength: *mut usize, + /// # ) -> i32; + /// # } + /// # impl StreamWrapper { + /// pub fn get_dictionary(&self) -> Option> { + /// // Per the FFI method's docs, "32768 bytes is always enough". + /// let mut dict = Vec::with_capacity(32_768); + /// let mut dict_length = 0; + /// // SAFETY: When `deflateGetDictionary` returns `Z_OK`, it holds that: + /// // 1. `dict_length` elements were initialized. + /// // 2. `dict_length` <= the capacity (32_768) + /// // which makes `set_len` safe to call. + /// unsafe { + /// // Make the FFI call... + /// let r = deflateGetDictionary(self.strm, dict.as_mut_ptr(), &mut dict_length); + /// if r == Z_OK { + /// // ...and update the length to what was initialized. + /// dict.set_len(dict_length); + /// Some(dict) + /// } else { + /// None + /// } + /// } + /// } + /// # } + /// ``` + /// + /// While the following example is sound, there is a memory leak since + /// the inner vectors were not freed prior to the `set_len` call: + /// + /// ``` + /// let mut vec = vec![vec![1, 0, 0], + /// vec![0, 1, 0], + /// vec![0, 0, 1]]; + /// // SAFETY: + /// // 1. `old_len..0` is empty so no elements need to be initialized. + /// // 2. `0 <= capacity` always holds whatever `capacity` is. + /// unsafe { + /// vec.set_len(0); + /// } + /// ``` + /// + /// Normally, here, one would use [`clear`] instead to correctly drop + /// the contents and thus not leak memory. + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub unsafe fn set_len(&mut self, new_len: usize) { + debug_assert!(new_len <= self.capacity()); + + self.len = new_len; + } + + /// Removes an element from the vector and returns it. + /// + /// The removed element is replaced by the last element of the vector. + /// + /// This does not preserve ordering, but is O(1). + /// + /// # Panics + /// + /// Panics if `index` is out of bounds. + /// + /// # Examples + /// + /// ``` + /// let mut v = vec!["foo", "bar", "baz", "qux"]; + /// + /// assert_eq!(v.swap_remove(1), "bar"); + /// assert_eq!(v, ["foo", "qux", "baz"]); + /// + /// assert_eq!(v.swap_remove(0), "foo"); + /// assert_eq!(v, ["baz", "qux"]); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn swap_remove(&mut self, index: usize) -> T { + #[cold] + #[inline(never)] + fn assert_failed(index: usize, len: usize) -> ! { + panic!("swap_remove index (is {}) should be < len (is {})", index, len); + } + + let len = self.len(); + if index >= len { + assert_failed(index, len); + } + unsafe { + // We replace self[index] with the last element. Note that if the + // bounds check above succeeds there must be a last element (which + // can be self[index] itself). + let last = ptr::read(self.as_ptr().add(len - 1)); + let hole = self.as_mut_ptr().add(index); + self.set_len(len - 1); + ptr::replace(hole, last) + } + } + + /// Inserts an element at position `index` within the vector, shifting all + /// elements after it to the right. + /// + /// # Panics + /// + /// Panics if `index > len`. + /// + /// # Examples + /// + /// ``` + /// let mut vec = vec![1, 2, 3]; + /// vec.insert(1, 4); + /// assert_eq!(vec, [1, 4, 2, 3]); + /// vec.insert(4, 5); + /// assert_eq!(vec, [1, 4, 2, 3, 5]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn insert(&mut self, index: usize, element: T) { + #[cold] + #[inline(never)] + fn assert_failed(index: usize, len: usize) -> ! { + panic!("insertion index (is {}) should be <= len (is {})", index, len); + } + + let len = self.len(); + if index > len { + assert_failed(index, len); + } + + // space for the new element + if len == self.buf.capacity() { + self.reserve(1); + } + + unsafe { + // infallible + // The spot to put the new value + { + let p = self.as_mut_ptr().add(index); + // Shift everything over to make space. (Duplicating the + // `index`th element into two consecutive places.) + ptr::copy(p, p.offset(1), len - index); + // Write it in, overwriting the first copy of the `index`th + // element. + ptr::write(p, element); + } + self.set_len(len + 1); + } + } + + /// Removes and returns the element at position `index` within the vector, + /// shifting all elements after it to the left. + /// + /// # Panics + /// + /// Panics if `index` is out of bounds. + /// + /// # Examples + /// + /// ``` + /// let mut v = vec![1, 2, 3]; + /// assert_eq!(v.remove(1), 2); + /// assert_eq!(v, [1, 3]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn remove(&mut self, index: usize) -> T { + #[cold] + #[inline(never)] + fn assert_failed(index: usize, len: usize) -> ! { + panic!("removal index (is {}) should be < len (is {})", index, len); + } + + let len = self.len(); + if index >= len { + assert_failed(index, len); + } + unsafe { + // infallible + let ret; + { + // the place we are taking from. + let ptr = self.as_mut_ptr().add(index); + // copy it out, unsafely having a copy of the value on + // the stack and in the vector at the same time. + ret = ptr::read(ptr); + + // Shift everything down to fill in that spot. + ptr::copy(ptr.offset(1), ptr, len - index - 1); + } + self.set_len(len - 1); + ret + } + } + + /// Retains only the elements specified by the predicate. + /// + /// In other words, remove all elements `e` such that `f(&e)` returns `false`. + /// This method operates in place, visiting each element exactly once in the + /// original order, and preserves the order of the retained elements. + /// + /// # Examples + /// + /// ``` + /// let mut vec = vec![1, 2, 3, 4]; + /// vec.retain(|&x| x % 2 == 0); + /// assert_eq!(vec, [2, 4]); + /// ``` + /// + /// The exact order may be useful for tracking external state, like an index. + /// + /// ``` + /// let mut vec = vec![1, 2, 3, 4, 5]; + /// let keep = [false, true, true, false, true]; + /// let mut i = 0; + /// vec.retain(|_| (keep[i], i += 1).0); + /// assert_eq!(vec, [2, 3, 5]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn retain(&mut self, mut f: F) + where + F: FnMut(&T) -> bool, + { + let len = self.len(); + let mut del = 0; + { + let v = &mut **self; + + for i in 0..len { + if !f(&v[i]) { + del += 1; + } else if del > 0 { + v.swap(i - del, i); + } + } + } + if del > 0 { + self.truncate(len - del); + } + } + + /// Removes all but the first of consecutive elements in the vector that resolve to the same + /// key. + /// + /// If the vector is sorted, this removes all duplicates. + /// + /// # Examples + /// + /// ``` + /// let mut vec = vec![10, 20, 21, 30, 20]; + /// + /// vec.dedup_by_key(|i| *i / 10); + /// + /// assert_eq!(vec, [10, 20, 30, 20]); + /// ``` + #[stable(feature = "dedup_by", since = "1.16.0")] + #[inline] + pub fn dedup_by_key(&mut self, mut key: F) + where + F: FnMut(&mut T) -> K, + K: PartialEq, + { + self.dedup_by(|a, b| key(a) == key(b)) + } + + /// Removes all but the first of consecutive elements in the vector satisfying a given equality + /// relation. + /// + /// The `same_bucket` function is passed references to two elements from the vector and + /// must determine if the elements compare equal. The elements are passed in opposite order + /// from their order in the slice, so if `same_bucket(a, b)` returns `true`, `a` is removed. + /// + /// If the vector is sorted, this removes all duplicates. + /// + /// # Examples + /// + /// ``` + /// let mut vec = vec!["foo", "bar", "Bar", "baz", "bar"]; + /// + /// vec.dedup_by(|a, b| a.eq_ignore_ascii_case(b)); + /// + /// assert_eq!(vec, ["foo", "bar", "baz", "bar"]); + /// ``` + #[stable(feature = "dedup_by", since = "1.16.0")] + pub fn dedup_by(&mut self, same_bucket: F) + where + F: FnMut(&mut T, &mut T) -> bool, + { + let len = { + let (dedup, _) = self.as_mut_slice().partition_dedup_by(same_bucket); + dedup.len() + }; + self.truncate(len); + } + + /// Appends an element to the back of a collection. + /// + /// # Panics + /// + /// Panics if the new capacity exceeds `isize::MAX` bytes. + /// + /// # Examples + /// + /// ``` + /// let mut vec = vec![1, 2]; + /// vec.push(3); + /// assert_eq!(vec, [1, 2, 3]); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn push(&mut self, value: T) { + // This will panic or abort if we would allocate > isize::MAX bytes + // or if the length increment would overflow for zero-sized types. + if self.len == self.buf.capacity() { + self.reserve(1); + } + unsafe { + let end = self.as_mut_ptr().add(self.len); + ptr::write(end, value); + self.len += 1; + } + } + + /// Removes the last element from a vector and returns it, or [`None`] if it + /// is empty. + /// + /// # Examples + /// + /// ``` + /// let mut vec = vec![1, 2, 3]; + /// assert_eq!(vec.pop(), Some(3)); + /// assert_eq!(vec, [1, 2]); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn pop(&mut self) -> Option { + if self.len == 0 { + None + } else { + unsafe { + self.len -= 1; + Some(ptr::read(self.as_ptr().add(self.len()))) + } + } + } + + /// Moves all the elements of `other` into `Self`, leaving `other` empty. + /// + /// # Panics + /// + /// Panics if the number of elements in the vector overflows a `usize`. + /// + /// # Examples + /// + /// ``` + /// let mut vec = vec![1, 2, 3]; + /// let mut vec2 = vec![4, 5, 6]; + /// vec.append(&mut vec2); + /// assert_eq!(vec, [1, 2, 3, 4, 5, 6]); + /// assert_eq!(vec2, []); + /// ``` + #[inline] + #[stable(feature = "append", since = "1.4.0")] + pub fn append(&mut self, other: &mut Self) { + unsafe { + self.append_elements(other.as_slice() as _); + other.set_len(0); + } + } + + /// Appends elements to `Self` from other buffer. + #[inline] + unsafe fn append_elements(&mut self, other: *const [T]) { + let count = unsafe { (*other).len() }; + self.reserve(count); + let len = self.len(); + unsafe { ptr::copy_nonoverlapping(other as *const T, self.as_mut_ptr().add(len), count) }; + self.len += count; + } + + /// Creates a draining iterator that removes the specified range in the vector + /// and yields the removed items. + /// + /// When the iterator **is** dropped, all elements in the range are removed + /// from the vector, even if the iterator was not fully consumed. If the + /// iterator **is not** dropped (with [`mem::forget`] for example), it is + /// unspecified how many elements are removed. + /// + /// # Panics + /// + /// Panics if the starting point is greater than the end point or if + /// the end point is greater than the length of the vector. + /// + /// # Examples + /// + /// ``` + /// let mut v = vec![1, 2, 3]; + /// let u: Vec<_> = v.drain(1..).collect(); + /// assert_eq!(v, &[1]); + /// assert_eq!(u, &[2, 3]); + /// + /// // A full range clears the vector + /// v.drain(..); + /// assert_eq!(v, &[]); + /// ``` + #[stable(feature = "drain", since = "1.6.0")] + pub fn drain(&mut self, range: R) -> Drain<'_, T, A> + where + R: RangeBounds, + { + // Memory safety + // + // When the Drain is first created, it shortens the length of + // the source vector to make sure no uninitialized or moved-from elements + // are accessible at all if the Drain's destructor never gets to run. + // + // Drain will ptr::read out the values to remove. + // When finished, remaining tail of the vec is copied back to cover + // the hole, and the vector length is restored to the new length. + // + let len = self.len(); + let Range { start, end } = range.assert_len(len); + + unsafe { + // set self.vec length's to start, to be safe in case Drain is leaked + self.set_len(start); + // Use the borrow in the IterMut to indicate borrowing behavior of the + // whole Drain iterator (like &mut T). + let range_slice = slice::from_raw_parts_mut(self.as_mut_ptr().add(start), end - start); + Drain { + tail_start: end, + tail_len: len - end, + iter: range_slice.iter(), + vec: NonNull::from(self), + } + } + } + + /// Clears the vector, removing all values. + /// + /// Note that this method has no effect on the allocated capacity + /// of the vector. + /// + /// # Examples + /// + /// ``` + /// let mut v = vec![1, 2, 3]; + /// + /// v.clear(); + /// + /// assert!(v.is_empty()); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn clear(&mut self) { + self.truncate(0) + } + + /// Returns the number of elements in the vector, also referred to + /// as its 'length'. + /// + /// # Examples + /// + /// ``` + /// let a = vec![1, 2, 3]; + /// assert_eq!(a.len(), 3); + /// ``` + #[doc(alias = "length")] + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn len(&self) -> usize { + self.len + } + + /// Returns `true` if the vector contains no elements. + /// + /// # Examples + /// + /// ``` + /// let mut v = Vec::new(); + /// assert!(v.is_empty()); + /// + /// v.push(1); + /// assert!(!v.is_empty()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + /// Splits the collection into two at the given index. + /// + /// Returns a newly allocated vector containing the elements in the range + /// `[at, len)`. After the call, the original vector will be left containing + /// the elements `[0, at)` with its previous capacity unchanged. + /// + /// # Panics + /// + /// Panics if `at > len`. + /// + /// # Examples + /// + /// ``` + /// let mut vec = vec![1, 2, 3]; + /// let vec2 = vec.split_off(1); + /// assert_eq!(vec, [1]); + /// assert_eq!(vec2, [2, 3]); + /// ``` + #[inline] + #[must_use = "use `.truncate()` if you don't need the other half"] + #[stable(feature = "split_off", since = "1.4.0")] + pub fn split_off(&mut self, at: usize) -> Self + where + A: Clone, + { + #[cold] + #[inline(never)] + fn assert_failed(at: usize, len: usize) -> ! { + panic!("`at` split index (is {}) should be <= len (is {})", at, len); + } + + if at > self.len() { + assert_failed(at, self.len()); + } + + if at == 0 { + // the new vector can take over the original buffer and avoid the copy + return mem::replace( + self, + Vec::with_capacity_in(self.capacity(), self.allocator().clone()), + ); + } + + let other_len = self.len - at; + let mut other = Vec::with_capacity_in(other_len, self.allocator().clone()); + + // Unsafely `set_len` and copy items to `other`. + unsafe { + self.set_len(at); + other.set_len(other_len); + + ptr::copy_nonoverlapping(self.as_ptr().add(at), other.as_mut_ptr(), other.len()); + } + other + } + + /// Resizes the `Vec` in-place so that `len` is equal to `new_len`. + /// + /// If `new_len` is greater than `len`, the `Vec` is extended by the + /// difference, with each additional slot filled with the result of + /// calling the closure `f`. The return values from `f` will end up + /// in the `Vec` in the order they have been generated. + /// + /// If `new_len` is less than `len`, the `Vec` is simply truncated. + /// + /// This method uses a closure to create new values on every push. If + /// you'd rather [`Clone`] a given value, use [`Vec::resize`]. If you + /// want to use the [`Default`] trait to generate values, you can + /// pass [`Default::default`] as the second argument. + /// + /// # Examples + /// + /// ``` + /// let mut vec = vec![1, 2, 3]; + /// vec.resize_with(5, Default::default); + /// assert_eq!(vec, [1, 2, 3, 0, 0]); + /// + /// let mut vec = vec![]; + /// let mut p = 1; + /// vec.resize_with(4, || { p *= 2; p }); + /// assert_eq!(vec, [2, 4, 8, 16]); + /// ``` + #[stable(feature = "vec_resize_with", since = "1.33.0")] + pub fn resize_with(&mut self, new_len: usize, f: F) + where + F: FnMut() -> T, + { + let len = self.len(); + if new_len > len { + self.extend_with(new_len - len, ExtendFunc(f)); + } else { + self.truncate(new_len); + } + } + + /// Consumes and leaks the `Vec`, returning a mutable reference to the contents, + /// `&'a mut [T]`. Note that the type `T` must outlive the chosen lifetime + /// `'a`. If the type has only static references, or none at all, then this + /// may be chosen to be `'static`. + /// + /// This function is similar to the [`leak`][Box::leak] function on [`Box`] + /// except that there is no way to recover the leaked memory. + /// + /// This function is mainly useful for data that lives for the remainder of + /// the program's life. Dropping the returned reference will cause a memory + /// leak. + /// + /// # Examples + /// + /// Simple usage: + /// + /// ``` + /// let x = vec![1, 2, 3]; + /// let static_ref: &'static mut [usize] = x.leak(); + /// static_ref[0] += 1; + /// assert_eq!(static_ref, &[2, 2, 3]); + /// ``` + #[stable(feature = "vec_leak", since = "1.47.0")] + #[inline] + pub fn leak<'a>(self) -> &'a mut [T] + where + A: 'a, + { + Box::leak(self.into_boxed_slice()) + } + + /// Returns the remaining spare capacity of the vector as a slice of + /// `MaybeUninit`. + /// + /// The returned slice can be used to fill the vector with data (e.g. by + /// reading from a file) before marking the data as initialized using the + /// [`set_len`] method. + /// + /// [`set_len`]: Vec::set_len + /// + /// # Examples + /// + /// ``` + /// #![feature(vec_spare_capacity, maybe_uninit_extra)] + /// + /// // Allocate vector big enough for 10 elements. + /// let mut v = Vec::with_capacity(10); + /// + /// // Fill in the first 3 elements. + /// let uninit = v.spare_capacity_mut(); + /// uninit[0].write(0); + /// uninit[1].write(1); + /// uninit[2].write(2); + /// + /// // Mark the first 3 elements of the vector as being initialized. + /// unsafe { + /// v.set_len(3); + /// } + /// + /// assert_eq!(&v, &[0, 1, 2]); + /// ``` + #[unstable(feature = "vec_spare_capacity", issue = "75017")] + #[inline] + pub fn spare_capacity_mut(&mut self) -> &mut [MaybeUninit] { + unsafe { + slice::from_raw_parts_mut( + self.as_mut_ptr().add(self.len) as *mut MaybeUninit, + self.buf.capacity() - self.len, + ) + } + } +} + +impl Vec { + /// Resizes the `Vec` in-place so that `len` is equal to `new_len`. + /// + /// If `new_len` is greater than `len`, the `Vec` is extended by the + /// difference, with each additional slot filled with `value`. + /// If `new_len` is less than `len`, the `Vec` is simply truncated. + /// + /// This method requires `T` to implement [`Clone`], + /// in order to be able to clone the passed value. + /// If you need more flexibility (or want to rely on [`Default`] instead of + /// [`Clone`]), use [`Vec::resize_with`]. + /// + /// # Examples + /// + /// ``` + /// let mut vec = vec!["hello"]; + /// vec.resize(3, "world"); + /// assert_eq!(vec, ["hello", "world", "world"]); + /// + /// let mut vec = vec![1, 2, 3, 4]; + /// vec.resize(2, 0); + /// assert_eq!(vec, [1, 2]); + /// ``` + #[stable(feature = "vec_resize", since = "1.5.0")] + pub fn resize(&mut self, new_len: usize, value: T) { + let len = self.len(); + + if new_len > len { + self.extend_with(new_len - len, ExtendElement(value)) + } else { + self.truncate(new_len); + } + } + + /// Clones and appends all elements in a slice to the `Vec`. + /// + /// Iterates over the slice `other`, clones each element, and then appends + /// it to this `Vec`. The `other` vector is traversed in-order. + /// + /// Note that this function is same as [`extend`] except that it is + /// specialized to work with slices instead. If and when Rust gets + /// specialization this function will likely be deprecated (but still + /// available). + /// + /// # Examples + /// + /// ``` + /// let mut vec = vec![1]; + /// vec.extend_from_slice(&[2, 3, 4]); + /// assert_eq!(vec, [1, 2, 3, 4]); + /// ``` + /// + /// [`extend`]: Vec::extend + #[stable(feature = "vec_extend_from_slice", since = "1.6.0")] + pub fn extend_from_slice(&mut self, other: &[T]) { + self.spec_extend(other.iter()) + } +} + +// This code generalizes `extend_with_{element,default}`. +trait ExtendWith { + fn next(&mut self) -> T; + fn last(self) -> T; +} + +struct ExtendElement(T); +impl ExtendWith for ExtendElement { + fn next(&mut self) -> T { + self.0.clone() + } + fn last(self) -> T { + self.0 + } +} + +struct ExtendDefault; +impl ExtendWith for ExtendDefault { + fn next(&mut self) -> T { + Default::default() + } + fn last(self) -> T { + Default::default() + } +} + +struct ExtendFunc(F); +impl T> ExtendWith for ExtendFunc { + fn next(&mut self) -> T { + (self.0)() + } + fn last(mut self) -> T { + (self.0)() + } +} + +impl Vec { + /// Extend the vector by `n` values, using the given generator. + fn extend_with>(&mut self, n: usize, mut value: E) { + self.reserve(n); + + unsafe { + let mut ptr = self.as_mut_ptr().add(self.len()); + // Use SetLenOnDrop to work around bug where compiler + // may not realize the store through `ptr` through self.set_len() + // don't alias. + let mut local_len = SetLenOnDrop::new(&mut self.len); + + // Write all elements except the last one + for _ in 1..n { + ptr::write(ptr, value.next()); + ptr = ptr.offset(1); + // Increment the length in every step in case next() panics + local_len.increment_len(1); + } + + if n > 0 { + // We can write the last element directly without cloning needlessly + ptr::write(ptr, value.last()); + local_len.increment_len(1); + } + + // len set by scope guard + } + } +} + +impl Vec { + /// Removes consecutive repeated elements in the vector according to the + /// [`PartialEq`] trait implementation. + /// + /// If the vector is sorted, this removes all duplicates. + /// + /// # Examples + /// + /// ``` + /// let mut vec = vec![1, 2, 2, 3, 2]; + /// + /// vec.dedup(); + /// + /// assert_eq!(vec, [1, 2, 3, 2]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn dedup(&mut self) { + self.dedup_by(|a, b| a == b) + } +} + +impl Vec { + /// Removes the first instance of `item` from the vector if the item exists. + /// + /// This method will be removed soon. + #[unstable(feature = "vec_remove_item", reason = "recently added", issue = "40062")] + #[rustc_deprecated( + reason = "Removing the first item equal to a needle is already easily possible \ + with iterators and the current Vec methods. Furthermore, having a method for \ + one particular case of removal (linear search, only the first item, no swap remove) \ + but not for others is inconsistent. This method will be removed soon.", + since = "1.46.0" + )] + pub fn remove_item(&mut self, item: &V) -> Option + where + T: PartialEq, + { + let pos = self.iter().position(|x| *x == *item)?; + Some(self.remove(pos)) + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Internal methods and functions +//////////////////////////////////////////////////////////////////////////////// + +#[doc(hidden)] +#[stable(feature = "rust1", since = "1.0.0")] +pub fn from_elem(elem: T, n: usize) -> Vec { + ::from_elem(elem, n, Global) +} + +#[doc(hidden)] +#[unstable(feature = "allocator_api", issue = "32838")] +pub fn from_elem_in(elem: T, n: usize, alloc: A) -> Vec { + ::from_elem(elem, n, alloc) +} + +//////////////////////////////////////////////////////////////////////////////// +// Common trait implementations for Vec +//////////////////////////////////////////////////////////////////////////////// + +#[stable(feature = "rust1", since = "1.0.0")] +impl ops::Deref for Vec { + type Target = [T]; + + fn deref(&self) -> &[T] { + unsafe { slice::from_raw_parts(self.as_ptr(), self.len) } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ops::DerefMut for Vec { + fn deref_mut(&mut self) -> &mut [T] { + unsafe { slice::from_raw_parts_mut(self.as_mut_ptr(), self.len) } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for Vec { + #[cfg(not(test))] + fn clone(&self) -> Self { + let alloc = self.allocator().clone(); + <[T]>::to_vec_in(&**self, alloc) + } + + // HACK(japaric): with cfg(test) the inherent `[T]::to_vec` method, which is + // required for this method definition, is not available. Instead use the + // `slice::to_vec` function which is only available with cfg(test) + // NB see the slice::hack module in slice.rs for more information + #[cfg(test)] + fn clone(&self) -> Self { + let alloc = self.allocator().clone(); + crate::slice::to_vec(&**self, alloc) + } + + fn clone_from(&mut self, other: &Self) { + // drop anything that will not be overwritten + self.truncate(other.len()); + + // self.len <= other.len due to the truncate above, so the + // slices here are always in-bounds. + let (init, tail) = other.split_at(self.len()); + + // reuse the contained values' allocations/resources. + self.clone_from_slice(init); + self.extend_from_slice(tail); + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Hash for Vec { + #[inline] + fn hash(&self, state: &mut H) { + Hash::hash(&**self, state) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented( + message = "vector indices are of type `usize` or ranges of `usize`", + label = "vector indices are of type `usize` or ranges of `usize`" +)] +impl, A: Allocator> Index for Vec { + type Output = I::Output; + + #[inline] + fn index(&self, index: I) -> &Self::Output { + Index::index(&**self, index) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented( + message = "vector indices are of type `usize` or ranges of `usize`", + label = "vector indices are of type `usize` or ranges of `usize`" +)] +impl, A: Allocator> IndexMut for Vec { + #[inline] + fn index_mut(&mut self, index: I) -> &mut Self::Output { + IndexMut::index_mut(&mut **self, index) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl FromIterator for Vec { + #[inline] + fn from_iter>(iter: I) -> Vec { + >::from_iter(iter.into_iter()) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl IntoIterator for Vec { + type Item = T; + type IntoIter = IntoIter; + + /// Creates a consuming iterator, that is, one that moves each value out of + /// the vector (from start to end). The vector cannot be used after calling + /// this. + /// + /// # Examples + /// + /// ``` + /// let v = vec!["a".to_string(), "b".to_string()]; + /// for s in v.into_iter() { + /// // s has type String, not &String + /// println!("{}", s); + /// } + /// ``` + #[inline] + fn into_iter(self) -> IntoIter { + unsafe { + let mut me = ManuallyDrop::new(self); + let alloc = ptr::read(me.allocator()); + let begin = me.as_mut_ptr(); + let end = if mem::size_of::() == 0 { + arith_offset(begin as *const i8, me.len() as isize) as *const T + } else { + begin.add(me.len()) as *const T + }; + let cap = me.buf.capacity(); + IntoIter { + buf: NonNull::new_unchecked(begin), + phantom: PhantomData, + cap, + alloc, + ptr: begin, + end, + } + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T, A: Allocator> IntoIterator for &'a Vec { + type Item = &'a T; + type IntoIter = slice::Iter<'a, T>; + + fn into_iter(self) -> slice::Iter<'a, T> { + self.iter() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T, A: Allocator> IntoIterator for &'a mut Vec { + type Item = &'a mut T; + type IntoIter = slice::IterMut<'a, T>; + + fn into_iter(self) -> slice::IterMut<'a, T> { + self.iter_mut() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Extend for Vec { + #[inline] + fn extend>(&mut self, iter: I) { + >::spec_extend(self, iter.into_iter()) + } + + #[inline] + fn extend_one(&mut self, item: T) { + self.push(item); + } + + #[inline] + fn extend_reserve(&mut self, additional: usize) { + self.reserve(additional); + } +} + +impl Vec { + // leaf method to which various SpecFrom/SpecExtend implementations delegate when + // they have no further optimizations to apply + fn extend_desugared>(&mut self, mut iterator: I) { + // This is the case for a general iterator. + // + // This function should be the moral equivalent of: + // + // for item in iterator { + // self.push(item); + // } + while let Some(element) = iterator.next() { + let len = self.len(); + if len == self.capacity() { + let (lower, _) = iterator.size_hint(); + self.reserve(lower.saturating_add(1)); + } + unsafe { + ptr::write(self.as_mut_ptr().add(len), element); + // NB can't overflow since we would have had to alloc the address space + self.set_len(len + 1); + } + } + } + + /// Creates a splicing iterator that replaces the specified range in the vector + /// with the given `replace_with` iterator and yields the removed items. + /// `replace_with` does not need to be the same length as `range`. + /// + /// `range` is removed even if the iterator is not consumed until the end. + /// + /// It is unspecified how many elements are removed from the vector + /// if the `Splice` value is leaked. + /// + /// The input iterator `replace_with` is only consumed when the `Splice` value is dropped. + /// + /// This is optimal if: + /// + /// * The tail (elements in the vector after `range`) is empty, + /// * or `replace_with` yields fewer elements than `range`’s length + /// * or the lower bound of its `size_hint()` is exact. + /// + /// Otherwise, a temporary vector is allocated and the tail is moved twice. + /// + /// # Panics + /// + /// Panics if the starting point is greater than the end point or if + /// the end point is greater than the length of the vector. + /// + /// # Examples + /// + /// ``` + /// let mut v = vec![1, 2, 3]; + /// let new = [7, 8]; + /// let u: Vec<_> = v.splice(..2, new.iter().cloned()).collect(); + /// assert_eq!(v, &[7, 8, 3]); + /// assert_eq!(u, &[1, 2]); + /// ``` + #[inline] + #[stable(feature = "vec_splice", since = "1.21.0")] + pub fn splice(&mut self, range: R, replace_with: I) -> Splice<'_, I::IntoIter, A> + where + R: RangeBounds, + I: IntoIterator, + { + Splice { drain: self.drain(range), replace_with: replace_with.into_iter() } + } + + /// Creates an iterator which uses a closure to determine if an element should be removed. + /// + /// If the closure returns true, then the element is removed and yielded. + /// If the closure returns false, the element will remain in the vector and will not be yielded + /// by the iterator. + /// + /// Using this method is equivalent to the following code: + /// + /// ``` + /// # let some_predicate = |x: &mut i32| { *x == 2 || *x == 3 || *x == 6 }; + /// # let mut vec = vec![1, 2, 3, 4, 5, 6]; + /// let mut i = 0; + /// while i != vec.len() { + /// if some_predicate(&mut vec[i]) { + /// let val = vec.remove(i); + /// // your code here + /// } else { + /// i += 1; + /// } + /// } + /// + /// # assert_eq!(vec, vec![1, 4, 5]); + /// ``` + /// + /// But `drain_filter` is easier to use. `drain_filter` is also more efficient, + /// because it can backshift the elements of the array in bulk. + /// + /// Note that `drain_filter` also lets you mutate every element in the filter closure, + /// regardless of whether you choose to keep or remove it. + /// + /// # Examples + /// + /// Splitting an array into evens and odds, reusing the original allocation: + /// + /// ``` + /// #![feature(drain_filter)] + /// let mut numbers = vec![1, 2, 3, 4, 5, 6, 8, 9, 11, 13, 14, 15]; + /// + /// let evens = numbers.drain_filter(|x| *x % 2 == 0).collect::>(); + /// let odds = numbers; + /// + /// assert_eq!(evens, vec![2, 4, 6, 8, 14]); + /// assert_eq!(odds, vec![1, 3, 5, 9, 11, 13, 15]); + /// ``` + #[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] + pub fn drain_filter(&mut self, filter: F) -> DrainFilter<'_, T, F, A> + where + F: FnMut(&mut T) -> bool, + { + let old_len = self.len(); + + // Guard against us getting leaked (leak amplification) + unsafe { + self.set_len(0); + } + + DrainFilter { vec: self, idx: 0, del: 0, old_len, pred: filter, panic_flag: false } + } +} + +/// Extend implementation that copies elements out of references before pushing them onto the Vec. +/// +/// This implementation is specialized for slice iterators, where it uses [`copy_from_slice`] to +/// append the entire slice at once. +/// +/// [`copy_from_slice`]: ../../std/primitive.slice.html#method.copy_from_slice +#[stable(feature = "extend_ref", since = "1.2.0")] +impl<'a, T: Copy + 'a, A: Allocator + 'a> Extend<&'a T> for Vec { + fn extend>(&mut self, iter: I) { + self.spec_extend(iter.into_iter()) + } + + #[inline] + fn extend_one(&mut self, &item: &'a T) { + self.push(item); + } + + #[inline] + fn extend_reserve(&mut self, additional: usize) { + self.reserve(additional); + } +} + +/// Implements comparison of vectors, [lexicographically](core::cmp::Ord#lexicographical-comparison). +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialOrd for Vec { + #[inline] + fn partial_cmp(&self, other: &Self) -> Option { + PartialOrd::partial_cmp(&**self, &**other) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Eq for Vec {} + +/// Implements ordering of vectors, [lexicographically](core::cmp::Ord#lexicographical-comparison). +#[stable(feature = "rust1", since = "1.0.0")] +impl Ord for Vec { + #[inline] + fn cmp(&self, other: &Self) -> Ordering { + Ord::cmp(&**self, &**other) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl<#[may_dangle] T, A: Allocator> Drop for Vec { + fn drop(&mut self) { + unsafe { + // use drop for [T] + // use a raw slice to refer to the elements of the vector as weakest necessary type; + // could avoid questions of validity in certain cases + ptr::drop_in_place(ptr::slice_from_raw_parts_mut(self.as_mut_ptr(), self.len)) + } + // RawVec handles deallocation + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Default for Vec { + /// Creates an empty `Vec`. + fn default() -> Vec { + Vec::new() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for Vec { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&**self, f) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl AsRef> for Vec { + fn as_ref(&self) -> &Vec { + self + } +} + +#[stable(feature = "vec_as_mut", since = "1.5.0")] +impl AsMut> for Vec { + fn as_mut(&mut self) -> &mut Vec { + self + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl AsRef<[T]> for Vec { + fn as_ref(&self) -> &[T] { + self + } +} + +#[stable(feature = "vec_as_mut", since = "1.5.0")] +impl AsMut<[T]> for Vec { + fn as_mut(&mut self) -> &mut [T] { + self + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl From<&[T]> for Vec { + #[cfg(not(test))] + fn from(s: &[T]) -> Vec { + s.to_vec() + } + #[cfg(test)] + fn from(s: &[T]) -> Vec { + crate::slice::to_vec(s, Global) + } +} + +#[stable(feature = "vec_from_mut", since = "1.19.0")] +impl From<&mut [T]> for Vec { + #[cfg(not(test))] + fn from(s: &mut [T]) -> Vec { + s.to_vec() + } + #[cfg(test)] + fn from(s: &mut [T]) -> Vec { + crate::slice::to_vec(s, Global) + } +} + +#[stable(feature = "vec_from_array", since = "1.44.0")] +impl From<[T; N]> for Vec { + #[cfg(not(test))] + fn from(s: [T; N]) -> Vec { + <[T]>::into_vec(box s) + } + #[cfg(test)] + fn from(s: [T; N]) -> Vec { + crate::slice::into_vec(box s) + } +} + +#[stable(feature = "vec_from_cow_slice", since = "1.14.0")] +impl<'a, T> From> for Vec +where + [T]: ToOwned>, +{ + fn from(s: Cow<'a, [T]>) -> Vec { + s.into_owned() + } +} + +// note: test pulls in libstd, which causes errors here +#[cfg(not(test))] +#[stable(feature = "vec_from_box", since = "1.18.0")] +impl From> for Vec { + fn from(s: Box<[T], A>) -> Self { + let len = s.len(); + Self { buf: RawVec::from_box(s), len } + } +} + +// note: test pulls in libstd, which causes errors here +#[cfg(not(test))] +#[stable(feature = "box_from_vec", since = "1.20.0")] +impl From> for Box<[T], A> { + fn from(v: Vec) -> Self { + v.into_boxed_slice() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl From<&str> for Vec { + fn from(s: &str) -> Vec { + From::from(s.as_bytes()) + } +} + +#[stable(feature = "array_try_from_vec", since = "1.48.0")] +impl TryFrom> for [T; N] { + type Error = Vec; + + /// Gets the entire contents of the `Vec` as an array, + /// if its size exactly matches that of the requested array. + /// + /// # Examples + /// + /// ``` + /// use std::convert::TryInto; + /// assert_eq!(vec![1, 2, 3].try_into(), Ok([1, 2, 3])); + /// assert_eq!(>::new().try_into(), Ok([])); + /// ``` + /// + /// If the length doesn't match, the input comes back in `Err`: + /// ``` + /// use std::convert::TryInto; + /// let r: Result<[i32; 4], _> = (0..10).collect::>().try_into(); + /// assert_eq!(r, Err(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9])); + /// ``` + /// + /// If you're fine with just getting a prefix of the `Vec`, + /// you can call [`.truncate(N)`](Vec::truncate) first. + /// ``` + /// use std::convert::TryInto; + /// let mut v = String::from("hello world").into_bytes(); + /// v.sort(); + /// v.truncate(2); + /// let [a, b]: [_; 2] = v.try_into().unwrap(); + /// assert_eq!(a, b' '); + /// assert_eq!(b, b'd'); + /// ``` + fn try_from(mut vec: Vec) -> Result<[T; N], Vec> { + if vec.len() != N { + return Err(vec); + } + + // SAFETY: `.set_len(0)` is always sound. + unsafe { vec.set_len(0) }; + + // SAFETY: A `Vec`'s pointer is always aligned properly, and + // the alignment the array needs is the same as the items. + // We checked earlier that we have sufficient items. + // The items will not double-drop as the `set_len` + // tells the `Vec` not to also drop them. + let array = unsafe { ptr::read(vec.as_ptr() as *const [T; N]) }; + Ok(array) + } +} diff --git a/library/alloc/src/vec/partial_eq.rs b/library/alloc/src/vec/partial_eq.rs new file mode 100644 index 00000000000..ff90b6caf46 --- /dev/null +++ b/library/alloc/src/vec/partial_eq.rs @@ -0,0 +1,43 @@ +use crate::alloc::Allocator; +use crate::borrow::Cow; + +use super::Vec; + +macro_rules! __impl_slice_eq1 { + ([$($vars:tt)*] $lhs:ty, $rhs:ty $(where $ty:ty: $bound:ident)?, #[$stability:meta]) => { + #[$stability] + impl PartialEq<$rhs> for $lhs + where + T: PartialEq, + $($ty: $bound)? + { + #[inline] + fn eq(&self, other: &$rhs) -> bool { self[..] == other[..] } + #[inline] + fn ne(&self, other: &$rhs) -> bool { self[..] != other[..] } + } + } +} + +__impl_slice_eq1! { [A: Allocator] Vec, Vec, #[stable(feature = "rust1", since = "1.0.0")] } +__impl_slice_eq1! { [A: Allocator] Vec, &[U], #[stable(feature = "rust1", since = "1.0.0")] } +__impl_slice_eq1! { [A: Allocator] Vec, &mut [U], #[stable(feature = "rust1", since = "1.0.0")] } +__impl_slice_eq1! { [A: Allocator] &[T], Vec, #[stable(feature = "partialeq_vec_for_ref_slice", since = "1.46.0")] } +__impl_slice_eq1! { [A: Allocator] &mut [T], Vec, #[stable(feature = "partialeq_vec_for_ref_slice", since = "1.46.0")] } +__impl_slice_eq1! { [A: Allocator] Vec, [U], #[stable(feature = "partialeq_vec_for_slice", since = "1.48.0")] } +__impl_slice_eq1! { [A: Allocator] [T], Vec, #[stable(feature = "partialeq_vec_for_slice", since = "1.48.0")] } +__impl_slice_eq1! { [A: Allocator] Cow<'_, [T]>, Vec where T: Clone, #[stable(feature = "rust1", since = "1.0.0")] } +__impl_slice_eq1! { [] Cow<'_, [T]>, &[U] where T: Clone, #[stable(feature = "rust1", since = "1.0.0")] } +__impl_slice_eq1! { [] Cow<'_, [T]>, &mut [U] where T: Clone, #[stable(feature = "rust1", since = "1.0.0")] } +__impl_slice_eq1! { [A: Allocator, const N: usize] Vec, [U; N], #[stable(feature = "rust1", since = "1.0.0")] } +__impl_slice_eq1! { [A: Allocator, const N: usize] Vec, &[U; N], #[stable(feature = "rust1", since = "1.0.0")] } + +// NOTE: some less important impls are omitted to reduce code bloat +// FIXME(Centril): Reconsider this? +//__impl_slice_eq1! { [const N: usize] Vec, &mut [B; N], } +//__impl_slice_eq1! { [const N: usize] [A; N], Vec, } +//__impl_slice_eq1! { [const N: usize] &[A; N], Vec, } +//__impl_slice_eq1! { [const N: usize] &mut [A; N], Vec, } +//__impl_slice_eq1! { [const N: usize] Cow<'a, [A]>, [B; N], } +//__impl_slice_eq1! { [const N: usize] Cow<'a, [A]>, &[B; N], } +//__impl_slice_eq1! { [const N: usize] Cow<'a, [A]>, &mut [B; N], } diff --git a/library/alloc/src/vec/set_len_on_drop.rs b/library/alloc/src/vec/set_len_on_drop.rs new file mode 100644 index 00000000000..8b66bc81212 --- /dev/null +++ b/library/alloc/src/vec/set_len_on_drop.rs @@ -0,0 +1,28 @@ +// Set the length of the vec when the `SetLenOnDrop` value goes out of scope. +// +// The idea is: The length field in SetLenOnDrop is a local variable +// that the optimizer will see does not alias with any stores through the Vec's data +// pointer. This is a workaround for alias analysis issue #32155 +pub(super) struct SetLenOnDrop<'a> { + len: &'a mut usize, + local_len: usize, +} + +impl<'a> SetLenOnDrop<'a> { + #[inline] + pub(super) fn new(len: &'a mut usize) -> Self { + SetLenOnDrop { local_len: *len, len } + } + + #[inline] + pub(super) fn increment_len(&mut self, increment: usize) { + self.local_len += increment; + } +} + +impl Drop for SetLenOnDrop<'_> { + #[inline] + fn drop(&mut self) { + *self.len = self.local_len; + } +} diff --git a/library/alloc/src/vec/source_iter_marker.rs b/library/alloc/src/vec/source_iter_marker.rs new file mode 100644 index 00000000000..8c0e95559fa --- /dev/null +++ b/library/alloc/src/vec/source_iter_marker.rs @@ -0,0 +1,108 @@ +use core::iter::{InPlaceIterable, SourceIter}; +use core::mem::{self, ManuallyDrop}; +use core::ptr::{self}; + +use super::{AsIntoIter, InPlaceDrop, SpecFromIter, SpecFromIterNested, Vec}; + +/// Specialization marker for collecting an iterator pipeline into a Vec while reusing the +/// source allocation, i.e. executing the pipeline in place. +/// +/// The SourceIter parent trait is necessary for the specializing function to access the allocation +/// which is to be reused. But it is not sufficient for the specialization to be valid. See +/// additional bounds on the impl. +#[rustc_unsafe_specialization_marker] +pub(super) trait SourceIterMarker: SourceIter {} + +// The std-internal SourceIter/InPlaceIterable traits are only implemented by chains of +// Adapter>> (all owned by core/std). Additional bounds +// on the adapter implementations (beyond `impl Trait for Adapter`) only depend on other +// traits already marked as specialization traits (Copy, TrustedRandomAccess, FusedIterator). +// I.e. the marker does not depend on lifetimes of user-supplied types. Modulo the Copy hole, which +// several other specializations already depend on. +impl SourceIterMarker for T where T: SourceIter + InPlaceIterable {} + +impl SpecFromIter for Vec +where + I: Iterator + SourceIterMarker, +{ + default fn from_iter(mut iterator: I) -> Self { + // Additional requirements which cannot expressed via trait bounds. We rely on const eval + // instead: + // a) no ZSTs as there would be no allocation to reuse and pointer arithmetic would panic + // b) size match as required by Alloc contract + // c) alignments match as required by Alloc contract + if mem::size_of::() == 0 + || mem::size_of::() + != mem::size_of::<<::Source as AsIntoIter>::Item>() + || mem::align_of::() + != mem::align_of::<<::Source as AsIntoIter>::Item>() + { + // fallback to more generic implementations + return SpecFromIterNested::from_iter(iterator); + } + + let (src_buf, src_ptr, dst_buf, dst_end, cap) = unsafe { + let inner = iterator.as_inner().as_into_iter(); + ( + inner.buf.as_ptr(), + inner.ptr, + inner.buf.as_ptr() as *mut T, + inner.end as *const T, + inner.cap, + ) + }; + + // use try-fold since + // - it vectorizes better for some iterator adapters + // - unlike most internal iteration methods, it only takes a &mut self + // - it lets us thread the write pointer through its innards and get it back in the end + let sink = InPlaceDrop { inner: dst_buf, dst: dst_buf }; + let sink = iterator + .try_fold::<_, _, Result<_, !>>(sink, write_in_place_with_drop(dst_end)) + .unwrap(); + // iteration succeeded, don't drop head + let dst = ManuallyDrop::new(sink).dst; + + let src = unsafe { iterator.as_inner().as_into_iter() }; + // check if SourceIter contract was upheld + // caveat: if they weren't we may not even make it to this point + debug_assert_eq!(src_buf, src.buf.as_ptr()); + // check InPlaceIterable contract. This is only possible if the iterator advanced the + // source pointer at all. If it uses unchecked access via TrustedRandomAccess + // then the source pointer will stay in its initial position and we can't use it as reference + if src.ptr != src_ptr { + debug_assert!( + dst as *const _ <= src.ptr, + "InPlaceIterable contract violation, write pointer advanced beyond read pointer" + ); + } + + // drop any remaining values at the tail of the source + src.drop_remaining(); + // but prevent drop of the allocation itself once IntoIter goes out of scope + src.forget_allocation(); + + let vec = unsafe { + let len = dst.offset_from(dst_buf) as usize; + Vec::from_raw_parts(dst_buf, len, cap) + }; + + vec + } +} + +fn write_in_place_with_drop( + src_end: *const T, +) -> impl FnMut(InPlaceDrop, T) -> Result, !> { + move |mut sink, item| { + unsafe { + // the InPlaceIterable contract cannot be verified precisely here since + // try_fold has an exclusive reference to the source pointer + // all we can do is check if it's still in range + debug_assert!(sink.dst as *const _ <= src_end, "InPlaceIterable contract violation"); + ptr::write(sink.dst, item); + sink.dst = sink.dst.add(1); + } + Ok(sink) + } +} diff --git a/library/alloc/src/vec/spec_extend.rs b/library/alloc/src/vec/spec_extend.rs new file mode 100644 index 00000000000..b6186a7ebaf --- /dev/null +++ b/library/alloc/src/vec/spec_extend.rs @@ -0,0 +1,82 @@ +use crate::alloc::Allocator; +use core::iter::TrustedLen; +use core::ptr::{self}; +use core::slice::{self}; + +use super::{IntoIter, SetLenOnDrop, Vec}; + +// Specialization trait used for Vec::extend +pub(super) trait SpecExtend { + fn spec_extend(&mut self, iter: I); +} + +impl SpecExtend for Vec +where + I: Iterator, +{ + default fn spec_extend(&mut self, iter: I) { + self.extend_desugared(iter) + } +} + +impl SpecExtend for Vec +where + I: TrustedLen, +{ + default fn spec_extend(&mut self, iterator: I) { + // This is the case for a TrustedLen iterator. + let (low, high) = iterator.size_hint(); + if let Some(high_value) = high { + debug_assert_eq!( + low, + high_value, + "TrustedLen iterator's size hint is not exact: {:?}", + (low, high) + ); + } + if let Some(additional) = high { + self.reserve(additional); + unsafe { + let mut ptr = self.as_mut_ptr().add(self.len()); + let mut local_len = SetLenOnDrop::new(&mut self.len); + iterator.for_each(move |element| { + ptr::write(ptr, element); + ptr = ptr.offset(1); + // NB can't overflow since we would have had to alloc the address space + local_len.increment_len(1); + }); + } + } else { + self.extend_desugared(iterator) + } + } +} + +impl SpecExtend> for Vec { + fn spec_extend(&mut self, mut iterator: IntoIter) { + unsafe { + self.append_elements(iterator.as_slice() as _); + } + iterator.ptr = iterator.end; + } +} + +impl<'a, T: 'a, I, A: Allocator + 'a> SpecExtend<&'a T, I> for Vec +where + I: Iterator, + T: Clone, +{ + default fn spec_extend(&mut self, iterator: I) { + self.spec_extend(iterator.cloned()) + } +} + +impl<'a, T: 'a, A: Allocator + 'a> SpecExtend<&'a T, slice::Iter<'a, T>> for Vec +where + T: Copy, +{ + fn spec_extend(&mut self, iterator: slice::Iter<'a, T>) { + 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 new file mode 100644 index 00000000000..de610174783 --- /dev/null +++ b/library/alloc/src/vec/spec_from_elem.rs @@ -0,0 +1,60 @@ +use crate::alloc::Allocator; +use crate::raw_vec::RawVec; +use core::ptr::{self}; + +use super::{ExtendElement, IsZero, Vec}; + +// Specialization trait used for Vec::from_elem +pub(super) trait SpecFromElem: Sized { + fn from_elem(elem: Self, n: usize, alloc: A) -> Vec; +} + +impl SpecFromElem for T { + default fn from_elem(elem: Self, n: usize, alloc: A) -> Vec { + let mut v = Vec::with_capacity_in(n, alloc); + v.extend_with(n, ExtendElement(elem)); + v + } +} + +impl SpecFromElem for i8 { + #[inline] + 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 }; + } + unsafe { + let mut v = Vec::with_capacity_in(n, alloc); + ptr::write_bytes(v.as_mut_ptr(), elem as u8, n); + v.set_len(n); + v + } + } +} + +impl SpecFromElem for u8 { + #[inline] + 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 }; + } + unsafe { + let mut v = Vec::with_capacity_in(n, alloc); + ptr::write_bytes(v.as_mut_ptr(), elem, n); + v.set_len(n); + v + } + } +} + +impl SpecFromElem for T { + #[inline] + 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 }; + } + let mut v = Vec::with_capacity_in(n, alloc); + v.extend_with(n, ExtendElement(elem)); + v + } +} diff --git a/library/alloc/src/vec/spec_from_iter.rs b/library/alloc/src/vec/spec_from_iter.rs new file mode 100644 index 00000000000..bbfcc68daef --- /dev/null +++ b/library/alloc/src/vec/spec_from_iter.rs @@ -0,0 +1,97 @@ +use core::mem::ManuallyDrop; +use core::ptr::{self}; +use core::slice::{self}; + +use super::{IntoIter, SpecExtend, SpecFromIterNested, Vec}; + +/// Specialization trait used for Vec::from_iter +/// +/// ## The delegation graph: +/// +/// ```text +/// +-------------+ +/// |FromIterator | +/// +-+-----------+ +/// | +/// v +/// +-+-------------------------------+ +---------------------+ +/// |SpecFromIter +---->+SpecFromIterNested | +/// |where I: | | |where I: | +/// | Iterator (default)----------+ | | Iterator (default) | +/// | vec::IntoIter | | | TrustedLen | +/// | SourceIterMarker---fallback-+ | | | +/// | slice::Iter | | | +/// | Iterator | +---------------------+ +/// +---------------------------------+ +/// ``` +pub(super) trait SpecFromIter { + fn from_iter(iter: I) -> Self; +} + +impl SpecFromIter for Vec +where + I: Iterator, +{ + default fn from_iter(iterator: I) -> Self { + SpecFromIterNested::from_iter(iterator) + } +} + +impl SpecFromIter> for Vec { + 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 + // has not been advanced at all. + // When it has been advanced We can also reuse the memory and move the data to the front. + // But we only do so when the resulting Vec wouldn't have more unused capacity + // than creating it through the generic FromIterator implementation would. That limitation + // is not strictly necessary as Vec's allocation behavior is intentionally unspecified. + // But it is a conservative choice. + let has_advanced = iterator.buf.as_ptr() as *const _ != iterator.ptr; + if !has_advanced || iterator.len() >= iterator.cap / 2 { + unsafe { + let it = ManuallyDrop::new(iterator); + if has_advanced { + ptr::copy(it.ptr, it.buf.as_ptr(), it.len()); + } + return Vec::from_raw_parts(it.buf.as_ptr(), it.len(), it.cap); + } + } + + let mut vec = Vec::new(); + // must delegate to spec_extend() since extend() itself delegates + // to spec_from for empty Vecs + vec.spec_extend(iterator); + vec + } +} + +impl<'a, T: 'a, I> SpecFromIter<&'a T, I> for Vec +where + I: Iterator, + T: Clone, +{ + default fn from_iter(iterator: I) -> Self { + SpecFromIter::from_iter(iterator.cloned()) + } +} + +// This utilizes `iterator.as_slice().to_vec()` since spec_extend +// must take more steps to reason about the final capacity + length +// and thus do more work. `to_vec()` directly allocates the correct amount +// and fills it exactly. +impl<'a, T: 'a + Clone> SpecFromIter<&'a T, slice::Iter<'a, T>> for Vec { + #[cfg(not(test))] + fn from_iter(iterator: slice::Iter<'a, T>) -> Self { + iterator.as_slice().to_vec() + } + + // HACK(japaric): with cfg(test) the inherent `[T]::to_vec` method, which is + // required for this method definition, is not available. Instead use the + // `slice::to_vec` function which is only available with cfg(test) + // NB see the slice::hack module in slice.rs for more information + #[cfg(test)] + fn from_iter(iterator: slice::Iter<'a, T>) -> Self { + crate::slice::to_vec(iterator.as_slice(), crate::alloc::Global) + } +} diff --git a/library/alloc/src/vec/spec_from_iter_nested.rs b/library/alloc/src/vec/spec_from_iter_nested.rs new file mode 100644 index 00000000000..6abd4ff2a3f --- /dev/null +++ b/library/alloc/src/vec/spec_from_iter_nested.rs @@ -0,0 +1,56 @@ +use core::iter::TrustedLen; +use core::ptr::{self}; + +use super::{SpecExtend, Vec}; + +/// Another specialization trait for Vec::from_iter +/// necessary to manually prioritize overlapping specializations +/// see [`SpecFromIter`] for details. +pub(super) trait SpecFromIterNested { + fn from_iter(iter: I) -> Self; +} + +impl SpecFromIterNested for Vec +where + I: Iterator, +{ + 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 + // empty, but the loop in extend_desugared() is not going to see the + // vector being full in the few subsequent loop iterations. + // So we get better branch prediction. + let mut vector = match iterator.next() { + None => return Vec::new(), + Some(element) => { + let (lower, _) = iterator.size_hint(); + let mut vector = Vec::with_capacity(lower.saturating_add(1)); + unsafe { + ptr::write(vector.as_mut_ptr(), element); + vector.set_len(1); + } + vector + } + }; + // must delegate to spec_extend() since extend() itself delegates + // to spec_from for empty Vecs + as SpecExtend>::spec_extend(&mut vector, iterator); + vector + } +} + +impl SpecFromIterNested for Vec +where + I: TrustedLen, +{ + fn from_iter(iterator: I) -> Self { + let mut vector = match iterator.size_hint() { + (_, Some(upper)) => Vec::with_capacity(upper), + _ => Vec::new(), + }; + // must delegate to spec_extend() since extend() itself delegates + // to spec_from for empty Vecs + vector.spec_extend(iterator); + vector + } +} diff --git a/library/alloc/src/vec/splice.rs b/library/alloc/src/vec/splice.rs new file mode 100644 index 00000000000..0a27b5b62ec --- /dev/null +++ b/library/alloc/src/vec/splice.rs @@ -0,0 +1,133 @@ +use crate::alloc::{Allocator, Global}; +use core::ptr::{self}; +use core::slice::{self}; + +use super::{Drain, Vec}; + +/// A splicing iterator for `Vec`. +/// +/// This struct is created by [`Vec::splice()`]. +/// See its documentation for more. +/// +/// # Example +/// +/// ``` +/// let mut v = vec![0, 1, 2]; +/// let new = [7, 8]; +/// let iter: std::vec::Splice<_> = v.splice(1.., new.iter().cloned()); +/// ``` +#[derive(Debug)] +#[stable(feature = "vec_splice", since = "1.21.0")] +pub struct Splice< + 'a, + I: Iterator + 'a, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + 'a = Global, +> { + pub(super) drain: Drain<'a, I::Item, A>, + pub(super) replace_with: I, +} + +#[stable(feature = "vec_splice", since = "1.21.0")] +impl Iterator for Splice<'_, I, A> { + type Item = I::Item; + + fn next(&mut self) -> Option { + self.drain.next() + } + + fn size_hint(&self) -> (usize, Option) { + self.drain.size_hint() + } +} + +#[stable(feature = "vec_splice", since = "1.21.0")] +impl DoubleEndedIterator for Splice<'_, I, A> { + fn next_back(&mut self) -> Option { + self.drain.next_back() + } +} + +#[stable(feature = "vec_splice", since = "1.21.0")] +impl ExactSizeIterator for Splice<'_, I, A> {} + +#[stable(feature = "vec_splice", since = "1.21.0")] +impl Drop for Splice<'_, I, A> { + fn drop(&mut self) { + self.drain.by_ref().for_each(drop); + + unsafe { + if self.drain.tail_len == 0 { + self.drain.vec.as_mut().extend(self.replace_with.by_ref()); + return; + } + + // First fill the range left by drain(). + if !self.drain.fill(&mut self.replace_with) { + return; + } + + // There may be more elements. Use the lower bound as an estimate. + // FIXME: Is the upper bound a better guess? Or something else? + let (lower_bound, _upper_bound) = self.replace_with.size_hint(); + if lower_bound > 0 { + self.drain.move_tail(lower_bound); + if !self.drain.fill(&mut self.replace_with) { + return; + } + } + + // Collect any remaining elements. + // This is a zero-length vector which does not allocate if `lower_bound` was exact. + let mut collected = self.replace_with.by_ref().collect::>().into_iter(); + // Now we have an exact count. + if collected.len() > 0 { + self.drain.move_tail(collected.len()); + let filled = self.drain.fill(&mut collected); + debug_assert!(filled); + debug_assert_eq!(collected.len(), 0); + } + } + // Let `Drain::drop` move the tail back if necessary and restore `vec.len`. + } +} + +/// Private helper methods for `Splice::drop` +impl Drain<'_, T, A> { + /// The range from `self.vec.len` to `self.tail_start` contains elements + /// that have been moved out. + /// Fill that range as much as possible with new elements from the `replace_with` iterator. + /// Returns `true` if we filled the entire range. (`replace_with.next()` didn’t return `None`.) + unsafe fn fill>(&mut self, replace_with: &mut I) -> bool { + let vec = unsafe { self.vec.as_mut() }; + let range_start = vec.len; + let range_end = self.tail_start; + let range_slice = unsafe { + slice::from_raw_parts_mut(vec.as_mut_ptr().add(range_start), range_end - range_start) + }; + + for place in range_slice { + if let Some(new_item) = replace_with.next() { + unsafe { ptr::write(place, new_item) }; + vec.len += 1; + } else { + return false; + } + } + true + } + + /// Makes room for inserting more elements before the tail. + unsafe fn move_tail(&mut self, additional: usize) { + let vec = unsafe { self.vec.as_mut() }; + let len = self.tail_start + self.tail_len; + vec.buf.reserve(len, additional); + + let new_tail_start = self.tail_start + additional; + unsafe { + let src = vec.as_ptr().add(self.tail_start); + let dst = vec.as_mut_ptr().add(new_tail_start); + ptr::copy(src, dst, self.tail_len); + } + self.tail_start = new_tail_start; + } +} diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs index b7cc03f8eb9..b56437bd188 100644 --- a/library/alloc/tests/lib.rs +++ b/library/alloc/tests/lib.rs @@ -16,7 +16,6 @@ #![feature(slice_ptr_get)] #![feature(split_inclusive)] #![feature(binary_heap_retain)] -#![feature(deque_range)] #![feature(inplace_iteration)] #![feature(iter_map_while)] #![feature(int_bits_const)] diff --git a/library/core/src/alloc/global.rs b/library/core/src/alloc/global.rs index c198797e650..6ec0f0b5ffc 100644 --- a/library/core/src/alloc/global.rs +++ b/library/core/src/alloc/global.rs @@ -53,6 +53,27 @@ /// * `Layout` queries and calculations in general must be correct. Callers of /// this trait are allowed to rely on the contracts defined on each method, /// and implementors must ensure such contracts remain true. +/// +/// * You may not rely on allocations actually happening, even if there are explicit +/// heap allocations in the source. The optimizer may detect unused allocations that it can either +/// eliminate entirely or move to the stack and thus never invoke the allocator. The +/// optimizer may further assume that allocation is infallible, so code that used to fail due +/// to allocator failures may now suddenly work because the optimizer worked around the +/// need for an allocation. More concretely, the following code example is unsound, irrespective +/// of whether your custom allocator allows counting how many allocations have happened. +/// +/// ```rust,ignore (unsound and has placeholders) +/// drop(Box::new(42)); +/// let number_of_heap_allocs = /* call private allocator API */; +/// unsafe { std::intrinsics::assume(number_of_heap_allocs > 0); } +/// ``` +/// +/// Note that the optimizations mentioned above are not the only +/// optimization that can be applied. You may generally not rely on heap allocations +/// happening if they can be removed without changing program behavior. +/// Whether allocations happen or not is not part of the program behavior, even if it +/// could be detected via an allocator that tracks allocations by printing or otherwise +/// having side effects. #[stable(feature = "global_alloc", since = "1.28.0")] pub unsafe trait GlobalAlloc { /// Allocate memory as described by the given `layout`. diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index a7cb1023229..71548bec7aa 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -463,6 +463,37 @@ fn drop(&mut self) { unsafe { crate::mem::transmute_copy::<_, [U; N]>(&dst) } } + /// 'Zips up' two arrays into a single array of pairs. + /// + /// `zip()` returns a new array where every element is a tuple where the + /// first element comes from the first array, and the second element comes + /// from the second array. In other words, it zips two arrays together, + /// into a single one. + /// + /// # Examples + /// + /// ``` + /// #![feature(array_zip)] + /// let x = [1, 2, 3]; + /// let y = [4, 5, 6]; + /// let z = x.zip(y); + /// assert_eq!(z, [(1, 4), (2, 5), (3, 6)]); + /// ``` + #[unstable(feature = "array_zip", issue = "80094")] + pub fn zip(self, rhs: [U; N]) -> [(T, U); N] { + use crate::mem::MaybeUninit; + + let mut dst = MaybeUninit::uninit_array::(); + for (i, (lhs, rhs)) in IntoIter::new(self).zip(IntoIter::new(rhs)).enumerate() { + dst[i].write((lhs, rhs)); + } + // FIXME: Convert to crate::mem::transmute once it works with generics. + // unsafe { crate::mem::transmute::<[MaybeUninit; N], [U; N]>(dst) } + // SAFETY: At this point we've properly initialized the whole array + // and we just need to cast it to the correct type. + unsafe { crate::mem::transmute_copy::<_, [(T, U); N]>(&dst) } + } + /// Returns a slice containing the entire array. Equivalent to `&s[..]`. #[unstable(feature = "array_methods", issue = "76118")] pub fn as_slice(&self) -> &[T] { diff --git a/library/core/src/char/convert.rs b/library/core/src/char/convert.rs index 394db5b5917..de05a8c82e8 100644 --- a/library/core/src/char/convert.rs +++ b/library/core/src/char/convert.rs @@ -47,6 +47,7 @@ /// /// assert_eq!(None, c); /// ``` +#[doc(alias = "chr")] #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn from_u32(i: u32) -> Option { diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 52921822693..938dc214486 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -1736,7 +1736,6 @@ /// Allocate at compile time. Should not be called at runtime. #[rustc_const_unstable(feature = "const_heap", issue = "79597")] - #[cfg(not(bootstrap))] pub fn const_allocate(size: usize, align: usize) -> *mut u8; } @@ -1846,20 +1845,22 @@ pub(crate) fn is_nonoverlapping(src: *const T, dst: *const T, count: usize) - /// [`Vec::append`]: ../../std/vec/struct.Vec.html#method.append #[doc(alias = "memcpy")] #[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "none")] #[inline] -pub unsafe fn copy_nonoverlapping(src: *const T, dst: *mut T, count: usize) { +pub const unsafe fn copy_nonoverlapping(src: *const T, dst: *mut T, count: usize) { extern "rust-intrinsic" { fn copy_nonoverlapping(src: *const T, dst: *mut T, count: usize); } - if cfg!(debug_assertions) + // FIXME: Perform these checks only at run time + /*if cfg!(debug_assertions) && !(is_aligned_and_not_null(src) && is_aligned_and_not_null(dst) && is_nonoverlapping(src, dst, count)) { // Not panicking to keep codegen impact smaller. abort(); - } + }*/ // SAFETY: the safety contract for `copy_nonoverlapping` must be // upheld by the caller. @@ -1928,16 +1929,19 @@ pub unsafe fn copy_nonoverlapping(src: *const T, dst: *mut T, count: usize) { /// ``` #[doc(alias = "memmove")] #[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "none")] #[inline] -pub unsafe fn copy(src: *const T, dst: *mut T, count: usize) { +pub const unsafe fn copy(src: *const T, dst: *mut T, count: usize) { extern "rust-intrinsic" { + #[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "none")] fn copy(src: *const T, dst: *mut T, count: usize); } - if cfg!(debug_assertions) && !(is_aligned_and_not_null(src) && is_aligned_and_not_null(dst)) { + // FIXME: Perform these checks only at run time + /*if cfg!(debug_assertions) && !(is_aligned_and_not_null(src) && is_aligned_and_not_null(dst)) { // Not panicking to keep codegen impact smaller. abort(); - } + }*/ // SAFETY: the safety contract for `copy` must be upheld by the caller. unsafe { copy(src, dst, count) } diff --git a/library/core/src/iter/adapters/intersperse.rs b/library/core/src/iter/adapters/intersperse.rs new file mode 100644 index 00000000000..36232672549 --- /dev/null +++ b/library/core/src/iter/adapters/intersperse.rs @@ -0,0 +1,76 @@ +use super::Peekable; + +/// An iterator adapter that places a separator between all elements. +#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] +#[derive(Debug, Clone)] +pub struct Intersperse +where + I::Item: Clone, +{ + separator: I::Item, + iter: Peekable, + needs_sep: bool, +} + +impl Intersperse +where + I::Item: Clone, +{ + pub(in crate::iter) fn new(iter: I, separator: I::Item) -> Self { + Self { iter: iter.peekable(), separator, needs_sep: false } + } +} + +#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] +impl Iterator for Intersperse +where + I: Iterator, + I::Item: Clone, +{ + type Item = I::Item; + + #[inline] + fn next(&mut self) -> Option { + if self.needs_sep && self.iter.peek().is_some() { + self.needs_sep = false; + Some(self.separator.clone()) + } else { + self.needs_sep = true; + self.iter.next() + } + } + + fn fold(mut self, init: B, mut f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + let mut accum = init; + + // Use `peek()` first to avoid calling `next()` on an empty iterator. + if !self.needs_sep || self.iter.peek().is_some() { + if let Some(x) = self.iter.next() { + accum = f(accum, x); + } + } + + let element = &self.separator; + + self.iter.fold(accum, |mut accum, x| { + accum = f(accum, element.clone()); + accum = f(accum, x); + accum + }) + } + + fn size_hint(&self) -> (usize, Option) { + let (lo, hi) = self.iter.size_hint(); + let next_is_elem = !self.needs_sep; + let lo = lo.saturating_sub(next_is_elem as usize).saturating_add(lo); + let hi = match hi { + Some(hi) => hi.saturating_sub(next_is_elem as usize).checked_add(hi), + None => None, + }; + (lo, hi) + } +} diff --git a/library/core/src/iter/adapters/mod.rs b/library/core/src/iter/adapters/mod.rs index b8d3430f910..7dfbf32cea7 100644 --- a/library/core/src/iter/adapters/mod.rs +++ b/library/core/src/iter/adapters/mod.rs @@ -11,6 +11,7 @@ mod flatten; mod fuse; mod inspect; +mod intersperse; mod map; mod map_while; mod peekable; @@ -41,6 +42,9 @@ #[stable(feature = "iter_copied", since = "1.36.0")] pub use self::copied::Copied; +#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] +pub use self::intersperse::Intersperse; + #[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")] pub use self::map_while::MapWhile; diff --git a/library/core/src/iter/mod.rs b/library/core/src/iter/mod.rs index 3e74637b49f..569de719d03 100644 --- a/library/core/src/iter/mod.rs +++ b/library/core/src/iter/mod.rs @@ -395,6 +395,8 @@ pub use self::adapters::Copied; #[stable(feature = "iterator_flatten", since = "1.29.0")] pub use self::adapters::Flatten; +#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] +pub use self::adapters::Intersperse; #[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")] pub use self::adapters::MapWhile; #[unstable(feature = "inplace_iteration", issue = "none")] diff --git a/library/core/src/iter/traits/exact_size.rs b/library/core/src/iter/traits/exact_size.rs index eadbdf45c7c..996d62e2b4a 100644 --- a/library/core/src/iter/traits/exact_size.rs +++ b/library/core/src/iter/traits/exact_size.rs @@ -91,6 +91,7 @@ pub trait ExactSizeIterator: Iterator { /// /// assert_eq!(5, five.len()); /// ``` + #[doc(alias = "length")] #[inline] #[stable(feature = "rust1", since = "1.0.0")] fn len(&self) -> usize { diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 7ba16f89284..633175702d8 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -8,7 +8,7 @@ use super::super::TrustedRandomAccess; use super::super::{Chain, Cloned, Copied, Cycle, Enumerate, Filter, FilterMap, Fuse}; use super::super::{FlatMap, Flatten}; -use super::super::{FromIterator, Product, Sum, Zip}; +use super::super::{FromIterator, Intersperse, Product, Sum, Zip}; use super::super::{ Inspect, Map, MapWhile, Peekable, Rev, Scan, Skip, SkipWhile, StepBy, Take, TakeWhile, }; @@ -569,6 +569,28 @@ fn zip(self, other: U) -> Zip Zip::new(self, other.into_iter()) } + /// Places a copy of `separator` between all elements. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(iter_intersperse)] + /// + /// let hello = ["Hello", "World"].iter().copied().intersperse(" ").collect::(); + /// assert_eq!(hello, "Hello World"); + /// ``` + #[inline] + #[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] + fn intersperse(self, separator: Self::Item) -> Intersperse + where + Self: Sized, + Self::Item: Clone, + { + Intersperse::new(self, separator) + } + /// Takes a closure and creates an iterator which calls that closure on each /// element. /// diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 5b19bf6b80f..099b98b824d 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -68,11 +68,12 @@ #![feature(arbitrary_self_types)] #![feature(asm)] #![feature(cfg_target_has_atomic)] -#![cfg_attr(not(bootstrap), feature(const_heap))] +#![feature(const_heap)] #![feature(const_alloc_layout)] #![feature(const_assert_type)] #![feature(const_discriminant)] #![feature(const_cell_into_inner)] +#![feature(const_intrinsic_copy)] #![feature(const_checked_int_methods)] #![feature(const_euclidean_int_methods)] #![feature(const_float_classify)] @@ -93,6 +94,7 @@ #![feature(const_precise_live_drops)] #![feature(const_ptr_offset)] #![feature(const_ptr_offset_from)] +#![feature(const_ptr_read)] #![feature(const_raw_ptr_comparison)] #![feature(const_raw_ptr_deref)] #![feature(const_slice_from_raw_parts)] @@ -111,6 +113,7 @@ #![feature(doc_spotlight)] #![feature(duration_consts_2)] #![feature(duration_saturating_ops)] +#![feature(extended_key_value_attributes)] #![feature(extern_types)] #![feature(fundamental)] #![feature(intrinsics)] @@ -122,8 +125,7 @@ #![feature(nll)] #![feature(exhaustive_patterns)] #![feature(no_core)] -#![cfg_attr(bootstrap, feature(optin_builtin_traits))] -#![cfg_attr(not(bootstrap), feature(auto_traits))] +#![feature(auto_traits)] #![feature(or_patterns)] #![feature(prelude_import)] #![feature(repr_simd, platform_intrinsics)] diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index 0699c9eab18..1634aff7b4d 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -2,7 +2,7 @@ #[macro_export] #[allow_internal_unstable(core_panic, const_caller_location)] #[stable(feature = "core", since = "1.6.0")] -#[cfg_attr(not(bootstrap), rustc_diagnostic_item = "core_panic_macro")] +#[rustc_diagnostic_item = "core_panic_macro"] macro_rules! panic { () => ( $crate::panic!("explicit panic") @@ -163,7 +163,7 @@ macro_rules! assert_ne { /// ``` #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(not(bootstrap), rustc_diagnostic_item = "debug_assert_macro")] +#[rustc_diagnostic_item = "debug_assert_macro"] macro_rules! debug_assert { ($($arg:tt)*) => (if $crate::cfg!(debug_assertions) { $crate::assert!($($arg)*); }) } @@ -1217,7 +1217,7 @@ macro_rules! include { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_builtin_macro] #[macro_export] - #[cfg_attr(not(bootstrap), rustc_diagnostic_item = "assert_macro")] + #[rustc_diagnostic_item = "assert_macro"] #[allow_internal_unstable(core_panic)] macro_rules! assert { ($cond:expr $(,)?) => {{ /* compiler built-in */ }}; diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index 57e0bb1499b..b2a4d897eed 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -575,8 +575,9 @@ pub const fn as_mut_ptr(&mut self) -> *mut T { /// // they both get dropped! /// ``` #[unstable(feature = "maybe_uninit_extra", issue = "63567")] + #[rustc_const_unstable(feature = "maybe_uninit_extra", issue = "63567")] #[inline(always)] - pub unsafe fn assume_init_read(&self) -> T { + pub const unsafe fn assume_init_read(&self) -> T { // SAFETY: the caller must guarantee that `self` is initialized. // Reading from `self.as_ptr()` is safe since `self` should be initialized. unsafe { diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index e84014c68a6..22e44a3c409 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -151,9 +151,14 @@ pub const fn forget(t: T) { #[inline] #[unstable(feature = "forget_unsized", issue = "none")] pub fn forget_unsized(t: T) { + #[cfg(bootstrap)] // SAFETY: the forget intrinsic could be safe, but there's no point in making it safe since // we'll be implementing this function soon via `ManuallyDrop` - unsafe { intrinsics::forget(t) } + unsafe { + intrinsics::forget(t) + } + #[cfg(not(bootstrap))] + intrinsics::forget(t) } /// Returns the size of a type in bytes. @@ -374,7 +379,8 @@ pub const fn size_of_val(val: &T) -> usize { /// ``` #[inline] #[unstable(feature = "layout_for_ptr", issue = "69835")] -pub unsafe fn size_of_val_raw(val: *const T) -> usize { +#[rustc_const_unstable(feature = "const_size_of_val_raw", issue = "46571")] +pub const unsafe fn size_of_val_raw(val: *const T) -> usize { intrinsics::size_of_val(val) } @@ -505,7 +511,8 @@ pub const fn align_of_val(val: &T) -> usize { /// ``` #[inline] #[unstable(feature = "layout_for_ptr", issue = "69835")] -pub unsafe fn align_of_val_raw(val: *const T) -> usize { +#[rustc_const_unstable(feature = "const_align_of_val_raw", issue = "46571")] +pub const unsafe fn align_of_val_raw(val: *const T) -> usize { intrinsics::min_align_of_val(val) } diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index 2cde5d9995b..162ed7d1b8d 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -1,2240 +1,2008 @@ macro_rules! int_impl { - ($SelfT:ty, $ActualT:ident, $UnsignedT:ty, $BITS:expr, $Min:expr, $Max:expr, $Feature:expr, - $EndFeature:expr, $rot:expr, $rot_op:expr, $rot_result:expr, $swap_op:expr, $swapped:expr, + ($SelfT:ty, $ActualT:ident, $UnsignedT:ty, $BITS:expr, $Min:expr, $Max:expr, + $rot:expr, $rot_op:expr, $rot_result:expr, $swap_op:expr, $swapped:expr, $reversed:expr, $le_bytes:expr, $be_bytes:expr, $to_xe_bytes_doc:expr, $from_xe_bytes_doc:expr) => { - doc_comment! { - concat!("The smallest value that can be represented by this integer type. - -# Examples - -Basic usage: - -``` -", $Feature, "assert_eq!(", stringify!($SelfT), "::MIN, ", stringify!($Min), ");", -$EndFeature, " -```"), - #[stable(feature = "assoc_int_consts", since = "1.43.0")] - pub const MIN: Self = !0 ^ ((!0 as $UnsignedT) >> 1) as Self; - } - - doc_comment! { - concat!("The largest value that can be represented by this integer type. - -# Examples - -Basic usage: - -``` -", $Feature, "assert_eq!(", stringify!($SelfT), "::MAX, ", stringify!($Max), ");", -$EndFeature, " -```"), - #[stable(feature = "assoc_int_consts", since = "1.43.0")] - pub const MAX: Self = !Self::MIN; - } - - doc_comment! { - concat!("The size of this integer type in bits. - -# Examples - -``` -", $Feature, "#![feature(int_bits_const)] -assert_eq!(", stringify!($SelfT), "::BITS, ", stringify!($BITS), ");", -$EndFeature, " -```"), - #[unstable(feature = "int_bits_const", issue = "76904")] - pub const BITS: u32 = $BITS; - } - - doc_comment! { - concat!("Converts a string slice in a given base to an integer. - -The string is expected to be an optional `+` or `-` sign followed by digits. -Leading and trailing whitespace represent an error. Digits are a subset of these characters, -depending on `radix`: - - * `0-9` - * `a-z` - * `A-Z` - -# Panics - -This function panics if `radix` is not in the range from 2 to 36. - -# Examples - -Basic usage: - -``` -", $Feature, "assert_eq!(", stringify!($SelfT), "::from_str_radix(\"A\", 16), Ok(10));", -$EndFeature, " -```"), - #[stable(feature = "rust1", since = "1.0.0")] - pub fn from_str_radix(src: &str, radix: u32) -> Result { - from_str_radix(src, radix) - } - } - - doc_comment! { - concat!("Returns the number of ones in the binary representation of `self`. - -# Examples - -Basic usage: - -``` -", $Feature, "let n = 0b100_0000", stringify!($SelfT), "; - -assert_eq!(n.count_ones(), 1);", -$EndFeature, " -``` -"), - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] - #[doc(alias = "popcount")] - #[doc(alias = "popcnt")] - #[inline] - pub const fn count_ones(self) -> u32 { (self as $UnsignedT).count_ones() } - } - - doc_comment! { - concat!("Returns the number of zeros in the binary representation of `self`. - -# Examples - -Basic usage: - -``` -", $Feature, "assert_eq!(", stringify!($SelfT), "::MAX.count_zeros(), 1);", $EndFeature, " -```"), - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] - #[inline] - pub const fn count_zeros(self) -> u32 { - (!self).count_ones() - } - } - - doc_comment! { - concat!("Returns the number of leading zeros in the binary representation of `self`. - -# Examples - -Basic usage: - -``` -", $Feature, "let n = -1", stringify!($SelfT), "; - -assert_eq!(n.leading_zeros(), 0);", -$EndFeature, " -```"), - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] - #[inline] - pub const fn leading_zeros(self) -> u32 { - (self as $UnsignedT).leading_zeros() - } - } - - doc_comment! { - concat!("Returns the number of trailing zeros in the binary representation of `self`. - -# Examples - -Basic usage: - -``` -", $Feature, "let n = -4", stringify!($SelfT), "; - -assert_eq!(n.trailing_zeros(), 2);", -$EndFeature, " -```"), - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] - #[inline] - pub const fn trailing_zeros(self) -> u32 { - (self as $UnsignedT).trailing_zeros() - } - } - - doc_comment! { - concat!("Returns the number of leading ones in the binary representation of `self`. - -# Examples - -Basic usage: - -``` -", $Feature, "let n = -1", stringify!($SelfT), "; - -assert_eq!(n.leading_ones(), ", stringify!($BITS), ");", -$EndFeature, " -```"), - #[stable(feature = "leading_trailing_ones", since = "1.46.0")] - #[rustc_const_stable(feature = "leading_trailing_ones", since = "1.46.0")] - #[inline] - pub const fn leading_ones(self) -> u32 { - (self as $UnsignedT).leading_ones() - } - } - - doc_comment! { - concat!("Returns the number of trailing ones in the binary representation of `self`. - -# Examples - -Basic usage: - -``` -", $Feature, "let n = 3", stringify!($SelfT), "; - -assert_eq!(n.trailing_ones(), 2);", -$EndFeature, " -```"), - #[stable(feature = "leading_trailing_ones", since = "1.46.0")] - #[rustc_const_stable(feature = "leading_trailing_ones", since = "1.46.0")] - #[inline] - pub const fn trailing_ones(self) -> u32 { - (self as $UnsignedT).trailing_ones() - } - } - - doc_comment! { - concat!("Shifts the bits to the left by a specified amount, `n`, -wrapping the truncated bits to the end of the resulting integer. - -Please note this isn't the same operation as the `<<` shifting operator! - -# Examples - -Basic usage: - -``` -let n = ", $rot_op, stringify!($SelfT), "; -let m = ", $rot_result, "; - -assert_eq!(n.rotate_left(", $rot, "), m); -```"), - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn rotate_left(self, n: u32) -> Self { - (self as $UnsignedT).rotate_left(n) as Self - } - } - - doc_comment! { - concat!("Shifts the bits to the right by a specified amount, `n`, -wrapping the truncated bits to the beginning of the resulting -integer. - -Please note this isn't the same operation as the `>>` shifting operator! - -# Examples - -Basic usage: - -``` -let n = ", $rot_result, stringify!($SelfT), "; -let m = ", $rot_op, "; - -assert_eq!(n.rotate_right(", $rot, "), m); -```"), - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn rotate_right(self, n: u32) -> Self { - (self as $UnsignedT).rotate_right(n) as Self - } - } - - doc_comment! { - concat!("Reverses the byte order of the integer. - -# Examples - -Basic usage: - -``` -let n = ", $swap_op, stringify!($SelfT), "; - -let m = n.swap_bytes(); - -assert_eq!(m, ", $swapped, "); -```"), - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] - #[inline] - pub const fn swap_bytes(self) -> Self { - (self as $UnsignedT).swap_bytes() as Self - } - } - - doc_comment! { - concat!("Reverses the order of bits in the integer. The least significant bit becomes the most significant bit, - second least-significant bit becomes second most-significant bit, etc. - -# Examples - -Basic usage: - -``` -let n = ", $swap_op, stringify!($SelfT), "; -let m = n.reverse_bits(); - -assert_eq!(m, ", $reversed, "); -assert_eq!(0, 0", stringify!($SelfT), ".reverse_bits()); -```"), - #[stable(feature = "reverse_bits", since = "1.37.0")] - #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] - #[inline] - #[must_use] - pub const fn reverse_bits(self) -> Self { - (self as $UnsignedT).reverse_bits() as Self - } - } - - doc_comment! { - concat!("Converts an integer from big endian to the target's endianness. - -On big endian this is a no-op. On little endian the bytes are swapped. - -# Examples - -Basic usage: - -``` -", $Feature, "let n = 0x1A", stringify!($SelfT), "; - -if cfg!(target_endian = \"big\") { - assert_eq!(", stringify!($SelfT), "::from_be(n), n) -} else { - assert_eq!(", stringify!($SelfT), "::from_be(n), n.swap_bytes()) -}", -$EndFeature, " -```"), - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_int_conversions", since = "1.32.0")] - #[inline] - pub const fn from_be(x: Self) -> Self { - #[cfg(target_endian = "big")] - { - x - } - #[cfg(not(target_endian = "big"))] - { - x.swap_bytes() - } - } - } - - doc_comment! { - concat!("Converts an integer from little endian to the target's endianness. - -On little endian this is a no-op. On big endian the bytes are swapped. - -# Examples - -Basic usage: - -``` -", $Feature, "let n = 0x1A", stringify!($SelfT), "; - -if cfg!(target_endian = \"little\") { - assert_eq!(", stringify!($SelfT), "::from_le(n), n) -} else { - assert_eq!(", stringify!($SelfT), "::from_le(n), n.swap_bytes()) -}", -$EndFeature, " -```"), - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_int_conversions", since = "1.32.0")] - #[inline] - pub const fn from_le(x: Self) -> Self { - #[cfg(target_endian = "little")] - { - x - } - #[cfg(not(target_endian = "little"))] - { - x.swap_bytes() - } - } - } - - doc_comment! { - concat!("Converts `self` to big endian from the target's endianness. - -On big endian this is a no-op. On little endian the bytes are swapped. - -# Examples - -Basic usage: - -``` -", $Feature, "let n = 0x1A", stringify!($SelfT), "; - -if cfg!(target_endian = \"big\") { - assert_eq!(n.to_be(), n) -} else { - assert_eq!(n.to_be(), n.swap_bytes()) -}", -$EndFeature, " -```"), - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_int_conversions", since = "1.32.0")] - #[inline] - pub const fn to_be(self) -> Self { // or not to be? - #[cfg(target_endian = "big")] - { - self - } - #[cfg(not(target_endian = "big"))] - { - self.swap_bytes() - } - } - } - - doc_comment! { - concat!("Converts `self` to little endian from the target's endianness. - -On little endian this is a no-op. On big endian the bytes are swapped. - -# Examples - -Basic usage: - -``` -", $Feature, "let n = 0x1A", stringify!($SelfT), "; - -if cfg!(target_endian = \"little\") { - assert_eq!(n.to_le(), n) -} else { - assert_eq!(n.to_le(), n.swap_bytes()) -}", -$EndFeature, " -```"), - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_int_conversions", since = "1.32.0")] - #[inline] - pub const fn to_le(self) -> Self { - #[cfg(target_endian = "little")] - { - self - } - #[cfg(not(target_endian = "little"))] - { - self.swap_bytes() - } - } - } - - doc_comment! { - concat!("Checked integer addition. Computes `self + rhs`, returning `None` -if overflow occurred. - -# Examples - -Basic usage: - -``` -", $Feature, "assert_eq!((", stringify!($SelfT), -"::MAX - 2).checked_add(1), Some(", stringify!($SelfT), "::MAX - 1)); -assert_eq!((", stringify!($SelfT), "::MAX - 2).checked_add(3), None);", -$EndFeature, " -```"), - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn checked_add(self, rhs: Self) -> Option { - let (a, b) = self.overflowing_add(rhs); - if unlikely!(b) {None} else {Some(a)} - } - } - - doc_comment! { - concat!("Unchecked integer addition. Computes `self + rhs`, assuming overflow -cannot occur. This results in undefined behavior when `self + rhs > ", stringify!($SelfT), -"::MAX` or `self + rhs < ", stringify!($SelfT), "::MIN`."), - #[unstable( - feature = "unchecked_math", - reason = "niche optimization path", - issue = "none", - )] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub unsafe fn unchecked_add(self, rhs: Self) -> Self { - // SAFETY: the caller must uphold the safety contract for - // `unchecked_add`. - unsafe { intrinsics::unchecked_add(self, rhs) } - } - } - - doc_comment! { - concat!("Checked integer subtraction. Computes `self - rhs`, returning `None` if -overflow occurred. - -# Examples - -Basic usage: - -``` -", $Feature, "assert_eq!((", stringify!($SelfT), -"::MIN + 2).checked_sub(1), Some(", stringify!($SelfT), "::MIN + 1)); -assert_eq!((", stringify!($SelfT), "::MIN + 2).checked_sub(3), None);", -$EndFeature, " -```"), - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn checked_sub(self, rhs: Self) -> Option { - let (a, b) = self.overflowing_sub(rhs); - if unlikely!(b) {None} else {Some(a)} - } - } - - doc_comment! { - concat!("Unchecked integer subtraction. Computes `self - rhs`, assuming overflow -cannot occur. This results in undefined behavior when `self - rhs > ", stringify!($SelfT), -"::MAX` or `self - rhs < ", stringify!($SelfT), "::MIN`."), - #[unstable( - feature = "unchecked_math", - reason = "niche optimization path", - issue = "none", - )] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub unsafe fn unchecked_sub(self, rhs: Self) -> Self { - // SAFETY: the caller must uphold the safety contract for - // `unchecked_sub`. - unsafe { intrinsics::unchecked_sub(self, rhs) } - } - } - - doc_comment! { - concat!("Checked integer multiplication. Computes `self * rhs`, returning `None` if -overflow occurred. - -# Examples - -Basic usage: - -``` -", $Feature, "assert_eq!(", stringify!($SelfT), -"::MAX.checked_mul(1), Some(", stringify!($SelfT), "::MAX)); -assert_eq!(", stringify!($SelfT), "::MAX.checked_mul(2), None);", -$EndFeature, " -```"), - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn checked_mul(self, rhs: Self) -> Option { - let (a, b) = self.overflowing_mul(rhs); - if unlikely!(b) {None} else {Some(a)} - } - } - - doc_comment! { - concat!("Unchecked integer multiplication. Computes `self * rhs`, assuming overflow -cannot occur. This results in undefined behavior when `self * rhs > ", stringify!($SelfT), -"::MAX` or `self * rhs < ", stringify!($SelfT), "::MIN`."), - #[unstable( - feature = "unchecked_math", - reason = "niche optimization path", - issue = "none", - )] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub unsafe fn unchecked_mul(self, rhs: Self) -> Self { - // SAFETY: the caller must uphold the safety contract for - // `unchecked_mul`. - unsafe { intrinsics::unchecked_mul(self, rhs) } - } - } - - doc_comment! { - concat!("Checked integer division. Computes `self / rhs`, returning `None` if `rhs == 0` -or the division results in overflow. - -# Examples - -Basic usage: - -``` -", $Feature, "assert_eq!((", stringify!($SelfT), -"::MIN + 1).checked_div(-1), Some(", stringify!($Max), ")); -assert_eq!(", stringify!($SelfT), "::MIN.checked_div(-1), None); -assert_eq!((1", stringify!($SelfT), ").checked_div(0), None);", -$EndFeature, " -```"), - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_checked_int_methods", issue = "53718")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn checked_div(self, rhs: Self) -> Option { - if unlikely!(rhs == 0 || (self == Self::MIN && rhs == -1)) { - None - } else { - // SAFETY: div by zero and by INT_MIN have been checked above - Some(unsafe { intrinsics::unchecked_div(self, rhs) }) - } - } - } - - doc_comment! { - concat!("Checked Euclidean division. Computes `self.div_euclid(rhs)`, -returning `None` if `rhs == 0` or the division results in overflow. - -# Examples - -Basic usage: - -``` -assert_eq!((", stringify!($SelfT), -"::MIN + 1).checked_div_euclid(-1), Some(", stringify!($Max), ")); -assert_eq!(", stringify!($SelfT), "::MIN.checked_div_euclid(-1), None); -assert_eq!((1", stringify!($SelfT), ").checked_div_euclid(0), None); -```"), - #[stable(feature = "euclidean_division", since = "1.38.0")] - #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn checked_div_euclid(self, rhs: Self) -> Option { - if unlikely!(rhs == 0 || (self == Self::MIN && rhs == -1)) { - None - } else { - Some(self.div_euclid(rhs)) - } - } - } - - doc_comment! { - concat!("Checked integer remainder. Computes `self % rhs`, returning `None` if -`rhs == 0` or the division results in overflow. - -# Examples - -Basic usage: - -``` -", $Feature, " -assert_eq!(5", stringify!($SelfT), ".checked_rem(2), Some(1)); -assert_eq!(5", stringify!($SelfT), ".checked_rem(0), None); -assert_eq!(", stringify!($SelfT), "::MIN.checked_rem(-1), None);", -$EndFeature, " -```"), - #[stable(feature = "wrapping", since = "1.7.0")] - #[rustc_const_unstable(feature = "const_checked_int_methods", issue = "53718")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn checked_rem(self, rhs: Self) -> Option { - if unlikely!(rhs == 0 || (self == Self::MIN && rhs == -1)) { - None - } else { - // SAFETY: div by zero and by INT_MIN have been checked above - Some(unsafe { intrinsics::unchecked_rem(self, rhs) }) - } - } - } - - doc_comment! { - concat!("Checked Euclidean remainder. Computes `self.rem_euclid(rhs)`, returning `None` -if `rhs == 0` or the division results in overflow. - -# Examples - -Basic usage: - -``` -assert_eq!(5", stringify!($SelfT), ".checked_rem_euclid(2), Some(1)); -assert_eq!(5", stringify!($SelfT), ".checked_rem_euclid(0), None); -assert_eq!(", stringify!($SelfT), "::MIN.checked_rem_euclid(-1), None); -```"), - #[stable(feature = "euclidean_division", since = "1.38.0")] - #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn checked_rem_euclid(self, rhs: Self) -> Option { - if unlikely!(rhs == 0 || (self == Self::MIN && rhs == -1)) { - None - } else { - Some(self.rem_euclid(rhs)) - } - } - } - - doc_comment! { - concat!("Checked negation. Computes `-self`, returning `None` if `self == MIN`. - -# Examples - -Basic usage: - -``` -", $Feature, " -assert_eq!(5", stringify!($SelfT), ".checked_neg(), Some(-5)); -assert_eq!(", stringify!($SelfT), "::MIN.checked_neg(), None);", -$EndFeature, " -```"), - #[stable(feature = "wrapping", since = "1.7.0")] - #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")] - #[inline] - pub const fn checked_neg(self) -> Option { - let (a, b) = self.overflowing_neg(); - if unlikely!(b) {None} else {Some(a)} - } - } - - doc_comment! { - concat!("Checked shift left. Computes `self << rhs`, returning `None` if `rhs` is larger -than or equal to the number of bits in `self`. - -# Examples - -Basic usage: - -``` -", $Feature, "assert_eq!(0x1", stringify!($SelfT), ".checked_shl(4), Some(0x10)); -assert_eq!(0x1", stringify!($SelfT), ".checked_shl(129), None);", -$EndFeature, " -```"), - #[stable(feature = "wrapping", since = "1.7.0")] - #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn checked_shl(self, rhs: u32) -> Option { - let (a, b) = self.overflowing_shl(rhs); - if unlikely!(b) {None} else {Some(a)} - } - } - - doc_comment! { - concat!("Checked shift right. Computes `self >> rhs`, returning `None` if `rhs` is -larger than or equal to the number of bits in `self`. - -# Examples - -Basic usage: - -``` -", $Feature, "assert_eq!(0x10", stringify!($SelfT), ".checked_shr(4), Some(0x1)); -assert_eq!(0x10", stringify!($SelfT), ".checked_shr(128), None);", -$EndFeature, " -```"), - #[stable(feature = "wrapping", since = "1.7.0")] - #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn checked_shr(self, rhs: u32) -> Option { - let (a, b) = self.overflowing_shr(rhs); - if unlikely!(b) {None} else {Some(a)} - } - } - - doc_comment! { - concat!("Checked absolute value. Computes `self.abs()`, returning `None` if -`self == MIN`. - -# Examples - -Basic usage: - -``` -", $Feature, " -assert_eq!((-5", stringify!($SelfT), ").checked_abs(), Some(5)); -assert_eq!(", stringify!($SelfT), "::MIN.checked_abs(), None);", -$EndFeature, " -```"), - #[stable(feature = "no_panic_abs", since = "1.13.0")] - #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")] - #[inline] - pub const fn checked_abs(self) -> Option { - if self.is_negative() { - self.checked_neg() - } else { - Some(self) - } - } - } - - doc_comment! { - concat!("Checked exponentiation. Computes `self.pow(exp)`, returning `None` if -overflow occurred. - -# Examples - -Basic usage: - -``` -", $Feature, "assert_eq!(8", stringify!($SelfT), ".checked_pow(2), Some(64)); -assert_eq!(", stringify!($SelfT), "::MAX.checked_pow(2), None);", -$EndFeature, " -```"), - - #[stable(feature = "no_panic_pow", since = "1.34.0")] - #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn checked_pow(self, mut exp: u32) -> Option { - if exp == 0 { - return Some(1); - } - let mut base = self; - let mut acc: Self = 1; - - while exp > 1 { - if (exp & 1) == 1 { - acc = try_opt!(acc.checked_mul(base)); - } - exp /= 2; - base = try_opt!(base.checked_mul(base)); - } - // since exp!=0, finally the exp must be 1. - // Deal with the final bit of the exponent separately, since - // squaring the base afterwards is not necessary and may cause a - // needless overflow. - Some(try_opt!(acc.checked_mul(base))) - } - } - - doc_comment! { - concat!("Saturating integer addition. Computes `self + rhs`, saturating at the numeric -bounds instead of overflowing. - -# Examples - -Basic usage: - -``` -", $Feature, "assert_eq!(100", stringify!($SelfT), ".saturating_add(1), 101); -assert_eq!(", stringify!($SelfT), "::MAX.saturating_add(100), ", stringify!($SelfT), -"::MAX); -assert_eq!(", stringify!($SelfT), "::MIN.saturating_add(-1), ", stringify!($SelfT), -"::MIN);", -$EndFeature, " -```"), - - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_saturating_int_methods", since = "1.47.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn saturating_add(self, rhs: Self) -> Self { - intrinsics::saturating_add(self, rhs) - } - } - - doc_comment! { - concat!("Saturating integer subtraction. Computes `self - rhs`, saturating at the -numeric bounds instead of overflowing. - -# Examples - -Basic usage: - -``` -", $Feature, "assert_eq!(100", stringify!($SelfT), ".saturating_sub(127), -27); -assert_eq!(", stringify!($SelfT), "::MIN.saturating_sub(100), ", stringify!($SelfT), -"::MIN); -assert_eq!(", stringify!($SelfT), "::MAX.saturating_sub(-1), ", stringify!($SelfT), -"::MAX);", -$EndFeature, " -```"), - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_saturating_int_methods", since = "1.47.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn saturating_sub(self, rhs: Self) -> Self { - intrinsics::saturating_sub(self, rhs) - } - } - - doc_comment! { - concat!("Saturating integer negation. Computes `-self`, returning `MAX` if `self == MIN` -instead of overflowing. - -# Examples - -Basic usage: - -``` -", $Feature, "assert_eq!(100", stringify!($SelfT), ".saturating_neg(), -100); -assert_eq!((-100", stringify!($SelfT), ").saturating_neg(), 100); -assert_eq!(", stringify!($SelfT), "::MIN.saturating_neg(), ", stringify!($SelfT), -"::MAX); -assert_eq!(", stringify!($SelfT), "::MAX.saturating_neg(), ", stringify!($SelfT), -"::MIN + 1);", -$EndFeature, " -```"), - - #[stable(feature = "saturating_neg", since = "1.45.0")] - #[rustc_const_stable(feature = "const_saturating_int_methods", since = "1.47.0")] - #[inline] - pub const fn saturating_neg(self) -> Self { - intrinsics::saturating_sub(0, self) - } - } - - doc_comment! { - concat!("Saturating absolute value. Computes `self.abs()`, returning `MAX` if `self == -MIN` instead of overflowing. - -# Examples - -Basic usage: - -``` -", $Feature, "assert_eq!(100", stringify!($SelfT), ".saturating_abs(), 100); -assert_eq!((-100", stringify!($SelfT), ").saturating_abs(), 100); -assert_eq!(", stringify!($SelfT), "::MIN.saturating_abs(), ", stringify!($SelfT), -"::MAX); -assert_eq!((", stringify!($SelfT), "::MIN + 1).saturating_abs(), ", stringify!($SelfT), -"::MAX);", -$EndFeature, " -```"), - - #[stable(feature = "saturating_neg", since = "1.45.0")] - #[rustc_const_stable(feature = "const_saturating_int_methods", since = "1.47.0")] - #[inline] - pub const fn saturating_abs(self) -> Self { - if self.is_negative() { - self.saturating_neg() - } else { - self - } - } - } - - doc_comment! { - concat!("Saturating integer multiplication. Computes `self * rhs`, saturating at the -numeric bounds instead of overflowing. - -# Examples - -Basic usage: - -``` -", $Feature, " -assert_eq!(10", stringify!($SelfT), ".saturating_mul(12), 120); -assert_eq!(", stringify!($SelfT), "::MAX.saturating_mul(10), ", stringify!($SelfT), "::MAX); -assert_eq!(", stringify!($SelfT), "::MIN.saturating_mul(10), ", stringify!($SelfT), "::MIN);", -$EndFeature, " -```"), - #[stable(feature = "wrapping", since = "1.7.0")] - #[rustc_const_stable(feature = "const_saturating_int_methods", since = "1.47.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn saturating_mul(self, rhs: Self) -> Self { - match self.checked_mul(rhs) { - Some(x) => x, - None => if (self < 0) == (rhs < 0) { - Self::MAX - } else { - Self::MIN - } - } - } - } - - doc_comment! { - concat!("Saturating integer exponentiation. Computes `self.pow(exp)`, -saturating at the numeric bounds instead of overflowing. - -# Examples - -Basic usage: - -``` -", $Feature, " -assert_eq!((-4", stringify!($SelfT), ").saturating_pow(3), -64); -assert_eq!(", stringify!($SelfT), "::MIN.saturating_pow(2), ", stringify!($SelfT), "::MAX); -assert_eq!(", stringify!($SelfT), "::MIN.saturating_pow(3), ", stringify!($SelfT), "::MIN);", -$EndFeature, " -```"), - #[stable(feature = "no_panic_pow", since = "1.34.0")] - #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn saturating_pow(self, exp: u32) -> Self { - match self.checked_pow(exp) { - Some(x) => x, - None if self < 0 && exp % 2 == 1 => Self::MIN, - None => Self::MAX, - } - } - } - - doc_comment! { - concat!("Wrapping (modular) addition. Computes `self + rhs`, wrapping around at the -boundary of the type. - -# Examples - -Basic usage: - -``` -", $Feature, "assert_eq!(100", stringify!($SelfT), ".wrapping_add(27), 127); -assert_eq!(", stringify!($SelfT), "::MAX.wrapping_add(2), ", stringify!($SelfT), -"::MIN + 1);", -$EndFeature, " -```"), - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn wrapping_add(self, rhs: Self) -> Self { - intrinsics::wrapping_add(self, rhs) - } - } - - doc_comment! { - concat!("Wrapping (modular) subtraction. Computes `self - rhs`, wrapping around at the -boundary of the type. - -# Examples - -Basic usage: - -``` -", $Feature, "assert_eq!(0", stringify!($SelfT), ".wrapping_sub(127), -127); -assert_eq!((-2", stringify!($SelfT), ").wrapping_sub(", stringify!($SelfT), "::MAX), ", -stringify!($SelfT), "::MAX);", -$EndFeature, " -```"), - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn wrapping_sub(self, rhs: Self) -> Self { - intrinsics::wrapping_sub(self, rhs) - } - } - - doc_comment! { - concat!("Wrapping (modular) multiplication. Computes `self * rhs`, wrapping around at -the boundary of the type. - -# Examples - -Basic usage: - -``` -", $Feature, "assert_eq!(10", stringify!($SelfT), ".wrapping_mul(12), 120); -assert_eq!(11i8.wrapping_mul(12), -124);", -$EndFeature, " -```"), - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn wrapping_mul(self, rhs: Self) -> Self { - intrinsics::wrapping_mul(self, rhs) - } - } - - doc_comment! { - concat!("Wrapping (modular) division. Computes `self / rhs`, wrapping around at the -boundary of the type. - -The only case where such wrapping can occur is when one divides `MIN / -1` on a signed type (where -`MIN` is the negative minimal value for the type); this is equivalent to `-MIN`, a positive value -that is too large to represent in the type. In such a case, this function returns `MIN` itself. - -# Panics - -This function will panic if `rhs` is 0. - -# Examples - -Basic usage: - -``` -", $Feature, "assert_eq!(100", stringify!($SelfT), ".wrapping_div(10), 10); -assert_eq!((-128i8).wrapping_div(-1), -128);", -$EndFeature, " -```"), - #[stable(feature = "num_wrapping", since = "1.2.0")] - #[rustc_const_unstable(feature = "const_wrapping_int_methods", issue = "53718")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn wrapping_div(self, rhs: Self) -> Self { - self.overflowing_div(rhs).0 - } - } - - doc_comment! { - concat!("Wrapping Euclidean division. Computes `self.div_euclid(rhs)`, -wrapping around at the boundary of the type. - -Wrapping will only occur in `MIN / -1` on a signed type (where `MIN` is the negative minimal value -for the type). This is equivalent to `-MIN`, a positive value that is too large to represent in the -type. In this case, this method returns `MIN` itself. - -# Panics - -This function will panic if `rhs` is 0. - -# Examples - -Basic usage: - -``` -assert_eq!(100", stringify!($SelfT), ".wrapping_div_euclid(10), 10); -assert_eq!((-128i8).wrapping_div_euclid(-1), -128); -```"), - #[stable(feature = "euclidean_division", since = "1.38.0")] - #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn wrapping_div_euclid(self, rhs: Self) -> Self { - self.overflowing_div_euclid(rhs).0 - } - } - - doc_comment! { - concat!("Wrapping (modular) remainder. Computes `self % rhs`, wrapping around at the -boundary of the type. - -Such wrap-around never actually occurs mathematically; implementation artifacts make `x % y` -invalid for `MIN / -1` on a signed type (where `MIN` is the negative minimal value). In such a case, -this function returns `0`. - -# Panics - -This function will panic if `rhs` is 0. - -# Examples - -Basic usage: - -``` -", $Feature, "assert_eq!(100", stringify!($SelfT), ".wrapping_rem(10), 0); -assert_eq!((-128i8).wrapping_rem(-1), 0);", -$EndFeature, " -```"), - #[stable(feature = "num_wrapping", since = "1.2.0")] - #[rustc_const_unstable(feature = "const_wrapping_int_methods", issue = "53718")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn wrapping_rem(self, rhs: Self) -> Self { - self.overflowing_rem(rhs).0 - } - } - - doc_comment! { - concat!("Wrapping Euclidean remainder. Computes `self.rem_euclid(rhs)`, wrapping around -at the boundary of the type. - -Wrapping will only occur in `MIN % -1` on a signed type (where `MIN` is the negative minimal value -for the type). In this case, this method returns 0. - -# Panics - -This function will panic if `rhs` is 0. - -# Examples - -Basic usage: - -``` -assert_eq!(100", stringify!($SelfT), ".wrapping_rem_euclid(10), 0); -assert_eq!((-128i8).wrapping_rem_euclid(-1), 0); -```"), - #[stable(feature = "euclidean_division", since = "1.38.0")] - #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn wrapping_rem_euclid(self, rhs: Self) -> Self { - self.overflowing_rem_euclid(rhs).0 - } - } - - doc_comment! { - concat!("Wrapping (modular) negation. Computes `-self`, wrapping around at the boundary -of the type. - -The only case where such wrapping can occur is when one negates `MIN` on a signed type (where `MIN` -is the negative minimal value for the type); this is a positive value that is too large to represent -in the type. In such a case, this function returns `MIN` itself. - -# Examples - -Basic usage: - -``` -", $Feature, "assert_eq!(100", stringify!($SelfT), ".wrapping_neg(), -100); -assert_eq!(", stringify!($SelfT), "::MIN.wrapping_neg(), ", stringify!($SelfT), -"::MIN);", -$EndFeature, " -```"), - #[stable(feature = "num_wrapping", since = "1.2.0")] - #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] - #[inline] - pub const fn wrapping_neg(self) -> Self { - self.overflowing_neg().0 - } - } - - doc_comment! { - concat!("Panic-free bitwise shift-left; yields `self << mask(rhs)`, where `mask` removes -any high-order bits of `rhs` that would cause the shift to exceed the bitwidth of the type. - -Note that this is *not* the same as a rotate-left; the RHS of a wrapping shift-left is restricted to -the range of the type, rather than the bits shifted out of the LHS being returned to the other end. -The primitive integer types all implement a [`rotate_left`](#method.rotate_left) function, -which may be what you want instead. - -# Examples - -Basic usage: - -``` -", $Feature, "assert_eq!((-1", stringify!($SelfT), ").wrapping_shl(7), -128); -assert_eq!((-1", stringify!($SelfT), ").wrapping_shl(128), -1);", -$EndFeature, " -```"), - #[stable(feature = "num_wrapping", since = "1.2.0")] - #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn wrapping_shl(self, rhs: u32) -> Self { - // SAFETY: the masking by the bitsize of the type ensures that we do not shift - // out of bounds - unsafe { - intrinsics::unchecked_shl(self, (rhs & ($BITS - 1)) as $SelfT) - } - } - } - - doc_comment! { - concat!("Panic-free bitwise shift-right; yields `self >> mask(rhs)`, where `mask` -removes any high-order bits of `rhs` that would cause the shift to exceed the bitwidth of the type. - -Note that this is *not* the same as a rotate-right; the RHS of a wrapping shift-right is restricted -to the range of the type, rather than the bits shifted out of the LHS being returned to the other -end. The primitive integer types all implement a [`rotate_right`](#method.rotate_right) function, -which may be what you want instead. - -# Examples - -Basic usage: - -``` -", $Feature, "assert_eq!((-128", stringify!($SelfT), ").wrapping_shr(7), -1); -assert_eq!((-128i16).wrapping_shr(64), -128);", -$EndFeature, " -```"), - #[stable(feature = "num_wrapping", since = "1.2.0")] - #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn wrapping_shr(self, rhs: u32) -> Self { - // SAFETY: the masking by the bitsize of the type ensures that we do not shift - // out of bounds - unsafe { - intrinsics::unchecked_shr(self, (rhs & ($BITS - 1)) as $SelfT) - } - } - } - - doc_comment! { - concat!("Wrapping (modular) absolute value. Computes `self.abs()`, wrapping around at -the boundary of the type. - -The only case where such wrapping can occur is when one takes the absolute value of the negative -minimal value for the type; this is a positive value that is too large to represent in the type. In -such a case, this function returns `MIN` itself. - -# Examples - -Basic usage: - -``` -", $Feature, "assert_eq!(100", stringify!($SelfT), ".wrapping_abs(), 100); -assert_eq!((-100", stringify!($SelfT), ").wrapping_abs(), 100); -assert_eq!(", stringify!($SelfT), "::MIN.wrapping_abs(), ", stringify!($SelfT), -"::MIN); -assert_eq!((-128i8).wrapping_abs() as u8, 128);", -$EndFeature, " -```"), - #[stable(feature = "no_panic_abs", since = "1.13.0")] - #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] - #[allow(unused_attributes)] - #[inline] - pub const fn wrapping_abs(self) -> Self { - if self.is_negative() { - self.wrapping_neg() - } else { - self - } - } - } - - doc_comment! { - concat!("Computes the absolute value of `self` without any wrapping -or panicking. - - -# Examples - -Basic usage: - -``` -", $Feature, "#![feature(unsigned_abs)] -assert_eq!(100", stringify!($SelfT), ".unsigned_abs(), 100", stringify!($UnsignedT), "); -assert_eq!((-100", stringify!($SelfT), ").unsigned_abs(), 100", stringify!($UnsignedT), "); -assert_eq!((-128i8).unsigned_abs(), 128u8);", -$EndFeature, " -```"), - #[unstable(feature = "unsigned_abs", issue = "74913")] - #[inline] - pub const fn unsigned_abs(self) -> $UnsignedT { - self.wrapping_abs() as $UnsignedT - } - } - - doc_comment! { - concat!("Wrapping (modular) exponentiation. Computes `self.pow(exp)`, -wrapping around at the boundary of the type. - -# Examples - -Basic usage: - -``` -", $Feature, "assert_eq!(3", stringify!($SelfT), ".wrapping_pow(4), 81); -assert_eq!(3i8.wrapping_pow(5), -13); -assert_eq!(3i8.wrapping_pow(6), -39);", -$EndFeature, " -```"), - #[stable(feature = "no_panic_pow", since = "1.34.0")] - #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn wrapping_pow(self, mut exp: u32) -> Self { - if exp == 0 { - return 1; - } - let mut base = self; - let mut acc: Self = 1; - - while exp > 1 { - if (exp & 1) == 1 { - acc = acc.wrapping_mul(base); - } - exp /= 2; - base = base.wrapping_mul(base); - } - - // since exp!=0, finally the exp must be 1. - // Deal with the final bit of the exponent separately, since - // squaring the base afterwards is not necessary and may cause a - // needless overflow. - acc.wrapping_mul(base) - } - } - - doc_comment! { - concat!("Calculates `self` + `rhs` - -Returns a tuple of the addition along with a boolean indicating whether an arithmetic overflow would -occur. If an overflow would have occurred then the wrapped value is returned. - -# Examples - -Basic usage: - -``` -", $Feature, " -assert_eq!(5", stringify!($SelfT), ".overflowing_add(2), (7, false)); -assert_eq!(", stringify!($SelfT), "::MAX.overflowing_add(1), (", stringify!($SelfT), -"::MIN, true));", $EndFeature, " -```"), - #[stable(feature = "wrapping", since = "1.7.0")] - #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn overflowing_add(self, rhs: Self) -> (Self, bool) { - let (a, b) = intrinsics::add_with_overflow(self as $ActualT, rhs as $ActualT); - (a as Self, b) - } - } - - doc_comment! { - concat!("Calculates `self` - `rhs` - -Returns a tuple of the subtraction along with a boolean indicating whether an arithmetic overflow -would occur. If an overflow would have occurred then the wrapped value is returned. - -# Examples - -Basic usage: - -``` -", $Feature, " -assert_eq!(5", stringify!($SelfT), ".overflowing_sub(2), (3, false)); -assert_eq!(", stringify!($SelfT), "::MIN.overflowing_sub(1), (", stringify!($SelfT), -"::MAX, true));", $EndFeature, " -```"), - #[stable(feature = "wrapping", since = "1.7.0")] - #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn overflowing_sub(self, rhs: Self) -> (Self, bool) { - let (a, b) = intrinsics::sub_with_overflow(self as $ActualT, rhs as $ActualT); - (a as Self, b) - } - } - - doc_comment! { - concat!("Calculates the multiplication of `self` and `rhs`. - -Returns a tuple of the multiplication along with a boolean indicating whether an arithmetic overflow -would occur. If an overflow would have occurred then the wrapped value is returned. - -# Examples - -Basic usage: - -``` -", $Feature, "assert_eq!(5", stringify!($SelfT), ".overflowing_mul(2), (10, false)); -assert_eq!(1_000_000_000i32.overflowing_mul(10), (1410065408, true));", -$EndFeature, " -```"), - #[stable(feature = "wrapping", since = "1.7.0")] - #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn overflowing_mul(self, rhs: Self) -> (Self, bool) { - let (a, b) = intrinsics::mul_with_overflow(self as $ActualT, rhs as $ActualT); - (a as Self, b) - } - } - - doc_comment! { - concat!("Calculates the divisor when `self` is divided by `rhs`. - -Returns a tuple of the divisor along with a boolean indicating whether an arithmetic overflow would -occur. If an overflow would occur then self is returned. - -# Panics - -This function will panic if `rhs` is 0. - -# Examples - -Basic usage: - -``` -", $Feature, " -assert_eq!(5", stringify!($SelfT), ".overflowing_div(2), (2, false)); -assert_eq!(", stringify!($SelfT), "::MIN.overflowing_div(-1), (", stringify!($SelfT), -"::MIN, true));", -$EndFeature, " -```"), - #[inline] - #[stable(feature = "wrapping", since = "1.7.0")] - #[rustc_const_unstable(feature = "const_overflowing_int_methods", issue = "53718")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - pub const fn overflowing_div(self, rhs: Self) -> (Self, bool) { - if unlikely!(self == Self::MIN && rhs == -1) { - (self, true) - } else { - (self / rhs, false) - } - } - } - - doc_comment! { - concat!("Calculates the quotient of Euclidean division `self.div_euclid(rhs)`. - -Returns a tuple of the divisor along with a boolean indicating whether an arithmetic overflow would -occur. If an overflow would occur then `self` is returned. - -# Panics - -This function will panic if `rhs` is 0. - -# Examples - -Basic usage: - -``` -assert_eq!(5", stringify!($SelfT), ".overflowing_div_euclid(2), (2, false)); -assert_eq!(", stringify!($SelfT), "::MIN.overflowing_div_euclid(-1), (", stringify!($SelfT), -"::MIN, true)); -```"), - #[inline] - #[stable(feature = "euclidean_division", since = "1.38.0")] - #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - pub const fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) { - if unlikely!(self == Self::MIN && rhs == -1) { - (self, true) - } else { - (self.div_euclid(rhs), false) - } - } - } - - doc_comment! { - concat!("Calculates the remainder when `self` is divided by `rhs`. - -Returns a tuple of the remainder after dividing along with a boolean indicating whether an -arithmetic overflow would occur. If an overflow would occur then 0 is returned. - -# Panics - -This function will panic if `rhs` is 0. - -# Examples - -Basic usage: - -``` -", $Feature, " -assert_eq!(5", stringify!($SelfT), ".overflowing_rem(2), (1, false)); -assert_eq!(", stringify!($SelfT), "::MIN.overflowing_rem(-1), (0, true));", -$EndFeature, " -```"), - #[inline] - #[stable(feature = "wrapping", since = "1.7.0")] - #[rustc_const_unstable(feature = "const_overflowing_int_methods", issue = "53718")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - pub const fn overflowing_rem(self, rhs: Self) -> (Self, bool) { - if unlikely!(self == Self::MIN && rhs == -1) { - (0, true) - } else { - (self % rhs, false) - } - } - } - - - doc_comment! { - concat!("Overflowing Euclidean remainder. Calculates `self.rem_euclid(rhs)`. - -Returns a tuple of the remainder after dividing along with a boolean indicating whether an -arithmetic overflow would occur. If an overflow would occur then 0 is returned. - -# Panics - -This function will panic if `rhs` is 0. - -# Examples - -Basic usage: - -``` -assert_eq!(5", stringify!($SelfT), ".overflowing_rem_euclid(2), (1, false)); -assert_eq!(", stringify!($SelfT), "::MIN.overflowing_rem_euclid(-1), (0, true)); -```"), - #[stable(feature = "euclidean_division", since = "1.38.0")] - #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) { - if unlikely!(self == Self::MIN && rhs == -1) { - (0, true) - } else { - (self.rem_euclid(rhs), false) + /// The smallest value that can be represented by this integer type. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN, ", stringify!($Min), ");")] + /// ``` + #[stable(feature = "assoc_int_consts", since = "1.43.0")] + pub const MIN: Self = !0 ^ ((!0 as $UnsignedT) >> 1) as Self; + + /// The largest value that can be represented by this integer type. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX, ", stringify!($Max), ");")] + /// ``` + #[stable(feature = "assoc_int_consts", since = "1.43.0")] + pub const MAX: Self = !Self::MIN; + + /// The size of this integer type in bits. + /// + /// # Examples + /// + /// ``` + /// #![feature(int_bits_const)] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::BITS, ", stringify!($BITS), ");")] + /// ``` + #[unstable(feature = "int_bits_const", issue = "76904")] + pub const BITS: u32 = $BITS; + + /// Converts a string slice in a given base to an integer. + /// + /// The string is expected to be an optional `+` or `-` sign followed by digits. + /// Leading and trailing whitespace represent an error. Digits are a subset of these characters, + /// depending on `radix`: + /// + /// * `0-9` + /// * `a-z` + /// * `A-Z` + /// + /// # Panics + /// + /// This function panics if `radix` is not in the range from 2 to 36. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::from_str_radix(\"A\", 16), Ok(10));")] + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn from_str_radix(src: &str, radix: u32) -> Result { + from_str_radix(src, radix) + } + + /// Returns the number of ones in the binary representation of `self`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let n = 0b100_0000", stringify!($SelfT), ";")] + /// + /// assert_eq!(n.count_ones(), 1); + /// ``` + /// + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] + #[doc(alias = "popcount")] + #[doc(alias = "popcnt")] + #[inline] + pub const fn count_ones(self) -> u32 { (self as $UnsignedT).count_ones() } + + /// Returns the number of zeros in the binary representation of `self`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.count_zeros(), 1);")] + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] + #[inline] + pub const fn count_zeros(self) -> u32 { + (!self).count_ones() + } + + /// Returns the number of leading zeros in the binary representation of `self`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let n = -1", stringify!($SelfT), ";")] + /// + /// assert_eq!(n.leading_zeros(), 0); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] + #[inline] + pub const fn leading_zeros(self) -> u32 { + (self as $UnsignedT).leading_zeros() + } + + /// Returns the number of trailing zeros in the binary representation of `self`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let n = -4", stringify!($SelfT), ";")] + /// + /// assert_eq!(n.trailing_zeros(), 2); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] + #[inline] + pub const fn trailing_zeros(self) -> u32 { + (self as $UnsignedT).trailing_zeros() + } + + /// Returns the number of leading ones in the binary representation of `self`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let n = -1", stringify!($SelfT), ";")] + /// + #[doc = concat!("assert_eq!(n.leading_ones(), ", stringify!($BITS), ");")] + /// ``` + #[stable(feature = "leading_trailing_ones", since = "1.46.0")] + #[rustc_const_stable(feature = "leading_trailing_ones", since = "1.46.0")] + #[inline] + pub const fn leading_ones(self) -> u32 { + (self as $UnsignedT).leading_ones() + } + + /// Returns the number of trailing ones in the binary representation of `self`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let n = 3", stringify!($SelfT), ";")] + /// + /// assert_eq!(n.trailing_ones(), 2); + /// ``` + #[stable(feature = "leading_trailing_ones", since = "1.46.0")] + #[rustc_const_stable(feature = "leading_trailing_ones", since = "1.46.0")] + #[inline] + pub const fn trailing_ones(self) -> u32 { + (self as $UnsignedT).trailing_ones() + } + + /// Shifts the bits to the left by a specified amount, `n`, + /// wrapping the truncated bits to the end of the resulting integer. + /// + /// Please note this isn't the same operation as the `<<` shifting operator! + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let n = ", $rot_op, stringify!($SelfT), ";")] + #[doc = concat!("let m = ", $rot_result, ";")] + /// + #[doc = concat!("assert_eq!(n.rotate_left(", $rot, "), m);")] + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn rotate_left(self, n: u32) -> Self { + (self as $UnsignedT).rotate_left(n) as Self + } + + /// Shifts the bits to the right by a specified amount, `n`, + /// wrapping the truncated bits to the beginning of the resulting + /// integer. + /// + /// Please note this isn't the same operation as the `>>` shifting operator! + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let n = ", $rot_result, stringify!($SelfT), ";")] + #[doc = concat!("let m = ", $rot_op, ";")] + /// + #[doc = concat!("assert_eq!(n.rotate_right(", $rot, "), m);")] + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn rotate_right(self, n: u32) -> Self { + (self as $UnsignedT).rotate_right(n) as Self + } + + /// Reverses the byte order of the integer. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let n = ", $swap_op, stringify!($SelfT), ";")] + /// + /// let m = n.swap_bytes(); + /// + #[doc = concat!("assert_eq!(m, ", $swapped, ");")] + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] + #[inline] + pub const fn swap_bytes(self) -> Self { + (self as $UnsignedT).swap_bytes() as Self + } + + /// Reverses the order of bits in the integer. The least significant bit becomes the most significant bit, + /// second least-significant bit becomes second most-significant bit, etc. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let n = ", $swap_op, stringify!($SelfT), ";")] + /// let m = n.reverse_bits(); + /// + #[doc = concat!("assert_eq!(m, ", $reversed, ");")] + #[doc = concat!("assert_eq!(0, 0", stringify!($SelfT), ".reverse_bits());")] + /// ``` + #[stable(feature = "reverse_bits", since = "1.37.0")] + #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] + #[inline] + #[must_use] + pub const fn reverse_bits(self) -> Self { + (self as $UnsignedT).reverse_bits() as Self + } + + /// Converts an integer from big endian to the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let n = 0x1A", stringify!($SelfT), ";")] + /// + /// if cfg!(target_endian = "big") { + #[doc = concat!(" assert_eq!(", stringify!($SelfT), "::from_be(n), n)")] + /// } else { + #[doc = concat!(" assert_eq!(", stringify!($SelfT), "::from_be(n), n.swap_bytes())")] + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_int_conversions", since = "1.32.0")] + #[inline] + pub const fn from_be(x: Self) -> Self { + #[cfg(target_endian = "big")] + { + x + } + #[cfg(not(target_endian = "big"))] + { + x.swap_bytes() + } + } + + /// Converts an integer from little endian to the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let n = 0x1A", stringify!($SelfT), ";")] + /// + /// if cfg!(target_endian = "little") { + #[doc = concat!(" assert_eq!(", stringify!($SelfT), "::from_le(n), n)")] + /// } else { + #[doc = concat!(" assert_eq!(", stringify!($SelfT), "::from_le(n), n.swap_bytes())")] + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_int_conversions", since = "1.32.0")] + #[inline] + pub const fn from_le(x: Self) -> Self { + #[cfg(target_endian = "little")] + { + x + } + #[cfg(not(target_endian = "little"))] + { + x.swap_bytes() + } + } + + /// Converts `self` to big endian from the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let n = 0x1A", stringify!($SelfT), ";")] + /// + /// if cfg!(target_endian = "big") { + /// assert_eq!(n.to_be(), n) + /// } else { + /// assert_eq!(n.to_be(), n.swap_bytes()) + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_int_conversions", since = "1.32.0")] + #[inline] + pub const fn to_be(self) -> Self { // or not to be? + #[cfg(target_endian = "big")] + { + self + } + #[cfg(not(target_endian = "big"))] + { + self.swap_bytes() + } + } + + /// Converts `self` to little endian from the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let n = 0x1A", stringify!($SelfT), ";")] + /// + /// if cfg!(target_endian = "little") { + /// assert_eq!(n.to_le(), n) + /// } else { + /// assert_eq!(n.to_le(), n.swap_bytes()) + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_int_conversions", since = "1.32.0")] + #[inline] + pub const fn to_le(self) -> Self { + #[cfg(target_endian = "little")] + { + self + } + #[cfg(not(target_endian = "little"))] + { + self.swap_bytes() + } + } + + /// Checked integer addition. Computes `self + rhs`, returning `None` + /// if overflow occurred. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).checked_add(1), Some(", stringify!($SelfT), "::MAX - 1));")] + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).checked_add(3), None);")] + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_add(self, rhs: Self) -> Option { + let (a, b) = self.overflowing_add(rhs); + if unlikely!(b) {None} else {Some(a)} + } + + /// Unchecked integer addition. Computes `self + rhs`, assuming overflow + /// cannot occur. This results in undefined behavior when + #[doc = concat!("`self + rhs > ", stringify!($SelfT), "::MAX` or `self + rhs < ", stringify!($SelfT), "::MIN`.")] + #[unstable( + feature = "unchecked_math", + reason = "niche optimization path", + issue = "none", + )] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub unsafe fn unchecked_add(self, rhs: Self) -> Self { + // SAFETY: the caller must uphold the safety contract for + // `unchecked_add`. + unsafe { intrinsics::unchecked_add(self, rhs) } + } + + /// Checked integer subtraction. Computes `self - rhs`, returning `None` if + /// overflow occurred. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN + 2).checked_sub(1), Some(", stringify!($SelfT), "::MIN + 1));")] + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN + 2).checked_sub(3), None);")] + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_sub(self, rhs: Self) -> Option { + let (a, b) = self.overflowing_sub(rhs); + if unlikely!(b) {None} else {Some(a)} + } + + /// Unchecked integer subtraction. Computes `self - rhs`, assuming overflow + /// cannot occur. This results in undefined behavior when + #[doc = concat!("`self - rhs > ", stringify!($SelfT), "::MAX` or `self - rhs < ", stringify!($SelfT), "::MIN`.")] + #[unstable( + feature = "unchecked_math", + reason = "niche optimization path", + issue = "none", + )] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub unsafe fn unchecked_sub(self, rhs: Self) -> Self { + // SAFETY: the caller must uphold the safety contract for + // `unchecked_sub`. + unsafe { intrinsics::unchecked_sub(self, rhs) } + } + + /// Checked integer multiplication. Computes `self * rhs`, returning `None` if + /// overflow occurred. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.checked_mul(1), Some(", stringify!($SelfT), "::MAX));")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.checked_mul(2), None);")] + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_mul(self, rhs: Self) -> Option { + let (a, b) = self.overflowing_mul(rhs); + if unlikely!(b) {None} else {Some(a)} + } + + /// Unchecked integer multiplication. Computes `self * rhs`, assuming overflow + /// cannot occur. This results in undefined behavior when + #[doc = concat!("`self * rhs > ", stringify!($SelfT), "::MAX` or `self * rhs < ", stringify!($SelfT), "::MIN`.")] + #[unstable( + feature = "unchecked_math", + reason = "niche optimization path", + issue = "none", + )] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub unsafe fn unchecked_mul(self, rhs: Self) -> Self { + // SAFETY: the caller must uphold the safety contract for + // `unchecked_mul`. + unsafe { intrinsics::unchecked_mul(self, rhs) } + } + + /// Checked integer division. Computes `self / rhs`, returning `None` if `rhs == 0` + /// or the division results in overflow. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN + 1).checked_div(-1), Some(", stringify!($Max), "));")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.checked_div(-1), None);")] + #[doc = concat!("assert_eq!((1", stringify!($SelfT), ").checked_div(0), None);")] + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_checked_int_methods", issue = "53718")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_div(self, rhs: Self) -> Option { + if unlikely!(rhs == 0 || (self == Self::MIN && rhs == -1)) { + None + } else { + // SAFETY: div by zero and by INT_MIN have been checked above + Some(unsafe { intrinsics::unchecked_div(self, rhs) }) + } + } + + /// Checked Euclidean division. Computes `self.div_euclid(rhs)`, + /// returning `None` if `rhs == 0` or the division results in overflow. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN + 1).checked_div_euclid(-1), Some(", stringify!($Max), "));")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.checked_div_euclid(-1), None);")] + #[doc = concat!("assert_eq!((1", stringify!($SelfT), ").checked_div_euclid(0), None);")] + /// ``` + #[stable(feature = "euclidean_division", since = "1.38.0")] + #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_div_euclid(self, rhs: Self) -> Option { + if unlikely!(rhs == 0 || (self == Self::MIN && rhs == -1)) { + None + } else { + Some(self.div_euclid(rhs)) + } + } + + /// Checked integer remainder. Computes `self % rhs`, returning `None` if + /// `rhs == 0` or the division results in overflow. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".checked_rem(2), Some(1));")] + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".checked_rem(0), None);")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.checked_rem(-1), None);")] + /// ``` + #[stable(feature = "wrapping", since = "1.7.0")] + #[rustc_const_unstable(feature = "const_checked_int_methods", issue = "53718")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_rem(self, rhs: Self) -> Option { + if unlikely!(rhs == 0 || (self == Self::MIN && rhs == -1)) { + None + } else { + // SAFETY: div by zero and by INT_MIN have been checked above + Some(unsafe { intrinsics::unchecked_rem(self, rhs) }) + } + } + + /// Checked Euclidean remainder. Computes `self.rem_euclid(rhs)`, returning `None` + /// if `rhs == 0` or the division results in overflow. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".checked_rem_euclid(2), Some(1));")] + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".checked_rem_euclid(0), None);")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.checked_rem_euclid(-1), None);")] + /// ``` + #[stable(feature = "euclidean_division", since = "1.38.0")] + #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_rem_euclid(self, rhs: Self) -> Option { + if unlikely!(rhs == 0 || (self == Self::MIN && rhs == -1)) { + None + } else { + Some(self.rem_euclid(rhs)) + } + } + + /// Checked negation. Computes `-self`, returning `None` if `self == MIN`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".checked_neg(), Some(-5));")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.checked_neg(), None);")] + /// ``` + #[stable(feature = "wrapping", since = "1.7.0")] + #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")] + #[inline] + pub const fn checked_neg(self) -> Option { + let (a, b) = self.overflowing_neg(); + if unlikely!(b) {None} else {Some(a)} + } + + /// Checked shift left. Computes `self << rhs`, returning `None` if `rhs` is larger + /// than or equal to the number of bits in `self`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".checked_shl(4), Some(0x10));")] + #[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".checked_shl(129), None);")] + /// ``` + #[stable(feature = "wrapping", since = "1.7.0")] + #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_shl(self, rhs: u32) -> Option { + let (a, b) = self.overflowing_shl(rhs); + if unlikely!(b) {None} else {Some(a)} + } + + /// Checked shift right. Computes `self >> rhs`, returning `None` if `rhs` is + /// larger than or equal to the number of bits in `self`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".checked_shr(4), Some(0x1));")] + #[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".checked_shr(128), None);")] + /// ``` + #[stable(feature = "wrapping", since = "1.7.0")] + #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_shr(self, rhs: u32) -> Option { + let (a, b) = self.overflowing_shr(rhs); + if unlikely!(b) {None} else {Some(a)} + } + + /// Checked absolute value. Computes `self.abs()`, returning `None` if + /// `self == MIN`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// + #[doc = concat!("assert_eq!((-5", stringify!($SelfT), ").checked_abs(), Some(5));")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.checked_abs(), None);")] + /// ``` + #[stable(feature = "no_panic_abs", since = "1.13.0")] + #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")] + #[inline] + pub const fn checked_abs(self) -> Option { + if self.is_negative() { + self.checked_neg() + } else { + Some(self) + } + } + + /// Checked exponentiation. Computes `self.pow(exp)`, returning `None` if + /// overflow occurred. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(8", stringify!($SelfT), ".checked_pow(2), Some(64));")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.checked_pow(2), None);")] + /// ``` + + #[stable(feature = "no_panic_pow", since = "1.34.0")] + #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_pow(self, mut exp: u32) -> Option { + if exp == 0 { + return Some(1); + } + let mut base = self; + let mut acc: Self = 1; + + while exp > 1 { + if (exp & 1) == 1 { + acc = try_opt!(acc.checked_mul(base)); } - } - } - - - doc_comment! { - concat!("Negates self, overflowing if this is equal to the minimum value. - -Returns a tuple of the negated version of self along with a boolean indicating whether an overflow -happened. If `self` is the minimum value (e.g., `i32::MIN` for values of type `i32`), then the -minimum value will be returned again and `true` will be returned for an overflow happening. - -# Examples - -Basic usage: - -``` -assert_eq!(2", stringify!($SelfT), ".overflowing_neg(), (-2, false)); -assert_eq!(", stringify!($SelfT), "::MIN.overflowing_neg(), (", stringify!($SelfT), -"::MIN, true));", $EndFeature, " -```"), - #[inline] - #[stable(feature = "wrapping", since = "1.7.0")] - #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] - #[allow(unused_attributes)] - pub const fn overflowing_neg(self) -> (Self, bool) { - if unlikely!(self == Self::MIN) { - (Self::MIN, true) + exp /= 2; + base = try_opt!(base.checked_mul(base)); + } + // since exp!=0, finally the exp must be 1. + // Deal with the final bit of the exponent separately, since + // squaring the base afterwards is not necessary and may cause a + // needless overflow. + Some(try_opt!(acc.checked_mul(base))) + } + + /// Saturating integer addition. Computes `self + rhs`, saturating at the numeric + /// bounds instead of overflowing. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".saturating_add(1), 101);")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.saturating_add(100), ", stringify!($SelfT), "::MAX);")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.saturating_add(-1), ", stringify!($SelfT), "::MIN);")] + /// ``` + + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_saturating_int_methods", since = "1.47.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn saturating_add(self, rhs: Self) -> Self { + intrinsics::saturating_add(self, rhs) + } + + /// Saturating integer subtraction. Computes `self - rhs`, saturating at the + /// numeric bounds instead of overflowing. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".saturating_sub(127), -27);")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.saturating_sub(100), ", stringify!($SelfT), "::MIN);")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.saturating_sub(-1), ", stringify!($SelfT), "::MAX);")] + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_saturating_int_methods", since = "1.47.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn saturating_sub(self, rhs: Self) -> Self { + intrinsics::saturating_sub(self, rhs) + } + + /// Saturating integer negation. Computes `-self`, returning `MAX` if `self == MIN` + /// instead of overflowing. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".saturating_neg(), -100);")] + #[doc = concat!("assert_eq!((-100", stringify!($SelfT), ").saturating_neg(), 100);")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.saturating_neg(), ", stringify!($SelfT), "::MAX);")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.saturating_neg(), ", stringify!($SelfT), "::MIN + 1);")] + /// ``` + + #[stable(feature = "saturating_neg", since = "1.45.0")] + #[rustc_const_stable(feature = "const_saturating_int_methods", since = "1.47.0")] + #[inline] + pub const fn saturating_neg(self) -> Self { + intrinsics::saturating_sub(0, self) + } + + /// Saturating absolute value. Computes `self.abs()`, returning `MAX` if `self == + /// MIN` instead of overflowing. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".saturating_abs(), 100);")] + #[doc = concat!("assert_eq!((-100", stringify!($SelfT), ").saturating_abs(), 100);")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.saturating_abs(), ", stringify!($SelfT), "::MAX);")] + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN + 1).saturating_abs(), ", stringify!($SelfT), "::MAX);")] + /// ``` + + #[stable(feature = "saturating_neg", since = "1.45.0")] + #[rustc_const_stable(feature = "const_saturating_int_methods", since = "1.47.0")] + #[inline] + pub const fn saturating_abs(self) -> Self { + if self.is_negative() { + self.saturating_neg() + } else { + self + } + } + + /// Saturating integer multiplication. Computes `self * rhs`, saturating at the + /// numeric bounds instead of overflowing. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// + #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".saturating_mul(12), 120);")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.saturating_mul(10), ", stringify!($SelfT), "::MAX);")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.saturating_mul(10), ", stringify!($SelfT), "::MIN);")] + /// ``` + #[stable(feature = "wrapping", since = "1.7.0")] + #[rustc_const_stable(feature = "const_saturating_int_methods", since = "1.47.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn saturating_mul(self, rhs: Self) -> Self { + match self.checked_mul(rhs) { + Some(x) => x, + None => if (self < 0) == (rhs < 0) { + Self::MAX } else { - (-self, false) + Self::MIN } } } - doc_comment! { - concat!("Shifts self left by `rhs` bits. - -Returns a tuple of the shifted version of self along with a boolean indicating whether the shift -value was larger than or equal to the number of bits. If the shift value is too large, then value is -masked (N-1) where N is the number of bits, and this value is then used to perform the shift. - -# Examples - -Basic usage: - -``` -", $Feature, "assert_eq!(0x1", stringify!($SelfT),".overflowing_shl(4), (0x10, false)); -assert_eq!(0x1i32.overflowing_shl(36), (0x10, true));", -$EndFeature, " -```"), - #[stable(feature = "wrapping", since = "1.7.0")] - #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn overflowing_shl(self, rhs: u32) -> (Self, bool) { - (self.wrapping_shl(rhs), (rhs > ($BITS - 1))) - } - } - - doc_comment! { - concat!("Shifts self right by `rhs` bits. - -Returns a tuple of the shifted version of self along with a boolean indicating whether the shift -value was larger than or equal to the number of bits. If the shift value is too large, then value is -masked (N-1) where N is the number of bits, and this value is then used to perform the shift. - -# Examples - -Basic usage: - -``` -", $Feature, "assert_eq!(0x10", stringify!($SelfT), ".overflowing_shr(4), (0x1, false)); -assert_eq!(0x10i32.overflowing_shr(36), (0x1, true));", -$EndFeature, " -```"), - #[stable(feature = "wrapping", since = "1.7.0")] - #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn overflowing_shr(self, rhs: u32) -> (Self, bool) { - (self.wrapping_shr(rhs), (rhs > ($BITS - 1))) - } - } - - doc_comment! { - concat!("Computes the absolute value of `self`. - -Returns a tuple of the absolute version of self along with a boolean indicating whether an overflow -happened. If self is the minimum value (e.g., ", stringify!($SelfT), "::MIN for values of type - ", stringify!($SelfT), "), then the minimum value will be returned again and true will be returned -for an overflow happening. - -# Examples - -Basic usage: - -``` -", $Feature, "assert_eq!(10", stringify!($SelfT), ".overflowing_abs(), (10, false)); -assert_eq!((-10", stringify!($SelfT), ").overflowing_abs(), (10, false)); -assert_eq!((", stringify!($SelfT), "::MIN).overflowing_abs(), (", stringify!($SelfT), -"::MIN, true));", -$EndFeature, " -```"), - #[stable(feature = "no_panic_abs", since = "1.13.0")] - #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] - #[inline] - pub const fn overflowing_abs(self) -> (Self, bool) { - (self.wrapping_abs(), self == Self::MIN) - } - } - - doc_comment! { - concat!("Raises self to the power of `exp`, using exponentiation by squaring. - -Returns a tuple of the exponentiation along with a bool indicating -whether an overflow happened. - -# Examples - -Basic usage: - -``` -", $Feature, "assert_eq!(3", stringify!($SelfT), ".overflowing_pow(4), (81, false)); -assert_eq!(3i8.overflowing_pow(5), (-13, true));", -$EndFeature, " -```"), - #[stable(feature = "no_panic_pow", since = "1.34.0")] - #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn overflowing_pow(self, mut exp: u32) -> (Self, bool) { - if exp == 0 { - return (1,false); + /// Saturating integer exponentiation. Computes `self.pow(exp)`, + /// saturating at the numeric bounds instead of overflowing. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// + #[doc = concat!("assert_eq!((-4", stringify!($SelfT), ").saturating_pow(3), -64);")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.saturating_pow(2), ", stringify!($SelfT), "::MAX);")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.saturating_pow(3), ", stringify!($SelfT), "::MIN);")] + /// ``` + #[stable(feature = "no_panic_pow", since = "1.34.0")] + #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn saturating_pow(self, exp: u32) -> Self { + match self.checked_pow(exp) { + Some(x) => x, + None if self < 0 && exp % 2 == 1 => Self::MIN, + None => Self::MAX, + } + } + + /// Wrapping (modular) addition. Computes `self + rhs`, wrapping around at the + /// boundary of the type. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".wrapping_add(27), 127);")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.wrapping_add(2), ", stringify!($SelfT), "::MIN + 1);")] + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn wrapping_add(self, rhs: Self) -> Self { + intrinsics::wrapping_add(self, rhs) + } + + /// Wrapping (modular) subtraction. Computes `self - rhs`, wrapping around at the + /// boundary of the type. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".wrapping_sub(127), -127);")] + #[doc = concat!("assert_eq!((-2", stringify!($SelfT), ").wrapping_sub(", stringify!($SelfT), "::MAX), ", stringify!($SelfT), "::MAX);")] + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn wrapping_sub(self, rhs: Self) -> Self { + intrinsics::wrapping_sub(self, rhs) + } + + /// Wrapping (modular) multiplication. Computes `self * rhs`, wrapping around at + /// the boundary of the type. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".wrapping_mul(12), 120);")] + /// assert_eq!(11i8.wrapping_mul(12), -124); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn wrapping_mul(self, rhs: Self) -> Self { + intrinsics::wrapping_mul(self, rhs) + } + + /// Wrapping (modular) division. Computes `self / rhs`, wrapping around at the + /// boundary of the type. + /// + /// The only case where such wrapping can occur is when one divides `MIN / -1` on a signed type (where + /// `MIN` is the negative minimal value for the type); this is equivalent to `-MIN`, a positive value + /// that is too large to represent in the type. In such a case, this function returns `MIN` itself. + /// + /// # Panics + /// + /// This function will panic if `rhs` is 0. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".wrapping_div(10), 10);")] + /// assert_eq!((-128i8).wrapping_div(-1), -128); + /// ``` + #[stable(feature = "num_wrapping", since = "1.2.0")] + #[rustc_const_unstable(feature = "const_wrapping_int_methods", issue = "53718")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn wrapping_div(self, rhs: Self) -> Self { + self.overflowing_div(rhs).0 + } + + /// Wrapping Euclidean division. Computes `self.div_euclid(rhs)`, + /// wrapping around at the boundary of the type. + /// + /// Wrapping will only occur in `MIN / -1` on a signed type (where `MIN` is the negative minimal value + /// for the type). This is equivalent to `-MIN`, a positive value that is too large to represent in the + /// type. In this case, this method returns `MIN` itself. + /// + /// # Panics + /// + /// This function will panic if `rhs` is 0. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".wrapping_div_euclid(10), 10);")] + /// assert_eq!((-128i8).wrapping_div_euclid(-1), -128); + /// ``` + #[stable(feature = "euclidean_division", since = "1.38.0")] + #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn wrapping_div_euclid(self, rhs: Self) -> Self { + self.overflowing_div_euclid(rhs).0 + } + + /// Wrapping (modular) remainder. Computes `self % rhs`, wrapping around at the + /// boundary of the type. + /// + /// Such wrap-around never actually occurs mathematically; implementation artifacts make `x % y` + /// invalid for `MIN / -1` on a signed type (where `MIN` is the negative minimal value). In such a case, + /// this function returns `0`. + /// + /// # Panics + /// + /// This function will panic if `rhs` is 0. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".wrapping_rem(10), 0);")] + /// assert_eq!((-128i8).wrapping_rem(-1), 0); + /// ``` + #[stable(feature = "num_wrapping", since = "1.2.0")] + #[rustc_const_unstable(feature = "const_wrapping_int_methods", issue = "53718")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn wrapping_rem(self, rhs: Self) -> Self { + self.overflowing_rem(rhs).0 + } + + /// Wrapping Euclidean remainder. Computes `self.rem_euclid(rhs)`, wrapping around + /// at the boundary of the type. + /// + /// Wrapping will only occur in `MIN % -1` on a signed type (where `MIN` is the negative minimal value + /// for the type). In this case, this method returns 0. + /// + /// # Panics + /// + /// This function will panic if `rhs` is 0. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".wrapping_rem_euclid(10), 0);")] + /// assert_eq!((-128i8).wrapping_rem_euclid(-1), 0); + /// ``` + #[stable(feature = "euclidean_division", since = "1.38.0")] + #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn wrapping_rem_euclid(self, rhs: Self) -> Self { + self.overflowing_rem_euclid(rhs).0 + } + + /// Wrapping (modular) negation. Computes `-self`, wrapping around at the boundary + /// of the type. + /// + /// The only case where such wrapping can occur is when one negates `MIN` on a signed type (where `MIN` + /// is the negative minimal value for the type); this is a positive value that is too large to represent + /// in the type. In such a case, this function returns `MIN` itself. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".wrapping_neg(), -100);")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.wrapping_neg(), ", stringify!($SelfT), "::MIN);")] + /// ``` + #[stable(feature = "num_wrapping", since = "1.2.0")] + #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] + #[inline] + pub const fn wrapping_neg(self) -> Self { + self.overflowing_neg().0 + } + + /// Panic-free bitwise shift-left; yields `self << mask(rhs)`, where `mask` removes + /// any high-order bits of `rhs` that would cause the shift to exceed the bitwidth of the type. + /// + /// Note that this is *not* the same as a rotate-left; the RHS of a wrapping shift-left is restricted to + /// the range of the type, rather than the bits shifted out of the LHS being returned to the other end. + /// The primitive integer types all implement a [`rotate_left`](#method.rotate_left) function, + /// which may be what you want instead. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!((-1", stringify!($SelfT), ").wrapping_shl(7), -128);")] + #[doc = concat!("assert_eq!((-1", stringify!($SelfT), ").wrapping_shl(128), -1);")] + /// ``` + #[stable(feature = "num_wrapping", since = "1.2.0")] + #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn wrapping_shl(self, rhs: u32) -> Self { + // SAFETY: the masking by the bitsize of the type ensures that we do not shift + // out of bounds + unsafe { + intrinsics::unchecked_shl(self, (rhs & ($BITS - 1)) as $SelfT) + } + } + + /// Panic-free bitwise shift-right; yields `self >> mask(rhs)`, where `mask` + /// removes any high-order bits of `rhs` that would cause the shift to exceed the bitwidth of the type. + /// + /// Note that this is *not* the same as a rotate-right; the RHS of a wrapping shift-right is restricted + /// to the range of the type, rather than the bits shifted out of the LHS being returned to the other + /// end. The primitive integer types all implement a [`rotate_right`](#method.rotate_right) function, + /// which may be what you want instead. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!((-128", stringify!($SelfT), ").wrapping_shr(7), -1);")] + /// assert_eq!((-128i16).wrapping_shr(64), -128); + /// ``` + #[stable(feature = "num_wrapping", since = "1.2.0")] + #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn wrapping_shr(self, rhs: u32) -> Self { + // SAFETY: the masking by the bitsize of the type ensures that we do not shift + // out of bounds + unsafe { + intrinsics::unchecked_shr(self, (rhs & ($BITS - 1)) as $SelfT) + } + } + + /// Wrapping (modular) absolute value. Computes `self.abs()`, wrapping around at + /// the boundary of the type. + /// + /// The only case where such wrapping can occur is when one takes the absolute value of the negative + /// minimal value for the type; this is a positive value that is too large to represent in the type. In + /// such a case, this function returns `MIN` itself. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".wrapping_abs(), 100);")] + #[doc = concat!("assert_eq!((-100", stringify!($SelfT), ").wrapping_abs(), 100);")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.wrapping_abs(), ", stringify!($SelfT), "::MIN);")] + /// assert_eq!((-128i8).wrapping_abs() as u8, 128); + /// ``` + #[stable(feature = "no_panic_abs", since = "1.13.0")] + #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] + #[allow(unused_attributes)] + #[inline] + pub const fn wrapping_abs(self) -> Self { + if self.is_negative() { + self.wrapping_neg() + } else { + self + } + } + + /// Computes the absolute value of `self` without any wrapping + /// or panicking. + /// + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(unsigned_abs)] + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".unsigned_abs(), 100", stringify!($UnsignedT), ");")] + #[doc = concat!("assert_eq!((-100", stringify!($SelfT), ").unsigned_abs(), 100", stringify!($UnsignedT), ");")] + /// assert_eq!((-128i8).unsigned_abs(), 128u8); + /// ``` + #[unstable(feature = "unsigned_abs", issue = "74913")] + #[inline] + pub const fn unsigned_abs(self) -> $UnsignedT { + self.wrapping_abs() as $UnsignedT + } + + /// Wrapping (modular) exponentiation. Computes `self.pow(exp)`, + /// wrapping around at the boundary of the type. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(3", stringify!($SelfT), ".wrapping_pow(4), 81);")] + /// assert_eq!(3i8.wrapping_pow(5), -13); + /// assert_eq!(3i8.wrapping_pow(6), -39); + /// ``` + #[stable(feature = "no_panic_pow", since = "1.34.0")] + #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn wrapping_pow(self, mut exp: u32) -> Self { + if exp == 0 { + return 1; + } + let mut base = self; + let mut acc: Self = 1; + + while exp > 1 { + if (exp & 1) == 1 { + acc = acc.wrapping_mul(base); } - let mut base = self; - let mut acc: Self = 1; - let mut overflown = false; - // Scratch space for storing results of overflowing_mul. - let mut r; - - while exp > 1 { - if (exp & 1) == 1 { - r = acc.overflowing_mul(base); - acc = r.0; - overflown |= r.1; - } - exp /= 2; - r = base.overflowing_mul(base); - base = r.0; + exp /= 2; + base = base.wrapping_mul(base); + } + + // since exp!=0, finally the exp must be 1. + // Deal with the final bit of the exponent separately, since + // squaring the base afterwards is not necessary and may cause a + // needless overflow. + acc.wrapping_mul(base) + } + + /// Calculates `self` + `rhs` + /// + /// Returns a tuple of the addition along with a boolean indicating whether an arithmetic overflow would + /// occur. If an overflow would have occurred then the wrapped value is returned. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_add(2), (7, false));")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.overflowing_add(1), (", stringify!($SelfT), "::MIN, true));")] + /// ``` + #[stable(feature = "wrapping", since = "1.7.0")] + #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn overflowing_add(self, rhs: Self) -> (Self, bool) { + let (a, b) = intrinsics::add_with_overflow(self as $ActualT, rhs as $ActualT); + (a as Self, b) + } + + /// Calculates `self` - `rhs` + /// + /// Returns a tuple of the subtraction along with a boolean indicating whether an arithmetic overflow + /// would occur. If an overflow would have occurred then the wrapped value is returned. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_sub(2), (3, false));")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.overflowing_sub(1), (", stringify!($SelfT), "::MAX, true));")] + /// ``` + #[stable(feature = "wrapping", since = "1.7.0")] + #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn overflowing_sub(self, rhs: Self) -> (Self, bool) { + let (a, b) = intrinsics::sub_with_overflow(self as $ActualT, rhs as $ActualT); + (a as Self, b) + } + + /// Calculates the multiplication of `self` and `rhs`. + /// + /// Returns a tuple of the multiplication along with a boolean indicating whether an arithmetic overflow + /// would occur. If an overflow would have occurred then the wrapped value is returned. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_mul(2), (10, false));")] + /// assert_eq!(1_000_000_000i32.overflowing_mul(10), (1410065408, true)); + /// ``` + #[stable(feature = "wrapping", since = "1.7.0")] + #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn overflowing_mul(self, rhs: Self) -> (Self, bool) { + let (a, b) = intrinsics::mul_with_overflow(self as $ActualT, rhs as $ActualT); + (a as Self, b) + } + + /// Calculates the divisor when `self` is divided by `rhs`. + /// + /// Returns a tuple of the divisor along with a boolean indicating whether an arithmetic overflow would + /// occur. If an overflow would occur then self is returned. + /// + /// # Panics + /// + /// This function will panic if `rhs` is 0. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_div(2), (2, false));")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.overflowing_div(-1), (", stringify!($SelfT), "::MIN, true));")] + /// ``` + #[inline] + #[stable(feature = "wrapping", since = "1.7.0")] + #[rustc_const_unstable(feature = "const_overflowing_int_methods", issue = "53718")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + pub const fn overflowing_div(self, rhs: Self) -> (Self, bool) { + if unlikely!(self == Self::MIN && rhs == -1) { + (self, true) + } else { + (self / rhs, false) + } + } + + /// Calculates the quotient of Euclidean division `self.div_euclid(rhs)`. + /// + /// Returns a tuple of the divisor along with a boolean indicating whether an arithmetic overflow would + /// occur. If an overflow would occur then `self` is returned. + /// + /// # Panics + /// + /// This function will panic if `rhs` is 0. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_div_euclid(2), (2, false));")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.overflowing_div_euclid(-1), (", stringify!($SelfT), "::MIN, true));")] + /// ``` + #[inline] + #[stable(feature = "euclidean_division", since = "1.38.0")] + #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + pub const fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) { + if unlikely!(self == Self::MIN && rhs == -1) { + (self, true) + } else { + (self.div_euclid(rhs), false) + } + } + + /// Calculates the remainder when `self` is divided by `rhs`. + /// + /// Returns a tuple of the remainder after dividing along with a boolean indicating whether an + /// arithmetic overflow would occur. If an overflow would occur then 0 is returned. + /// + /// # Panics + /// + /// This function will panic if `rhs` is 0. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_rem(2), (1, false));")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.overflowing_rem(-1), (0, true));")] + /// ``` + #[inline] + #[stable(feature = "wrapping", since = "1.7.0")] + #[rustc_const_unstable(feature = "const_overflowing_int_methods", issue = "53718")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + pub const fn overflowing_rem(self, rhs: Self) -> (Self, bool) { + if unlikely!(self == Self::MIN && rhs == -1) { + (0, true) + } else { + (self % rhs, false) + } + } + + + /// Overflowing Euclidean remainder. Calculates `self.rem_euclid(rhs)`. + /// + /// Returns a tuple of the remainder after dividing along with a boolean indicating whether an + /// arithmetic overflow would occur. If an overflow would occur then 0 is returned. + /// + /// # Panics + /// + /// This function will panic if `rhs` is 0. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_rem_euclid(2), (1, false));")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.overflowing_rem_euclid(-1), (0, true));")] + /// ``` + #[stable(feature = "euclidean_division", since = "1.38.0")] + #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) { + if unlikely!(self == Self::MIN && rhs == -1) { + (0, true) + } else { + (self.rem_euclid(rhs), false) + } + } + + + /// Negates self, overflowing if this is equal to the minimum value. + /// + /// Returns a tuple of the negated version of self along with a boolean indicating whether an overflow + /// happened. If `self` is the minimum value (e.g., `i32::MIN` for values of type `i32`), then the + /// minimum value will be returned again and `true` will be returned for an overflow happening. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".overflowing_neg(), (-2, false));")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.overflowing_neg(), (", stringify!($SelfT), "::MIN, true));")] + /// ``` + #[inline] + #[stable(feature = "wrapping", since = "1.7.0")] + #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] + #[allow(unused_attributes)] + pub const fn overflowing_neg(self) -> (Self, bool) { + if unlikely!(self == Self::MIN) { + (Self::MIN, true) + } else { + (-self, false) + } + } + + /// Shifts self left by `rhs` bits. + /// + /// Returns a tuple of the shifted version of self along with a boolean indicating whether the shift + /// value was larger than or equal to the number of bits. If the shift value is too large, then value is + /// masked (N-1) where N is the number of bits, and this value is then used to perform the shift. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(0x1", stringify!($SelfT),".overflowing_shl(4), (0x10, false));")] + /// assert_eq!(0x1i32.overflowing_shl(36), (0x10, true)); + /// ``` + #[stable(feature = "wrapping", since = "1.7.0")] + #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn overflowing_shl(self, rhs: u32) -> (Self, bool) { + (self.wrapping_shl(rhs), (rhs > ($BITS - 1))) + } + + /// Shifts self right by `rhs` bits. + /// + /// Returns a tuple of the shifted version of self along with a boolean indicating whether the shift + /// value was larger than or equal to the number of bits. If the shift value is too large, then value is + /// masked (N-1) where N is the number of bits, and this value is then used to perform the shift. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".overflowing_shr(4), (0x1, false));")] + /// assert_eq!(0x10i32.overflowing_shr(36), (0x1, true)); + /// ``` + #[stable(feature = "wrapping", since = "1.7.0")] + #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn overflowing_shr(self, rhs: u32) -> (Self, bool) { + (self.wrapping_shr(rhs), (rhs > ($BITS - 1))) + } + + /// Computes the absolute value of `self`. + /// + /// Returns a tuple of the absolute version of self along with a boolean indicating whether an overflow + /// happened. If self is the minimum value + #[doc = concat!("(e.g., ", stringify!($SelfT), "::MIN for values of type ", stringify!($SelfT), "),")] + /// then the minimum value will be returned again and true will be returned + /// for an overflow happening. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".overflowing_abs(), (10, false));")] + #[doc = concat!("assert_eq!((-10", stringify!($SelfT), ").overflowing_abs(), (10, false));")] + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN).overflowing_abs(), (", stringify!($SelfT), "::MIN, true));")] + /// ``` + #[stable(feature = "no_panic_abs", since = "1.13.0")] + #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] + #[inline] + pub const fn overflowing_abs(self) -> (Self, bool) { + (self.wrapping_abs(), self == Self::MIN) + } + + /// Raises self to the power of `exp`, using exponentiation by squaring. + /// + /// Returns a tuple of the exponentiation along with a bool indicating + /// whether an overflow happened. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(3", stringify!($SelfT), ".overflowing_pow(4), (81, false));")] + /// assert_eq!(3i8.overflowing_pow(5), (-13, true)); + /// ``` + #[stable(feature = "no_panic_pow", since = "1.34.0")] + #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn overflowing_pow(self, mut exp: u32) -> (Self, bool) { + if exp == 0 { + return (1,false); + } + let mut base = self; + let mut acc: Self = 1; + let mut overflown = false; + // Scratch space for storing results of overflowing_mul. + let mut r; + + while exp > 1 { + if (exp & 1) == 1 { + r = acc.overflowing_mul(base); + acc = r.0; overflown |= r.1; } - - // since exp!=0, finally the exp must be 1. - // Deal with the final bit of the exponent separately, since - // squaring the base afterwards is not necessary and may cause a - // needless overflow. - r = acc.overflowing_mul(base); - r.1 |= overflown; - r - } - } - - doc_comment! { - concat!("Raises self to the power of `exp`, using exponentiation by squaring. - -# Examples - -Basic usage: - -``` -", $Feature, "let x: ", stringify!($SelfT), " = 2; // or any other integer type - -assert_eq!(x.pow(5), 32);", -$EndFeature, " -```"), - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - #[rustc_inherit_overflow_checks] - pub const fn pow(self, mut exp: u32) -> Self { - if exp == 0 { - return 1; - } - let mut base = self; - let mut acc = 1; - - while exp > 1 { - if (exp & 1) == 1 { - acc = acc * base; - } - exp /= 2; - base = base * base; - } - - // since exp!=0, finally the exp must be 1. - // Deal with the final bit of the exponent separately, since - // squaring the base afterwards is not necessary and may cause a - // needless overflow. - acc * base - } - } - - doc_comment! { - concat!("Calculates the quotient of Euclidean division of `self` by `rhs`. - -This computes the integer `n` such that `self = n * rhs + self.rem_euclid(rhs)`, -with `0 <= self.rem_euclid(rhs) < rhs`. - -In other words, the result is `self / rhs` rounded to the integer `n` -such that `self >= n * rhs`. -If `self > 0`, this is equal to round towards zero (the default in Rust); -if `self < 0`, this is equal to round towards +/- infinity. - -# Panics - -This function will panic if `rhs` is 0 or the division results in overflow. - -# Examples - -Basic usage: - -``` -let a: ", stringify!($SelfT), " = 7; // or any other integer type -let b = 4; - -assert_eq!(a.div_euclid(b), 1); // 7 >= 4 * 1 -assert_eq!(a.div_euclid(-b), -1); // 7 >= -4 * -1 -assert_eq!((-a).div_euclid(b), -2); // -7 >= 4 * -2 -assert_eq!((-a).div_euclid(-b), 2); // -7 >= -4 * 2 -```"), - #[stable(feature = "euclidean_division", since = "1.38.0")] - #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - #[rustc_inherit_overflow_checks] - pub const fn div_euclid(self, rhs: Self) -> Self { - let q = self / rhs; - if self % rhs < 0 { - return if rhs > 0 { q - 1 } else { q + 1 } - } - q - } - } - - - doc_comment! { - concat!("Calculates the least nonnegative remainder of `self (mod rhs)`. - -This is done as if by the Euclidean division algorithm -- given -`r = self.rem_euclid(rhs)`, `self = rhs * self.div_euclid(rhs) + r`, and -`0 <= r < abs(rhs)`. - -# Panics - -This function will panic if `rhs` is 0 or the division results in overflow. - -# Examples - -Basic usage: - -``` -let a: ", stringify!($SelfT), " = 7; // or any other integer type -let b = 4; - -assert_eq!(a.rem_euclid(b), 3); -assert_eq!((-a).rem_euclid(b), 1); -assert_eq!(a.rem_euclid(-b), 3); -assert_eq!((-a).rem_euclid(-b), 1); -```"), - #[stable(feature = "euclidean_division", since = "1.38.0")] - #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - #[rustc_inherit_overflow_checks] - pub const fn rem_euclid(self, rhs: Self) -> Self { - let r = self % rhs; - if r < 0 { - if rhs < 0 { - r - rhs - } else { - r + rhs - } - } else { - r + exp /= 2; + r = base.overflowing_mul(base); + base = r.0; + overflown |= r.1; + } + + // since exp!=0, finally the exp must be 1. + // Deal with the final bit of the exponent separately, since + // squaring the base afterwards is not necessary and may cause a + // needless overflow. + r = acc.overflowing_mul(base); + r.1 |= overflown; + r + } + + /// Raises self to the power of `exp`, using exponentiation by squaring. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let x: ", stringify!($SelfT), " = 2; // or any other integer type")] + /// + /// assert_eq!(x.pow(5), 32); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[rustc_inherit_overflow_checks] + pub const fn pow(self, mut exp: u32) -> Self { + if exp == 0 { + return 1; + } + let mut base = self; + let mut acc = 1; + + while exp > 1 { + if (exp & 1) == 1 { + acc = acc * base; } - } - } - - doc_comment! { - concat!("Computes the absolute value of `self`. - -# Overflow behavior - -The absolute value of `", stringify!($SelfT), "::MIN` cannot be represented as an -`", stringify!($SelfT), "`, and attempting to calculate it will cause an overflow. This means that -code in debug mode will trigger a panic on this case and optimized code will return `", -stringify!($SelfT), "::MIN` without a panic. - -# Examples - -Basic usage: - -``` -", $Feature, "assert_eq!(10", stringify!($SelfT), ".abs(), 10); -assert_eq!((-10", stringify!($SelfT), ").abs(), 10);", -$EndFeature, " -```"), - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] - #[allow(unused_attributes)] - #[inline] - #[rustc_inherit_overflow_checks] - pub const fn abs(self) -> Self { - // Note that the #[inline] above means that the overflow - // semantics of the subtraction depend on the crate we're being - // inlined into. - if self.is_negative() { - -self + exp /= 2; + base = base * base; + } + + // since exp!=0, finally the exp must be 1. + // Deal with the final bit of the exponent separately, since + // squaring the base afterwards is not necessary and may cause a + // needless overflow. + acc * base + } + + /// Calculates the quotient of Euclidean division of `self` by `rhs`. + /// + /// This computes the integer `n` such that `self = n * rhs + self.rem_euclid(rhs)`, + /// with `0 <= self.rem_euclid(rhs) < rhs`. + /// + /// In other words, the result is `self / rhs` rounded to the integer `n` + /// such that `self >= n * rhs`. + /// If `self > 0`, this is equal to round towards zero (the default in Rust); + /// if `self < 0`, this is equal to round towards +/- infinity. + /// + /// # Panics + /// + /// This function will panic if `rhs` is 0 or the division results in overflow. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let a: ", stringify!($SelfT), " = 7; // or any other integer type")] + /// let b = 4; + /// + /// assert_eq!(a.div_euclid(b), 1); // 7 >= 4 * 1 + /// assert_eq!(a.div_euclid(-b), -1); // 7 >= -4 * -1 + /// assert_eq!((-a).div_euclid(b), -2); // -7 >= 4 * -2 + /// assert_eq!((-a).div_euclid(-b), 2); // -7 >= -4 * 2 + /// ``` + #[stable(feature = "euclidean_division", since = "1.38.0")] + #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[rustc_inherit_overflow_checks] + pub const fn div_euclid(self, rhs: Self) -> Self { + let q = self / rhs; + if self % rhs < 0 { + return if rhs > 0 { q - 1 } else { q + 1 } + } + q + } + + + /// Calculates the least nonnegative remainder of `self (mod rhs)`. + /// + /// This is done as if by the Euclidean division algorithm -- given + /// `r = self.rem_euclid(rhs)`, `self = rhs * self.div_euclid(rhs) + r`, and + /// `0 <= r < abs(rhs)`. + /// + /// # Panics + /// + /// This function will panic if `rhs` is 0 or the division results in overflow. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let a: ", stringify!($SelfT), " = 7; // or any other integer type")] + /// let b = 4; + /// + /// assert_eq!(a.rem_euclid(b), 3); + /// assert_eq!((-a).rem_euclid(b), 1); + /// assert_eq!(a.rem_euclid(-b), 3); + /// assert_eq!((-a).rem_euclid(-b), 1); + /// ``` + #[stable(feature = "euclidean_division", since = "1.38.0")] + #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[rustc_inherit_overflow_checks] + pub const fn rem_euclid(self, rhs: Self) -> Self { + let r = self % rhs; + if r < 0 { + if rhs < 0 { + r - rhs } else { - self - } - } - } - - doc_comment! { - concat!("Returns a number representing sign of `self`. - - - `0` if the number is zero - - `1` if the number is positive - - `-1` if the number is negative - -# Examples - -Basic usage: - -``` -", $Feature, "assert_eq!(10", stringify!($SelfT), ".signum(), 1); -assert_eq!(0", stringify!($SelfT), ".signum(), 0); -assert_eq!((-10", stringify!($SelfT), ").signum(), -1);", -$EndFeature, " -```"), - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_int_sign", since = "1.47.0")] - #[inline] - pub const fn signum(self) -> Self { - match self { - n if n > 0 => 1, - 0 => 0, - _ => -1, + r + rhs } + } else { + r } } - doc_comment! { - concat!("Returns `true` if `self` is positive and `false` if the number is zero or -negative. - -# Examples - -Basic usage: - -``` -", $Feature, "assert!(10", stringify!($SelfT), ".is_positive()); -assert!(!(-10", stringify!($SelfT), ").is_positive());", -$EndFeature, " -```"), - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] - #[inline] - pub const fn is_positive(self) -> bool { self > 0 } - } - - doc_comment! { - concat!("Returns `true` if `self` is negative and `false` if the number is zero or -positive. - -# Examples - -Basic usage: - -``` -", $Feature, "assert!((-10", stringify!($SelfT), ").is_negative()); -assert!(!10", stringify!($SelfT), ".is_negative());", -$EndFeature, " -```"), - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] - #[inline] - pub const fn is_negative(self) -> bool { self < 0 } - } - - doc_comment! { - concat!("Return the memory representation of this integer as a byte array in -big-endian (network) byte order. -", -$to_xe_bytes_doc, -" -# Examples - -``` -let bytes = ", $swap_op, stringify!($SelfT), ".to_be_bytes(); -assert_eq!(bytes, ", $be_bytes, "); -```"), - #[stable(feature = "int_to_from_bytes", since = "1.32.0")] - #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")] - #[inline] - pub const fn to_be_bytes(self) -> [u8; mem::size_of::()] { - self.to_be().to_ne_bytes() - } - } - -doc_comment! { - concat!("Return the memory representation of this integer as a byte array in -little-endian byte order. -", -$to_xe_bytes_doc, -" -# Examples - -``` -let bytes = ", $swap_op, stringify!($SelfT), ".to_le_bytes(); -assert_eq!(bytes, ", $le_bytes, "); -```"), - #[stable(feature = "int_to_from_bytes", since = "1.32.0")] - #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")] - #[inline] - pub const fn to_le_bytes(self) -> [u8; mem::size_of::()] { - self.to_le().to_ne_bytes() - } - } - - doc_comment! { - concat!(" -Return the memory representation of this integer as a byte array in -native byte order. - -As the target platform's native endianness is used, portable code -should use [`to_be_bytes`] or [`to_le_bytes`], as appropriate, -instead. -", -$to_xe_bytes_doc, -" -[`to_be_bytes`]: #method.to_be_bytes -[`to_le_bytes`]: #method.to_le_bytes - -# Examples - -``` -let bytes = ", $swap_op, stringify!($SelfT), ".to_ne_bytes(); -assert_eq!( - bytes, - if cfg!(target_endian = \"big\") { - ", $be_bytes, " - } else { - ", $le_bytes, " - } -); -```"), - #[stable(feature = "int_to_from_bytes", since = "1.32.0")] - #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")] - // SAFETY: const sound because integers are plain old datatypes so we can always - // transmute them to arrays of bytes - #[rustc_allow_const_fn_unstable(const_fn_transmute)] - #[inline] - pub const fn to_ne_bytes(self) -> [u8; mem::size_of::()] { - // SAFETY: integers are plain old datatypes so we can always transmute them to - // arrays of bytes - unsafe { mem::transmute(self) } - } - } - - doc_comment! { - concat!(" -Return the memory representation of this integer as a byte array in -native byte order. - -[`to_ne_bytes`] should be preferred over this whenever possible. - -[`to_ne_bytes`]: #method.to_ne_bytes -", - -" -# Examples - -``` -#![feature(num_as_ne_bytes)] -let num = ", $swap_op, stringify!($SelfT), "; -let bytes = num.as_ne_bytes(); -assert_eq!( - bytes, - if cfg!(target_endian = \"big\") { - &", $be_bytes, " - } else { - &", $le_bytes, " - } -); -```"), - #[unstable(feature = "num_as_ne_bytes", issue = "76976")] - #[inline] - pub fn as_ne_bytes(&self) -> &[u8; mem::size_of::()] { - // SAFETY: integers are plain old datatypes so we can always transmute them to - // arrays of bytes - unsafe { &*(self as *const Self as *const _) } - } - } - -doc_comment! { - concat!("Create an integer value from its representation as a byte array in -big endian. -", -$from_xe_bytes_doc, -" -# Examples - -``` -let value = ", stringify!($SelfT), "::from_be_bytes(", $be_bytes, "); -assert_eq!(value, ", $swap_op, "); -``` - -When starting from a slice rather than an array, fallible conversion APIs can be used: - -``` -use std::convert::TryInto; - -fn read_be_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " { - let (int_bytes, rest) = input.split_at(std::mem::size_of::<", stringify!($SelfT), ">()); - *input = rest; - ", stringify!($SelfT), "::from_be_bytes(int_bytes.try_into().unwrap()) -} -```"), - #[stable(feature = "int_to_from_bytes", since = "1.32.0")] - #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")] - #[inline] - pub const fn from_be_bytes(bytes: [u8; mem::size_of::()]) -> Self { - Self::from_be(Self::from_ne_bytes(bytes)) - } - } - -doc_comment! { - concat!(" -Create an integer value from its representation as a byte array in -little endian. -", -$from_xe_bytes_doc, -" -# Examples - -``` -let value = ", stringify!($SelfT), "::from_le_bytes(", $le_bytes, "); -assert_eq!(value, ", $swap_op, "); -``` - -When starting from a slice rather than an array, fallible conversion APIs can be used: - -``` -use std::convert::TryInto; - -fn read_le_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " { - let (int_bytes, rest) = input.split_at(std::mem::size_of::<", stringify!($SelfT), ">()); - *input = rest; - ", stringify!($SelfT), "::from_le_bytes(int_bytes.try_into().unwrap()) -} -```"), - #[stable(feature = "int_to_from_bytes", since = "1.32.0")] - #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")] - #[inline] - pub const fn from_le_bytes(bytes: [u8; mem::size_of::()]) -> Self { - Self::from_le(Self::from_ne_bytes(bytes)) - } - } - - doc_comment! { - concat!("Create an integer value from its memory representation as a byte -array in native endianness. - -As the target platform's native endianness is used, portable code -likely wants to use [`from_be_bytes`] or [`from_le_bytes`], as -appropriate instead. - -[`from_be_bytes`]: #method.from_be_bytes -[`from_le_bytes`]: #method.from_le_bytes -", -$from_xe_bytes_doc, -" -# Examples - -``` -let value = ", stringify!($SelfT), "::from_ne_bytes(if cfg!(target_endian = \"big\") { - ", $be_bytes, " -} else { - ", $le_bytes, " -}); -assert_eq!(value, ", $swap_op, "); -``` - -When starting from a slice rather than an array, fallible conversion APIs can be used: - -``` -use std::convert::TryInto; - -fn read_ne_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " { - let (int_bytes, rest) = input.split_at(std::mem::size_of::<", stringify!($SelfT), ">()); - *input = rest; - ", stringify!($SelfT), "::from_ne_bytes(int_bytes.try_into().unwrap()) -} -```"), - #[stable(feature = "int_to_from_bytes", since = "1.32.0")] - #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")] - // SAFETY: const sound because integers are plain old datatypes so we can always - // transmute to them - #[rustc_allow_const_fn_unstable(const_fn_transmute)] - #[inline] - pub const fn from_ne_bytes(bytes: [u8; mem::size_of::()]) -> Self { - // SAFETY: integers are plain old datatypes so we can always transmute to them - unsafe { mem::transmute(bytes) } - } - } - - doc_comment! { - concat!("**This method is soft-deprecated.** - -Although using it won’t cause a compilation warning, -new code should use [`", stringify!($SelfT), "::MIN", "`](#associatedconstant.MIN) instead. - -Returns the smallest value that can be represented by this integer type."), - #[stable(feature = "rust1", since = "1.0.0")] - #[inline(always)] - #[rustc_promotable] - #[rustc_const_stable(feature = "const_min_value", since = "1.32.0")] - pub const fn min_value() -> Self { - Self::MIN - } - } - - doc_comment! { - concat!("**This method is soft-deprecated.** - -Although using it won’t cause a compilation warning, -new code should use [`", stringify!($SelfT), "::MAX", "`](#associatedconstant.MAX) instead. - -Returns the largest value that can be represented by this integer type."), - #[stable(feature = "rust1", since = "1.0.0")] - #[inline(always)] - #[rustc_promotable] - #[rustc_const_stable(feature = "const_max_value", since = "1.32.0")] - pub const fn max_value() -> Self { - Self::MAX - } + /// Computes the absolute value of `self`. + /// + /// # Overflow behavior + /// + /// The absolute value of + #[doc = concat!("`", stringify!($SelfT), "::MIN`")] + /// cannot be represented as an + #[doc = concat!("`", stringify!($SelfT), "`,")] + /// and attempting to calculate it will cause an overflow. This means + /// that code in debug mode will trigger a panic on this case and + /// optimized code will return + #[doc = concat!("`", stringify!($SelfT), "::MIN`")] + /// without a panic. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".abs(), 10);")] + #[doc = concat!("assert_eq!((-10", stringify!($SelfT), ").abs(), 10);")] + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] + #[allow(unused_attributes)] + #[inline] + #[rustc_inherit_overflow_checks] + pub const fn abs(self) -> Self { + // Note that the #[inline] above means that the overflow + // semantics of the subtraction depend on the crate we're being + // inlined into. + if self.is_negative() { + -self + } else { + self + } + } + + /// Returns a number representing sign of `self`. + /// + /// - `0` if the number is zero + /// - `1` if the number is positive + /// - `-1` if the number is negative + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".signum(), 1);")] + #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".signum(), 0);")] + #[doc = concat!("assert_eq!((-10", stringify!($SelfT), ").signum(), -1);")] + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_int_sign", since = "1.47.0")] + #[inline] + pub const fn signum(self) -> Self { + match self { + n if n > 0 => 1, + 0 => 0, + _ => -1, + } + } + + /// Returns `true` if `self` is positive and `false` if the number is zero or + /// negative. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert!(10", stringify!($SelfT), ".is_positive());")] + #[doc = concat!("assert!(!(-10", stringify!($SelfT), ").is_positive());")] + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] + #[inline] + pub const fn is_positive(self) -> bool { self > 0 } + + /// Returns `true` if `self` is negative and `false` if the number is zero or + /// positive. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert!((-10", stringify!($SelfT), ").is_negative());")] + #[doc = concat!("assert!(!10", stringify!($SelfT), ".is_negative());")] + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] + #[inline] + pub const fn is_negative(self) -> bool { self < 0 } + + /// Return the memory representation of this integer as a byte array in + /// big-endian (network) byte order. + /// + #[doc = $to_xe_bytes_doc] + /// + /// # Examples + /// + /// ``` + #[doc = concat!("let bytes = ", $swap_op, stringify!($SelfT), ".to_be_bytes();")] + #[doc = concat!("assert_eq!(bytes, ", $be_bytes, ");")] + /// ``` + #[stable(feature = "int_to_from_bytes", since = "1.32.0")] + #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")] + #[inline] + pub const fn to_be_bytes(self) -> [u8; mem::size_of::()] { + self.to_be().to_ne_bytes() + } + + /// Return the memory representation of this integer as a byte array in + /// little-endian byte order. + /// + #[doc = $to_xe_bytes_doc] + /// + /// # Examples + /// + /// ``` + #[doc = concat!("let bytes = ", $swap_op, stringify!($SelfT), ".to_le_bytes();")] + #[doc = concat!("assert_eq!(bytes, ", $le_bytes, ");")] + /// ``` + #[stable(feature = "int_to_from_bytes", since = "1.32.0")] + #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")] + #[inline] + pub const fn to_le_bytes(self) -> [u8; mem::size_of::()] { + self.to_le().to_ne_bytes() + } + + /// Return the memory representation of this integer as a byte array in + /// native byte order. + /// + /// As the target platform's native endianness is used, portable code + /// should use [`to_be_bytes`] or [`to_le_bytes`], as appropriate, + /// instead. + /// + #[doc = $to_xe_bytes_doc] + /// + /// [`to_be_bytes`]: #method.to_be_bytes + /// [`to_le_bytes`]: #method.to_le_bytes + /// + /// # Examples + /// + /// ``` + #[doc = concat!("let bytes = ", $swap_op, stringify!($SelfT), ".to_ne_bytes();")] + /// assert_eq!( + /// bytes, + /// if cfg!(target_endian = "big") { + #[doc = concat!(" ", $be_bytes)] + /// } else { + #[doc = concat!(" ", $le_bytes)] + /// } + /// ); + /// ``` + #[stable(feature = "int_to_from_bytes", since = "1.32.0")] + #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")] + // SAFETY: const sound because integers are plain old datatypes so we can always + // transmute them to arrays of bytes + #[rustc_allow_const_fn_unstable(const_fn_transmute)] + #[inline] + pub const fn to_ne_bytes(self) -> [u8; mem::size_of::()] { + // SAFETY: integers are plain old datatypes so we can always transmute them to + // arrays of bytes + unsafe { mem::transmute(self) } + } + + /// Return the memory representation of this integer as a byte array in + /// native byte order. + /// + /// [`to_ne_bytes`] should be preferred over this whenever possible. + /// + /// [`to_ne_bytes`]: #method.to_ne_bytes + /// + /// # Examples + /// + /// ``` + /// #![feature(num_as_ne_bytes)] + #[doc = concat!("let num = ", $swap_op, stringify!($SelfT), ";")] + /// let bytes = num.as_ne_bytes(); + /// assert_eq!( + /// bytes, + /// if cfg!(target_endian = "big") { + #[doc = concat!(" &", $be_bytes)] + /// } else { + #[doc = concat!(" &", $le_bytes)] + /// } + /// ); + /// ``` + #[unstable(feature = "num_as_ne_bytes", issue = "76976")] + #[inline] + pub fn as_ne_bytes(&self) -> &[u8; mem::size_of::()] { + // SAFETY: integers are plain old datatypes so we can always transmute them to + // arrays of bytes + unsafe { &*(self as *const Self as *const _) } + } + + /// Create an integer value from its representation as a byte array in + /// big endian. + /// + #[doc = $to_xe_bytes_doc] + /// + /// # Examples + /// + /// ``` + #[doc = concat!("let value = ", stringify!($SelfT), "::from_be_bytes(", $be_bytes, ");")] + #[doc = concat!("assert_eq!(value, ", $swap_op, ");")] + /// ``` + /// + /// When starting from a slice rather than an array, fallible conversion APIs can be used: + /// + /// ``` + /// use std::convert::TryInto; + /// + #[doc = concat!("fn read_be_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " {")] + #[doc = concat!(" let (int_bytes, rest) = input.split_at(std::mem::size_of::<", stringify!($SelfT), ">());")] + /// *input = rest; + #[doc = concat!(" ", stringify!($SelfT), "::from_be_bytes(int_bytes.try_into().unwrap())")] + /// } + /// ``` + #[stable(feature = "int_to_from_bytes", since = "1.32.0")] + #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")] + #[inline] + pub const fn from_be_bytes(bytes: [u8; mem::size_of::()]) -> Self { + Self::from_be(Self::from_ne_bytes(bytes)) + } + + /// Create an integer value from its representation as a byte array in + /// little endian. + /// + #[doc = $to_xe_bytes_doc] + /// + /// # Examples + /// + /// ``` + #[doc = concat!("let value = ", stringify!($SelfT), "::from_le_bytes(", $le_bytes, ");")] + #[doc = concat!("assert_eq!(value, ", $swap_op, ");")] + /// ``` + /// + /// When starting from a slice rather than an array, fallible conversion APIs can be used: + /// + /// ``` + /// use std::convert::TryInto; + /// + #[doc = concat!("fn read_le_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " {")] + #[doc = concat!(" let (int_bytes, rest) = input.split_at(std::mem::size_of::<", stringify!($SelfT), ">());")] + /// *input = rest; + #[doc = concat!(" ", stringify!($SelfT), "::from_le_bytes(int_bytes.try_into().unwrap())")] + /// } + /// ``` + #[stable(feature = "int_to_from_bytes", since = "1.32.0")] + #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")] + #[inline] + pub const fn from_le_bytes(bytes: [u8; mem::size_of::()]) -> Self { + Self::from_le(Self::from_ne_bytes(bytes)) + } + + /// Create an integer value from its memory representation as a byte + /// array in native endianness. + /// + /// As the target platform's native endianness is used, portable code + /// likely wants to use [`from_be_bytes`] or [`from_le_bytes`], as + /// appropriate instead. + /// + /// [`from_be_bytes`]: #method.from_be_bytes + /// [`from_le_bytes`]: #method.from_le_bytes + /// + #[doc = $to_xe_bytes_doc] + /// + /// # Examples + /// + /// ``` + #[doc = concat!("let value = ", stringify!($SelfT), "::from_ne_bytes(if cfg!(target_endian = \"big\") {")] + #[doc = concat!(" ", $be_bytes)] + /// } else { + #[doc = concat!(" ", $le_bytes)] + /// }); + #[doc = concat!("assert_eq!(value, ", $swap_op, ");")] + /// ``` + /// + /// When starting from a slice rather than an array, fallible conversion APIs can be used: + /// + /// ``` + /// use std::convert::TryInto; + /// + #[doc = concat!("fn read_ne_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " {")] + #[doc = concat!(" let (int_bytes, rest) = input.split_at(std::mem::size_of::<", stringify!($SelfT), ">());")] + /// *input = rest; + #[doc = concat!(" ", stringify!($SelfT), "::from_ne_bytes(int_bytes.try_into().unwrap())")] + /// } + /// ``` + #[stable(feature = "int_to_from_bytes", since = "1.32.0")] + #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")] + // SAFETY: const sound because integers are plain old datatypes so we can always + // transmute to them + #[rustc_allow_const_fn_unstable(const_fn_transmute)] + #[inline] + pub const fn from_ne_bytes(bytes: [u8; mem::size_of::()]) -> Self { + // SAFETY: integers are plain old datatypes so we can always transmute to them + unsafe { mem::transmute(bytes) } + } + + /// **This method is soft-deprecated.** + /// + /// Although using it won’t cause a compilation warning, new code should use + #[doc = concat!("[`", stringify!($SelfT), "::MIN", "`](#associatedconstant.MIN)")] + /// instead. + /// + /// Returns the smallest value that can be represented by this integer type. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline(always)] + #[rustc_promotable] + #[rustc_const_stable(feature = "const_min_value", since = "1.32.0")] + pub const fn min_value() -> Self { + Self::MIN + } + + /// **This method is soft-deprecated.** + /// + /// Although using it won’t cause a compilation warning, new code should use + #[doc = concat!("[`", stringify!($SelfT), "::MAX", "`](#associatedconstant.MAX)")] + /// instead. + /// + /// Returns the largest value that can be represented by this integer type. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline(always)] + #[rustc_promotable] + #[rustc_const_stable(feature = "const_max_value", since = "1.32.0")] + pub const fn max_value() -> Self { + Self::MAX } } } diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index 9f5ae57b74a..6bdfa18fa43 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -23,13 +23,6 @@ macro_rules! unlikely { }; } -macro_rules! doc_comment { - ($x:expr, $($tt:tt)*) => { - #[doc = $x] - $($tt)* - }; -} - // All these modules are technically private and only exposed for coretests: pub mod bignum; pub mod dec2flt; @@ -95,26 +88,26 @@ macro_rules! usize_isize_from_xe_bytes_doc { #[lang = "i8"] impl i8 { - int_impl! { i8, i8, u8, 8, -128, 127, "", "", 2, "-0x7e", "0xa", "0x12", "0x12", "0x48", + int_impl! { i8, i8, u8, 8, -128, 127, 2, "-0x7e", "0xa", "0x12", "0x12", "0x48", "[0x12]", "[0x12]", "", "" } } #[lang = "i16"] impl i16 { - int_impl! { i16, i16, u16, 16, -32768, 32767, "", "", 4, "-0x5ffd", "0x3a", "0x1234", "0x3412", + int_impl! { i16, i16, u16, 16, -32768, 32767, 4, "-0x5ffd", "0x3a", "0x1234", "0x3412", "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]", "", "" } } #[lang = "i32"] impl i32 { - int_impl! { i32, i32, u32, 32, -2147483648, 2147483647, "", "", 8, "0x10000b3", "0xb301", + int_impl! { i32, i32, u32, 32, -2147483648, 2147483647, 8, "0x10000b3", "0xb301", "0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]", "", "" } } #[lang = "i64"] impl i64 { - int_impl! { i64, i64, u64, 64, -9223372036854775808, 9223372036854775807, "", "", 12, + int_impl! { i64, i64, u64, 64, -9223372036854775808, 9223372036854775807, 12, "0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48", "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", "", "" } @@ -123,7 +116,7 @@ impl i64 { #[lang = "i128"] impl i128 { int_impl! { i128, i128, u128, 128, -170141183460469231731687303715884105728, - 170141183460469231731687303715884105727, "", "", 16, + 170141183460469231731687303715884105727, 16, "0x13f40000000000000000000000004f76", "0x4f7613f4", "0x12345678901234567890123456789012", "0x12907856341290785634129078563412", "0x48091e6a2c48091e6a2c48091e6a2c48", "[0x12, 0x90, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78, \ @@ -135,7 +128,7 @@ impl i128 { #[cfg(target_pointer_width = "16")] #[lang = "isize"] impl isize { - int_impl! { isize, i16, usize, 16, -32768, 32767, "", "", 4, "-0x5ffd", "0x3a", "0x1234", + int_impl! { isize, i16, usize, 16, -32768, 32767, 4, "-0x5ffd", "0x3a", "0x1234", "0x3412", "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]", usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() } } @@ -143,7 +136,7 @@ impl isize { #[cfg(target_pointer_width = "32")] #[lang = "isize"] impl isize { - int_impl! { isize, i32, usize, 32, -2147483648, 2147483647, "", "", 8, "0x10000b3", "0xb301", + int_impl! { isize, i32, usize, 32, -2147483648, 2147483647, 8, "0x10000b3", "0xb301", "0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]", usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() } @@ -152,7 +145,7 @@ impl isize { #[cfg(target_pointer_width = "64")] #[lang = "isize"] impl isize { - int_impl! { isize, i64, usize, 64, -9223372036854775808, 9223372036854775807, "", "", + int_impl! { isize, i64, usize, 64, -9223372036854775808, 9223372036854775807, 12, "0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48", "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", @@ -161,7 +154,7 @@ impl isize { #[lang = "u8"] impl u8 { - uint_impl! { u8, u8, 8, 255, "", "", 2, "0x82", "0xa", "0x12", "0x12", "0x48", "[0x12]", + uint_impl! { u8, u8, 8, 255, 2, "0x82", "0xa", "0x12", "0x12", "0x48", "[0x12]", "[0x12]", "", "" } /// Checks if the value is within the ASCII range. @@ -660,19 +653,19 @@ pub const fn is_ascii_control(&self) -> bool { #[lang = "u16"] impl u16 { - uint_impl! { u16, u16, 16, 65535, "", "", 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48", + uint_impl! { u16, u16, 16, 65535, 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]", "", "" } } #[lang = "u32"] impl u32 { - uint_impl! { u32, u32, 32, 4294967295, "", "", 8, "0x10000b3", "0xb301", "0x12345678", + uint_impl! { u32, u32, 32, 4294967295, 8, "0x10000b3", "0xb301", "0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]", "", "" } } #[lang = "u64"] impl u64 { - uint_impl! { u64, u64, 64, 18446744073709551615, "", "", 12, "0xaa00000000006e1", "0x6e10aa", + uint_impl! { u64, u64, 64, 18446744073709551615, 12, "0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48", "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", @@ -681,7 +674,7 @@ impl u64 { #[lang = "u128"] impl u128 { - uint_impl! { u128, u128, 128, 340282366920938463463374607431768211455, "", "", 16, + uint_impl! { u128, u128, 128, 340282366920938463463374607431768211455, 16, "0x13f40000000000000000000000004f76", "0x4f7613f4", "0x12345678901234567890123456789012", "0x12907856341290785634129078563412", "0x48091e6a2c48091e6a2c48091e6a2c48", "[0x12, 0x90, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78, \ @@ -694,14 +687,14 @@ impl u128 { #[cfg(target_pointer_width = "16")] #[lang = "usize"] impl usize { - uint_impl! { usize, u16, 16, 65535, "", "", 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48", + uint_impl! { usize, u16, 16, 65535, 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]", usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() } } #[cfg(target_pointer_width = "32")] #[lang = "usize"] impl usize { - uint_impl! { usize, u32, 32, 4294967295, "", "", 8, "0x10000b3", "0xb301", "0x12345678", + uint_impl! { usize, u32, 32, 4294967295, 8, "0x10000b3", "0xb301", "0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]", usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() } } @@ -709,7 +702,7 @@ impl usize { #[cfg(target_pointer_width = "64")] #[lang = "usize"] impl usize { - uint_impl! { usize, u64, 64, 18446744073709551615, "", "", 12, "0xaa00000000006e1", "0x6e10aa", + uint_impl! { usize, u64, 64, 18446744073709551615, 12, "0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48", "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 716b4a90e5e..ba8918b192f 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -1,20 +1,13 @@ //! Definitions of integer that is known not to equal zero. use crate::fmt; -use crate::ops::{BitOr, BitOrAssign}; +use crate::ops::{BitOr, BitOrAssign, Div, Rem}; use crate::str::FromStr; use super::from_str_radix; use super::{IntErrorKind, ParseIntError}; use crate::intrinsics; -macro_rules! doc_comment { - ($x:expr, $($tt:tt)*) => { - #[doc = $x] - $($tt)* - }; -} - macro_rules! impl_nonzero_fmt { ( #[$stability: meta] ( $( $Trait: ident ),+ ) for $Ty: ident ) => { $( @@ -32,24 +25,21 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { macro_rules! nonzero_integers { ( $( #[$stability: meta] $Ty: ident($Int: ty); )+ ) => { $( - doc_comment! { - concat!("An integer that is known not to equal zero. - -This enables some memory layout optimization. -For example, `Option<", stringify!($Ty), ">` is the same size as `", stringify!($Int), "`: - -```rust -use std::mem::size_of; -assert_eq!(size_of::>(), size_of::<", stringify!($Int), -">()); -```"), - #[$stability] - #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] - #[repr(transparent)] - #[rustc_layout_scalar_valid_range_start(1)] - #[rustc_nonnull_optimization_guaranteed] - pub struct $Ty($Int); - } + /// An integer that is known not to equal zero. + /// + /// This enables some memory layout optimization. + #[doc = concat!("For example, `Option<", stringify!($Ty), ">` is the same size as `", stringify!($Int), "`:")] + /// + /// ```rust + /// use std::mem::size_of; + #[doc = concat!("assert_eq!(size_of::>(), size_of::<", stringify!($Int), ">());")] + /// ``` + #[$stability] + #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] + #[repr(transparent)] + #[rustc_layout_scalar_valid_range_start(1)] + #[rustc_nonnull_optimization_guaranteed] + pub struct $Ty($Int); impl $Ty { /// Creates a non-zero without checking the value. @@ -90,13 +80,10 @@ pub const fn get(self) -> $Int { #[stable(feature = "from_nonzero", since = "1.31.0")] impl From<$Ty> for $Int { - doc_comment! { - concat!( -"Converts a `", stringify!($Ty), "` into an `", stringify!($Int), "`"), - #[inline] - fn from(nonzero: $Ty) -> Self { - nonzero.0 - } + #[doc = concat!("Converts a `", stringify!($Ty), "` into an `", stringify!($Int), "`")] + #[inline] + fn from(nonzero: $Ty) -> Self { + nonzero.0 } } @@ -195,53 +182,49 @@ macro_rules! nonzero_leading_trailing_zeros { ( $( $Ty: ident($Uint: ty) , $LeadingTestExpr:expr ;)+ ) => { $( impl $Ty { - doc_comment! { - concat!("Returns the number of leading zeros in the binary representation of `self`. - -On many architectures, this function can perform better than `leading_zeros()` on the underlying integer type, as special handling of zero can be avoided. - -# Examples - -Basic usage: - -``` -#![feature(nonzero_leading_trailing_zeros)] -let n = std::num::", stringify!($Ty), "::new(", stringify!($LeadingTestExpr), ").unwrap(); - -assert_eq!(n.leading_zeros(), 0); -```"), - #[unstable(feature = "nonzero_leading_trailing_zeros", issue = "79143")] - #[rustc_const_unstable(feature = "nonzero_leading_trailing_zeros", issue = "79143")] - #[inline] - pub const fn leading_zeros(self) -> u32 { - // SAFETY: since `self` can not be zero it is safe to call ctlz_nonzero - unsafe { intrinsics::ctlz_nonzero(self.0 as $Uint) as u32 } - } + /// Returns the number of leading zeros in the binary representation of `self`. + /// + /// On many architectures, this function can perform better than `leading_zeros()` on the underlying integer type, as special handling of zero can be avoided. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(nonzero_leading_trailing_zeros)] + #[doc = concat!("let n = std::num::", stringify!($Ty), "::new(", stringify!($LeadingTestExpr), ").unwrap();")] + /// + /// assert_eq!(n.leading_zeros(), 0); + /// ``` + #[unstable(feature = "nonzero_leading_trailing_zeros", issue = "79143")] + #[rustc_const_unstable(feature = "nonzero_leading_trailing_zeros", issue = "79143")] + #[inline] + pub const fn leading_zeros(self) -> u32 { + // SAFETY: since `self` can not be zero it is safe to call ctlz_nonzero + unsafe { intrinsics::ctlz_nonzero(self.0 as $Uint) as u32 } } - doc_comment! { - concat!("Returns the number of trailing zeros in the binary representation -of `self`. - -On many architectures, this function can perform better than `trailing_zeros()` on the underlying integer type, as special handling of zero can be avoided. - -# Examples - -Basic usage: - -``` -#![feature(nonzero_leading_trailing_zeros)] -let n = std::num::", stringify!($Ty), "::new(0b0101000).unwrap(); - -assert_eq!(n.trailing_zeros(), 3); -```"), - #[unstable(feature = "nonzero_leading_trailing_zeros", issue = "79143")] - #[rustc_const_unstable(feature = "nonzero_leading_trailing_zeros", issue = "79143")] - #[inline] - pub const fn trailing_zeros(self) -> u32 { - // SAFETY: since `self` can not be zero it is safe to call cttz_nonzero - unsafe { intrinsics::cttz_nonzero(self.0 as $Uint) as u32 } - } + /// Returns the number of trailing zeros in the binary representation + /// of `self`. + /// + /// On many architectures, this function can perform better than `trailing_zeros()` on the underlying integer type, as special handling of zero can be avoided. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(nonzero_leading_trailing_zeros)] + #[doc = concat!("let n = std::num::", stringify!($Ty), "::new(0b0101000).unwrap();")] + /// + /// assert_eq!(n.trailing_zeros(), 3); + /// ``` + #[unstable(feature = "nonzero_leading_trailing_zeros", issue = "79143")] + #[rustc_const_unstable(feature = "nonzero_leading_trailing_zeros", issue = "79143")] + #[inline] + pub const fn trailing_zeros(self) -> u32 { + // SAFETY: since `self` can not be zero it is safe to call cttz_nonzero + unsafe { intrinsics::cttz_nonzero(self.0 as $Uint) as u32 } } } @@ -263,3 +246,43 @@ pub const fn trailing_zeros(self) -> u32 { NonZeroI128(u128), -1i128; NonZeroIsize(usize), -1isize; } + +macro_rules! nonzero_integers_div { + ( $( $Ty: ident($Int: ty); )+ ) => { + $( + #[stable(feature = "nonzero_div", since = "1.51.0")] + impl Div<$Ty> for $Int { + type Output = $Int; + /// This operation rounds towards zero, + /// truncating any fractional part of the exact result, and cannot panic. + #[inline] + fn div(self, other: $Ty) -> $Int { + // SAFETY: div by zero is checked because `other` is a nonzero, + // and MIN/-1 is checked because `self` is an unsigned int. + unsafe { crate::intrinsics::unchecked_div(self, other.get()) } + } + } + + #[stable(feature = "nonzero_div", since = "1.51.0")] + impl Rem<$Ty> for $Int { + type Output = $Int; + /// This operation satisfies `n % d == n - (n / d) * d`, and cannot panic. + #[inline] + fn rem(self, other: $Ty) -> $Int { + // SAFETY: rem by zero is checked because `other` is a nonzero, + // and MIN/-1 is checked because `self` is an unsigned int. + unsafe { crate::intrinsics::unchecked_rem(self, other.get()) } + } + } + )+ + } +} + +nonzero_integers_div! { + NonZeroU8(u8); + NonZeroU16(u16); + NonZeroU32(u32); + NonZeroU64(u64); + NonZeroU128(u128); + NonZeroUsize(usize); +} diff --git a/library/core/src/num/shells/int_macros.rs b/library/core/src/num/shells/int_macros.rs index ffd30b03f21..5f8bb648d04 100644 --- a/library/core/src/num/shells/int_macros.rs +++ b/library/core/src/num/shells/int_macros.rs @@ -1,49 +1,44 @@ #![doc(hidden)] -macro_rules! doc_comment { - ($x:expr, $($tt:tt)*) => { - #[doc = $x] - $($tt)* - }; -} - macro_rules! int_module { ($T:ident) => (int_module!($T, #[stable(feature = "rust1", since = "1.0.0")]);); ($T:ident, #[$attr:meta]) => ( - doc_comment! { - concat!("The smallest value that can be represented by this integer type. -Use [`", stringify!($T), "::MIN", "`](../../std/primitive.", stringify!($T), ".html#associatedconstant.MIN) instead. - -# Examples - -```rust -// deprecated way -let min = std::", stringify!($T), "::MIN; - -// intended way -let min = ", stringify!($T), "::MIN; -``` -"), - #[$attr] - pub const MIN: $T = $T::MIN; - } - - doc_comment! { - concat!("The largest value that can be represented by this integer type. -Use [`", stringify!($T), "::MAX", "`](../../std/primitive.", stringify!($T), ".html#associatedconstant.MAX) instead. - -# Examples - -```rust -// deprecated way -let max = std::", stringify!($T), "::MAX; - -// intended way -let max = ", stringify!($T), "::MAX; -``` -"), - #[$attr] - pub const MAX: $T = $T::MAX; - } + #[doc = concat!( + "The smallest value that can be represented by this integer type. Use ", + "[`", stringify!($T), "::MIN", "`](../../std/primitive.", stringify!($T), ".html#associatedconstant.MIN)", + " instead.", + )] + /// + /// # Examples + /// + /// ```rust + /// // deprecated way + #[doc = concat!("let min = std::", stringify!($T), "::MIN;")] + /// + /// // intended way + #[doc = concat!("let min = ", stringify!($T), "::MIN;")] + /// ``` + /// + #[$attr] + pub const MIN: $T = $T::MIN; + + #[doc = concat!( + "The largest value that can be represented by this integer type. Use ", + "[`", stringify!($T), "::MAX", "`](../../std/primitive.", stringify!($T), ".html#associatedconstant.MAX)", + " instead.", + )] + /// + /// # Examples + /// + /// ```rust + /// // deprecated way + #[doc = concat!("let max = std::", stringify!($T), "::MAX;")] + /// + /// // intended way + #[doc = concat!("let max = ", stringify!($T), "::MAX;")] + /// ``` + /// + #[$attr] + pub const MAX: $T = $T::MAX; ) } diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index ae8fc18a838..8f141a3ff9e 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -1,928 +1,842 @@ macro_rules! uint_impl { - ($SelfT:ty, $ActualT:ty, $BITS:expr, $MaxV:expr, $Feature:expr, $EndFeature:expr, + ($SelfT:ty, $ActualT:ty, $BITS:expr, $MaxV:expr, $rot:expr, $rot_op:expr, $rot_result:expr, $swap_op:expr, $swapped:expr, $reversed:expr, $le_bytes:expr, $be_bytes:expr, $to_xe_bytes_doc:expr, $from_xe_bytes_doc:expr) => { - doc_comment! { - concat!("The smallest value that can be represented by this integer type. - -# Examples - -Basic usage: - -``` -", $Feature, "assert_eq!(", stringify!($SelfT), "::MIN, 0);", $EndFeature, " -```"), - #[stable(feature = "assoc_int_consts", since = "1.43.0")] - pub const MIN: Self = 0; - } - - doc_comment! { - concat!("The largest value that can be represented by this integer type. - -# Examples - -Basic usage: - -``` -", $Feature, "assert_eq!(", stringify!($SelfT), "::MAX, ", stringify!($MaxV), ");", -$EndFeature, " -```"), - #[stable(feature = "assoc_int_consts", since = "1.43.0")] - pub const MAX: Self = !0; - } - - doc_comment! { - concat!("The size of this integer type in bits. - -# Examples - -``` -", $Feature, "#![feature(int_bits_const)] -assert_eq!(", stringify!($SelfT), "::BITS, ", stringify!($BITS), ");", -$EndFeature, " -```"), - #[unstable(feature = "int_bits_const", issue = "76904")] - pub const BITS: u32 = $BITS; - } - - doc_comment! { - concat!("Converts a string slice in a given base to an integer. - -The string is expected to be an optional `+` sign -followed by digits. -Leading and trailing whitespace represent an error. -Digits are a subset of these characters, depending on `radix`: - -* `0-9` -* `a-z` -* `A-Z` - -# Panics - -This function panics if `radix` is not in the range from 2 to 36. - -# Examples - -Basic usage: - -``` -", $Feature, "assert_eq!(", stringify!($SelfT), "::from_str_radix(\"A\", 16), Ok(10));", -$EndFeature, " -```"), - #[stable(feature = "rust1", since = "1.0.0")] - pub fn from_str_radix(src: &str, radix: u32) -> Result { - from_str_radix(src, radix) - } - } - - doc_comment! { - concat!("Returns the number of ones in the binary representation of `self`. - -# Examples + /// The smallest value that can be represented by this integer type. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN, 0);")] + /// ``` + #[stable(feature = "assoc_int_consts", since = "1.43.0")] + pub const MIN: Self = 0; -Basic usage: + /// The largest value that can be represented by this integer type. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX, ", stringify!($MaxV), ");")] + /// ``` + #[stable(feature = "assoc_int_consts", since = "1.43.0")] + pub const MAX: Self = !0; -``` -", $Feature, "let n = 0b01001100", stringify!($SelfT), "; + /// The size of this integer type in bits. + /// + /// # Examples + /// + /// ``` + /// #![feature(int_bits_const)] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::BITS, ", stringify!($BITS), ");")] + /// ``` + #[unstable(feature = "int_bits_const", issue = "76904")] + pub const BITS: u32 = $BITS; -assert_eq!(n.count_ones(), 3);", $EndFeature, " -```"), - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_math", since = "1.32.0")] - #[doc(alias = "popcount")] - #[doc(alias = "popcnt")] - #[inline] - pub const fn count_ones(self) -> u32 { - intrinsics::ctpop(self as $ActualT) as u32 - } + /// Converts a string slice in a given base to an integer. + /// + /// The string is expected to be an optional `+` sign + /// followed by digits. + /// Leading and trailing whitespace represent an error. + /// Digits are a subset of these characters, depending on `radix`: + /// + /// * `0-9` + /// * `a-z` + /// * `A-Z` + /// + /// # Panics + /// + /// This function panics if `radix` is not in the range from 2 to 36. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::from_str_radix(\"A\", 16), Ok(10));")] + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn from_str_radix(src: &str, radix: u32) -> Result { + from_str_radix(src, radix) } - doc_comment! { - concat!("Returns the number of zeros in the binary representation of `self`. - -# Examples - -Basic usage: - -``` -", $Feature, "assert_eq!(", stringify!($SelfT), "::MAX.count_zeros(), 0);", $EndFeature, " -```"), - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_math", since = "1.32.0")] - #[inline] - pub const fn count_zeros(self) -> u32 { - (!self).count_ones() - } + /// Returns the number of ones in the binary representation of `self`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let n = 0b01001100", stringify!($SelfT), ";")] + /// + /// assert_eq!(n.count_ones(), 3); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_math", since = "1.32.0")] + #[doc(alias = "popcount")] + #[doc(alias = "popcnt")] + #[inline] + pub const fn count_ones(self) -> u32 { + intrinsics::ctpop(self as $ActualT) as u32 } - doc_comment! { - concat!("Returns the number of leading zeros in the binary representation of `self`. - -# Examples - -Basic usage: - -``` -", $Feature, "let n = ", stringify!($SelfT), "::MAX >> 2; - -assert_eq!(n.leading_zeros(), 2);", $EndFeature, " -```"), - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_math", since = "1.32.0")] - #[inline] - pub const fn leading_zeros(self) -> u32 { - intrinsics::ctlz(self as $ActualT) as u32 - } + /// Returns the number of zeros in the binary representation of `self`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.count_zeros(), 0);")] + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_math", since = "1.32.0")] + #[inline] + pub const fn count_zeros(self) -> u32 { + (!self).count_ones() } - doc_comment! { - concat!("Returns the number of trailing zeros in the binary representation -of `self`. - -# Examples - -Basic usage: - -``` -", $Feature, "let n = 0b0101000", stringify!($SelfT), "; - -assert_eq!(n.trailing_zeros(), 3);", $EndFeature, " -```"), - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_math", since = "1.32.0")] - #[inline] - pub const fn trailing_zeros(self) -> u32 { - intrinsics::cttz(self) as u32 - } + /// Returns the number of leading zeros in the binary representation of `self`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let n = ", stringify!($SelfT), "::MAX >> 2;")] + /// + /// assert_eq!(n.leading_zeros(), 2); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_math", since = "1.32.0")] + #[inline] + pub const fn leading_zeros(self) -> u32 { + intrinsics::ctlz(self as $ActualT) as u32 } - doc_comment! { - concat!("Returns the number of leading ones in the binary representation of `self`. - -# Examples - -Basic usage: - -``` -", $Feature, "let n = !(", stringify!($SelfT), "::MAX >> 2); - -assert_eq!(n.leading_ones(), 2);", $EndFeature, " -```"), - #[stable(feature = "leading_trailing_ones", since = "1.46.0")] - #[rustc_const_stable(feature = "leading_trailing_ones", since = "1.46.0")] - #[inline] - pub const fn leading_ones(self) -> u32 { - (!self).leading_zeros() - } + /// Returns the number of trailing zeros in the binary representation + /// of `self`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let n = 0b0101000", stringify!($SelfT), ";")] + /// + /// assert_eq!(n.trailing_zeros(), 3); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_math", since = "1.32.0")] + #[inline] + pub const fn trailing_zeros(self) -> u32 { + intrinsics::cttz(self) as u32 } - doc_comment! { - concat!("Returns the number of trailing ones in the binary representation -of `self`. - -# Examples - -Basic usage: - -``` -", $Feature, "let n = 0b1010111", stringify!($SelfT), "; - -assert_eq!(n.trailing_ones(), 3);", $EndFeature, " -```"), - #[stable(feature = "leading_trailing_ones", since = "1.46.0")] - #[rustc_const_stable(feature = "leading_trailing_ones", since = "1.46.0")] - #[inline] - pub const fn trailing_ones(self) -> u32 { - (!self).trailing_zeros() - } + /// Returns the number of leading ones in the binary representation of `self`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let n = !(", stringify!($SelfT), "::MAX >> 2);")] + /// + /// assert_eq!(n.leading_ones(), 2); + /// ``` + #[stable(feature = "leading_trailing_ones", since = "1.46.0")] + #[rustc_const_stable(feature = "leading_trailing_ones", since = "1.46.0")] + #[inline] + pub const fn leading_ones(self) -> u32 { + (!self).leading_zeros() } - doc_comment! { - concat!("Shifts the bits to the left by a specified amount, `n`, -wrapping the truncated bits to the end of the resulting integer. - -Please note this isn't the same operation as the `<<` shifting operator! - -# Examples - -Basic usage: - -``` -let n = ", $rot_op, stringify!($SelfT), "; -let m = ", $rot_result, "; - -assert_eq!(n.rotate_left(", $rot, "), m); -```"), - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_math", since = "1.32.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn rotate_left(self, n: u32) -> Self { - intrinsics::rotate_left(self, n as $SelfT) - } + /// Returns the number of trailing ones in the binary representation + /// of `self`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let n = 0b1010111", stringify!($SelfT), ";")] + /// + /// assert_eq!(n.trailing_ones(), 3); + /// ``` + #[stable(feature = "leading_trailing_ones", since = "1.46.0")] + #[rustc_const_stable(feature = "leading_trailing_ones", since = "1.46.0")] + #[inline] + pub const fn trailing_ones(self) -> u32 { + (!self).trailing_zeros() } - doc_comment! { - concat!("Shifts the bits to the right by a specified amount, `n`, -wrapping the truncated bits to the beginning of the resulting -integer. - -Please note this isn't the same operation as the `>>` shifting operator! - -# Examples - -Basic usage: - -``` -let n = ", $rot_result, stringify!($SelfT), "; -let m = ", $rot_op, "; - -assert_eq!(n.rotate_right(", $rot, "), m); -```"), - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_math", since = "1.32.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn rotate_right(self, n: u32) -> Self { - intrinsics::rotate_right(self, n as $SelfT) - } + /// Shifts the bits to the left by a specified amount, `n`, + /// wrapping the truncated bits to the end of the resulting integer. + /// + /// Please note this isn't the same operation as the `<<` shifting operator! + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let n = ", $rot_op, stringify!($SelfT), ";")] + #[doc = concat!("let m = ", $rot_result, ";")] + /// + #[doc = concat!("assert_eq!(n.rotate_left(", $rot, "), m);")] + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_math", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn rotate_left(self, n: u32) -> Self { + intrinsics::rotate_left(self, n as $SelfT) } - doc_comment! { - concat!(" -Reverses the byte order of the integer. - -# Examples - -Basic usage: - -``` -let n = ", $swap_op, stringify!($SelfT), "; -let m = n.swap_bytes(); - -assert_eq!(m, ", $swapped, "); -```"), - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_math", since = "1.32.0")] - #[inline] - pub const fn swap_bytes(self) -> Self { - intrinsics::bswap(self as $ActualT) as Self - } + /// Shifts the bits to the right by a specified amount, `n`, + /// wrapping the truncated bits to the beginning of the resulting + /// integer. + /// + /// Please note this isn't the same operation as the `>>` shifting operator! + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let n = ", $rot_result, stringify!($SelfT), ";")] + #[doc = concat!("let m = ", $rot_op, ";")] + /// + #[doc = concat!("assert_eq!(n.rotate_right(", $rot, "), m);")] + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_math", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn rotate_right(self, n: u32) -> Self { + intrinsics::rotate_right(self, n as $SelfT) } - doc_comment! { - concat!("Reverses the order of bits in the integer. The least significant bit becomes the most significant bit, - second least-significant bit becomes second most-significant bit, etc. - -# Examples - -Basic usage: - -``` -let n = ", $swap_op, stringify!($SelfT), "; -let m = n.reverse_bits(); - -assert_eq!(m, ", $reversed, "); -assert_eq!(0, 0", stringify!($SelfT), ".reverse_bits()); -```"), - #[stable(feature = "reverse_bits", since = "1.37.0")] - #[rustc_const_stable(feature = "const_math", since = "1.32.0")] - #[inline] - #[must_use] - pub const fn reverse_bits(self) -> Self { - intrinsics::bitreverse(self as $ActualT) as Self - } + /// Reverses the byte order of the integer. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let n = ", $swap_op, stringify!($SelfT), ";")] + /// let m = n.swap_bytes(); + /// + #[doc = concat!("assert_eq!(m, ", $swapped, ");")] + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_math", since = "1.32.0")] + #[inline] + pub const fn swap_bytes(self) -> Self { + intrinsics::bswap(self as $ActualT) as Self } - doc_comment! { - concat!("Converts an integer from big endian to the target's endianness. - -On big endian this is a no-op. On little endian the bytes are -swapped. - -# Examples - -Basic usage: - -``` -", $Feature, "let n = 0x1A", stringify!($SelfT), "; - -if cfg!(target_endian = \"big\") { - assert_eq!(", stringify!($SelfT), "::from_be(n), n) -} else { - assert_eq!(", stringify!($SelfT), "::from_be(n), n.swap_bytes()) -}", $EndFeature, " -```"), - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_math", since = "1.32.0")] - #[inline] - pub const fn from_be(x: Self) -> Self { - #[cfg(target_endian = "big")] - { - x - } - #[cfg(not(target_endian = "big"))] - { - x.swap_bytes() - } - } + /// Reverses the order of bits in the integer. The least significant bit becomes the most significant bit, + /// second least-significant bit becomes second most-significant bit, etc. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let n = ", $swap_op, stringify!($SelfT), ";")] + /// let m = n.reverse_bits(); + /// + #[doc = concat!("assert_eq!(m, ", $reversed, ");")] + #[doc = concat!("assert_eq!(0, 0", stringify!($SelfT), ".reverse_bits());")] + /// ``` + #[stable(feature = "reverse_bits", since = "1.37.0")] + #[rustc_const_stable(feature = "const_math", since = "1.32.0")] + #[inline] + #[must_use] + pub const fn reverse_bits(self) -> Self { + intrinsics::bitreverse(self as $ActualT) as Self } - doc_comment! { - concat!("Converts an integer from little endian to the target's endianness. - -On little endian this is a no-op. On big endian the bytes are -swapped. - -# Examples - -Basic usage: - -``` -", $Feature, "let n = 0x1A", stringify!($SelfT), "; - -if cfg!(target_endian = \"little\") { - assert_eq!(", stringify!($SelfT), "::from_le(n), n) -} else { - assert_eq!(", stringify!($SelfT), "::from_le(n), n.swap_bytes()) -}", $EndFeature, " -```"), - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_math", since = "1.32.0")] - #[inline] - pub const fn from_le(x: Self) -> Self { - #[cfg(target_endian = "little")] - { - x - } - #[cfg(not(target_endian = "little"))] - { - x.swap_bytes() - } + /// Converts an integer from big endian to the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are + /// swapped. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let n = 0x1A", stringify!($SelfT), ";")] + /// + /// if cfg!(target_endian = "big") { + #[doc = concat!(" assert_eq!(", stringify!($SelfT), "::from_be(n), n)")] + /// } else { + #[doc = concat!(" assert_eq!(", stringify!($SelfT), "::from_be(n), n.swap_bytes())")] + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_math", since = "1.32.0")] + #[inline] + pub const fn from_be(x: Self) -> Self { + #[cfg(target_endian = "big")] + { + x } - } - - doc_comment! { - concat!("Converts `self` to big endian from the target's endianness. - -On big endian this is a no-op. On little endian the bytes are -swapped. - -# Examples - -Basic usage: - -``` -", $Feature, "let n = 0x1A", stringify!($SelfT), "; - -if cfg!(target_endian = \"big\") { - assert_eq!(n.to_be(), n) -} else { - assert_eq!(n.to_be(), n.swap_bytes()) -}", $EndFeature, " -```"), - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_math", since = "1.32.0")] - #[inline] - pub const fn to_be(self) -> Self { // or not to be? - #[cfg(target_endian = "big")] - { - self - } - #[cfg(not(target_endian = "big"))] - { - self.swap_bytes() - } + #[cfg(not(target_endian = "big"))] + { + x.swap_bytes() } } - doc_comment! { - concat!("Converts `self` to little endian from the target's endianness. - -On little endian this is a no-op. On big endian the bytes are -swapped. - -# Examples - -Basic usage: - -``` -", $Feature, "let n = 0x1A", stringify!($SelfT), "; - -if cfg!(target_endian = \"little\") { - assert_eq!(n.to_le(), n) -} else { - assert_eq!(n.to_le(), n.swap_bytes()) -}", $EndFeature, " -```"), - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_math", since = "1.32.0")] - #[inline] - pub const fn to_le(self) -> Self { - #[cfg(target_endian = "little")] - { - self - } - #[cfg(not(target_endian = "little"))] - { - self.swap_bytes() - } + /// Converts an integer from little endian to the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are + /// swapped. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let n = 0x1A", stringify!($SelfT), ";")] + /// + /// if cfg!(target_endian = "little") { + #[doc = concat!(" assert_eq!(", stringify!($SelfT), "::from_le(n), n)")] + /// } else { + #[doc = concat!(" assert_eq!(", stringify!($SelfT), "::from_le(n), n.swap_bytes())")] + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_math", since = "1.32.0")] + #[inline] + pub const fn from_le(x: Self) -> Self { + #[cfg(target_endian = "little")] + { + x } - } - - doc_comment! { - concat!("Checked integer addition. Computes `self + rhs`, returning `None` -if overflow occurred. - -# Examples - -Basic usage: - -``` -", $Feature, "assert_eq!((", stringify!($SelfT), "::MAX - 2).checked_add(1), ", -"Some(", stringify!($SelfT), "::MAX - 1)); -assert_eq!((", stringify!($SelfT), "::MAX - 2).checked_add(3), None);", $EndFeature, " -```"), - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn checked_add(self, rhs: Self) -> Option { - let (a, b) = self.overflowing_add(rhs); - if unlikely!(b) {None} else {Some(a)} + #[cfg(not(target_endian = "little"))] + { + x.swap_bytes() } } - doc_comment! { - concat!("Unchecked integer addition. Computes `self + rhs`, assuming overflow -cannot occur. This results in undefined behavior when `self + rhs > ", stringify!($SelfT), -"::MAX` or `self + rhs < ", stringify!($SelfT), "::MIN`."), - #[unstable( - feature = "unchecked_math", - reason = "niche optimization path", - issue = "none", - )] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub unsafe fn unchecked_add(self, rhs: Self) -> Self { - // SAFETY: the caller must uphold the safety contract for - // `unchecked_add`. - unsafe { intrinsics::unchecked_add(self, rhs) } + /// Converts `self` to big endian from the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are + /// swapped. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let n = 0x1A", stringify!($SelfT), ";")] + /// + /// if cfg!(target_endian = "big") { + /// assert_eq!(n.to_be(), n) + /// } else { + /// assert_eq!(n.to_be(), n.swap_bytes()) + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_math", since = "1.32.0")] + #[inline] + pub const fn to_be(self) -> Self { // or not to be? + #[cfg(target_endian = "big")] + { + self } - } - - doc_comment! { - concat!("Checked integer subtraction. Computes `self - rhs`, returning -`None` if overflow occurred. - -# Examples - -Basic usage: - -``` -", $Feature, "assert_eq!(1", stringify!($SelfT), ".checked_sub(1), Some(0)); -assert_eq!(0", stringify!($SelfT), ".checked_sub(1), None);", $EndFeature, " -```"), - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn checked_sub(self, rhs: Self) -> Option { - let (a, b) = self.overflowing_sub(rhs); - if unlikely!(b) {None} else {Some(a)} + #[cfg(not(target_endian = "big"))] + { + self.swap_bytes() } } - doc_comment! { - concat!("Unchecked integer subtraction. Computes `self - rhs`, assuming overflow -cannot occur. This results in undefined behavior when `self - rhs > ", stringify!($SelfT), -"::MAX` or `self - rhs < ", stringify!($SelfT), "::MIN`."), - #[unstable( - feature = "unchecked_math", - reason = "niche optimization path", - issue = "none", - )] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub unsafe fn unchecked_sub(self, rhs: Self) -> Self { - // SAFETY: the caller must uphold the safety contract for - // `unchecked_sub`. - unsafe { intrinsics::unchecked_sub(self, rhs) } + /// Converts `self` to little endian from the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are + /// swapped. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let n = 0x1A", stringify!($SelfT), ";")] + /// + /// if cfg!(target_endian = "little") { + /// assert_eq!(n.to_le(), n) + /// } else { + /// assert_eq!(n.to_le(), n.swap_bytes()) + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_math", since = "1.32.0")] + #[inline] + pub const fn to_le(self) -> Self { + #[cfg(target_endian = "little")] + { + self } - } - - doc_comment! { - concat!("Checked integer multiplication. Computes `self * rhs`, returning -`None` if overflow occurred. - -# Examples - -Basic usage: - -``` -", $Feature, "assert_eq!(5", stringify!($SelfT), ".checked_mul(1), Some(5)); -assert_eq!(", stringify!($SelfT), "::MAX.checked_mul(2), None);", $EndFeature, " -```"), - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn checked_mul(self, rhs: Self) -> Option { - let (a, b) = self.overflowing_mul(rhs); - if unlikely!(b) {None} else {Some(a)} + #[cfg(not(target_endian = "little"))] + { + self.swap_bytes() } } - doc_comment! { - concat!("Unchecked integer multiplication. Computes `self * rhs`, assuming overflow -cannot occur. This results in undefined behavior when `self * rhs > ", stringify!($SelfT), -"::MAX` or `self * rhs < ", stringify!($SelfT), "::MIN`."), - #[unstable( - feature = "unchecked_math", - reason = "niche optimization path", - issue = "none", - )] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub unsafe fn unchecked_mul(self, rhs: Self) -> Self { - // SAFETY: the caller must uphold the safety contract for - // `unchecked_mul`. - unsafe { intrinsics::unchecked_mul(self, rhs) } - } + /// Checked integer addition. Computes `self + rhs`, returning `None` + /// if overflow occurred. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!( + "assert_eq!((", stringify!($SelfT), "::MAX - 2).checked_add(1), ", + "Some(", stringify!($SelfT), "::MAX - 1));" + )] + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).checked_add(3), None);")] + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_add(self, rhs: Self) -> Option { + let (a, b) = self.overflowing_add(rhs); + if unlikely!(b) {None} else {Some(a)} + } + + /// Unchecked integer addition. Computes `self + rhs`, assuming overflow + /// cannot occur. This results in undefined behavior when + #[doc = concat!("`self + rhs > ", stringify!($SelfT), "::MAX` or `self + rhs < ", stringify!($SelfT), "::MIN`.")] + #[unstable( + feature = "unchecked_math", + reason = "niche optimization path", + issue = "none", + )] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub unsafe fn unchecked_add(self, rhs: Self) -> Self { + // SAFETY: the caller must uphold the safety contract for + // `unchecked_add`. + unsafe { intrinsics::unchecked_add(self, rhs) } } - doc_comment! { - concat!("Checked integer division. Computes `self / rhs`, returning `None` -if `rhs == 0`. - -# Examples - -Basic usage: - -``` -", $Feature, "assert_eq!(128", stringify!($SelfT), ".checked_div(2), Some(64)); -assert_eq!(1", stringify!($SelfT), ".checked_div(0), None);", $EndFeature, " -```"), - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_checked_int_methods", issue = "53718")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn checked_div(self, rhs: Self) -> Option { - if unlikely!(rhs == 0) { - None - } else { - // SAFETY: div by zero has been checked above and unsigned types have no other - // failure modes for division - Some(unsafe { intrinsics::unchecked_div(self, rhs) }) - } - } + /// Checked integer subtraction. Computes `self - rhs`, returning + /// `None` if overflow occurred. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".checked_sub(1), Some(0));")] + #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".checked_sub(1), None);")] + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_sub(self, rhs: Self) -> Option { + let (a, b) = self.overflowing_sub(rhs); + if unlikely!(b) {None} else {Some(a)} + } + + /// Unchecked integer subtraction. Computes `self - rhs`, assuming overflow + /// cannot occur. This results in undefined behavior when + #[doc = concat!("`self - rhs > ", stringify!($SelfT), "::MAX` or `self - rhs < ", stringify!($SelfT), "::MIN`.")] + #[unstable( + feature = "unchecked_math", + reason = "niche optimization path", + issue = "none", + )] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub unsafe fn unchecked_sub(self, rhs: Self) -> Self { + // SAFETY: the caller must uphold the safety contract for + // `unchecked_sub`. + unsafe { intrinsics::unchecked_sub(self, rhs) } } - doc_comment! { - concat!("Checked Euclidean division. Computes `self.div_euclid(rhs)`, returning `None` -if `rhs == 0`. - -# Examples - -Basic usage: - -``` -assert_eq!(128", stringify!($SelfT), ".checked_div_euclid(2), Some(64)); -assert_eq!(1", stringify!($SelfT), ".checked_div_euclid(0), None); -```"), - #[stable(feature = "euclidean_division", since = "1.38.0")] - #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn checked_div_euclid(self, rhs: Self) -> Option { - if unlikely!(rhs == 0) { - None - } else { - Some(self.div_euclid(rhs)) - } - } + /// Checked integer multiplication. Computes `self * rhs`, returning + /// `None` if overflow occurred. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".checked_mul(1), Some(5));")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.checked_mul(2), None);")] + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_mul(self, rhs: Self) -> Option { + let (a, b) = self.overflowing_mul(rhs); + if unlikely!(b) {None} else {Some(a)} + } + + /// Unchecked integer multiplication. Computes `self * rhs`, assuming overflow + /// cannot occur. This results in undefined behavior when + #[doc = concat!("`self * rhs > ", stringify!($SelfT), "::MAX` or `self * rhs < ", stringify!($SelfT), "::MIN`.")] + #[unstable( + feature = "unchecked_math", + reason = "niche optimization path", + issue = "none", + )] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub unsafe fn unchecked_mul(self, rhs: Self) -> Self { + // SAFETY: the caller must uphold the safety contract for + // `unchecked_mul`. + unsafe { intrinsics::unchecked_mul(self, rhs) } } - - doc_comment! { - concat!("Checked integer remainder. Computes `self % rhs`, returning `None` -if `rhs == 0`. - -# Examples - -Basic usage: - -``` -", $Feature, "assert_eq!(5", stringify!($SelfT), ".checked_rem(2), Some(1)); -assert_eq!(5", stringify!($SelfT), ".checked_rem(0), None);", $EndFeature, " -```"), - #[stable(feature = "wrapping", since = "1.7.0")] - #[rustc_const_unstable(feature = "const_checked_int_methods", issue = "53718")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn checked_rem(self, rhs: Self) -> Option { - if unlikely!(rhs == 0) { - None - } else { - // SAFETY: div by zero has been checked above and unsigned types have no other - // failure modes for division - Some(unsafe { intrinsics::unchecked_rem(self, rhs) }) - } + /// Checked integer division. Computes `self / rhs`, returning `None` + /// if `rhs == 0`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(128", stringify!($SelfT), ".checked_div(2), Some(64));")] + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".checked_div(0), None);")] + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_checked_int_methods", issue = "53718")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_div(self, rhs: Self) -> Option { + if unlikely!(rhs == 0) { + None + } else { + // SAFETY: div by zero has been checked above and unsigned types have no other + // failure modes for division + Some(unsafe { intrinsics::unchecked_div(self, rhs) }) } } - doc_comment! { - concat!("Checked Euclidean modulo. Computes `self.rem_euclid(rhs)`, returning `None` -if `rhs == 0`. - -# Examples - -Basic usage: - -``` -assert_eq!(5", stringify!($SelfT), ".checked_rem_euclid(2), Some(1)); -assert_eq!(5", stringify!($SelfT), ".checked_rem_euclid(0), None); -```"), - #[stable(feature = "euclidean_division", since = "1.38.0")] - #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn checked_rem_euclid(self, rhs: Self) -> Option { - if unlikely!(rhs == 0) { - None - } else { - Some(self.rem_euclid(rhs)) - } + /// Checked Euclidean division. Computes `self.div_euclid(rhs)`, returning `None` + /// if `rhs == 0`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(128", stringify!($SelfT), ".checked_div_euclid(2), Some(64));")] + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".checked_div_euclid(0), None);")] + /// ``` + #[stable(feature = "euclidean_division", since = "1.38.0")] + #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_div_euclid(self, rhs: Self) -> Option { + if unlikely!(rhs == 0) { + None + } else { + Some(self.div_euclid(rhs)) } } - doc_comment! { - concat!("Checked negation. Computes `-self`, returning `None` unless `self == -0`. - -Note that negating any positive integer will overflow. - -# Examples -Basic usage: - -``` -", $Feature, "assert_eq!(0", stringify!($SelfT), ".checked_neg(), Some(0)); -assert_eq!(1", stringify!($SelfT), ".checked_neg(), None);", $EndFeature, " -```"), - #[stable(feature = "wrapping", since = "1.7.0")] - #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")] - #[inline] - pub const fn checked_neg(self) -> Option { - let (a, b) = self.overflowing_neg(); - if unlikely!(b) {None} else {Some(a)} + /// Checked integer remainder. Computes `self % rhs`, returning `None` + /// if `rhs == 0`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".checked_rem(2), Some(1));")] + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".checked_rem(0), None);")] + /// ``` + #[stable(feature = "wrapping", since = "1.7.0")] + #[rustc_const_unstable(feature = "const_checked_int_methods", issue = "53718")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_rem(self, rhs: Self) -> Option { + if unlikely!(rhs == 0) { + None + } else { + // SAFETY: div by zero has been checked above and unsigned types have no other + // failure modes for division + Some(unsafe { intrinsics::unchecked_rem(self, rhs) }) } } - doc_comment! { - concat!("Checked shift left. Computes `self << rhs`, returning `None` -if `rhs` is larger than or equal to the number of bits in `self`. - -# Examples - -Basic usage: - -``` -", $Feature, "assert_eq!(0x1", stringify!($SelfT), ".checked_shl(4), Some(0x10)); -assert_eq!(0x10", stringify!($SelfT), ".checked_shl(129), None);", $EndFeature, " -```"), - #[stable(feature = "wrapping", since = "1.7.0")] - #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn checked_shl(self, rhs: u32) -> Option { - let (a, b) = self.overflowing_shl(rhs); - if unlikely!(b) {None} else {Some(a)} + /// Checked Euclidean modulo. Computes `self.rem_euclid(rhs)`, returning `None` + /// if `rhs == 0`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".checked_rem_euclid(2), Some(1));")] + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".checked_rem_euclid(0), None);")] + /// ``` + #[stable(feature = "euclidean_division", since = "1.38.0")] + #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_rem_euclid(self, rhs: Self) -> Option { + if unlikely!(rhs == 0) { + None + } else { + Some(self.rem_euclid(rhs)) } } - doc_comment! { - concat!("Checked shift right. Computes `self >> rhs`, returning `None` -if `rhs` is larger than or equal to the number of bits in `self`. - -# Examples - -Basic usage: - -``` -", $Feature, "assert_eq!(0x10", stringify!($SelfT), ".checked_shr(4), Some(0x1)); -assert_eq!(0x10", stringify!($SelfT), ".checked_shr(129), None);", $EndFeature, " -```"), - #[stable(feature = "wrapping", since = "1.7.0")] - #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn checked_shr(self, rhs: u32) -> Option { - let (a, b) = self.overflowing_shr(rhs); - if unlikely!(b) {None} else {Some(a)} - } + /// Checked negation. Computes `-self`, returning `None` unless `self == + /// 0`. + /// + /// Note that negating any positive integer will overflow. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".checked_neg(), Some(0));")] + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".checked_neg(), None);")] + /// ``` + #[stable(feature = "wrapping", since = "1.7.0")] + #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")] + #[inline] + pub const fn checked_neg(self) -> Option { + let (a, b) = self.overflowing_neg(); + if unlikely!(b) {None} else {Some(a)} } - doc_comment! { - concat!("Checked exponentiation. Computes `self.pow(exp)`, returning `None` if -overflow occurred. + /// Checked shift left. Computes `self << rhs`, returning `None` + /// if `rhs` is larger than or equal to the number of bits in `self`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".checked_shl(4), Some(0x10));")] + #[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".checked_shl(129), None);")] + /// ``` + #[stable(feature = "wrapping", since = "1.7.0")] + #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_shl(self, rhs: u32) -> Option { + let (a, b) = self.overflowing_shl(rhs); + if unlikely!(b) {None} else {Some(a)} + } -# Examples + /// Checked shift right. Computes `self >> rhs`, returning `None` + /// if `rhs` is larger than or equal to the number of bits in `self`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".checked_shr(4), Some(0x1));")] + #[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".checked_shr(129), None);")] + /// ``` + #[stable(feature = "wrapping", since = "1.7.0")] + #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_shr(self, rhs: u32) -> Option { + let (a, b) = self.overflowing_shr(rhs); + if unlikely!(b) {None} else {Some(a)} + } -Basic usage: + /// Checked exponentiation. Computes `self.pow(exp)`, returning `None` if + /// overflow occurred. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".checked_pow(5), Some(32));")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.checked_pow(2), None);")] + /// ``` + #[stable(feature = "no_panic_pow", since = "1.34.0")] + #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_pow(self, mut exp: u32) -> Option { + if exp == 0 { + return Some(1); + } + let mut base = self; + let mut acc: Self = 1; -``` -", $Feature, "assert_eq!(2", stringify!($SelfT), ".checked_pow(5), Some(32)); -assert_eq!(", stringify!($SelfT), "::MAX.checked_pow(2), None);", $EndFeature, " -```"), - #[stable(feature = "no_panic_pow", since = "1.34.0")] - #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn checked_pow(self, mut exp: u32) -> Option { - if exp == 0 { - return Some(1); - } - let mut base = self; - let mut acc: Self = 1; - - while exp > 1 { - if (exp & 1) == 1 { - acc = try_opt!(acc.checked_mul(base)); - } - exp /= 2; - base = try_opt!(base.checked_mul(base)); + while exp > 1 { + if (exp & 1) == 1 { + acc = try_opt!(acc.checked_mul(base)); } - - // since exp!=0, finally the exp must be 1. - // Deal with the final bit of the exponent separately, since - // squaring the base afterwards is not necessary and may cause a - // needless overflow. - - Some(try_opt!(acc.checked_mul(base))) + exp /= 2; + base = try_opt!(base.checked_mul(base)); } - } - - doc_comment! { - concat!("Saturating integer addition. Computes `self + rhs`, saturating at -the numeric bounds instead of overflowing. - -# Examples -Basic usage: - -``` -", $Feature, "assert_eq!(100", stringify!($SelfT), ".saturating_add(1), 101); -assert_eq!(", stringify!($SelfT), "::MAX.saturating_add(127), ", stringify!($SelfT), "::MAX);", -$EndFeature, " -```"), + // since exp!=0, finally the exp must be 1. + // Deal with the final bit of the exponent separately, since + // squaring the base afterwards is not necessary and may cause a + // needless overflow. - #[stable(feature = "rust1", since = "1.0.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[rustc_const_stable(feature = "const_saturating_int_methods", since = "1.47.0")] - #[inline] - pub const fn saturating_add(self, rhs: Self) -> Self { - intrinsics::saturating_add(self, rhs) - } + Some(try_opt!(acc.checked_mul(base))) } - doc_comment! { - concat!("Saturating integer subtraction. Computes `self - rhs`, saturating -at the numeric bounds instead of overflowing. - -# Examples - -Basic usage: - -``` -", $Feature, "assert_eq!(100", stringify!($SelfT), ".saturating_sub(27), 73); -assert_eq!(13", stringify!($SelfT), ".saturating_sub(127), 0);", $EndFeature, " -```"), - #[stable(feature = "rust1", since = "1.0.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[rustc_const_stable(feature = "const_saturating_int_methods", since = "1.47.0")] - #[inline] - pub const fn saturating_sub(self, rhs: Self) -> Self { - intrinsics::saturating_sub(self, rhs) - } + /// Saturating integer addition. Computes `self + rhs`, saturating at + /// the numeric bounds instead of overflowing. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".saturating_add(1), 101);")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.saturating_add(127), ", stringify!($SelfT), "::MAX);")] + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[rustc_const_stable(feature = "const_saturating_int_methods", since = "1.47.0")] + #[inline] + pub const fn saturating_add(self, rhs: Self) -> Self { + intrinsics::saturating_add(self, rhs) } - doc_comment! { - concat!("Saturating integer multiplication. Computes `self * rhs`, -saturating at the numeric bounds instead of overflowing. - -# Examples - -Basic usage: - -``` -", $Feature, " -assert_eq!(2", stringify!($SelfT), ".saturating_mul(10), 20); -assert_eq!((", stringify!($SelfT), "::MAX).saturating_mul(10), ", stringify!($SelfT), -"::MAX);", $EndFeature, " -```"), - #[stable(feature = "wrapping", since = "1.7.0")] - #[rustc_const_stable(feature = "const_saturating_int_methods", since = "1.47.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn saturating_mul(self, rhs: Self) -> Self { - match self.checked_mul(rhs) { - Some(x) => x, - None => Self::MAX, - } - } + /// Saturating integer subtraction. Computes `self - rhs`, saturating + /// at the numeric bounds instead of overflowing. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".saturating_sub(27), 73);")] + #[doc = concat!("assert_eq!(13", stringify!($SelfT), ".saturating_sub(127), 0);")] + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[rustc_const_stable(feature = "const_saturating_int_methods", since = "1.47.0")] + #[inline] + pub const fn saturating_sub(self, rhs: Self) -> Self { + intrinsics::saturating_sub(self, rhs) } - doc_comment! { - concat!("Saturating integer exponentiation. Computes `self.pow(exp)`, -saturating at the numeric bounds instead of overflowing. - -# Examples - -Basic usage: - -``` -", $Feature, " -assert_eq!(4", stringify!($SelfT), ".saturating_pow(3), 64); -assert_eq!(", stringify!($SelfT), "::MAX.saturating_pow(2), ", stringify!($SelfT), "::MAX);", -$EndFeature, " -```"), - #[stable(feature = "no_panic_pow", since = "1.34.0")] - #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn saturating_pow(self, exp: u32) -> Self { - match self.checked_pow(exp) { - Some(x) => x, - None => Self::MAX, - } + /// Saturating integer multiplication. Computes `self * rhs`, + /// saturating at the numeric bounds instead of overflowing. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".saturating_mul(10), 20);")] + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX).saturating_mul(10), ", stringify!($SelfT),"::MAX);")] + /// ``` + #[stable(feature = "wrapping", since = "1.7.0")] + #[rustc_const_stable(feature = "const_saturating_int_methods", since = "1.47.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn saturating_mul(self, rhs: Self) -> Self { + match self.checked_mul(rhs) { + Some(x) => x, + None => Self::MAX, } } - doc_comment! { - concat!("Wrapping (modular) addition. Computes `self + rhs`, -wrapping around at the boundary of the type. - -# Examples - -Basic usage: - -``` -", $Feature, "assert_eq!(200", stringify!($SelfT), ".wrapping_add(55), 255); -assert_eq!(200", stringify!($SelfT), ".wrapping_add(", stringify!($SelfT), "::MAX), 199);", -$EndFeature, " -```"), - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn wrapping_add(self, rhs: Self) -> Self { - intrinsics::wrapping_add(self, rhs) + /// Saturating integer exponentiation. Computes `self.pow(exp)`, + /// saturating at the numeric bounds instead of overflowing. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(4", stringify!($SelfT), ".saturating_pow(3), 64);")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.saturating_pow(2), ", stringify!($SelfT), "::MAX);")] + /// ``` + #[stable(feature = "no_panic_pow", since = "1.34.0")] + #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn saturating_pow(self, exp: u32) -> Self { + match self.checked_pow(exp) { + Some(x) => x, + None => Self::MAX, } } - doc_comment! { - concat!("Wrapping (modular) subtraction. Computes `self - rhs`, -wrapping around at the boundary of the type. - -# Examples - -Basic usage: + /// Wrapping (modular) addition. Computes `self + rhs`, + /// wrapping around at the boundary of the type. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(200", stringify!($SelfT), ".wrapping_add(55), 255);")] + #[doc = concat!("assert_eq!(200", stringify!($SelfT), ".wrapping_add(", stringify!($SelfT), "::MAX), 199);")] + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn wrapping_add(self, rhs: Self) -> Self { + intrinsics::wrapping_add(self, rhs) + } -``` -", $Feature, "assert_eq!(100", stringify!($SelfT), ".wrapping_sub(100), 0); -assert_eq!(100", stringify!($SelfT), ".wrapping_sub(", stringify!($SelfT), "::MAX), 101);", -$EndFeature, " -```"), - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn wrapping_sub(self, rhs: Self) -> Self { - intrinsics::wrapping_sub(self, rhs) - } + /// Wrapping (modular) subtraction. Computes `self - rhs`, + /// wrapping around at the boundary of the type. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".wrapping_sub(100), 0);")] + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".wrapping_sub(", stringify!($SelfT), "::MAX), 101);")] + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn wrapping_sub(self, rhs: Self) -> Self { + intrinsics::wrapping_sub(self, rhs) } /// Wrapping (modular) multiplication. Computes `self * @@ -936,120 +850,112 @@ pub const fn wrapping_sub(self, rhs: Self) -> Self { /// Which explains why `u8` is used here. /// /// ``` - /// assert_eq!(10u8.wrapping_mul(12), 120); - /// assert_eq!(25u8.wrapping_mul(12), 44); + /// assert_eq!(10u8.wrapping_mul(12), 120); + /// assert_eq!(25u8.wrapping_mul(12), 44); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn wrapping_mul(self, rhs: Self) -> Self { + intrinsics::wrapping_mul(self, rhs) + } + + /// Wrapping (modular) division. Computes `self / rhs`. + /// Wrapped division on unsigned types is just normal division. + /// There's no way wrapping could ever happen. + /// This function exists, so that all operations + /// are accounted for in the wrapping operations. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".wrapping_div(10), 10);")] + /// ``` + #[stable(feature = "num_wrapping", since = "1.2.0")] + #[rustc_const_unstable(feature = "const_wrapping_int_methods", issue = "53718")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn wrapping_div(self, rhs: Self) -> Self { + self / rhs + } + + /// Wrapping Euclidean division. Computes `self.div_euclid(rhs)`. + /// Wrapped division on unsigned types is just normal division. + /// There's no way wrapping could ever happen. + /// This function exists, so that all operations + /// are accounted for in the wrapping operations. + /// Since, for the positive integers, all common + /// definitions of division are equal, this + /// is exactly equal to `self.wrapping_div(rhs)`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".wrapping_div_euclid(10), 10);")] + /// ``` + #[stable(feature = "euclidean_division", since = "1.38.0")] + #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn wrapping_div_euclid(self, rhs: Self) -> Self { + self / rhs + } + + /// Wrapping (modular) remainder. Computes `self % rhs`. + /// Wrapped remainder calculation on unsigned types is + /// just the regular remainder calculation. + /// There's no way wrapping could ever happen. + /// This function exists, so that all operations + /// are accounted for in the wrapping operations. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".wrapping_rem(10), 0);")] + /// ``` + #[stable(feature = "num_wrapping", since = "1.2.0")] + #[rustc_const_unstable(feature = "const_wrapping_int_methods", issue = "53718")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn wrapping_rem(self, rhs: Self) -> Self { + self % rhs + } + + /// Wrapping Euclidean modulo. Computes `self.rem_euclid(rhs)`. + /// Wrapped modulo calculation on unsigned types is + /// just the regular remainder calculation. + /// There's no way wrapping could ever happen. + /// This function exists, so that all operations + /// are accounted for in the wrapping operations. + /// Since, for the positive integers, all common + /// definitions of division are equal, this + /// is exactly equal to `self.wrapping_rem(rhs)`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".wrapping_rem_euclid(10), 0);")] /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")] + #[stable(feature = "euclidean_division", since = "1.38.0")] + #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")] #[must_use = "this returns the result of the operation, \ - without modifying the original"] + without modifying the original"] #[inline] - pub const fn wrapping_mul(self, rhs: Self) -> Self { - intrinsics::wrapping_mul(self, rhs) - } - - doc_comment! { - concat!("Wrapping (modular) division. Computes `self / rhs`. -Wrapped division on unsigned types is just normal division. -There's no way wrapping could ever happen. -This function exists, so that all operations -are accounted for in the wrapping operations. - -# Examples - -Basic usage: - -``` -", $Feature, "assert_eq!(100", stringify!($SelfT), ".wrapping_div(10), 10);", $EndFeature, " -```"), - #[stable(feature = "num_wrapping", since = "1.2.0")] - #[rustc_const_unstable(feature = "const_wrapping_int_methods", issue = "53718")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn wrapping_div(self, rhs: Self) -> Self { - self / rhs - } - } - - doc_comment! { - concat!("Wrapping Euclidean division. Computes `self.div_euclid(rhs)`. -Wrapped division on unsigned types is just normal division. -There's no way wrapping could ever happen. -This function exists, so that all operations -are accounted for in the wrapping operations. -Since, for the positive integers, all common -definitions of division are equal, this -is exactly equal to `self.wrapping_div(rhs)`. - -# Examples - -Basic usage: - -``` -assert_eq!(100", stringify!($SelfT), ".wrapping_div_euclid(10), 10); -```"), - #[stable(feature = "euclidean_division", since = "1.38.0")] - #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn wrapping_div_euclid(self, rhs: Self) -> Self { - self / rhs - } - } - - doc_comment! { - concat!("Wrapping (modular) remainder. Computes `self % rhs`. -Wrapped remainder calculation on unsigned types is -just the regular remainder calculation. -There's no way wrapping could ever happen. -This function exists, so that all operations -are accounted for in the wrapping operations. - -# Examples - -Basic usage: - -``` -", $Feature, "assert_eq!(100", stringify!($SelfT), ".wrapping_rem(10), 0);", $EndFeature, " -```"), - #[stable(feature = "num_wrapping", since = "1.2.0")] - #[rustc_const_unstable(feature = "const_wrapping_int_methods", issue = "53718")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn wrapping_rem(self, rhs: Self) -> Self { - self % rhs - } - } - - doc_comment! { - concat!("Wrapping Euclidean modulo. Computes `self.rem_euclid(rhs)`. -Wrapped modulo calculation on unsigned types is -just the regular remainder calculation. -There's no way wrapping could ever happen. -This function exists, so that all operations -are accounted for in the wrapping operations. -Since, for the positive integers, all common -definitions of division are equal, this -is exactly equal to `self.wrapping_rem(rhs)`. - -# Examples - -Basic usage: - -``` -assert_eq!(100", stringify!($SelfT), ".wrapping_rem_euclid(10), 0); -```"), - #[stable(feature = "euclidean_division", since = "1.38.0")] - #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn wrapping_rem_euclid(self, rhs: Self) -> Self { - self % rhs - } + pub const fn wrapping_rem_euclid(self, rhs: Self) -> Self { + self % rhs } /// Wrapping (modular) negation. Computes `-self`, @@ -1080,167 +986,156 @@ pub const fn wrapping_neg(self) -> Self { self.overflowing_neg().0 } - doc_comment! { - concat!("Panic-free bitwise shift-left; yields `self << mask(rhs)`, -where `mask` removes any high-order bits of `rhs` that -would cause the shift to exceed the bitwidth of the type. - -Note that this is *not* the same as a rotate-left; the -RHS of a wrapping shift-left is restricted to the range -of the type, rather than the bits shifted out of the LHS -being returned to the other end. The primitive integer -types all implement a [`rotate_left`](#method.rotate_left) function, -which may be what you want instead. - -# Examples - -Basic usage: - -``` -", $Feature, "assert_eq!(1", stringify!($SelfT), ".wrapping_shl(7), 128); -assert_eq!(1", stringify!($SelfT), ".wrapping_shl(128), 1);", $EndFeature, " -```"), - #[stable(feature = "num_wrapping", since = "1.2.0")] - #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn wrapping_shl(self, rhs: u32) -> Self { - // SAFETY: the masking by the bitsize of the type ensures that we do not shift - // out of bounds - unsafe { - intrinsics::unchecked_shl(self, (rhs & ($BITS - 1)) as $SelfT) - } + /// Panic-free bitwise shift-left; yields `self << mask(rhs)`, + /// where `mask` removes any high-order bits of `rhs` that + /// would cause the shift to exceed the bitwidth of the type. + /// + /// Note that this is *not* the same as a rotate-left; the + /// RHS of a wrapping shift-left is restricted to the range + /// of the type, rather than the bits shifted out of the LHS + /// being returned to the other end. The primitive integer + /// types all implement a [`rotate_left`](#method.rotate_left) function, + /// which may be what you want instead. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".wrapping_shl(7), 128);")] + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".wrapping_shl(128), 1);")] + /// ``` + #[stable(feature = "num_wrapping", since = "1.2.0")] + #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn wrapping_shl(self, rhs: u32) -> Self { + // SAFETY: the masking by the bitsize of the type ensures that we do not shift + // out of bounds + unsafe { + intrinsics::unchecked_shl(self, (rhs & ($BITS - 1)) as $SelfT) } } - doc_comment! { - concat!("Panic-free bitwise shift-right; yields `self >> mask(rhs)`, -where `mask` removes any high-order bits of `rhs` that -would cause the shift to exceed the bitwidth of the type. - -Note that this is *not* the same as a rotate-right; the -RHS of a wrapping shift-right is restricted to the range -of the type, rather than the bits shifted out of the LHS -being returned to the other end. The primitive integer -types all implement a [`rotate_right`](#method.rotate_right) function, -which may be what you want instead. - -# Examples - -Basic usage: - -``` -", $Feature, "assert_eq!(128", stringify!($SelfT), ".wrapping_shr(7), 1); -assert_eq!(128", stringify!($SelfT), ".wrapping_shr(128), 128);", $EndFeature, " -```"), - #[stable(feature = "num_wrapping", since = "1.2.0")] - #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn wrapping_shr(self, rhs: u32) -> Self { - // SAFETY: the masking by the bitsize of the type ensures that we do not shift - // out of bounds - unsafe { - intrinsics::unchecked_shr(self, (rhs & ($BITS - 1)) as $SelfT) - } + /// Panic-free bitwise shift-right; yields `self >> mask(rhs)`, + /// where `mask` removes any high-order bits of `rhs` that + /// would cause the shift to exceed the bitwidth of the type. + /// + /// Note that this is *not* the same as a rotate-right; the + /// RHS of a wrapping shift-right is restricted to the range + /// of the type, rather than the bits shifted out of the LHS + /// being returned to the other end. The primitive integer + /// types all implement a [`rotate_right`](#method.rotate_right) function, + /// which may be what you want instead. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(128", stringify!($SelfT), ".wrapping_shr(7), 1);")] + #[doc = concat!("assert_eq!(128", stringify!($SelfT), ".wrapping_shr(128), 128);")] + /// ``` + #[stable(feature = "num_wrapping", since = "1.2.0")] + #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn wrapping_shr(self, rhs: u32) -> Self { + // SAFETY: the masking by the bitsize of the type ensures that we do not shift + // out of bounds + unsafe { + intrinsics::unchecked_shr(self, (rhs & ($BITS - 1)) as $SelfT) } } - doc_comment! { - concat!("Wrapping (modular) exponentiation. Computes `self.pow(exp)`, -wrapping around at the boundary of the type. - -# Examples - -Basic usage: + /// Wrapping (modular) exponentiation. Computes `self.pow(exp)`, + /// wrapping around at the boundary of the type. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(3", stringify!($SelfT), ".wrapping_pow(5), 243);")] + /// assert_eq!(3u8.wrapping_pow(6), 217); + /// ``` + #[stable(feature = "no_panic_pow", since = "1.34.0")] + #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn wrapping_pow(self, mut exp: u32) -> Self { + if exp == 0 { + return 1; + } + let mut base = self; + let mut acc: Self = 1; -``` -", $Feature, "assert_eq!(3", stringify!($SelfT), ".wrapping_pow(5), 243); -assert_eq!(3u8.wrapping_pow(6), 217);", $EndFeature, " -```"), - #[stable(feature = "no_panic_pow", since = "1.34.0")] - #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn wrapping_pow(self, mut exp: u32) -> Self { - if exp == 0 { - return 1; - } - let mut base = self; - let mut acc: Self = 1; - - while exp > 1 { - if (exp & 1) == 1 { - acc = acc.wrapping_mul(base); - } - exp /= 2; - base = base.wrapping_mul(base); + while exp > 1 { + if (exp & 1) == 1 { + acc = acc.wrapping_mul(base); } - - // since exp!=0, finally the exp must be 1. - // Deal with the final bit of the exponent separately, since - // squaring the base afterwards is not necessary and may cause a - // needless overflow. - acc.wrapping_mul(base) + exp /= 2; + base = base.wrapping_mul(base); } - } - doc_comment! { - concat!("Calculates `self` + `rhs` - -Returns a tuple of the addition along with a boolean indicating -whether an arithmetic overflow would occur. If an overflow would -have occurred then the wrapped value is returned. - -# Examples - -Basic usage - -``` -", $Feature, " -assert_eq!(5", stringify!($SelfT), ".overflowing_add(2), (7, false)); -assert_eq!(", stringify!($SelfT), "::MAX.overflowing_add(1), (0, true));", $EndFeature, " -```"), - #[stable(feature = "wrapping", since = "1.7.0")] - #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn overflowing_add(self, rhs: Self) -> (Self, bool) { - let (a, b) = intrinsics::add_with_overflow(self as $ActualT, rhs as $ActualT); - (a as Self, b) - } + // since exp!=0, finally the exp must be 1. + // Deal with the final bit of the exponent separately, since + // squaring the base afterwards is not necessary and may cause a + // needless overflow. + acc.wrapping_mul(base) } - doc_comment! { - concat!("Calculates `self` - `rhs` - -Returns a tuple of the subtraction along with a boolean indicating -whether an arithmetic overflow would occur. If an overflow would -have occurred then the wrapped value is returned. - -# Examples - -Basic usage + /// Calculates `self` + `rhs` + /// + /// Returns a tuple of the addition along with a boolean indicating + /// whether an arithmetic overflow would occur. If an overflow would + /// have occurred then the wrapped value is returned. + /// + /// # Examples + /// + /// Basic usage + /// + /// ``` + /// + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_add(2), (7, false));")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.overflowing_add(1), (0, true));")] + /// ``` + #[stable(feature = "wrapping", since = "1.7.0")] + #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn overflowing_add(self, rhs: Self) -> (Self, bool) { + let (a, b) = intrinsics::add_with_overflow(self as $ActualT, rhs as $ActualT); + (a as Self, b) + } -``` -", $Feature, " -assert_eq!(5", stringify!($SelfT), ".overflowing_sub(2), (3, false)); -assert_eq!(0", stringify!($SelfT), ".overflowing_sub(1), (", stringify!($SelfT), "::MAX, true));", -$EndFeature, " -```"), - #[stable(feature = "wrapping", since = "1.7.0")] - #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn overflowing_sub(self, rhs: Self) -> (Self, bool) { - let (a, b) = intrinsics::sub_with_overflow(self as $ActualT, rhs as $ActualT); - (a as Self, b) - } + /// Calculates `self` - `rhs` + /// + /// Returns a tuple of the subtraction along with a boolean indicating + /// whether an arithmetic overflow would occur. If an overflow would + /// have occurred then the wrapped value is returned. + /// + /// # Examples + /// + /// Basic usage + /// + /// ``` + /// + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_sub(2), (3, false));")] + #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".overflowing_sub(1), (", stringify!($SelfT), "::MAX, true));")] + /// ``` + #[stable(feature = "wrapping", since = "1.7.0")] + #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn overflowing_sub(self, rhs: Self) -> (Self, bool) { + let (a, b) = intrinsics::sub_with_overflow(self as $ActualT, rhs as $ActualT); + (a as Self, b) } /// Calculates the multiplication of `self` and `rhs`. @@ -1270,269 +1165,251 @@ pub const fn overflowing_mul(self, rhs: Self) -> (Self, bool) { (a as Self, b) } - doc_comment! { - concat!("Calculates the divisor when `self` is divided by `rhs`. - -Returns a tuple of the divisor along with a boolean indicating -whether an arithmetic overflow would occur. Note that for unsigned -integers overflow never occurs, so the second value is always -`false`. - -# Panics - -This function will panic if `rhs` is 0. - -# Examples - -Basic usage - -``` -", $Feature, "assert_eq!(5", stringify!($SelfT), ".overflowing_div(2), (2, false));", $EndFeature, " -```"), - #[inline] - #[stable(feature = "wrapping", since = "1.7.0")] - #[rustc_const_unstable(feature = "const_overflowing_int_methods", issue = "53718")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - pub const fn overflowing_div(self, rhs: Self) -> (Self, bool) { - (self / rhs, false) - } - } - - doc_comment! { - concat!("Calculates the quotient of Euclidean division `self.div_euclid(rhs)`. - -Returns a tuple of the divisor along with a boolean indicating -whether an arithmetic overflow would occur. Note that for unsigned -integers overflow never occurs, so the second value is always -`false`. -Since, for the positive integers, all common -definitions of division are equal, this -is exactly equal to `self.overflowing_div(rhs)`. - -# Panics - -This function will panic if `rhs` is 0. - -# Examples - -Basic usage - -``` -assert_eq!(5", stringify!($SelfT), ".overflowing_div_euclid(2), (2, false)); -```"), - #[inline] - #[stable(feature = "euclidean_division", since = "1.38.0")] - #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - pub const fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) { - (self / rhs, false) - } + /// Calculates the divisor when `self` is divided by `rhs`. + /// + /// Returns a tuple of the divisor along with a boolean indicating + /// whether an arithmetic overflow would occur. Note that for unsigned + /// integers overflow never occurs, so the second value is always + /// `false`. + /// + /// # Panics + /// + /// This function will panic if `rhs` is 0. + /// + /// # Examples + /// + /// Basic usage + /// + /// ``` + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_div(2), (2, false));")] + /// ``` + #[inline] + #[stable(feature = "wrapping", since = "1.7.0")] + #[rustc_const_unstable(feature = "const_overflowing_int_methods", issue = "53718")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + pub const fn overflowing_div(self, rhs: Self) -> (Self, bool) { + (self / rhs, false) } - doc_comment! { - concat!("Calculates the remainder when `self` is divided by `rhs`. - -Returns a tuple of the remainder after dividing along with a boolean -indicating whether an arithmetic overflow would occur. Note that for -unsigned integers overflow never occurs, so the second value is -always `false`. - -# Panics - -This function will panic if `rhs` is 0. - -# Examples - -Basic usage - -``` -", $Feature, "assert_eq!(5", stringify!($SelfT), ".overflowing_rem(2), (1, false));", $EndFeature, " -```"), - #[inline] - #[stable(feature = "wrapping", since = "1.7.0")] - #[rustc_const_unstable(feature = "const_overflowing_int_methods", issue = "53718")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - pub const fn overflowing_rem(self, rhs: Self) -> (Self, bool) { - (self % rhs, false) - } + /// Calculates the quotient of Euclidean division `self.div_euclid(rhs)`. + /// + /// Returns a tuple of the divisor along with a boolean indicating + /// whether an arithmetic overflow would occur. Note that for unsigned + /// integers overflow never occurs, so the second value is always + /// `false`. + /// Since, for the positive integers, all common + /// definitions of division are equal, this + /// is exactly equal to `self.overflowing_div(rhs)`. + /// + /// # Panics + /// + /// This function will panic if `rhs` is 0. + /// + /// # Examples + /// + /// Basic usage + /// + /// ``` + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_div_euclid(2), (2, false));")] + /// ``` + #[inline] + #[stable(feature = "euclidean_division", since = "1.38.0")] + #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + pub const fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) { + (self / rhs, false) } - doc_comment! { - concat!("Calculates the remainder `self.rem_euclid(rhs)` as if by Euclidean division. - -Returns a tuple of the modulo after dividing along with a boolean -indicating whether an arithmetic overflow would occur. Note that for -unsigned integers overflow never occurs, so the second value is -always `false`. -Since, for the positive integers, all common -definitions of division are equal, this operation -is exactly equal to `self.overflowing_rem(rhs)`. - -# Panics - -This function will panic if `rhs` is 0. - -# Examples - -Basic usage - -``` -assert_eq!(5", stringify!($SelfT), ".overflowing_rem_euclid(2), (1, false)); -```"), - #[inline] - #[stable(feature = "euclidean_division", since = "1.38.0")] - #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - pub const fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) { - (self % rhs, false) - } + /// Calculates the remainder when `self` is divided by `rhs`. + /// + /// Returns a tuple of the remainder after dividing along with a boolean + /// indicating whether an arithmetic overflow would occur. Note that for + /// unsigned integers overflow never occurs, so the second value is + /// always `false`. + /// + /// # Panics + /// + /// This function will panic if `rhs` is 0. + /// + /// # Examples + /// + /// Basic usage + /// + /// ``` + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_rem(2), (1, false));")] + /// ``` + #[inline] + #[stable(feature = "wrapping", since = "1.7.0")] + #[rustc_const_unstable(feature = "const_overflowing_int_methods", issue = "53718")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + pub const fn overflowing_rem(self, rhs: Self) -> (Self, bool) { + (self % rhs, false) } - doc_comment! { - concat!("Negates self in an overflowing fashion. - -Returns `!self + 1` using wrapping operations to return the value -that represents the negation of this unsigned value. Note that for -positive unsigned values overflow always occurs, but negating 0 does -not overflow. - -# Examples - -Basic usage - -``` -", $Feature, "assert_eq!(0", stringify!($SelfT), ".overflowing_neg(), (0, false)); -assert_eq!(2", stringify!($SelfT), ".overflowing_neg(), (-2i32 as ", stringify!($SelfT), -", true));", $EndFeature, " -```"), - #[inline] - #[stable(feature = "wrapping", since = "1.7.0")] - #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")] - pub const fn overflowing_neg(self) -> (Self, bool) { - ((!self).wrapping_add(1), self != 0) - } + /// Calculates the remainder `self.rem_euclid(rhs)` as if by Euclidean division. + /// + /// Returns a tuple of the modulo after dividing along with a boolean + /// indicating whether an arithmetic overflow would occur. Note that for + /// unsigned integers overflow never occurs, so the second value is + /// always `false`. + /// Since, for the positive integers, all common + /// definitions of division are equal, this operation + /// is exactly equal to `self.overflowing_rem(rhs)`. + /// + /// # Panics + /// + /// This function will panic if `rhs` is 0. + /// + /// # Examples + /// + /// Basic usage + /// + /// ``` + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_rem_euclid(2), (1, false));")] + /// ``` + #[inline] + #[stable(feature = "euclidean_division", since = "1.38.0")] + #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + pub const fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) { + (self % rhs, false) } - doc_comment! { - concat!("Shifts self left by `rhs` bits. - -Returns a tuple of the shifted version of self along with a boolean -indicating whether the shift value was larger than or equal to the -number of bits. If the shift value is too large, then value is -masked (N-1) where N is the number of bits, and this value is then -used to perform the shift. - -# Examples - -Basic usage - -``` -", $Feature, "assert_eq!(0x1", stringify!($SelfT), ".overflowing_shl(4), (0x10, false)); -assert_eq!(0x1", stringify!($SelfT), ".overflowing_shl(132), (0x10, true));", $EndFeature, " -```"), - #[stable(feature = "wrapping", since = "1.7.0")] - #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn overflowing_shl(self, rhs: u32) -> (Self, bool) { - (self.wrapping_shl(rhs), (rhs > ($BITS - 1))) - } + /// Negates self in an overflowing fashion. + /// + /// Returns `!self + 1` using wrapping operations to return the value + /// that represents the negation of this unsigned value. Note that for + /// positive unsigned values overflow always occurs, but negating 0 does + /// not overflow. + /// + /// # Examples + /// + /// Basic usage + /// + /// ``` + #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".overflowing_neg(), (0, false));")] + #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".overflowing_neg(), (-2i32 as ", stringify!($SelfT), ", true));")] + /// ``` + #[inline] + #[stable(feature = "wrapping", since = "1.7.0")] + #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")] + pub const fn overflowing_neg(self) -> (Self, bool) { + ((!self).wrapping_add(1), self != 0) } - doc_comment! { - concat!("Shifts self right by `rhs` bits. - -Returns a tuple of the shifted version of self along with a boolean -indicating whether the shift value was larger than or equal to the -number of bits. If the shift value is too large, then value is -masked (N-1) where N is the number of bits, and this value is then -used to perform the shift. - -# Examples - -Basic usage - -``` -", $Feature, "assert_eq!(0x10", stringify!($SelfT), ".overflowing_shr(4), (0x1, false)); -assert_eq!(0x10", stringify!($SelfT), ".overflowing_shr(132), (0x1, true));", $EndFeature, " -```"), - #[stable(feature = "wrapping", since = "1.7.0")] - #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn overflowing_shr(self, rhs: u32) -> (Self, bool) { - (self.wrapping_shr(rhs), (rhs > ($BITS - 1))) - } + /// Shifts self left by `rhs` bits. + /// + /// Returns a tuple of the shifted version of self along with a boolean + /// indicating whether the shift value was larger than or equal to the + /// number of bits. If the shift value is too large, then value is + /// masked (N-1) where N is the number of bits, and this value is then + /// used to perform the shift. + /// + /// # Examples + /// + /// Basic usage + /// + /// ``` + #[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".overflowing_shl(4), (0x10, false));")] + #[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".overflowing_shl(132), (0x10, true));")] + /// ``` + #[stable(feature = "wrapping", since = "1.7.0")] + #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn overflowing_shl(self, rhs: u32) -> (Self, bool) { + (self.wrapping_shl(rhs), (rhs > ($BITS - 1))) } - doc_comment! { - concat!("Raises self to the power of `exp`, using exponentiation by squaring. - -Returns a tuple of the exponentiation along with a bool indicating -whether an overflow happened. - -# Examples + /// Shifts self right by `rhs` bits. + /// + /// Returns a tuple of the shifted version of self along with a boolean + /// indicating whether the shift value was larger than or equal to the + /// number of bits. If the shift value is too large, then value is + /// masked (N-1) where N is the number of bits, and this value is then + /// used to perform the shift. + /// + /// # Examples + /// + /// Basic usage + /// + /// ``` + #[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".overflowing_shr(4), (0x1, false));")] + #[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".overflowing_shr(132), (0x1, true));")] + /// ``` + #[stable(feature = "wrapping", since = "1.7.0")] + #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn overflowing_shr(self, rhs: u32) -> (Self, bool) { + (self.wrapping_shr(rhs), (rhs > ($BITS - 1))) + } -Basic usage: + /// Raises self to the power of `exp`, using exponentiation by squaring. + /// + /// Returns a tuple of the exponentiation along with a bool indicating + /// whether an overflow happened. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(3", stringify!($SelfT), ".overflowing_pow(5), (243, false));")] + /// assert_eq!(3u8.overflowing_pow(6), (217, true)); + /// ``` + #[stable(feature = "no_panic_pow", since = "1.34.0")] + #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn overflowing_pow(self, mut exp: u32) -> (Self, bool) { + if exp == 0{ + return (1,false); + } + let mut base = self; + let mut acc: Self = 1; + let mut overflown = false; + // Scratch space for storing results of overflowing_mul. + let mut r; -``` -", $Feature, "assert_eq!(3", stringify!($SelfT), ".overflowing_pow(5), (243, false)); -assert_eq!(3u8.overflowing_pow(6), (217, true));", $EndFeature, " -```"), - #[stable(feature = "no_panic_pow", since = "1.34.0")] - #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn overflowing_pow(self, mut exp: u32) -> (Self, bool) { - if exp == 0{ - return (1,false); - } - let mut base = self; - let mut acc: Self = 1; - let mut overflown = false; - // Scratch space for storing results of overflowing_mul. - let mut r; - - while exp > 1 { - if (exp & 1) == 1 { - r = acc.overflowing_mul(base); - acc = r.0; - overflown |= r.1; - } - exp /= 2; - r = base.overflowing_mul(base); - base = r.0; + while exp > 1 { + if (exp & 1) == 1 { + r = acc.overflowing_mul(base); + acc = r.0; overflown |= r.1; } - - // since exp!=0, finally the exp must be 1. - // Deal with the final bit of the exponent separately, since - // squaring the base afterwards is not necessary and may cause a - // needless overflow. - r = acc.overflowing_mul(base); - r.1 |= overflown; - - r + exp /= 2; + r = base.overflowing_mul(base); + base = r.0; + overflown |= r.1; } - } - - doc_comment! { - concat!("Raises self to the power of `exp`, using exponentiation by squaring. -# Examples + // since exp!=0, finally the exp must be 1. + // Deal with the final bit of the exponent separately, since + // squaring the base afterwards is not necessary and may cause a + // needless overflow. + r = acc.overflowing_mul(base); + r.1 |= overflown; -Basic usage: + r + } -``` -", $Feature, "assert_eq!(2", stringify!($SelfT), ".pow(5), 32);", $EndFeature, " -```"), + /// Raises self to the power of `exp`, using exponentiation by squaring. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".pow(5), 32);")] + /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] #[must_use = "this returns the result of the operation, \ @@ -1560,84 +1437,77 @@ pub const fn pow(self, mut exp: u32) -> Self { // needless overflow. acc * base } - } - - doc_comment! { - concat!("Performs Euclidean division. - -Since, for the positive integers, all common -definitions of division are equal, this -is exactly equal to `self / rhs`. - -# Panics -This function will panic if `rhs` is 0. - -# Examples - -Basic usage: - -``` -assert_eq!(7", stringify!($SelfT), ".div_euclid(4), 1); // or any other integer type -```"), - #[stable(feature = "euclidean_division", since = "1.38.0")] - #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - #[rustc_inherit_overflow_checks] - pub const fn div_euclid(self, rhs: Self) -> Self { - self / rhs - } + /// Performs Euclidean division. + /// + /// Since, for the positive integers, all common + /// definitions of division are equal, this + /// is exactly equal to `self / rhs`. + /// + /// # Panics + /// + /// This function will panic if `rhs` is 0. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(7", stringify!($SelfT), ".div_euclid(4), 1); // or any other integer type")] + /// ``` + #[stable(feature = "euclidean_division", since = "1.38.0")] + #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[rustc_inherit_overflow_checks] + pub const fn div_euclid(self, rhs: Self) -> Self { + self / rhs } - doc_comment! { - concat!("Calculates the least remainder of `self (mod rhs)`. - -Since, for the positive integers, all common -definitions of division are equal, this -is exactly equal to `self % rhs`. - -# Panics - -This function will panic if `rhs` is 0. - -# Examples - -Basic usage: - -``` -assert_eq!(7", stringify!($SelfT), ".rem_euclid(4), 3); // or any other integer type -```"), - #[stable(feature = "euclidean_division", since = "1.38.0")] - #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - #[rustc_inherit_overflow_checks] - pub const fn rem_euclid(self, rhs: Self) -> Self { - self % rhs - } + /// Calculates the least remainder of `self (mod rhs)`. + /// + /// Since, for the positive integers, all common + /// definitions of division are equal, this + /// is exactly equal to `self % rhs`. + /// + /// # Panics + /// + /// This function will panic if `rhs` is 0. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(7", stringify!($SelfT), ".rem_euclid(4), 3); // or any other integer type")] + /// ``` + #[stable(feature = "euclidean_division", since = "1.38.0")] + #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[rustc_inherit_overflow_checks] + pub const fn rem_euclid(self, rhs: Self) -> Self { + self % rhs } - doc_comment! { - concat!("Returns `true` if and only if `self == 2^k` for some `k`. - -# Examples - -Basic usage: - -``` -", $Feature, "assert!(16", stringify!($SelfT), ".is_power_of_two()); -assert!(!10", stringify!($SelfT), ".is_power_of_two());", $EndFeature, " -```"), - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_is_power_of_two", since = "1.32.0")] - #[inline] - pub const fn is_power_of_two(self) -> bool { - self.count_ones() == 1 - } + /// Returns `true` if and only if `self == 2^k` for some `k`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert!(16", stringify!($SelfT), ".is_power_of_two());")] + #[doc = concat!("assert!(!10", stringify!($SelfT), ".is_power_of_two());")] + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_is_power_of_two", since = "1.32.0")] + #[inline] + pub const fn is_power_of_two(self) -> bool { + self.count_ones() == 1 } // Returns one less than next power of two. @@ -1663,332 +1533,302 @@ const fn one_less_than_next_power_of_two(self) -> Self { <$SelfT>::MAX >> z } - doc_comment! { - concat!("Returns the smallest power of two greater than or equal to `self`. - -When return value overflows (i.e., `self > (1 << (N-1))` for type -`uN`), it panics in debug mode and return value is wrapped to 0 in -release mode (the only situation in which method can return 0). - -# Examples - -Basic usage: - -``` -", $Feature, "assert_eq!(2", stringify!($SelfT), ".next_power_of_two(), 2); -assert_eq!(3", stringify!($SelfT), ".next_power_of_two(), 4);", $EndFeature, " -```"), - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] - #[inline] - #[rustc_inherit_overflow_checks] - pub const fn next_power_of_two(self) -> Self { - self.one_less_than_next_power_of_two() + 1 - } - } - - doc_comment! { - concat!("Returns the smallest power of two greater than or equal to `n`. If -the next power of two is greater than the type's maximum value, -`None` is returned, otherwise the power of two is wrapped in `Some`. - -# Examples - -Basic usage: - -``` -", $Feature, "assert_eq!(2", stringify!($SelfT), -".checked_next_power_of_two(), Some(2)); -assert_eq!(3", stringify!($SelfT), ".checked_next_power_of_two(), Some(4)); -assert_eq!(", stringify!($SelfT), "::MAX.checked_next_power_of_two(), None);", -$EndFeature, " -```"), - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] - pub const fn checked_next_power_of_two(self) -> Option { - self.one_less_than_next_power_of_two().checked_add(1) - } + /// Returns the smallest power of two greater than or equal to `self`. + /// + /// When return value overflows (i.e., `self > (1 << (N-1))` for type + /// `uN`), it panics in debug mode and return value is wrapped to 0 in + /// release mode (the only situation in which method can return 0). + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".next_power_of_two(), 2);")] + #[doc = concat!("assert_eq!(3", stringify!($SelfT), ".next_power_of_two(), 4);")] + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] + #[inline] + #[rustc_inherit_overflow_checks] + pub const fn next_power_of_two(self) -> Self { + self.one_less_than_next_power_of_two() + 1 } - doc_comment! { - concat!("Returns the smallest power of two greater than or equal to `n`. If -the next power of two is greater than the type's maximum value, -the return value is wrapped to `0`. - -# Examples - -Basic usage: - -``` -#![feature(wrapping_next_power_of_two)] -", $Feature, " -assert_eq!(2", stringify!($SelfT), ".wrapping_next_power_of_two(), 2); -assert_eq!(3", stringify!($SelfT), ".wrapping_next_power_of_two(), 4); -assert_eq!(", stringify!($SelfT), "::MAX.wrapping_next_power_of_two(), 0);", -$EndFeature, " -```"), - #[unstable(feature = "wrapping_next_power_of_two", issue = "32463", - reason = "needs decision on wrapping behaviour")] - #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] - pub const fn wrapping_next_power_of_two(self) -> Self { - self.one_less_than_next_power_of_two().wrapping_add(1) - } + /// Returns the smallest power of two greater than or equal to `n`. If + /// the next power of two is greater than the type's maximum value, + /// `None` is returned, otherwise the power of two is wrapped in `Some`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".checked_next_power_of_two(), Some(2));")] + #[doc = concat!("assert_eq!(3", stringify!($SelfT), ".checked_next_power_of_two(), Some(4));")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.checked_next_power_of_two(), None);")] + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] + pub const fn checked_next_power_of_two(self) -> Option { + self.one_less_than_next_power_of_two().checked_add(1) } - doc_comment! { - concat!("Return the memory representation of this integer as a byte array in -big-endian (network) byte order. -", -$to_xe_bytes_doc, -" -# Examples - -``` -let bytes = ", $swap_op, stringify!($SelfT), ".to_be_bytes(); -assert_eq!(bytes, ", $be_bytes, "); -```"), - #[stable(feature = "int_to_from_bytes", since = "1.32.0")] - #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")] - #[inline] - pub const fn to_be_bytes(self) -> [u8; mem::size_of::()] { - self.to_be().to_ne_bytes() - } + /// Returns the smallest power of two greater than or equal to `n`. If + /// the next power of two is greater than the type's maximum value, + /// the return value is wrapped to `0`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_next_power_of_two)] + /// + #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".wrapping_next_power_of_two(), 2);")] + #[doc = concat!("assert_eq!(3", stringify!($SelfT), ".wrapping_next_power_of_two(), 4);")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.wrapping_next_power_of_two(), 0);")] + /// ``` + #[unstable(feature = "wrapping_next_power_of_two", issue = "32463", + reason = "needs decision on wrapping behaviour")] + #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] + pub const fn wrapping_next_power_of_two(self) -> Self { + self.one_less_than_next_power_of_two().wrapping_add(1) } - doc_comment! { - concat!("Return the memory representation of this integer as a byte array in -little-endian byte order. -", -$to_xe_bytes_doc, -" -# Examples - -``` -let bytes = ", $swap_op, stringify!($SelfT), ".to_le_bytes(); -assert_eq!(bytes, ", $le_bytes, "); -```"), - #[stable(feature = "int_to_from_bytes", since = "1.32.0")] - #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")] - #[inline] - pub const fn to_le_bytes(self) -> [u8; mem::size_of::()] { - self.to_le().to_ne_bytes() - } + /// Return the memory representation of this integer as a byte array in + /// big-endian (network) byte order. + /// + #[doc = $to_xe_bytes_doc] + /// + /// # Examples + /// + /// ``` + #[doc = concat!("let bytes = ", $swap_op, stringify!($SelfT), ".to_be_bytes();")] + #[doc = concat!("assert_eq!(bytes, ", $be_bytes, ");")] + /// ``` + #[stable(feature = "int_to_from_bytes", since = "1.32.0")] + #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")] + #[inline] + pub const fn to_be_bytes(self) -> [u8; mem::size_of::()] { + self.to_be().to_ne_bytes() } - doc_comment! { - concat!(" -Return the memory representation of this integer as a byte array in -native byte order. - -As the target platform's native endianness is used, portable code -should use [`to_be_bytes`] or [`to_le_bytes`], as appropriate, -instead. -", -$to_xe_bytes_doc, -" -[`to_be_bytes`]: #method.to_be_bytes -[`to_le_bytes`]: #method.to_le_bytes - -# Examples - -``` -let bytes = ", $swap_op, stringify!($SelfT), ".to_ne_bytes(); -assert_eq!( - bytes, - if cfg!(target_endian = \"big\") { - ", $be_bytes, " - } else { - ", $le_bytes, " - } -); -```"), - #[stable(feature = "int_to_from_bytes", since = "1.32.0")] - #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")] - // SAFETY: const sound because integers are plain old datatypes so we can always - // transmute them to arrays of bytes - #[rustc_allow_const_fn_unstable(const_fn_transmute)] - #[inline] - pub const fn to_ne_bytes(self) -> [u8; mem::size_of::()] { - // SAFETY: integers are plain old datatypes so we can always transmute them to - // arrays of bytes - unsafe { mem::transmute(self) } - } + /// Return the memory representation of this integer as a byte array in + /// little-endian byte order. + /// + #[doc = $to_xe_bytes_doc] + /// + /// # Examples + /// + /// ``` + #[doc = concat!("let bytes = ", $swap_op, stringify!($SelfT), ".to_le_bytes();")] + #[doc = concat!("assert_eq!(bytes, ", $le_bytes, ");")] + /// ``` + #[stable(feature = "int_to_from_bytes", since = "1.32.0")] + #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")] + #[inline] + pub const fn to_le_bytes(self) -> [u8; mem::size_of::()] { + self.to_le().to_ne_bytes() } - doc_comment! { - concat!(" -Return the memory representation of this integer as a byte array in -native byte order. - -[`to_ne_bytes`] should be preferred over this whenever possible. - -[`to_ne_bytes`]: #method.to_ne_bytes -", - -" -# Examples - -``` -#![feature(num_as_ne_bytes)] -let num = ", $swap_op, stringify!($SelfT), "; -let bytes = num.as_ne_bytes(); -assert_eq!( - bytes, - if cfg!(target_endian = \"big\") { - &", $be_bytes, " - } else { - &", $le_bytes, " - } -); -```"), - #[unstable(feature = "num_as_ne_bytes", issue = "76976")] - #[inline] - pub fn as_ne_bytes(&self) -> &[u8; mem::size_of::()] { - // SAFETY: integers are plain old datatypes so we can always transmute them to - // arrays of bytes - unsafe { &*(self as *const Self as *const _) } - } + /// Return the memory representation of this integer as a byte array in + /// native byte order. + /// + /// As the target platform's native endianness is used, portable code + /// should use [`to_be_bytes`] or [`to_le_bytes`], as appropriate, + /// instead. + /// + #[doc = $to_xe_bytes_doc] + /// + /// [`to_be_bytes`]: #method.to_be_bytes + /// [`to_le_bytes`]: #method.to_le_bytes + /// + /// # Examples + /// + /// ``` + #[doc = concat!("let bytes = ", $swap_op, stringify!($SelfT), ".to_ne_bytes();")] + /// assert_eq!( + /// bytes, + /// if cfg!(target_endian = "big") { + #[doc = concat!(" ", $be_bytes)] + /// } else { + #[doc = concat!(" ", $le_bytes)] + /// } + /// ); + /// ``` + #[stable(feature = "int_to_from_bytes", since = "1.32.0")] + #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")] + // SAFETY: const sound because integers are plain old datatypes so we can always + // transmute them to arrays of bytes + #[rustc_allow_const_fn_unstable(const_fn_transmute)] + #[inline] + pub const fn to_ne_bytes(self) -> [u8; mem::size_of::()] { + // SAFETY: integers are plain old datatypes so we can always transmute them to + // arrays of bytes + unsafe { mem::transmute(self) } } - doc_comment! { - concat!("Create a native endian integer value from its representation -as a byte array in big endian. -", -$from_xe_bytes_doc, -" -# Examples - -``` -let value = ", stringify!($SelfT), "::from_be_bytes(", $be_bytes, "); -assert_eq!(value, ", $swap_op, "); -``` - -When starting from a slice rather than an array, fallible conversion APIs can be used: - -``` -use std::convert::TryInto; - -fn read_be_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " { - let (int_bytes, rest) = input.split_at(std::mem::size_of::<", stringify!($SelfT), ">()); - *input = rest; - ", stringify!($SelfT), "::from_be_bytes(int_bytes.try_into().unwrap()) -} -```"), - #[stable(feature = "int_to_from_bytes", since = "1.32.0")] - #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")] - #[inline] - pub const fn from_be_bytes(bytes: [u8; mem::size_of::()]) -> Self { - Self::from_be(Self::from_ne_bytes(bytes)) - } + /// Return the memory representation of this integer as a byte array in + /// native byte order. + /// + /// [`to_ne_bytes`] should be preferred over this whenever possible. + /// + /// [`to_ne_bytes`]: #method.to_ne_bytes + /// + /// # Examples + /// + /// ``` + /// #![feature(num_as_ne_bytes)] + #[doc = concat!("let num = ", $swap_op, stringify!($SelfT), ";")] + /// let bytes = num.as_ne_bytes(); + /// assert_eq!( + /// bytes, + /// if cfg!(target_endian = "big") { + #[doc = concat!(" &", $be_bytes)] + /// } else { + #[doc = concat!(" &", $le_bytes)] + /// } + /// ); + /// ``` + #[unstable(feature = "num_as_ne_bytes", issue = "76976")] + #[inline] + pub fn as_ne_bytes(&self) -> &[u8; mem::size_of::()] { + // SAFETY: integers are plain old datatypes so we can always transmute them to + // arrays of bytes + unsafe { &*(self as *const Self as *const _) } } - doc_comment! { - concat!(" -Create a native endian integer value from its representation -as a byte array in little endian. -", -$from_xe_bytes_doc, -" -# Examples - -``` -let value = ", stringify!($SelfT), "::from_le_bytes(", $le_bytes, "); -assert_eq!(value, ", $swap_op, "); -``` - -When starting from a slice rather than an array, fallible conversion APIs can be used: - -``` -use std::convert::TryInto; - -fn read_le_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " { - let (int_bytes, rest) = input.split_at(std::mem::size_of::<", stringify!($SelfT), ">()); - *input = rest; - ", stringify!($SelfT), "::from_le_bytes(int_bytes.try_into().unwrap()) -} -```"), - #[stable(feature = "int_to_from_bytes", since = "1.32.0")] - #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")] - #[inline] - pub const fn from_le_bytes(bytes: [u8; mem::size_of::()]) -> Self { - Self::from_le(Self::from_ne_bytes(bytes)) - } + /// Create a native endian integer value from its representation + /// as a byte array in big endian. + /// + #[doc = $from_xe_bytes_doc] + /// + /// # Examples + /// + /// ``` + #[doc = concat!("let value = ", stringify!($SelfT), "::from_be_bytes(", $be_bytes, ");")] + #[doc = concat!("assert_eq!(value, ", $swap_op, ");")] + /// ``` + /// + /// When starting from a slice rather than an array, fallible conversion APIs can be used: + /// + /// ``` + /// use std::convert::TryInto; + /// + #[doc = concat!("fn read_be_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " {")] + #[doc = concat!(" let (int_bytes, rest) = input.split_at(std::mem::size_of::<", stringify!($SelfT), ">());")] + /// *input = rest; + #[doc = concat!(" ", stringify!($SelfT), "::from_be_bytes(int_bytes.try_into().unwrap())")] + /// } + /// ``` + #[stable(feature = "int_to_from_bytes", since = "1.32.0")] + #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")] + #[inline] + pub const fn from_be_bytes(bytes: [u8; mem::size_of::()]) -> Self { + Self::from_be(Self::from_ne_bytes(bytes)) } - doc_comment! { - concat!("Create a native endian integer value from its memory representation -as a byte array in native endianness. - -As the target platform's native endianness is used, portable code -likely wants to use [`from_be_bytes`] or [`from_le_bytes`], as -appropriate instead. - -[`from_be_bytes`]: #method.from_be_bytes -[`from_le_bytes`]: #method.from_le_bytes -", -$from_xe_bytes_doc, -" -# Examples - -``` -let value = ", stringify!($SelfT), "::from_ne_bytes(if cfg!(target_endian = \"big\") { - ", $be_bytes, " -} else { - ", $le_bytes, " -}); -assert_eq!(value, ", $swap_op, "); -``` - -When starting from a slice rather than an array, fallible conversion APIs can be used: - -``` -use std::convert::TryInto; - -fn read_ne_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " { - let (int_bytes, rest) = input.split_at(std::mem::size_of::<", stringify!($SelfT), ">()); - *input = rest; - ", stringify!($SelfT), "::from_ne_bytes(int_bytes.try_into().unwrap()) -} -```"), - #[stable(feature = "int_to_from_bytes", since = "1.32.0")] - #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")] - // SAFETY: const sound because integers are plain old datatypes so we can always - // transmute to them - #[rustc_allow_const_fn_unstable(const_fn_transmute)] - #[inline] - pub const fn from_ne_bytes(bytes: [u8; mem::size_of::()]) -> Self { - // SAFETY: integers are plain old datatypes so we can always transmute to them - unsafe { mem::transmute(bytes) } - } + /// Create a native endian integer value from its representation + /// as a byte array in little endian. + /// + #[doc = $from_xe_bytes_doc] + /// + /// # Examples + /// + /// ``` + #[doc = concat!("let value = ", stringify!($SelfT), "::from_le_bytes(", $le_bytes, ");")] + #[doc = concat!("assert_eq!(value, ", $swap_op, ");")] + /// ``` + /// + /// When starting from a slice rather than an array, fallible conversion APIs can be used: + /// + /// ``` + /// use std::convert::TryInto; + /// + #[doc = concat!("fn read_le_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " {")] + #[doc = concat!(" let (int_bytes, rest) = input.split_at(std::mem::size_of::<", stringify!($SelfT), ">());")] + /// *input = rest; + #[doc = concat!(" ", stringify!($SelfT), "::from_le_bytes(int_bytes.try_into().unwrap())")] + /// } + /// ``` + #[stable(feature = "int_to_from_bytes", since = "1.32.0")] + #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")] + #[inline] + pub const fn from_le_bytes(bytes: [u8; mem::size_of::()]) -> Self { + Self::from_le(Self::from_ne_bytes(bytes)) } - doc_comment! { - concat!("**This method is soft-deprecated.** - -Although using it won’t cause compilation warning, -new code should use [`", stringify!($SelfT), "::MIN", "`](#associatedconstant.MIN) instead. - -Returns the smallest value that can be represented by this integer type."), - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_promotable] - #[inline(always)] - #[rustc_const_stable(feature = "const_max_value", since = "1.32.0")] - pub const fn min_value() -> Self { Self::MIN } + /// Create a native endian integer value from its memory representation + /// as a byte array in native endianness. + /// + /// As the target platform's native endianness is used, portable code + /// likely wants to use [`from_be_bytes`] or [`from_le_bytes`], as + /// appropriate instead. + /// + /// [`from_be_bytes`]: #method.from_be_bytes + /// [`from_le_bytes`]: #method.from_le_bytes + /// + #[doc = $from_xe_bytes_doc] + /// + /// # Examples + /// + /// ``` + #[doc = concat!("let value = ", stringify!($SelfT), "::from_ne_bytes(if cfg!(target_endian = \"big\") {")] + #[doc = concat!(" ", $be_bytes, "")] + /// } else { + #[doc = concat!(" ", $le_bytes, "")] + /// }); + #[doc = concat!("assert_eq!(value, ", $swap_op, ");")] + /// ``` + /// + /// When starting from a slice rather than an array, fallible conversion APIs can be used: + /// + /// ``` + /// use std::convert::TryInto; + /// + #[doc = concat!("fn read_ne_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " {")] + #[doc = concat!(" let (int_bytes, rest) = input.split_at(std::mem::size_of::<", stringify!($SelfT), ">());")] + /// *input = rest; + #[doc = concat!(" ", stringify!($SelfT), "::from_ne_bytes(int_bytes.try_into().unwrap())")] + /// } + /// ``` + #[stable(feature = "int_to_from_bytes", since = "1.32.0")] + #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")] + // SAFETY: const sound because integers are plain old datatypes so we can always + // transmute to them + #[rustc_allow_const_fn_unstable(const_fn_transmute)] + #[inline] + pub const fn from_ne_bytes(bytes: [u8; mem::size_of::()]) -> Self { + // SAFETY: integers are plain old datatypes so we can always transmute to them + unsafe { mem::transmute(bytes) } } - doc_comment! { - concat!("**This method is soft-deprecated.** - -Although using it won’t cause compilation warning, -new code should use [`", stringify!($SelfT), "::MAX", "`](#associatedconstant.MAX) instead. + /// **This method is soft-deprecated.** + /// + /// Although using it won’t cause compilation warning, new code should use + #[doc = concat!("[`", stringify!($SelfT), "::MIN", "`](#associatedconstant.MIN)")] + /// instead. + /// + /// Returns the smallest value that can be represented by this integer type. + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_promotable] + #[inline(always)] + #[rustc_const_stable(feature = "const_max_value", since = "1.32.0")] + pub const fn min_value() -> Self { Self::MIN } -Returns the largest value that can be represented by this integer type."), - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_promotable] - #[inline(always)] - #[rustc_const_stable(feature = "const_max_value", since = "1.32.0")] - pub const fn max_value() -> Self { Self::MAX } - } + /// **This method is soft-deprecated.** + /// + /// Although using it won’t cause compilation warning, new code should use + #[doc = concat!("[`", stringify!($SelfT), "::MAX", "`](#associatedconstant.MAX)")] + /// instead. + /// + /// Returns the largest value that can be represented by this integer type. + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_promotable] + #[inline(always)] + #[rustc_const_stable(feature = "const_max_value", since = "1.32.0")] + pub const fn max_value() -> Self { Self::MAX } } } diff --git a/library/core/src/num/wrapping.rs b/library/core/src/num/wrapping.rs index 77c9a93008c..f1b9dabe7d6 100644 --- a/library/core/src/num/wrapping.rs +++ b/library/core/src/num/wrapping.rs @@ -403,105 +403,94 @@ fn neg(self) -> Self { macro_rules! wrapping_int_impl { ($($t:ty)*) => ($( impl Wrapping<$t> { - doc_comment! { - concat!("Returns the smallest value that can be represented by this integer type. - -# Examples - -Basic usage: - -``` -#![feature(wrapping_int_impl)] -use std::num::Wrapping; - -assert_eq!(>::MIN, Wrapping(", stringify!($t), "::MIN)); -```"), - #[unstable(feature = "wrapping_int_impl", issue = "32463")] - pub const MIN: Self = Self(<$t>::MIN); - } - - doc_comment! { - concat!("Returns the largest value that can be represented by this integer type. - -# Examples - -Basic usage: - -``` -#![feature(wrapping_int_impl)] -use std::num::Wrapping; - -assert_eq!(>::MAX, Wrapping(", stringify!($t), "::MAX)); -```"), - #[unstable(feature = "wrapping_int_impl", issue = "32463")] - pub const MAX: Self = Self(<$t>::MAX); - } - - doc_comment! { - concat!("Returns the number of ones in the binary representation of `self`. - -# Examples - -Basic usage: - -``` -#![feature(wrapping_int_impl)] -use std::num::Wrapping; + /// Returns the smallest value that can be represented by this integer type. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + #[doc = concat!("assert_eq!(>::MIN, Wrapping(", stringify!($t), "::MIN));")] + /// ``` + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub const MIN: Self = Self(<$t>::MIN); -let n = Wrapping(0b01001100", stringify!($t), "); + /// Returns the largest value that can be represented by this integer type. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + #[doc = concat!("assert_eq!(>::MAX, Wrapping(", stringify!($t), "::MAX));")] + /// ``` + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub const MAX: Self = Self(<$t>::MAX); -assert_eq!(n.count_ones(), 3); -```"), - #[inline] - #[doc(alias = "popcount")] - #[doc(alias = "popcnt")] - #[unstable(feature = "wrapping_int_impl", issue = "32463")] - pub const fn count_ones(self) -> u32 { - self.0.count_ones() - } + /// Returns the number of ones in the binary representation of `self`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + #[doc = concat!("let n = Wrapping(0b01001100", stringify!($t), ");")] + /// + /// assert_eq!(n.count_ones(), 3); + /// ``` + #[inline] + #[doc(alias = "popcount")] + #[doc(alias = "popcnt")] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub const fn count_ones(self) -> u32 { + self.0.count_ones() } - doc_comment! { - concat!("Returns the number of zeros in the binary representation of `self`. - -# Examples - -Basic usage: - -``` -#![feature(wrapping_int_impl)] -use std::num::Wrapping; - -assert_eq!(Wrapping(!0", stringify!($t), ").count_zeros(), 0); -```"), - #[inline] - #[unstable(feature = "wrapping_int_impl", issue = "32463")] - pub const fn count_zeros(self) -> u32 { - self.0.count_zeros() - } + /// Returns the number of zeros in the binary representation of `self`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + #[doc = concat!("assert_eq!(Wrapping(!0", stringify!($t), ").count_zeros(), 0);")] + /// ``` + #[inline] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub const fn count_zeros(self) -> u32 { + self.0.count_zeros() } - doc_comment! { - concat!("Returns the number of trailing zeros in the binary representation -of `self`. - -# Examples - -Basic usage: - -``` -#![feature(wrapping_int_impl)] -use std::num::Wrapping; - -let n = Wrapping(0b0101000", stringify!($t), "); - -assert_eq!(n.trailing_zeros(), 3); -```"), - #[inline] - #[unstable(feature = "wrapping_int_impl", issue = "32463")] - pub const fn trailing_zeros(self) -> u32 { - self.0.trailing_zeros() - } + /// Returns the number of trailing zeros in the binary representation of `self`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + #[doc = concat!("let n = Wrapping(0b0101000", stringify!($t), ");")] + /// + /// assert_eq!(n.trailing_zeros(), 3); + /// ``` + #[inline] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub const fn trailing_zeros(self) -> u32 { + self.0.trailing_zeros() } /// Shifts the bits to the left by a specified amount, `n`, @@ -608,150 +597,140 @@ pub const fn reverse_bits(self) -> Self { Wrapping(self.0.reverse_bits()) } - doc_comment! { - concat!("Converts an integer from big endian to the target's endianness. - -On big endian this is a no-op. On little endian the bytes are -swapped. - -# Examples - -Basic usage: - -``` -#![feature(wrapping_int_impl)] -use std::num::Wrapping; - -let n = Wrapping(0x1A", stringify!($t), "); - -if cfg!(target_endian = \"big\") { - assert_eq!(>::from_be(n), n) -} else { - assert_eq!(>::from_be(n), n.swap_bytes()) -} -```"), - #[inline] - #[unstable(feature = "wrapping_int_impl", issue = "32463")] - pub const fn from_be(x: Self) -> Self { - Wrapping(<$t>::from_be(x.0)) - } + /// Converts an integer from big endian to the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are + /// swapped. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + #[doc = concat!("let n = Wrapping(0x1A", stringify!($t), ");")] + /// + /// if cfg!(target_endian = "big") { + #[doc = concat!(" assert_eq!(>::from_be(n), n)")] + /// } else { + #[doc = concat!(" assert_eq!(>::from_be(n), n.swap_bytes())")] + /// } + /// ``` + #[inline] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub const fn from_be(x: Self) -> Self { + Wrapping(<$t>::from_be(x.0)) } - doc_comment! { - concat!("Converts an integer from little endian to the target's endianness. - -On little endian this is a no-op. On big endian the bytes are -swapped. - -# Examples - -Basic usage: - -``` -#![feature(wrapping_int_impl)] -use std::num::Wrapping; - -let n = Wrapping(0x1A", stringify!($t), "); - -if cfg!(target_endian = \"little\") { - assert_eq!(>::from_le(n), n) -} else { - assert_eq!(>::from_le(n), n.swap_bytes()) -} -```"), - #[inline] - #[unstable(feature = "wrapping_int_impl", issue = "32463")] - pub const fn from_le(x: Self) -> Self { - Wrapping(<$t>::from_le(x.0)) - } + /// Converts an integer from little endian to the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are + /// swapped. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + #[doc = concat!("let n = Wrapping(0x1A", stringify!($t), ");")] + /// + /// if cfg!(target_endian = "little") { + #[doc = concat!(" assert_eq!(>::from_le(n), n)")] + /// } else { + #[doc = concat!(" assert_eq!(>::from_le(n), n.swap_bytes())")] + /// } + /// ``` + #[inline] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub const fn from_le(x: Self) -> Self { + Wrapping(<$t>::from_le(x.0)) } - doc_comment! { - concat!("Converts `self` to big endian from the target's endianness. - -On big endian this is a no-op. On little endian the bytes are -swapped. - -# Examples - -Basic usage: - -``` -#![feature(wrapping_int_impl)] -use std::num::Wrapping; - -let n = Wrapping(0x1A", stringify!($t), "); - -if cfg!(target_endian = \"big\") { - assert_eq!(n.to_be(), n) -} else { - assert_eq!(n.to_be(), n.swap_bytes()) -} -```"), - #[inline] - #[unstable(feature = "wrapping_int_impl", issue = "32463")] - pub const fn to_be(self) -> Self { - Wrapping(self.0.to_be()) - } + /// Converts `self` to big endian from the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are + /// swapped. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + #[doc = concat!("let n = Wrapping(0x1A", stringify!($t), ");")] + /// + /// if cfg!(target_endian = "big") { + /// assert_eq!(n.to_be(), n) + /// } else { + /// assert_eq!(n.to_be(), n.swap_bytes()) + /// } + /// ``` + #[inline] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub const fn to_be(self) -> Self { + Wrapping(self.0.to_be()) } - doc_comment! { - concat!("Converts `self` to little endian from the target's endianness. - -On little endian this is a no-op. On big endian the bytes are -swapped. - -# Examples - -Basic usage: - -``` -#![feature(wrapping_int_impl)] -use std::num::Wrapping; - -let n = Wrapping(0x1A", stringify!($t), "); - -if cfg!(target_endian = \"little\") { - assert_eq!(n.to_le(), n) -} else { - assert_eq!(n.to_le(), n.swap_bytes()) -} -```"), - #[inline] - #[unstable(feature = "wrapping_int_impl", issue = "32463")] - pub const fn to_le(self) -> Self { - Wrapping(self.0.to_le()) - } + /// Converts `self` to little endian from the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are + /// swapped. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + #[doc = concat!("let n = Wrapping(0x1A", stringify!($t), ");")] + /// + /// if cfg!(target_endian = "little") { + /// assert_eq!(n.to_le(), n) + /// } else { + /// assert_eq!(n.to_le(), n.swap_bytes()) + /// } + /// ``` + #[inline] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub const fn to_le(self) -> Self { + Wrapping(self.0.to_le()) } - doc_comment! { - concat!("Raises self to the power of `exp`, using exponentiation by squaring. - -# Examples - -Basic usage: - -``` -#![feature(wrapping_int_impl)] -use std::num::Wrapping; - -assert_eq!(Wrapping(3", stringify!($t), ").pow(4), Wrapping(81)); -``` - -Results that are too large are wrapped: - -``` -#![feature(wrapping_int_impl)] -use std::num::Wrapping; - -assert_eq!(Wrapping(3i8).pow(5), Wrapping(-13)); -assert_eq!(Wrapping(3i8).pow(6), Wrapping(-39)); -```"), - #[inline] - #[unstable(feature = "wrapping_int_impl", issue = "32463")] - pub fn pow(self, exp: u32) -> Self { - Wrapping(self.0.wrapping_pow(exp)) - } + /// Raises self to the power of `exp`, using exponentiation by squaring. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + #[doc = concat!("assert_eq!(Wrapping(3", stringify!($t), ").pow(4), Wrapping(81));")] + /// ``` + /// + /// Results that are too large are wrapped: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + /// assert_eq!(Wrapping(3i8).pow(5), Wrapping(-13)); + /// assert_eq!(Wrapping(3i8).pow(6), Wrapping(-39)); + /// ``` + #[inline] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub fn pow(self, exp: u32) -> Self { + Wrapping(self.0.wrapping_pow(exp)) } } )*) @@ -762,124 +741,114 @@ pub fn pow(self, exp: u32) -> Self { macro_rules! wrapping_int_impl_signed { ($($t:ty)*) => ($( impl Wrapping<$t> { - doc_comment! { - concat!("Returns the number of leading zeros in the binary representation of `self`. - -# Examples - -Basic usage: - -``` -#![feature(wrapping_int_impl)] -use std::num::Wrapping; - -let n = Wrapping(", stringify!($t), "::MAX) >> 2; - -assert_eq!(n.leading_zeros(), 3); -```"), - #[inline] - #[unstable(feature = "wrapping_int_impl", issue = "32463")] - pub const fn leading_zeros(self) -> u32 { - self.0.leading_zeros() - } + /// Returns the number of leading zeros in the binary representation of `self`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + #[doc = concat!("let n = Wrapping(", stringify!($t), "::MAX) >> 2;")] + /// + /// assert_eq!(n.leading_zeros(), 3); + /// ``` + #[inline] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub const fn leading_zeros(self) -> u32 { + self.0.leading_zeros() } - doc_comment! { - concat!("Computes the absolute value of `self`, wrapping around at -the boundary of the type. - -The only case where such wrapping can occur is when one takes the absolute value of the negative -minimal value for the type this is a positive value that is too large to represent in the type. In -such a case, this function returns `MIN` itself. - -# Examples - -Basic usage: - -``` -#![feature(wrapping_int_impl)] -use std::num::Wrapping; - -assert_eq!(Wrapping(100", stringify!($t), ").abs(), Wrapping(100)); -assert_eq!(Wrapping(-100", stringify!($t), ").abs(), Wrapping(100)); -assert_eq!(Wrapping(", stringify!($t), "::MIN).abs(), Wrapping(", stringify!($t), "::MIN)); -assert_eq!(Wrapping(-128i8).abs().0 as u8, 128u8); -```"), - #[inline] - #[unstable(feature = "wrapping_int_impl", issue = "32463")] - pub fn abs(self) -> Wrapping<$t> { - Wrapping(self.0.wrapping_abs()) - } + /// Computes the absolute value of `self`, wrapping around at + /// the boundary of the type. + /// + /// The only case where such wrapping can occur is when one takes the absolute value of the negative + /// minimal value for the type this is a positive value that is too large to represent in the type. In + /// such a case, this function returns `MIN` itself. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + #[doc = concat!("assert_eq!(Wrapping(100", stringify!($t), ").abs(), Wrapping(100));")] + #[doc = concat!("assert_eq!(Wrapping(-100", stringify!($t), ").abs(), Wrapping(100));")] + #[doc = concat!("assert_eq!(Wrapping(", stringify!($t), "::MIN).abs(), Wrapping(", stringify!($t), "::MIN));")] + /// assert_eq!(Wrapping(-128i8).abs().0 as u8, 128u8); + /// ``` + #[inline] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub fn abs(self) -> Wrapping<$t> { + Wrapping(self.0.wrapping_abs()) } - doc_comment! { - concat!("Returns a number representing sign of `self`. - - - `0` if the number is zero - - `1` if the number is positive - - `-1` if the number is negative - -# Examples - -Basic usage: - -``` -#![feature(wrapping_int_impl)] -use std::num::Wrapping; - -assert_eq!(Wrapping(10", stringify!($t), ").signum(), Wrapping(1)); -assert_eq!(Wrapping(0", stringify!($t), ").signum(), Wrapping(0)); -assert_eq!(Wrapping(-10", stringify!($t), ").signum(), Wrapping(-1)); -```"), - #[inline] - #[unstable(feature = "wrapping_int_impl", issue = "32463")] - pub fn signum(self) -> Wrapping<$t> { - Wrapping(self.0.signum()) - } + /// Returns a number representing sign of `self`. + /// + /// - `0` if the number is zero + /// - `1` if the number is positive + /// - `-1` if the number is negative + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + #[doc = concat!("assert_eq!(Wrapping(10", stringify!($t), ").signum(), Wrapping(1));")] + #[doc = concat!("assert_eq!(Wrapping(0", stringify!($t), ").signum(), Wrapping(0));")] + #[doc = concat!("assert_eq!(Wrapping(-10", stringify!($t), ").signum(), Wrapping(-1));")] + /// ``` + #[inline] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub fn signum(self) -> Wrapping<$t> { + Wrapping(self.0.signum()) } - doc_comment! { - concat!("Returns `true` if `self` is positive and `false` if the number is zero or -negative. - -# Examples - -Basic usage: - -``` -#![feature(wrapping_int_impl)] -use std::num::Wrapping; - -assert!(Wrapping(10", stringify!($t), ").is_positive()); -assert!(!Wrapping(-10", stringify!($t), ").is_positive()); -```"), - #[inline] - #[unstable(feature = "wrapping_int_impl", issue = "32463")] - pub const fn is_positive(self) -> bool { - self.0.is_positive() - } + /// Returns `true` if `self` is positive and `false` if the number is zero or + /// negative. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + #[doc = concat!("assert!(Wrapping(10", stringify!($t), ").is_positive());")] + #[doc = concat!("assert!(!Wrapping(-10", stringify!($t), ").is_positive());")] + /// ``` + #[inline] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub const fn is_positive(self) -> bool { + self.0.is_positive() } - doc_comment! { - concat!("Returns `true` if `self` is negative and `false` if the number is zero or -positive. - -# Examples - -Basic usage: - -``` -#![feature(wrapping_int_impl)] -use std::num::Wrapping; - -assert!(Wrapping(-10", stringify!($t), ").is_negative()); -assert!(!Wrapping(10", stringify!($t), ").is_negative()); -```"), - #[inline] - #[unstable(feature = "wrapping_int_impl", issue = "32463")] - pub const fn is_negative(self) -> bool { - self.0.is_negative() - } + /// Returns `true` if `self` is negative and `false` if the number is zero or + /// positive. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + #[doc = concat!("assert!(Wrapping(-10", stringify!($t), ").is_negative());")] + #[doc = concat!("assert!(!Wrapping(10", stringify!($t), ").is_negative());")] + /// ``` + #[inline] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub const fn is_negative(self) -> bool { + self.0.is_negative() } } )*) @@ -890,73 +859,67 @@ pub const fn is_negative(self) -> bool { macro_rules! wrapping_int_impl_unsigned { ($($t:ty)*) => ($( impl Wrapping<$t> { - doc_comment! { - concat!("Returns the number of leading zeros in the binary representation of `self`. - -# Examples - -Basic usage: - -``` -#![feature(wrapping_int_impl)] -use std::num::Wrapping; - -let n = Wrapping(", stringify!($t), "::MAX) >> 2; - -assert_eq!(n.leading_zeros(), 2); -```"), - #[inline] - #[unstable(feature = "wrapping_int_impl", issue = "32463")] - pub const fn leading_zeros(self) -> u32 { - self.0.leading_zeros() - } + /// Returns the number of leading zeros in the binary representation of `self`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + #[doc = concat!("let n = Wrapping(", stringify!($t), "::MAX) >> 2;")] + /// + /// assert_eq!(n.leading_zeros(), 2); + /// ``` + #[inline] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub const fn leading_zeros(self) -> u32 { + self.0.leading_zeros() } - doc_comment! { - concat!("Returns `true` if and only if `self == 2^k` for some `k`. - -# Examples - -Basic usage: - -``` -#![feature(wrapping_int_impl)] -use std::num::Wrapping; - -assert!(Wrapping(16", stringify!($t), ").is_power_of_two()); -assert!(!Wrapping(10", stringify!($t), ").is_power_of_two()); -```"), - #[inline] - #[unstable(feature = "wrapping_int_impl", issue = "32463")] - pub fn is_power_of_two(self) -> bool { - self.0.is_power_of_two() - } + /// Returns `true` if and only if `self == 2^k` for some `k`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + #[doc = concat!("assert!(Wrapping(16", stringify!($t), ").is_power_of_two());")] + #[doc = concat!("assert!(!Wrapping(10", stringify!($t), ").is_power_of_two());")] + /// ``` + #[inline] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub fn is_power_of_two(self) -> bool { + self.0.is_power_of_two() } - doc_comment! { - concat!("Returns the smallest power of two greater than or equal to `self`. - -When return value overflows (i.e., `self > (1 << (N-1))` for type -`uN`), overflows to `2^N = 0`. - -# Examples - -Basic usage: - -``` -#![feature(wrapping_next_power_of_two)] -use std::num::Wrapping; - -assert_eq!(Wrapping(2", stringify!($t), ").next_power_of_two(), Wrapping(2)); -assert_eq!(Wrapping(3", stringify!($t), ").next_power_of_two(), Wrapping(4)); -assert_eq!(Wrapping(200_u8).next_power_of_two(), Wrapping(0)); -```"), - #[inline] - #[unstable(feature = "wrapping_next_power_of_two", issue = "32463", - reason = "needs decision on wrapping behaviour")] - pub fn next_power_of_two(self) -> Self { - Wrapping(self.0.wrapping_next_power_of_two()) - } + /// Returns the smallest power of two greater than or equal to `self`. + /// + /// When return value overflows (i.e., `self > (1 << (N-1))` for type + /// `uN`), overflows to `2^N = 0`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_next_power_of_two)] + /// use std::num::Wrapping; + /// + #[doc = concat!("assert_eq!(Wrapping(2", stringify!($t), ").next_power_of_two(), Wrapping(2));")] + #[doc = concat!("assert_eq!(Wrapping(3", stringify!($t), ").next_power_of_two(), Wrapping(4));")] + #[doc = concat!("assert_eq!(Wrapping(200_u8).next_power_of_two(), Wrapping(0));")] + /// ``` + #[inline] + #[unstable(feature = "wrapping_next_power_of_two", issue = "32463", + reason = "needs decision on wrapping behaviour")] + pub fn next_power_of_two(self) -> Self { + Wrapping(self.0.wrapping_next_power_of_two()) } } )*) diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 8fd9ff768c4..66300116786 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -232,23 +232,27 @@ pub unsafe fn as_uninit_ref<'a>(self) -> Option<&'a MaybeUninit> /// /// # Safety /// - /// The resulting pointer does not need to be in bounds, but it is - /// potentially hazardous to dereference (which requires `unsafe`). + /// This operation itself is always safe, but using the resulting pointer is not. /// - /// In particular, the resulting pointer remains attached to the same allocated - /// object that `self` points to. It may *not* be used to access a - /// different allocated object. Note that in Rust, - /// every (stack-allocated) variable is considered a separate allocated object. + /// The resulting pointer remains attached to the same allocated object that `self` points to. + /// It may *not* be used to access a different allocated object. Note that in Rust, every + /// (stack-allocated) variable is considered a separate allocated object. /// - /// In other words, `x.wrapping_offset((y as usize).wrapping_sub(x as usize) / size_of::())` - /// is *not* the same as `y`, and dereferencing it is undefined behavior - /// unless `x` and `y` point into the same allocated object. + /// In other words, `let z = x.wrapping_offset((y as isize) - (x as isize))` does *not* make `z` + /// the same as `y` even if we assume `T` has size `1` and there is no overflow: `z` is still + /// attached to the object `x` is attached to, and dereferencing it is Undefined Behavior unless + /// `x` and `y` point into the same allocated object. /// - /// Compared to [`offset`], this method basically delays the requirement of staying - /// within the same allocated object: [`offset`] is immediate Undefined Behavior when - /// crossing object boundaries; `wrapping_offset` produces a pointer but still leads - /// to Undefined Behavior if that pointer is dereferenced. [`offset`] can be optimized - /// better and is thus preferable in performance-sensitive code. + /// Compared to [`offset`], this method basically delays the requirement of staying within the + /// same allocated object: [`offset`] is immediate Undefined Behavior when crossing object + /// boundaries; `wrapping_offset` produces a pointer but still leads to Undefined Behavior if a + /// pointer is dereferenced when it is out-of-bounds of the object it is attached to. [`offset`] + /// can be optimized better and is thus preferable in performance-sensitive code. + /// + /// The delayed check only considers the value of the pointer that was dereferenced, not the + /// intermediate values used during the computation of the final result. For example, + /// `x.wrapping_offset(o).wrapping_offset(o.wrapping_neg())` is always the same as `x`. In other + /// words, leaving the allocated object and then re-entering it later is permitted. /// /// If you need to cross object boundaries, cast the pointer to an integer and /// do the arithmetic there. @@ -571,19 +575,27 @@ pub const fn guaranteed_ne(self, other: *const T) -> bool /// /// # Safety /// - /// The resulting pointer does not need to be in bounds, but it is - /// potentially hazardous to dereference (which requires `unsafe`). + /// This operation itself is always safe, but using the resulting pointer is not. + /// + /// The resulting pointer remains attached to the same allocated object that `self` points to. + /// It may *not* be used to access a different allocated object. Note that in Rust, every + /// (stack-allocated) variable is considered a separate allocated object. + /// + /// In other words, `let z = x.wrapping_add((y as usize) - (x as usize))` does *not* make `z` + /// the same as `y` even if we assume `T` has size `1` and there is no overflow: `z` is still + /// attached to the object `x` is attached to, and dereferencing it is Undefined Behavior unless + /// `x` and `y` point into the same allocated object. /// - /// In particular, the resulting pointer remains attached to the same allocated - /// object that `self` points to. It may *not* be used to access a - /// different allocated object. Note that in Rust, - /// every (stack-allocated) variable is considered a separate allocated object. + /// Compared to [`add`], this method basically delays the requirement of staying within the + /// same allocated object: [`add`] is immediate Undefined Behavior when crossing object + /// boundaries; `wrapping_add` produces a pointer but still leads to Undefined Behavior if a + /// pointer is dereferenced when it is out-of-bounds of the object it is attached to. [`add`] + /// can be optimized better and is thus preferable in performance-sensitive code. /// - /// Compared to [`add`], this method basically delays the requirement of staying - /// within the same allocated object: [`add`] is immediate Undefined Behavior when - /// crossing object boundaries; `wrapping_add` produces a pointer but still leads - /// to Undefined Behavior if that pointer is dereferenced. [`add`] can be optimized - /// better and is thus preferable in performance-sensitive code. + /// The delayed check only considers the value of the pointer that was dereferenced, not the + /// intermediate values used during the computation of the final result. For example, + /// `x.wrapping_add(o).wrapping_sub(o)` is always the same as `x`. In other words, leaving the + /// allocated object and then re-entering it later is permitted. /// /// If you need to cross object boundaries, cast the pointer to an integer and /// do the arithmetic there. @@ -628,19 +640,27 @@ pub const fn wrapping_add(self, count: usize) -> Self /// /// # Safety /// - /// The resulting pointer does not need to be in bounds, but it is - /// potentially hazardous to dereference (which requires `unsafe`). + /// This operation itself is always safe, but using the resulting pointer is not. + /// + /// The resulting pointer remains attached to the same allocated object that `self` points to. + /// It may *not* be used to access a different allocated object. Note that in Rust, every + /// (stack-allocated) variable is considered a separate allocated object. + /// + /// In other words, `let z = x.wrapping_sub((x as usize) - (y as usize))` does *not* make `z` + /// the same as `y` even if we assume `T` has size `1` and there is no overflow: `z` is still + /// attached to the object `x` is attached to, and dereferencing it is Undefined Behavior unless + /// `x` and `y` point into the same allocated object. /// - /// In particular, the resulting pointer remains attached to the same allocated - /// object that `self` points to. It may *not* be used to access a - /// different allocated object. Note that in Rust, - /// every (stack-allocated) variable is considered a separate allocated object. + /// Compared to [`sub`], this method basically delays the requirement of staying within the + /// same allocated object: [`sub`] is immediate Undefined Behavior when crossing object + /// boundaries; `wrapping_sub` produces a pointer but still leads to Undefined Behavior if a + /// pointer is dereferenced when it is out-of-bounds of the object it is attached to. [`sub`] + /// can be optimized better and is thus preferable in performance-sensitive code. /// - /// Compared to [`sub`], this method basically delays the requirement of staying - /// within the same allocated object: [`sub`] is immediate Undefined Behavior when - /// crossing object boundaries; `wrapping_sub` produces a pointer but still leads - /// to Undefined Behavior if that pointer is dereferenced. [`sub`] can be optimized - /// better and is thus preferable in performance-sensitive code. + /// The delayed check only considers the value of the pointer that was dereferenced, not the + /// intermediate values used during the computation of the final result. For example, + /// `x.wrapping_add(o).wrapping_sub(o)` is always the same as `x`. In other words, leaving the + /// allocated object and then re-entering it later is permitted. /// /// If you need to cross object boundaries, cast the pointer to an integer and /// do the arithmetic there. @@ -725,8 +745,9 @@ pub fn set_ptr_value(mut self, val: *const u8) -> Self { /// /// [`ptr::read`]: crate::ptr::read() #[stable(feature = "pointer_methods", since = "1.26.0")] + #[rustc_const_unstable(feature = "const_ptr_read", issue = "80377")] #[inline] - pub unsafe fn read(self) -> T + pub const unsafe fn read(self) -> T where T: Sized, { @@ -763,8 +784,9 @@ pub unsafe fn read_volatile(self) -> T /// /// [`ptr::read_unaligned`]: crate::ptr::read_unaligned() #[stable(feature = "pointer_methods", since = "1.26.0")] + #[rustc_const_unstable(feature = "const_ptr_read", issue = "80377")] #[inline] - pub unsafe fn read_unaligned(self) -> T + pub const unsafe fn read_unaligned(self) -> T where T: Sized, { diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 27d49529a5e..807f114ea46 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -685,7 +685,8 @@ pub unsafe fn replace(dst: *mut T, mut src: T) -> T { /// [valid]: self#safety #[inline] #[stable(feature = "rust1", since = "1.0.0")] -pub unsafe fn read(src: *const T) -> T { +#[rustc_const_unstable(feature = "const_ptr_read", issue = "80377")] +pub const unsafe fn read(src: *const T) -> T { // `copy_nonoverlapping` takes care of debug_assert. let mut tmp = MaybeUninit::::uninit(); // SAFETY: the caller must guarantee that `src` is valid for reads. @@ -784,7 +785,8 @@ pub unsafe fn read(src: *const T) -> T { /// ``` #[inline] #[stable(feature = "ptr_unaligned", since = "1.17.0")] -pub unsafe fn read_unaligned(src: *const T) -> T { +#[rustc_const_unstable(feature = "const_ptr_read", issue = "80377")] +pub const unsafe fn read_unaligned(src: *const T) -> T { // `copy_nonoverlapping` takes care of debug_assert. let mut tmp = MaybeUninit::::uninit(); // SAFETY: the caller must guarantee that `src` is valid for reads. diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 5f94c2393ae..785bf70c299 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -238,23 +238,27 @@ pub unsafe fn as_uninit_ref<'a>(self) -> Option<&'a MaybeUninit> /// /// # Safety /// - /// The resulting pointer does not need to be in bounds, but it is - /// potentially hazardous to dereference (which requires `unsafe`). + /// This operation itself is always safe, but using the resulting pointer is not. /// - /// In particular, the resulting pointer remains attached to the same allocated - /// object that `self` points to. It may *not* be used to access a - /// different allocated object. Note that in Rust, - /// every (stack-allocated) variable is considered a separate allocated object. + /// The resulting pointer remains attached to the same allocated object that `self` points to. + /// It may *not* be used to access a different allocated object. Note that in Rust, every + /// (stack-allocated) variable is considered a separate allocated object. /// - /// In other words, `x.wrapping_offset((y as usize).wrapping_sub(x as usize) / size_of::())` - /// is *not* the same as `y`, and dereferencing it is undefined behavior - /// unless `x` and `y` point into the same allocated object. + /// In other words, `let z = x.wrapping_offset((y as isize) - (x as isize))` does *not* make `z` + /// the same as `y` even if we assume `T` has size `1` and there is no overflow: `z` is still + /// attached to the object `x` is attached to, and dereferencing it is Undefined Behavior unless + /// `x` and `y` point into the same allocated object. /// - /// Compared to [`offset`], this method basically delays the requirement of staying - /// within the same allocated object: [`offset`] is immediate Undefined Behavior when - /// crossing object boundaries; `wrapping_offset` produces a pointer but still leads - /// to Undefined Behavior if that pointer is dereferenced. [`offset`] can be optimized - /// better and is thus preferable in performance-sensitive code. + /// Compared to [`offset`], this method basically delays the requirement of staying within the + /// same allocated object: [`offset`] is immediate Undefined Behavior when crossing object + /// boundaries; `wrapping_offset` produces a pointer but still leads to Undefined Behavior if a + /// pointer is dereferenced when it is out-of-bounds of the object it is attached to. [`offset`] + /// can be optimized better and is thus preferable in performance-sensitive code. + /// + /// The delayed check only considers the value of the pointer that was dereferenced, not the + /// intermediate values used during the computation of the final result. For example, + /// `x.wrapping_offset(o).wrapping_offset(o.wrapping_neg())` is always the same as `x`. In other + /// words, leaving the allocated object and then re-entering it later is permitted. /// /// If you need to cross object boundaries, cast the pointer to an integer and /// do the arithmetic there. @@ -678,19 +682,27 @@ pub const fn guaranteed_eq(self, other: *mut T) -> bool /// /// # Safety /// - /// The resulting pointer does not need to be in bounds, but it is - /// potentially hazardous to dereference (which requires `unsafe`). + /// This operation itself is always safe, but using the resulting pointer is not. + /// + /// The resulting pointer remains attached to the same allocated object that `self` points to. + /// It may *not* be used to access a different allocated object. Note that in Rust, every + /// (stack-allocated) variable is considered a separate allocated object. + /// + /// In other words, `let z = x.wrapping_add((y as usize) - (x as usize))` does *not* make `z` + /// the same as `y` even if we assume `T` has size `1` and there is no overflow: `z` is still + /// attached to the object `x` is attached to, and dereferencing it is Undefined Behavior unless + /// `x` and `y` point into the same allocated object. /// - /// In particular, the resulting pointer remains attached to the same allocated - /// object that `self` points to. It may *not* be used to access a - /// different allocated object. Note that in Rust, - /// every (stack-allocated) variable is considered a separate allocated object. + /// Compared to [`add`], this method basically delays the requirement of staying within the + /// same allocated object: [`add`] is immediate Undefined Behavior when crossing object + /// boundaries; `wrapping_add` produces a pointer but still leads to Undefined Behavior if a + /// pointer is dereferenced when it is out-of-bounds of the object it is attached to. [`add`] + /// can be optimized better and is thus preferable in performance-sensitive code. /// - /// Compared to [`add`], this method basically delays the requirement of staying - /// within the same allocated object: [`add`] is immediate Undefined Behavior when - /// crossing object boundaries; `wrapping_add` produces a pointer but still leads - /// to Undefined Behavior if that pointer is dereferenced. [`add`] can be optimized - /// better and is thus preferable in performance-sensitive code. + /// The delayed check only considers the value of the pointer that was dereferenced, not the + /// intermediate values used during the computation of the final result. For example, + /// `x.wrapping_add(o).wrapping_sub(o)` is always the same as `x`. In other words, leaving the + /// allocated object and then re-entering it later is permitted. /// /// If you need to cross object boundaries, cast the pointer to an integer and /// do the arithmetic there. @@ -735,19 +747,27 @@ pub const fn wrapping_add(self, count: usize) -> Self /// /// # Safety /// - /// The resulting pointer does not need to be in bounds, but it is - /// potentially hazardous to dereference (which requires `unsafe`). + /// This operation itself is always safe, but using the resulting pointer is not. + /// + /// The resulting pointer remains attached to the same allocated object that `self` points to. + /// It may *not* be used to access a different allocated object. Note that in Rust, every + /// (stack-allocated) variable is considered a separate allocated object. + /// + /// In other words, `let z = x.wrapping_sub((x as usize) - (y as usize))` does *not* make `z` + /// the same as `y` even if we assume `T` has size `1` and there is no overflow: `z` is still + /// attached to the object `x` is attached to, and dereferencing it is Undefined Behavior unless + /// `x` and `y` point into the same allocated object. /// - /// In particular, the resulting pointer remains attached to the same allocated - /// object that `self` points to. It may *not* be used to access a - /// different allocated object. Note that in Rust, - /// every (stack-allocated) variable is considered a separate allocated object. + /// Compared to [`sub`], this method basically delays the requirement of staying within the + /// same allocated object: [`sub`] is immediate Undefined Behavior when crossing object + /// boundaries; `wrapping_sub` produces a pointer but still leads to Undefined Behavior if a + /// pointer is dereferenced when it is out-of-bounds of the object it is attached to. [`sub`] + /// can be optimized better and is thus preferable in performance-sensitive code. /// - /// Compared to [`sub`], this method basically delays the requirement of staying - /// within the same allocated object: [`sub`] is immediate Undefined Behavior when - /// crossing object boundaries; `wrapping_sub` produces a pointer but still leads - /// to Undefined Behavior if that pointer is dereferenced. [`sub`] can be optimized - /// better and is thus preferable in performance-sensitive code. + /// The delayed check only considers the value of the pointer that was dereferenced, not the + /// intermediate values used during the computation of the final result. For example, + /// `x.wrapping_add(o).wrapping_sub(o)` is always the same as `x`. In other words, leaving the + /// allocated object and then re-entering it later is permitted. /// /// If you need to cross object boundaries, cast the pointer to an integer and /// do the arithmetic there. @@ -832,8 +852,9 @@ pub fn set_ptr_value(mut self, val: *mut u8) -> Self { /// /// [`ptr::read`]: crate::ptr::read() #[stable(feature = "pointer_methods", since = "1.26.0")] + #[rustc_const_unstable(feature = "const_ptr_read", issue = "80377")] #[inline] - pub unsafe fn read(self) -> T + pub const unsafe fn read(self) -> T where T: Sized, { @@ -870,8 +891,9 @@ pub unsafe fn read_volatile(self) -> T /// /// [`ptr::read_unaligned`]: crate::ptr::read_unaligned() #[stable(feature = "pointer_methods", since = "1.26.0")] + #[rustc_const_unstable(feature = "const_ptr_read", issue = "80377")] #[inline] - pub unsafe fn read_unaligned(self) -> T + pub const unsafe fn read_unaligned(self) -> T where T: Sized, { diff --git a/library/core/src/slice/cmp.rs b/library/core/src/slice/cmp.rs index 18073f4afed..72af47c71dd 100644 --- a/library/core/src/slice/cmp.rs +++ b/library/core/src/slice/cmp.rs @@ -75,28 +75,6 @@ impl SlicePartialEq for [A] } } -// Use an equal-pointer optimization when types are `Eq` -// We can't make `A` and `B` the same type because `min_specialization` won't -// allow it. -impl SlicePartialEq for [A] -where - A: MarkerEq, -{ - default fn equal(&self, other: &[B]) -> bool { - if self.len() != other.len() { - return false; - } - - // While performance would suffer if `guaranteed_eq` just returned `false` - // for all arguments, correctness and return value of this function are not affected. - if self.as_ptr().guaranteed_eq(other.as_ptr() as *const A) { - return true; - } - - self.iter().zip(other.iter()).all(|(x, y)| x == y) - } -} - // Use memcmp for bytewise equality when the types allow impl SlicePartialEq for [A] where @@ -107,11 +85,6 @@ fn equal(&self, other: &[B]) -> bool { return false; } - // While performance would suffer if `guaranteed_eq` just returned `false` - // for all arguments, correctness and return value of this function are not affected. - if self.as_ptr().guaranteed_eq(other.as_ptr() as *const A) { - return true; - } // SAFETY: `self` and `other` are references and are thus guaranteed to be valid. // The two slices have been checked to have the same size above. unsafe { diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 44fe2ca8859..bb1014332a1 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -84,6 +84,7 @@ impl [T] { /// let a = [1, 2, 3]; /// assert_eq!(a.len(), 3); /// ``` + #[doc(alias = "length")] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_slice_len", since = "1.32.0")] #[inline] @@ -2581,14 +2582,12 @@ pub fn rotate_right(&mut self, k: usize) { /// # Examples /// /// ``` - /// #![feature(slice_fill)] - /// /// let mut buf = vec![0; 10]; /// buf.fill(1); /// assert_eq!(buf, vec![1; 10]); /// ``` #[doc(alias = "memset")] - #[unstable(feature = "slice_fill", issue = "70758")] + #[stable(feature = "slice_fill", since = "1.50.0")] pub fn fill(&mut self, value: T) where T: Clone, diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index 83cf47c8c8f..ba495a1a9fb 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -138,6 +138,7 @@ impl str { /// assert_eq!("ƒoo".len(), 4); // fancy f! /// assert_eq!("ƒoo".chars().count(), 3); /// ``` + #[doc(alias = "length")] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_str_len", since = "1.32.0")] #[inline] diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index a96da9aa6dc..d03c19e51f3 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -464,6 +464,23 @@ pub fn swap(&self, val: bool, order: Ordering) -> bool { /// **Note:** This method is only available on platforms that support atomic /// operations on `u8`. /// + /// # Migrating to `compare_exchange` and `compare_exchange_weak` + /// + /// `compare_and_swap` is equivalent to `compare_exchange` with the following mapping for + /// memory orderings: + /// + /// Original | Success | Failure + /// -------- | ------- | ------- + /// Relaxed | Relaxed | Relaxed + /// Acquire | Acquire | Acquire + /// Release | Release | Relaxed + /// AcqRel | AcqRel | Acquire + /// SeqCst | SeqCst | SeqCst + /// + /// `compare_exchange_weak` is allowed to fail spuriously even when the comparison succeeds, + /// which allows the compiler to generate better assembly code when the compare and swap + /// is used in a loop. + /// /// # Examples /// /// ``` @@ -479,6 +496,10 @@ pub fn swap(&self, val: bool, order: Ordering) -> bool { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_deprecated( + since = "1.50.0", + reason = "Use `compare_exchange` or `compare_exchange_weak` instead" + )] #[cfg(target_has_atomic = "8")] pub fn compare_and_swap(&self, current: bool, new: bool, order: Ordering) -> bool { match self.compare_exchange(current, new, order, strongest_failure_ordering(order)) { @@ -493,9 +514,10 @@ pub fn compare_and_swap(&self, current: bool, new: bool, order: Ordering) -> boo /// the previous value. On success this value is guaranteed to be equal to `current`. /// /// `compare_exchange` takes two [`Ordering`] arguments to describe the memory - /// ordering of this operation. The first describes the required ordering if the - /// operation succeeds while the second describes the required ordering when the - /// operation fails. Using [`Acquire`] as success ordering makes the store part + /// ordering of this operation. `success` describes the required ordering for the + /// read-modify-write operation that takes place if the comparison with `current` succeeds. + /// `failure` describes the required ordering for the load operation that takes place when + /// the comparison fails. Using [`Acquire`] as success ordering makes the store part /// of this operation [`Relaxed`], and using [`Release`] makes the successful load /// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`] /// and must be equivalent to or weaker than the success ordering. @@ -525,6 +547,7 @@ pub fn compare_and_swap(&self, current: bool, new: bool, order: Ordering) -> boo /// ``` #[inline] #[stable(feature = "extended_compare_and_swap", since = "1.10.0")] + #[doc(alias = "compare_and_swap")] #[cfg(target_has_atomic = "8")] pub fn compare_exchange( &self, @@ -550,9 +573,10 @@ pub fn compare_exchange( /// previous value. /// /// `compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory - /// ordering of this operation. The first describes the required ordering if the - /// operation succeeds while the second describes the required ordering when the - /// operation fails. Using [`Acquire`] as success ordering makes the store part + /// ordering of this operation. `success` describes the required ordering for the + /// read-modify-write operation that takes place if the comparison with `current` succeeds. + /// `failure` describes the required ordering for the load operation that takes place when + /// the comparison fails. Using [`Acquire`] as success ordering makes the store part /// of this operation [`Relaxed`], and using [`Release`] makes the successful load /// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`] /// and must be equivalent to or weaker than the success ordering. @@ -578,6 +602,7 @@ pub fn compare_exchange( /// ``` #[inline] #[stable(feature = "extended_compare_and_swap", since = "1.10.0")] + #[doc(alias = "compare_and_swap")] #[cfg(target_has_atomic = "8")] pub fn compare_exchange_weak( &self, @@ -966,16 +991,8 @@ pub const fn into_inner(self) -> *mut T { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn load(&self, order: Ordering) -> *mut T { - #[cfg(not(bootstrap))] - // SAFETY: data races are prevented by atomic intrinsics. - unsafe { - atomic_load(self.p.get(), order) - } - #[cfg(bootstrap)] // SAFETY: data races are prevented by atomic intrinsics. - unsafe { - atomic_load(self.p.get() as *mut usize, order) as *mut T - } + unsafe { atomic_load(self.p.get(), order) } } /// Stores a value into the pointer. @@ -1002,16 +1019,10 @@ pub fn load(&self, order: Ordering) -> *mut T { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn store(&self, ptr: *mut T, order: Ordering) { - #[cfg(not(bootstrap))] // SAFETY: data races are prevented by atomic intrinsics. unsafe { atomic_store(self.p.get(), ptr, order); } - #[cfg(bootstrap)] - // SAFETY: data races are prevented by atomic intrinsics. - unsafe { - atomic_store(self.p.get() as *mut usize, ptr as usize, order); - } } /// Stores a value into the pointer, returning the previous value. @@ -1040,16 +1051,8 @@ pub fn store(&self, ptr: *mut T, order: Ordering) { #[stable(feature = "rust1", since = "1.0.0")] #[cfg(target_has_atomic = "ptr")] pub fn swap(&self, ptr: *mut T, order: Ordering) -> *mut T { - #[cfg(bootstrap)] // SAFETY: data races are prevented by atomic intrinsics. - unsafe { - atomic_swap(self.p.get() as *mut usize, ptr as usize, order) as *mut T - } - #[cfg(not(bootstrap))] - // SAFETY: data races are prevented by atomic intrinsics. - unsafe { - atomic_swap(self.p.get(), ptr, order) - } + unsafe { atomic_swap(self.p.get(), ptr, order) } } /// Stores a value into the pointer if the current value is the same as the `current` value. @@ -1066,6 +1069,23 @@ pub fn swap(&self, ptr: *mut T, order: Ordering) -> *mut T { /// **Note:** This method is only available on platforms that support atomic /// operations on pointers. /// + /// # Migrating to `compare_exchange` and `compare_exchange_weak` + /// + /// `compare_and_swap` is equivalent to `compare_exchange` with the following mapping for + /// memory orderings: + /// + /// Original | Success | Failure + /// -------- | ------- | ------- + /// Relaxed | Relaxed | Relaxed + /// Acquire | Acquire | Acquire + /// Release | Release | Relaxed + /// AcqRel | AcqRel | Acquire + /// SeqCst | SeqCst | SeqCst + /// + /// `compare_exchange_weak` is allowed to fail spuriously even when the comparison succeeds, + /// which allows the compiler to generate better assembly code when the compare and swap + /// is used in a loop. + /// /// # Examples /// /// ``` @@ -1080,6 +1100,10 @@ pub fn swap(&self, ptr: *mut T, order: Ordering) -> *mut T { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_deprecated( + since = "1.50.0", + reason = "Use `compare_exchange` or `compare_exchange_weak` instead" + )] #[cfg(target_has_atomic = "ptr")] pub fn compare_and_swap(&self, current: *mut T, new: *mut T, order: Ordering) -> *mut T { match self.compare_exchange(current, new, order, strongest_failure_ordering(order)) { @@ -1094,9 +1118,10 @@ pub fn compare_and_swap(&self, current: *mut T, new: *mut T, order: Ordering) -> /// the previous value. On success this value is guaranteed to be equal to `current`. /// /// `compare_exchange` takes two [`Ordering`] arguments to describe the memory - /// ordering of this operation. The first describes the required ordering if the - /// operation succeeds while the second describes the required ordering when the - /// operation fails. Using [`Acquire`] as success ordering makes the store part + /// ordering of this operation. `success` describes the required ordering for the + /// read-modify-write operation that takes place if the comparison with `current` succeeds. + /// `failure` describes the required ordering for the load operation that takes place when + /// the comparison fails. Using [`Acquire`] as success ordering makes the store part /// of this operation [`Relaxed`], and using [`Release`] makes the successful load /// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`] /// and must be equivalent to or weaker than the success ordering. @@ -1127,26 +1152,8 @@ pub fn compare_exchange( success: Ordering, failure: Ordering, ) -> Result<*mut T, *mut T> { - #[cfg(bootstrap)] - // SAFETY: data races are prevented by atomic intrinsics. - unsafe { - let res = atomic_compare_exchange( - self.p.get() as *mut usize, - current as usize, - new as usize, - success, - failure, - ); - match res { - Ok(x) => Ok(x as *mut T), - Err(x) => Err(x as *mut T), - } - } - #[cfg(not(bootstrap))] // SAFETY: data races are prevented by atomic intrinsics. - unsafe { - atomic_compare_exchange(self.p.get(), current, new, success, failure) - } + unsafe { atomic_compare_exchange(self.p.get(), current, new, success, failure) } } /// Stores a value into the pointer if the current value is the same as the `current` value. @@ -1157,9 +1164,10 @@ pub fn compare_exchange( /// previous value. /// /// `compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory - /// ordering of this operation. The first describes the required ordering if the - /// operation succeeds while the second describes the required ordering when the - /// operation fails. Using [`Acquire`] as success ordering makes the store part + /// ordering of this operation. `success` describes the required ordering for the + /// read-modify-write operation that takes place if the comparison with `current` succeeds. + /// `failure` describes the required ordering for the load operation that takes place when + /// the comparison fails. Using [`Acquire`] as success ordering makes the store part /// of this operation [`Relaxed`], and using [`Release`] makes the successful load /// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`] /// and must be equivalent to or weaker than the success ordering. @@ -1193,29 +1201,11 @@ pub fn compare_exchange_weak( success: Ordering, failure: Ordering, ) -> Result<*mut T, *mut T> { - #[cfg(bootstrap)] - // SAFETY: data races are prevented by atomic intrinsics. - unsafe { - let res = atomic_compare_exchange_weak( - self.p.get() as *mut usize, - current as usize, - new as usize, - success, - failure, - ); - match res { - Ok(x) => Ok(x as *mut T), - Err(x) => Err(x as *mut T), - } - } - #[cfg(not(bootstrap))] // SAFETY: This intrinsic is unsafe because it operates on a raw pointer // but we know for sure that the pointer is valid (we just got it from // an `UnsafeCell` that we have by reference) and the atomic operation // itself allows us to safely mutate the `UnsafeCell` contents. - unsafe { - atomic_compare_exchange_weak(self.p.get(), current, new, success, failure) - } + unsafe { atomic_compare_exchange_weak(self.p.get(), current, new, success, failure) } } /// Fetches the value, and applies a function to it that returns an optional @@ -1382,12 +1372,9 @@ fn default() -> Self { #[$stable_from] impl From<$int_type> for $atomic_type { - doc_comment! { - concat!( -"Converts an `", stringify!($int_type), "` into an `", stringify!($atomic_type), "`."), - #[inline] - fn from(v: $int_type) -> Self { Self::new(v) } - } + #[doc = concat!("Converts an `", stringify!($int_type), "` into an `", stringify!($atomic_type), "`.")] + #[inline] + fn from(v: $int_type) -> Self { Self::new(v) } } #[$stable_debug] @@ -1402,721 +1389,703 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { unsafe impl Sync for $atomic_type {} impl $atomic_type { - doc_comment! { - concat!("Creates a new atomic integer. - -# Examples - -``` -", $extra_feature, "use std::sync::atomic::", stringify!($atomic_type), "; - -let atomic_forty_two = ", stringify!($atomic_type), "::new(42); -```"), - #[inline] - #[$stable] - #[$const_stable] - pub const fn new(v: $int_type) -> Self { - Self {v: UnsafeCell::new(v)} - } + /// Creates a new atomic integer. + /// + /// # Examples + /// + /// ``` + #[doc = concat!($extra_feature, "use std::sync::atomic::", stringify!($atomic_type), ";")] + /// + #[doc = concat!("let atomic_forty_two = ", stringify!($atomic_type), "::new(42);")] + /// ``` + #[inline] + #[$stable] + #[$const_stable] + pub const fn new(v: $int_type) -> Self { + Self {v: UnsafeCell::new(v)} } - doc_comment! { - concat!("Returns a mutable reference to the underlying integer. - -This is safe because the mutable reference guarantees that no other threads are -concurrently accessing the atomic data. - -# Examples - -``` -", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering}; - -let mut some_var = ", stringify!($atomic_type), "::new(10); -assert_eq!(*some_var.get_mut(), 10); -*some_var.get_mut() = 5; -assert_eq!(some_var.load(Ordering::SeqCst), 5); -```"), - #[inline] - #[$stable_access] - pub fn get_mut(&mut self) -> &mut $int_type { - self.v.get_mut() - } + /// Returns a mutable reference to the underlying integer. + /// + /// This is safe because the mutable reference guarantees that no other threads are + /// concurrently accessing the atomic data. + /// + /// # Examples + /// + /// ``` + #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")] + /// + #[doc = concat!("let mut some_var = ", stringify!($atomic_type), "::new(10);")] + /// assert_eq!(*some_var.get_mut(), 10); + /// *some_var.get_mut() = 5; + /// assert_eq!(some_var.load(Ordering::SeqCst), 5); + /// ``` + #[inline] + #[$stable_access] + pub fn get_mut(&mut self) -> &mut $int_type { + self.v.get_mut() } - doc_comment! { - concat!("Get atomic access to a `&mut ", stringify!($int_type), "`. - -", -if_not_8_bit! { - $int_type, - concat!( - "**Note:** This function is only available on targets where `", - stringify!($int_type), "` has an alignment of ", $align, " bytes." - ) -}, -" - -# Examples - -``` -#![feature(atomic_from_mut)] -", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering}; - -let mut some_int = 123; -let a = ", stringify!($atomic_type), "::from_mut(&mut some_int); -a.store(100, Ordering::Relaxed); -assert_eq!(some_int, 100); -``` - "), - #[inline] - #[$cfg_align] - #[unstable(feature = "atomic_from_mut", issue = "76314")] - pub fn from_mut(v: &mut $int_type) -> &Self { - use crate::mem::align_of; - let [] = [(); align_of::() - align_of::<$int_type>()]; - // SAFETY: - // - the mutable reference guarantees unique ownership. - // - the alignment of `$int_type` and `Self` is the - // same, as promised by $cfg_align and verified above. - unsafe { &*(v as *mut $int_type as *mut Self) } - } + #[doc = concat!("Get atomic access to a `&mut ", stringify!($int_type), "`.")] + /// + #[doc = if_not_8_bit! { + $int_type, + concat!( + "**Note:** This function is only available on targets where `", + stringify!($int_type), "` has an alignment of ", $align, " bytes." + ) + }] + /// + /// # Examples + /// + /// ``` + /// #![feature(atomic_from_mut)] + #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")] + /// + /// let mut some_int = 123; + #[doc = concat!("let a = ", stringify!($atomic_type), "::from_mut(&mut some_int);")] + /// a.store(100, Ordering::Relaxed); + /// assert_eq!(some_int, 100); + /// ``` + /// + #[inline] + #[$cfg_align] + #[unstable(feature = "atomic_from_mut", issue = "76314")] + pub fn from_mut(v: &mut $int_type) -> &Self { + use crate::mem::align_of; + let [] = [(); align_of::() - align_of::<$int_type>()]; + // SAFETY: + // - the mutable reference guarantees unique ownership. + // - the alignment of `$int_type` and `Self` is the + // same, as promised by $cfg_align and verified above. + unsafe { &*(v as *mut $int_type as *mut Self) } } - doc_comment! { - concat!("Consumes the atomic and returns the contained value. - -This is safe because passing `self` by value guarantees that no other threads are -concurrently accessing the atomic data. - -# Examples - -``` -", $extra_feature, "use std::sync::atomic::", stringify!($atomic_type), "; - -let some_var = ", stringify!($atomic_type), "::new(5); -assert_eq!(some_var.into_inner(), 5); -```"), - #[inline] - #[$stable_access] - #[rustc_const_unstable(feature = "const_cell_into_inner", issue = "78729")] - pub const fn into_inner(self) -> $int_type { - self.v.into_inner() - } + /// Consumes the atomic and returns the contained value. + /// + /// This is safe because passing `self` by value guarantees that no other threads are + /// concurrently accessing the atomic data. + /// + /// # Examples + /// + /// ``` + #[doc = concat!($extra_feature, "use std::sync::atomic::", stringify!($atomic_type), ";")] + /// + #[doc = concat!("let some_var = ", stringify!($atomic_type), "::new(5);")] + /// assert_eq!(some_var.into_inner(), 5); + /// ``` + #[inline] + #[$stable_access] + #[rustc_const_unstable(feature = "const_cell_into_inner", issue = "78729")] + pub const fn into_inner(self) -> $int_type { + self.v.into_inner() } - doc_comment! { - concat!("Loads a value from the atomic integer. - -`load` takes an [`Ordering`] argument which describes the memory ordering of this operation. -Possible values are [`SeqCst`], [`Acquire`] and [`Relaxed`]. - -# Panics - -Panics if `order` is [`Release`] or [`AcqRel`]. - -# Examples - -``` -", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering}; - -let some_var = ", stringify!($atomic_type), "::new(5); - -assert_eq!(some_var.load(Ordering::Relaxed), 5); -```"), - #[inline] - #[$stable] - pub fn load(&self, order: Ordering) -> $int_type { - // SAFETY: data races are prevented by atomic intrinsics. - unsafe { atomic_load(self.v.get(), order) } - } + /// Loads a value from the atomic integer. + /// + /// `load` takes an [`Ordering`] argument which describes the memory ordering of this operation. + /// Possible values are [`SeqCst`], [`Acquire`] and [`Relaxed`]. + /// + /// # Panics + /// + /// Panics if `order` is [`Release`] or [`AcqRel`]. + /// + /// # Examples + /// + /// ``` + #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")] + /// + #[doc = concat!("let some_var = ", stringify!($atomic_type), "::new(5);")] + /// + /// assert_eq!(some_var.load(Ordering::Relaxed), 5); + /// ``` + #[inline] + #[$stable] + pub fn load(&self, order: Ordering) -> $int_type { + // SAFETY: data races are prevented by atomic intrinsics. + unsafe { atomic_load(self.v.get(), order) } } - doc_comment! { - concat!("Stores a value into the atomic integer. - -`store` takes an [`Ordering`] argument which describes the memory ordering of this operation. - Possible values are [`SeqCst`], [`Release`] and [`Relaxed`]. - -# Panics - -Panics if `order` is [`Acquire`] or [`AcqRel`]. - -# Examples - -``` -", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering}; - -let some_var = ", stringify!($atomic_type), "::new(5); - -some_var.store(10, Ordering::Relaxed); -assert_eq!(some_var.load(Ordering::Relaxed), 10); -```"), - #[inline] - #[$stable] - pub fn store(&self, val: $int_type, order: Ordering) { - // SAFETY: data races are prevented by atomic intrinsics. - unsafe { atomic_store(self.v.get(), val, order); } - } + /// Stores a value into the atomic integer. + /// + /// `store` takes an [`Ordering`] argument which describes the memory ordering of this operation. + /// Possible values are [`SeqCst`], [`Release`] and [`Relaxed`]. + /// + /// # Panics + /// + /// Panics if `order` is [`Acquire`] or [`AcqRel`]. + /// + /// # Examples + /// + /// ``` + #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")] + /// + #[doc = concat!("let some_var = ", stringify!($atomic_type), "::new(5);")] + /// + /// some_var.store(10, Ordering::Relaxed); + /// assert_eq!(some_var.load(Ordering::Relaxed), 10); + /// ``` + #[inline] + #[$stable] + pub fn store(&self, val: $int_type, order: Ordering) { + // SAFETY: data races are prevented by atomic intrinsics. + unsafe { atomic_store(self.v.get(), val, order); } } - doc_comment! { - concat!("Stores a value into the atomic integer, returning the previous value. - -`swap` takes an [`Ordering`] argument which describes the memory ordering -of this operation. All ordering modes are possible. Note that using -[`Acquire`] makes the store part of this operation [`Relaxed`], and -using [`Release`] makes the load part [`Relaxed`]. - -**Note**: This method is only available on platforms that support atomic -operations on [`", $s_int_type, "`](", $int_ref, "). - -# Examples - -``` -", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering}; - -let some_var = ", stringify!($atomic_type), "::new(5); - -assert_eq!(some_var.swap(10, Ordering::Relaxed), 5); -```"), - #[inline] - #[$stable] - #[$cfg_cas] - pub fn swap(&self, val: $int_type, order: Ordering) -> $int_type { - // SAFETY: data races are prevented by atomic intrinsics. - unsafe { atomic_swap(self.v.get(), val, order) } - } + /// Stores a value into the atomic integer, returning the previous value. + /// + /// `swap` takes an [`Ordering`] argument which describes the memory ordering + /// of this operation. All ordering modes are possible. Note that using + /// [`Acquire`] makes the store part of this operation [`Relaxed`], and + /// using [`Release`] makes the load part [`Relaxed`]. + /// + /// **Note**: This method is only available on platforms that support atomic operations on + #[doc = concat!("[`", $s_int_type, "`](", $int_ref, ").")] + /// + /// # Examples + /// + /// ``` + #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")] + /// + #[doc = concat!("let some_var = ", stringify!($atomic_type), "::new(5);")] + /// + /// assert_eq!(some_var.swap(10, Ordering::Relaxed), 5); + /// ``` + #[inline] + #[$stable] + #[$cfg_cas] + pub fn swap(&self, val: $int_type, order: Ordering) -> $int_type { + // SAFETY: data races are prevented by atomic intrinsics. + unsafe { atomic_swap(self.v.get(), val, order) } } - doc_comment! { - concat!("Stores a value into the atomic integer if the current value is the same as -the `current` value. - -The return value is always the previous value. If it is equal to `current`, then the -value was updated. - -`compare_and_swap` also takes an [`Ordering`] argument which describes the memory -ordering of this operation. Notice that even when using [`AcqRel`], the operation -might fail and hence just perform an `Acquire` load, but not have `Release` semantics. -Using [`Acquire`] makes the store part of this operation [`Relaxed`] if it -happens, and using [`Release`] makes the load part [`Relaxed`]. - -**Note**: This method is only available on platforms that support atomic -operations on [`", $s_int_type, "`](", $int_ref, "). - -# Examples - -``` -", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering}; - -let some_var = ", stringify!($atomic_type), "::new(5); - -assert_eq!(some_var.compare_and_swap(5, 10, Ordering::Relaxed), 5); -assert_eq!(some_var.load(Ordering::Relaxed), 10); - -assert_eq!(some_var.compare_and_swap(6, 12, Ordering::Relaxed), 10); -assert_eq!(some_var.load(Ordering::Relaxed), 10); -```"), - #[inline] - #[$stable] - #[$cfg_cas] - pub fn compare_and_swap(&self, - current: $int_type, - new: $int_type, - order: Ordering) -> $int_type { - match self.compare_exchange(current, - new, - order, - strongest_failure_ordering(order)) { - Ok(x) => x, - Err(x) => x, - } + /// Stores a value into the atomic integer if the current value is the same as + /// the `current` value. + /// + /// The return value is always the previous value. If it is equal to `current`, then the + /// value was updated. + /// + /// `compare_and_swap` also takes an [`Ordering`] argument which describes the memory + /// ordering of this operation. Notice that even when using [`AcqRel`], the operation + /// might fail and hence just perform an `Acquire` load, but not have `Release` semantics. + /// Using [`Acquire`] makes the store part of this operation [`Relaxed`] if it + /// happens, and using [`Release`] makes the load part [`Relaxed`]. + /// + /// **Note**: This method is only available on platforms that support atomic operations on + #[doc = concat!("[`", $s_int_type, "`](", $int_ref, ").")] + /// + /// # Migrating to `compare_exchange` and `compare_exchange_weak` + /// + /// `compare_and_swap` is equivalent to `compare_exchange` with the following mapping for + /// memory orderings: + /// + /// Original | Success | Failure + /// -------- | ------- | ------- + /// Relaxed | Relaxed | Relaxed + /// Acquire | Acquire | Acquire + /// Release | Release | Relaxed + /// AcqRel | AcqRel | Acquire + /// SeqCst | SeqCst | SeqCst + /// + /// `compare_exchange_weak` is allowed to fail spuriously even when the comparison succeeds, + /// which allows the compiler to generate better assembly code when the compare and swap + /// is used in a loop. + /// + /// # Examples + /// + /// ``` + #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")] + /// + #[doc = concat!("let some_var = ", stringify!($atomic_type), "::new(5);")] + /// + /// assert_eq!(some_var.compare_and_swap(5, 10, Ordering::Relaxed), 5); + /// assert_eq!(some_var.load(Ordering::Relaxed), 10); + /// + /// assert_eq!(some_var.compare_and_swap(6, 12, Ordering::Relaxed), 10); + /// assert_eq!(some_var.load(Ordering::Relaxed), 10); + /// ``` + #[inline] + #[$stable] + #[rustc_deprecated( + since = "1.50.0", + reason = "Use `compare_exchange` or `compare_exchange_weak` instead") + ] + #[$cfg_cas] + pub fn compare_and_swap(&self, + current: $int_type, + new: $int_type, + order: Ordering) -> $int_type { + match self.compare_exchange(current, + new, + order, + strongest_failure_ordering(order)) { + Ok(x) => x, + Err(x) => x, } } - doc_comment! { - concat!("Stores a value into the atomic integer if the current value is the same as -the `current` value. - -The return value is a result indicating whether the new value was written and -containing the previous value. On success this value is guaranteed to be equal to -`current`. - -`compare_exchange` takes two [`Ordering`] arguments to describe the memory -ordering of this operation. The first describes the required ordering if the -operation succeeds while the second describes the required ordering when the -operation fails. Using [`Acquire`] as success ordering makes the store part -of this operation [`Relaxed`], and using [`Release`] makes the successful load -[`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`] -and must be equivalent to or weaker than the success ordering. - -**Note**: This method is only available on platforms that support atomic -operations on [`", $s_int_type, "`](", $int_ref, "). - -# Examples - -``` -", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering}; - -let some_var = ", stringify!($atomic_type), "::new(5); - -assert_eq!(some_var.compare_exchange(5, 10, - Ordering::Acquire, - Ordering::Relaxed), - Ok(5)); -assert_eq!(some_var.load(Ordering::Relaxed), 10); - -assert_eq!(some_var.compare_exchange(6, 12, - Ordering::SeqCst, - Ordering::Acquire), - Err(10)); -assert_eq!(some_var.load(Ordering::Relaxed), 10); -```"), - #[inline] - #[$stable_cxchg] - #[$cfg_cas] - pub fn compare_exchange(&self, - current: $int_type, - new: $int_type, - success: Ordering, - failure: Ordering) -> Result<$int_type, $int_type> { - // SAFETY: data races are prevented by atomic intrinsics. - unsafe { atomic_compare_exchange(self.v.get(), current, new, success, failure) } - } + /// Stores a value into the atomic integer if the current value is the same as + /// the `current` value. + /// + /// The return value is a result indicating whether the new value was written and + /// containing the previous value. On success this value is guaranteed to be equal to + /// `current`. + /// + /// `compare_exchange` takes two [`Ordering`] arguments to describe the memory + /// ordering of this operation. `success` describes the required ordering for the + /// read-modify-write operation that takes place if the comparison with `current` succeeds. + /// `failure` describes the required ordering for the load operation that takes place when + /// the comparison fails. Using [`Acquire`] as success ordering makes the store part + /// of this operation [`Relaxed`], and using [`Release`] makes the successful load + /// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`] + /// and must be equivalent to or weaker than the success ordering. + /// + /// **Note**: This method is only available on platforms that support atomic operations on + #[doc = concat!("[`", $s_int_type, "`](", $int_ref, ").")] + /// + /// # Examples + /// + /// ``` + #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")] + /// + #[doc = concat!("let some_var = ", stringify!($atomic_type), "::new(5);")] + /// + /// assert_eq!(some_var.compare_exchange(5, 10, + /// Ordering::Acquire, + /// Ordering::Relaxed), + /// Ok(5)); + /// assert_eq!(some_var.load(Ordering::Relaxed), 10); + /// + /// assert_eq!(some_var.compare_exchange(6, 12, + /// Ordering::SeqCst, + /// Ordering::Acquire), + /// Err(10)); + /// assert_eq!(some_var.load(Ordering::Relaxed), 10); + /// ``` + #[inline] + #[$stable_cxchg] + #[$cfg_cas] + pub fn compare_exchange(&self, + current: $int_type, + new: $int_type, + success: Ordering, + failure: Ordering) -> Result<$int_type, $int_type> { + // SAFETY: data races are prevented by atomic intrinsics. + unsafe { atomic_compare_exchange(self.v.get(), current, new, success, failure) } } - doc_comment! { - concat!("Stores a value into the atomic integer if the current value is the same as -the `current` value. - -Unlike [`", stringify!($atomic_type), "::compare_exchange`], this function is allowed to spuriously fail even -when the comparison succeeds, which can result in more efficient code on some -platforms. The return value is a result indicating whether the new value was -written and containing the previous value. - -`compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory -ordering of this operation. The first describes the required ordering if the -operation succeeds while the second describes the required ordering when the -operation fails. Using [`Acquire`] as success ordering makes the store part -of this operation [`Relaxed`], and using [`Release`] makes the successful load -[`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`] -and must be equivalent to or weaker than the success ordering. - -**Note**: This method is only available on platforms that support atomic -operations on [`", $s_int_type, "`](", $int_ref, "). - -# Examples - -``` -", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering}; - -let val = ", stringify!($atomic_type), "::new(4); - -let mut old = val.load(Ordering::Relaxed); -loop { - let new = old * 2; - match val.compare_exchange_weak(old, new, Ordering::SeqCst, Ordering::Relaxed) { - Ok(_) => break, - Err(x) => old = x, - } -} -```"), - #[inline] - #[$stable_cxchg] - #[$cfg_cas] - pub fn compare_exchange_weak(&self, - current: $int_type, - new: $int_type, - success: Ordering, - failure: Ordering) -> Result<$int_type, $int_type> { - // SAFETY: data races are prevented by atomic intrinsics. - unsafe { - atomic_compare_exchange_weak(self.v.get(), current, new, success, failure) - } + /// Stores a value into the atomic integer if the current value is the same as + /// the `current` value. + /// + #[doc = concat!("Unlike [`", stringify!($atomic_type), "::compare_exchange`],")] + /// this function is allowed to spuriously fail even + /// when the comparison succeeds, which can result in more efficient code on some + /// platforms. The return value is a result indicating whether the new value was + /// written and containing the previous value. + /// + /// `compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory + /// ordering of this operation. `success` describes the required ordering for the + /// read-modify-write operation that takes place if the comparison with `current` succeeds. + /// `failure` describes the required ordering for the load operation that takes place when + /// the comparison fails. Using [`Acquire`] as success ordering makes the store part + /// of this operation [`Relaxed`], and using [`Release`] makes the successful load + /// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`] + /// and must be equivalent to or weaker than the success ordering. + /// + /// **Note**: This method is only available on platforms that support atomic operations on + #[doc = concat!("[`", $s_int_type, "`](", $int_ref, ").")] + /// + /// # Examples + /// + /// ``` + #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")] + /// + #[doc = concat!("let val = ", stringify!($atomic_type), "::new(4);")] + /// + /// let mut old = val.load(Ordering::Relaxed); + /// loop { + /// let new = old * 2; + /// match val.compare_exchange_weak(old, new, Ordering::SeqCst, Ordering::Relaxed) { + /// Ok(_) => break, + /// Err(x) => old = x, + /// } + /// } + /// ``` + #[inline] + #[$stable_cxchg] + #[$cfg_cas] + pub fn compare_exchange_weak(&self, + current: $int_type, + new: $int_type, + success: Ordering, + failure: Ordering) -> Result<$int_type, $int_type> { + // SAFETY: data races are prevented by atomic intrinsics. + unsafe { + atomic_compare_exchange_weak(self.v.get(), current, new, success, failure) } } - doc_comment! { - concat!("Adds to the current value, returning the previous value. - -This operation wraps around on overflow. - -`fetch_add` takes an [`Ordering`] argument which describes the memory ordering -of this operation. All ordering modes are possible. Note that using -[`Acquire`] makes the store part of this operation [`Relaxed`], and -using [`Release`] makes the load part [`Relaxed`]. - -**Note**: This method is only available on platforms that support atomic -operations on [`", $s_int_type, "`](", $int_ref, "). - -# Examples - -``` -", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering}; - -let foo = ", stringify!($atomic_type), "::new(0); -assert_eq!(foo.fetch_add(10, Ordering::SeqCst), 0); -assert_eq!(foo.load(Ordering::SeqCst), 10); -```"), - #[inline] - #[$stable] - #[$cfg_cas] - pub fn fetch_add(&self, val: $int_type, order: Ordering) -> $int_type { - // SAFETY: data races are prevented by atomic intrinsics. - unsafe { atomic_add(self.v.get(), val, order) } - } + /// Adds to the current value, returning the previous value. + /// + /// This operation wraps around on overflow. + /// + /// `fetch_add` takes an [`Ordering`] argument which describes the memory ordering + /// of this operation. All ordering modes are possible. Note that using + /// [`Acquire`] makes the store part of this operation [`Relaxed`], and + /// using [`Release`] makes the load part [`Relaxed`]. + /// + /// **Note**: This method is only available on platforms that support atomic operations on + #[doc = concat!("[`", $s_int_type, "`](", $int_ref, ").")] + /// + /// # Examples + /// + /// ``` + #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")] + /// + #[doc = concat!("let foo = ", stringify!($atomic_type), "::new(0);")] + /// assert_eq!(foo.fetch_add(10, Ordering::SeqCst), 0); + /// assert_eq!(foo.load(Ordering::SeqCst), 10); + /// ``` + #[inline] + #[$stable] + #[$cfg_cas] + pub fn fetch_add(&self, val: $int_type, order: Ordering) -> $int_type { + // SAFETY: data races are prevented by atomic intrinsics. + unsafe { atomic_add(self.v.get(), val, order) } } - doc_comment! { - concat!("Subtracts from the current value, returning the previous value. - -This operation wraps around on overflow. - -`fetch_sub` takes an [`Ordering`] argument which describes the memory ordering -of this operation. All ordering modes are possible. Note that using -[`Acquire`] makes the store part of this operation [`Relaxed`], and -using [`Release`] makes the load part [`Relaxed`]. - -**Note**: This method is only available on platforms that support atomic -operations on [`", $s_int_type, "`](", $int_ref, "). - -# Examples - -``` -", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering}; - -let foo = ", stringify!($atomic_type), "::new(20); -assert_eq!(foo.fetch_sub(10, Ordering::SeqCst), 20); -assert_eq!(foo.load(Ordering::SeqCst), 10); -```"), - #[inline] - #[$stable] - #[$cfg_cas] - pub fn fetch_sub(&self, val: $int_type, order: Ordering) -> $int_type { - // SAFETY: data races are prevented by atomic intrinsics. - unsafe { atomic_sub(self.v.get(), val, order) } - } + /// Subtracts from the current value, returning the previous value. + /// + /// This operation wraps around on overflow. + /// + /// `fetch_sub` takes an [`Ordering`] argument which describes the memory ordering + /// of this operation. All ordering modes are possible. Note that using + /// [`Acquire`] makes the store part of this operation [`Relaxed`], and + /// using [`Release`] makes the load part [`Relaxed`]. + /// + /// **Note**: This method is only available on platforms that support atomic operations on + #[doc = concat!("[`", $s_int_type, "`](", $int_ref, ").")] + /// + /// # Examples + /// + /// ``` + #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")] + /// + #[doc = concat!("let foo = ", stringify!($atomic_type), "::new(20);")] + /// assert_eq!(foo.fetch_sub(10, Ordering::SeqCst), 20); + /// assert_eq!(foo.load(Ordering::SeqCst), 10); + /// ``` + #[inline] + #[$stable] + #[$cfg_cas] + pub fn fetch_sub(&self, val: $int_type, order: Ordering) -> $int_type { + // SAFETY: data races are prevented by atomic intrinsics. + unsafe { atomic_sub(self.v.get(), val, order) } } - doc_comment! { - concat!("Bitwise \"and\" with the current value. - -Performs a bitwise \"and\" operation on the current value and the argument `val`, and -sets the new value to the result. - -Returns the previous value. - -`fetch_and` takes an [`Ordering`] argument which describes the memory ordering -of this operation. All ordering modes are possible. Note that using -[`Acquire`] makes the store part of this operation [`Relaxed`], and -using [`Release`] makes the load part [`Relaxed`]. - -**Note**: This method is only available on platforms that support atomic -operations on [`", $s_int_type, "`](", $int_ref, "). - -# Examples - -``` -", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering}; - -let foo = ", stringify!($atomic_type), "::new(0b101101); -assert_eq!(foo.fetch_and(0b110011, Ordering::SeqCst), 0b101101); -assert_eq!(foo.load(Ordering::SeqCst), 0b100001); -```"), - #[inline] - #[$stable] - #[$cfg_cas] - pub fn fetch_and(&self, val: $int_type, order: Ordering) -> $int_type { - // SAFETY: data races are prevented by atomic intrinsics. - unsafe { atomic_and(self.v.get(), val, order) } - } + /// Bitwise "and" with the current value. + /// + /// Performs a bitwise "and" operation on the current value and the argument `val`, and + /// sets the new value to the result. + /// + /// Returns the previous value. + /// + /// `fetch_and` takes an [`Ordering`] argument which describes the memory ordering + /// of this operation. All ordering modes are possible. Note that using + /// [`Acquire`] makes the store part of this operation [`Relaxed`], and + /// using [`Release`] makes the load part [`Relaxed`]. + /// + /// **Note**: This method is only available on platforms that support atomic operations on + #[doc = concat!("[`", $s_int_type, "`](", $int_ref, ").")] + /// + /// # Examples + /// + /// ``` + #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")] + /// + #[doc = concat!("let foo = ", stringify!($atomic_type), "::new(0b101101);")] + /// assert_eq!(foo.fetch_and(0b110011, Ordering::SeqCst), 0b101101); + /// assert_eq!(foo.load(Ordering::SeqCst), 0b100001); + /// ``` + #[inline] + #[$stable] + #[$cfg_cas] + pub fn fetch_and(&self, val: $int_type, order: Ordering) -> $int_type { + // SAFETY: data races are prevented by atomic intrinsics. + unsafe { atomic_and(self.v.get(), val, order) } } - doc_comment! { - concat!("Bitwise \"nand\" with the current value. - -Performs a bitwise \"nand\" operation on the current value and the argument `val`, and -sets the new value to the result. - -Returns the previous value. - -`fetch_nand` takes an [`Ordering`] argument which describes the memory ordering -of this operation. All ordering modes are possible. Note that using -[`Acquire`] makes the store part of this operation [`Relaxed`], and -using [`Release`] makes the load part [`Relaxed`]. - -**Note**: This method is only available on platforms that support atomic -operations on [`", $s_int_type, "`](", $int_ref, "). - -# Examples - -``` -", $extra_feature, " -use std::sync::atomic::{", stringify!($atomic_type), ", Ordering}; - -let foo = ", stringify!($atomic_type), "::new(0x13); -assert_eq!(foo.fetch_nand(0x31, Ordering::SeqCst), 0x13); -assert_eq!(foo.load(Ordering::SeqCst), !(0x13 & 0x31)); -```"), - #[inline] - #[$stable_nand] - #[$cfg_cas] - pub fn fetch_nand(&self, val: $int_type, order: Ordering) -> $int_type { - // SAFETY: data races are prevented by atomic intrinsics. - unsafe { atomic_nand(self.v.get(), val, order) } - } + /// Bitwise "nand" with the current value. + /// + /// Performs a bitwise "nand" operation on the current value and the argument `val`, and + /// sets the new value to the result. + /// + /// Returns the previous value. + /// + /// `fetch_nand` takes an [`Ordering`] argument which describes the memory ordering + /// of this operation. All ordering modes are possible. Note that using + /// [`Acquire`] makes the store part of this operation [`Relaxed`], and + /// using [`Release`] makes the load part [`Relaxed`]. + /// + /// **Note**: This method is only available on platforms that support atomic operations on + #[doc = concat!("[`", $s_int_type, "`](", $int_ref, ").")] + /// + /// # Examples + /// + /// ``` + #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")] + /// + #[doc = concat!("let foo = ", stringify!($atomic_type), "::new(0x13);")] + /// assert_eq!(foo.fetch_nand(0x31, Ordering::SeqCst), 0x13); + /// assert_eq!(foo.load(Ordering::SeqCst), !(0x13 & 0x31)); + /// ``` + #[inline] + #[$stable_nand] + #[$cfg_cas] + pub fn fetch_nand(&self, val: $int_type, order: Ordering) -> $int_type { + // SAFETY: data races are prevented by atomic intrinsics. + unsafe { atomic_nand(self.v.get(), val, order) } } - doc_comment! { - concat!("Bitwise \"or\" with the current value. - -Performs a bitwise \"or\" operation on the current value and the argument `val`, and -sets the new value to the result. - -Returns the previous value. - -`fetch_or` takes an [`Ordering`] argument which describes the memory ordering -of this operation. All ordering modes are possible. Note that using -[`Acquire`] makes the store part of this operation [`Relaxed`], and -using [`Release`] makes the load part [`Relaxed`]. - -**Note**: This method is only available on platforms that support atomic -operations on [`", $s_int_type, "`](", $int_ref, "). - -# Examples - -``` -", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering}; - -let foo = ", stringify!($atomic_type), "::new(0b101101); -assert_eq!(foo.fetch_or(0b110011, Ordering::SeqCst), 0b101101); -assert_eq!(foo.load(Ordering::SeqCst), 0b111111); -```"), - #[inline] - #[$stable] - #[$cfg_cas] - pub fn fetch_or(&self, val: $int_type, order: Ordering) -> $int_type { - // SAFETY: data races are prevented by atomic intrinsics. - unsafe { atomic_or(self.v.get(), val, order) } - } + /// Bitwise "or" with the current value. + /// + /// Performs a bitwise "or" operation on the current value and the argument `val`, and + /// sets the new value to the result. + /// + /// Returns the previous value. + /// + /// `fetch_or` takes an [`Ordering`] argument which describes the memory ordering + /// of this operation. All ordering modes are possible. Note that using + /// [`Acquire`] makes the store part of this operation [`Relaxed`], and + /// using [`Release`] makes the load part [`Relaxed`]. + /// + /// **Note**: This method is only available on platforms that support atomic operations on + #[doc = concat!("[`", $s_int_type, "`](", $int_ref, ").")] + /// + /// # Examples + /// + /// ``` + #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")] + /// + #[doc = concat!("let foo = ", stringify!($atomic_type), "::new(0b101101);")] + /// assert_eq!(foo.fetch_or(0b110011, Ordering::SeqCst), 0b101101); + /// assert_eq!(foo.load(Ordering::SeqCst), 0b111111); + /// ``` + #[inline] + #[$stable] + #[$cfg_cas] + pub fn fetch_or(&self, val: $int_type, order: Ordering) -> $int_type { + // SAFETY: data races are prevented by atomic intrinsics. + unsafe { atomic_or(self.v.get(), val, order) } } - doc_comment! { - concat!("Bitwise \"xor\" with the current value. - -Performs a bitwise \"xor\" operation on the current value and the argument `val`, and -sets the new value to the result. - -Returns the previous value. - -`fetch_xor` takes an [`Ordering`] argument which describes the memory ordering -of this operation. All ordering modes are possible. Note that using -[`Acquire`] makes the store part of this operation [`Relaxed`], and -using [`Release`] makes the load part [`Relaxed`]. - -**Note**: This method is only available on platforms that support atomic -operations on [`", $s_int_type, "`](", $int_ref, "). - -# Examples - -``` -", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering}; - -let foo = ", stringify!($atomic_type), "::new(0b101101); -assert_eq!(foo.fetch_xor(0b110011, Ordering::SeqCst), 0b101101); -assert_eq!(foo.load(Ordering::SeqCst), 0b011110); -```"), - #[inline] - #[$stable] - #[$cfg_cas] - pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type { - // SAFETY: data races are prevented by atomic intrinsics. - unsafe { atomic_xor(self.v.get(), val, order) } - } + /// Bitwise "xor" with the current value. + /// + /// Performs a bitwise "xor" operation on the current value and the argument `val`, and + /// sets the new value to the result. + /// + /// Returns the previous value. + /// + /// `fetch_xor` takes an [`Ordering`] argument which describes the memory ordering + /// of this operation. All ordering modes are possible. Note that using + /// [`Acquire`] makes the store part of this operation [`Relaxed`], and + /// using [`Release`] makes the load part [`Relaxed`]. + /// + /// **Note**: This method is only available on platforms that support atomic operations on + #[doc = concat!("[`", $s_int_type, "`](", $int_ref, ").")] + /// + /// # Examples + /// + /// ``` + #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")] + /// + #[doc = concat!("let foo = ", stringify!($atomic_type), "::new(0b101101);")] + /// assert_eq!(foo.fetch_xor(0b110011, Ordering::SeqCst), 0b101101); + /// assert_eq!(foo.load(Ordering::SeqCst), 0b011110); + /// ``` + #[inline] + #[$stable] + #[$cfg_cas] + pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type { + // SAFETY: data races are prevented by atomic intrinsics. + unsafe { atomic_xor(self.v.get(), val, order) } } - doc_comment! { - concat!("Fetches the value, and applies a function to it that returns an optional -new value. Returns a `Result` of `Ok(previous_value)` if the function returned `Some(_)`, else -`Err(previous_value)`. - -Note: This may call the function multiple times if the value has been changed from other threads in -the meantime, as long as the function returns `Some(_)`, but the function will have been applied -only once to the stored value. - -`fetch_update` takes two [`Ordering`] arguments to describe the memory ordering of this operation. -The first describes the required ordering for when the operation finally succeeds while the second -describes the required ordering for loads. These correspond to the success and failure orderings of -[`", stringify!($atomic_type), "::compare_exchange`] respectively. - -Using [`Acquire`] as success ordering makes the store part -of this operation [`Relaxed`], and using [`Release`] makes the final successful load -[`Relaxed`]. The (failed) load ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`] -and must be equivalent to or weaker than the success ordering. - -**Note**: This method is only available on platforms that support atomic -operations on [`", $s_int_type, "`](", $int_ref, "). - -# Examples - -```rust -", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering}; - -let x = ", stringify!($atomic_type), "::new(7); -assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |_| None), Err(7)); -assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(x + 1)), Ok(7)); -assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(x + 1)), Ok(8)); -assert_eq!(x.load(Ordering::SeqCst), 9); -```"), - #[inline] - #[stable(feature = "no_more_cas", since = "1.45.0")] - #[$cfg_cas] - pub fn fetch_update(&self, - set_order: Ordering, - fetch_order: Ordering, - mut f: F) -> Result<$int_type, $int_type> - where F: FnMut($int_type) -> Option<$int_type> { - let mut prev = self.load(fetch_order); - while let Some(next) = f(prev) { - match self.compare_exchange_weak(prev, next, set_order, fetch_order) { - x @ Ok(_) => return x, - Err(next_prev) => prev = next_prev - } + /// Fetches the value, and applies a function to it that returns an optional + /// new value. Returns a `Result` of `Ok(previous_value)` if the function returned `Some(_)`, else + /// `Err(previous_value)`. + /// + /// Note: This may call the function multiple times if the value has been changed from other threads in + /// the meantime, as long as the function returns `Some(_)`, but the function will have been applied + /// only once to the stored value. + /// + /// `fetch_update` takes two [`Ordering`] arguments to describe the memory ordering of this operation. + /// The first describes the required ordering for when the operation finally succeeds while the second + /// describes the required ordering for loads. These correspond to the success and failure orderings of + #[doc = concat!("[`", stringify!($atomic_type), "::compare_exchange`]")] + /// respectively. + /// + /// Using [`Acquire`] as success ordering makes the store part + /// of this operation [`Relaxed`], and using [`Release`] makes the final successful load + /// [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`] + /// and must be equivalent to or weaker than the success ordering. + /// + /// **Note**: This method is only available on platforms that support atomic operations on + #[doc = concat!("[`", $s_int_type, "`](", $int_ref, ").")] + /// + /// # Examples + /// + /// ```rust + #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")] + /// + #[doc = concat!("let x = ", stringify!($atomic_type), "::new(7);")] + /// assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |_| None), Err(7)); + /// assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(x + 1)), Ok(7)); + /// assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(x + 1)), Ok(8)); + /// assert_eq!(x.load(Ordering::SeqCst), 9); + /// ``` + #[inline] + #[stable(feature = "no_more_cas", since = "1.45.0")] + #[$cfg_cas] + pub fn fetch_update(&self, + set_order: Ordering, + fetch_order: Ordering, + mut f: F) -> Result<$int_type, $int_type> + where F: FnMut($int_type) -> Option<$int_type> { + let mut prev = self.load(fetch_order); + while let Some(next) = f(prev) { + match self.compare_exchange_weak(prev, next, set_order, fetch_order) { + x @ Ok(_) => return x, + Err(next_prev) => prev = next_prev } - Err(prev) } + Err(prev) } - doc_comment! { - concat!("Maximum with the current value. - -Finds the maximum of the current value and the argument `val`, and -sets the new value to the result. - -Returns the previous value. - -`fetch_max` takes an [`Ordering`] argument which describes the memory ordering -of this operation. All ordering modes are possible. Note that using -[`Acquire`] makes the store part of this operation [`Relaxed`], and -using [`Release`] makes the load part [`Relaxed`]. - -**Note**: This method is only available on platforms that support atomic -operations on [`", $s_int_type, "`](", $int_ref, "). - -# Examples - -``` -", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering}; - -let foo = ", stringify!($atomic_type), "::new(23); -assert_eq!(foo.fetch_max(42, Ordering::SeqCst), 23); -assert_eq!(foo.load(Ordering::SeqCst), 42); -``` - -If you want to obtain the maximum value in one step, you can use the following: - -``` -", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering}; - -let foo = ", stringify!($atomic_type), "::new(23); -let bar = 42; -let max_foo = foo.fetch_max(bar, Ordering::SeqCst).max(bar); -assert!(max_foo == 42); -```"), - #[inline] - #[stable(feature = "atomic_min_max", since = "1.45.0")] - #[$cfg_cas] - pub fn fetch_max(&self, val: $int_type, order: Ordering) -> $int_type { - // SAFETY: data races are prevented by atomic intrinsics. - unsafe { $max_fn(self.v.get(), val, order) } - } + /// Maximum with the current value. + /// + /// Finds the maximum of the current value and the argument `val`, and + /// sets the new value to the result. + /// + /// Returns the previous value. + /// + /// `fetch_max` takes an [`Ordering`] argument which describes the memory ordering + /// of this operation. All ordering modes are possible. Note that using + /// [`Acquire`] makes the store part of this operation [`Relaxed`], and + /// using [`Release`] makes the load part [`Relaxed`]. + /// + /// **Note**: This method is only available on platforms that support atomic operations on + #[doc = concat!("[`", $s_int_type, "`](", $int_ref, ").")] + /// + /// # Examples + /// + /// ``` + #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")] + /// + #[doc = concat!("let foo = ", stringify!($atomic_type), "::new(23);")] + /// assert_eq!(foo.fetch_max(42, Ordering::SeqCst), 23); + /// assert_eq!(foo.load(Ordering::SeqCst), 42); + /// ``` + /// + /// If you want to obtain the maximum value in one step, you can use the following: + /// + /// ``` + #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")] + /// + #[doc = concat!("let foo = ", stringify!($atomic_type), "::new(23);")] + /// let bar = 42; + /// let max_foo = foo.fetch_max(bar, Ordering::SeqCst).max(bar); + /// assert!(max_foo == 42); + /// ``` + #[inline] + #[stable(feature = "atomic_min_max", since = "1.45.0")] + #[$cfg_cas] + pub fn fetch_max(&self, val: $int_type, order: Ordering) -> $int_type { + // SAFETY: data races are prevented by atomic intrinsics. + unsafe { $max_fn(self.v.get(), val, order) } } - doc_comment! { - concat!("Minimum with the current value. - -Finds the minimum of the current value and the argument `val`, and -sets the new value to the result. - -Returns the previous value. - -`fetch_min` takes an [`Ordering`] argument which describes the memory ordering -of this operation. All ordering modes are possible. Note that using -[`Acquire`] makes the store part of this operation [`Relaxed`], and -using [`Release`] makes the load part [`Relaxed`]. - -**Note**: This method is only available on platforms that support atomic -operations on [`", $s_int_type, "`](", $int_ref, "). - -# Examples - -``` -", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering}; - -let foo = ", stringify!($atomic_type), "::new(23); -assert_eq!(foo.fetch_min(42, Ordering::Relaxed), 23); -assert_eq!(foo.load(Ordering::Relaxed), 23); -assert_eq!(foo.fetch_min(22, Ordering::Relaxed), 23); -assert_eq!(foo.load(Ordering::Relaxed), 22); -``` - -If you want to obtain the minimum value in one step, you can use the following: - -``` -", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering}; - -let foo = ", stringify!($atomic_type), "::new(23); -let bar = 12; -let min_foo = foo.fetch_min(bar, Ordering::SeqCst).min(bar); -assert_eq!(min_foo, 12); -```"), - #[inline] - #[stable(feature = "atomic_min_max", since = "1.45.0")] - #[$cfg_cas] - pub fn fetch_min(&self, val: $int_type, order: Ordering) -> $int_type { - // SAFETY: data races are prevented by atomic intrinsics. - unsafe { $min_fn(self.v.get(), val, order) } - } + /// Minimum with the current value. + /// + /// Finds the minimum of the current value and the argument `val`, and + /// sets the new value to the result. + /// + /// Returns the previous value. + /// + /// `fetch_min` takes an [`Ordering`] argument which describes the memory ordering + /// of this operation. All ordering modes are possible. Note that using + /// [`Acquire`] makes the store part of this operation [`Relaxed`], and + /// using [`Release`] makes the load part [`Relaxed`]. + /// + /// **Note**: This method is only available on platforms that support atomic operations on + #[doc = concat!("[`", $s_int_type, "`](", $int_ref, ").")] + /// + /// # Examples + /// + /// ``` + #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")] + /// + #[doc = concat!("let foo = ", stringify!($atomic_type), "::new(23);")] + /// assert_eq!(foo.fetch_min(42, Ordering::Relaxed), 23); + /// assert_eq!(foo.load(Ordering::Relaxed), 23); + /// assert_eq!(foo.fetch_min(22, Ordering::Relaxed), 23); + /// assert_eq!(foo.load(Ordering::Relaxed), 22); + /// ``` + /// + /// If you want to obtain the minimum value in one step, you can use the following: + /// + /// ``` + #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")] + /// + #[doc = concat!("let foo = ", stringify!($atomic_type), "::new(23);")] + /// let bar = 12; + /// let min_foo = foo.fetch_min(bar, Ordering::SeqCst).min(bar); + /// assert_eq!(min_foo, 12); + /// ``` + #[inline] + #[stable(feature = "atomic_min_max", since = "1.45.0")] + #[$cfg_cas] + pub fn fetch_min(&self, val: $int_type, order: Ordering) -> $int_type { + // SAFETY: data races are prevented by atomic intrinsics. + unsafe { $min_fn(self.v.get(), val, order) } } - doc_comment! { - concat!("Returns a mutable pointer to the underlying integer. - -Doing non-atomic reads and writes on the resulting integer can be a data race. -This method is mostly useful for FFI, where the function signature may use -`*mut ", stringify!($int_type), "` instead of `&", stringify!($atomic_type), "`. - -Returning an `*mut` pointer from a shared reference to this atomic is safe because the -atomic types work with interior mutability. All modifications of an atomic change the value -through a shared reference, and can do so safely as long as they use atomic operations. Any -use of the returned raw pointer requires an `unsafe` block and still has to uphold the same -restriction: operations on it must be atomic. - -# Examples - -```ignore (extern-declaration) -# fn main() { -", $extra_feature, "use std::sync::atomic::", stringify!($atomic_type), "; - -extern { - fn my_atomic_op(arg: *mut ", stringify!($int_type), "); -} - -let mut atomic = ", stringify!($atomic_type), "::new(1); -", -// SAFETY: Safe as long as `my_atomic_op` is atomic. -"unsafe { - my_atomic_op(atomic.as_mut_ptr()); -} -# } -```"), - #[inline] - #[unstable(feature = "atomic_mut_ptr", - reason = "recently added", - issue = "66893")] - pub fn as_mut_ptr(&self) -> *mut $int_type { - self.v.get() - } + /// Returns a mutable pointer to the underlying integer. + /// + /// Doing non-atomic reads and writes on the resulting integer can be a data race. + /// This method is mostly useful for FFI, where the function signature may use + #[doc = concat!("`*mut ", stringify!($int_type), "` instead of `&", stringify!($atomic_type), "`.")] + /// + /// Returning an `*mut` pointer from a shared reference to this atomic is safe because the + /// atomic types work with interior mutability. All modifications of an atomic change the value + /// through a shared reference, and can do so safely as long as they use atomic operations. Any + /// use of the returned raw pointer requires an `unsafe` block and still has to uphold the same + /// restriction: operations on it must be atomic. + /// + /// # Examples + /// + /// ```ignore (extern-declaration) + /// # fn main() { + #[doc = concat!($extra_feature, "use std::sync::atomic::", stringify!($atomic_type), ";")] + /// + /// extern { + #[doc = concat!(" fn my_atomic_op(arg: *mut ", stringify!($int_type), ");")] + /// } + /// + #[doc = concat!("let mut atomic = ", stringify!($atomic_type), "::new(1);")] + /// + // SAFETY: Safe as long as `my_atomic_op` is atomic. + /// unsafe { + /// my_atomic_op(atomic.as_mut_ptr()); + /// } + /// # } + /// ``` + #[inline] + #[unstable(feature = "atomic_mut_ptr", + reason = "recently added", + issue = "66893")] + pub fn as_mut_ptr(&self) -> *mut $int_type { + self.v.get() } } } diff --git a/library/core/tests/atomic.rs b/library/core/tests/atomic.rs index 75528ebb54e..2d1e4496aee 100644 --- a/library/core/tests/atomic.rs +++ b/library/core/tests/atomic.rs @@ -4,11 +4,11 @@ #[test] fn bool_() { let a = AtomicBool::new(false); - assert_eq!(a.compare_and_swap(false, true, SeqCst), false); - assert_eq!(a.compare_and_swap(false, true, SeqCst), true); + assert_eq!(a.compare_exchange(false, true, SeqCst, SeqCst), Ok(false)); + assert_eq!(a.compare_exchange(false, true, SeqCst, SeqCst), Err(true)); a.store(false, SeqCst); - assert_eq!(a.compare_and_swap(false, true, SeqCst), false); + assert_eq!(a.compare_exchange(false, true, SeqCst, SeqCst), Ok(false)); } #[test] diff --git a/library/core/tests/const_ptr.rs b/library/core/tests/const_ptr.rs new file mode 100644 index 00000000000..4acd059ab03 --- /dev/null +++ b/library/core/tests/const_ptr.rs @@ -0,0 +1,51 @@ +// Aligned to two bytes +const DATA: [u16; 2] = [u16::from_ne_bytes([0x01, 0x23]), u16::from_ne_bytes([0x45, 0x67])]; + +const fn unaligned_ptr() -> *const u16 { + // Since DATA.as_ptr() is aligned to two bytes, adding 1 byte to that produces an unaligned *const u16 + unsafe { (DATA.as_ptr() as *const u8).add(1) as *const u16 } +} + +#[test] +fn read() { + use core::ptr; + + const FOO: i32 = unsafe { ptr::read(&42 as *const i32) }; + assert_eq!(FOO, 42); + + const ALIGNED: i32 = unsafe { ptr::read_unaligned(&42 as *const i32) }; + assert_eq!(ALIGNED, 42); + + const UNALIGNED_PTR: *const u16 = unaligned_ptr(); + + const UNALIGNED: u16 = unsafe { ptr::read_unaligned(UNALIGNED_PTR) }; + assert_eq!(UNALIGNED, u16::from_ne_bytes([0x23, 0x45])); +} + +#[test] +fn const_ptr_read() { + const FOO: i32 = unsafe { (&42 as *const i32).read() }; + assert_eq!(FOO, 42); + + const ALIGNED: i32 = unsafe { (&42 as *const i32).read_unaligned() }; + assert_eq!(ALIGNED, 42); + + const UNALIGNED_PTR: *const u16 = unaligned_ptr(); + + const UNALIGNED: u16 = unsafe { UNALIGNED_PTR.read_unaligned() }; + assert_eq!(UNALIGNED, u16::from_ne_bytes([0x23, 0x45])); +} + +#[test] +fn mut_ptr_read() { + const FOO: i32 = unsafe { (&42 as *const i32 as *mut i32).read() }; + assert_eq!(FOO, 42); + + const ALIGNED: i32 = unsafe { (&42 as *const i32 as *mut i32).read_unaligned() }; + assert_eq!(ALIGNED, 42); + + const UNALIGNED_PTR: *mut u16 = unaligned_ptr() as *mut u16; + + const UNALIGNED: u16 = unsafe { UNALIGNED_PTR.read_unaligned() }; + assert_eq!(UNALIGNED, u16::from_ne_bytes([0x23, 0x45])); +} diff --git a/library/core/tests/iter.rs b/library/core/tests/iter.rs index ec4b49da384..7376e7848ef 100644 --- a/library/core/tests/iter.rs +++ b/library/core/tests/iter.rs @@ -3505,3 +3505,85 @@ pub fn extend_for_unit() { } assert_eq!(x, 5); } + +#[test] +fn test_intersperse() { + let xs = ["a", "", "b", "c"]; + let v: Vec<&str> = xs.iter().map(|x| x.clone()).intersperse(", ").collect(); + let text: String = v.concat(); + assert_eq!(text, "a, , b, c".to_string()); + + let ys = [0, 1, 2, 3]; + let mut it = ys[..0].iter().map(|x| *x).intersperse(1); + assert!(it.next() == None); +} + +#[test] +fn test_intersperse_size_hint() { + let xs = ["a", "", "b", "c"]; + let mut iter = xs.iter().map(|x| x.clone()).intersperse(", "); + assert_eq!(iter.size_hint(), (7, Some(7))); + + assert_eq!(iter.next(), Some("a")); + assert_eq!(iter.size_hint(), (6, Some(6))); + assert_eq!(iter.next(), Some(", ")); + assert_eq!(iter.size_hint(), (5, Some(5))); + + assert_eq!([].iter().intersperse(&()).size_hint(), (0, Some(0))); +} + +#[test] +fn test_fold_specialization_intersperse() { + let mut iter = (1..2).intersperse(0); + iter.clone().for_each(|x| assert_eq!(Some(x), iter.next())); + + let mut iter = (1..3).intersperse(0); + iter.clone().for_each(|x| assert_eq!(Some(x), iter.next())); + + let mut iter = (1..4).intersperse(0); + iter.clone().for_each(|x| assert_eq!(Some(x), iter.next())); +} + +#[test] +fn test_try_fold_specialization_intersperse_ok() { + let mut iter = (1..2).intersperse(0); + iter.clone().try_for_each(|x| { + assert_eq!(Some(x), iter.next()); + Some(()) + }); + + let mut iter = (1..3).intersperse(0); + iter.clone().try_for_each(|x| { + assert_eq!(Some(x), iter.next()); + Some(()) + }); + + let mut iter = (1..4).intersperse(0); + iter.clone().try_for_each(|x| { + assert_eq!(Some(x), iter.next()); + Some(()) + }); +} + +#[test] +fn test_try_fold_specialization_intersperse_err() { + let orig_iter = ["a", "b"].iter().copied().intersperse("-"); + + // Abort after the first item. + let mut iter = orig_iter.clone(); + iter.try_for_each(|_| None::<()>); + assert_eq!(iter.next(), Some("-")); + assert_eq!(iter.next(), Some("b")); + assert_eq!(iter.next(), None); + + // Abort after the second item. + let mut iter = orig_iter.clone(); + iter.try_for_each(|item| if item == "-" { None } else { Some(()) }); + assert_eq!(iter.next(), Some("b")); + assert_eq!(iter.next(), None); + + // Abort after the third item. + let mut iter = orig_iter.clone(); + iter.try_for_each(|item| if item == "b" { None } else { Some(()) }); + assert_eq!(iter.next(), None); +} diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 2828235c3e3..fba3294e0bb 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -13,6 +13,8 @@ #![feature(const_assume)] #![feature(const_cell_into_inner)] #![feature(const_maybe_uninit_assume_init)] +#![feature(const_ptr_read)] +#![feature(const_ptr_offset)] #![feature(core_intrinsics)] #![feature(core_private_bignum)] #![feature(core_private_diy_float)] @@ -34,6 +36,7 @@ #![feature(raw)] #![feature(sort_internals)] #![feature(slice_partition_at_index)] +#![feature(maybe_uninit_extra)] #![feature(maybe_uninit_write_slice)] #![feature(min_specialization)] #![feature(step_trait)] @@ -48,6 +51,7 @@ #![feature(array_value_iter)] #![feature(iter_advance_by)] #![feature(iter_partition_in_place)] +#![feature(iter_intersperse)] #![feature(iter_is_partitioned)] #![feature(iter_order_by)] #![feature(cmp_min_max_by)] @@ -82,6 +86,10 @@ mod char; mod clone; mod cmp; + +#[cfg(not(bootstrap))] +mod const_ptr; + mod fmt; mod hash; mod intrinsics; diff --git a/library/core/tests/mem.rs b/library/core/tests/mem.rs index 5d0fedd4d9c..79ca2bba403 100644 --- a/library/core/tests/mem.rs +++ b/library/core/tests/mem.rs @@ -134,7 +134,6 @@ fn is_send_sync() {} } #[test] -#[cfg(not(bootstrap))] fn assume_init_good() { const TRUE: bool = unsafe { MaybeUninit::::new(true).assume_init() }; @@ -267,3 +266,10 @@ fn drop(&mut self) { forget(src); } + +#[test] +#[cfg(not(bootstrap))] +fn uninit_const_assume_init_read() { + const FOO: u32 = unsafe { MaybeUninit::new(42).assume_init_read() }; + assert_eq!(FOO, 42); +} diff --git a/library/core/tests/nonzero.rs b/library/core/tests/nonzero.rs index b66c482c5e5..c2c08522d0c 100644 --- a/library/core/tests/nonzero.rs +++ b/library/core/tests/nonzero.rs @@ -312,3 +312,19 @@ fn nonzero_trailing_zeros() { const TRAILING_ZEROS: u32 = NonZeroU16::new(1 << 2).unwrap().trailing_zeros(); assert_eq!(TRAILING_ZEROS, 2); } + +#[test] +fn test_nonzero_uint_div() { + let nz = NonZeroU32::new(1).unwrap(); + + let x: u32 = 42u32 / nz; + assert_eq!(x, 42u32); +} + +#[test] +fn test_nonzero_uint_rem() { + let nz = NonZeroU32::new(10).unwrap(); + + let x: u32 = 42u32 % nz; + assert_eq!(x, 2u32); +} diff --git a/library/panic_abort/src/lib.rs b/library/panic_abort/src/lib.rs index a8ebb4b3219..eb2277d8baa 100644 --- a/library/panic_abort/src/lib.rs +++ b/library/panic_abort/src/lib.rs @@ -14,11 +14,13 @@ #![feature(core_intrinsics)] #![feature(nll)] #![feature(panic_runtime)] +#![feature(std_internals)] #![feature(staged_api)] #![feature(rustc_attrs)] #![feature(asm)] use core::any::Any; +use core::panic::BoxMeUp; #[rustc_std_internal_symbol] #[allow(improper_ctypes_definitions)] @@ -28,7 +30,7 @@ // "Leak" the payload and shim to the relevant abort on the platform in question. #[rustc_std_internal_symbol] -pub unsafe extern "C" fn __rust_start_panic(_payload: usize) -> u32 { +pub unsafe extern "C" fn __rust_start_panic(_payload: *mut &mut dyn BoxMeUp) -> u32 { abort(); cfg_if::cfg_if! { diff --git a/library/panic_unwind/src/lib.rs b/library/panic_unwind/src/lib.rs index 0b74a844fec..9ce9c477ec0 100644 --- a/library/panic_unwind/src/lib.rs +++ b/library/panic_unwind/src/lib.rs @@ -104,9 +104,8 @@ // implementation. #[rustc_std_internal_symbol] #[unwind(allowed)] -pub unsafe extern "C" fn __rust_start_panic(payload: usize) -> u32 { - let payload = payload as *mut &mut dyn BoxMeUp; - let payload = (*payload).take_box(); +pub unsafe extern "C" fn __rust_start_panic(payload: *mut &mut dyn BoxMeUp) -> u32 { + let payload = Box::from_raw((*payload).take_box()); - imp::panic(Box::from_raw(payload)) + imp::panic(payload) } diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index ca40293ed58..a89e7b53e43 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -28,8 +28,7 @@ #![feature(extern_types)] #![feature(in_band_lifetimes)] #![feature(negative_impls)] -#![cfg_attr(bootstrap, feature(optin_builtin_traits))] -#![cfg_attr(not(bootstrap), feature(auto_traits))] +#![feature(auto_traits)] #![feature(restricted_std)] #![feature(rustc_attrs)] #![feature(min_specialization)] diff --git a/library/rtstartup/rsbegin.rs b/library/rtstartup/rsbegin.rs index b64f13dba4c..c6a4548ec0c 100644 --- a/library/rtstartup/rsbegin.rs +++ b/library/rtstartup/rsbegin.rs @@ -14,8 +14,7 @@ #![feature(no_core)] #![feature(lang_items)] -#![cfg_attr(bootstrap, feature(optin_builtin_traits))] -#![cfg_attr(not(bootstrap), feature(auto_traits))] +#![feature(auto_traits)] #![crate_type = "rlib"] #![no_core] #![allow(non_camel_case_types)] diff --git a/library/rtstartup/rsend.rs b/library/rtstartup/rsend.rs index 18ee7c19ba0..d5aca80edf9 100644 --- a/library/rtstartup/rsend.rs +++ b/library/rtstartup/rsend.rs @@ -2,8 +2,7 @@ #![feature(no_core)] #![feature(lang_items)] -#![cfg_attr(bootstrap, feature(optin_builtin_traits))] -#![cfg_attr(not(bootstrap), feature(auto_traits))] +#![feature(auto_traits)] #![crate_type = "rlib"] #![no_core] diff --git a/library/rustc-std-workspace-core/README.md b/library/rustc-std-workspace-core/README.md index 9c2b1fa91d3..40e0b62afab 100644 --- a/library/rustc-std-workspace-core/README.md +++ b/library/rustc-std-workspace-core/README.md @@ -4,12 +4,12 @@ This crate is a shim and empty crate which simply depends on `libcore` and reexports all of its contents. The crate is the crux of empowering the standard library to depend on crates from crates.io -Crates on crates.io that the standard library depend on the -`rustc-std-workspace-core` crate from crates.io. On crates.io, however, this -crate is empty. We use `[patch]` to override it to this crate in this -repository. As a result, crates on crates.io will draw a dependency edge to -`libcore`, the version defined in this repository. That should draw all the -dependency edges to ensure Cargo builds crates successfully! +Crates on crates.io that the standard library depend on need to depend on the +`rustc-std-workspace-core` crate from crates.io, which is empty. We use +`[patch]` to override it to this crate in this repository. As a result, crates +on crates.io will draw a dependency edge to `libcore`, the version defined in +this repository. That should draw all the dependency edges to ensure Cargo +builds crates successfully! Note that crates on crates.io need to depend on this crate with the name `core` for everything to work correctly. To do that they can use: diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index ac72345dad4..0680b1fc329 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -195,7 +195,6 @@ /// // use the values stored in map /// ``` -#[derive(Clone)] #[cfg_attr(not(test), rustc_diagnostic_item = "hashmap_type")] #[stable(feature = "rust1", since = "1.0.0")] pub struct HashMap { @@ -449,6 +448,7 @@ pub fn iter_mut(&mut self) -> IterMut<'_, K, V> { /// a.insert(1, "a"); /// assert_eq!(a.len(), 1); /// ``` + #[doc(alias = "length")] #[stable(feature = "rust1", since = "1.0.0")] pub fn len(&self) -> usize { self.base.len() @@ -1029,6 +1029,24 @@ pub fn raw_entry(&self) -> RawEntryBuilder<'_, K, V, S> { } } +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for HashMap +where + K: Clone, + V: Clone, + S: Clone, +{ + #[inline] + fn clone(&self) -> Self { + Self { base: self.base.clone() } + } + + #[inline] + fn clone_from(&mut self, other: &Self) { + self.base.clone_from(&other.base); + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl PartialEq for HashMap where diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs index 3299fd12e02..f49e5801c35 100644 --- a/library/std/src/collections/hash/set.rs +++ b/library/std/src/collections/hash/set.rs @@ -106,7 +106,6 @@ /// [`HashMap`]: crate::collections::HashMap /// [`RefCell`]: crate::cell::RefCell /// [`Cell`]: crate::cell::Cell -#[derive(Clone)] #[cfg_attr(not(test), rustc_diagnostic_item = "hashset_type")] #[stable(feature = "rust1", since = "1.0.0")] pub struct HashSet { @@ -200,6 +199,7 @@ pub fn iter(&self) -> Iter<'_, T> { /// v.insert(1); /// assert_eq!(v.len(), 1); /// ``` + #[doc(alias = "length")] #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn len(&self) -> usize { @@ -932,6 +932,23 @@ pub fn retain(&mut self, f: F) } } +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for HashSet +where + T: Clone, + S: Clone, +{ + #[inline] + fn clone(&self) -> Self { + Self { base: self.base.clone() } + } + + #[inline] + fn clone_from(&mut self, other: &Self) { + self.base.clone_from(&other.base); + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl PartialEq for HashSet where diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs index 5d93016cadb..2eef4d58507 100644 --- a/library/std/src/ffi/os_str.rs +++ b/library/std/src/ffi/os_str.rs @@ -653,6 +653,7 @@ pub fn is_empty(&self) -> bool { /// let os_str = OsStr::new("foo"); /// assert_eq!(os_str.len(), 3); /// ``` + #[doc(alias = "length")] #[stable(feature = "osstring_simple_functions", since = "1.9.0")] pub fn len(&self) -> usize { self.inner.inner.len() diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 39b0ca63301..2c6f03fe224 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -175,7 +175,7 @@ //! [`str`]: prim@str //! [`mpsc`]: sync::mpsc //! [`std::cmp`]: cmp -//! [`std::slice`]: slice +//! [`std::slice`]: mod@slice //! [`use std::env`]: env/index.html //! [`use`]: ../book/ch07-02-defining-modules-to-control-scope-and-privacy.html //! [crates.io]: https://crates.io @@ -185,7 +185,8 @@ //! [other]: #what-is-in-the-standard-library-documentation //! [primitive types]: ../book/ch03-02-data-types.html //! [rust-discord]: https://discord.gg/rust-lang - +#![cfg_attr(not(bootstrap), doc = "[array]: prim@array")] +#![cfg_attr(not(bootstrap), doc = "[slice]: prim@slice")] #![cfg_attr(not(feature = "restricted-std"), stable(feature = "rust1", since = "1.0.0"))] #![cfg_attr(feature = "restricted-std", unstable(feature = "restricted_std", issue = "none"))] #![doc( @@ -288,8 +289,7 @@ #![feature(nll)] #![feature(nonnull_slice_from_raw_parts)] #![feature(once_cell)] -#![cfg_attr(bootstrap, feature(optin_builtin_traits))] -#![cfg_attr(not(bootstrap), feature(auto_traits))] +#![feature(auto_traits)] #![feature(or_patterns)] #![feature(panic_info_message)] #![feature(panic_internals)] @@ -304,7 +304,6 @@ #![feature(rustc_private)] #![feature(shrink_to)] #![feature(slice_concat_ext)] -#![feature(slice_fill)] #![feature(slice_internals)] #![feature(slice_ptr_get)] #![feature(slice_ptr_len)] diff --git a/library/std/src/macros.rs b/library/std/src/macros.rs index de072e83dfc..5a70aa070e8 100644 --- a/library/std/src/macros.rs +++ b/library/std/src/macros.rs @@ -8,7 +8,7 @@ #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] #[allow_internal_unstable(libstd_sys_internals)] -#[cfg_attr(not(any(bootstrap, test)), rustc_diagnostic_item = "std_panic_macro")] +#[cfg_attr(not(test), rustc_diagnostic_item = "std_panic_macro")] macro_rules! panic { () => ({ $crate::panic!("explicit panic") }); ($msg:expr $(,)?) => ({ $crate::rt::begin_panic($msg) }); diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs index 8ba3feccb6b..6cd572cbe87 100644 --- a/library/std/src/panicking.rs +++ b/library/std/src/panicking.rs @@ -44,11 +44,11 @@ extern "C" { fn __rust_panic_cleanup(payload: *mut u8) -> *mut (dyn Any + Send + 'static); - /// `payload` is actually a `*mut &mut dyn BoxMeUp` but that would cause FFI warnings. - /// It cannot be `Box` because the other end of this call does not depend - /// on liballoc, and thus cannot use `Box`. + /// `payload` is passed through another layer of raw pointers as `&mut dyn Trait` is not + /// FFI-safe. `BoxMeUp` lazily performs allocation only when needed (this avoids allocations + /// when using the "abort" panic runtime). #[unwind(allowed)] - fn __rust_start_panic(payload: usize) -> u32; + fn __rust_start_panic(payload: *mut &mut dyn BoxMeUp) -> u32; } /// This function is called by the panic runtime if FFI code catches a Rust @@ -637,7 +637,7 @@ fn get(&mut self) -> &(dyn Any + Send) { fn rust_panic(mut msg: &mut dyn BoxMeUp) -> ! { let code = unsafe { let obj = &mut msg as *mut &mut dyn BoxMeUp; - __rust_start_panic(obj as usize) + __rust_start_panic(obj) }; rtabort!("failed to initiate panic, error {}", code) } diff --git a/library/std/src/sync/mpsc/blocking.rs b/library/std/src/sync/mpsc/blocking.rs index d34de6a4fac..4c852b8ee81 100644 --- a/library/std/src/sync/mpsc/blocking.rs +++ b/library/std/src/sync/mpsc/blocking.rs @@ -36,7 +36,11 @@ pub fn tokens() -> (WaitToken, SignalToken) { impl SignalToken { pub fn signal(&self) -> bool { - let wake = !self.inner.woken.compare_and_swap(false, true, Ordering::SeqCst); + let wake = self + .inner + .woken + .compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst) + .is_ok(); if wake { self.inner.thread.unpark(); } diff --git a/library/std/src/sync/mpsc/oneshot.rs b/library/std/src/sync/mpsc/oneshot.rs index 75f5621fa12..3dcf03f579a 100644 --- a/library/std/src/sync/mpsc/oneshot.rs +++ b/library/std/src/sync/mpsc/oneshot.rs @@ -129,7 +129,7 @@ pub fn recv(&self, deadline: Option) -> Result> { let ptr = unsafe { signal_token.cast_to_usize() }; // race with senders to enter the blocking state - if self.state.compare_and_swap(EMPTY, ptr, Ordering::SeqCst) == EMPTY { + if self.state.compare_exchange(EMPTY, ptr, Ordering::SeqCst, Ordering::SeqCst).is_ok() { if let Some(deadline) = deadline { let timed_out = !wait_token.wait_max_until(deadline); // Try to reset the state @@ -161,7 +161,12 @@ pub fn try_recv(&self) -> Result> { // the state changes under our feet we'd rather just see that state // change. DATA => { - self.state.compare_and_swap(DATA, EMPTY, Ordering::SeqCst); + let _ = self.state.compare_exchange( + DATA, + EMPTY, + Ordering::SeqCst, + Ordering::SeqCst, + ); match (&mut *self.data.get()).take() { Some(data) => Ok(data), None => unreachable!(), @@ -264,7 +269,10 @@ pub fn abort_selection(&self) -> Result> { // If we've got a blocked thread, then use an atomic to gain ownership // of it (may fail) - ptr => self.state.compare_and_swap(ptr, EMPTY, Ordering::SeqCst), + ptr => self + .state + .compare_exchange(ptr, EMPTY, Ordering::SeqCst, Ordering::SeqCst) + .unwrap_or_else(|x| x), }; // Now that we've got ownership of our state, figure out what to do diff --git a/library/std/src/sync/mpsc/shared.rs b/library/std/src/sync/mpsc/shared.rs index 898654f21f2..0c32e636a56 100644 --- a/library/std/src/sync/mpsc/shared.rs +++ b/library/std/src/sync/mpsc/shared.rs @@ -385,8 +385,15 @@ pub fn drop_port(&self) { self.port_dropped.store(true, Ordering::SeqCst); let mut steals = unsafe { *self.steals.get() }; while { - let cnt = self.cnt.compare_and_swap(steals, DISCONNECTED, Ordering::SeqCst); - cnt != DISCONNECTED && cnt != steals + match self.cnt.compare_exchange( + steals, + DISCONNECTED, + Ordering::SeqCst, + Ordering::SeqCst, + ) { + Ok(_) => false, + Err(old) => old != DISCONNECTED, + } } { // See the discussion in 'try_recv' for why we yield // control of this thread. diff --git a/library/std/src/sync/mpsc/stream.rs b/library/std/src/sync/mpsc/stream.rs index 9f7c1af8951..a652f24c58a 100644 --- a/library/std/src/sync/mpsc/stream.rs +++ b/library/std/src/sync/mpsc/stream.rs @@ -322,12 +322,15 @@ pub fn drop_port(&self) { // (because there is a bounded number of senders). let mut steals = unsafe { *self.queue.consumer_addition().steals.get() }; while { - let cnt = self.queue.producer_addition().cnt.compare_and_swap( + match self.queue.producer_addition().cnt.compare_exchange( steals, DISCONNECTED, Ordering::SeqCst, - ); - cnt != DISCONNECTED && cnt != steals + Ordering::SeqCst, + ) { + Ok(_) => false, + Err(old) => old != DISCONNECTED, + } } { while self.queue.pop().is_some() { steals += 1; diff --git a/library/std/src/sync/once.rs b/library/std/src/sync/once.rs index de5ddf1daf2..6a330834489 100644 --- a/library/std/src/sync/once.rs +++ b/library/std/src/sync/once.rs @@ -65,7 +65,7 @@ // must do so with Release ordering to make the result available. // - `wait` inserts `Waiter` nodes as a pointer in `state_and_queue`, and // needs to make the nodes available with Release ordering. The load in -// its `compare_and_swap` can be Relaxed because it only has to compare +// its `compare_exchange` can be Relaxed because it only has to compare // the atomic, not to read other data. // - `WaiterQueue::Drop` must see the `Waiter` nodes, so it must load // `state_and_queue` with Acquire ordering. @@ -110,7 +110,7 @@ /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub struct Once { - // `state_and_queue` is actually an a pointer to a `Waiter` with extra state + // `state_and_queue` is actually a pointer to a `Waiter` with extra state // bits, so we add the `PhantomData` appropriately. state_and_queue: AtomicUsize, _marker: marker::PhantomData<*const Waiter>, @@ -395,12 +395,13 @@ fn call_inner(&self, ignore_poisoning: bool, init: &mut dyn FnMut(&OnceState)) { } POISONED | INCOMPLETE => { // Try to register this thread as the one RUNNING. - let old = self.state_and_queue.compare_and_swap( + let exchange_result = self.state_and_queue.compare_exchange( state_and_queue, RUNNING, Ordering::Acquire, + Ordering::Acquire, ); - if old != state_and_queue { + if let Err(old) = exchange_result { state_and_queue = old; continue; } @@ -452,8 +453,13 @@ fn wait(state_and_queue: &AtomicUsize, mut current_state: usize) { // Try to slide in the node at the head of the linked list, making sure // that another thread didn't just replace the head of the linked list. - let old = state_and_queue.compare_and_swap(current_state, me | RUNNING, Ordering::Release); - if old != current_state { + let exchange_result = state_and_queue.compare_exchange( + current_state, + me | RUNNING, + Ordering::Release, + Ordering::Relaxed, + ); + if let Err(old) = exchange_result { current_state = old; continue; } diff --git a/library/std/src/sys/sgx/abi/mod.rs b/library/std/src/sys/sgx/abi/mod.rs index a0eb12c3d15..a5e45303476 100644 --- a/library/std/src/sys/sgx/abi/mod.rs +++ b/library/std/src/sys/sgx/abi/mod.rs @@ -36,20 +36,20 @@ } // Try to atomically swap UNINIT with BUSY. The returned state can be: - match RELOC_STATE.compare_and_swap(UNINIT, BUSY, Ordering::Acquire) { + match RELOC_STATE.compare_exchange(UNINIT, BUSY, Ordering::Acquire, Ordering::Acquire) { // This thread just obtained the lock and other threads will observe BUSY - UNINIT => { + Ok(_) => { reloc::relocate_elf_rela(); RELOC_STATE.store(DONE, Ordering::Release); } // We need to wait until the initialization is done. - BUSY => { + Err(BUSY) => { while RELOC_STATE.load(Ordering::Acquire) == BUSY { core::hint::spin_loop(); } } // Initialization is done. - DONE => {} + Err(DONE) => {} _ => unreachable!(), } } diff --git a/library/std/src/sys/sgx/waitqueue/spin_mutex.rs b/library/std/src/sys/sgx/waitqueue/spin_mutex.rs index d99ce895da5..9140041c584 100644 --- a/library/std/src/sys/sgx/waitqueue/spin_mutex.rs +++ b/library/std/src/sys/sgx/waitqueue/spin_mutex.rs @@ -42,7 +42,7 @@ pub fn lock(&self) -> SpinMutexGuard<'_, T> { #[inline(always)] pub fn try_lock(&self) -> Option> { - if !self.lock.compare_and_swap(false, true, Ordering::Acquire) { + if self.lock.compare_exchange(false, true, Ordering::Acquire, Ordering::Acquire).is_ok() { Some(SpinMutexGuard { mutex: self }) } else { None diff --git a/library/std/src/sys/unix/time.rs b/library/std/src/sys/unix/time.rs index fac4b05ad0b..23a5c81c005 100644 --- a/library/std/src/sys/unix/time.rs +++ b/library/std/src/sys/unix/time.rs @@ -237,7 +237,7 @@ fn info() -> mach_timebase_info { // `denom` field. // // Encoding this as a single `AtomicU64` allows us to use `Relaxed` - // operations, as we are only interested in in the effects on a single + // operations, as we are only interested in the effects on a single // memory location. static INFO_BITS: AtomicU64 = AtomicU64::new(0); diff --git a/library/std/src/sys/windows/mutex.rs b/library/std/src/sys/windows/mutex.rs index fa51b006c34..d4cc56d4cb3 100644 --- a/library/std/src/sys/windows/mutex.rs +++ b/library/std/src/sys/windows/mutex.rs @@ -123,9 +123,9 @@ unsafe fn inner(&self) -> *const Inner { let inner = box Inner { remutex: ReentrantMutex::uninitialized(), held: Cell::new(false) }; inner.remutex.init(); let inner = Box::into_raw(inner); - match self.lock.compare_and_swap(0, inner as usize, Ordering::SeqCst) { - 0 => inner, - n => { + match self.lock.compare_exchange(0, inner as usize, Ordering::SeqCst, Ordering::SeqCst) { + Ok(_) => inner, + Err(n) => { Box::from_raw(inner).remutex.destroy(); n as *const _ } diff --git a/library/std/src/sys/windows/thread_parker.rs b/library/std/src/sys/windows/thread_parker.rs index 701c6e2e9be..9e4c9aa0a51 100644 --- a/library/std/src/sys/windows/thread_parker.rs +++ b/library/std/src/sys/windows/thread_parker.rs @@ -113,7 +113,7 @@ pub unsafe fn park(&self) { // Wait for something to happen, assuming it's still set to PARKED. c::WaitOnAddress(self.ptr(), &PARKED as *const _ as c::LPVOID, 1, c::INFINITE); // Change NOTIFIED=>EMPTY but leave PARKED alone. - if self.state.compare_and_swap(NOTIFIED, EMPTY, Acquire) == NOTIFIED { + if self.state.compare_exchange(NOTIFIED, EMPTY, Acquire, Acquire).is_ok() { // Actually woken up by unpark(). return; } else { diff --git a/library/std/src/sys_common/condvar/check.rs b/library/std/src/sys_common/condvar/check.rs index fecb732b910..1578a2de60c 100644 --- a/library/std/src/sys_common/condvar/check.rs +++ b/library/std/src/sys_common/condvar/check.rs @@ -23,9 +23,9 @@ pub const fn new() -> Self { } pub fn verify(&self, mutex: &MovableMutex) { let addr = mutex.raw() as *const mutex_imp::Mutex as usize; - match self.addr.compare_and_swap(0, addr, Ordering::SeqCst) { - 0 => {} // Stored the address - n if n == addr => {} // Lost a race to store the same address + match self.addr.compare_exchange(0, addr, Ordering::SeqCst, Ordering::SeqCst) { + Ok(_) => {} // Stored the address + Err(n) if n == addr => {} // Lost a race to store the same address _ => panic!("attempted to use a condition variable with two mutexes"), } } diff --git a/library/std/src/sys_common/thread_local_key.rs b/library/std/src/sys_common/thread_local_key.rs index dbcb7b36265..32cd5641665 100644 --- a/library/std/src/sys_common/thread_local_key.rs +++ b/library/std/src/sys_common/thread_local_key.rs @@ -168,7 +168,7 @@ unsafe fn lazy_init(&self) -> usize { return key; } - // POSIX allows the key created here to be 0, but the compare_and_swap + // POSIX allows the key created here to be 0, but the compare_exchange // below relies on using 0 as a sentinel value to check who won the // race to set the shared TLS key. As far as I know, there is no // guaranteed value that cannot be returned as a posix_key_create key, @@ -186,11 +186,11 @@ unsafe fn lazy_init(&self) -> usize { key2 }; rtassert!(key != 0); - match self.key.compare_and_swap(0, key as usize, Ordering::SeqCst) { + match self.key.compare_exchange(0, key as usize, Ordering::SeqCst, Ordering::SeqCst) { // The CAS succeeded, so we've created the actual key - 0 => key as usize, + Ok(_) => key as usize, // If someone beat us to the punch, use their key instead - n => { + Err(n) => { imp::destroy(key); n } diff --git a/library/std/src/sys_common/thread_parker/futex.rs b/library/std/src/sys_common/thread_parker/futex.rs index a5d4927dcc5..0132743b244 100644 --- a/library/std/src/sys_common/thread_parker/futex.rs +++ b/library/std/src/sys_common/thread_parker/futex.rs @@ -49,7 +49,7 @@ pub unsafe fn park(&self) { // Wait for something to happen, assuming it's still set to PARKED. futex_wait(&self.state, PARKED, None); // Change NOTIFIED=>EMPTY and return in that case. - if self.state.compare_and_swap(NOTIFIED, EMPTY, Acquire) == NOTIFIED { + if self.state.compare_exchange(NOTIFIED, EMPTY, Acquire, Acquire).is_ok() { return; } else { // Spurious wake up. We loop to try again. diff --git a/library/stdarch b/library/stdarch index f1ed22803f0..9c732a56f67 160000 --- a/library/stdarch +++ b/library/stdarch @@ -1 +1 @@ -Subproject commit f1ed22803f09e3b2c2b86d773db07ce70804987a +Subproject commit 9c732a56f67f54d12a0b4fd99993154906c95ea6 diff --git a/src/bootstrap/CHANGELOG.md b/src/bootstrap/CHANGELOG.md index a103c9fb0b7..f899f21080e 100644 --- a/src/bootstrap/CHANGELOG.md +++ b/src/bootstrap/CHANGELOG.md @@ -4,7 +4,12 @@ All notable changes to bootstrap will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). -## [Non-breaking changes since the last major version] + +## [Changes since the last major version] + +- `llvm-libunwind` now accepts `in-tree` (formerly true), `system` or `no` (formerly false) [#77703](https://github.com/rust-lang/rust/pull/77703) + +### Non-breaking changes - `x.py check` needs opt-in to check tests (--all-targets) [#77473](https://github.com/rust-lang/rust/pull/77473) - The default bootstrap profiles are now located at `bootstrap/defaults/config.$PROFILE.toml` (previously they were located at `bootstrap/defaults/config.toml.$PROFILE`) [#77558](https://github.com/rust-lang/rust/pull/77558) diff --git a/src/bootstrap/README.md b/src/bootstrap/README.md index 84ed9446ae7..a2e596bf4e9 100644 --- a/src/bootstrap/README.md +++ b/src/bootstrap/README.md @@ -201,7 +201,6 @@ build/ # Output for all compiletest-based test suites test/ ui/ - compile-fail/ debuginfo/ ... diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 97f40815b87..b8bae69d063 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -351,11 +351,13 @@ def output(filepath): with open(tmp, 'w') as f: yield f try: - os.remove(filepath) # PermissionError/OSError on Win32 if in use - os.rename(tmp, filepath) + if os.path.exists(filepath): + os.remove(filepath) # PermissionError/OSError on Win32 if in use except OSError: shutil.copy2(tmp, filepath) os.remove(tmp) + return + os.rename(tmp, filepath) class RustBuild(object): diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index ab0c4a5c31b..c2abb01fa8c 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -384,7 +384,6 @@ macro_rules! describe { test::ExpandYamlAnchors, test::Tidy, test::Ui, - test::CompileFail, test::RunPassValgrind, test::MirOpt, test::Codegen, @@ -471,6 +470,7 @@ macro_rules! describe { dist::RustDev, dist::Extended, dist::BuildManifest, + dist::ReproducibleArtifacts, ), Kind::Install => describe!( install::Docs, @@ -736,10 +736,7 @@ pub fn rustdoc_cmd(&self, compiler: Compiler) -> Command { if self.config.deny_warnings { cmd.arg("-Dwarnings"); } - // cfg(not(bootstrap)), can be removed on the next beta bump - if compiler.stage != 0 { - cmd.arg("-Znormalize-docs"); - } + cmd.arg("-Znormalize-docs"); // Remove make-related flags that can cause jobserver problems. cmd.env_remove("MAKEFLAGS"); diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index fbebb26c746..2707a640457 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -7,6 +7,7 @@ //! goes along from the output of the previous stage. use std::borrow::Cow; +use std::collections::HashSet; use std::env; use std::fs; use std::io::prelude::*; @@ -501,6 +502,41 @@ fn run(self, builder: &Builder<'_>) { let mut cargo = builder.cargo(compiler, Mode::Rustc, SourceType::InTree, target, "build"); rustc_cargo(builder, &mut cargo, target); + if builder.config.rust_profile_use.is_some() + && builder.config.rust_profile_generate.is_some() + { + panic!("Cannot use and generate PGO profiles at the same time"); + } + + let is_collecting = if let Some(path) = &builder.config.rust_profile_generate { + if compiler.stage == 1 { + cargo.rustflag(&format!("-Cprofile-generate={}", path)); + // Apparently necessary to avoid overflowing the counters during + // a Cargo build profile + cargo.rustflag("-Cllvm-args=-vp-counters-per-site=4"); + true + } else { + false + } + } else if let Some(path) = &builder.config.rust_profile_use { + if compiler.stage == 1 { + cargo.rustflag(&format!("-Cprofile-use={}", path)); + cargo.rustflag("-Cllvm-args=-pgo-warn-missing-function"); + true + } else { + false + } + } else { + false + }; + if is_collecting { + // Ensure paths to Rust sources are relative, not absolute. + cargo.rustflag(&format!( + "-Cllvm-args=-static-func-strip-dirname-prefix={}", + builder.config.src.components().count() + )); + } + builder.info(&format!( "Building stage{} compiler artifacts ({} -> {})", compiler.stage, &compiler.host, target @@ -752,7 +788,7 @@ fn copy_codegen_backends_to_sysroot( // Here we're looking for the output dylib of the `CodegenBackend` step and // we're copying that into the `codegen-backends` folder. let dst = builder.sysroot_codegen_backends(target_compiler); - t!(fs::create_dir_all(&dst)); + t!(fs::create_dir_all(&dst), dst); if builder.config.dry_run { return; @@ -956,13 +992,26 @@ fn run(self, builder: &Builder<'_>) -> Compiler { builder.info(&format!("Assembling stage{} compiler ({})", stage, host)); // Link in all dylibs to the libdir + let stamp = librustc_stamp(builder, build_compiler, target_compiler.host); + let proc_macros = builder + .read_stamp_file(&stamp) + .into_iter() + .filter_map(|(path, dependency_type)| { + if dependency_type == DependencyType::Host { + Some(path.file_name().unwrap().to_owned().into_string().unwrap()) + } else { + None + } + }) + .collect::>(); + let sysroot = builder.sysroot(target_compiler); let rustc_libdir = builder.rustc_libdir(target_compiler); t!(fs::create_dir_all(&rustc_libdir)); let src_libdir = builder.sysroot_libdir(build_compiler, host); for f in builder.read_dir(&src_libdir) { let filename = f.file_name().into_string().unwrap(); - if is_dylib(&filename) { + if is_dylib(&filename) && !proc_macros.contains(&filename) { builder.copy(&f.path(), &rustc_libdir.join(&filename)); } } diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index ece8a7494b5..8a3b936d80d 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -134,6 +134,8 @@ pub struct Config { pub rust_thin_lto_import_instr_limit: Option, pub rust_remap_debuginfo: bool, pub rust_new_symbol_mangling: bool, + pub rust_profile_use: Option, + pub rust_profile_generate: Option, pub build: TargetSelection, pub hosts: Vec, @@ -146,6 +148,7 @@ pub struct Config { pub dist_sign_folder: Option, pub dist_upload_addr: Option, pub dist_gpg_password_file: Option, + pub dist_compression_formats: Option>, // libstd features pub backtrace: bool, // support for RUST_BACKTRACE @@ -436,6 +439,7 @@ struct Dist { upload_addr: Option, src_tarball: Option, missing_tools: Option, + compression_formats: Option>, } #[derive(Deserialize)] @@ -496,6 +500,8 @@ struct Rust { llvm_libunwind: Option, control_flow_guard: Option, new_symbol_mangling: Option, + profile_generate: Option, + profile_use: Option, } /// TOML representation of how each build target is configured. @@ -874,6 +880,11 @@ pub fn parse(args: &[String]) -> Config { config.rust_codegen_units = rust.codegen_units.map(threads_from_config); config.rust_codegen_units_std = rust.codegen_units_std.map(threads_from_config); + config.rust_profile_use = flags.rust_profile_use.or(rust.profile_use); + config.rust_profile_generate = flags.rust_profile_generate.or(rust.profile_generate); + } else { + config.rust_profile_use = flags.rust_profile_use; + config.rust_profile_generate = flags.rust_profile_generate; } if let Some(t) = toml.target { @@ -927,6 +938,7 @@ pub fn parse(args: &[String]) -> Config { config.dist_sign_folder = t.sign_folder.map(PathBuf::from); config.dist_gpg_password_file = t.gpg_password_file.map(PathBuf::from); config.dist_upload_addr = t.upload_addr; + config.dist_compression_formats = t.compression_formats; set(&mut config.rust_dist_src, t.src_tarball); set(&mut config.missing_tools, t.missing_tools); } diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py index 42f00ce9621..2cabaee68ea 100755 --- a/src/bootstrap/configure.py +++ b/src/bootstrap/configure.py @@ -147,6 +147,8 @@ v("experimental-targets", "llvm.experimental-targets", "experimental LLVM targets to build") v("release-channel", "rust.channel", "the name of the release channel to build") v("release-description", "rust.description", "optional descriptive string for version output") +v("dist-compression-formats", None, + "comma-separated list of compression formats to use") # Used on systems where "cc" is unavailable v("default-linker", "rust.default-linker", "the default linker") @@ -349,6 +351,8 @@ for key in known_args: elif option.name == 'option-checking': # this was handled above pass + elif option.name == 'dist-compression-formats': + set('dist.compression-formats', value.split(',')) else: raise RuntimeError("unhandled option {}".format(option.name)) diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 9ebf76dceef..0a79d09b27f 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -19,6 +19,7 @@ use crate::cache::{Interned, INTERNER}; use crate::compile; use crate::config::TargetSelection; +use crate::tarball::{OverlayKind, Tarball}; use crate::tool::{self, Tool}; use crate::util::{exe, is_dylib, timeit}; use crate::{Compiler, DependencyType, Mode, LLVM_TOOLS}; @@ -36,10 +37,6 @@ pub fn tmpdir(builder: &Builder<'_>) -> PathBuf { builder.out.join("tmp/dist") } -fn rust_installer(builder: &Builder<'_>) -> Command { - builder.tool_cmd(Tool::RustInstaller) -} - fn missing_tool(tool_name: &str, skip: bool) { if skip { println!("Unable to build {}, skipping dist", tool_name) @@ -54,7 +51,7 @@ pub struct Docs { } impl Step for Docs { - type Output = PathBuf; + type Output = Option; const DEFAULT: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { @@ -66,48 +63,20 @@ fn make_run(run: RunConfig<'_>) { } /// Builds the `rust-docs` installer component. - fn run(self, builder: &Builder<'_>) -> PathBuf { + fn run(self, builder: &Builder<'_>) -> Option { let host = self.host; - - let name = pkgname(builder, "rust-docs"); - if !builder.config.docs { - return distdir(builder).join(format!("{}-{}.tar.gz", name, host.triple)); + return None; } - builder.default_doc(None); - builder.info(&format!("Dist docs ({})", host)); - let _time = timeit(builder); + let dest = "share/doc/rust/html"; - let image = tmpdir(builder).join(format!("{}-{}-image", name, host.triple)); - let _ = fs::remove_dir_all(&image); - - let dst = image.join("share/doc/rust/html"); - t!(fs::create_dir_all(&dst)); - let src = builder.doc_out(host); - builder.cp_r(&src, &dst); - builder.install(&builder.src.join("src/doc/robots.txt"), &dst, 0o644); - - let mut cmd = rust_installer(builder); - cmd.arg("generate") - .arg("--product-name=Rust-Documentation") - .arg("--rel-manifest-dir=rustlib") - .arg("--success-message=Rust-documentation-is-installed.") - .arg("--image-dir") - .arg(&image) - .arg("--work-dir") - .arg(&tmpdir(builder)) - .arg("--output-dir") - .arg(&distdir(builder)) - .arg(format!("--package-name={}-{}", name, host.triple)) - .arg("--component-name=rust-docs") - .arg("--legacy-manifest-dirs=rustlib,cargo") - .arg("--bulk-dirs=share/doc/rust/html"); - builder.run(&mut cmd); - builder.remove_dir(&image); - - distdir(builder).join(format!("{}-{}.tar.gz", name, host.triple)) + let mut tarball = Tarball::new(builder, "rust-docs", &host.triple); + tarball.set_product_name("Rust Documentation"); + tarball.add_dir(&builder.doc_out(host), dest); + tarball.add_file(&builder.src.join("src/doc/robots.txt"), dest, 0o644); + Some(tarball.generate()) } } @@ -117,7 +86,7 @@ pub struct RustcDocs { } impl Step for RustcDocs { - type Output = PathBuf; + type Output = Option; const DEFAULT: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { @@ -129,47 +98,17 @@ fn make_run(run: RunConfig<'_>) { } /// Builds the `rustc-docs` installer component. - fn run(self, builder: &Builder<'_>) -> PathBuf { + fn run(self, builder: &Builder<'_>) -> Option { let host = self.host; - - let name = pkgname(builder, "rustc-docs"); - if !builder.config.compiler_docs { - return distdir(builder).join(format!("{}-{}.tar.gz", name, host.triple)); + return None; } - builder.default_doc(None); - let image = tmpdir(builder).join(format!("{}-{}-image", name, host.triple)); - let _ = fs::remove_dir_all(&image); - - let dst = image.join("share/doc/rust/html/rustc"); - t!(fs::create_dir_all(&dst)); - let src = builder.compiler_doc_out(host); - builder.cp_r(&src, &dst); - - let mut cmd = rust_installer(builder); - cmd.arg("generate") - .arg("--product-name=Rustc-Documentation") - .arg("--rel-manifest-dir=rustlib") - .arg("--success-message=Rustc-documentation-is-installed.") - .arg("--image-dir") - .arg(&image) - .arg("--work-dir") - .arg(&tmpdir(builder)) - .arg("--output-dir") - .arg(&distdir(builder)) - .arg(format!("--package-name={}-{}", name, host.triple)) - .arg("--component-name=rustc-docs") - .arg("--legacy-manifest-dirs=rustlib,cargo") - .arg("--bulk-dirs=share/doc/rust/html/rustc"); - - builder.info(&format!("Dist compiler docs ({})", host)); - let _time = timeit(builder); - builder.run(&mut cmd); - builder.remove_dir(&image); - - distdir(builder).join(format!("{}-{}.tar.gz", name, host.triple)) + let mut tarball = Tarball::new(builder, "rustc-docs", &host.triple); + tarball.set_product_name("Rustc Documentation"); + tarball.add_dir(&builder.compiler_doc_out(host), "share/doc/rust/html/rustc"); + Some(tarball.generate()) } } @@ -345,41 +284,20 @@ fn make_run(run: RunConfig<'_>) { /// without any extra installed software (e.g., we bundle gcc, libraries, etc). fn run(self, builder: &Builder<'_>) -> Option { let host = self.host; - if !host.contains("pc-windows-gnu") { return None; } - builder.info(&format!("Dist mingw ({})", host)); - let _time = timeit(builder); - let name = pkgname(builder, "rust-mingw"); - let image = tmpdir(builder).join(format!("{}-{}-image", name, host.triple)); - let _ = fs::remove_dir_all(&image); - t!(fs::create_dir_all(&image)); + let mut tarball = Tarball::new(builder, "rust-mingw", &host.triple); + tarball.set_product_name("Rust MinGW"); // The first argument is a "temporary directory" which is just // thrown away (this contains the runtime DLLs included in the rustc package // above) and the second argument is where to place all the MinGW components // (which is what we want). - make_win_dist(&tmpdir(builder), &image, host, &builder); - - let mut cmd = rust_installer(builder); - cmd.arg("generate") - .arg("--product-name=Rust-MinGW") - .arg("--rel-manifest-dir=rustlib") - .arg("--success-message=Rust-MinGW-is-installed.") - .arg("--image-dir") - .arg(&image) - .arg("--work-dir") - .arg(&tmpdir(builder)) - .arg("--output-dir") - .arg(&distdir(builder)) - .arg(format!("--package-name={}-{}", name, host.triple)) - .arg("--component-name=rust-mingw") - .arg("--legacy-manifest-dirs=rustlib,cargo"); - builder.run(&mut cmd); - t!(fs::remove_dir_all(&image)); - Some(distdir(builder).join(format!("{}-{}.tar.gz", name, host.triple))) + make_win_dist(&tmpdir(builder), tarball.image_dir(), host, &builder); + + Some(tarball.generate()) } } @@ -407,30 +325,10 @@ fn run(self, builder: &Builder<'_>) -> PathBuf { let compiler = self.compiler; let host = self.compiler.host; - let name = pkgname(builder, "rustc"); - let image = tmpdir(builder).join(format!("{}-{}-image", name, host.triple)); - let _ = fs::remove_dir_all(&image); - let overlay = tmpdir(builder).join(format!("{}-{}-overlay", name, host.triple)); - let _ = fs::remove_dir_all(&overlay); + let tarball = Tarball::new(builder, "rustc", &host.triple); // Prepare the rustc "image", what will actually end up getting installed - prepare_image(builder, compiler, &image); - - // Prepare the overlay which is part of the tarball but won't actually be - // installed - let cp = |file: &str| { - builder.install(&builder.src.join(file), &overlay, 0o644); - }; - cp("COPYRIGHT"); - cp("LICENSE-APACHE"); - cp("LICENSE-MIT"); - cp("README.md"); - // tiny morsel of metadata is used by rust-packaging - let version = builder.rust_version(); - builder.create(&overlay.join("version"), &version); - if let Some(sha) = builder.rust_sha() { - builder.create(&overlay.join("git-commit-hash"), &sha); - } + prepare_image(builder, compiler, tarball.image_dir()); // On MinGW we've got a few runtime DLL dependencies that we need to // include. The first argument to this script is where to put these DLLs @@ -443,38 +341,11 @@ fn run(self, builder: &Builder<'_>) -> PathBuf { // install will *also* include the rust-mingw package, which also needs // licenses, so to be safe we just include it here in all MinGW packages. if host.contains("pc-windows-gnu") { - make_win_dist(&image, &tmpdir(builder), host, builder); - - let dst = image.join("share/doc"); - t!(fs::create_dir_all(&dst)); - builder.cp_r(&builder.src.join("src/etc/third-party"), &dst); + make_win_dist(tarball.image_dir(), &tmpdir(builder), host, builder); + tarball.add_dir(builder.src.join("src/etc/third-party"), "share/doc"); } - // Finally, wrap everything up in a nice tarball! - let mut cmd = rust_installer(builder); - cmd.arg("generate") - .arg("--product-name=Rust") - .arg("--rel-manifest-dir=rustlib") - .arg("--success-message=Rust-is-ready-to-roll.") - .arg("--image-dir") - .arg(&image) - .arg("--work-dir") - .arg(&tmpdir(builder)) - .arg("--output-dir") - .arg(&distdir(builder)) - .arg("--non-installed-overlay") - .arg(&overlay) - .arg(format!("--package-name={}-{}", name, host.triple)) - .arg("--component-name=rustc") - .arg("--legacy-manifest-dirs=rustlib,cargo"); - - builder.info(&format!("Dist rustc stage{} ({})", compiler.stage, host.triple)); - let _time = timeit(builder); - builder.run(&mut cmd); - builder.remove_dir(&image); - builder.remove_dir(&overlay); - - return distdir(builder).join(format!("{}-{}.tar.gz", name, host.triple)); + return tarball.generate(); fn prepare_image(builder: &Builder<'_>, compiler: Compiler, image: &Path) { let host = compiler.host; @@ -684,7 +555,7 @@ pub struct Std { } impl Step for Std { - type Output = PathBuf; + type Output = Option; const DEFAULT: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { @@ -702,46 +573,24 @@ fn make_run(run: RunConfig<'_>) { }); } - fn run(self, builder: &Builder<'_>) -> PathBuf { + fn run(self, builder: &Builder<'_>) -> Option { let compiler = self.compiler; let target = self.target; - let name = pkgname(builder, "rust-std"); - let archive = distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple)); if skip_host_target_lib(builder, compiler) { - return archive; + return None; } builder.ensure(compile::Std { compiler, target }); - let image = tmpdir(builder).join(format!("{}-{}-image", name, target.triple)); - let _ = fs::remove_dir_all(&image); + let mut tarball = Tarball::new(builder, "rust-std", &target.triple); + tarball.include_target_in_component_name(true); let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target); let stamp = compile::libstd_stamp(builder, compiler_to_use, target); - copy_target_libs(builder, target, &image, &stamp); - - let mut cmd = rust_installer(builder); - cmd.arg("generate") - .arg("--product-name=Rust") - .arg("--rel-manifest-dir=rustlib") - .arg("--success-message=std-is-standing-at-the-ready.") - .arg("--image-dir") - .arg(&image) - .arg("--work-dir") - .arg(&tmpdir(builder)) - .arg("--output-dir") - .arg(&distdir(builder)) - .arg(format!("--package-name={}-{}", name, target.triple)) - .arg(format!("--component-name=rust-std-{}", target.triple)) - .arg("--legacy-manifest-dirs=rustlib,cargo"); - - builder - .info(&format!("Dist std stage{} ({} -> {})", compiler.stage, &compiler.host, target)); - let _time = timeit(builder); - builder.run(&mut cmd); - builder.remove_dir(&image); - archive + copy_target_libs(builder, target, &tarball.image_dir(), &stamp); + + Some(tarball.generate()) } } @@ -752,7 +601,7 @@ pub struct RustcDev { } impl Step for RustcDev { - type Output = PathBuf; + type Output = Option; const DEFAULT: bool = true; const ONLY_HOSTS: bool = true; @@ -771,60 +620,36 @@ fn make_run(run: RunConfig<'_>) { }); } - fn run(self, builder: &Builder<'_>) -> PathBuf { + fn run(self, builder: &Builder<'_>) -> Option { let compiler = self.compiler; let target = self.target; - - let name = pkgname(builder, "rustc-dev"); - let archive = distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple)); if skip_host_target_lib(builder, compiler) { - return archive; + return None; } builder.ensure(compile::Rustc { compiler, target }); - let image = tmpdir(builder).join(format!("{}-{}-image", name, target.triple)); - let _ = fs::remove_dir_all(&image); + let tarball = Tarball::new(builder, "rustc-dev", &target.triple); let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target); let stamp = compile::librustc_stamp(builder, compiler_to_use, target); - copy_target_libs(builder, target, &image, &stamp); - - // Copy compiler sources. - let dst_src = image.join("lib/rustlib/rustc-src/rust"); - t!(fs::create_dir_all(&dst_src)); + copy_target_libs(builder, target, tarball.image_dir(), &stamp); - let src_files = ["Cargo.lock"]; + let src_files = &["Cargo.lock"]; // This is the reduced set of paths which will become the rustc-dev component // (essentially the compiler crates and all of their path dependencies). - copy_src_dirs(builder, &builder.src, &["compiler"], &[], &dst_src); - for file in src_files.iter() { - builder.copy(&builder.src.join(file), &dst_src.join(file)); + copy_src_dirs( + builder, + &builder.src, + &["compiler"], + &[], + &tarball.image_dir().join("lib/rustlib/rustc-src/rust"), + ); + for file in src_files { + tarball.add_file(builder.src.join(file), "lib/rustlib/rustc-src/rust", 0o644); } - let mut cmd = rust_installer(builder); - cmd.arg("generate") - .arg("--product-name=Rust") - .arg("--rel-manifest-dir=rustlib") - .arg("--success-message=Rust-is-ready-to-develop.") - .arg("--image-dir") - .arg(&image) - .arg("--work-dir") - .arg(&tmpdir(builder)) - .arg("--output-dir") - .arg(&distdir(builder)) - .arg(format!("--package-name={}-{}", name, target.triple)) - .arg(format!("--component-name=rustc-dev-{}", target.triple)) - .arg("--legacy-manifest-dirs=rustlib,cargo"); - - builder.info(&format!( - "Dist rustc-dev stage{} ({} -> {})", - compiler.stage, &compiler.host, target - )); - let _time = timeit(builder); - builder.run(&mut cmd); - builder.remove_dir(&image); - archive + Some(tarball.generate()) } } @@ -835,7 +660,7 @@ pub struct Analysis { } impl Step for Analysis { - type Output = PathBuf; + type Output = Option; const DEFAULT: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { @@ -858,52 +683,26 @@ fn make_run(run: RunConfig<'_>) { } /// Creates a tarball of save-analysis metadata, if available. - fn run(self, builder: &Builder<'_>) -> PathBuf { + fn run(self, builder: &Builder<'_>) -> Option { let compiler = self.compiler; let target = self.target; assert!(builder.config.extended); - let name = pkgname(builder, "rust-analysis"); - if compiler.host != builder.config.build { - return distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple)); + return None; } builder.ensure(compile::Std { compiler, target }); - - let image = tmpdir(builder).join(format!("{}-{}-image", name, target.triple)); - let src = builder .stage_out(compiler, Mode::Std) .join(target.triple) .join(builder.cargo_dir()) - .join("deps"); + .join("deps") + .join("save-analysis"); - let image_src = src.join("save-analysis"); - let dst = image.join("lib/rustlib").join(target.triple).join("analysis"); - t!(fs::create_dir_all(&dst)); - builder.info(&format!("image_src: {:?}, dst: {:?}", image_src, dst)); - builder.cp_r(&image_src, &dst); - - let mut cmd = rust_installer(builder); - cmd.arg("generate") - .arg("--product-name=Rust") - .arg("--rel-manifest-dir=rustlib") - .arg("--success-message=save-analysis-saved.") - .arg("--image-dir") - .arg(&image) - .arg("--work-dir") - .arg(&tmpdir(builder)) - .arg("--output-dir") - .arg(&distdir(builder)) - .arg(format!("--package-name={}-{}", name, target.triple)) - .arg(format!("--component-name=rust-analysis-{}", target.triple)) - .arg("--legacy-manifest-dirs=rustlib,cargo"); - - builder.info("Dist analysis"); - let _time = timeit(builder); - builder.run(&mut cmd); - builder.remove_dir(&image); - distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple)) + let mut tarball = Tarball::new(builder, "rust-analysis", &target.triple); + tarball.include_target_in_component_name(true); + tarball.add_dir(src, format!("lib/rustlib/{}/analysis", target.triple)); + Some(tarball.generate()) } } @@ -1011,9 +810,7 @@ fn make_run(run: RunConfig<'_>) { /// Creates the `rust-src` installer component fn run(self, builder: &Builder<'_>) -> PathBuf { - let name = pkgname(builder, "rust-src"); - let image = tmpdir(builder).join(format!("{}-image", name)); - let _ = fs::remove_dir_all(&image); + let tarball = Tarball::new_targetless(builder, "rust-src"); // A lot of tools expect the rust-src component to be entirely in this directory, so if you // change that (e.g. by adding another directory `lib/rustlib/src/foo` or @@ -1022,8 +819,7 @@ fn run(self, builder: &Builder<'_>) -> PathBuf { // // NOTE: if you update the paths here, you also should update the "virtual" path // translation code in `imported_source_files` in `src/librustc_metadata/rmeta/decoder.rs` - let dst_src = image.join("lib/rustlib/src/rust"); - t!(fs::create_dir_all(&dst_src)); + let dst_src = tarball.image_dir().join("lib/rustlib/src/rust"); let src_files = ["Cargo.lock"]; // This is the reduced set of paths which will become the rust-src component @@ -1043,28 +839,7 @@ fn run(self, builder: &Builder<'_>) -> PathBuf { builder.copy(&builder.src.join(file), &dst_src.join(file)); } - // Create source tarball in rust-installer format - let mut cmd = rust_installer(builder); - cmd.arg("generate") - .arg("--product-name=Rust") - .arg("--rel-manifest-dir=rustlib") - .arg("--success-message=Awesome-Source.") - .arg("--image-dir") - .arg(&image) - .arg("--work-dir") - .arg(&tmpdir(builder)) - .arg("--output-dir") - .arg(&distdir(builder)) - .arg(format!("--package-name={}", name)) - .arg("--component-name=rust-src") - .arg("--legacy-manifest-dirs=rustlib,cargo"); - - builder.info("Dist src"); - let _time = timeit(builder); - builder.run(&mut cmd); - - builder.remove_dir(&image); - distdir(builder).join(&format!("{}.tar.gz", name)) + tarball.generate() } } @@ -1088,11 +863,8 @@ fn make_run(run: RunConfig<'_>) { /// Creates the plain source tarball fn run(self, builder: &Builder<'_>) -> PathBuf { - // Make sure that the root folder of tarball has the correct name - let plain_name = format!("{}-src", pkgname(builder, "rustc")); - let plain_dst_src = tmpdir(builder).join(&plain_name); - let _ = fs::remove_dir_all(&plain_dst_src); - t!(fs::create_dir_all(&plain_dst_src)); + let tarball = Tarball::new(builder, "rustc", "src"); + let plain_dst_src = tarball.image_dir(); // This is the set of root paths which will become part of the source package let src_files = [ @@ -1135,28 +907,7 @@ fn run(self, builder: &Builder<'_>) -> PathBuf { builder.run(&mut cmd); } - // Create plain source tarball - let plain_name = format!("rustc-{}-src", builder.rust_package_vers()); - let mut tarball = distdir(builder).join(&format!("{}.tar.gz", plain_name)); - tarball.set_extension(""); // strip .gz - tarball.set_extension(""); // strip .tar - if let Some(dir) = tarball.parent() { - builder.create_dir(&dir); - } - builder.info("running installer"); - let mut cmd = rust_installer(builder); - cmd.arg("tarball") - .arg("--input") - .arg(&plain_name) - .arg("--output") - .arg(&tarball) - .arg("--work-dir=.") - .current_dir(tmpdir(builder)); - - builder.info("Create plain source tarball"); - let _time = timeit(builder); - builder.run(&mut cmd); - distdir(builder).join(&format!("{}.tar.gz", plain_name)) + tarball.bare() } } @@ -1212,72 +963,28 @@ fn run(self, builder: &Builder<'_>) -> PathBuf { let compiler = self.compiler; let target = self.target; + let cargo = builder.ensure(tool::Cargo { compiler, target }); let src = builder.src.join("src/tools/cargo"); let etc = src.join("src/etc"); - let release_num = builder.release_num("cargo"); - let name = pkgname(builder, "cargo"); - let version = builder.cargo_info.version(builder, &release_num); - - let tmp = tmpdir(builder); - let image = tmp.join("cargo-image"); - drop(fs::remove_dir_all(&image)); - builder.create_dir(&image); // Prepare the image directory - builder.create_dir(&image.join("share/zsh/site-functions")); - builder.create_dir(&image.join("etc/bash_completion.d")); - let cargo = builder.ensure(tool::Cargo { compiler, target }); - builder.install(&cargo, &image.join("bin"), 0o755); + let mut tarball = Tarball::new(builder, "cargo", &target.triple); + tarball.set_overlay(OverlayKind::Cargo); + + tarball.add_file(&cargo, "bin", 0o755); + tarball.add_file(etc.join("_cargo"), "share/zsh/site-functions", 0o644); + tarball.add_renamed_file(etc.join("cargo.bashcomp.sh"), "etc/bash_completion.d", "cargo"); + tarball.add_dir(etc.join("man"), "share/man/man1"); + tarball.add_legal_and_readme_to("share/doc/cargo"); + for dirent in fs::read_dir(cargo.parent().unwrap()).expect("read_dir") { let dirent = dirent.expect("read dir entry"); if dirent.file_name().to_str().expect("utf8").starts_with("cargo-credential-") { - builder.install(&dirent.path(), &image.join("libexec"), 0o755); + tarball.add_file(&dirent.path(), "libexec", 0o755); } } - for man in t!(etc.join("man").read_dir()) { - let man = t!(man); - builder.install(&man.path(), &image.join("share/man/man1"), 0o644); - } - builder.install(&etc.join("_cargo"), &image.join("share/zsh/site-functions"), 0o644); - builder.copy(&etc.join("cargo.bashcomp.sh"), &image.join("etc/bash_completion.d/cargo")); - let doc = image.join("share/doc/cargo"); - builder.install(&src.join("README.md"), &doc, 0o644); - builder.install(&src.join("LICENSE-MIT"), &doc, 0o644); - builder.install(&src.join("LICENSE-APACHE"), &doc, 0o644); - builder.install(&src.join("LICENSE-THIRD-PARTY"), &doc, 0o644); - - // Prepare the overlay - let overlay = tmp.join("cargo-overlay"); - drop(fs::remove_dir_all(&overlay)); - builder.create_dir(&overlay); - builder.install(&src.join("README.md"), &overlay, 0o644); - builder.install(&src.join("LICENSE-MIT"), &overlay, 0o644); - builder.install(&src.join("LICENSE-APACHE"), &overlay, 0o644); - builder.install(&src.join("LICENSE-THIRD-PARTY"), &overlay, 0o644); - builder.create(&overlay.join("version"), &version); - - // Generate the installer tarball - let mut cmd = rust_installer(builder); - cmd.arg("generate") - .arg("--product-name=Rust") - .arg("--rel-manifest-dir=rustlib") - .arg("--success-message=Rust-is-ready-to-roll.") - .arg("--image-dir") - .arg(&image) - .arg("--work-dir") - .arg(&tmpdir(builder)) - .arg("--output-dir") - .arg(&distdir(builder)) - .arg("--non-installed-overlay") - .arg(&overlay) - .arg(format!("--package-name={}-{}", name, target.triple)) - .arg("--component-name=cargo") - .arg("--legacy-manifest-dirs=rustlib,cargo"); - - builder.info(&format!("Dist cargo stage{} ({})", compiler.stage, target)); - let _time = timeit(builder); - builder.run(&mut cmd); - distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple)) + + tarball.generate() } } @@ -1311,19 +1018,6 @@ fn run(self, builder: &Builder<'_>) -> Option { let target = self.target; assert!(builder.config.extended); - let src = builder.src.join("src/tools/rls"); - let release_num = builder.release_num("rls"); - let name = pkgname(builder, "rls"); - let version = builder.rls_info.version(builder, &release_num); - - let tmp = tmpdir(builder); - let image = tmp.join("rls-image"); - drop(fs::remove_dir_all(&image)); - t!(fs::create_dir_all(&image)); - - // Prepare the image directory - // We expect RLS to build, because we've exited this step above if tool - // state for RLS isn't testing. let rls = builder .ensure(tool::Rls { compiler, target, extra_features: Vec::new() }) .or_else(|| { @@ -1331,43 +1025,12 @@ fn run(self, builder: &Builder<'_>) -> Option { None })?; - builder.install(&rls, &image.join("bin"), 0o755); - let doc = image.join("share/doc/rls"); - builder.install(&src.join("README.md"), &doc, 0o644); - builder.install(&src.join("LICENSE-MIT"), &doc, 0o644); - builder.install(&src.join("LICENSE-APACHE"), &doc, 0o644); - - // Prepare the overlay - let overlay = tmp.join("rls-overlay"); - drop(fs::remove_dir_all(&overlay)); - t!(fs::create_dir_all(&overlay)); - builder.install(&src.join("README.md"), &overlay, 0o644); - builder.install(&src.join("LICENSE-MIT"), &overlay, 0o644); - builder.install(&src.join("LICENSE-APACHE"), &overlay, 0o644); - builder.create(&overlay.join("version"), &version); - - // Generate the installer tarball - let mut cmd = rust_installer(builder); - cmd.arg("generate") - .arg("--product-name=Rust") - .arg("--rel-manifest-dir=rustlib") - .arg("--success-message=RLS-ready-to-serve.") - .arg("--image-dir") - .arg(&image) - .arg("--work-dir") - .arg(&tmpdir(builder)) - .arg("--output-dir") - .arg(&distdir(builder)) - .arg("--non-installed-overlay") - .arg(&overlay) - .arg(format!("--package-name={}-{}", name, target.triple)) - .arg("--legacy-manifest-dirs=rustlib,cargo") - .arg("--component-name=rls-preview"); - - builder.info(&format!("Dist RLS stage{} ({})", compiler.stage, target.triple)); - let _time = timeit(builder); - builder.run(&mut cmd); - Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple))) + let mut tarball = Tarball::new(builder, "rls", &target.triple); + tarball.set_overlay(OverlayKind::RLS); + tarball.is_preview(true); + tarball.add_file(rls, "bin", 0o755); + tarball.add_legal_and_readme_to("share/doc/rls"); + Some(tarball.generate()) } } @@ -1407,60 +1070,16 @@ fn run(self, builder: &Builder<'_>) -> Option { return None; } - let src = builder.src.join("src/tools/rust-analyzer"); - let release_num = builder.release_num("rust-analyzer/crates/rust-analyzer"); - let name = pkgname(builder, "rust-analyzer"); - let version = builder.rust_analyzer_info.version(builder, &release_num); - - let tmp = tmpdir(builder); - let image = tmp.join("rust-analyzer-image"); - drop(fs::remove_dir_all(&image)); - builder.create_dir(&image); - - // Prepare the image directory - // We expect rust-analyer to always build, as it doesn't depend on rustc internals - // and doesn't have associated toolstate. let rust_analyzer = builder .ensure(tool::RustAnalyzer { compiler, target, extra_features: Vec::new() }) .expect("rust-analyzer always builds"); - builder.install(&rust_analyzer, &image.join("bin"), 0o755); - let doc = image.join("share/doc/rust-analyzer"); - builder.install(&src.join("README.md"), &doc, 0o644); - builder.install(&src.join("LICENSE-APACHE"), &doc, 0o644); - builder.install(&src.join("LICENSE-MIT"), &doc, 0o644); - - // Prepare the overlay - let overlay = tmp.join("rust-analyzer-overlay"); - drop(fs::remove_dir_all(&overlay)); - t!(fs::create_dir_all(&overlay)); - builder.install(&src.join("README.md"), &overlay, 0o644); - builder.install(&src.join("LICENSE-APACHE"), &doc, 0o644); - builder.install(&src.join("LICENSE-MIT"), &doc, 0o644); - builder.create(&overlay.join("version"), &version); - - // Generate the installer tarball - let mut cmd = rust_installer(builder); - cmd.arg("generate") - .arg("--product-name=Rust") - .arg("--rel-manifest-dir=rustlib") - .arg("--success-message=rust-analyzer-ready-to-serve.") - .arg("--image-dir") - .arg(&image) - .arg("--work-dir") - .arg(&tmpdir(builder)) - .arg("--output-dir") - .arg(&distdir(builder)) - .arg("--non-installed-overlay") - .arg(&overlay) - .arg(format!("--package-name={}-{}", name, target.triple)) - .arg("--legacy-manifest-dirs=rustlib,cargo") - .arg("--component-name=rust-analyzer-preview"); - - builder.info(&format!("Dist rust-analyzer stage{} ({})", compiler.stage, target)); - let _time = timeit(builder); - builder.run(&mut cmd); - Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple))) + let mut tarball = Tarball::new(builder, "rust-analyzer", &target.triple); + tarball.set_overlay(OverlayKind::RustAnalyzer); + tarball.is_preview(true); + tarball.add_file(rust_analyzer, "bin", 0o755); + tarball.add_legal_and_readme_to("share/doc/rust-analyzer"); + Some(tarball.generate()) } } @@ -1494,16 +1113,6 @@ fn run(self, builder: &Builder<'_>) -> PathBuf { let target = self.target; assert!(builder.config.extended); - let src = builder.src.join("src/tools/clippy"); - let release_num = builder.release_num("clippy"); - let name = pkgname(builder, "clippy"); - let version = builder.clippy_info.version(builder, &release_num); - - let tmp = tmpdir(builder); - let image = tmp.join("clippy-image"); - drop(fs::remove_dir_all(&image)); - builder.create_dir(&image); - // Prepare the image directory // We expect clippy to build, because we've exited this step above if tool // state for clippy isn't testing. @@ -1514,44 +1123,13 @@ fn run(self, builder: &Builder<'_>) -> PathBuf { .ensure(tool::CargoClippy { compiler, target, extra_features: Vec::new() }) .expect("clippy expected to build - essential tool"); - builder.install(&clippy, &image.join("bin"), 0o755); - builder.install(&cargoclippy, &image.join("bin"), 0o755); - let doc = image.join("share/doc/clippy"); - builder.install(&src.join("README.md"), &doc, 0o644); - builder.install(&src.join("LICENSE-APACHE"), &doc, 0o644); - builder.install(&src.join("LICENSE-MIT"), &doc, 0o644); - - // Prepare the overlay - let overlay = tmp.join("clippy-overlay"); - drop(fs::remove_dir_all(&overlay)); - t!(fs::create_dir_all(&overlay)); - builder.install(&src.join("README.md"), &overlay, 0o644); - builder.install(&src.join("LICENSE-APACHE"), &doc, 0o644); - builder.install(&src.join("LICENSE-MIT"), &doc, 0o644); - builder.create(&overlay.join("version"), &version); - - // Generate the installer tarball - let mut cmd = rust_installer(builder); - cmd.arg("generate") - .arg("--product-name=Rust") - .arg("--rel-manifest-dir=rustlib") - .arg("--success-message=clippy-ready-to-serve.") - .arg("--image-dir") - .arg(&image) - .arg("--work-dir") - .arg(&tmpdir(builder)) - .arg("--output-dir") - .arg(&distdir(builder)) - .arg("--non-installed-overlay") - .arg(&overlay) - .arg(format!("--package-name={}-{}", name, target.triple)) - .arg("--legacy-manifest-dirs=rustlib,cargo") - .arg("--component-name=clippy-preview"); - - builder.info(&format!("Dist clippy stage{} ({})", compiler.stage, target)); - let _time = timeit(builder); - builder.run(&mut cmd); - distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple)) + let mut tarball = Tarball::new(builder, "clippy", &target.triple); + tarball.set_overlay(OverlayKind::Clippy); + tarball.is_preview(true); + tarball.add_file(clippy, "bin", 0o755); + tarball.add_file(cargoclippy, "bin", 0o755); + tarball.add_legal_and_readme_to("share/doc/clippy"); + tarball.generate() } } @@ -1585,19 +1163,6 @@ fn run(self, builder: &Builder<'_>) -> Option { let target = self.target; assert!(builder.config.extended); - let src = builder.src.join("src/tools/miri"); - let release_num = builder.release_num("miri"); - let name = pkgname(builder, "miri"); - let version = builder.miri_info.version(builder, &release_num); - - let tmp = tmpdir(builder); - let image = tmp.join("miri-image"); - drop(fs::remove_dir_all(&image)); - builder.create_dir(&image); - - // Prepare the image directory - // We expect miri to build, because we've exited this step above if tool - // state for miri isn't testing. let miri = builder .ensure(tool::Miri { compiler, target, extra_features: Vec::new() }) .or_else(|| { @@ -1611,44 +1176,13 @@ fn run(self, builder: &Builder<'_>) -> Option { None })?; - builder.install(&miri, &image.join("bin"), 0o755); - builder.install(&cargomiri, &image.join("bin"), 0o755); - let doc = image.join("share/doc/miri"); - builder.install(&src.join("README.md"), &doc, 0o644); - builder.install(&src.join("LICENSE-APACHE"), &doc, 0o644); - builder.install(&src.join("LICENSE-MIT"), &doc, 0o644); - - // Prepare the overlay - let overlay = tmp.join("miri-overlay"); - drop(fs::remove_dir_all(&overlay)); - t!(fs::create_dir_all(&overlay)); - builder.install(&src.join("README.md"), &overlay, 0o644); - builder.install(&src.join("LICENSE-APACHE"), &doc, 0o644); - builder.install(&src.join("LICENSE-MIT"), &doc, 0o644); - builder.create(&overlay.join("version"), &version); - - // Generate the installer tarball - let mut cmd = rust_installer(builder); - cmd.arg("generate") - .arg("--product-name=Rust") - .arg("--rel-manifest-dir=rustlib") - .arg("--success-message=miri-ready-to-serve.") - .arg("--image-dir") - .arg(&image) - .arg("--work-dir") - .arg(&tmpdir(builder)) - .arg("--output-dir") - .arg(&distdir(builder)) - .arg("--non-installed-overlay") - .arg(&overlay) - .arg(format!("--package-name={}-{}", name, target.triple)) - .arg("--legacy-manifest-dirs=rustlib,cargo") - .arg("--component-name=miri-preview"); - - builder.info(&format!("Dist miri stage{} ({})", compiler.stage, target)); - let _time = timeit(builder); - builder.run(&mut cmd); - Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple))) + let mut tarball = Tarball::new(builder, "miri", &target.triple); + tarball.set_overlay(OverlayKind::Miri); + tarball.is_preview(true); + tarball.add_file(miri, "bin", 0o755); + tarball.add_file(cargomiri, "bin", 0o755); + tarball.add_legal_and_readme_to("share/doc/miri"); + Some(tarball.generate()) } } @@ -1681,17 +1215,6 @@ fn run(self, builder: &Builder<'_>) -> Option { let compiler = self.compiler; let target = self.target; - let src = builder.src.join("src/tools/rustfmt"); - let release_num = builder.release_num("rustfmt"); - let name = pkgname(builder, "rustfmt"); - let version = builder.rustfmt_info.version(builder, &release_num); - - let tmp = tmpdir(builder); - let image = tmp.join("rustfmt-image"); - drop(fs::remove_dir_all(&image)); - builder.create_dir(&image); - - // Prepare the image directory let rustfmt = builder .ensure(tool::Rustfmt { compiler, target, extra_features: Vec::new() }) .or_else(|| { @@ -1705,44 +1228,13 @@ fn run(self, builder: &Builder<'_>) -> Option { None })?; - builder.install(&rustfmt, &image.join("bin"), 0o755); - builder.install(&cargofmt, &image.join("bin"), 0o755); - let doc = image.join("share/doc/rustfmt"); - builder.install(&src.join("README.md"), &doc, 0o644); - builder.install(&src.join("LICENSE-MIT"), &doc, 0o644); - builder.install(&src.join("LICENSE-APACHE"), &doc, 0o644); - - // Prepare the overlay - let overlay = tmp.join("rustfmt-overlay"); - drop(fs::remove_dir_all(&overlay)); - builder.create_dir(&overlay); - builder.install(&src.join("README.md"), &overlay, 0o644); - builder.install(&src.join("LICENSE-MIT"), &overlay, 0o644); - builder.install(&src.join("LICENSE-APACHE"), &overlay, 0o644); - builder.create(&overlay.join("version"), &version); - - // Generate the installer tarball - let mut cmd = rust_installer(builder); - cmd.arg("generate") - .arg("--product-name=Rust") - .arg("--rel-manifest-dir=rustlib") - .arg("--success-message=rustfmt-ready-to-fmt.") - .arg("--image-dir") - .arg(&image) - .arg("--work-dir") - .arg(&tmpdir(builder)) - .arg("--output-dir") - .arg(&distdir(builder)) - .arg("--non-installed-overlay") - .arg(&overlay) - .arg(format!("--package-name={}-{}", name, target.triple)) - .arg("--legacy-manifest-dirs=rustlib,cargo") - .arg("--component-name=rustfmt-preview"); - - builder.info(&format!("Dist Rustfmt stage{} ({})", compiler.stage, target)); - let _time = timeit(builder); - builder.run(&mut cmd); - Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple))) + let mut tarball = Tarball::new(builder, "rustfmt", &target.triple); + tarball.set_overlay(OverlayKind::Rustfmt); + tarball.is_preview(true); + tarball.add_file(rustfmt, "bin", 0o755); + tarball.add_file(cargofmt, "bin", 0o755); + tarball.add_legal_and_readme_to("share/doc/rustfmt"); + Some(tarball.generate()) } } @@ -1791,24 +1283,14 @@ fn run(self, builder: &Builder<'_>) { let analysis_installer = builder.ensure(Analysis { compiler, target }); let docs_installer = builder.ensure(Docs { host: target }); - let std_installer = - builder.ensure(Std { compiler: builder.compiler(stage, target), target }); + let std_installer = builder.ensure(Std { compiler, target }); - let tmp = tmpdir(builder); - let overlay = tmp.join("extended-overlay"); let etc = builder.src.join("src/etc/installer"); - let work = tmp.join("work"); - - let _ = fs::remove_dir_all(&overlay); - builder.install(&builder.src.join("COPYRIGHT"), &overlay, 0o644); - builder.install(&builder.src.join("LICENSE-APACHE"), &overlay, 0o644); - builder.install(&builder.src.join("LICENSE-MIT"), &overlay, 0o644); - let version = builder.rust_version(); - builder.create(&overlay.join("version"), &version); - if let Some(sha) = builder.rust_sha() { - builder.create(&overlay.join("git-commit-hash"), &sha); + + // Avoid producing tarballs during a dry run. + if builder.config.dry_run { + return; } - builder.install(&etc.join("README.md"), &overlay, 0o644); // When rust-std package split from rustc, we needed to ensure that during // upgrades rustc was upgraded before rust-std. To avoid rustc clobbering @@ -1823,39 +1305,22 @@ fn run(self, builder: &Builder<'_>) { tarballs.extend(miri_installer.clone()); tarballs.extend(rustfmt_installer.clone()); tarballs.extend(llvm_tools_installer); - tarballs.push(analysis_installer); - tarballs.push(std_installer); - if builder.config.docs { + if let Some(analysis_installer) = analysis_installer { + tarballs.push(analysis_installer); + } + tarballs.push(std_installer.expect("missing std")); + if let Some(docs_installer) = docs_installer { tarballs.push(docs_installer); } if target.contains("pc-windows-gnu") { tarballs.push(mingw_installer.unwrap()); } - let mut input_tarballs = tarballs[0].as_os_str().to_owned(); - for tarball in &tarballs[1..] { - input_tarballs.push(","); - input_tarballs.push(tarball); - } - builder.info("building combined installer"); - let mut cmd = rust_installer(builder); - cmd.arg("combine") - .arg("--product-name=Rust") - .arg("--rel-manifest-dir=rustlib") - .arg("--success-message=Rust-is-ready-to-roll.") - .arg("--work-dir") - .arg(&work) - .arg("--output-dir") - .arg(&distdir(builder)) - .arg(format!("--package-name={}-{}", pkgname(builder, "rust"), target.triple)) - .arg("--legacy-manifest-dirs=rustlib,cargo") - .arg("--input-tarballs") - .arg(input_tarballs) - .arg("--non-installed-overlay") - .arg(&overlay); - let time = timeit(&builder); - builder.run(&mut cmd); - drop(time); + let mut tarball = Tarball::new(builder, "rust", &target.triple); + let work = tarball.persist_work_dir(); + tarball.combine(&tarballs); + + let tmp = tmpdir(builder).join("combined-tarball"); let mut license = String::new(); license += &builder.read(&builder.src.join("COPYRIGHT")); @@ -2428,58 +1893,25 @@ fn run(self, builder: &Builder<'_>) -> Option { } } - builder.info(&format!("Dist LlvmTools ({})", target)); - let _time = timeit(builder); - let src = builder.src.join("src/llvm-project/llvm"); - let name = pkgname(builder, "llvm-tools"); - - let tmp = tmpdir(builder); - let image = tmp.join("llvm-tools-image"); - drop(fs::remove_dir_all(&image)); + let mut tarball = Tarball::new(builder, "llvm-tools", &target.triple); + tarball.set_overlay(OverlayKind::LLVM); + tarball.is_preview(true); // Prepare the image directory let src_bindir = builder.llvm_out(target).join("bin"); - let dst_bindir = image.join("lib/rustlib").join(&*target.triple).join("bin"); - t!(fs::create_dir_all(&dst_bindir)); + let dst_bindir = format!("lib/rustlib/{}/bin", target.triple); for tool in LLVM_TOOLS { let exe = src_bindir.join(exe(tool, target)); - builder.install(&exe, &dst_bindir, 0o755); + tarball.add_file(&exe, &dst_bindir, 0o755); } // Copy libLLVM.so to the target lib dir as well, so the RPATH like // `$ORIGIN/../lib` can find it. It may also be used as a dependency // of `rustc-dev` to support the inherited `-lLLVM` when using the // compiler libraries. - maybe_install_llvm_target(builder, target, &image); - - // Prepare the overlay - let overlay = tmp.join("llvm-tools-overlay"); - drop(fs::remove_dir_all(&overlay)); - builder.create_dir(&overlay); - builder.install(&src.join("README.txt"), &overlay, 0o644); - builder.install(&src.join("LICENSE.TXT"), &overlay, 0o644); - builder.create(&overlay.join("version"), &builder.llvm_tools_vers()); - - // Generate the installer tarball - let mut cmd = rust_installer(builder); - cmd.arg("generate") - .arg("--product-name=Rust") - .arg("--rel-manifest-dir=rustlib") - .arg("--success-message=llvm-tools-installed.") - .arg("--image-dir") - .arg(&image) - .arg("--work-dir") - .arg(&tmpdir(builder)) - .arg("--output-dir") - .arg(&distdir(builder)) - .arg("--non-installed-overlay") - .arg(&overlay) - .arg(format!("--package-name={}-{}", name, target.triple)) - .arg("--legacy-manifest-dirs=rustlib,cargo") - .arg("--component-name=llvm-tools-preview"); - - builder.run(&mut cmd); - Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple))) + maybe_install_llvm_target(builder, target, tarball.image_dir()); + + Some(tarball.generate()) } } @@ -2515,70 +1947,35 @@ fn run(self, builder: &Builder<'_>) -> Option { } } - builder.info(&format!("Dist RustDev ({})", target)); - let _time = timeit(builder); - let src = builder.src.join("src/llvm-project/llvm"); - let name = pkgname(builder, "rust-dev"); - - let tmp = tmpdir(builder); - let image = tmp.join("rust-dev-image"); - drop(fs::remove_dir_all(&image)); - - // Prepare the image directory - let dst_bindir = image.join("bin"); - t!(fs::create_dir_all(&dst_bindir)); + let mut tarball = Tarball::new(builder, "rust-dev", &target.triple); + tarball.set_overlay(OverlayKind::LLVM); let src_bindir = builder.llvm_out(target).join("bin"); - let install_bin = - |name| builder.install(&src_bindir.join(exe(name, target)), &dst_bindir, 0o755); - install_bin("llvm-config"); - install_bin("llvm-ar"); - install_bin("llvm-objdump"); - install_bin("llvm-profdata"); - install_bin("llvm-bcanalyzer"); - install_bin("llvm-cov"); - install_bin("llvm-dwp"); - builder.install(&builder.llvm_filecheck(target), &dst_bindir, 0o755); + for bin in &[ + "llvm-config", + "llvm-ar", + "llvm-objdump", + "llvm-profdata", + "llvm-bcanalyzer", + "llvm-cov", + "llvm-dwp", + ] { + tarball.add_file(src_bindir.join(exe(bin, target)), "bin", 0o755); + } + tarball.add_file(&builder.llvm_filecheck(target), "bin", 0o755); // Copy the include directory as well; needed mostly to build // librustc_llvm properly (e.g., llvm-config.h is in here). But also // just broadly useful to be able to link against the bundled LLVM. - builder.cp_r(&builder.llvm_out(target).join("include"), &image.join("include")); + tarball.add_dir(&builder.llvm_out(target).join("include"), "include"); // Copy libLLVM.so to the target lib dir as well, so the RPATH like // `$ORIGIN/../lib` can find it. It may also be used as a dependency // of `rustc-dev` to support the inherited `-lLLVM` when using the // compiler libraries. - maybe_install_llvm(builder, target, &image.join("lib")); - - // Prepare the overlay - let overlay = tmp.join("rust-dev-overlay"); - drop(fs::remove_dir_all(&overlay)); - builder.create_dir(&overlay); - builder.install(&src.join("README.txt"), &overlay, 0o644); - builder.install(&src.join("LICENSE.TXT"), &overlay, 0o644); - builder.create(&overlay.join("version"), &builder.rust_version()); - - // Generate the installer tarball - let mut cmd = rust_installer(builder); - cmd.arg("generate") - .arg("--product-name=Rust") - .arg("--rel-manifest-dir=rustlib") - .arg("--success-message=rust-dev-installed.") - .arg("--image-dir") - .arg(&image) - .arg("--work-dir") - .arg(&tmpdir(builder)) - .arg("--output-dir") - .arg(&distdir(builder)) - .arg("--non-installed-overlay") - .arg(&overlay) - .arg(format!("--package-name={}-{}", name, target.triple)) - .arg("--legacy-manifest-dirs=rustlib,cargo") - .arg("--component-name=rust-dev"); - - builder.run(&mut cmd); - Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple))) + maybe_install_llvm(builder, target, &tarball.image_dir().join("lib")); + + Some(tarball.generate()) } } @@ -2607,44 +2004,40 @@ fn make_run(run: RunConfig<'_>) { fn run(self, builder: &Builder<'_>) -> PathBuf { let build_manifest = builder.tool_exe(Tool::BuildManifest); - let name = pkgname(builder, "build-manifest"); - let tmp = tmpdir(builder); - - // Prepare the image. - let image = tmp.join("build-manifest-image"); - let image_bin = image.join("bin"); - let _ = fs::remove_dir_all(&image); - t!(fs::create_dir_all(&image_bin)); - builder.install(&build_manifest, &image_bin, 0o755); - - // Prepare the overlay. - let overlay = tmp.join("build-manifest-overlay"); - let _ = fs::remove_dir_all(&overlay); - builder.create_dir(&overlay); - builder.create(&overlay.join("version"), &builder.rust_version()); - for file in &["COPYRIGHT", "LICENSE-APACHE", "LICENSE-MIT", "README.md"] { - builder.install(&builder.src.join(file), &overlay, 0o644); - } + let tarball = Tarball::new(builder, "build-manifest", &self.target.triple); + tarball.add_file(&build_manifest, "bin", 0o755); + tarball.generate() + } +} + +/// Tarball containing artifacts necessary to reproduce the build of rustc. +/// +/// Currently this is the PGO profile data. +/// +/// Should not be considered stable by end users. +#[derive(Clone, Debug, Eq, Hash, PartialEq)] +pub struct ReproducibleArtifacts { + pub target: TargetSelection, +} + +impl Step for ReproducibleArtifacts { + type Output = Option; + const DEFAULT: bool = true; + const ONLY_HOSTS: bool = true; + + fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + run.path("reproducible") + } + + fn make_run(run: RunConfig<'_>) { + run.builder.ensure(ReproducibleArtifacts { target: run.target }); + } + + fn run(self, builder: &Builder<'_>) -> Self::Output { + let path = builder.config.rust_profile_use.as_ref()?; - // Create the final tarball. - let mut cmd = rust_installer(builder); - cmd.arg("generate") - .arg("--product-name=Rust") - .arg("--rel-manifest-dir=rustlib") - .arg("--success-message=build-manifest installed.") - .arg("--image-dir") - .arg(&image) - .arg("--work-dir") - .arg(&tmpdir(builder)) - .arg("--output-dir") - .arg(&distdir(builder)) - .arg("--non-installed-overlay") - .arg(&overlay) - .arg(format!("--package-name={}-{}", name, self.target.triple)) - .arg("--legacy-manifest-dirs=rustlib,cargo") - .arg("--component-name=build-manifest"); - - builder.run(&mut cmd); - distdir(builder).join(format!("{}-{}.tar.gz", name, self.target.triple)) + let tarball = Tarball::new(builder, "reproducible-artifacts", &self.target.triple); + tarball.add_file(path, ".", 0o644); + Some(tarball.generate()) } } diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 8cacc2512ef..8c849846676 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -500,18 +500,17 @@ fn run(self, builder: &Builder<'_>) { let target = self.target; builder.info(&format!("Documenting stage{} compiler ({})", stage, target)); - // This is the intended out directory for compiler documentation. - let out = builder.compiler_doc_out(target); - t!(fs::create_dir_all(&out)); - - let compiler = builder.compiler(stage, builder.config.build); - if !builder.config.compiler_docs { builder.info("\tskipping - compiler/librustdoc docs disabled"); return; } + // This is the intended out directory for compiler documentation. + let out = builder.compiler_doc_out(target); + t!(fs::create_dir_all(&out)); + // Build rustc. + let compiler = builder.compiler(stage, builder.config.build); builder.ensure(compile::Rustc { compiler, target }); // This uses a shared directory so that librustdoc documentation gets @@ -521,16 +520,17 @@ fn run(self, builder: &Builder<'_>) { // merging the search index, or generating local (relative) links. let out_dir = builder.stage_out(compiler, Mode::Rustc).join(target.triple).join("doc"); t!(symlink_dir_force(&builder.config, &out, &out_dir)); + // Cargo puts proc macros in `target/doc` even if you pass `--target` + // explicitly (https://github.com/rust-lang/cargo/issues/7677). + let proc_macro_out_dir = builder.stage_out(compiler, Mode::Rustc).join("doc"); + t!(symlink_dir_force(&builder.config, &out, &proc_macro_out_dir)); // Build cargo command. let mut cargo = builder.cargo(compiler, Mode::Rustc, SourceType::InTree, target, "doc"); cargo.rustdocflag("--document-private-items"); cargo.rustdocflag("--enable-index-page"); cargo.rustdocflag("-Zunstable-options"); - // cfg(not(bootstrap)), can be removed on the next beta bump - if stage != 0 { - cargo.rustdocflag("-Znormalize-docs"); - } + cargo.rustdocflag("-Znormalize-docs"); compile::rustc_cargo(builder, &mut cargo, target); // Only include compiler crates, no dependencies of those, such as `libc`. @@ -628,6 +628,8 @@ fn run(self, builder: &Builder<'_>) { cargo.arg("-p").arg("rustdoc"); cargo.rustdocflag("--document-private-items"); + cargo.rustdocflag("--enable-index-page"); + cargo.rustdocflag("-Zunstable-options"); builder.run(&mut cargo.into()); } } diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index 5a8096674c6..d6a45f1c170 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -68,6 +68,9 @@ pub struct Flags { pub deny_warnings: Option, pub llvm_skip_rebuild: Option, + + pub rust_profile_use: Option, + pub rust_profile_generate: Option, } pub enum Subcommand { @@ -219,6 +222,8 @@ pub fn parse(args: &[String]) -> Flags { VALUE overrides the skip-rebuild option in config.toml.", "VALUE", ); + opts.optopt("", "rust-profile-generate", "rustc error format", "FORMAT"); + opts.optopt("", "rust-profile-use", "rustc error format", "FORMAT"); // We can't use getopt to parse the options until we have completed specifying which // options are valid, but under the current implementation, some options are conditional on @@ -674,6 +679,8 @@ pub fn parse(args: &[String]) -> Flags { color: matches .opt_get_default("color", Color::Auto) .expect("`color` should be `always`, `never`, or `auto`"), + rust_profile_use: matches.opt_str("rust-profile-use"), + rust_profile_generate: matches.opt_str("rust-profile-generate"), } } } diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index ece9bdc7a64..a47ddfbcc1f 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -142,6 +142,7 @@ mod run; mod sanity; mod setup; +mod tarball; mod test; mod tool; mod toolstate; @@ -1068,10 +1069,6 @@ fn rust_package_vers(&self) -> String { self.package_vers(&self.version) } - fn llvm_tools_vers(&self) -> String { - self.rust_version() - } - fn llvm_link_tools_dynamically(&self, target: TargetSelection) -> bool { target.contains("linux-gnu") || target.contains("apple-darwin") } diff --git a/src/bootstrap/mk/Makefile.in b/src/bootstrap/mk/Makefile.in index 1564cfb0619..fd39944e176 100644 --- a/src/bootstrap/mk/Makefile.in +++ b/src/bootstrap/mk/Makefile.in @@ -66,7 +66,6 @@ check-stage2-T-x86_64-unknown-linux-musl-H-x86_64-unknown-linux-gnu: TESTS_IN_2 := \ src/test/ui \ - src/test/compile-fail \ src/tools/linkchecker ci-subset-1: @@ -75,8 +74,7 @@ ci-subset-2: $(Q)$(BOOTSTRAP) test --stage 2 $(TESTS_IN_2) TESTS_IN_MINGW_2 := \ - src/test/ui \ - src/test/compile-fail + src/test/ui ci-mingw-subset-1: $(Q)$(BOOTSTRAP) test --stage 2 $(TESTS_IN_MINGW_2:%=--exclude %) diff --git a/src/bootstrap/tarball.rs b/src/bootstrap/tarball.rs new file mode 100644 index 00000000000..137370fe6cb --- /dev/null +++ b/src/bootstrap/tarball.rs @@ -0,0 +1,318 @@ +use std::{ + path::{Path, PathBuf}, + process::Command, +}; + +use build_helper::t; + +use crate::builder::Builder; + +#[derive(Copy, Clone)] +pub(crate) enum OverlayKind { + Rust, + LLVM, + Cargo, + Clippy, + Miri, + Rustfmt, + RLS, + RustAnalyzer, +} + +impl OverlayKind { + fn legal_and_readme(&self) -> &[&str] { + match self { + OverlayKind::Rust => &["COPYRIGHT", "LICENSE-APACHE", "LICENSE-MIT", "README.md"], + OverlayKind::LLVM => { + &["src/llvm-project/llvm/LICENSE.TXT", "src/llvm-project/llvm/README.txt"] + } + OverlayKind::Cargo => &[ + "src/tools/cargo/README.md", + "src/tools/cargo/LICENSE-MIT", + "src/tools/cargo/LICENSE-APACHE", + "src/tools/cargo/LICENSE-THIRD-PARTY", + ], + OverlayKind::Clippy => &[ + "src/tools/clippy/README.md", + "src/tools/clippy/LICENSE-APACHE", + "src/tools/clippy/LICENSE-MIT", + ], + OverlayKind::Miri => &[ + "src/tools/miri/README.md", + "src/tools/miri/LICENSE-APACHE", + "src/tools/miri/LICENSE-MIT", + ], + OverlayKind::Rustfmt => &[ + "src/tools/rustfmt/README.md", + "src/tools/rustfmt/LICENSE-APACHE", + "src/tools/rustfmt/LICENSE-MIT", + ], + OverlayKind::RLS => &[ + "src/tools/rls/README.md", + "src/tools/rls/LICENSE-APACHE", + "src/tools/rls/LICENSE-MIT", + ], + OverlayKind::RustAnalyzer => &[ + "src/tools/rust-analyzer/README.md", + "src/tools/rust-analyzer/LICENSE-APACHE", + "src/tools/rust-analyzer/LICENSE-MIT", + ], + } + } + + fn version(&self, builder: &Builder<'_>) -> String { + match self { + OverlayKind::Rust => builder.rust_version(), + OverlayKind::LLVM => builder.rust_version(), + OverlayKind::Cargo => { + builder.cargo_info.version(builder, &builder.release_num("cargo")) + } + OverlayKind::Clippy => { + builder.clippy_info.version(builder, &builder.release_num("clippy")) + } + OverlayKind::Miri => builder.miri_info.version(builder, &builder.release_num("miri")), + OverlayKind::Rustfmt => { + builder.rustfmt_info.version(builder, &builder.release_num("rustfmt")) + } + OverlayKind::RLS => builder.rls_info.version(builder, &builder.release_num("rls")), + OverlayKind::RustAnalyzer => builder + .rust_analyzer_info + .version(builder, &builder.release_num("rust-analyzer/crates/rust-analyzer")), + } + } +} + +pub(crate) struct Tarball<'a> { + builder: &'a Builder<'a>, + + pkgname: String, + component: String, + target: Option, + product_name: String, + overlay: OverlayKind, + + temp_dir: PathBuf, + image_dir: PathBuf, + overlay_dir: PathBuf, + + include_target_in_component_name: bool, + is_preview: bool, + delete_temp_dir: bool, +} + +impl<'a> Tarball<'a> { + pub(crate) fn new(builder: &'a Builder<'a>, component: &str, target: &str) -> Self { + Self::new_inner(builder, component, Some(target.into())) + } + + pub(crate) fn new_targetless(builder: &'a Builder<'a>, component: &str) -> Self { + Self::new_inner(builder, component, None) + } + + fn new_inner(builder: &'a Builder<'a>, component: &str, target: Option) -> Self { + let pkgname = crate::dist::pkgname(builder, component); + + let mut temp_dir = builder.out.join("tmp").join("tarball").join(component); + if let Some(target) = &target { + temp_dir = temp_dir.join(target); + } + let _ = std::fs::remove_dir_all(&temp_dir); + + let image_dir = temp_dir.join("image"); + let overlay_dir = temp_dir.join("overlay"); + + Self { + builder, + + pkgname, + component: component.into(), + target, + product_name: "Rust".into(), + overlay: OverlayKind::Rust, + + temp_dir, + image_dir, + overlay_dir, + + include_target_in_component_name: false, + is_preview: false, + delete_temp_dir: true, + } + } + + pub(crate) fn set_overlay(&mut self, overlay: OverlayKind) { + self.overlay = overlay; + } + + pub(crate) fn set_product_name(&mut self, name: &str) { + self.product_name = name.into(); + } + + pub(crate) fn include_target_in_component_name(&mut self, include: bool) { + self.include_target_in_component_name = include; + } + + pub(crate) fn is_preview(&mut self, is: bool) { + self.is_preview = is; + } + + pub(crate) fn image_dir(&self) -> &Path { + t!(std::fs::create_dir_all(&self.image_dir)); + &self.image_dir + } + + pub(crate) fn add_file(&self, src: impl AsRef, destdir: impl AsRef, perms: u32) { + // create_dir_all fails to create `foo/bar/.`, so when the destination is "." this simply + // uses the base directory as the destination directory. + let destdir = if destdir.as_ref() == Path::new(".") { + self.image_dir.clone() + } else { + self.image_dir.join(destdir.as_ref()) + }; + + t!(std::fs::create_dir_all(&destdir)); + self.builder.install(src.as_ref(), &destdir, perms); + } + + pub(crate) fn add_renamed_file( + &self, + src: impl AsRef, + destdir: impl AsRef, + new_name: &str, + ) { + let destdir = self.image_dir.join(destdir.as_ref()); + t!(std::fs::create_dir_all(&destdir)); + self.builder.copy(src.as_ref(), &destdir.join(new_name)); + } + + pub(crate) fn add_legal_and_readme_to(&self, destdir: impl AsRef) { + for file in self.overlay.legal_and_readme() { + self.add_file(self.builder.src.join(file), destdir.as_ref(), 0o644); + } + } + + pub(crate) fn add_dir(&self, src: impl AsRef, dest: impl AsRef) { + let dest = self.image_dir.join(dest.as_ref()); + + t!(std::fs::create_dir_all(&dest)); + self.builder.cp_r(src.as_ref(), &dest); + } + + pub(crate) fn persist_work_dir(&mut self) -> PathBuf { + self.delete_temp_dir = false; + self.temp_dir.clone() + } + + pub(crate) fn generate(self) -> PathBuf { + let mut component_name = self.component.clone(); + if self.is_preview { + component_name.push_str("-preview"); + } + if self.include_target_in_component_name { + component_name.push('-'); + component_name.push_str( + &self + .target + .as_ref() + .expect("include_target_in_component_name used in a targetless tarball"), + ); + } + + self.run(|this, cmd| { + cmd.arg("generate") + .arg("--image-dir") + .arg(&this.image_dir) + .arg(format!("--component-name={}", &component_name)); + this.non_bare_args(cmd); + }) + } + + pub(crate) fn combine(self, tarballs: &[PathBuf]) { + let mut input_tarballs = tarballs[0].as_os_str().to_os_string(); + for tarball in &tarballs[1..] { + input_tarballs.push(","); + input_tarballs.push(tarball); + } + + self.run(|this, cmd| { + cmd.arg("combine").arg("--input-tarballs").arg(input_tarballs); + this.non_bare_args(cmd); + }); + } + + pub(crate) fn bare(self) -> PathBuf { + // Bare tarballs should have the top level directory match the package + // name, not "image". We rename the image directory just before passing + // into rust-installer. + let dest = self.temp_dir.join(self.package_name()); + t!(std::fs::rename(&self.image_dir, &dest)); + + self.run(|this, cmd| { + cmd.arg("tarball") + .arg("--input") + .arg(&dest) + .arg("--output") + .arg(crate::dist::distdir(this.builder).join(this.package_name())); + }) + } + + fn package_name(&self) -> String { + if let Some(target) = &self.target { + format!("{}-{}", self.pkgname, target) + } else { + self.pkgname.clone() + } + } + + fn non_bare_args(&self, cmd: &mut Command) { + cmd.arg("--rel-manifest-dir=rustlib") + .arg("--legacy-manifest-dirs=rustlib,cargo") + .arg(format!("--product-name={}", self.product_name)) + .arg(format!("--success-message={} installed.", self.component)) + .arg(format!("--package-name={}", self.package_name())) + .arg("--non-installed-overlay") + .arg(&self.overlay_dir) + .arg("--output-dir") + .arg(crate::dist::distdir(self.builder)); + } + + fn run(self, build_cli: impl FnOnce(&Tarball<'a>, &mut Command)) -> PathBuf { + t!(std::fs::create_dir_all(&self.overlay_dir)); + self.builder.create(&self.overlay_dir.join("version"), &self.overlay.version(self.builder)); + if let Some(sha) = self.builder.rust_sha() { + self.builder.create(&self.overlay_dir.join("git-commit-hash"), &sha); + } + for file in self.overlay.legal_and_readme() { + self.builder.install(&self.builder.src.join(file), &self.overlay_dir, 0o644); + } + + let mut cmd = self.builder.tool_cmd(crate::tool::Tool::RustInstaller); + + let package_name = self.package_name(); + self.builder.info(&format!("Dist {}", package_name)); + let _time = crate::util::timeit(self.builder); + + build_cli(&self, &mut cmd); + cmd.arg("--work-dir").arg(&self.temp_dir); + if let Some(formats) = &self.builder.config.dist_compression_formats { + assert!(!formats.is_empty(), "dist.compression-formats can't be empty"); + cmd.arg("--compression-formats").arg(formats.join(",")); + } + self.builder.run(&mut cmd); + if self.delete_temp_dir { + t!(std::fs::remove_dir_all(&self.temp_dir)); + } + + // Use either the first compression format defined, or "gz" as the default. + let ext = self + .builder + .config + .dist_compression_formats + .as_ref() + .and_then(|formats| formats.get(0)) + .map(|s| s.as_str()) + .unwrap_or("gz"); + + crate::dist::distdir(self.builder).join(format!("{}.tar.{}", package_name, ext)) + } +} diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index b99692e8ba5..1f209f328a2 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -869,12 +869,6 @@ fn run(self, builder: &Builder<'_>) { compare_mode: "nll" }); -default_test!(CompileFail { - path: "src/test/compile-fail", - mode: "compile-fail", - suite: "compile-fail" -}); - default_test!(RunPassValgrind { path: "src/test/run-pass-valgrind", mode: "run-pass-valgrind", @@ -1968,7 +1962,7 @@ fn run(self, builder: &Builder<'_>) { builder.ensure(dist::Src); let mut cmd = Command::new("tar"); - cmd.arg("-xzf") + cmd.arg("-xf") .arg(builder.ensure(dist::PlainSourceTarball)) .arg("--strip-components=1") .current_dir(&dir); @@ -1992,10 +1986,7 @@ fn run(self, builder: &Builder<'_>) { t!(fs::create_dir_all(&dir)); let mut cmd = Command::new("tar"); - cmd.arg("-xzf") - .arg(builder.ensure(dist::Src)) - .arg("--strip-components=1") - .current_dir(&dir); + cmd.arg("-xf").arg(builder.ensure(dist::Src)).arg("--strip-components=1").current_dir(&dir); builder.run(&mut cmd); let toml = dir.join("rust-src/lib/rustlib/src/rust/library/std/Cargo.toml"); diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile index 14700aeea05..d1b4bbf7fff 100644 --- a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile @@ -85,6 +85,8 @@ ENV CC=clang CXX=clang++ COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh +ENV PGO_HOST=x86_64-unknown-linux-gnu + ENV HOSTS=x86_64-unknown-linux-gnu ENV RUST_CONFIGURE_ARGS \ @@ -98,9 +100,10 @@ ENV RUST_CONFIGURE_ARGS \ --set llvm.thin-lto=true \ --set llvm.ninja=false \ --set rust.jemalloc -ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS \ - --include-default-paths \ - src/tools/build-manifest +ENV SCRIPT ../src/ci/pgo.sh python2.7 ../x.py dist \ + --host $HOSTS --target $HOSTS \ + --include-default-paths \ + src/tools/build-manifest ENV CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER=clang # This is the only builder which will create source tarballs diff --git a/src/ci/docker/host-x86_64/test-various/Dockerfile b/src/ci/docker/host-x86_64/test-various/Dockerfile index 8653aecc12c..147de5f8015 100644 --- a/src/ci/docker/host-x86_64/test-various/Dockerfile +++ b/src/ci/docker/host-x86_64/test-various/Dockerfile @@ -44,7 +44,6 @@ ENV WASM_TARGETS=wasm32-unknown-unknown ENV WASM_SCRIPT python3 /checkout/x.py --stage 2 test --host='' --target $WASM_TARGETS \ src/test/run-make \ src/test/ui \ - src/test/compile-fail \ src/test/mir-opt \ src/test/codegen-units \ library/core diff --git a/src/ci/pgo.sh b/src/ci/pgo.sh new file mode 100755 index 00000000000..13b8ca91f89 --- /dev/null +++ b/src/ci/pgo.sh @@ -0,0 +1,47 @@ +#!/bin/bash + +set -euxo pipefail + +rm -rf /tmp/rustc-pgo + +python2.7 ../x.py build --target=$PGO_HOST --host=$PGO_HOST \ + --stage 2 library/std --rust-profile-generate=/tmp/rustc-pgo + +./build/$PGO_HOST/stage2/bin/rustc --edition=2018 \ + --crate-type=lib ../library/core/src/lib.rs + +# Download and build a single-file stress test benchmark on perf.rust-lang.org. +function pgo_perf_benchmark { + local PERF=e095f5021bf01cf3800f50b3a9f14a9683eb3e4e + local github_prefix=https://raw.githubusercontent.com/rust-lang/rustc-perf/$PERF + local name=$1 + curl -o /tmp/$name.rs $github_prefix/collector/benchmarks/$name/src/lib.rs + ./build/$PGO_HOST/stage2/bin/rustc --edition=2018 --crate-type=lib /tmp/$name.rs +} + +pgo_perf_benchmark externs +pgo_perf_benchmark ctfe-stress-4 + +cp -pri ../src/tools/cargo /tmp/cargo + +# Build cargo (with some flags) +function pgo_cargo { + RUSTC=./build/$PGO_HOST/stage2/bin/rustc \ + ./build/$PGO_HOST/stage0/bin/cargo $@ \ + --manifest-path /tmp/cargo/Cargo.toml +} + +# Build a couple different variants of Cargo +CARGO_INCREMENTAL=1 pgo_cargo check +echo 'pub fn barbarbar() {}' >> /tmp/cargo/src/cargo/lib.rs +CARGO_INCREMENTAL=1 pgo_cargo check +touch /tmp/cargo/src/cargo/lib.rs +CARGO_INCREMENTAL=1 pgo_cargo check +pgo_cargo build --release + +# Merge the profile data we gathered +./build/$PGO_HOST/llvm/bin/llvm-profdata \ + merge -o /tmp/rustc-pgo.profdata /tmp/rustc-pgo + +# This produces the actual final set of artifacts. +$@ --rust-profile-use=/tmp/rustc-pgo.profdata diff --git a/src/ci/run.sh b/src/ci/run.sh index 181a7fcb732..1958b6ee41d 100755 --- a/src/ci/run.sh +++ b/src/ci/run.sh @@ -53,6 +53,11 @@ RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-locked-deps" RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-cargo-native-static" RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set rust.codegen-units-std=1" +# Only produce xz tarballs on CI. gz tarballs will be generated by the release +# process by recompressing the existing xz ones. This decreases the storage +# space required for CI artifacts. +RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --dist-compression-formats=xz" + if [ "$DIST_SRC" = "" ]; then RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --disable-dist-src" fi diff --git a/src/doc/book b/src/doc/book index a190438d77d..5bb44f8b5b0 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit a190438d77d28041f24da4f6592e287fab073a61 +Subproject commit 5bb44f8b5b0aa105c8b22602e9b18800484afa21 diff --git a/src/doc/nomicon b/src/doc/nomicon index d8383b65f79..a5a48441d41 160000 --- a/src/doc/nomicon +++ b/src/doc/nomicon @@ -1 +1 @@ -Subproject commit d8383b65f7948c2ca19191b3b4bd709b403aaf45 +Subproject commit a5a48441d411f61556b57d762b03d6874afe575d diff --git a/src/doc/reference b/src/doc/reference index a8afdca5d07..b278478b766 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit a8afdca5d0715b2257b6f8b9a032fd4dd7dae855 +Subproject commit b278478b766178491a8b6f67afa4bcd6b64d977a diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index 236c734a2cb..1cce0737d6a 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit 236c734a2cb323541b3394f98682cb981b9ec086 +Subproject commit 1cce0737d6a7d3ceafb139b4a206861fb1dcb2ab diff --git a/src/doc/rustc/book.toml b/src/doc/rustc/book.toml index 8adc05c5137..21d127c39c9 100644 --- a/src/doc/rustc/book.toml +++ b/src/doc/rustc/book.toml @@ -3,3 +3,6 @@ authors = ["The Rust Project Developers"] multilingual = false src = "src" title = "The rustc book" + +[output.html] +git-repository-url = "https://github.com/rust-lang/rust/tree/master/src/doc/rustc" diff --git a/src/doc/rustdoc/book.toml b/src/doc/rustdoc/book.toml index ba30c107667..c2e7ff58906 100644 --- a/src/doc/rustdoc/book.toml +++ b/src/doc/rustdoc/book.toml @@ -2,3 +2,6 @@ authors = ["The Rust Project Developers"] src = "src" title = "The rustdoc book" + +[output.html] +git-repository-url = "https://github.com/rust-lang/rust/tree/master/src/doc/rustdoc" diff --git a/src/doc/rustdoc/src/command-line-arguments.md b/src/doc/rustdoc/src/command-line-arguments.md index 31e002810ce..80f7851debf 100644 --- a/src/doc/rustdoc/src/command-line-arguments.md +++ b/src/doc/rustdoc/src/command-line-arguments.md @@ -237,6 +237,26 @@ for a target triple that's different than your host triple. All of the usual caveats of cross-compiling code apply. +## `--default-theme`: set the default theme + +Using this flag looks like this: + +```bash +$ rustdoc src/lib.rs --default-theme=ayu +``` + +Sets the default theme (for users whose browser has not remembered a +previous theme selection from the on-page theme picker). + +The supplied value should be the lowercase version of the theme name. +The set of available themes can be seen in the theme picker in the +generated output. + +Note that the set of available themes - and their appearance - is not +necessarily stable from one rustdoc version to the next. If the +requested theme does not exist, the builtin default (currently +`light`) is used instead. + ## `--markdown-css`: include more CSS files when rendering markdown Using this flag looks like this: diff --git a/src/doc/rustdoc/src/what-is-rustdoc.md b/src/doc/rustdoc/src/what-is-rustdoc.md index 1f6dced180b..32dc1e02bb3 100644 --- a/src/doc/rustdoc/src/what-is-rustdoc.md +++ b/src/doc/rustdoc/src/what-is-rustdoc.md @@ -10,7 +10,7 @@ CSS, and JavaScript. Let's give it a try! Create a new project with Cargo: ```bash -$ cargo new docs +$ cargo new docs --lib $ cd docs ``` diff --git a/src/doc/unstable-book/src/language-features/ffi-pure.md b/src/doc/unstable-book/src/language-features/ffi-pure.md index 4aef4eeab55..236ccb9f905 100644 --- a/src/doc/unstable-book/src/language-features/ffi-pure.md +++ b/src/doc/unstable-book/src/language-features/ffi-pure.md @@ -31,7 +31,7 @@ parameters (e.g. pointers), globals, etc. `#[ffi_pure]` functions are not referentially-transparent, and are therefore more relaxed than `#[ffi_const]` functions. -However, accesing global memory through volatile or atomic reads can violate the +However, accessing global memory through volatile or atomic reads can violate the requirement that two consecutive function calls shall return the same value. A `pure` function that returns unit has no effect on the abstract machine's diff --git a/src/etc/generate-deriving-span-tests.py b/src/etc/generate-deriving-span-tests.py index a0ba47e1dbe..d38f5add747 100755 --- a/src/etc/generate-deriving-span-tests.py +++ b/src/etc/generate-deriving-span-tests.py @@ -1,7 +1,7 @@ #!/usr/bin/env python """ -This script creates a pile of compile-fail tests check that all the +This script creates a pile of UI tests check that all the derives have spans that point to the fields, rather than the #[derive(...)] line. diff --git a/src/etc/natvis/intrinsic.natvis b/src/etc/natvis/intrinsic.natvis index 874550da8b0..030892a432b 100644 --- a/src/etc/natvis/intrinsic.natvis +++ b/src/etc/natvis/intrinsic.natvis @@ -4,17 +4,21 @@ {data_ptr,[length]s8} data_ptr,[length]s8 - length - - length - data_ptr - + length + + + + length + data_ptr + + + - {{ length={length} }} + {{ len={length} }} - length + length length data_ptr diff --git a/src/etc/natvis/liballoc.natvis b/src/etc/natvis/liballoc.natvis index de30b58526a..cfaafc5734b 100644 --- a/src/etc/natvis/liballoc.natvis +++ b/src/etc/natvis/liballoc.natvis @@ -1,9 +1,9 @@ - {{ size={len} }} + {{ len={len} }} - len + len buf.cap len @@ -12,9 +12,9 @@ - {{ size={tail <= head ? head - tail : buf.cap - tail + head} }} + {{ len={tail <= head ? head - tail : buf.cap - tail + head} }} - tail <= head ? head - tail : buf.cap - tail + head + tail <= head ? head - tail : buf.cap - tail + head buf.cap @@ -31,7 +31,7 @@ - {{ size={len} }} + {{ len={len} }} len @@ -42,15 +42,37 @@ - {*(char**)this,[vec.len]s8} - *(char**)this,[vec.len]s8 + {(char*)vec.buf.ptr.pointer,[vec.len]s8} + (char*)vec.buf.ptr.pointer,[vec.len]s8 - vec.len + vec.len vec.buf.cap - - vec.len - *(char**)this - + + + + vec.len + (char*)vec.buf.ptr.pointer + + + + + + + {ptr.pointer->value} + + ptr.pointer->value + + + + {ptr.pointer->data} + + ptr.pointer->data + + + + {ptr.pointer->data} + + ptr.pointer->data diff --git a/src/etc/natvis/libcore.natvis b/src/etc/natvis/libcore.natvis index 0e703b3b950..984a8bfb13c 100644 --- a/src/etc/natvis/libcore.natvis +++ b/src/etc/natvis/libcore.natvis @@ -6,34 +6,28 @@ pointer + {{ Shared {pointer} }} pointer + - {{ None }} - {{ Some {__0} }} + None + Some({__0}) - (ULONG)(RUST$ENUM$DISR != 0) - __0 - - (ULONG)(RUST$ENUM$DISR != 0) - &__0 - + __0 + - {{ None }} - {{ Some {($T1 *)this} }} + None + Some({($T1 *)this}) - (ULONG)(*(PVOID *)this != nullptr) - ($T1 *)this - - (ULONG)(*(PVOID *)this != nullptr) - ($T1 *)this - + ($T1 *)this + \ No newline at end of file diff --git a/src/etc/natvis/libstd.natvis b/src/etc/natvis/libstd.natvis index 9550c25f2fc..7e5ee7b13da 100644 --- a/src/etc/natvis/libstd.natvis +++ b/src/etc/natvis/libstd.natvis @@ -26,9 +26,9 @@ --> - {{ size={base.table.items} }} + {{ len={base.table.items} }} - base.table.items + base.table.items base.table.items + base.table.growth_left base.hash_builder @@ -50,9 +50,9 @@ - {{ size={base.map.table.items} }} + {{ len={base.map.table.items} }} - base.map.table.items + base.map.table.items base.map.table.items + base.map.table.growth_left base.map.hash_builder diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index 40c59ed1e0b..2a8b6a321f1 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -123,10 +123,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { attrs: Default::default(), visibility: Inherited, def_id: self.cx.next_def_id(param_env_def_id.krate), - stability: None, - const_stability: None, - deprecation: None, - kind: ImplItem(Impl { + kind: box ImplItem(Impl { unsafety: hir::Unsafety::Normal, generics: new_generics, provided_trait_methods: Default::default(), @@ -600,7 +597,7 @@ fn param_env_to_generics( ref mut bindings, .. } => { bindings.push(TypeBinding { - name: left_name.clone(), + name: left_name, kind: TypeBindingKind::Equality { ty: rhs }, }); } @@ -668,7 +665,7 @@ fn param_env_to_generics( GenericParamDefKind::Type { ref mut default, ref mut bounds, .. } => { // We never want something like `impl`. default.take(); - let generic_ty = Type::Generic(param.name.clone()); + let generic_ty = Type::Generic(param.name); if !has_sized.contains(&generic_ty) { bounds.insert(0, GenericBound::maybe_sized(self.cx)); } diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs index 22496065afd..ba3eb007e38 100644 --- a/src/librustdoc/clean/blanket_impl.rs +++ b/src/librustdoc/clean/blanket_impl.rs @@ -112,10 +112,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> { attrs: Default::default(), visibility: Inherited, def_id: self.cx.next_def_id(impl_def_id.krate), - stability: None, - const_stability: None, - deprecation: None, - kind: ImplItem(Impl { + kind: box ImplItem(Impl { unsafety: hir::Unsafety::Normal, generics: ( self.cx.tcx.generics_of(impl_def_id), diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 783be6c8243..c168c56d30d 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -482,10 +482,7 @@ fn fill_in( source: clean::Span::dummy(), def_id: DefId::local(CRATE_DEF_INDEX), visibility: clean::Public, - stability: None, - const_stability: None, - deprecation: None, - kind: clean::ImportItem(clean::Import::new_simple( + kind: box clean::ImportItem(clean::Import::new_simple( item.ident.name, clean::ImportSource { path: clean::Path { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 9a15a4bb917..8b80f098baa 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -218,11 +218,6 @@ fn clean(&self, cx: &DocContext<'_>) -> ExternalCrate { impl Clean for doctree::Module<'_> { fn clean(&self, cx: &DocContext<'_>) -> Item { - // maintain a stack of mod ids, for doc comment path resolution - // but we also need to resolve the module's own docs based on whether its docs were written - // inside or outside the module, so check for that - let attrs = self.attrs.clean(cx); - let mut items: Vec = vec![]; items.extend(self.imports.iter().flat_map(|x| x.clean(cx))); items.extend(self.foreigns.iter().map(|x| x.clean(cx))); @@ -251,7 +246,7 @@ fn clean(&self, cx: &DocContext<'_>) -> Item { ModuleItem(Module { is_crate: self.is_crate, items }), cx, ); - Item { attrs, source: span.clean(cx), ..what_rustc_thinks } + Item { source: span.clean(cx), ..what_rustc_thinks } } } @@ -638,6 +633,18 @@ fn is_impl_trait(param: &hir::GenericParam<'_>) -> bool { _ => false, } } + /// This can happen for `async fn`, e.g. `async fn f<'_>(&'_ self)`. + /// + /// See [`lifetime_to_generic_param`] in [`rustc_ast_lowering`] for more information. + /// + /// [`lifetime_to_generic_param`]: rustc_ast_lowering::LoweringContext::lifetime_to_generic_param + fn is_elided_lifetime(param: &hir::GenericParam<'_>) -> bool { + match param.kind { + hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Elided } => true, + _ => false, + } + } + let impl_trait_params = self .params .iter() @@ -656,7 +663,7 @@ fn is_impl_trait(param: &hir::GenericParam<'_>) -> bool { .collect::>(); let mut params = Vec::with_capacity(self.params.len()); - for p in self.params.iter().filter(|p| !is_impl_trait(p)) { + for p in self.params.iter().filter(|p| !is_impl_trait(p) && !is_elided_lifetime(p)) { let p = p.clean(cx); params.push(p); } @@ -824,7 +831,7 @@ fn clean(&self, cx: &DocContext<'_>) -> Generics { where_predicates.retain(|pred| match *pred { WP::BoundPredicate { ty: Generic(ref g), ref bounds } => { if bounds.iter().any(|b| b.is_sized_bound(cx)) { - sized_params.insert(g.clone()); + sized_params.insert(*g); false } else { true @@ -840,7 +847,7 @@ fn clean(&self, cx: &DocContext<'_>) -> Generics { && !sized_params.contains(&tp.name) { where_predicates.push(WP::BoundPredicate { - ty: Type::Generic(tp.name.clone()), + ty: Type::Generic(tp.name), bounds: vec![GenericBound::maybe_sized(cx)], }) } @@ -934,7 +941,7 @@ fn clean(&self, cx: &DocContext<'_>) -> Arguments { .iter() .enumerate() .map(|(i, ty)| { - let mut name = self.1.get(i).map(|ident| ident.name).unwrap_or(kw::Invalid); + let mut name = self.1.get(i).map(|ident| ident.name).unwrap_or(kw::Empty); if name.is_empty() { name = kw::Underscore; } @@ -993,7 +1000,7 @@ fn clean(&self, cx: &DocContext<'_>) -> FnDecl { .iter() .map(|t| Argument { type_: t.clean(cx), - name: names.next().map(|i| i.name).unwrap_or(kw::Invalid), + name: names.next().map(|i| i.name).unwrap_or(kw::Empty), }) .collect(), }, @@ -1437,7 +1444,16 @@ fn clean(&self, cx: &DocContext<'_>) -> Type { TyKind::Never => Never, TyKind::Ptr(ref m) => RawPointer(m.mutbl, box m.ty.clean(cx)), TyKind::Rptr(ref l, ref m) => { - let lifetime = if l.is_elided() { None } else { Some(l.clean(cx)) }; + // There are two times a `Fresh` lifetime can be created: + // 1. For `&'_ x`, written by the user. This corresponds to `lower_lifetime` in `rustc_ast_lowering`. + // 2. For `&x` as a parameter to an `async fn`. This corresponds to `elided_ref_lifetime in `rustc_ast_lowering`. + // See #59286 for more information. + // Ideally we would only hide the `'_` for case 2., but I don't know a way to distinguish it. + // Turning `fn f(&'_ self)` into `fn f(&self)` isn't the worst thing in the world, though; + // there's no case where it could cause the function to fail to compile. + let elided = + l.is_elided() || matches!(l.name, LifetimeName::Param(ParamName::Fresh(_))); + let lifetime = if elided { None } else { Some(l.clean(cx)) }; BorrowedRef { lifetime, mutability: m.mutbl, type_: box m.ty.clean(cx) } } TyKind::Slice(ref ty) => Slice(box ty.clean(cx)), @@ -1777,25 +1793,28 @@ fn clean(&self, cx: &DocContext<'_>) -> Visibility { hir::VisibilityKind::Inherited => Visibility::Inherited, hir::VisibilityKind::Crate(_) => { let krate = DefId::local(CRATE_DEF_INDEX); - Visibility::Restricted(krate, cx.tcx.def_path(krate)) + Visibility::Restricted(krate) } hir::VisibilityKind::Restricted { ref path, .. } => { let path = path.clean(cx); let did = register_res(cx, path.res); - Visibility::Restricted(did, cx.tcx.def_path(did)) + Visibility::Restricted(did) } } } } impl Clean for ty::Visibility { - fn clean(&self, cx: &DocContext<'_>) -> Visibility { + fn clean(&self, _cx: &DocContext<'_>) -> Visibility { match *self { ty::Visibility::Public => Visibility::Public, + // NOTE: this is not quite right: `ty` uses `Invisible` to mean 'private', + // while rustdoc really does mean inherited. That means that for enum variants, such as + // `pub enum E { V }`, `V` will be marked as `Public` by `ty`, but as `Inherited` by rustdoc. + // This is the main reason `impl Clean for hir::Visibility` still exists; various parts of clean + // override `tcx.visibility` explicitly to make sure this distinction is captured. ty::Visibility::Invisible => Visibility::Inherited, - ty::Visibility::Restricted(module) => { - Visibility::Restricted(module, cx.tcx.def_path(module)) - } + ty::Visibility::Restricted(module) => Visibility::Restricted(module), } } } @@ -2141,10 +2160,7 @@ fn clean_extern_crate( source: krate.span.clean(cx), def_id: crate_def_id, visibility: krate.vis.clean(cx), - stability: None, - const_stability: None, - deprecation: None, - kind: ExternCrateItem(name, orig_name), + kind: box ExternCrateItem(name, orig_name), }] } @@ -2226,10 +2242,7 @@ fn clean(&self, cx: &DocContext<'_>) -> Vec { source: self.span.clean(cx), def_id: cx.tcx.hir().local_def_id(self.id).to_def_id(), visibility: self.vis.clean(cx), - stability: None, - const_stability: None, - deprecation: None, - kind: ImportItem(Import::new_simple( + kind: box ImportItem(Import::new_simple( self.name, resolve_use_source(cx, path), false, @@ -2247,10 +2260,7 @@ fn clean(&self, cx: &DocContext<'_>) -> Vec { source: self.span.clean(cx), def_id: cx.tcx.hir().local_def_id(self.id).to_def_id(), visibility: self.vis.clean(cx), - stability: None, - const_stability: None, - deprecation: None, - kind: ImportItem(inner), + kind: box ImportItem(inner), }] } } @@ -2319,14 +2329,14 @@ fn clean(&self, cx: &DocContext<'_>) -> Item { if matchers.len() <= 1 { format!( "{}macro {}{} {{\n ...\n}}", - vis.print_with_space(), + vis.print_with_space(cx.tcx), name, matchers.iter().map(|span| span.to_src(cx)).collect::(), ) } else { format!( "{}macro {} {{\n{}}}", - vis.print_with_space(), + vis.print_with_space(cx.tcx), name, matchers .iter() diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index d8dfdd0941b..0d33bc9afd5 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -84,13 +84,14 @@ crate name: Option, crate attrs: Attributes, crate visibility: Visibility, - crate kind: ItemKind, + crate kind: Box, crate def_id: DefId, - crate stability: Option, - crate deprecation: Option, - crate const_stability: Option, } +// `Item` is used a lot. Make sure it doesn't unintentionally get bigger. +#[cfg(target_arch = "x86_64")] +rustc_data_structures::static_assert_size!(Item, 136); + impl fmt::Debug for Item { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { let def_id: &dyn fmt::Debug = if self.is_fake() { &"**FAKE**" } else { &self.def_id }; @@ -102,13 +103,23 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { .field("kind", &self.kind) .field("visibility", &self.visibility) .field("def_id", def_id) - .field("stability", &self.stability) - .field("deprecation", &self.deprecation) .finish() } } impl Item { + crate fn stability<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Option<&'tcx Stability> { + if self.is_fake() { None } else { tcx.lookup_stability(self.def_id) } + } + + crate fn const_stability<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Option<&'tcx ConstStability> { + if self.is_fake() { None } else { tcx.lookup_const_stability(self.def_id) } + } + + crate fn deprecation(&self, tcx: TyCtxt<'_>) -> Option { + if self.is_fake() { None } else { tcx.lookup_deprecation(self.def_id) } + } + /// Finds the `doc` attribute as a NameValue and returns the corresponding /// value found. crate fn doc_value(&self) -> Option<&str> { @@ -145,14 +156,11 @@ pub fn from_def_id_and_parts( Item { def_id, - kind, + kind: box kind, name, source: source.clean(cx), attrs: cx.tcx.get_attrs(def_id).clean(cx), visibility: cx.tcx.visibility(def_id).clean(cx), - stability: cx.tcx.lookup_stability(def_id).cloned(), - deprecation: cx.tcx.lookup_deprecation(def_id), - const_stability: cx.tcx.lookup_const_stability(def_id).cloned(), } } @@ -167,7 +175,7 @@ pub fn from_def_id_and_parts( } crate fn is_crate(&self) -> bool { - match self.kind { + match *self.kind { StrippedItem(box ModuleItem(Module { is_crate: true, .. })) | ModuleItem(Module { is_crate: true, .. }) => true, _ => false, @@ -219,14 +227,14 @@ pub fn from_def_id_and_parts( self.type_() == ItemType::Keyword } crate fn is_stripped(&self) -> bool { - match self.kind { + match *self.kind { StrippedItem(..) => true, ImportItem(ref i) => !i.should_be_displayed, _ => false, } } crate fn has_stripped_fields(&self) -> Option { - match self.kind { + match *self.kind { StructItem(ref _struct) => Some(_struct.fields_stripped), UnionItem(ref union) => Some(union.fields_stripped), VariantItem(Variant { kind: VariantKind::Struct(ref vstruct) }) => { @@ -236,8 +244,8 @@ pub fn from_def_id_and_parts( } } - crate fn stability_class(&self) -> Option { - self.stability.as_ref().and_then(|ref s| { + crate fn stability_class(&self, tcx: TyCtxt<'_>) -> Option { + self.stability(tcx).as_ref().and_then(|ref s| { let mut classes = Vec::with_capacity(2); if s.level.is_unstable() { @@ -245,7 +253,7 @@ pub fn from_def_id_and_parts( } // FIXME: what about non-staged API items that are deprecated? - if self.deprecation.is_some() { + if self.deprecation(tcx).is_some() { classes.push("deprecated"); } @@ -253,15 +261,15 @@ pub fn from_def_id_and_parts( }) } - crate fn stable_since(&self) -> Option { - match self.stability?.level { + crate fn stable_since(&self, tcx: TyCtxt<'_>) -> Option { + match self.stability(tcx)?.level { StabilityLevel::Stable { since, .. } => Some(since.as_str()), StabilityLevel::Unstable { .. } => None, } } - crate fn const_stable_since(&self) -> Option { - match self.const_stability?.level { + crate fn const_stable_since(&self, tcx: TyCtxt<'_>) -> Option { + match self.const_stability(tcx)?.level { StabilityLevel::Stable { since, .. } => Some(since.as_str()), StabilityLevel::Unstable { .. } => None, } @@ -277,7 +285,7 @@ pub fn from_def_id_and_parts( } crate fn is_default(&self) -> bool { - match self.kind { + match *self.kind { ItemKind::MethodItem(_, Some(defaultness)) => { defaultness.has_value() && !defaultness.is_final() } @@ -627,7 +635,7 @@ impl Attributes { let clean_attr = |(attr, parent_module): (&ast::Attribute, _)| { if let Some(value) = attr.doc_str() { trace!("got doc_str={:?}", value); - let value = beautify_doc_string(value); + let value = beautify_doc_string(value).to_string(); let kind = if attr.is_doc_comment() { DocFragmentKind::SugaredDoc } else { @@ -1579,11 +1587,11 @@ fn from(prim_ty: hir::PrimTy) -> PrimitiveType { } } -#[derive(Clone, Debug)] +#[derive(Copy, Clone, Debug)] crate enum Visibility { Public, Inherited, - Restricted(DefId, rustc_hir::definitions::DefPath), + Restricted(DefId), } impl Visibility { diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 4d525d62c52..a6c090c6576 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -8,7 +8,6 @@ }; use crate::core::DocContext; -use itertools::Itertools; use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; @@ -43,7 +42,7 @@ let mut module = module.clean(cx); let mut masked_crates = FxHashSet::default(); - match module.kind { + match *module.kind { ItemKind::ModuleItem(ref module) => { for it in &module.items { // `compiler_builtins` should be masked too, but we can't apply @@ -61,7 +60,7 @@ let ExternalCrate { name, src, primitives, keywords, .. } = LOCAL_CRATE.clean(cx); { - let m = match module.kind { + let m = match *module.kind { ItemKind::ModuleItem(ref mut m) => m, _ => unreachable!(), }; @@ -74,7 +73,7 @@ ) })); m.items.extend(keywords.into_iter().map(|(def_id, kw)| { - Item::from_def_id_and_parts(def_id, Some(kw.clone()), ItemKind::KeywordItem(kw), cx) + Item::from_def_id_and_parts(def_id, Some(kw), ItemKind::KeywordItem(kw), cx) })); } @@ -307,7 +306,7 @@ pub(super) fn external_path( .segments .iter() .map(|s| PathSegment { - name: s.name.clone(), + name: s.name, args: GenericArgs::AngleBracketed { args: vec![], bindings: vec![] }, }) .collect(); @@ -338,7 +337,7 @@ pub(super) fn external_path( let tcx = cx.tcx; for item in items { - let target = match item.kind { + let target = match *item.kind { ItemKind::TypedefItem(ref t, true) => &t.type_, _ => continue, }; @@ -558,10 +557,13 @@ fn print_const_with_custom_print_scalar(cx: &DocContext<'_>, ct: &'tcx ty::Const ty: Ty<'tcx>, param_env_def_id: DefId, ) -> impl Iterator { - AutoTraitFinder::new(cx) - .get_auto_trait_impls(ty, param_env_def_id) - .into_iter() - .chain(BlanketImplFinder::new(cx).get_blanket_impls(ty, param_env_def_id)) + let auto_impls = cx.sess().time("get_auto_trait_impls", || { + AutoTraitFinder::new(cx).get_auto_trait_impls(ty, param_env_def_id) + }); + let blanket_impls = cx.sess().time("get_blanket_impls", || { + BlanketImplFinder::new(cx).get_blanket_impls(ty, param_env_def_id) + }); + auto_impls.into_iter().chain(blanket_impls) } crate fn register_res(cx: &DocContext<'_>, res: Res) -> DefId { diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index 37fe13c32ce..02dd42ce0c1 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -247,9 +247,10 @@ fn run_test( edition: Edition, outdir: DirState, path: PathBuf, + test_id: &str, ) -> Result<(), TestFailure> { let (test, line_offset, supports_color) = - make_test(test, Some(cratename), as_test_harness, opts, edition); + make_test(test, Some(cratename), as_test_harness, opts, edition, Some(test_id)); let output_file = outdir.path().join("rust_out"); @@ -387,6 +388,7 @@ fn drop(&mut self) { dont_insert_main: bool, opts: &TestOptions, edition: Edition, + test_id: Option<&str>, ) -> (String, usize, bool) { let (crate_attrs, everything_else, crates) = partition_source(s); let everything_else = everything_else.trim(); @@ -542,16 +544,41 @@ fn drop(&mut self) { prog.push_str(everything_else); } else { let returns_result = everything_else.trim_end().ends_with("(())"); + // Give each doctest main function a unique name. + // This is for example needed for the tooling around `-Z instrument-coverage`. + let inner_fn_name = if let Some(test_id) = test_id { + format!("_doctest_main_{}", test_id) + } else { + "_inner".into() + }; + let inner_attr = if test_id.is_some() { "#[allow(non_snake_case)] " } else { "" }; let (main_pre, main_post) = if returns_result { ( - "fn main() { fn _inner() -> Result<(), impl core::fmt::Debug> {", - "}\n_inner().unwrap() }", + format!( + "fn main() {{ {}fn {}() -> Result<(), impl core::fmt::Debug> {{\n", + inner_attr, inner_fn_name + ), + format!("\n}} {}().unwrap() }}", inner_fn_name), + ) + } else if test_id.is_some() { + ( + format!("fn main() {{ {}fn {}() {{\n", inner_attr, inner_fn_name), + format!("\n}} {}() }}", inner_fn_name), ) } else { - ("fn main() {\n", "\n}") + ("fn main() {\n".into(), "\n}".into()) }; - prog.extend([main_pre, everything_else, main_post].iter().cloned()); + // Note on newlines: We insert a line/newline *before*, and *after* + // the doctest and adjust the `line_offset` accordingly. + // In the case of `-Z instrument-coverage`, this means that the generated + // inner `main` function spans from the doctest opening codeblock to the + // closing one. For example + // /// ``` <- start of the inner main + // /// <- code under doctest + // /// ``` <- end of the inner main line_offset += 1; + + prog.extend([&main_pre, everything_else, &main_post].iter().cloned()); } debug!("final doctest:\n{}", prog); @@ -749,28 +776,24 @@ fn add_test(&mut self, test: String, config: LangString, line: usize) { _ => PathBuf::from(r"doctest.rs"), }; + // For example `module/file.rs` would become `module_file_rs` + let file = filename + .to_string() + .chars() + .map(|c| if c.is_ascii_alphanumeric() { c } else { '_' }) + .collect::(); + let test_id = format!( + "{file}_{line}_{number}", + file = file, + line = line, + number = { + // Increases the current test number, if this file already + // exists or it creates a new entry with a test number of 0. + self.visited_tests.entry((file.clone(), line)).and_modify(|v| *v += 1).or_insert(0) + }, + ); let outdir = if let Some(mut path) = options.persist_doctests.clone() { - // For example `module/file.rs` would become `module_file_rs` - let folder_name = filename - .to_string() - .chars() - .map(|c| if c == '\\' || c == '/' || c == '.' { '_' } else { c }) - .collect::(); - - path.push(format!( - "{krate}_{file}_{line}_{number}", - krate = cratename, - file = folder_name, - line = line, - number = { - // Increases the current test number, if this file already - // exists or it creates a new entry with a test number of 0. - self.visited_tests - .entry((folder_name.clone(), line)) - .and_modify(|v| *v += 1) - .or_insert(0) - }, - )); + path.push(&test_id); std::fs::create_dir_all(&path) .expect("Couldn't create directory for doctest executables"); @@ -817,6 +840,7 @@ fn add_test(&mut self, test: String, config: LangString, line: usize) { edition, outdir, path, + &test_id, ); if let Err(err) = res { diff --git a/src/librustdoc/doctest/tests.rs b/src/librustdoc/doctest/tests.rs index a024e9c72a4..465b2b1d69b 100644 --- a/src/librustdoc/doctest/tests.rs +++ b/src/librustdoc/doctest/tests.rs @@ -11,7 +11,7 @@ fn main() { assert_eq!(2+2, 4); }" .to_string(); - let (output, len, _) = make_test(input, None, false, &opts, DEFAULT_EDITION); + let (output, len, _) = make_test(input, None, false, &opts, DEFAULT_EDITION, None); assert_eq!((output, len), (expected, 2)); } @@ -26,7 +26,7 @@ fn main() { assert_eq!(2+2, 4); }" .to_string(); - let (output, len, _) = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION); + let (output, len, _) = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION, None); assert_eq!((output, len), (expected, 2)); } @@ -44,7 +44,7 @@ fn main() { assert_eq!(2+2, 4); }" .to_string(); - let (output, len, _) = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION); + let (output, len, _) = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION, None); assert_eq!((output, len), (expected, 3)); } @@ -61,7 +61,7 @@ fn main() { assert_eq!(2+2, 4); }" .to_string(); - let (output, len, _) = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION); + let (output, len, _) = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION, None); assert_eq!((output, len), (expected, 2)); } @@ -79,7 +79,7 @@ fn main() { assert_eq!(2+2, 4); }" .to_string(); - let (output, len, _) = make_test(input, Some("std"), false, &opts, DEFAULT_EDITION); + let (output, len, _) = make_test(input, Some("std"), false, &opts, DEFAULT_EDITION, None); assert_eq!((output, len), (expected, 2)); } @@ -98,7 +98,7 @@ fn main() { assert_eq!(2+2, 4); }" .to_string(); - let (output, len, _) = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION); + let (output, len, _) = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION, None); assert_eq!((output, len), (expected, 2)); } @@ -115,7 +115,7 @@ fn main() { assert_eq!(2+2, 4); }" .to_string(); - let (output, len, _) = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION); + let (output, len, _) = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION, None); assert_eq!((output, len), (expected, 2)); } @@ -134,7 +134,7 @@ fn main() { assert_eq!(2+2, 4); }" .to_string(); - let (output, len, _) = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION); + let (output, len, _) = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION, None); assert_eq!((output, len), (expected, 3)); // Adding more will also bump the returned line offset. @@ -147,7 +147,7 @@ fn main() { assert_eq!(2+2, 4); }" .to_string(); - let (output, len, _) = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION); + let (output, len, _) = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION, None); assert_eq!((output, len), (expected, 4)); } @@ -164,7 +164,7 @@ fn main() { assert_eq!(2+2, 4); }" .to_string(); - let (output, len, _) = make_test(input, None, false, &opts, DEFAULT_EDITION); + let (output, len, _) = make_test(input, None, false, &opts, DEFAULT_EDITION, None); assert_eq!((output, len), (expected, 2)); } @@ -180,7 +180,7 @@ fn main() { assert_eq!(2+2, 4); }" .to_string(); - let (output, len, _) = make_test(input, None, false, &opts, DEFAULT_EDITION); + let (output, len, _) = make_test(input, None, false, &opts, DEFAULT_EDITION, None); assert_eq!((output, len), (expected, 1)); } @@ -196,7 +196,7 @@ fn main() { assert_eq!(2+2, 4); }" .to_string(); - let (output, len, _) = make_test(input, None, false, &opts, DEFAULT_EDITION); + let (output, len, _) = make_test(input, None, false, &opts, DEFAULT_EDITION, None); assert_eq!((output, len), (expected, 2)); } @@ -210,7 +210,7 @@ fn make_test_dont_insert_main() { //Ceci n'est pas une `fn main` assert_eq!(2+2, 4);" .to_string(); - let (output, len, _) = make_test(input, None, true, &opts, DEFAULT_EDITION); + let (output, len, _) = make_test(input, None, true, &opts, DEFAULT_EDITION, None); assert_eq!((output, len), (expected, 1)); } @@ -224,7 +224,7 @@ fn make_test_display_warnings() { assert_eq!(2+2, 4); }" .to_string(); - let (output, len, _) = make_test(input, None, false, &opts, DEFAULT_EDITION); + let (output, len, _) = make_test(input, None, false, &opts, DEFAULT_EDITION, None); assert_eq!((output, len), (expected, 1)); } @@ -242,7 +242,7 @@ fn main() { }" .to_string(); - let (output, len, _) = make_test(input, None, false, &opts, DEFAULT_EDITION); + let (output, len, _) = make_test(input, None, false, &opts, DEFAULT_EDITION, None); assert_eq!((output, len), (expected, 2)); let input = "extern crate hella_qwop; @@ -256,7 +256,7 @@ fn main() { }" .to_string(); - let (output, len, _) = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION); + let (output, len, _) = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION, None); assert_eq!((output, len), (expected, 3)); } @@ -274,6 +274,41 @@ fn main() {} }" .to_string(); - let (output, len, _) = make_test(input, Some("my_crate"), false, &opts, DEFAULT_EDITION); + let (output, len, _) = make_test(input, Some("my_crate"), false, &opts, DEFAULT_EDITION, None); assert_eq!((output, len), (expected, 1)); } + +#[test] +fn make_test_returns_result() { + // creates an inner function and unwraps it + let opts = TestOptions::default(); + let input = "use std::io; +let mut input = String::new(); +io::stdin().read_line(&mut input)?; +Ok::<(), io:Error>(())"; + let expected = "#![allow(unused)] +fn main() { fn _inner() -> Result<(), impl core::fmt::Debug> { +use std::io; +let mut input = String::new(); +io::stdin().read_line(&mut input)?; +Ok::<(), io:Error>(()) +} _inner().unwrap() }" + .to_string(); + let (output, len, _) = make_test(input, None, false, &opts, DEFAULT_EDITION, None); + assert_eq!((output, len), (expected, 2)); +} + +#[test] +fn make_test_named_wrapper() { + // creates an inner function with a specific name + let opts = TestOptions::default(); + let input = "assert_eq!(2+2, 4);"; + let expected = "#![allow(unused)] +fn main() { #[allow(non_snake_case)] fn _doctest_main__some_unique_name() { +assert_eq!(2+2, 4); +} _doctest_main__some_unique_name() }" + .to_string(); + let (output, len, _) = + make_test(input, None, false, &opts, DEFAULT_EDITION, Some("_some_unique_name")); + assert_eq!((output, len), (expected, 2)); +} diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs index ee9a6981857..bc9f1cf8806 100644 --- a/src/librustdoc/doctree.rs +++ b/src/librustdoc/doctree.rs @@ -9,7 +9,6 @@ crate struct Module<'hir> { crate name: Option, - crate attrs: &'hir [ast::Attribute], crate where_outer: Span, crate where_inner: Span, crate imports: Vec>, @@ -23,13 +22,12 @@ } impl Module<'hir> { - crate fn new(name: Option, attrs: &'hir [ast::Attribute]) -> Module<'hir> { + crate fn new(name: Option) -> Module<'hir> { Module { name, id: hir::CRATE_HIR_ID, where_outer: rustc_span::DUMMY_SP, where_inner: rustc_span::DUMMY_SP, - attrs, imports: Vec::new(), mods: Vec::new(), items: Vec::new(), diff --git a/src/librustdoc/fold.rs b/src/librustdoc/fold.rs index 285fabdc372..c39cc3ca397 100644 --- a/src/librustdoc/fold.rs +++ b/src/librustdoc/fold.rs @@ -3,12 +3,12 @@ crate struct StripItem(pub Item); impl StripItem { - crate fn strip(self) -> Option { + crate fn strip(self) -> Item { match self.0 { - Item { kind: StrippedItem(..), .. } => Some(self.0), + Item { kind: box StrippedItem(..), .. } => self.0, mut i => { - i.kind = StrippedItem(box i.kind); - Some(i) + i.kind = box StrippedItem(i.kind); + i } } } @@ -72,9 +72,9 @@ fn fold_inner_recur(&mut self, kind: ItemKind) -> ItemKind { /// don't override! fn fold_item_recur(&mut self, mut item: Item) -> Item { - item.kind = match item.kind { + item.kind = box match *item.kind { StrippedItem(box i) => StrippedItem(box self.fold_inner_recur(i)), - _ => self.fold_inner_recur(item.kind), + _ => self.fold_inner_recur(*item.kind), }; item } diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index 77a3e9fa954..899d61d8e43 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -219,7 +219,7 @@ fn fold_item(&mut self, item: clean::Item) -> Option { // If this is a stripped module, // we don't want it or its children in the search index. - let orig_stripped_mod = match item.kind { + let orig_stripped_mod = match *item.kind { clean::StrippedItem(box clean::ModuleItem(..)) => { mem::replace(&mut self.stripped_mod, true) } @@ -228,7 +228,7 @@ fn fold_item(&mut self, item: clean::Item) -> Option { // If the impl is from a masked crate or references something from a // masked crate then remove it completely. - if let clean::ImplItem(ref i) = item.kind { + if let clean::ImplItem(ref i) = *item.kind { if self.masked_crates.contains(&item.def_id.krate) || i.trait_.def_id().map_or(false, |d| self.masked_crates.contains(&d.krate)) || i.for_.def_id().map_or(false, |d| self.masked_crates.contains(&d.krate)) @@ -239,12 +239,12 @@ fn fold_item(&mut self, item: clean::Item) -> Option { // Propagate a trait method's documentation to all implementors of the // trait. - if let clean::TraitItem(ref t) = item.kind { + if let clean::TraitItem(ref t) = *item.kind { self.traits.entry(item.def_id).or_insert_with(|| t.clone()); } // Collect all the implementors of traits. - if let clean::ImplItem(ref i) = item.kind { + if let clean::ImplItem(ref i) = *item.kind { if let Some(did) = i.trait_.def_id() { if i.blanket_impl.is_none() { self.implementors @@ -257,7 +257,7 @@ fn fold_item(&mut self, item: clean::Item) -> Option { // Index this method for searching later on. if let Some(ref s) = item.name { - let (parent, is_inherent_impl_item) = match item.kind { + let (parent, is_inherent_impl_item) = match *item.kind { clean::StrippedItem(..) => ((None, None), false), clean::AssocConstItem(..) | clean::TypedefItem(_, true) if self.parent_is_trait_impl => @@ -348,7 +348,7 @@ fn fold_item(&mut self, item: clean::Item) -> Option { _ => false, }; - match item.kind { + match *item.kind { clean::StructItem(..) | clean::EnumItem(..) | clean::TypedefItem(..) @@ -387,7 +387,7 @@ fn fold_item(&mut self, item: clean::Item) -> Option { // Maintain the parent stack let orig_parent_is_trait_impl = self.parent_is_trait_impl; - let parent_pushed = match item.kind { + let parent_pushed = match *item.kind { clean::TraitItem(..) | clean::EnumItem(..) | clean::ForeignTypeItem @@ -425,38 +425,33 @@ fn fold_item(&mut self, item: clean::Item) -> Option { // Once we've recursively found all the generics, hoard off all the // implementations elsewhere. let item = self.fold_item_recur(item); - let ret = if let clean::Item { kind: clean::ImplItem(_), .. } = item { + let ret = if let clean::Item { kind: box clean::ImplItem(ref i), .. } = item { // Figure out the id of this impl. This may map to a // primitive rather than always to a struct/enum. // Note: matching twice to restrict the lifetime of the `i` borrow. let mut dids = FxHashSet::default(); - if let clean::Item { kind: clean::ImplItem(ref i), .. } = item { - match i.for_ { - clean::ResolvedPath { did, .. } - | clean::BorrowedRef { type_: box clean::ResolvedPath { did, .. }, .. } => { - dids.insert(did); - } - ref t => { - let did = t - .primitive_type() - .and_then(|t| self.primitive_locations.get(&t).cloned()); + match i.for_ { + clean::ResolvedPath { did, .. } + | clean::BorrowedRef { type_: box clean::ResolvedPath { did, .. }, .. } => { + dids.insert(did); + } + ref t => { + let did = + t.primitive_type().and_then(|t| self.primitive_locations.get(&t).cloned()); - if let Some(did) = did { - dids.insert(did); - } + if let Some(did) = did { + dids.insert(did); } } + } - if let Some(generics) = i.trait_.as_ref().and_then(|t| t.generics()) { - for bound in generics { - if let Some(did) = bound.def_id() { - dids.insert(did); - } + if let Some(generics) = i.trait_.as_ref().and_then(|t| t.generics()) { + for bound in generics { + if let Some(did) = bound.def_id() { + dids.insert(did); } } - } else { - unreachable!() - }; + } let impl_item = Impl { impl_item: item }; if impl_item.trait_did().map_or(true, |d| self.traits.contains_key(&d)) { for did in dids { diff --git a/src/librustdoc/formats/item_type.rs b/src/librustdoc/formats/item_type.rs index af512e37460..ad51adf2fe3 100644 --- a/src/librustdoc/formats/item_type.rs +++ b/src/librustdoc/formats/item_type.rs @@ -60,7 +60,7 @@ fn serialize(&self, serializer: S) -> Result impl<'a> From<&'a clean::Item> for ItemType { fn from(item: &'a clean::Item) -> ItemType { - let kind = match item.kind { + let kind = match *item.kind { clean::StrippedItem(box ref item) => item, ref kind => kind, }; diff --git a/src/librustdoc/formats/mod.rs b/src/librustdoc/formats/mod.rs index 55fd4948f45..58b9f5fbf0f 100644 --- a/src/librustdoc/formats/mod.rs +++ b/src/librustdoc/formats/mod.rs @@ -32,7 +32,7 @@ impl Impl { crate fn inner_impl(&self) -> &clean::Impl { - match self.impl_item.kind { + match *self.impl_item.kind { clean::ImplItem(ref impl_) => impl_, _ => panic!("non-impl item found in impl"), } diff --git a/src/librustdoc/formats/renderer.rs b/src/librustdoc/formats/renderer.rs index fbbd3c1ccf5..e84a9853d9b 100644 --- a/src/librustdoc/formats/renderer.rs +++ b/src/librustdoc/formats/renderer.rs @@ -89,7 +89,7 @@ fn mod_item_in( } cx.mod_item_in(&item, &name, &cache)?; - let module = match item.kind { + let module = match *item.kind { clean::StrippedItem(box clean::ModuleItem(m)) | clean::ModuleItem(m) => m, _ => unreachable!(), }; diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index f80346aa50b..7b0b219570b 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -11,6 +11,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; +use rustc_middle::ty::TyCtxt; use rustc_span::def_id::{DefId, CRATE_DEF_INDEX}; use rustc_target::spec::abi::Abi; @@ -1084,18 +1085,18 @@ impl Function<'_> { } impl clean::Visibility { - crate fn print_with_space(&self) -> impl fmt::Display + '_ { + crate fn print_with_space<'tcx>(self, tcx: TyCtxt<'tcx>) -> impl fmt::Display + 'tcx { use rustc_span::symbol::kw; - display_fn(move |f| match *self { + display_fn(move |f| match self { clean::Public => f.write_str("pub "), clean::Inherited => Ok(()), - // If this is `pub(crate)`, `path` will be empty. - clean::Visibility::Restricted(did, _) if did.index == CRATE_DEF_INDEX => { + clean::Visibility::Restricted(did) if did.index == CRATE_DEF_INDEX => { write!(f, "pub(crate) ") } - clean::Visibility::Restricted(did, ref path) => { + clean::Visibility::Restricted(did) => { f.write_str("pub(")?; + let path = tcx.def_path(did); debug!("path={:?}", path); let first_name = path.data[0].data.get_opt_name().expect("modules are always named"); diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index 1cbfbf50dd7..d21998bb8cf 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -11,7 +11,8 @@ use std::iter::Peekable; use rustc_lexer::{LiteralKind, TokenKind}; -use rustc_span::symbol::Ident; +use rustc_span::edition::Edition; +use rustc_span::symbol::Symbol; use rustc_span::with_default_session_globals; /// Highlights `src`, returning the HTML output. @@ -19,22 +20,27 @@ src: String, class: Option<&str>, playground_button: Option<&str>, - tooltip: Option<(&str, &str)>, + tooltip: Option<(Option, &str)>, + edition: Edition, ) -> String { debug!("highlighting: ================\n{}\n==============", src); let mut out = String::with_capacity(src.len()); - if let Some((tooltip, class)) = tooltip { + if let Some((edition_info, class)) = tooltip { write!( out, - "
ⓘ{}
", - class, tooltip + "
ⓘ
", + class, + if let Some(edition_info) = edition_info { + format!(" data-edition=\"{}\"", edition_info) + } else { + String::new() + }, ) .unwrap(); } write_header(&mut out, class); - write_code(&mut out, &src); + write_code(&mut out, &src, edition); write_footer(&mut out, playground_button); out @@ -45,10 +51,10 @@ fn write_header(out: &mut String, class: Option<&str>) { .unwrap() } -fn write_code(out: &mut String, src: &str) { +fn write_code(out: &mut String, src: &str, edition: Edition) { // This replace allows to fix how the code source with DOS backline characters is displayed. let src = src.replace("\r\n", "\n"); - Classifier::new(&src).highlight(&mut |highlight| { + Classifier::new(&src, edition).highlight(&mut |highlight| { match highlight { Highlight::Token { text, class } => string(out, Escape(text), class), Highlight::EnterSpan { class } => enter_span(out, class), @@ -139,12 +145,19 @@ struct Classifier<'a> { in_attribute: bool, in_macro: bool, in_macro_nonterminal: bool, + edition: Edition, } impl<'a> Classifier<'a> { - fn new(src: &str) -> Classifier<'_> { + fn new(src: &str, edition: Edition) -> Classifier<'_> { let tokens = TokenIter { src }.peekable(); - Classifier { tokens, in_attribute: false, in_macro: false, in_macro_nonterminal: false } + Classifier { + tokens, + in_attribute: false, + in_macro: false, + in_macro_nonterminal: false, + edition, + } } /// Exhausts the `Classifier` writing the output into `sink`. @@ -296,7 +309,7 @@ fn advance(&mut self, token: TokenKind, text: &'a str, sink: &mut dyn FnMut(High "Option" | "Result" => Class::PreludeTy, "Some" | "None" | "Ok" | "Err" => Class::PreludeVal, // Keywords are also included in the identifier set. - _ if Ident::from_str(text).is_reserved() => Class::KeyWord, + _ if Symbol::intern(text).is_reserved(|| self.edition) => Class::KeyWord, _ if self.in_macro_nonterminal => { self.in_macro_nonterminal = false; Class::MacroNonTerminal diff --git a/src/librustdoc/html/highlight/tests.rs b/src/librustdoc/html/highlight/tests.rs index f57f52d6f08..f97c8a7ab71 100644 --- a/src/librustdoc/html/highlight/tests.rs +++ b/src/librustdoc/html/highlight/tests.rs @@ -1,5 +1,6 @@ use super::write_code; use expect_test::expect_file; +use rustc_span::edition::Edition; const STYLE: &str = r#" + + +
@0⦊fn main() ⦉@0{ + if @0⦊true⦉@0 { + @5⦊@4,6,7,8,9⦊assert_eq!(1, 1);⦉@4,6,7,8,9⦉@5 + } else { + @11⦊@10,12,13,14,15⦊assert_eq!(1, 2);⦉@10,12,13,14,15⦉@11 + } +}@16⦊‸⦉@16
+ + diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.doctest_crate/doctest_crate.fn_run_in_doctests.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.doctest_crate/doctest_crate.fn_run_in_doctests.-------.InstrumentCoverage.0.html new file mode 100644 index 00000000000..ae119d9ca9f --- /dev/null +++ b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.doctest_crate/doctest_crate.fn_run_in_doctests.-------.InstrumentCoverage.0.html @@ -0,0 +1,173 @@ + + + + +doctest_crate.fn_run_in_doctests - Coverage Spans + + + +
@0⦊pub fn fn_run_in_doctests(conditional: usize) ⦉@0{ + match @0⦊conditional⦉@0 { + 1 => @7⦊@6,8,9,10,11⦊assert_eq!(1, 1)⦉@6,8,9,10,11⦉@7, // this is run, + 2 => @14⦊@13,15,16,17,18⦊assert_eq!(1, 1)⦉@13,15,16,17,18⦉@14, // this, + 3 => @21⦊@20,22,23,24,25⦊assert_eq!(1, 1)⦉@20,22,23,24,25⦉@21, // and this too + _ => @27⦊@26,28,29,30,31⦊assert_eq!(1, 2)⦉@26,28,29,30,31⦉@27, // however this is not + } +}@32⦊‸⦉@32
+ + diff --git a/src/test/run-make-fulldeps/coverage/compiletest-ignore-dir b/src/test/run-make-fulldeps/coverage/compiletest-ignore-dir index abf8df8fdc9..d1824d189e3 100644 --- a/src/test/run-make-fulldeps/coverage/compiletest-ignore-dir +++ b/src/test/run-make-fulldeps/coverage/compiletest-ignore-dir @@ -1,3 +1,3 @@ -# Directory "instrument-coverage" supports the tests at prefix ../instrument-coverage-* +# Directory "coverage" supports the tests at prefix ../coverage-* -# Use ./x.py [options] test src/test/run-make-fulldeps/instrument-coverage to run all related tests. +# Use ./x.py [options] test src/test/run-make-fulldeps/coverage to run all related tests. diff --git a/src/test/run-make-fulldeps/coverage/coverage_tools.mk b/src/test/run-make-fulldeps/coverage/coverage_tools.mk index 7dc485cd94d..4d340d4b1da 100644 --- a/src/test/run-make-fulldeps/coverage/coverage_tools.mk +++ b/src/test/run-make-fulldeps/coverage/coverage_tools.mk @@ -1,7 +1,7 @@ -# Common Makefile include for Rust `run-make-fulldeps/instrument-coverage-* tests. Include this +# Common Makefile include for Rust `run-make-fulldeps/coverage-* tests. Include this # file with the line: # -# -include ../instrument-coverage/coverage_tools.mk +# -include ../coverage/coverage_tools.mk -include ../tools.mk diff --git a/src/test/run-make-fulldeps/coverage/doctest.rs b/src/test/run-make-fulldeps/coverage/doctest.rs new file mode 100644 index 00000000000..e41d669bf0c --- /dev/null +++ b/src/test/run-make-fulldeps/coverage/doctest.rs @@ -0,0 +1,66 @@ +//! This test ensures that code from doctests is properly re-mapped. +//! See for more info. +//! +//! Just some random code: +//! ``` +//! if true { +//! // this is executed! +//! assert_eq!(1, 1); +//! } else { +//! // this is not! +//! assert_eq!(1, 2); +//! } +//! ``` +//! +//! doctest testing external code: +//! ``` +//! extern crate doctest_crate; +//! doctest_crate::fn_run_in_doctests(1); +//! ``` +//! +//! doctest returning a result: +//! ``` +//! #[derive(Debug)] +//! struct SomeError; +//! let mut res = Err(SomeError); +//! if res.is_ok() { +//! res?; +//! } else { +//! res = Ok(0); +//! } +//! // need to be explicit because rustdoc cant infer the return type +//! Ok::<(), SomeError>(()) +//! ``` +//! +//! doctest with custom main: +//! ``` +//! #[derive(Debug)] +//! struct SomeError; +//! +//! extern crate doctest_crate; +//! +//! fn doctest_main() -> Result<(), SomeError> { +//! doctest_crate::fn_run_in_doctests(2); +//! Ok(()) +//! } +//! +//! // this `main` is not shown as covered, as it clashes with all the other +//! // `main` functions that were automatically generated for doctests +//! fn main() -> Result<(), SomeError> { +//! doctest_main() +//! } +//! ``` + +/// doctest attached to fn testing external code: +/// ``` +/// extern crate doctest_crate; +/// doctest_crate::fn_run_in_doctests(3); +/// ``` +/// +fn main() { + if true { + assert_eq!(1, 1); + } else { + assert_eq!(1, 2); + } +} diff --git a/src/test/run-make-fulldeps/coverage/lib/doctest_crate.rs b/src/test/run-make-fulldeps/coverage/lib/doctest_crate.rs new file mode 100644 index 00000000000..c3210146d69 --- /dev/null +++ b/src/test/run-make-fulldeps/coverage/lib/doctest_crate.rs @@ -0,0 +1,9 @@ +/// A function run only from within doctests +pub fn fn_run_in_doctests(conditional: usize) { + match conditional { + 1 => assert_eq!(1, 1), // this is run, + 2 => assert_eq!(1, 1), // this, + 3 => assert_eq!(1, 1), // and this too + _ => assert_eq!(1, 2), // however this is not + } +} diff --git a/src/test/run-make-fulldeps/many-crates-but-no-match/Makefile b/src/test/run-make-fulldeps/many-crates-but-no-match/Makefile index 03a797d95f9..e7268311b13 100644 --- a/src/test/run-make-fulldeps/many-crates-but-no-match/Makefile +++ b/src/test/run-make-fulldeps/many-crates-but-no-match/Makefile @@ -1,9 +1,8 @@ -include ../tools.mk -# Modelled after compile-fail/changing-crates test, but this one puts +# Modelled after ui/changing-crates.rs test, but this one puts # more than one (mismatching) candidate crate into the search path, -# which did not appear directly expressible in compile-fail/aux-build -# infrastructure. +# which did not appear directly expressible in UI testing infrastructure. # # Note that we move the built libraries into target direcrtories rather than # use the `--out-dir` option because the `../tools.mk` file already bakes a @@ -33,4 +32,4 @@ all: 'crate `crateA`:' \ 'crate `crateB`:' \ < $(LOG) - # the 'crate `crateA`' will match two entries. \ No newline at end of file + # the 'crate `crateA`' will match two entries. diff --git a/src/test/run-make-fulldeps/separate-link/Makefile b/src/test/run-make-fulldeps/separate-link/Makefile new file mode 100644 index 00000000000..060484e89f9 --- /dev/null +++ b/src/test/run-make-fulldeps/separate-link/Makefile @@ -0,0 +1,6 @@ +-include ../tools.mk + +all: + echo 'fn main(){}' | $(RUSTC) -Z no-link - + $(RUSTC) -Z link-only $(TMPDIR)/rust_out.rlink + $(call RUN,rust_out) diff --git a/src/test/run-make-fulldeps/type-mismatch-same-crate-name/crateC.rs b/src/test/run-make-fulldeps/type-mismatch-same-crate-name/crateC.rs index 12898aa5c74..71b38a9f8ca 100644 --- a/src/test/run-make-fulldeps/type-mismatch-same-crate-name/crateC.rs +++ b/src/test/run-make-fulldeps/type-mismatch-same-crate-name/crateC.rs @@ -5,7 +5,7 @@ // causing a type mismatch. // The test is nearly the same as the one in -// compile-fail/type-mismatch-same-crate-name.rs +// ui/type/type-mismatch-same-crate-name.rs // but deals with the case where one of the crates // is only introduced as an indirect dependency. // and the type is accessed via a re-export. diff --git a/src/test/rustdoc-ui/error-in-impl-trait/const-generics.rs b/src/test/rustdoc-ui/error-in-impl-trait/const-generics.rs index 97760cbf8fb..ed62f0208aa 100644 --- a/src/test/rustdoc-ui/error-in-impl-trait/const-generics.rs +++ b/src/test/rustdoc-ui/error-in-impl-trait/const-generics.rs @@ -1,6 +1,5 @@ // check-pass // edition:2018 -#![feature(min_const_generics)] trait ValidTrait {} /// This has docs diff --git a/src/test/rustdoc-ui/intra-doc/non-path-primitives.rs b/src/test/rustdoc-ui/intra-doc/non-path-primitives.rs new file mode 100644 index 00000000000..114502b0ddf --- /dev/null +++ b/src/test/rustdoc-ui/intra-doc/non-path-primitives.rs @@ -0,0 +1,34 @@ +#![deny(broken_intra_doc_links)] +// These are links that could reasonably expected to work, but don't. + +// `[]` isn't supported because it had too many false positives. +//! [X]([T]::not_here) +//! [Y](&[]::not_here) +//! [X]([]::not_here) +//! [Y]([T;N]::not_here) + +// These don't work because markdown syntax doesn't allow it. +//! [[T]::rotate_left] //~ ERROR unresolved link to `T` +//! [&[]::not_here] +//![Z]([T; N]::map) //~ ERROR unresolved link to `Z` +//! [`[T; N]::map`] +//! [[]::map] +//! [Z][] //~ ERROR unresolved link to `Z` +//! +//! [Z]: [T; N]::map //~ ERROR unresolved link to `Z` + +// `()` isn't supported because it had too many false positives. +//! [()::not_here] +//! [X]((,)::not_here) +//! [(,)::not_here] + +// FIXME: Associated items on some primitives aren't working, because the impls +// are part of the compiler instead of being part of the source code. +//! [unit::eq] //~ ERROR unresolved +//! [tuple::eq] //~ ERROR unresolved +//! [fn::eq] //~ ERROR unresolved +//! [never::eq] //~ ERROR unresolved + +// FIXME(#78800): This breaks because it's a blanket impl +// (I think? Might break for other reasons too.) +//! [reference::deref] //~ ERROR unresolved diff --git a/src/test/rustdoc-ui/intra-doc/non-path-primitives.stderr b/src/test/rustdoc-ui/intra-doc/non-path-primitives.stderr new file mode 100644 index 00000000000..ea831e648f6 --- /dev/null +++ b/src/test/rustdoc-ui/intra-doc/non-path-primitives.stderr @@ -0,0 +1,69 @@ +error: unresolved link to `T` + --> $DIR/non-path-primitives.rs:11:7 + | +LL | //! [[T]::rotate_left] + | ^ no item named `T` in scope + | +note: the lint level is defined here + --> $DIR/non-path-primitives.rs:1:9 + | +LL | #![deny(broken_intra_doc_links)] + | ^^^^^^^^^^^^^^^^^^^^^^ + = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` + +error: unresolved link to `Z` + --> $DIR/non-path-primitives.rs:13:5 + | +LL | //![Z]([T; N]::map) + | ^ no item named `Z` in scope + | + = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` + +error: unresolved link to `Z` + --> $DIR/non-path-primitives.rs:16:6 + | +LL | //! [Z][] + | ^ no item named `Z` in scope + | + = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` + +error: unresolved link to `Z` + --> $DIR/non-path-primitives.rs:18:6 + | +LL | //! [Z]: [T; N]::map + | ^ no item named `Z` in scope + | + = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` + +error: unresolved link to `unit::eq` + --> $DIR/non-path-primitives.rs:27:6 + | +LL | //! [unit::eq] + | ^^^^^^^^ the builtin type `unit` has no associated item named `eq` + +error: unresolved link to `tuple::eq` + --> $DIR/non-path-primitives.rs:28:6 + | +LL | //! [tuple::eq] + | ^^^^^^^^^ the builtin type `tuple` has no associated item named `eq` + +error: unresolved link to `fn::eq` + --> $DIR/non-path-primitives.rs:29:6 + | +LL | //! [fn::eq] + | ^^^^^^ the builtin type `fn` has no associated item named `eq` + +error: unresolved link to `never::eq` + --> $DIR/non-path-primitives.rs:30:6 + | +LL | //! [never::eq] + | ^^^^^^^^^ the builtin type `never` has no associated item named `eq` + +error: unresolved link to `reference::deref` + --> $DIR/non-path-primitives.rs:34:6 + | +LL | //! [reference::deref] + | ^^^^^^^^^^^^^^^^ the builtin type `reference` has no associated item named `deref` + +error: aborting due to 9 previous errors + diff --git a/src/test/rustdoc-ui/reference-link-has-one-warning.rs b/src/test/rustdoc-ui/reference-link-has-one-warning.rs deleted file mode 100644 index 21cb7eb9040..00000000000 --- a/src/test/rustdoc-ui/reference-link-has-one-warning.rs +++ /dev/null @@ -1,6 +0,0 @@ -// ignore-test -// check-pass - -/// docs [label][with#anchor#error] -//~^ WARNING has an issue with the link anchor -pub struct S; diff --git a/src/test/rustdoc-ui/reference-link-has-one-warning.stderr b/src/test/rustdoc-ui/reference-link-has-one-warning.stderr deleted file mode 100644 index a1eeb60f178..00000000000 --- a/src/test/rustdoc-ui/reference-link-has-one-warning.stderr +++ /dev/null @@ -1,10 +0,0 @@ -warning: `[with#anchor#error]` has an issue with the link anchor. - --> $DIR/reference-link-has-one-warning.rs:3:18 - | -LL | /// docs [label][with#anchor#error] - | ^^^^^^^^^^^^^^^^^ only one `#` is allowed in a link - | - = note: `#[warn(broken_intra_doc_links)]` on by default - -warning: 1 warning emitted - diff --git a/src/test/rustdoc-ui/reference-links.rs b/src/test/rustdoc-ui/reference-links.rs new file mode 100644 index 00000000000..7c1a79722c9 --- /dev/null +++ b/src/test/rustdoc-ui/reference-links.rs @@ -0,0 +1,7 @@ +// Test that errors point to the reference, not to the title text. +#![deny(broken_intra_doc_links)] +//! Links to [a] [link][a] +//! +//! [a]: std::process::Comman +//~^ ERROR unresolved +//~| ERROR unresolved diff --git a/src/test/rustdoc-ui/reference-links.stderr b/src/test/rustdoc-ui/reference-links.stderr new file mode 100644 index 00000000000..6ba73fbdb00 --- /dev/null +++ b/src/test/rustdoc-ui/reference-links.stderr @@ -0,0 +1,20 @@ +error: unresolved link to `std::process::Comman` + --> $DIR/reference-links.rs:5:10 + | +LL | //! [a]: std::process::Comman + | ^^^^^^^^^^^^^^^^^^^^ no item named `Comman` in module `process` + | +note: the lint level is defined here + --> $DIR/reference-links.rs:2:9 + | +LL | #![deny(broken_intra_doc_links)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: unresolved link to `std::process::Comman` + --> $DIR/reference-links.rs:5:10 + | +LL | //! [a]: std::process::Comman + | ^^^^^^^^^^^^^^^^^^^^ no item named `Comman` in module `process` + +error: aborting due to 2 previous errors + diff --git a/src/test/rustdoc/async-fn.rs b/src/test/rustdoc/async-fn.rs index e7a7d1831f7..aa4ad261c80 100644 --- a/src/test/rustdoc/async-fn.rs +++ b/src/test/rustdoc/async-fn.rs @@ -1,6 +1,5 @@ +// ignore-tidy-linelength // edition:2018 -#![feature(min_const_generics)] - // @has async_fn/fn.foo.html '//pre[@class="rust fn"]' 'pub async fn foo() -> Option' pub async fn foo() -> Option { None @@ -48,7 +47,50 @@ pub async fn f() {} pub async fn mut_self(mut self, mut first: usize) {} } +pub trait Pattern<'a> {} + pub trait Trait {} // @has async_fn/fn.const_generics.html // @has - '//pre[@class="rust fn"]' 'pub async fn const_generics(_: impl Trait)' pub async fn const_generics(_: impl Trait) {} + +// test that elided lifetimes are properly elided and not displayed as `'_` +// regression test for #63037 +// @has async_fn/fn.elided.html +// @has - '//pre[@class="rust fn"]' 'pub async fn elided(foo: &str) -> &str' +pub async fn elided(foo: &str) -> &str {} +// This should really be shown as written, but for implementation reasons it's difficult. +// See `impl Clean for TyKind::Rptr`. +// @has async_fn/fn.user_elided.html +// @has - '//pre[@class="rust fn"]' 'pub async fn user_elided(foo: &str) -> &str' +pub async fn user_elided(foo: &'_ str) -> &str {} +// @has async_fn/fn.static_trait.html +// @has - '//pre[@class="rust fn"]' 'pub async fn static_trait(foo: &str) -> Box' +pub async fn static_trait(foo: &str) -> Box {} +// @has async_fn/fn.lifetime_for_trait.html +// @has - '//pre[@class="rust fn"]' "pub async fn lifetime_for_trait(foo: &str) -> Box" +pub async fn lifetime_for_trait(foo: &str) -> Box {} +// @has async_fn/fn.elided_in_input_trait.html +// @has - '//pre[@class="rust fn"]' "pub async fn elided_in_input_trait(t: impl Pattern<'_>)" +pub async fn elided_in_input_trait(t: impl Pattern<'_>) {} + +struct AsyncFdReadyGuard<'a, T> { x: &'a T } + +impl Foo { + // @has async_fn/struct.Foo.html + // @has - '//h4[@class="method"]' 'pub async fn complicated_lifetimes( &self, context: &impl Bar) -> impl Iterator' + pub async fn complicated_lifetimes(&self, context: &impl Bar) -> impl Iterator {} + // taken from `tokio` as an example of a method that was particularly bad before + // @has - '//h4[@class="method"]' "pub async fn readable(&self) -> Result, ()>" + pub async fn readable(&self) -> Result, ()> {} + // @has - '//h4[@class="method"]' "pub async fn mut_self(&mut self)" + pub async fn mut_self(&mut self) {} +} + +// test named lifetimes, just in case +// @has async_fn/fn.named.html +// @has - '//pre[@class="rust fn"]' "pub async fn named<'a, 'b>(foo: &'a str) -> &'b str" +pub async fn named<'a, 'b>(foo: &'a str) -> &'b str {} +// @has async_fn/fn.named_trait.html +// @has - '//pre[@class="rust fn"]' "pub async fn named_trait<'a, 'b>(foo: impl Pattern<'a>) -> impl Pattern<'b>" +pub async fn named_trait<'a, 'b>(foo: impl Pattern<'a>) -> impl Pattern<'b> {} diff --git a/src/test/rustdoc/codeblock-title.rs b/src/test/rustdoc/codeblock-title.rs index b59b21111b0..140c5b3a672 100644 --- a/src/test/rustdoc/codeblock-title.rs +++ b/src/test/rustdoc/codeblock-title.rs @@ -1,10 +1,9 @@ #![crate_name = "foo"] -// ignore-tidy-linelength - -// @has foo/fn.bar.html '//*[@class="tooltip compile_fail"]/span' "This example deliberately fails to compile" -// @has foo/fn.bar.html '//*[@class="tooltip ignore"]/span' "This example is not tested" -// @has foo/fn.bar.html '//*[@class="tooltip should_panic"]/span' "This example panics" +// @has foo/fn.bar.html '//*[@class="tooltip compile_fail"]' "ⓘ" +// @has foo/fn.bar.html '//*[@class="tooltip ignore"]' "ⓘ" +// @has foo/fn.bar.html '//*[@class="tooltip should_panic"]' "ⓘ" +// @has foo/fn.bar.html '//*[@data-edition="2018"]' "ⓘ" /// foo /// @@ -20,7 +19,7 @@ /// hoo(); /// ``` /// -/// ``` +/// ```edition2018 /// let x = 0; /// ``` pub fn bar() -> usize { 2 } diff --git a/src/test/rustdoc/const-generics/auxiliary/extern_crate.rs b/src/test/rustdoc/const-generics/auxiliary/extern_crate.rs index b8bd040f7a4..55b632a48f2 100644 --- a/src/test/rustdoc/const-generics/auxiliary/extern_crate.rs +++ b/src/test/rustdoc/const-generics/auxiliary/extern_crate.rs @@ -1,6 +1,4 @@ // edition:2018 -#![feature(min_const_generics)] - pub fn extern_fn() -> impl Iterator { [[0; N]; N].iter().copied() } diff --git a/src/test/rustdoc/const-generics/const-generics-docs.rs b/src/test/rustdoc/const-generics/const-generics-docs.rs index 9c68e067c6f..21bf216c304 100644 --- a/src/test/rustdoc/const-generics/const-generics-docs.rs +++ b/src/test/rustdoc/const-generics/const-generics-docs.rs @@ -1,6 +1,5 @@ // edition:2018 // aux-build: extern_crate.rs -#![feature(min_const_generics)] #![crate_name = "foo"] extern crate extern_crate; diff --git a/src/test/rustdoc/const-generics/type-alias.rs b/src/test/rustdoc/const-generics/type-alias.rs index 3064d0701e3..85160dc07a7 100644 --- a/src/test/rustdoc/const-generics/type-alias.rs +++ b/src/test/rustdoc/const-generics/type-alias.rs @@ -1,5 +1,4 @@ // ignore-tidy-linelength -#![feature(min_const_generics)] #![crate_name = "foo"] // @has foo/type.CellIndex.html '//pre[@class="rust typedef"]' 'type CellIndex = [i64; D];' diff --git a/src/test/rustdoc/intra-doc/non-path-primitives.rs b/src/test/rustdoc/intra-doc/non-path-primitives.rs new file mode 100644 index 00000000000..ad4f6ddd9de --- /dev/null +++ b/src/test/rustdoc/intra-doc/non-path-primitives.rs @@ -0,0 +1,39 @@ +// ignore-tidy-linelength +#![crate_name = "foo"] +#![deny(broken_intra_doc_links)] + +// @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.rotate_left"]' 'slice::rotate_left' +//! [slice::rotate_left] + +// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.array.html#method.map"]' 'array::map' +//! [array::map] + +// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.pointer.html#method.is_null"]' 'pointer::is_null' +// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.pointer.html#method.is_null"]' '*const::is_null' +// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.pointer.html#method.is_null"]' '*mut::is_null' +// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.pointer.html#method.is_null"]' '*::is_null' +//! [pointer::is_null] +//! [*const::is_null] +//! [*mut::is_null] +//! [*::is_null] + +// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.unit.html"]' 'unit' +//! [unit] + +// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.tuple.html"]' 'tuple' +//! [tuple] + +// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.reference.html"]' 'reference' +// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.reference.html"]' '&' +// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.reference.html"]' '&mut' +//! [reference] +//! [&] +//! [&mut] + +// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.fn.html"]' 'fn' +//! [fn] + +// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.never.html"]' 'never' +// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.never.html"]' '!' +//! [never] +//! [!] diff --git a/src/test/ui-fulldeps/dropck-tarena-cycle-checked.rs b/src/test/ui-fulldeps/dropck-tarena-cycle-checked.rs index fabcd727482..cc97971a0dd 100644 --- a/src/test/ui-fulldeps/dropck-tarena-cycle-checked.rs +++ b/src/test/ui-fulldeps/dropck-tarena-cycle-checked.rs @@ -1,8 +1,8 @@ // Reject mixing cyclic structure and Drop when using TypedArena. // -// (Compare against compile-fail/dropck_vec_cycle_checked.rs) +// (Compare against dropck-vec-cycle-checked.rs) // -// (Also compare against compile-fail/dropck_tarena_unsound_drop.rs, +// (Also compare against ui-fulldeps/dropck-tarena-unsound-drop.rs, // which is a reduction of this code to more directly show the reason // for the error message we see here.) diff --git a/src/test/ui-fulldeps/dropck_tarena_sound_drop.rs b/src/test/ui-fulldeps/dropck_tarena_sound_drop.rs index c5b9efee8e7..187f9a24a90 100644 --- a/src/test/ui-fulldeps/dropck_tarena_sound_drop.rs +++ b/src/test/ui-fulldeps/dropck_tarena_sound_drop.rs @@ -5,7 +5,7 @@ // methods might access borrowed data, as long as the borrowed data // has lifetime that strictly outlives the arena itself. // -// Compare against compile-fail/dropck_tarena_unsound_drop.rs, which +// Compare against ui-fulldeps/dropck-tarena-unsound-drop.rs, which // shows a similar setup, but restricts `f` so that the struct `C<'a>` // is force-fed a lifetime equal to that of the borrowed arena. diff --git a/src/test/ui/array-slice-vec/box-of-array-of-drop-1.rs b/src/test/ui/array-slice-vec/box-of-array-of-drop-1.rs index d4858932815..c8559d24728 100644 --- a/src/test/ui/array-slice-vec/box-of-array-of-drop-1.rs +++ b/src/test/ui/array-slice-vec/box-of-array-of-drop-1.rs @@ -17,7 +17,12 @@ impl Drop for D { fn drop(&mut self) { println!("Dropping {}", self.0); let old = LOG.load(Ordering::SeqCst); - LOG.compare_and_swap(old, old << 4 | self.0 as usize, Ordering::SeqCst); + let _ = LOG.compare_exchange( + old, + old << 4 | self.0 as usize, + Ordering::SeqCst, + Ordering::SeqCst + ); } } diff --git a/src/test/ui/array-slice-vec/box-of-array-of-drop-2.rs b/src/test/ui/array-slice-vec/box-of-array-of-drop-2.rs index e8a5b00a55b..e75051caabc 100644 --- a/src/test/ui/array-slice-vec/box-of-array-of-drop-2.rs +++ b/src/test/ui/array-slice-vec/box-of-array-of-drop-2.rs @@ -17,7 +17,12 @@ impl Drop for D { fn drop(&mut self) { println!("Dropping {}", self.0); let old = LOG.load(Ordering::SeqCst); - LOG.compare_and_swap(old, old << 4 | self.0 as usize, Ordering::SeqCst); + let _ = LOG.compare_exchange( + old, + old << 4 | self.0 as usize, + Ordering::SeqCst, + Ordering::SeqCst + ); } } diff --git a/src/test/ui/array-slice-vec/copy-out-of-array-1.rs b/src/test/ui/array-slice-vec/copy-out-of-array-1.rs index e64985ae3f6..c6d311148d0 100644 --- a/src/test/ui/array-slice-vec/copy-out-of-array-1.rs +++ b/src/test/ui/array-slice-vec/copy-out-of-array-1.rs @@ -2,7 +2,7 @@ // Ensure that we can copy out of a fixed-size array. // -// (Compare with compile-fail/move-out-of-array-1.rs) +// (Compare with ui/moves/move-out-of-array-1.rs) #[derive(Copy, Clone)] struct C { _x: u8 } diff --git a/src/test/ui/array-slice-vec/match_arr_unknown_len.stderr b/src/test/ui/array-slice-vec/match_arr_unknown_len.stderr index 7c1a92c79d9..0ad05b3adeb 100644 --- a/src/test/ui/array-slice-vec/match_arr_unknown_len.stderr +++ b/src/test/ui/array-slice-vec/match_arr_unknown_len.stderr @@ -6,7 +6,6 @@ LL | #![feature(const_generics)] | = note: `#[warn(incomplete_features)]` on by default = note: see issue #44580 for more information - = help: consider using `min_const_generics` instead, which is more stable and complete error[E0308]: mismatched types --> $DIR/match_arr_unknown_len.rs:6:9 diff --git a/src/test/ui/array-slice-vec/nested-vec-3.rs b/src/test/ui/array-slice-vec/nested-vec-3.rs index 52b892dbcdf..96497a53d30 100644 --- a/src/test/ui/array-slice-vec/nested-vec-3.rs +++ b/src/test/ui/array-slice-vec/nested-vec-3.rs @@ -18,7 +18,12 @@ impl Drop for D { fn drop(&mut self) { println!("Dropping {}", self.0); let old = LOG.load(Ordering::SeqCst); - LOG.compare_and_swap(old, old << 4 | self.0 as usize, Ordering::SeqCst); + let _ = LOG.compare_exchange( + old, + old << 4 | self.0 as usize, + Ordering::SeqCst, + Ordering::SeqCst, + ); } } diff --git a/src/test/ui/associated-consts/associated-const-type-parameter-arrays.rs b/src/test/ui/associated-consts/associated-const-type-parameter-arrays.rs index d51821059fc..5152d784047 100644 --- a/src/test/ui/associated-consts/associated-const-type-parameter-arrays.rs +++ b/src/test/ui/associated-consts/associated-const-type-parameter-arrays.rs @@ -14,8 +14,7 @@ impl Foo for Def { pub fn test() { let _array: [u32;
::Y]; - //~^ ERROR the trait bound `A: Foo` is not satisfied [E0277] + //~^ ERROR generic parameters may not be used } -fn main() { -} +fn main() {} diff --git a/src/test/ui/associated-consts/associated-const-type-parameter-arrays.stderr b/src/test/ui/associated-consts/associated-const-type-parameter-arrays.stderr index ac40e390cfb..d3a1cd30e2b 100644 --- a/src/test/ui/associated-consts/associated-const-type-parameter-arrays.stderr +++ b/src/test/ui/associated-consts/associated-const-type-parameter-arrays.stderr @@ -1,17 +1,11 @@ -error[E0277]: the trait bound `A: Foo` is not satisfied - --> $DIR/associated-const-type-parameter-arrays.rs:16:23 +error: generic parameters may not be used in const operations + --> $DIR/associated-const-type-parameter-arrays.rs:16:24 | -LL | const Y: usize; - | --------------- required by `Foo::Y` -... LL | let _array: [u32; ::Y]; - | ^^^^^^^^^^^^^ the trait `Foo` is not implemented for `A` + | ^ cannot perform const operation using `A` | -help: consider further restricting this bound - | -LL | pub fn test() { - | ^^^^^ + = note: type parameters may not be used in const expressions + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: aborting due to previous error -For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/associated-item/associated-item-duplicate-bounds.rs b/src/test/ui/associated-item/associated-item-duplicate-bounds.rs index bec922b0721..242a02353a1 100644 --- a/src/test/ui/associated-item/associated-item-duplicate-bounds.rs +++ b/src/test/ui/associated-item/associated-item-duplicate-bounds.rs @@ -5,7 +5,7 @@ trait Adapter { struct Foo { adapter: A, links: [u32; A::LINKS], // Shouldn't suggest bounds already there. - //~^ ERROR: no associated item named `LINKS` found + //~^ ERROR generic parameters may not be used in const operations } fn main() {} diff --git a/src/test/ui/associated-item/associated-item-duplicate-bounds.stderr b/src/test/ui/associated-item/associated-item-duplicate-bounds.stderr index ff1ad4c006e..0d84dca5b80 100644 --- a/src/test/ui/associated-item/associated-item-duplicate-bounds.stderr +++ b/src/test/ui/associated-item/associated-item-duplicate-bounds.stderr @@ -1,11 +1,11 @@ -error[E0599]: no associated item named `LINKS` found for type parameter `A` in the current scope - --> $DIR/associated-item-duplicate-bounds.rs:7:21 +error: generic parameters may not be used in const operations + --> $DIR/associated-item-duplicate-bounds.rs:7:18 | LL | links: [u32; A::LINKS], // Shouldn't suggest bounds already there. - | ^^^^^ associated item not found in `A` + | ^^^^^^^^ cannot perform const operation using `A` | - = help: items from traits can only be used if the type parameter is bounded by the trait + = note: type parameters may not be used in const expressions + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: aborting due to previous error -For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait.rs b/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait.rs index 5f06a829600..3b8c8c019e5 100644 --- a/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait.rs +++ b/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait.rs @@ -3,7 +3,7 @@ // the trait definition if there is no default method and for every impl, // `Self` does implement `Get`. // -// See also compile-fail tests associated-types-no-suitable-supertrait +// See also tests associated-types-no-suitable-supertrait // and associated-types-no-suitable-supertrait-2, which show how small // variants of the code below can fail. diff --git a/src/test/ui/associated-types/defaults-cyclic-fail-1.rs b/src/test/ui/associated-types/defaults-cyclic-fail-1.rs index afb2b3df716..61ef013236e 100644 --- a/src/test/ui/associated-types/defaults-cyclic-fail-1.rs +++ b/src/test/ui/associated-types/defaults-cyclic-fail-1.rs @@ -24,13 +24,13 @@ impl Tr for u32 { // ...but not in an impl that redefines one of the types. impl Tr for bool { type A = Box; - //~^ ERROR type mismatch resolving `::B == _` + //~^ ERROR overflow evaluating the requirement `::B == _` } // (the error is shown twice for some reason) impl Tr for usize { type B = &'static Self::A; - //~^ ERROR type mismatch resolving `::A == _` + //~^ ERROR overflow evaluating the requirement `::A == _` } fn main() { diff --git a/src/test/ui/associated-types/defaults-cyclic-fail-1.stderr b/src/test/ui/associated-types/defaults-cyclic-fail-1.stderr index ae7150d47ca..5e98520b411 100644 --- a/src/test/ui/associated-types/defaults-cyclic-fail-1.stderr +++ b/src/test/ui/associated-types/defaults-cyclic-fail-1.stderr @@ -1,15 +1,15 @@ -error[E0271]: type mismatch resolving `::B == _` +error[E0275]: overflow evaluating the requirement `::B == _` --> $DIR/defaults-cyclic-fail-1.rs:26:5 | LL | type A = Box; - | ^^^^^^^^^^^^^^^^^^^^^^ cyclic type of infinite size + | ^^^^^^^^^^^^^^^^^^^^^^ -error[E0271]: type mismatch resolving `::A == _` +error[E0275]: overflow evaluating the requirement `::A == _` --> $DIR/defaults-cyclic-fail-1.rs:32:5 | LL | type B = &'static Self::A; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ cyclic type of infinite size + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0275`. diff --git a/src/test/ui/associated-types/defaults-cyclic-fail-2.rs b/src/test/ui/associated-types/defaults-cyclic-fail-2.rs index ba4bb0d5a29..e91c9f2d29a 100644 --- a/src/test/ui/associated-types/defaults-cyclic-fail-2.rs +++ b/src/test/ui/associated-types/defaults-cyclic-fail-2.rs @@ -25,13 +25,13 @@ impl Tr for u32 { impl Tr for bool { type A = Box; - //~^ ERROR type mismatch resolving `::B == _` + //~^ ERROR overflow evaluating the requirement `::B == _` } // (the error is shown twice for some reason) impl Tr for usize { type B = &'static Self::A; - //~^ ERROR type mismatch resolving `::A == _` + //~^ ERROR overflow evaluating the requirement `::A == _` } fn main() { diff --git a/src/test/ui/associated-types/defaults-cyclic-fail-2.stderr b/src/test/ui/associated-types/defaults-cyclic-fail-2.stderr index 0dfbac2dec5..c538805f858 100644 --- a/src/test/ui/associated-types/defaults-cyclic-fail-2.stderr +++ b/src/test/ui/associated-types/defaults-cyclic-fail-2.stderr @@ -1,15 +1,15 @@ -error[E0271]: type mismatch resolving `::B == _` +error[E0275]: overflow evaluating the requirement `::B == _` --> $DIR/defaults-cyclic-fail-2.rs:27:5 | LL | type A = Box; - | ^^^^^^^^^^^^^^^^^^^^^^ cyclic type of infinite size + | ^^^^^^^^^^^^^^^^^^^^^^ -error[E0271]: type mismatch resolving `::A == _` +error[E0275]: overflow evaluating the requirement `::A == _` --> $DIR/defaults-cyclic-fail-2.rs:33:5 | LL | type B = &'static Self::A; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ cyclic type of infinite size + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0275`. diff --git a/src/test/ui/associated-types/defaults-wf.stderr b/src/test/ui/associated-types/defaults-wf.stderr index 4c43e6a182d..d4fa5be742f 100644 --- a/src/test/ui/associated-types/defaults-wf.stderr +++ b/src/test/ui/associated-types/defaults-wf.stderr @@ -4,7 +4,7 @@ error[E0277]: the size for values of type `[u8]` cannot be known at compilation LL | type Ty = Vec<[u8]>; | ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | - ::: $SRC_DIR/alloc/src/vec.rs:LL:COL + ::: $SRC_DIR/alloc/src/vec/mod.rs:LL:COL | LL | pub struct Vec { | - required by this bound in `Vec` diff --git a/src/test/ui/associated-types/impl-wf-cycle-1.rs b/src/test/ui/associated-types/impl-wf-cycle-1.rs new file mode 100644 index 00000000000..ba074210a2b --- /dev/null +++ b/src/test/ui/associated-types/impl-wf-cycle-1.rs @@ -0,0 +1,29 @@ +// Regression test for #79714 + +trait Baz {} +impl Baz for () {} +impl Baz for (T,) {} + +trait Fiz {} +impl Fiz for bool {} + +trait Grault { + type A; + type B; +} + +impl Grault for (T,) +where + Self::A: Baz, + Self::B: Fiz, +{ + type A = (); + //~^ ERROR overflow evaluating the requirement `<(T,) as Grault>::A == _` + type B = bool; + //~^ ERROR overflow evaluating the requirement `<(T,) as Grault>::A == _` +} +//~^^^^^^^^^^ ERROR overflow evaluating the requirement `<(T,) as Grault>::A == _` + +fn main() { + let x: <(_,) as Grault>::A = (); +} diff --git a/src/test/ui/associated-types/impl-wf-cycle-1.stderr b/src/test/ui/associated-types/impl-wf-cycle-1.stderr new file mode 100644 index 00000000000..82328048c99 --- /dev/null +++ b/src/test/ui/associated-types/impl-wf-cycle-1.stderr @@ -0,0 +1,39 @@ +error[E0275]: overflow evaluating the requirement `<(T,) as Grault>::A == _` + --> $DIR/impl-wf-cycle-1.rs:15:1 + | +LL | / impl Grault for (T,) +LL | | where +LL | | Self::A: Baz, +LL | | Self::B: Fiz, +... | +LL | | +LL | | } + | |_^ + | + = note: required because of the requirements on the impl of `Grault` for `(T,)` + = note: 1 redundant requirements hidden + = note: required because of the requirements on the impl of `Grault` for `(T,)` + +error[E0275]: overflow evaluating the requirement `<(T,) as Grault>::A == _` + --> $DIR/impl-wf-cycle-1.rs:20:5 + | +LL | type A = (); + | ^^^^^^^^^^^^ + | + = note: required because of the requirements on the impl of `Grault` for `(T,)` + = note: 1 redundant requirements hidden + = note: required because of the requirements on the impl of `Grault` for `(T,)` + +error[E0275]: overflow evaluating the requirement `<(T,) as Grault>::A == _` + --> $DIR/impl-wf-cycle-1.rs:22:5 + | +LL | type B = bool; + | ^^^^^^^^^^^^^^ + | + = note: required because of the requirements on the impl of `Grault` for `(T,)` + = note: 1 redundant requirements hidden + = note: required because of the requirements on the impl of `Grault` for `(T,)` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0275`. diff --git a/src/test/ui/associated-types/impl-wf-cycle-2.rs b/src/test/ui/associated-types/impl-wf-cycle-2.rs new file mode 100644 index 00000000000..6fccc54f229 --- /dev/null +++ b/src/test/ui/associated-types/impl-wf-cycle-2.rs @@ -0,0 +1,16 @@ +// Regression test for #79714 + +trait Grault { + type A; +} + +impl Grault for (T,) +where + Self::A: Copy, +{ + type A = (); + //~^ ERROR overflow evaluating the requirement `<(T,) as Grault>::A == _` +} +//~^^^^^^^ ERROR overflow evaluating the requirement `<(T,) as Grault>::A == _` + +fn main() {} diff --git a/src/test/ui/associated-types/impl-wf-cycle-2.stderr b/src/test/ui/associated-types/impl-wf-cycle-2.stderr new file mode 100644 index 00000000000..5cd18a33adf --- /dev/null +++ b/src/test/ui/associated-types/impl-wf-cycle-2.stderr @@ -0,0 +1,25 @@ +error[E0275]: overflow evaluating the requirement `<(T,) as Grault>::A == _` + --> $DIR/impl-wf-cycle-2.rs:7:1 + | +LL | / impl Grault for (T,) +LL | | where +LL | | Self::A: Copy, +LL | | { +LL | | type A = (); +LL | | +LL | | } + | |_^ + | + = note: required because of the requirements on the impl of `Grault` for `(T,)` + +error[E0275]: overflow evaluating the requirement `<(T,) as Grault>::A == _` + --> $DIR/impl-wf-cycle-2.rs:11:5 + | +LL | type A = (); + | ^^^^^^^^^^^^ + | + = note: required because of the requirements on the impl of `Grault` for `(T,)` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0275`. diff --git a/src/test/ui/associated-types/issue-23595-1.rs b/src/test/ui/associated-types/issue-23595-1.rs new file mode 100644 index 00000000000..483c205f42d --- /dev/null +++ b/src/test/ui/associated-types/issue-23595-1.rs @@ -0,0 +1,14 @@ +#![feature(associated_type_defaults)] + +use std::ops::Index; + +trait Hierarchy { + type Value; + type ChildKey; + type Children = dyn Index; + //~^ ERROR: the value of the associated types + + fn data(&self) -> Option<(Self::Value, Self::Children)>; +} + +fn main() {} diff --git a/src/test/ui/associated-types/issue-23595-1.stderr b/src/test/ui/associated-types/issue-23595-1.stderr new file mode 100644 index 00000000000..bb455684ee3 --- /dev/null +++ b/src/test/ui/associated-types/issue-23595-1.stderr @@ -0,0 +1,16 @@ +error[E0191]: the value of the associated types `ChildKey` (from trait `Hierarchy`), `Children` (from trait `Hierarchy`), `Value` (from trait `Hierarchy`) must be specified + --> $DIR/issue-23595-1.rs:8:58 + | +LL | type Value; + | ----------- `Value` defined here +LL | type ChildKey; + | -------------- `ChildKey` defined here +LL | type Children = dyn Index; + | -----------------------------------------------------^^^^^^^^^-- + | | | + | | help: specify the associated types: `Hierarchy` + | `Children` defined here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0191`. diff --git a/src/test/ui/associated-types/issue-27675-unchecked-bounds.rs b/src/test/ui/associated-types/issue-27675-unchecked-bounds.rs new file mode 100644 index 00000000000..1cfc2304531 --- /dev/null +++ b/src/test/ui/associated-types/issue-27675-unchecked-bounds.rs @@ -0,0 +1,19 @@ +/// The compiler previously did not properly check the bound of `From` when it was used from type +/// of the dyn trait object (use in `copy_any` below). Since the associated type is under user +/// control in this usage, the compiler could be tricked to believe any type implemented any trait. +/// This would ICE, except for pure marker traits like `Copy`. It did not require providing an +/// instance of the dyn trait type, only name said type. +trait Setup { + type From: Copy; +} + +fn copy(from: &U::From) -> U::From { + *from +} + +pub fn copy_any(t: &T) -> T { + copy::>(t) + //~^ ERROR the trait bound `T: Copy` is not satisfied +} + +fn main() {} diff --git a/src/test/ui/associated-types/issue-27675-unchecked-bounds.stderr b/src/test/ui/associated-types/issue-27675-unchecked-bounds.stderr new file mode 100644 index 00000000000..02396bd00a5 --- /dev/null +++ b/src/test/ui/associated-types/issue-27675-unchecked-bounds.stderr @@ -0,0 +1,17 @@ +error[E0277]: the trait bound `T: Copy` is not satisfied + --> $DIR/issue-27675-unchecked-bounds.rs:15:31 + | +LL | fn copy(from: &U::From) -> U::From { + | ----- required by this bound in `copy` +... +LL | copy::>(t) + | ^ the trait `Copy` is not implemented for `T` + | +help: consider restricting type parameter `T` + | +LL | pub fn copy_any(t: &T) -> T { + | ^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/async-await/issues/issue-78654.full.stderr b/src/test/ui/async-await/issues/issue-78654.full.stderr index ff0260523db..a9208ade740 100644 --- a/src/test/ui/async-await/issues/issue-78654.full.stderr +++ b/src/test/ui/async-await/issues/issue-78654.full.stderr @@ -1,11 +1,11 @@ error[E0573]: expected type, found built-in attribute `feature` - --> $DIR/issue-78654.rs:10:15 + --> $DIR/issue-78654.rs:9:15 | LL | impl Foo { | ^^^^^^^ not a type error[E0207]: the const parameter `H` is not constrained by the impl trait, self type, or predicates - --> $DIR/issue-78654.rs:10:12 + --> $DIR/issue-78654.rs:9:12 | LL | impl Foo { | ^ unconstrained const parameter diff --git a/src/test/ui/async-await/issues/issue-78654.min.stderr b/src/test/ui/async-await/issues/issue-78654.min.stderr index ff0260523db..a9208ade740 100644 --- a/src/test/ui/async-await/issues/issue-78654.min.stderr +++ b/src/test/ui/async-await/issues/issue-78654.min.stderr @@ -1,11 +1,11 @@ error[E0573]: expected type, found built-in attribute `feature` - --> $DIR/issue-78654.rs:10:15 + --> $DIR/issue-78654.rs:9:15 | LL | impl Foo { | ^^^^^^^ not a type error[E0207]: the const parameter `H` is not constrained by the impl trait, self type, or predicates - --> $DIR/issue-78654.rs:10:12 + --> $DIR/issue-78654.rs:9:12 | LL | impl Foo { | ^ unconstrained const parameter diff --git a/src/test/ui/async-await/issues/issue-78654.rs b/src/test/ui/async-await/issues/issue-78654.rs index b57ed35f8e3..37ebb4ecac8 100644 --- a/src/test/ui/async-await/issues/issue-78654.rs +++ b/src/test/ui/async-await/issues/issue-78654.rs @@ -3,7 +3,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] struct Foo; diff --git a/src/test/ui/bad/bad-sized.stderr b/src/test/ui/bad/bad-sized.stderr index 60a5bb9f786..260d78b543a 100644 --- a/src/test/ui/bad/bad-sized.stderr +++ b/src/test/ui/bad/bad-sized.stderr @@ -15,7 +15,7 @@ error[E0277]: the size for values of type `dyn Trait` cannot be known at compila LL | let x: Vec = Vec::new(); | ^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | - ::: $SRC_DIR/alloc/src/vec.rs:LL:COL + ::: $SRC_DIR/alloc/src/vec/mod.rs:LL:COL | LL | pub struct Vec { | - required by this bound in `Vec` diff --git a/src/test/ui/binding/const-param.full.stderr b/src/test/ui/binding/const-param.full.stderr new file mode 100644 index 00000000000..0200c6def24 --- /dev/null +++ b/src/test/ui/binding/const-param.full.stderr @@ -0,0 +1,9 @@ +error[E0158]: const parameters cannot be referenced in patterns + --> $DIR/const-param.rs:8:9 + | +LL | N => {} + | ^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0158`. diff --git a/src/test/ui/binding/const-param.min.stderr b/src/test/ui/binding/const-param.min.stderr new file mode 100644 index 00000000000..0200c6def24 --- /dev/null +++ b/src/test/ui/binding/const-param.min.stderr @@ -0,0 +1,9 @@ +error[E0158]: const parameters cannot be referenced in patterns + --> $DIR/const-param.rs:8:9 + | +LL | N => {} + | ^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0158`. diff --git a/src/test/ui/binding/const-param.rs b/src/test/ui/binding/const-param.rs index 3c7f4d071f6..4aec801cb15 100644 --- a/src/test/ui/binding/const-param.rs +++ b/src/test/ui/binding/const-param.rs @@ -1,6 +1,7 @@ // Identifier pattern referring to a const generic parameter is an error (issue #68853). - -#![feature(const_generics)] //~ WARN the feature `const_generics` is incomplete +// revisions: full min +#![cfg_attr(full, feature(const_generics))] +#![cfg_attr(full, allow(incomplete_features))] fn check() { match 1 { diff --git a/src/test/ui/binding/const-param.stderr b/src/test/ui/binding/const-param.stderr deleted file mode 100644 index d3d06a2d834..00000000000 --- a/src/test/ui/binding/const-param.stderr +++ /dev/null @@ -1,19 +0,0 @@ -warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/const-param.rs:3:12 - | -LL | #![feature(const_generics)] - | ^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #44580 for more information - = help: consider using `min_const_generics` instead, which is more stable and complete - -error[E0158]: const parameters cannot be referenced in patterns - --> $DIR/const-param.rs:7:9 - | -LL | N => {} - | ^ - -error: aborting due to previous error; 1 warning emitted - -For more information about this error, try `rustc --explain E0158`. diff --git a/src/test/ui/borrowck/borrowck-mut-borrow-linear-errors.stderr b/src/test/ui/borrowck/borrowck-mut-borrow-linear-errors.stderr index ca1496a6c8d..a4090777939 100644 --- a/src/test/ui/borrowck/borrowck-mut-borrow-linear-errors.stderr +++ b/src/test/ui/borrowck/borrowck-mut-borrow-linear-errors.stderr @@ -23,7 +23,7 @@ error[E0499]: cannot borrow `x` as mutable more than once at a time --> $DIR/borrowck-mut-borrow-linear-errors.rs:12:30 | LL | _ => { addr.push(&mut x); } - | ^^^^^^ mutable borrow starts here in previous iteration of loop + | ^^^^^^ `x` was mutably borrowed here in the previous iteration of the loop error: aborting due to 3 previous errors diff --git a/src/test/ui/borrowck/mut-borrow-in-loop.stderr b/src/test/ui/borrowck/mut-borrow-in-loop.stderr index 260b9673d74..b621694a548 100644 --- a/src/test/ui/borrowck/mut-borrow-in-loop.stderr +++ b/src/test/ui/borrowck/mut-borrow-in-loop.stderr @@ -15,7 +15,7 @@ LL | impl<'a, T : 'a> FuncWrapper<'a, T> { LL | (self.func)(arg) | ------------^^^- | | | - | | mutable borrow starts here in previous iteration of loop + | | `*arg` was mutably borrowed here in the previous iteration of the loop | argument requires that `*arg` is borrowed for `'a` error[E0499]: cannot borrow `*arg` as mutable more than once at a time @@ -27,7 +27,7 @@ LL | impl<'a, T : 'a> FuncWrapper<'a, T> { LL | (self.func)(arg) | ------------^^^- | | | - | | mutable borrow starts here in previous iteration of loop + | | `*arg` was mutably borrowed here in the previous iteration of the loop | argument requires that `*arg` is borrowed for `'a` error[E0499]: cannot borrow `*arg` as mutable more than once at a time @@ -39,7 +39,7 @@ LL | impl<'a, T : 'a> FuncWrapper<'a, T> { LL | (self.func)(arg) | ------------^^^- | | | - | | mutable borrow starts here in previous iteration of loop + | | `*arg` was mutably borrowed here in the previous iteration of the loop | argument requires that `*arg` is borrowed for `'a` error: aborting due to 3 previous errors; 1 warning emitted diff --git a/src/test/ui/borrowck/two-phase-across-loop.stderr b/src/test/ui/borrowck/two-phase-across-loop.stderr index 38993a50bf6..d4e515d12bb 100644 --- a/src/test/ui/borrowck/two-phase-across-loop.stderr +++ b/src/test/ui/borrowck/two-phase-across-loop.stderr @@ -2,7 +2,7 @@ error[E0499]: cannot borrow `foo` as mutable more than once at a time --> $DIR/two-phase-across-loop.rs:17:22 | LL | strings.push(foo.get_string()); - | ^^^ mutable borrow starts here in previous iteration of loop + | ^^^ `foo` was mutably borrowed here in the previous iteration of the loop error: aborting due to previous error diff --git a/src/test/ui/closures/coerce-unsafe-closure-to-unsafe-fn-ptr.rs b/src/test/ui/closures/coerce-unsafe-closure-to-unsafe-fn-ptr.rs new file mode 100644 index 00000000000..36777693fab --- /dev/null +++ b/src/test/ui/closures/coerce-unsafe-closure-to-unsafe-fn-ptr.rs @@ -0,0 +1,5 @@ +fn main() { + let _: unsafe fn() = || { ::std::pin::Pin::new_unchecked(&0_u8); }; + //~^ ERROR E0133 + let _: unsafe fn() = || unsafe { ::std::pin::Pin::new_unchecked(&0_u8); }; // OK +} diff --git a/src/test/ui/closures/coerce-unsafe-closure-to-unsafe-fn-ptr.stderr b/src/test/ui/closures/coerce-unsafe-closure-to-unsafe-fn-ptr.stderr new file mode 100644 index 00000000000..a1fb1c02e46 --- /dev/null +++ b/src/test/ui/closures/coerce-unsafe-closure-to-unsafe-fn-ptr.stderr @@ -0,0 +1,11 @@ +error[E0133]: call to unsafe function is unsafe and requires unsafe function or block + --> $DIR/coerce-unsafe-closure-to-unsafe-fn-ptr.rs:2:31 + | +LL | let _: unsafe fn() = || { ::std::pin::Pin::new_unchecked(&0_u8); }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/src/test/ui/closures/coerce-unsafe-to-closure.rs b/src/test/ui/closures/coerce-unsafe-to-closure.rs new file mode 100644 index 00000000000..78bdd36f9cc --- /dev/null +++ b/src/test/ui/closures/coerce-unsafe-to-closure.rs @@ -0,0 +1,4 @@ +fn main() { + let x: Option<&[u8]> = Some("foo").map(std::mem::transmute); + //~^ ERROR E0277 +} diff --git a/src/test/ui/closures/coerce-unsafe-to-closure.stderr b/src/test/ui/closures/coerce-unsafe-to-closure.stderr new file mode 100644 index 00000000000..ab035d03b05 --- /dev/null +++ b/src/test/ui/closures/coerce-unsafe-to-closure.stderr @@ -0,0 +1,11 @@ +error[E0277]: expected a `FnOnce<(&str,)>` closure, found `unsafe extern "rust-intrinsic" fn(_) -> _ {transmute::<_, _>}` + --> $DIR/coerce-unsafe-to-closure.rs:2:44 + | +LL | let x: Option<&[u8]> = Some("foo").map(std::mem::transmute); + | ^^^^^^^^^^^^^^^^^^^ expected an `FnOnce<(&str,)>` closure, found `unsafe extern "rust-intrinsic" fn(_) -> _ {transmute::<_, _>}` + | + = help: the trait `FnOnce<(&str,)>` is not implemented for `unsafe extern "rust-intrinsic" fn(_) -> _ {transmute::<_, _>}` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/const-generics/apit-with-const-param.rs b/src/test/ui/const-generics/apit-with-const-param.rs index facc0bcf513..3bc62141927 100644 --- a/src/test/ui/const-generics/apit-with-const-param.rs +++ b/src/test/ui/const-generics/apit-with-const-param.rs @@ -3,7 +3,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] trait Trait {} diff --git a/src/test/ui/const-generics/argument_order.full.stderr b/src/test/ui/const-generics/argument_order.full.stderr index b52e5050703..e533d4f7fb8 100644 --- a/src/test/ui/const-generics/argument_order.full.stderr +++ b/src/test/ui/const-generics/argument_order.full.stderr @@ -1,11 +1,11 @@ error: lifetime parameters must be declared prior to const parameters - --> $DIR/argument_order.rs:12:32 + --> $DIR/argument_order.rs:11:32 | LL | struct AlsoBad { | -----------------^^-----^^-------------------- help: reorder the parameters: lifetimes, then consts and types: `<'a, 'b, const N: usize, T, const M: usize, U>` error[E0747]: lifetime provided when a type was expected - --> $DIR/argument_order.rs:20:23 + --> $DIR/argument_order.rs:19:23 | LL | let _: AlsoBad<7, 'static, u32, 'static, 17, u16>; | ^^^^^^^ diff --git a/src/test/ui/const-generics/argument_order.min.stderr b/src/test/ui/const-generics/argument_order.min.stderr index 728ae69b41f..f23bc6d6a2b 100644 --- a/src/test/ui/const-generics/argument_order.min.stderr +++ b/src/test/ui/const-generics/argument_order.min.stderr @@ -1,23 +1,23 @@ error: type parameters must be declared prior to const parameters - --> $DIR/argument_order.rs:6:28 + --> $DIR/argument_order.rs:5:28 | LL | struct Bad { | -----------------^- help: reorder the parameters: lifetimes, then types, then consts: `` error: lifetime parameters must be declared prior to const parameters - --> $DIR/argument_order.rs:12:32 + --> $DIR/argument_order.rs:11:32 | LL | struct AlsoBad { | -----------------^^-----^^-------------------- help: reorder the parameters: lifetimes, then types, then consts: `<'a, 'b, T, U, const N: usize, const M: usize>` error: type parameters must be declared prior to const parameters - --> $DIR/argument_order.rs:12:36 + --> $DIR/argument_order.rs:11:36 | LL | struct AlsoBad { | ---------------------^----------------------^- help: reorder the parameters: lifetimes, then types, then consts: `<'a, 'b, T, U, const N: usize, const M: usize>` error[E0747]: lifetime provided when a type was expected - --> $DIR/argument_order.rs:20:23 + --> $DIR/argument_order.rs:19:23 | LL | let _: AlsoBad<7, 'static, u32, 'static, 17, u16>; | ^^^^^^^ diff --git a/src/test/ui/const-generics/argument_order.rs b/src/test/ui/const-generics/argument_order.rs index 507baf5fd75..95eaeea5818 100644 --- a/src/test/ui/const-generics/argument_order.rs +++ b/src/test/ui/const-generics/argument_order.rs @@ -1,7 +1,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] struct Bad { //[min]~^ ERROR type parameters must be declared prior to const parameters diff --git a/src/test/ui/const-generics/array-size-in-generic-struct-param.full.stderr b/src/test/ui/const-generics/array-size-in-generic-struct-param.full.stderr index cf4487b5829..0fb23e41b01 100644 --- a/src/test/ui/const-generics/array-size-in-generic-struct-param.full.stderr +++ b/src/test/ui/const-generics/array-size-in-generic-struct-param.full.stderr @@ -1,5 +1,5 @@ error: constant expression depends on a generic parameter - --> $DIR/array-size-in-generic-struct-param.rs:9:38 + --> $DIR/array-size-in-generic-struct-param.rs:8:38 | LL | struct ArithArrayLen([u32; 0 + N]); | ^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | struct ArithArrayLen([u32; 0 + N]); = note: this may fail depending on what value the parameter takes error: constant expression depends on a generic parameter - --> $DIR/array-size-in-generic-struct-param.rs:20:10 + --> $DIR/array-size-in-generic-struct-param.rs:19:10 | LL | arr: [u8; CFG.arr_size], | ^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/const-generics/array-size-in-generic-struct-param.min.stderr b/src/test/ui/const-generics/array-size-in-generic-struct-param.min.stderr index 73c9ea59c95..7af23103ce7 100644 --- a/src/test/ui/const-generics/array-size-in-generic-struct-param.min.stderr +++ b/src/test/ui/const-generics/array-size-in-generic-struct-param.min.stderr @@ -1,5 +1,5 @@ error: generic parameters may not be used in const operations - --> $DIR/array-size-in-generic-struct-param.rs:9:48 + --> $DIR/array-size-in-generic-struct-param.rs:8:48 | LL | struct ArithArrayLen([u32; 0 + N]); | ^ cannot perform const operation using `N` @@ -8,7 +8,7 @@ LL | struct ArithArrayLen([u32; 0 + N]); = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: generic parameters may not be used in const operations - --> $DIR/array-size-in-generic-struct-param.rs:20:15 + --> $DIR/array-size-in-generic-struct-param.rs:19:15 | LL | arr: [u8; CFG.arr_size], | ^^^ cannot perform const operation using `CFG` @@ -17,7 +17,7 @@ LL | arr: [u8; CFG.arr_size], = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: `Config` is forbidden as the type of a const generic parameter - --> $DIR/array-size-in-generic-struct-param.rs:18:21 + --> $DIR/array-size-in-generic-struct-param.rs:17:21 | LL | struct B { | ^^^^^^ diff --git a/src/test/ui/const-generics/array-size-in-generic-struct-param.rs b/src/test/ui/const-generics/array-size-in-generic-struct-param.rs index 768180d0813..cd0a9742cd1 100644 --- a/src/test/ui/const-generics/array-size-in-generic-struct-param.rs +++ b/src/test/ui/const-generics/array-size-in-generic-struct-param.rs @@ -3,7 +3,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] #[allow(dead_code)] struct ArithArrayLen([u32; 0 + N]); diff --git a/src/test/ui/const-generics/array-wrapper-struct-ctor.rs b/src/test/ui/const-generics/array-wrapper-struct-ctor.rs index 390b6cc2049..732a1871456 100644 --- a/src/test/ui/const-generics/array-wrapper-struct-ctor.rs +++ b/src/test/ui/const-generics/array-wrapper-struct-ctor.rs @@ -2,7 +2,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] #![allow(dead_code)] diff --git a/src/test/ui/const-generics/associated-type-bound-fail.full.stderr b/src/test/ui/const-generics/associated-type-bound-fail.full.stderr index 8ccbe5dee0e..6644e74f97a 100644 --- a/src/test/ui/const-generics/associated-type-bound-fail.full.stderr +++ b/src/test/ui/const-generics/associated-type-bound-fail.full.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `u16: Bar` is not satisfied - --> $DIR/associated-type-bound-fail.rs:14:5 + --> $DIR/associated-type-bound-fail.rs:13:5 | LL | type Assoc: Bar; | ------ required by this bound in `Foo::Assoc` diff --git a/src/test/ui/const-generics/associated-type-bound-fail.min.stderr b/src/test/ui/const-generics/associated-type-bound-fail.min.stderr index 8ccbe5dee0e..6644e74f97a 100644 --- a/src/test/ui/const-generics/associated-type-bound-fail.min.stderr +++ b/src/test/ui/const-generics/associated-type-bound-fail.min.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `u16: Bar` is not satisfied - --> $DIR/associated-type-bound-fail.rs:14:5 + --> $DIR/associated-type-bound-fail.rs:13:5 | LL | type Assoc: Bar; | ------ required by this bound in `Foo::Assoc` diff --git a/src/test/ui/const-generics/associated-type-bound-fail.rs b/src/test/ui/const-generics/associated-type-bound-fail.rs index 3440b1356c2..83b26700805 100644 --- a/src/test/ui/const-generics/associated-type-bound-fail.rs +++ b/src/test/ui/const-generics/associated-type-bound-fail.rs @@ -1,7 +1,6 @@ // revisions: full min #![cfg_attr(full, allow(incomplete_features))] #![cfg_attr(full, feature(const_generics))] -#![cfg_attr(min, feature(min_const_generics))] trait Bar {} diff --git a/src/test/ui/const-generics/associated-type-bound.rs b/src/test/ui/const-generics/associated-type-bound.rs index 374a49194b1..02f77396c0b 100644 --- a/src/test/ui/const-generics/associated-type-bound.rs +++ b/src/test/ui/const-generics/associated-type-bound.rs @@ -2,7 +2,6 @@ // revisions: full min #![cfg_attr(full, allow(incomplete_features))] #![cfg_attr(full, feature(const_generics))] -#![cfg_attr(min, feature(min_const_generics))] trait Bar {} diff --git a/src/test/ui/const-generics/auxiliary/const_generic_lib.rs b/src/test/ui/const-generics/auxiliary/const_generic_lib.rs index 899a5a1836c..8d4cd9c0d6b 100644 --- a/src/test/ui/const-generics/auxiliary/const_generic_lib.rs +++ b/src/test/ui/const-generics/auxiliary/const_generic_lib.rs @@ -1,6 +1,5 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] pub struct Struct(pub [u8; N]); diff --git a/src/test/ui/const-generics/auxiliary/crayte.rs b/src/test/ui/const-generics/auxiliary/crayte.rs index 725005971e1..d9baab956c9 100644 --- a/src/test/ui/const-generics/auxiliary/crayte.rs +++ b/src/test/ui/const-generics/auxiliary/crayte.rs @@ -1,7 +1,6 @@ // edition:2018 #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] pub trait Foo {} struct Local; diff --git a/src/test/ui/const-generics/auxiliary/impl-const.rs b/src/test/ui/const-generics/auxiliary/impl-const.rs index 2e25dadf119..4a6b5784221 100644 --- a/src/test/ui/const-generics/auxiliary/impl-const.rs +++ b/src/test/ui/const-generics/auxiliary/impl-const.rs @@ -1,6 +1,5 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] pub struct Num; diff --git a/src/test/ui/const-generics/broken-mir-1.rs b/src/test/ui/const-generics/broken-mir-1.rs index d13ae12c03b..34255fa9f58 100644 --- a/src/test/ui/const-generics/broken-mir-1.rs +++ b/src/test/ui/const-generics/broken-mir-1.rs @@ -3,7 +3,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] pub trait Foo { fn foo(&self); diff --git a/src/test/ui/const-generics/broken-mir-2.rs b/src/test/ui/const-generics/broken-mir-2.rs index 2f9afe0b464..ac358b01672 100644 --- a/src/test/ui/const-generics/broken-mir-2.rs +++ b/src/test/ui/const-generics/broken-mir-2.rs @@ -3,7 +3,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] use std::fmt::Debug; diff --git a/src/test/ui/const-generics/cannot-infer-type-for-const-param.rs b/src/test/ui/const-generics/cannot-infer-type-for-const-param.rs index 931f6ade7f1..44aef859f2d 100644 --- a/src/test/ui/const-generics/cannot-infer-type-for-const-param.rs +++ b/src/test/ui/const-generics/cannot-infer-type-for-const-param.rs @@ -2,7 +2,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] // This test confirms that the types can be inferred correctly for this example with const // generics. Previously this would ICE, and more recently error. diff --git a/src/test/ui/const-generics/closing-args-token.full.stderr b/src/test/ui/const-generics/closing-args-token.full.stderr index 1c3ddd345a5..7737705440e 100644 --- a/src/test/ui/const-generics/closing-args-token.full.stderr +++ b/src/test/ui/const-generics/closing-args-token.full.stderr @@ -1,5 +1,5 @@ error: expressions must be enclosed in braces to be used as const generic arguments - --> $DIR/closing-args-token.rs:11:9 + --> $DIR/closing-args-token.rs:10:9 | LL | S::<5 + 2 >> 7>; | ^^^^^ @@ -10,7 +10,7 @@ LL | S::<{ 5 + 2 } >> 7>; | ^ ^ error: comparison operators cannot be chained - --> $DIR/closing-args-token.rs:11:16 + --> $DIR/closing-args-token.rs:10:16 | LL | S::<5 + 2 >> 7>; | ^ ^ @@ -21,7 +21,7 @@ LL | S::<5 + 2 >> 7 && 7>; | ^^^^ error: comparison operators cannot be chained - --> $DIR/closing-args-token.rs:17:20 + --> $DIR/closing-args-token.rs:16:20 | LL | S::<{ 5 + 2 } >> 7>; | ^ ^ @@ -32,13 +32,13 @@ LL | S::<{ 5 + 2 } >> 7 && 7>; | ^^^^ error: expected expression, found `;` - --> $DIR/closing-args-token.rs:22:16 + --> $DIR/closing-args-token.rs:21:16 | LL | T::<0 >= 3>; | ^ expected expression error: comparison operators cannot be chained - --> $DIR/closing-args-token.rs:28:12 + --> $DIR/closing-args-token.rs:27:12 | LL | T::>= 2 > 0>; | ^^ ^ diff --git a/src/test/ui/const-generics/closing-args-token.min.stderr b/src/test/ui/const-generics/closing-args-token.min.stderr index 1c3ddd345a5..7737705440e 100644 --- a/src/test/ui/const-generics/closing-args-token.min.stderr +++ b/src/test/ui/const-generics/closing-args-token.min.stderr @@ -1,5 +1,5 @@ error: expressions must be enclosed in braces to be used as const generic arguments - --> $DIR/closing-args-token.rs:11:9 + --> $DIR/closing-args-token.rs:10:9 | LL | S::<5 + 2 >> 7>; | ^^^^^ @@ -10,7 +10,7 @@ LL | S::<{ 5 + 2 } >> 7>; | ^ ^ error: comparison operators cannot be chained - --> $DIR/closing-args-token.rs:11:16 + --> $DIR/closing-args-token.rs:10:16 | LL | S::<5 + 2 >> 7>; | ^ ^ @@ -21,7 +21,7 @@ LL | S::<5 + 2 >> 7 && 7>; | ^^^^ error: comparison operators cannot be chained - --> $DIR/closing-args-token.rs:17:20 + --> $DIR/closing-args-token.rs:16:20 | LL | S::<{ 5 + 2 } >> 7>; | ^ ^ @@ -32,13 +32,13 @@ LL | S::<{ 5 + 2 } >> 7 && 7>; | ^^^^ error: expected expression, found `;` - --> $DIR/closing-args-token.rs:22:16 + --> $DIR/closing-args-token.rs:21:16 | LL | T::<0 >= 3>; | ^ expected expression error: comparison operators cannot be chained - --> $DIR/closing-args-token.rs:28:12 + --> $DIR/closing-args-token.rs:27:12 | LL | T::>= 2 > 0>; | ^^ ^ diff --git a/src/test/ui/const-generics/closing-args-token.rs b/src/test/ui/const-generics/closing-args-token.rs index 8699637c54e..a9b552ebed7 100644 --- a/src/test/ui/const-generics/closing-args-token.rs +++ b/src/test/ui/const-generics/closing-args-token.rs @@ -2,7 +2,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] struct S; struct T; diff --git a/src/test/ui/const-generics/coerce_unsized_array.rs b/src/test/ui/const-generics/coerce_unsized_array.rs index a3c295f73c7..8e20df28103 100644 --- a/src/test/ui/const-generics/coerce_unsized_array.rs +++ b/src/test/ui/const-generics/coerce_unsized_array.rs @@ -3,7 +3,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] fn foo(v: &[u8; N]) -> &[u8] { v diff --git a/src/test/ui/const-generics/concrete-const-as-fn-arg.rs b/src/test/ui/const-generics/concrete-const-as-fn-arg.rs index 7771bf33601..8c31c8651a2 100644 --- a/src/test/ui/const-generics/concrete-const-as-fn-arg.rs +++ b/src/test/ui/const-generics/concrete-const-as-fn-arg.rs @@ -4,7 +4,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] struct A; // ok diff --git a/src/test/ui/const-generics/concrete-const-impl-method.rs b/src/test/ui/const-generics/concrete-const-impl-method.rs index edb403ce8fd..3d3bd2664c8 100644 --- a/src/test/ui/const-generics/concrete-const-impl-method.rs +++ b/src/test/ui/const-generics/concrete-const-impl-method.rs @@ -5,7 +5,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] pub struct A; diff --git a/src/test/ui/const-generics/condition-in-trait-const-arg.rs b/src/test/ui/const-generics/condition-in-trait-const-arg.rs index 77b68052fc0..ad40b48afe5 100644 --- a/src/test/ui/const-generics/condition-in-trait-const-arg.rs +++ b/src/test/ui/const-generics/condition-in-trait-const-arg.rs @@ -4,7 +4,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] trait IsZeroTrait{} diff --git a/src/test/ui/const-generics/const-arg-in-const-arg.min.stderr b/src/test/ui/const-generics/const-arg-in-const-arg.min.stderr index 042fa9ad958..bfa4ba30686 100644 --- a/src/test/ui/const-generics/const-arg-in-const-arg.min.stderr +++ b/src/test/ui/const-generics/const-arg-in-const-arg.min.stderr @@ -1,5 +1,5 @@ error: generic parameters may not be used in const operations - --> $DIR/const-arg-in-const-arg.rs:14:23 + --> $DIR/const-arg-in-const-arg.rs:13:23 | LL | let _: [u8; foo::()]; | ^ cannot perform const operation using `T` @@ -8,7 +8,7 @@ LL | let _: [u8; foo::()]; = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: generic parameters may not be used in const operations - --> $DIR/const-arg-in-const-arg.rs:15:23 + --> $DIR/const-arg-in-const-arg.rs:14:23 | LL | let _: [u8; bar::()]; | ^ cannot perform const operation using `N` @@ -17,7 +17,7 @@ LL | let _: [u8; bar::()]; = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: generic parameters may not be used in const operations - --> $DIR/const-arg-in-const-arg.rs:25:23 + --> $DIR/const-arg-in-const-arg.rs:24:23 | LL | let _ = [0; bar::()]; | ^ cannot perform const operation using `N` @@ -26,7 +26,7 @@ LL | let _ = [0; bar::()]; = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: generic parameters may not be used in const operations - --> $DIR/const-arg-in-const-arg.rs:30:24 + --> $DIR/const-arg-in-const-arg.rs:29:24 | LL | let _: Foo<{ foo::() }>; | ^ cannot perform const operation using `T` @@ -35,7 +35,7 @@ LL | let _: Foo<{ foo::() }>; = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: generic parameters may not be used in const operations - --> $DIR/const-arg-in-const-arg.rs:31:24 + --> $DIR/const-arg-in-const-arg.rs:30:24 | LL | let _: Foo<{ bar::() }>; | ^ cannot perform const operation using `N` @@ -44,7 +44,7 @@ LL | let _: Foo<{ bar::() }>; = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: generic parameters may not be used in const operations - --> $DIR/const-arg-in-const-arg.rs:36:27 + --> $DIR/const-arg-in-const-arg.rs:35:27 | LL | let _ = Foo::<{ foo::() }>; | ^ cannot perform const operation using `T` @@ -53,7 +53,7 @@ LL | let _ = Foo::<{ foo::() }>; = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: generic parameters may not be used in const operations - --> $DIR/const-arg-in-const-arg.rs:37:27 + --> $DIR/const-arg-in-const-arg.rs:36:27 | LL | let _ = Foo::<{ bar::() }>; | ^ cannot perform const operation using `N` @@ -62,7 +62,7 @@ LL | let _ = Foo::<{ bar::() }>; = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error[E0658]: a non-static lifetime is not allowed in a `const` - --> $DIR/const-arg-in-const-arg.rs:16:23 + --> $DIR/const-arg-in-const-arg.rs:15:23 | LL | let _: [u8; faz::<'a>(&())]; | ^^ @@ -71,7 +71,7 @@ LL | let _: [u8; faz::<'a>(&())]; = help: add `#![feature(const_generics)]` to the crate attributes to enable error[E0658]: a non-static lifetime is not allowed in a `const` - --> $DIR/const-arg-in-const-arg.rs:17:23 + --> $DIR/const-arg-in-const-arg.rs:16:23 | LL | let _: [u8; baz::<'a>(&())]; | ^^ @@ -80,7 +80,7 @@ LL | let _: [u8; baz::<'a>(&())]; = help: add `#![feature(const_generics)]` to the crate attributes to enable error[E0658]: a non-static lifetime is not allowed in a `const` - --> $DIR/const-arg-in-const-arg.rs:18:23 + --> $DIR/const-arg-in-const-arg.rs:17:23 | LL | let _: [u8; faz::<'b>(&())]; | ^^ @@ -89,7 +89,7 @@ LL | let _: [u8; faz::<'b>(&())]; = help: add `#![feature(const_generics)]` to the crate attributes to enable error[E0658]: a non-static lifetime is not allowed in a `const` - --> $DIR/const-arg-in-const-arg.rs:19:23 + --> $DIR/const-arg-in-const-arg.rs:18:23 | LL | let _: [u8; baz::<'b>(&())]; | ^^ @@ -98,7 +98,7 @@ LL | let _: [u8; baz::<'b>(&())]; = help: add `#![feature(const_generics)]` to the crate attributes to enable error[E0658]: a non-static lifetime is not allowed in a `const` - --> $DIR/const-arg-in-const-arg.rs:26:23 + --> $DIR/const-arg-in-const-arg.rs:25:23 | LL | let _ = [0; faz::<'a>(&())]; | ^^ @@ -107,7 +107,7 @@ LL | let _ = [0; faz::<'a>(&())]; = help: add `#![feature(const_generics)]` to the crate attributes to enable error[E0658]: a non-static lifetime is not allowed in a `const` - --> $DIR/const-arg-in-const-arg.rs:27:23 + --> $DIR/const-arg-in-const-arg.rs:26:23 | LL | let _ = [0; baz::<'a>(&())]; | ^^ @@ -116,7 +116,7 @@ LL | let _ = [0; baz::<'a>(&())]; = help: add `#![feature(const_generics)]` to the crate attributes to enable error[E0658]: a non-static lifetime is not allowed in a `const` - --> $DIR/const-arg-in-const-arg.rs:28:23 + --> $DIR/const-arg-in-const-arg.rs:27:23 | LL | let _ = [0; faz::<'b>(&())]; | ^^ @@ -125,7 +125,7 @@ LL | let _ = [0; faz::<'b>(&())]; = help: add `#![feature(const_generics)]` to the crate attributes to enable error[E0658]: a non-static lifetime is not allowed in a `const` - --> $DIR/const-arg-in-const-arg.rs:29:23 + --> $DIR/const-arg-in-const-arg.rs:28:23 | LL | let _ = [0; baz::<'b>(&())]; | ^^ @@ -134,7 +134,7 @@ LL | let _ = [0; baz::<'b>(&())]; = help: add `#![feature(const_generics)]` to the crate attributes to enable error[E0658]: a non-static lifetime is not allowed in a `const` - --> $DIR/const-arg-in-const-arg.rs:32:24 + --> $DIR/const-arg-in-const-arg.rs:31:24 | LL | let _: Foo<{ faz::<'a>(&()) }>; | ^^ @@ -143,7 +143,7 @@ LL | let _: Foo<{ faz::<'a>(&()) }>; = help: add `#![feature(const_generics)]` to the crate attributes to enable error[E0658]: a non-static lifetime is not allowed in a `const` - --> $DIR/const-arg-in-const-arg.rs:33:24 + --> $DIR/const-arg-in-const-arg.rs:32:24 | LL | let _: Foo<{ baz::<'a>(&()) }>; | ^^ @@ -152,7 +152,7 @@ LL | let _: Foo<{ baz::<'a>(&()) }>; = help: add `#![feature(const_generics)]` to the crate attributes to enable error[E0658]: a non-static lifetime is not allowed in a `const` - --> $DIR/const-arg-in-const-arg.rs:34:24 + --> $DIR/const-arg-in-const-arg.rs:33:24 | LL | let _: Foo<{ faz::<'b>(&()) }>; | ^^ @@ -161,7 +161,7 @@ LL | let _: Foo<{ faz::<'b>(&()) }>; = help: add `#![feature(const_generics)]` to the crate attributes to enable error[E0658]: a non-static lifetime is not allowed in a `const` - --> $DIR/const-arg-in-const-arg.rs:35:24 + --> $DIR/const-arg-in-const-arg.rs:34:24 | LL | let _: Foo<{ baz::<'b>(&()) }>; | ^^ @@ -170,7 +170,7 @@ LL | let _: Foo<{ baz::<'b>(&()) }>; = help: add `#![feature(const_generics)]` to the crate attributes to enable error[E0658]: a non-static lifetime is not allowed in a `const` - --> $DIR/const-arg-in-const-arg.rs:38:27 + --> $DIR/const-arg-in-const-arg.rs:37:27 | LL | let _ = Foo::<{ faz::<'a>(&()) }>; | ^^ @@ -179,7 +179,7 @@ LL | let _ = Foo::<{ faz::<'a>(&()) }>; = help: add `#![feature(const_generics)]` to the crate attributes to enable error[E0658]: a non-static lifetime is not allowed in a `const` - --> $DIR/const-arg-in-const-arg.rs:39:27 + --> $DIR/const-arg-in-const-arg.rs:38:27 | LL | let _ = Foo::<{ baz::<'a>(&()) }>; | ^^ @@ -188,7 +188,7 @@ LL | let _ = Foo::<{ baz::<'a>(&()) }>; = help: add `#![feature(const_generics)]` to the crate attributes to enable error[E0658]: a non-static lifetime is not allowed in a `const` - --> $DIR/const-arg-in-const-arg.rs:40:27 + --> $DIR/const-arg-in-const-arg.rs:39:27 | LL | let _ = Foo::<{ faz::<'b>(&()) }>; | ^^ @@ -197,7 +197,7 @@ LL | let _ = Foo::<{ faz::<'b>(&()) }>; = help: add `#![feature(const_generics)]` to the crate attributes to enable error[E0658]: a non-static lifetime is not allowed in a `const` - --> $DIR/const-arg-in-const-arg.rs:41:27 + --> $DIR/const-arg-in-const-arg.rs:40:27 | LL | let _ = Foo::<{ baz::<'b>(&()) }>; | ^^ diff --git a/src/test/ui/const-generics/const-arg-in-const-arg.rs b/src/test/ui/const-generics/const-arg-in-const-arg.rs index 9927538ef50..8279f4a3f61 100644 --- a/src/test/ui/const-generics/const-arg-in-const-arg.rs +++ b/src/test/ui/const-generics/const-arg-in-const-arg.rs @@ -2,7 +2,6 @@ // FIXME(const_generics): This test currently causes an ICE because // we don't yet correctly deal with lifetimes, reenable this test once // this is fixed. -#![cfg_attr(min, feature(min_const_generics))] const fn foo() -> usize { std::mem::size_of::() } const fn bar() -> usize { N } diff --git a/src/test/ui/const-generics/const-arg-in-fn.rs b/src/test/ui/const-generics/const-arg-in-fn.rs index 5c438efd82a..43ed12efb89 100644 --- a/src/test/ui/const-generics/const-arg-in-fn.rs +++ b/src/test/ui/const-generics/const-arg-in-fn.rs @@ -3,7 +3,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] fn const_u32_identity() -> u32 { X diff --git a/src/test/ui/const-generics/const-arg-type-arg-misordered.full.stderr b/src/test/ui/const-generics/const-arg-type-arg-misordered.full.stderr index 3827002ff4b..d0ea51ea417 100644 --- a/src/test/ui/const-generics/const-arg-type-arg-misordered.full.stderr +++ b/src/test/ui/const-generics/const-arg-type-arg-misordered.full.stderr @@ -1,5 +1,5 @@ error[E0747]: constant provided when a type was expected - --> $DIR/const-arg-type-arg-misordered.rs:8:35 + --> $DIR/const-arg-type-arg-misordered.rs:7:35 | LL | fn foo() -> Array { | ^ diff --git a/src/test/ui/const-generics/const-arg-type-arg-misordered.min.stderr b/src/test/ui/const-generics/const-arg-type-arg-misordered.min.stderr index 2c5fc8dcc01..d7b7df0eb55 100644 --- a/src/test/ui/const-generics/const-arg-type-arg-misordered.min.stderr +++ b/src/test/ui/const-generics/const-arg-type-arg-misordered.min.stderr @@ -1,5 +1,5 @@ error[E0747]: constant provided when a type was expected - --> $DIR/const-arg-type-arg-misordered.rs:8:35 + --> $DIR/const-arg-type-arg-misordered.rs:7:35 | LL | fn foo() -> Array { | ^ diff --git a/src/test/ui/const-generics/const-arg-type-arg-misordered.rs b/src/test/ui/const-generics/const-arg-type-arg-misordered.rs index 6680f772fa3..5415791d21b 100644 --- a/src/test/ui/const-generics/const-arg-type-arg-misordered.rs +++ b/src/test/ui/const-generics/const-arg-type-arg-misordered.rs @@ -1,7 +1,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] type Array = [T; N]; diff --git a/src/test/ui/const-generics/const-argument-if-length.full.stderr b/src/test/ui/const-generics/const-argument-if-length.full.stderr index 4d627f05adc..5dca01f0dc0 100644 --- a/src/test/ui/const-generics/const-argument-if-length.full.stderr +++ b/src/test/ui/const-generics/const-argument-if-length.full.stderr @@ -1,5 +1,5 @@ error[E0277]: the size for values of type `T` cannot be known at compilation time - --> $DIR/const-argument-if-length.rs:8:28 + --> $DIR/const-argument-if-length.rs:7:28 | LL | pub const fn is_zst() -> usize { | - this type parameter needs to be `Sized` @@ -12,7 +12,7 @@ LL | pub const fn size_of() -> usize { | - required by this bound in `std::mem::size_of` error[E0277]: the size for values of type `T` cannot be known at compilation time - --> $DIR/const-argument-if-length.rs:17:12 + --> $DIR/const-argument-if-length.rs:16:12 | LL | pub struct AtLeastByte { | - this type parameter needs to be `Sized` diff --git a/src/test/ui/const-generics/const-argument-if-length.min.stderr b/src/test/ui/const-generics/const-argument-if-length.min.stderr index 8a1074392a5..ea177c19746 100644 --- a/src/test/ui/const-generics/const-argument-if-length.min.stderr +++ b/src/test/ui/const-generics/const-argument-if-length.min.stderr @@ -1,5 +1,5 @@ error: generic parameters may not be used in const operations - --> $DIR/const-argument-if-length.rs:19:24 + --> $DIR/const-argument-if-length.rs:18:24 | LL | pad: [u8; is_zst::()], | ^ cannot perform const operation using `T` @@ -8,7 +8,7 @@ LL | pad: [u8; is_zst::()], = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error[E0277]: the size for values of type `T` cannot be known at compilation time - --> $DIR/const-argument-if-length.rs:17:12 + --> $DIR/const-argument-if-length.rs:16:12 | LL | pub struct AtLeastByte { | - this type parameter needs to be `Sized` diff --git a/src/test/ui/const-generics/const-argument-if-length.rs b/src/test/ui/const-generics/const-argument-if-length.rs index 80907383124..67ed85f96af 100644 --- a/src/test/ui/const-generics/const-argument-if-length.rs +++ b/src/test/ui/const-generics/const-argument-if-length.rs @@ -2,7 +2,6 @@ #![cfg_attr(full, allow(incomplete_features))] #![cfg_attr(full, feature(const_generics))] -#![cfg_attr(min, feature(min_const_generics))] pub const fn is_zst() -> usize { if std::mem::size_of::() == 0 { diff --git a/src/test/ui/const-generics/const-expression-parameter.full.stderr b/src/test/ui/const-generics/const-expression-parameter.full.stderr index 0615a4c206d..93c5173554f 100644 --- a/src/test/ui/const-generics/const-expression-parameter.full.stderr +++ b/src/test/ui/const-generics/const-expression-parameter.full.stderr @@ -1,5 +1,5 @@ error: expressions must be enclosed in braces to be used as const generic arguments - --> $DIR/const-expression-parameter.rs:16:20 + --> $DIR/const-expression-parameter.rs:15:20 | LL | i32_identity::<1 + 2>(); | ^^^^^ diff --git a/src/test/ui/const-generics/const-expression-parameter.min.stderr b/src/test/ui/const-generics/const-expression-parameter.min.stderr index 0615a4c206d..93c5173554f 100644 --- a/src/test/ui/const-generics/const-expression-parameter.min.stderr +++ b/src/test/ui/const-generics/const-expression-parameter.min.stderr @@ -1,5 +1,5 @@ error: expressions must be enclosed in braces to be used as const generic arguments - --> $DIR/const-expression-parameter.rs:16:20 + --> $DIR/const-expression-parameter.rs:15:20 | LL | i32_identity::<1 + 2>(); | ^^^^^ diff --git a/src/test/ui/const-generics/const-expression-parameter.rs b/src/test/ui/const-generics/const-expression-parameter.rs index 3ef7c8b32e0..cb609a56416 100644 --- a/src/test/ui/const-generics/const-expression-parameter.rs +++ b/src/test/ui/const-generics/const-expression-parameter.rs @@ -2,7 +2,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] fn i32_identity() -> i32 { 5 diff --git a/src/test/ui/const-generics/const-fn-with-const-param.rs b/src/test/ui/const-generics/const-fn-with-const-param.rs index add1290b1d9..5c1ee4e0d5a 100644 --- a/src/test/ui/const-generics/const-fn-with-const-param.rs +++ b/src/test/ui/const-generics/const-fn-with-const-param.rs @@ -4,7 +4,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] const fn const_u32_identity() -> u32 { X diff --git a/src/test/ui/const-generics/const-generic-array-wrapper.rs b/src/test/ui/const-generics/const-generic-array-wrapper.rs index 34edd0b4a8e..224fc794e32 100644 --- a/src/test/ui/const-generics/const-generic-array-wrapper.rs +++ b/src/test/ui/const-generics/const-generic-array-wrapper.rs @@ -3,7 +3,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] struct Foo([T; N]); diff --git a/src/test/ui/const-generics/const-generic-type_name.rs b/src/test/ui/const-generics/const-generic-type_name.rs index a954c026352..95632f79896 100644 --- a/src/test/ui/const-generics/const-generic-type_name.rs +++ b/src/test/ui/const-generics/const-generic-type_name.rs @@ -3,7 +3,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] #[derive(Debug)] struct S; diff --git a/src/test/ui/const-generics/const-param-after-const-literal-arg.rs b/src/test/ui/const-generics/const-param-after-const-literal-arg.rs index 3982f7a7f12..6c2b14f2770 100644 --- a/src/test/ui/const-generics/const-param-after-const-literal-arg.rs +++ b/src/test/ui/const-generics/const-param-after-const-literal-arg.rs @@ -3,7 +3,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] struct Foo; diff --git a/src/test/ui/const-generics/const-param-before-other-params.full.stderr b/src/test/ui/const-generics/const-param-before-other-params.full.stderr index c2acaabbd88..09a4f66de39 100644 --- a/src/test/ui/const-generics/const-param-before-other-params.full.stderr +++ b/src/test/ui/const-generics/const-param-before-other-params.full.stderr @@ -1,5 +1,5 @@ error: lifetime parameters must be declared prior to const parameters - --> $DIR/const-param-before-other-params.rs:6:21 + --> $DIR/const-param-before-other-params.rs:5:21 | LL | fn bar(_: &'a ()) { | --------------^^- help: reorder the parameters: lifetimes, then consts and types: `<'a, const X: ()>` diff --git a/src/test/ui/const-generics/const-param-before-other-params.min.stderr b/src/test/ui/const-generics/const-param-before-other-params.min.stderr index 354c6d0615f..1e49588f1b4 100644 --- a/src/test/ui/const-generics/const-param-before-other-params.min.stderr +++ b/src/test/ui/const-generics/const-param-before-other-params.min.stderr @@ -1,17 +1,17 @@ error: lifetime parameters must be declared prior to const parameters - --> $DIR/const-param-before-other-params.rs:6:21 + --> $DIR/const-param-before-other-params.rs:5:21 | LL | fn bar(_: &'a ()) { | --------------^^- help: reorder the parameters: lifetimes, then types, then consts: `<'a, const X: ()>` error: type parameters must be declared prior to const parameters - --> $DIR/const-param-before-other-params.rs:11:21 + --> $DIR/const-param-before-other-params.rs:10:21 | LL | fn foo(_: &T) {} | --------------^- help: reorder the parameters: lifetimes, then types, then consts: `` error: `()` is forbidden as the type of a const generic parameter - --> $DIR/const-param-before-other-params.rs:6:17 + --> $DIR/const-param-before-other-params.rs:5:17 | LL | fn bar(_: &'a ()) { | ^^ @@ -20,7 +20,7 @@ LL | fn bar(_: &'a ()) { = help: more complex types are supported with `#[feature(const_generics)]` error: `()` is forbidden as the type of a const generic parameter - --> $DIR/const-param-before-other-params.rs:11:17 + --> $DIR/const-param-before-other-params.rs:10:17 | LL | fn foo(_: &T) {} | ^^ diff --git a/src/test/ui/const-generics/const-param-before-other-params.rs b/src/test/ui/const-generics/const-param-before-other-params.rs index f1be90cf2e4..508bb3e6a68 100644 --- a/src/test/ui/const-generics/const-param-before-other-params.rs +++ b/src/test/ui/const-generics/const-param-before-other-params.rs @@ -1,7 +1,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] fn bar(_: &'a ()) { //~^ ERROR lifetime parameters must be declared prior to const parameters diff --git a/src/test/ui/const-generics/const-param-elided-lifetime.full.stderr b/src/test/ui/const-generics/const-param-elided-lifetime.full.stderr index aa29d61d917..119f932745b 100644 --- a/src/test/ui/const-generics/const-param-elided-lifetime.full.stderr +++ b/src/test/ui/const-generics/const-param-elided-lifetime.full.stderr @@ -1,29 +1,29 @@ error[E0637]: `&` without an explicit lifetime name cannot be used here - --> $DIR/const-param-elided-lifetime.rs:11:19 + --> $DIR/const-param-elided-lifetime.rs:10:19 | LL | struct A; | ^ explicit lifetime name needed here error[E0637]: `&` without an explicit lifetime name cannot be used here - --> $DIR/const-param-elided-lifetime.rs:16:15 + --> $DIR/const-param-elided-lifetime.rs:15:15 | LL | impl A { | ^ explicit lifetime name needed here error[E0637]: `&` without an explicit lifetime name cannot be used here - --> $DIR/const-param-elided-lifetime.rs:19:21 + --> $DIR/const-param-elided-lifetime.rs:18:21 | LL | fn foo(&self) {} | ^ explicit lifetime name needed here error[E0637]: `&` without an explicit lifetime name cannot be used here - --> $DIR/const-param-elided-lifetime.rs:24:15 + --> $DIR/const-param-elided-lifetime.rs:23:15 | LL | impl B for A {} | ^ explicit lifetime name needed here error[E0637]: `&` without an explicit lifetime name cannot be used here - --> $DIR/const-param-elided-lifetime.rs:28:17 + --> $DIR/const-param-elided-lifetime.rs:27:17 | LL | fn bar() {} | ^ explicit lifetime name needed here diff --git a/src/test/ui/const-generics/const-param-elided-lifetime.min.stderr b/src/test/ui/const-generics/const-param-elided-lifetime.min.stderr index ed30182690a..5d3c8f7b2e6 100644 --- a/src/test/ui/const-generics/const-param-elided-lifetime.min.stderr +++ b/src/test/ui/const-generics/const-param-elided-lifetime.min.stderr @@ -1,35 +1,35 @@ error[E0637]: `&` without an explicit lifetime name cannot be used here - --> $DIR/const-param-elided-lifetime.rs:11:19 + --> $DIR/const-param-elided-lifetime.rs:10:19 | LL | struct A; | ^ explicit lifetime name needed here error[E0637]: `&` without an explicit lifetime name cannot be used here - --> $DIR/const-param-elided-lifetime.rs:16:15 + --> $DIR/const-param-elided-lifetime.rs:15:15 | LL | impl A { | ^ explicit lifetime name needed here error[E0637]: `&` without an explicit lifetime name cannot be used here - --> $DIR/const-param-elided-lifetime.rs:19:21 + --> $DIR/const-param-elided-lifetime.rs:18:21 | LL | fn foo(&self) {} | ^ explicit lifetime name needed here error[E0637]: `&` without an explicit lifetime name cannot be used here - --> $DIR/const-param-elided-lifetime.rs:24:15 + --> $DIR/const-param-elided-lifetime.rs:23:15 | LL | impl B for A {} | ^ explicit lifetime name needed here error[E0637]: `&` without an explicit lifetime name cannot be used here - --> $DIR/const-param-elided-lifetime.rs:28:17 + --> $DIR/const-param-elided-lifetime.rs:27:17 | LL | fn bar() {} | ^ explicit lifetime name needed here error: `&'static u8` is forbidden as the type of a const generic parameter - --> $DIR/const-param-elided-lifetime.rs:11:19 + --> $DIR/const-param-elided-lifetime.rs:10:19 | LL | struct A; | ^^^ @@ -38,7 +38,7 @@ LL | struct A; = help: more complex types are supported with `#[feature(const_generics)]` error: `&'static u8` is forbidden as the type of a const generic parameter - --> $DIR/const-param-elided-lifetime.rs:16:15 + --> $DIR/const-param-elided-lifetime.rs:15:15 | LL | impl A { | ^^^ @@ -47,7 +47,7 @@ LL | impl A { = help: more complex types are supported with `#[feature(const_generics)]` error: `&'static u8` is forbidden as the type of a const generic parameter - --> $DIR/const-param-elided-lifetime.rs:24:15 + --> $DIR/const-param-elided-lifetime.rs:23:15 | LL | impl B for A {} | ^^^ @@ -56,7 +56,7 @@ LL | impl B for A {} = help: more complex types are supported with `#[feature(const_generics)]` error: `&'static u8` is forbidden as the type of a const generic parameter - --> $DIR/const-param-elided-lifetime.rs:28:17 + --> $DIR/const-param-elided-lifetime.rs:27:17 | LL | fn bar() {} | ^^^ @@ -65,7 +65,7 @@ LL | fn bar() {} = help: more complex types are supported with `#[feature(const_generics)]` error: `&'static u8` is forbidden as the type of a const generic parameter - --> $DIR/const-param-elided-lifetime.rs:19:21 + --> $DIR/const-param-elided-lifetime.rs:18:21 | LL | fn foo(&self) {} | ^^^ diff --git a/src/test/ui/const-generics/const-param-elided-lifetime.rs b/src/test/ui/const-generics/const-param-elided-lifetime.rs index 633e876f1d7..89715a7b8e9 100644 --- a/src/test/ui/const-generics/const-param-elided-lifetime.rs +++ b/src/test/ui/const-generics/const-param-elided-lifetime.rs @@ -6,7 +6,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] struct A; //~^ ERROR `&` without an explicit lifetime name cannot be used here diff --git a/src/test/ui/const-generics/const-param-from-outer-fn.full.stderr b/src/test/ui/const-generics/const-param-from-outer-fn.full.stderr index 5a126f5c3c6..c2ec7359c9f 100644 --- a/src/test/ui/const-generics/const-param-from-outer-fn.full.stderr +++ b/src/test/ui/const-generics/const-param-from-outer-fn.full.stderr @@ -1,5 +1,5 @@ error[E0401]: can't use generic parameters from outer function - --> $DIR/const-param-from-outer-fn.rs:9:9 + --> $DIR/const-param-from-outer-fn.rs:8:9 | LL | fn foo() { | - const parameter from outer function diff --git a/src/test/ui/const-generics/const-param-from-outer-fn.min.stderr b/src/test/ui/const-generics/const-param-from-outer-fn.min.stderr index 5a126f5c3c6..c2ec7359c9f 100644 --- a/src/test/ui/const-generics/const-param-from-outer-fn.min.stderr +++ b/src/test/ui/const-generics/const-param-from-outer-fn.min.stderr @@ -1,5 +1,5 @@ error[E0401]: can't use generic parameters from outer function - --> $DIR/const-param-from-outer-fn.rs:9:9 + --> $DIR/const-param-from-outer-fn.rs:8:9 | LL | fn foo() { | - const parameter from outer function diff --git a/src/test/ui/const-generics/const-param-from-outer-fn.rs b/src/test/ui/const-generics/const-param-from-outer-fn.rs index e1376c6e108..27b9ca9c291 100644 --- a/src/test/ui/const-generics/const-param-from-outer-fn.rs +++ b/src/test/ui/const-generics/const-param-from-outer-fn.rs @@ -2,7 +2,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] fn foo() { fn bar() -> u32 { diff --git a/src/test/ui/const-generics/const-param-hygiene.rs b/src/test/ui/const-generics/const-param-hygiene.rs index c8cefc36732..9cafb05fbcb 100644 --- a/src/test/ui/const-generics/const-param-hygiene.rs +++ b/src/test/ui/const-generics/const-param-hygiene.rs @@ -3,7 +3,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] macro_rules! bar { ($($t:tt)*) => { impl $($t)* }; diff --git a/src/test/ui/const-generics/const-param-in-async.rs b/src/test/ui/const-generics/const-param-in-async.rs index e8601985287..9dc9c80241d 100644 --- a/src/test/ui/const-generics/const-param-in-async.rs +++ b/src/test/ui/const-generics/const-param-in-async.rs @@ -3,7 +3,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] async fn foo(arg: [u8; N]) -> usize { arg.len() } diff --git a/src/test/ui/const-generics/const-param-in-trait-ungated.rs b/src/test/ui/const-generics/const-param-in-trait-ungated.rs deleted file mode 100644 index 8a81bcc1a80..00000000000 --- a/src/test/ui/const-generics/const-param-in-trait-ungated.rs +++ /dev/null @@ -1,3 +0,0 @@ -trait Trait {} //~ ERROR const generics are unstable - -fn main() {} diff --git a/src/test/ui/const-generics/const-param-in-trait-ungated.stderr b/src/test/ui/const-generics/const-param-in-trait-ungated.stderr deleted file mode 100644 index d53a4ac2d4c..00000000000 --- a/src/test/ui/const-generics/const-param-in-trait-ungated.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0658]: const generics are unstable - --> $DIR/const-param-in-trait-ungated.rs:1:19 - | -LL | trait Trait {} - | ^ - | - = note: see issue #74878 for more information - = help: add `#![feature(min_const_generics)]` to the crate attributes to enable - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/const-generics/const-param-in-trait.rs b/src/test/ui/const-generics/const-param-in-trait.rs index 9d31162c1c6..79b3ae2037e 100644 --- a/src/test/ui/const-generics/const-param-in-trait.rs +++ b/src/test/ui/const-generics/const-param-in-trait.rs @@ -4,7 +4,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] trait Trait {} diff --git a/src/test/ui/const-generics/const-param-shadowing.rs b/src/test/ui/const-generics/const-param-shadowing.rs index 8440e47968e..ddd15dbc41b 100644 --- a/src/test/ui/const-generics/const-param-shadowing.rs +++ b/src/test/ui/const-generics/const-param-shadowing.rs @@ -1,5 +1,3 @@ -#![feature(min_const_generics)] - type N = u32; struct Foo; fn test() -> Foo { //~ ERROR type provided when diff --git a/src/test/ui/const-generics/const-param-shadowing.stderr b/src/test/ui/const-generics/const-param-shadowing.stderr index df170278026..7447ca3ff36 100644 --- a/src/test/ui/const-generics/const-param-shadowing.stderr +++ b/src/test/ui/const-generics/const-param-shadowing.stderr @@ -1,5 +1,5 @@ error[E0747]: type provided when a constant was expected - --> $DIR/const-param-shadowing.rs:5:34 + --> $DIR/const-param-shadowing.rs:3:34 | LL | fn test() -> Foo { | ^ diff --git a/src/test/ui/const-generics/const-param-type-depends-on-const-param.full.stderr b/src/test/ui/const-generics/const-param-type-depends-on-const-param.full.stderr index f7ad579dbca..f639e276f46 100644 --- a/src/test/ui/const-generics/const-param-type-depends-on-const-param.full.stderr +++ b/src/test/ui/const-generics/const-param-type-depends-on-const-param.full.stderr @@ -1,11 +1,11 @@ error[E0770]: the type of const parameters must not depend on other generic parameters - --> $DIR/const-param-type-depends-on-const-param.rs:12:52 + --> $DIR/const-param-type-depends-on-const-param.rs:11:52 | LL | pub struct Dependent([(); N]); | ^ the type must not depend on the parameter `N` error[E0770]: the type of const parameters must not depend on other generic parameters - --> $DIR/const-param-type-depends-on-const-param.rs:16:40 + --> $DIR/const-param-type-depends-on-const-param.rs:15:40 | LL | pub struct SelfDependent; | ^ the type must not depend on the parameter `N` diff --git a/src/test/ui/const-generics/const-param-type-depends-on-const-param.min.stderr b/src/test/ui/const-generics/const-param-type-depends-on-const-param.min.stderr index 6b7a218ada5..d63bc236320 100644 --- a/src/test/ui/const-generics/const-param-type-depends-on-const-param.min.stderr +++ b/src/test/ui/const-generics/const-param-type-depends-on-const-param.min.stderr @@ -1,17 +1,17 @@ error[E0770]: the type of const parameters must not depend on other generic parameters - --> $DIR/const-param-type-depends-on-const-param.rs:12:52 + --> $DIR/const-param-type-depends-on-const-param.rs:11:52 | LL | pub struct Dependent([(); N]); | ^ the type must not depend on the parameter `N` error[E0770]: the type of const parameters must not depend on other generic parameters - --> $DIR/const-param-type-depends-on-const-param.rs:16:40 + --> $DIR/const-param-type-depends-on-const-param.rs:15:40 | LL | pub struct SelfDependent; | ^ the type must not depend on the parameter `N` error: `[u8; _]` is forbidden as the type of a const generic parameter - --> $DIR/const-param-type-depends-on-const-param.rs:12:47 + --> $DIR/const-param-type-depends-on-const-param.rs:11:47 | LL | pub struct Dependent([(); N]); | ^^^^^^^ @@ -20,7 +20,7 @@ LL | pub struct Dependent([(); N]); = help: more complex types are supported with `#[feature(const_generics)]` error: `[u8; _]` is forbidden as the type of a const generic parameter - --> $DIR/const-param-type-depends-on-const-param.rs:16:35 + --> $DIR/const-param-type-depends-on-const-param.rs:15:35 | LL | pub struct SelfDependent; | ^^^^^^^ diff --git a/src/test/ui/const-generics/const-param-type-depends-on-const-param.rs b/src/test/ui/const-generics/const-param-type-depends-on-const-param.rs index 29371eeb21d..62b146e016a 100644 --- a/src/test/ui/const-generics/const-param-type-depends-on-const-param.rs +++ b/src/test/ui/const-generics/const-param-type-depends-on-const-param.rs @@ -2,7 +2,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] // Currently, const parameters cannot depend on other generic parameters, // as our current implementation can't really support this. diff --git a/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.rs b/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.rs index ea75a3d0403..781f50e6173 100644 --- a/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.rs +++ b/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.rs @@ -3,7 +3,7 @@ use std::marker::PhantomData; -struct B(PhantomData<[T; N]>); //~ ERROR const generics are unstable +struct B(PhantomData<[T; N]>); //~^ ERROR the type of const parameters must not depend on other generic parameters fn main() {} diff --git a/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr b/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr index 5d379ff083c..8e14defd65d 100644 --- a/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr +++ b/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr @@ -4,16 +4,6 @@ error[E0770]: the type of const parameters must not depend on other generic para LL | struct B(PhantomData<[T; N]>); | ^ the type must not depend on the parameter `T` -error[E0658]: const generics are unstable - --> $DIR/const-param-type-depends-on-type-param-ungated.rs:6:19 - | -LL | struct B(PhantomData<[T; N]>); - | ^ - | - = note: see issue #74878 for more information - = help: add `#![feature(min_const_generics)]` to the crate attributes to enable - -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0658, E0770. -For more information about an error, try `rustc --explain E0658`. +For more information about this error, try `rustc --explain E0770`. diff --git a/src/test/ui/const-generics/const-param-type-depends-on-type-param.full.stderr b/src/test/ui/const-generics/const-param-type-depends-on-type-param.full.stderr index f860788e778..a83ee627187 100644 --- a/src/test/ui/const-generics/const-param-type-depends-on-type-param.full.stderr +++ b/src/test/ui/const-generics/const-param-type-depends-on-type-param.full.stderr @@ -1,11 +1,11 @@ error[E0770]: the type of const parameters must not depend on other generic parameters - --> $DIR/const-param-type-depends-on-type-param.rs:12:34 + --> $DIR/const-param-type-depends-on-type-param.rs:11:34 | LL | pub struct Dependent([(); X]); | ^ the type must not depend on the parameter `T` error[E0392]: parameter `T` is never used - --> $DIR/const-param-type-depends-on-type-param.rs:12:22 + --> $DIR/const-param-type-depends-on-type-param.rs:11:22 | LL | pub struct Dependent([(); X]); | ^ unused parameter diff --git a/src/test/ui/const-generics/const-param-type-depends-on-type-param.min.stderr b/src/test/ui/const-generics/const-param-type-depends-on-type-param.min.stderr index f860788e778..a83ee627187 100644 --- a/src/test/ui/const-generics/const-param-type-depends-on-type-param.min.stderr +++ b/src/test/ui/const-generics/const-param-type-depends-on-type-param.min.stderr @@ -1,11 +1,11 @@ error[E0770]: the type of const parameters must not depend on other generic parameters - --> $DIR/const-param-type-depends-on-type-param.rs:12:34 + --> $DIR/const-param-type-depends-on-type-param.rs:11:34 | LL | pub struct Dependent([(); X]); | ^ the type must not depend on the parameter `T` error[E0392]: parameter `T` is never used - --> $DIR/const-param-type-depends-on-type-param.rs:12:22 + --> $DIR/const-param-type-depends-on-type-param.rs:11:22 | LL | pub struct Dependent([(); X]); | ^ unused parameter diff --git a/src/test/ui/const-generics/const-param-type-depends-on-type-param.rs b/src/test/ui/const-generics/const-param-type-depends-on-type-param.rs index 93ae1117512..910a9643502 100644 --- a/src/test/ui/const-generics/const-param-type-depends-on-type-param.rs +++ b/src/test/ui/const-generics/const-param-type-depends-on-type-param.rs @@ -2,7 +2,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] // Currently, const parameters cannot depend on other generic parameters, // as our current implementation can't really support this. diff --git a/src/test/ui/const-generics/const-parameter-uppercase-lint.full.stderr b/src/test/ui/const-generics/const-parameter-uppercase-lint.full.stderr index 0f4f007f9d2..923964a4070 100644 --- a/src/test/ui/const-generics/const-parameter-uppercase-lint.full.stderr +++ b/src/test/ui/const-generics/const-parameter-uppercase-lint.full.stderr @@ -1,11 +1,11 @@ error: const parameter `x` should have an upper case name - --> $DIR/const-parameter-uppercase-lint.rs:9:15 + --> $DIR/const-parameter-uppercase-lint.rs:8:15 | LL | fn noop() { | ^ help: convert the identifier to upper case (notice the capitalization): `X` | note: the lint level is defined here - --> $DIR/const-parameter-uppercase-lint.rs:7:9 + --> $DIR/const-parameter-uppercase-lint.rs:6:9 | LL | #![deny(non_upper_case_globals)] | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/const-generics/const-parameter-uppercase-lint.min.stderr b/src/test/ui/const-generics/const-parameter-uppercase-lint.min.stderr index 0f4f007f9d2..923964a4070 100644 --- a/src/test/ui/const-generics/const-parameter-uppercase-lint.min.stderr +++ b/src/test/ui/const-generics/const-parameter-uppercase-lint.min.stderr @@ -1,11 +1,11 @@ error: const parameter `x` should have an upper case name - --> $DIR/const-parameter-uppercase-lint.rs:9:15 + --> $DIR/const-parameter-uppercase-lint.rs:8:15 | LL | fn noop() { | ^ help: convert the identifier to upper case (notice the capitalization): `X` | note: the lint level is defined here - --> $DIR/const-parameter-uppercase-lint.rs:7:9 + --> $DIR/const-parameter-uppercase-lint.rs:6:9 | LL | #![deny(non_upper_case_globals)] | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/const-generics/const-parameter-uppercase-lint.rs b/src/test/ui/const-generics/const-parameter-uppercase-lint.rs index b9bd6666af3..5d97907c2e7 100644 --- a/src/test/ui/const-generics/const-parameter-uppercase-lint.rs +++ b/src/test/ui/const-generics/const-parameter-uppercase-lint.rs @@ -2,7 +2,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] #![deny(non_upper_case_globals)] diff --git a/src/test/ui/const-generics/const-types.rs b/src/test/ui/const-generics/const-types.rs index cd34cfc0478..fb150f892ed 100644 --- a/src/test/ui/const-generics/const-types.rs +++ b/src/test/ui/const-generics/const-types.rs @@ -4,7 +4,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] #![allow(dead_code, unused_variables)] diff --git a/src/test/ui/const-generics/const_evaluatable_checked/feature-gate-const_evaluatable_checked.full.stderr b/src/test/ui/const-generics/const_evaluatable_checked/feature-gate-const_evaluatable_checked.full.stderr index b2816367ea1..d6a54ead131 100644 --- a/src/test/ui/const-generics/const_evaluatable_checked/feature-gate-const_evaluatable_checked.full.stderr +++ b/src/test/ui/const-generics/const_evaluatable_checked/feature-gate-const_evaluatable_checked.full.stderr @@ -1,5 +1,5 @@ error: constant expression depends on a generic parameter - --> $DIR/feature-gate-const_evaluatable_checked.rs:9:30 + --> $DIR/feature-gate-const_evaluatable_checked.rs:8:30 | LL | fn test() -> Arr where Arr: Default { | ^^^^^^ diff --git a/src/test/ui/const-generics/const_evaluatable_checked/feature-gate-const_evaluatable_checked.min.stderr b/src/test/ui/const-generics/const_evaluatable_checked/feature-gate-const_evaluatable_checked.min.stderr index 573bc66b7c7..7de4bfcdd05 100644 --- a/src/test/ui/const-generics/const_evaluatable_checked/feature-gate-const_evaluatable_checked.min.stderr +++ b/src/test/ui/const-generics/const_evaluatable_checked/feature-gate-const_evaluatable_checked.min.stderr @@ -1,5 +1,5 @@ error: generic parameters may not be used in const operations - --> $DIR/feature-gate-const_evaluatable_checked.rs:6:33 + --> $DIR/feature-gate-const_evaluatable_checked.rs:5:33 | LL | type Arr = [u8; N - 1]; | ^ cannot perform const operation using `N` diff --git a/src/test/ui/const-generics/const_evaluatable_checked/feature-gate-const_evaluatable_checked.rs b/src/test/ui/const-generics/const_evaluatable_checked/feature-gate-const_evaluatable_checked.rs index 9746adab29b..f49ca0251aa 100644 --- a/src/test/ui/const-generics/const_evaluatable_checked/feature-gate-const_evaluatable_checked.rs +++ b/src/test/ui/const-generics/const_evaluatable_checked/feature-gate-const_evaluatable_checked.rs @@ -1,7 +1,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] type Arr = [u8; N - 1]; //[min]~^ ERROR generic parameters may not be used in const operations diff --git a/src/test/ui/const-generics/const_evaluatable_checked/simple.min.stderr b/src/test/ui/const-generics/const_evaluatable_checked/simple.min.stderr index d476a7eb645..9f3d94bbd8a 100644 --- a/src/test/ui/const-generics/const_evaluatable_checked/simple.min.stderr +++ b/src/test/ui/const-generics/const_evaluatable_checked/simple.min.stderr @@ -1,5 +1,5 @@ error: generic parameters may not be used in const operations - --> $DIR/simple.rs:8:53 + --> $DIR/simple.rs:7:53 | LL | fn test() -> [u8; N - 1] where [u8; N - 1]: Default { | ^ cannot perform const operation using `N` @@ -8,7 +8,7 @@ LL | fn test() -> [u8; N - 1] where [u8; N - 1]: Default { = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: generic parameters may not be used in const operations - --> $DIR/simple.rs:8:35 + --> $DIR/simple.rs:7:35 | LL | fn test() -> [u8; N - 1] where [u8; N - 1]: Default { | ^ cannot perform const operation using `N` diff --git a/src/test/ui/const-generics/const_evaluatable_checked/simple.rs b/src/test/ui/const-generics/const_evaluatable_checked/simple.rs index dcf0071cb29..94ad71b6c1a 100644 --- a/src/test/ui/const-generics/const_evaluatable_checked/simple.rs +++ b/src/test/ui/const-generics/const_evaluatable_checked/simple.rs @@ -1,7 +1,6 @@ // [full] run-pass // revisions: full min #![cfg_attr(full, feature(const_generics))] -#![cfg_attr(min, feature(min_const_generics))] #![feature(const_evaluatable_checked)] #![allow(incomplete_features)] diff --git a/src/test/ui/const-generics/const_evaluatable_checked/simple_fail.full.stderr b/src/test/ui/const-generics/const_evaluatable_checked/simple_fail.full.stderr index f95d6d2d570..c8549f101da 100644 --- a/src/test/ui/const-generics/const_evaluatable_checked/simple_fail.full.stderr +++ b/src/test/ui/const-generics/const_evaluatable_checked/simple_fail.full.stderr @@ -1,5 +1,5 @@ error[E0080]: evaluation of constant value failed - --> $DIR/simple_fail.rs:7:33 + --> $DIR/simple_fail.rs:6:33 | LL | type Arr = [u8; N - 1]; | ^^^^^ attempt to compute `0_usize - 1_usize`, which would overflow diff --git a/src/test/ui/const-generics/const_evaluatable_checked/simple_fail.min.stderr b/src/test/ui/const-generics/const_evaluatable_checked/simple_fail.min.stderr index bd81e0bc5a8..df54b4cbca5 100644 --- a/src/test/ui/const-generics/const_evaluatable_checked/simple_fail.min.stderr +++ b/src/test/ui/const-generics/const_evaluatable_checked/simple_fail.min.stderr @@ -1,5 +1,5 @@ error: generic parameters may not be used in const operations - --> $DIR/simple_fail.rs:7:33 + --> $DIR/simple_fail.rs:6:33 | LL | type Arr = [u8; N - 1]; | ^ cannot perform const operation using `N` diff --git a/src/test/ui/const-generics/const_evaluatable_checked/simple_fail.rs b/src/test/ui/const-generics/const_evaluatable_checked/simple_fail.rs index 5e2c080927f..3cbc077f4f1 100644 --- a/src/test/ui/const-generics/const_evaluatable_checked/simple_fail.rs +++ b/src/test/ui/const-generics/const_evaluatable_checked/simple_fail.rs @@ -1,6 +1,5 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] -#![cfg_attr(min, feature(min_const_generics))] #![feature(const_evaluatable_checked)] #![allow(incomplete_features)] diff --git a/src/test/ui/const-generics/core-types.rs b/src/test/ui/const-generics/core-types.rs index c4351e059de..b6fa478f48d 100644 --- a/src/test/ui/const-generics/core-types.rs +++ b/src/test/ui/const-generics/core-types.rs @@ -4,7 +4,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] struct A; struct B; diff --git a/src/test/ui/const-generics/cross_crate_complex.rs b/src/test/ui/const-generics/cross_crate_complex.rs index 30749b8bc6d..1d495c9562d 100644 --- a/src/test/ui/const-generics/cross_crate_complex.rs +++ b/src/test/ui/const-generics/cross_crate_complex.rs @@ -5,7 +5,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] extern crate crayte; use crayte::*; diff --git a/src/test/ui/const-generics/defaults/complex-unord-param.min.stderr b/src/test/ui/const-generics/defaults/complex-unord-param.min.stderr index 0574ddfb255..cec56d7038a 100644 --- a/src/test/ui/const-generics/defaults/complex-unord-param.min.stderr +++ b/src/test/ui/const-generics/defaults/complex-unord-param.min.stderr @@ -1,5 +1,5 @@ error: type parameters must be declared prior to const parameters - --> $DIR/complex-unord-param.rs:9:41 + --> $DIR/complex-unord-param.rs:8:41 | LL | struct NestedArrays<'a, const N: usize, A: 'a, const M: usize, T:'a =u32> { | ---------------------^----------------------^--------- help: reorder the parameters: lifetimes, then types, then consts: `<'a, A: 'a, T: 'a, const N: usize, const M: usize>` diff --git a/src/test/ui/const-generics/defaults/complex-unord-param.rs b/src/test/ui/const-generics/defaults/complex-unord-param.rs index e83a96388c1..82b3627d22f 100644 --- a/src/test/ui/const-generics/defaults/complex-unord-param.rs +++ b/src/test/ui/const-generics/defaults/complex-unord-param.rs @@ -3,7 +3,6 @@ // Checks a complicated usage of unordered params #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] #![allow(dead_code)] struct NestedArrays<'a, const N: usize, A: 'a, const M: usize, T:'a =u32> { diff --git a/src/test/ui/const-generics/defaults/intermixed-lifetime.full.stderr b/src/test/ui/const-generics/defaults/intermixed-lifetime.full.stderr index 9cc3e9c0da6..98352addaef 100644 --- a/src/test/ui/const-generics/defaults/intermixed-lifetime.full.stderr +++ b/src/test/ui/const-generics/defaults/intermixed-lifetime.full.stderr @@ -1,11 +1,11 @@ error: lifetime parameters must be declared prior to const parameters - --> $DIR/intermixed-lifetime.rs:7:28 + --> $DIR/intermixed-lifetime.rs:6:28 | LL | struct Foo(&'a (), T); | -----------------^^---------- help: reorder the parameters: lifetimes, then consts and types: `<'a, const N: usize, T>` error: lifetime parameters must be declared prior to type parameters - --> $DIR/intermixed-lifetime.rs:11:37 + --> $DIR/intermixed-lifetime.rs:10:37 | LL | struct Bar(&'a (), T); | --------------------------^^- help: reorder the parameters: lifetimes, then consts and types: `<'a, const N: usize, T>` diff --git a/src/test/ui/const-generics/defaults/intermixed-lifetime.min.stderr b/src/test/ui/const-generics/defaults/intermixed-lifetime.min.stderr index 4d80fdb5bcb..532f6d700b2 100644 --- a/src/test/ui/const-generics/defaults/intermixed-lifetime.min.stderr +++ b/src/test/ui/const-generics/defaults/intermixed-lifetime.min.stderr @@ -1,23 +1,23 @@ error: lifetime parameters must be declared prior to const parameters - --> $DIR/intermixed-lifetime.rs:7:28 + --> $DIR/intermixed-lifetime.rs:6:28 | LL | struct Foo(&'a (), T); | -----------------^^---------- help: reorder the parameters: lifetimes, then types, then consts: `<'a, T, const N: usize>` error: type parameters must be declared prior to const parameters - --> $DIR/intermixed-lifetime.rs:7:32 + --> $DIR/intermixed-lifetime.rs:6:32 | LL | struct Foo(&'a (), T); | ---------------------^------- help: reorder the parameters: lifetimes, then types, then consts: `<'a, T, const N: usize>` error: lifetime parameters must be declared prior to const parameters - --> $DIR/intermixed-lifetime.rs:11:37 + --> $DIR/intermixed-lifetime.rs:10:37 | LL | struct Bar(&'a (), T); | --------------------------^^- help: reorder the parameters: lifetimes, then types, then consts: `<'a, T, const N: usize>` error: type parameters must be declared prior to const parameters - --> $DIR/intermixed-lifetime.rs:11:28 + --> $DIR/intermixed-lifetime.rs:10:28 | LL | struct Bar(&'a (), T); | -----------------^----------- help: reorder the parameters: lifetimes, then types, then consts: `<'a, T, const N: usize>` diff --git a/src/test/ui/const-generics/defaults/intermixed-lifetime.rs b/src/test/ui/const-generics/defaults/intermixed-lifetime.rs index cc0d1c6c0c9..9e83bf92a59 100644 --- a/src/test/ui/const-generics/defaults/intermixed-lifetime.rs +++ b/src/test/ui/const-generics/defaults/intermixed-lifetime.rs @@ -2,7 +2,6 @@ // Checks that lifetimes cannot be interspersed between consts and types. #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] struct Foo(&'a (), T); //~^ Error lifetime parameters must be declared prior to const parameters diff --git a/src/test/ui/const-generics/defaults/needs-feature.min.stderr b/src/test/ui/const-generics/defaults/needs-feature.min.stderr index 7058327fdce..86d6173fa02 100644 --- a/src/test/ui/const-generics/defaults/needs-feature.min.stderr +++ b/src/test/ui/const-generics/defaults/needs-feature.min.stderr @@ -1,5 +1,5 @@ error: type parameters must be declared prior to const parameters - --> $DIR/needs-feature.rs:10:26 + --> $DIR/needs-feature.rs:9:26 | LL | struct A(T); | -----------------^----- help: reorder the parameters: lifetimes, then types, then consts: `` diff --git a/src/test/ui/const-generics/defaults/needs-feature.none.stderr b/src/test/ui/const-generics/defaults/needs-feature.none.stderr index 3b6f63a8efe..86d6173fa02 100644 --- a/src/test/ui/const-generics/defaults/needs-feature.none.stderr +++ b/src/test/ui/const-generics/defaults/needs-feature.none.stderr @@ -1,18 +1,8 @@ error: type parameters must be declared prior to const parameters - --> $DIR/needs-feature.rs:10:26 + --> $DIR/needs-feature.rs:9:26 | LL | struct A(T); - | -----------------^----- help: reorder the parameters: lifetimes, then types: `` + | -----------------^----- help: reorder the parameters: lifetimes, then types, then consts: `` -error[E0658]: const generics are unstable - --> $DIR/needs-feature.rs:10:16 - | -LL | struct A(T); - | ^ - | - = note: see issue #74878 for more information - = help: add `#![feature(min_const_generics)]` to the crate attributes to enable - -error: aborting due to 2 previous errors +error: aborting due to previous error -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/const-generics/defaults/needs-feature.rs b/src/test/ui/const-generics/defaults/needs-feature.rs index ec02dbf407d..7eb7764a644 100644 --- a/src/test/ui/const-generics/defaults/needs-feature.rs +++ b/src/test/ui/const-generics/defaults/needs-feature.rs @@ -1,16 +1,13 @@ //[full] run-pass // Verifies that having generic parameters after constants is not permitted without the // `const_generics` feature. -// revisions: none min full +// revisions: min full #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] struct A(T); -//[none]~^ ERROR type parameters must be declared prior -//[none]~| ERROR const generics are unstable -//[min]~^^^ ERROR type parameters must be declared prior +//[min]~^ ERROR type parameters must be declared prior fn main() { let _: A<3> = A(0); diff --git a/src/test/ui/const-generics/defaults/simple-defaults.min.stderr b/src/test/ui/const-generics/defaults/simple-defaults.min.stderr index 59cc6f28af8..01fb4210dd6 100644 --- a/src/test/ui/const-generics/defaults/simple-defaults.min.stderr +++ b/src/test/ui/const-generics/defaults/simple-defaults.min.stderr @@ -1,5 +1,5 @@ error: type parameters must be declared prior to const parameters - --> $DIR/simple-defaults.rs:9:40 + --> $DIR/simple-defaults.rs:8:40 | LL | struct FixedOutput<'a, const N: usize, T=u32> { | ---------------------^----- help: reorder the parameters: lifetimes, then types, then consts: `<'a, T, const N: usize>` diff --git a/src/test/ui/const-generics/defaults/simple-defaults.rs b/src/test/ui/const-generics/defaults/simple-defaults.rs index 78abe351998..1f1b6c2260d 100644 --- a/src/test/ui/const-generics/defaults/simple-defaults.rs +++ b/src/test/ui/const-generics/defaults/simple-defaults.rs @@ -3,7 +3,6 @@ // Checks some basic test cases for defaults. #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] #![allow(dead_code)] struct FixedOutput<'a, const N: usize, T=u32> { diff --git a/src/test/ui/const-generics/defaults/wrong-order.full.stderr b/src/test/ui/const-generics/defaults/wrong-order.full.stderr index 99f46309bf6..96deb4a8b5a 100644 --- a/src/test/ui/const-generics/defaults/wrong-order.full.stderr +++ b/src/test/ui/const-generics/defaults/wrong-order.full.stderr @@ -1,5 +1,5 @@ error: type parameters with a default must be trailing - --> $DIR/wrong-order.rs:5:10 + --> $DIR/wrong-order.rs:4:10 | LL | struct A { | ^ @@ -14,7 +14,6 @@ LL | #![cfg_attr(full, feature(const_generics))] | = note: `#[warn(incomplete_features)]` on by default = note: see issue #44580 for more information - = help: consider using `min_const_generics` instead, which is more stable and complete error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/const-generics/defaults/wrong-order.min.stderr b/src/test/ui/const-generics/defaults/wrong-order.min.stderr index 29a46367004..b19da76f415 100644 --- a/src/test/ui/const-generics/defaults/wrong-order.min.stderr +++ b/src/test/ui/const-generics/defaults/wrong-order.min.stderr @@ -1,5 +1,5 @@ error: type parameters with a default must be trailing - --> $DIR/wrong-order.rs:5:10 + --> $DIR/wrong-order.rs:4:10 | LL | struct A { | ^ diff --git a/src/test/ui/const-generics/defaults/wrong-order.rs b/src/test/ui/const-generics/defaults/wrong-order.rs index cb36d456f38..4f1c05011b0 100644 --- a/src/test/ui/const-generics/defaults/wrong-order.rs +++ b/src/test/ui/const-generics/defaults/wrong-order.rs @@ -1,6 +1,5 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] //[full]~WARN the feature `const_generics` is incomplete -#![cfg_attr(min, feature(min_const_generics))] struct A { //~^ ERROR type parameters with a default must be trailing diff --git a/src/test/ui/const-generics/derive-debug-array-wrapper.rs b/src/test/ui/const-generics/derive-debug-array-wrapper.rs index 13fd87f1e3e..ce1481d97e9 100644 --- a/src/test/ui/const-generics/derive-debug-array-wrapper.rs +++ b/src/test/ui/const-generics/derive-debug-array-wrapper.rs @@ -4,7 +4,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] #[derive(Debug)] struct X { diff --git a/src/test/ui/const-generics/different_byref.full.stderr b/src/test/ui/const-generics/different_byref.full.stderr index 4463ed7fcdd..d6b32323e2d 100644 --- a/src/test/ui/const-generics/different_byref.full.stderr +++ b/src/test/ui/const-generics/different_byref.full.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/different_byref.rs:13:9 + --> $DIR/different_byref.rs:12:9 | LL | x = Const::<{ [4] }> {}; | ^^^^^^^^^^^^^^^^^^^ expected `3_usize`, found `4_usize` diff --git a/src/test/ui/const-generics/different_byref.min.stderr b/src/test/ui/const-generics/different_byref.min.stderr index e5b393ffe99..05720d15404 100644 --- a/src/test/ui/const-generics/different_byref.min.stderr +++ b/src/test/ui/const-generics/different_byref.min.stderr @@ -1,5 +1,5 @@ error: `[usize; 1]` is forbidden as the type of a const generic parameter - --> $DIR/different_byref.rs:8:23 + --> $DIR/different_byref.rs:7:23 | LL | struct Const {} | ^^^^^^^^^^ diff --git a/src/test/ui/const-generics/different_byref.rs b/src/test/ui/const-generics/different_byref.rs index cd3960eeb8e..7977560ecbc 100644 --- a/src/test/ui/const-generics/different_byref.rs +++ b/src/test/ui/const-generics/different_byref.rs @@ -3,7 +3,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] struct Const {} //[min]~^ ERROR `[usize; 1]` is forbidden diff --git a/src/test/ui/const-generics/different_byref_simple.full.stderr b/src/test/ui/const-generics/different_byref_simple.full.stderr index b6729c852ab..027e282c398 100644 --- a/src/test/ui/const-generics/different_byref_simple.full.stderr +++ b/src/test/ui/const-generics/different_byref_simple.full.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/different_byref_simple.rs:12:9 + --> $DIR/different_byref_simple.rs:11:9 | LL | u = ConstUsize::<4> {}; | ^^^^^^^^^^^^^^^^^^ expected `3_usize`, found `4_usize` diff --git a/src/test/ui/const-generics/different_byref_simple.min.stderr b/src/test/ui/const-generics/different_byref_simple.min.stderr index b6729c852ab..027e282c398 100644 --- a/src/test/ui/const-generics/different_byref_simple.min.stderr +++ b/src/test/ui/const-generics/different_byref_simple.min.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/different_byref_simple.rs:12:9 + --> $DIR/different_byref_simple.rs:11:9 | LL | u = ConstUsize::<4> {}; | ^^^^^^^^^^^^^^^^^^ expected `3_usize`, found `4_usize` diff --git a/src/test/ui/const-generics/different_byref_simple.rs b/src/test/ui/const-generics/different_byref_simple.rs index 93289f93331..b48189fc2cb 100644 --- a/src/test/ui/const-generics/different_byref_simple.rs +++ b/src/test/ui/const-generics/different_byref_simple.rs @@ -3,7 +3,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] struct ConstUsize {} diff --git a/src/test/ui/const-generics/dyn-supertraits.rs b/src/test/ui/const-generics/dyn-supertraits.rs index 0295255d809..73ed23521c3 100644 --- a/src/test/ui/const-generics/dyn-supertraits.rs +++ b/src/test/ui/const-generics/dyn-supertraits.rs @@ -3,7 +3,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] trait Foo { fn myfun(&self) -> usize; diff --git a/src/test/ui/const-generics/exhaustive-value.full.stderr b/src/test/ui/const-generics/exhaustive-value.full.stderr index fdea1fb0c3e..e0e1423ba01 100644 --- a/src/test/ui/const-generics/exhaustive-value.full.stderr +++ b/src/test/ui/const-generics/exhaustive-value.full.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `(): Foo` is not satisfied - --> $DIR/exhaustive-value.rs:267:5 + --> $DIR/exhaustive-value.rs:266:5 | LL | fn test() {} | --------- required by `Foo::test` diff --git a/src/test/ui/const-generics/exhaustive-value.min.stderr b/src/test/ui/const-generics/exhaustive-value.min.stderr index fdea1fb0c3e..e0e1423ba01 100644 --- a/src/test/ui/const-generics/exhaustive-value.min.stderr +++ b/src/test/ui/const-generics/exhaustive-value.min.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `(): Foo` is not satisfied - --> $DIR/exhaustive-value.rs:267:5 + --> $DIR/exhaustive-value.rs:266:5 | LL | fn test() {} | --------- required by `Foo::test` diff --git a/src/test/ui/const-generics/exhaustive-value.rs b/src/test/ui/const-generics/exhaustive-value.rs index fce036b0da6..921f9a46707 100644 --- a/src/test/ui/const-generics/exhaustive-value.rs +++ b/src/test/ui/const-generics/exhaustive-value.rs @@ -1,7 +1,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] trait Foo { fn test() {} diff --git a/src/test/ui/const-generics/fn-const-param-call.full.stderr b/src/test/ui/const-generics/fn-const-param-call.full.stderr index f1bd8def9ff..d984449e6ca 100644 --- a/src/test/ui/const-generics/fn-const-param-call.full.stderr +++ b/src/test/ui/const-generics/fn-const-param-call.full.stderr @@ -1,11 +1,11 @@ error: using function pointers as const generic parameters is forbidden - --> $DIR/fn-const-param-call.rs:12:25 + --> $DIR/fn-const-param-call.rs:11:25 | LL | struct Wrapper u32>; | ^^^^^^^^^^^ error: using function pointers as const generic parameters is forbidden - --> $DIR/fn-const-param-call.rs:14:15 + --> $DIR/fn-const-param-call.rs:13:15 | LL | impl u32> Wrapper { | ^^^^^^^^^^^ diff --git a/src/test/ui/const-generics/fn-const-param-call.min.stderr b/src/test/ui/const-generics/fn-const-param-call.min.stderr index f1bd8def9ff..d984449e6ca 100644 --- a/src/test/ui/const-generics/fn-const-param-call.min.stderr +++ b/src/test/ui/const-generics/fn-const-param-call.min.stderr @@ -1,11 +1,11 @@ error: using function pointers as const generic parameters is forbidden - --> $DIR/fn-const-param-call.rs:12:25 + --> $DIR/fn-const-param-call.rs:11:25 | LL | struct Wrapper u32>; | ^^^^^^^^^^^ error: using function pointers as const generic parameters is forbidden - --> $DIR/fn-const-param-call.rs:14:15 + --> $DIR/fn-const-param-call.rs:13:15 | LL | impl u32> Wrapper { | ^^^^^^^^^^^ diff --git a/src/test/ui/const-generics/fn-const-param-call.rs b/src/test/ui/const-generics/fn-const-param-call.rs index bba6c1f7a16..70a104e2222 100644 --- a/src/test/ui/const-generics/fn-const-param-call.rs +++ b/src/test/ui/const-generics/fn-const-param-call.rs @@ -3,7 +3,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] fn function() -> u32 { 17 diff --git a/src/test/ui/const-generics/fn-const-param-infer.full.stderr b/src/test/ui/const-generics/fn-const-param-infer.full.stderr index 4bdc9b89af6..f0767a10994 100644 --- a/src/test/ui/const-generics/fn-const-param-infer.full.stderr +++ b/src/test/ui/const-generics/fn-const-param-infer.full.stderr @@ -1,5 +1,5 @@ error: using function pointers as const generic parameters is forbidden - --> $DIR/fn-const-param-infer.rs:7:25 + --> $DIR/fn-const-param-infer.rs:6:25 | LL | struct Checked bool>; | ^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/const-generics/fn-const-param-infer.min.stderr b/src/test/ui/const-generics/fn-const-param-infer.min.stderr index 4bdc9b89af6..f0767a10994 100644 --- a/src/test/ui/const-generics/fn-const-param-infer.min.stderr +++ b/src/test/ui/const-generics/fn-const-param-infer.min.stderr @@ -1,5 +1,5 @@ error: using function pointers as const generic parameters is forbidden - --> $DIR/fn-const-param-infer.rs:7:25 + --> $DIR/fn-const-param-infer.rs:6:25 | LL | struct Checked bool>; | ^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/const-generics/fn-const-param-infer.rs b/src/test/ui/const-generics/fn-const-param-infer.rs index 3ed75e7b00d..d090479d4c3 100644 --- a/src/test/ui/const-generics/fn-const-param-infer.rs +++ b/src/test/ui/const-generics/fn-const-param-infer.rs @@ -2,7 +2,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] struct Checked bool>; //~^ ERROR: using function pointers as const generic parameters diff --git a/src/test/ui/const-generics/fn-taking-const-generic-array.rs b/src/test/ui/const-generics/fn-taking-const-generic-array.rs index 950684aaa8d..58c1b95893e 100644 --- a/src/test/ui/const-generics/fn-taking-const-generic-array.rs +++ b/src/test/ui/const-generics/fn-taking-const-generic-array.rs @@ -3,7 +3,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] use std::fmt::Display; diff --git a/src/test/ui/const-generics/forbid-non-structural_match-types.full.stderr b/src/test/ui/const-generics/forbid-non-structural_match-types.full.stderr index adcaa759963..5c0f17537fa 100644 --- a/src/test/ui/const-generics/forbid-non-structural_match-types.full.stderr +++ b/src/test/ui/const-generics/forbid-non-structural_match-types.full.stderr @@ -1,5 +1,5 @@ error[E0741]: `C` must be annotated with `#[derive(PartialEq, Eq)]` to be used as the type of a const parameter - --> $DIR/forbid-non-structural_match-types.rs:15:19 + --> $DIR/forbid-non-structural_match-types.rs:14:19 | LL | struct D; | ^ `C` doesn't derive both `PartialEq` and `Eq` diff --git a/src/test/ui/const-generics/forbid-non-structural_match-types.min.stderr b/src/test/ui/const-generics/forbid-non-structural_match-types.min.stderr index 014200178b9..3912cf57751 100644 --- a/src/test/ui/const-generics/forbid-non-structural_match-types.min.stderr +++ b/src/test/ui/const-generics/forbid-non-structural_match-types.min.stderr @@ -1,5 +1,5 @@ error: `A` is forbidden as the type of a const generic parameter - --> $DIR/forbid-non-structural_match-types.rs:10:19 + --> $DIR/forbid-non-structural_match-types.rs:9:19 | LL | struct B; // ok | ^ @@ -8,7 +8,7 @@ LL | struct B; // ok = help: more complex types are supported with `#[feature(const_generics)]` error: `C` is forbidden as the type of a const generic parameter - --> $DIR/forbid-non-structural_match-types.rs:15:19 + --> $DIR/forbid-non-structural_match-types.rs:14:19 | LL | struct D; | ^ @@ -17,7 +17,7 @@ LL | struct D; = help: more complex types are supported with `#[feature(const_generics)]` error[E0741]: `C` must be annotated with `#[derive(PartialEq, Eq)]` to be used as the type of a const parameter - --> $DIR/forbid-non-structural_match-types.rs:15:19 + --> $DIR/forbid-non-structural_match-types.rs:14:19 | LL | struct D; | ^ `C` doesn't derive both `PartialEq` and `Eq` diff --git a/src/test/ui/const-generics/forbid-non-structural_match-types.rs b/src/test/ui/const-generics/forbid-non-structural_match-types.rs index e7356d485db..0fdb3ed4a5a 100644 --- a/src/test/ui/const-generics/forbid-non-structural_match-types.rs +++ b/src/test/ui/const-generics/forbid-non-structural_match-types.rs @@ -2,7 +2,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] #[derive(PartialEq, Eq)] struct A; diff --git a/src/test/ui/const-generics/foreign-item-const-parameter.full.stderr b/src/test/ui/const-generics/foreign-item-const-parameter.full.stderr index 0ac51e8c9e6..b827e482977 100644 --- a/src/test/ui/const-generics/foreign-item-const-parameter.full.stderr +++ b/src/test/ui/const-generics/foreign-item-const-parameter.full.stderr @@ -1,5 +1,5 @@ error[E0044]: foreign items may not have const parameters - --> $DIR/foreign-item-const-parameter.rs:8:5 + --> $DIR/foreign-item-const-parameter.rs:7:5 | LL | fn foo(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ can't have const parameters @@ -7,7 +7,7 @@ LL | fn foo(); = help: replace the const parameters with concrete consts error[E0044]: foreign items may not have type or const parameters - --> $DIR/foreign-item-const-parameter.rs:10:5 + --> $DIR/foreign-item-const-parameter.rs:9:5 | LL | fn bar(_: T); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't have type or const parameters diff --git a/src/test/ui/const-generics/foreign-item-const-parameter.min.stderr b/src/test/ui/const-generics/foreign-item-const-parameter.min.stderr index 0ac51e8c9e6..b827e482977 100644 --- a/src/test/ui/const-generics/foreign-item-const-parameter.min.stderr +++ b/src/test/ui/const-generics/foreign-item-const-parameter.min.stderr @@ -1,5 +1,5 @@ error[E0044]: foreign items may not have const parameters - --> $DIR/foreign-item-const-parameter.rs:8:5 + --> $DIR/foreign-item-const-parameter.rs:7:5 | LL | fn foo(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ can't have const parameters @@ -7,7 +7,7 @@ LL | fn foo(); = help: replace the const parameters with concrete consts error[E0044]: foreign items may not have type or const parameters - --> $DIR/foreign-item-const-parameter.rs:10:5 + --> $DIR/foreign-item-const-parameter.rs:9:5 | LL | fn bar(_: T); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't have type or const parameters diff --git a/src/test/ui/const-generics/foreign-item-const-parameter.rs b/src/test/ui/const-generics/foreign-item-const-parameter.rs index 44b6d0332c3..83caa89f033 100644 --- a/src/test/ui/const-generics/foreign-item-const-parameter.rs +++ b/src/test/ui/const-generics/foreign-item-const-parameter.rs @@ -2,7 +2,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] extern "C" { fn foo(); //~ ERROR foreign items may not have const parameters diff --git a/src/test/ui/const-generics/generic-function-call-in-array-length.full.stderr b/src/test/ui/const-generics/generic-function-call-in-array-length.full.stderr index 43b42d82d0c..2d19a58a145 100644 --- a/src/test/ui/const-generics/generic-function-call-in-array-length.full.stderr +++ b/src/test/ui/const-generics/generic-function-call-in-array-length.full.stderr @@ -1,5 +1,5 @@ error: constant expression depends on a generic parameter - --> $DIR/generic-function-call-in-array-length.rs:9:29 + --> $DIR/generic-function-call-in-array-length.rs:8:29 | LL | fn bar() -> [u32; foo(N)] { | ^^^^^^^^^^^^^ diff --git a/src/test/ui/const-generics/generic-function-call-in-array-length.min.stderr b/src/test/ui/const-generics/generic-function-call-in-array-length.min.stderr index 526f98fe8cd..d7a3f04a8da 100644 --- a/src/test/ui/const-generics/generic-function-call-in-array-length.min.stderr +++ b/src/test/ui/const-generics/generic-function-call-in-array-length.min.stderr @@ -1,5 +1,5 @@ error: generic parameters may not be used in const operations - --> $DIR/generic-function-call-in-array-length.rs:9:39 + --> $DIR/generic-function-call-in-array-length.rs:8:39 | LL | fn bar() -> [u32; foo(N)] { | ^ cannot perform const operation using `N` @@ -8,7 +8,7 @@ LL | fn bar() -> [u32; foo(N)] { = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: generic parameters may not be used in const operations - --> $DIR/generic-function-call-in-array-length.rs:12:13 + --> $DIR/generic-function-call-in-array-length.rs:11:13 | LL | [0; foo(N)] | ^ cannot perform const operation using `N` diff --git a/src/test/ui/const-generics/generic-function-call-in-array-length.rs b/src/test/ui/const-generics/generic-function-call-in-array-length.rs index c838070dc95..a6d2bbd17ea 100644 --- a/src/test/ui/const-generics/generic-function-call-in-array-length.rs +++ b/src/test/ui/const-generics/generic-function-call-in-array-length.rs @@ -2,7 +2,6 @@ #![cfg_attr(full, allow(incomplete_features))] #![cfg_attr(full, feature(const_generics))] -#![cfg_attr(min, feature(min_const_generics))] const fn foo(n: usize) -> usize { n * 2 } diff --git a/src/test/ui/const-generics/generic-param-mismatch.full.stderr b/src/test/ui/const-generics/generic-param-mismatch.full.stderr index 6befa9d1f69..aff8780fb0d 100644 --- a/src/test/ui/const-generics/generic-param-mismatch.full.stderr +++ b/src/test/ui/const-generics/generic-param-mismatch.full.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/generic-param-mismatch.rs:7:5 + --> $DIR/generic-param-mismatch.rs:6:5 | LL | fn test() -> [u8; M] { | ------- expected `[u8; M]` because of return type diff --git a/src/test/ui/const-generics/generic-param-mismatch.min.stderr b/src/test/ui/const-generics/generic-param-mismatch.min.stderr index 6befa9d1f69..aff8780fb0d 100644 --- a/src/test/ui/const-generics/generic-param-mismatch.min.stderr +++ b/src/test/ui/const-generics/generic-param-mismatch.min.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/generic-param-mismatch.rs:7:5 + --> $DIR/generic-param-mismatch.rs:6:5 | LL | fn test() -> [u8; M] { | ------- expected `[u8; M]` because of return type diff --git a/src/test/ui/const-generics/generic-param-mismatch.rs b/src/test/ui/const-generics/generic-param-mismatch.rs index e409094eb73..22fffe47dcc 100644 --- a/src/test/ui/const-generics/generic-param-mismatch.rs +++ b/src/test/ui/const-generics/generic-param-mismatch.rs @@ -1,7 +1,6 @@ // revisions: full min #![cfg_attr(full, allow(incomplete_features))] #![cfg_attr(full, feature(const_generics))] -#![cfg_attr(min, feature(min_const_generics))] fn test() -> [u8; M] { [0; N] //~ ERROR mismatched types diff --git a/src/test/ui/const-generics/generic-sum-in-array-length.full.stderr b/src/test/ui/const-generics/generic-sum-in-array-length.full.stderr index d311e1c0bae..c13882e7fe1 100644 --- a/src/test/ui/const-generics/generic-sum-in-array-length.full.stderr +++ b/src/test/ui/const-generics/generic-sum-in-array-length.full.stderr @@ -1,5 +1,5 @@ error: constant expression depends on a generic parameter - --> $DIR/generic-sum-in-array-length.rs:7:45 + --> $DIR/generic-sum-in-array-length.rs:6:45 | LL | fn foo(bar: [usize; A + B]) {} | ^^^^^^^^^^^^^^ diff --git a/src/test/ui/const-generics/generic-sum-in-array-length.min.stderr b/src/test/ui/const-generics/generic-sum-in-array-length.min.stderr index e531b612b56..cff5a62193c 100644 --- a/src/test/ui/const-generics/generic-sum-in-array-length.min.stderr +++ b/src/test/ui/const-generics/generic-sum-in-array-length.min.stderr @@ -1,5 +1,5 @@ error: generic parameters may not be used in const operations - --> $DIR/generic-sum-in-array-length.rs:7:53 + --> $DIR/generic-sum-in-array-length.rs:6:53 | LL | fn foo(bar: [usize; A + B]) {} | ^ cannot perform const operation using `A` @@ -8,7 +8,7 @@ LL | fn foo(bar: [usize; A + B]) {} = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: generic parameters may not be used in const operations - --> $DIR/generic-sum-in-array-length.rs:7:57 + --> $DIR/generic-sum-in-array-length.rs:6:57 | LL | fn foo(bar: [usize; A + B]) {} | ^ cannot perform const operation using `B` diff --git a/src/test/ui/const-generics/generic-sum-in-array-length.rs b/src/test/ui/const-generics/generic-sum-in-array-length.rs index 84ddfe055dc..7ee0394ba14 100644 --- a/src/test/ui/const-generics/generic-sum-in-array-length.rs +++ b/src/test/ui/const-generics/generic-sum-in-array-length.rs @@ -2,7 +2,6 @@ #![cfg_attr(full, allow(incomplete_features))] #![cfg_attr(full, feature(const_generics))] -#![cfg_attr(min, feature(min_const_generics))] fn foo(bar: [usize; A + B]) {} //[min]~^ ERROR generic parameters may not be used in const operations diff --git a/src/test/ui/const-generics/impl-const-generic-struct.rs b/src/test/ui/const-generics/impl-const-generic-struct.rs index 05cabc46baa..1aa22698b64 100644 --- a/src/test/ui/const-generics/impl-const-generic-struct.rs +++ b/src/test/ui/const-generics/impl-const-generic-struct.rs @@ -3,7 +3,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] struct S; diff --git a/src/test/ui/const-generics/impl-trait-with-const-arguments.full.stderr b/src/test/ui/const-generics/impl-trait-with-const-arguments.full.stderr index a587cb61873..26b965901a4 100644 --- a/src/test/ui/const-generics/impl-trait-with-const-arguments.full.stderr +++ b/src/test/ui/const-generics/impl-trait-with-const-arguments.full.stderr @@ -1,5 +1,5 @@ error[E0632]: cannot provide explicit generic arguments when `impl Trait` is used in argument position - --> $DIR/impl-trait-with-const-arguments.rs:24:20 + --> $DIR/impl-trait-with-const-arguments.rs:23:20 | LL | assert_eq!(f::<4usize>(Usizable), 20usize); | ^^^^^^ explicit generic argument not allowed diff --git a/src/test/ui/const-generics/impl-trait-with-const-arguments.min.stderr b/src/test/ui/const-generics/impl-trait-with-const-arguments.min.stderr index a587cb61873..26b965901a4 100644 --- a/src/test/ui/const-generics/impl-trait-with-const-arguments.min.stderr +++ b/src/test/ui/const-generics/impl-trait-with-const-arguments.min.stderr @@ -1,5 +1,5 @@ error[E0632]: cannot provide explicit generic arguments when `impl Trait` is used in argument position - --> $DIR/impl-trait-with-const-arguments.rs:24:20 + --> $DIR/impl-trait-with-const-arguments.rs:23:20 | LL | assert_eq!(f::<4usize>(Usizable), 20usize); | ^^^^^^ explicit generic argument not allowed diff --git a/src/test/ui/const-generics/impl-trait-with-const-arguments.rs b/src/test/ui/const-generics/impl-trait-with-const-arguments.rs index a4c75792ee3..2e6e49b9c0a 100644 --- a/src/test/ui/const-generics/impl-trait-with-const-arguments.rs +++ b/src/test/ui/const-generics/impl-trait-with-const-arguments.rs @@ -2,7 +2,6 @@ #![cfg_attr(full, allow(incomplete_features))] #![cfg_attr(full, feature(const_generics))] -#![cfg_attr(min, feature(min_const_generics))] trait Usizer { fn m(self) -> usize; diff --git a/src/test/ui/const-generics/incorrect-number-of-const-args.full.stderr b/src/test/ui/const-generics/incorrect-number-of-const-args.full.stderr index 6b902e2d658..9c8359b08a5 100644 --- a/src/test/ui/const-generics/incorrect-number-of-const-args.full.stderr +++ b/src/test/ui/const-generics/incorrect-number-of-const-args.full.stderr @@ -1,11 +1,11 @@ error[E0107]: wrong number of const arguments: expected 2, found 1 - --> $DIR/incorrect-number-of-const-args.rs:12:5 + --> $DIR/incorrect-number-of-const-args.rs:11:5 | LL | foo::<0>(); | ^^^^^^^^ expected 2 const arguments error[E0107]: wrong number of const arguments: expected 2, found 3 - --> $DIR/incorrect-number-of-const-args.rs:13:17 + --> $DIR/incorrect-number-of-const-args.rs:12:17 | LL | foo::<0, 0, 0>(); | ^ unexpected const argument diff --git a/src/test/ui/const-generics/incorrect-number-of-const-args.min.stderr b/src/test/ui/const-generics/incorrect-number-of-const-args.min.stderr index 6b902e2d658..9c8359b08a5 100644 --- a/src/test/ui/const-generics/incorrect-number-of-const-args.min.stderr +++ b/src/test/ui/const-generics/incorrect-number-of-const-args.min.stderr @@ -1,11 +1,11 @@ error[E0107]: wrong number of const arguments: expected 2, found 1 - --> $DIR/incorrect-number-of-const-args.rs:12:5 + --> $DIR/incorrect-number-of-const-args.rs:11:5 | LL | foo::<0>(); | ^^^^^^^^ expected 2 const arguments error[E0107]: wrong number of const arguments: expected 2, found 3 - --> $DIR/incorrect-number-of-const-args.rs:13:17 + --> $DIR/incorrect-number-of-const-args.rs:12:17 | LL | foo::<0, 0, 0>(); | ^ unexpected const argument diff --git a/src/test/ui/const-generics/incorrect-number-of-const-args.rs b/src/test/ui/const-generics/incorrect-number-of-const-args.rs index f7bdf761f7d..3c4290df056 100644 --- a/src/test/ui/const-generics/incorrect-number-of-const-args.rs +++ b/src/test/ui/const-generics/incorrect-number-of-const-args.rs @@ -2,7 +2,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] fn foo() -> usize { 0 diff --git a/src/test/ui/const-generics/infer/cannot-infer-const-args.full.stderr b/src/test/ui/const-generics/infer/cannot-infer-const-args.full.stderr index 05bf67a5ff7..e85bf8829ae 100644 --- a/src/test/ui/const-generics/infer/cannot-infer-const-args.full.stderr +++ b/src/test/ui/const-generics/infer/cannot-infer-const-args.full.stderr @@ -1,5 +1,5 @@ error[E0282]: type annotations needed - --> $DIR/cannot-infer-const-args.rs:12:5 + --> $DIR/cannot-infer-const-args.rs:11:5 | LL | foo(); | ^^^ cannot infer the value of const parameter `X` declared on the function `foo` diff --git a/src/test/ui/const-generics/infer/cannot-infer-const-args.min.stderr b/src/test/ui/const-generics/infer/cannot-infer-const-args.min.stderr index 05bf67a5ff7..e85bf8829ae 100644 --- a/src/test/ui/const-generics/infer/cannot-infer-const-args.min.stderr +++ b/src/test/ui/const-generics/infer/cannot-infer-const-args.min.stderr @@ -1,5 +1,5 @@ error[E0282]: type annotations needed - --> $DIR/cannot-infer-const-args.rs:12:5 + --> $DIR/cannot-infer-const-args.rs:11:5 | LL | foo(); | ^^^ cannot infer the value of const parameter `X` declared on the function `foo` diff --git a/src/test/ui/const-generics/infer/cannot-infer-const-args.rs b/src/test/ui/const-generics/infer/cannot-infer-const-args.rs index 2d74b4788bf..cc52892bd04 100644 --- a/src/test/ui/const-generics/infer/cannot-infer-const-args.rs +++ b/src/test/ui/const-generics/infer/cannot-infer-const-args.rs @@ -2,7 +2,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] fn foo() -> usize { 0 diff --git a/src/test/ui/const-generics/infer/issue-77092.rs b/src/test/ui/const-generics/infer/issue-77092.rs index 9a1dd1a8258..fcf7d3282b4 100644 --- a/src/test/ui/const-generics/infer/issue-77092.rs +++ b/src/test/ui/const-generics/infer/issue-77092.rs @@ -1,5 +1,3 @@ -#![feature(min_const_generics)] - use std::convert::TryInto; fn take_array_from_mut(data: &mut [T], start: usize) -> &mut [T; N] { diff --git a/src/test/ui/const-generics/infer/issue-77092.stderr b/src/test/ui/const-generics/infer/issue-77092.stderr index 99894173bc8..5857a421198 100644 --- a/src/test/ui/const-generics/infer/issue-77092.stderr +++ b/src/test/ui/const-generics/infer/issue-77092.stderr @@ -1,5 +1,5 @@ error[E0282]: type annotations needed - --> $DIR/issue-77092.rs:13:26 + --> $DIR/issue-77092.rs:11:26 | LL | println!("{:?}", take_array_from_mut(&mut arr, i)); | ^^^^^^^^^^^^^^^^^^^ cannot infer the value of const parameter `N` declared on the function `take_array_from_mut` diff --git a/src/test/ui/const-generics/infer/method-chain.full.stderr b/src/test/ui/const-generics/infer/method-chain.full.stderr index 7aa3bd44df8..f6d9c4a2645 100644 --- a/src/test/ui/const-generics/infer/method-chain.full.stderr +++ b/src/test/ui/const-generics/infer/method-chain.full.stderr @@ -1,5 +1,5 @@ error[E0282]: type annotations needed - --> $DIR/method-chain.rs:21:33 + --> $DIR/method-chain.rs:20:33 | LL | Foo.bar().bar().bar().bar().baz(); | ^^^ cannot infer the value of const parameter `N` declared on the associated function `baz` diff --git a/src/test/ui/const-generics/infer/method-chain.min.stderr b/src/test/ui/const-generics/infer/method-chain.min.stderr index 7aa3bd44df8..f6d9c4a2645 100644 --- a/src/test/ui/const-generics/infer/method-chain.min.stderr +++ b/src/test/ui/const-generics/infer/method-chain.min.stderr @@ -1,5 +1,5 @@ error[E0282]: type annotations needed - --> $DIR/method-chain.rs:21:33 + --> $DIR/method-chain.rs:20:33 | LL | Foo.bar().bar().bar().bar().baz(); | ^^^ cannot infer the value of const parameter `N` declared on the associated function `baz` diff --git a/src/test/ui/const-generics/infer/method-chain.rs b/src/test/ui/const-generics/infer/method-chain.rs index 9389ca20d10..8ac6a7d6267 100644 --- a/src/test/ui/const-generics/infer/method-chain.rs +++ b/src/test/ui/const-generics/infer/method-chain.rs @@ -2,7 +2,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] struct Foo; diff --git a/src/test/ui/const-generics/infer/uninferred-consts.full.stderr b/src/test/ui/const-generics/infer/uninferred-consts.full.stderr index 4be625ba909..254a28f70e2 100644 --- a/src/test/ui/const-generics/infer/uninferred-consts.full.stderr +++ b/src/test/ui/const-generics/infer/uninferred-consts.full.stderr @@ -1,5 +1,5 @@ error[E0282]: type annotations needed - --> $DIR/uninferred-consts.rs:14:9 + --> $DIR/uninferred-consts.rs:13:9 | LL | Foo.foo(); | ^^^ cannot infer the value of const parameter `A` declared on the associated function `foo` diff --git a/src/test/ui/const-generics/infer/uninferred-consts.min.stderr b/src/test/ui/const-generics/infer/uninferred-consts.min.stderr index 4be625ba909..254a28f70e2 100644 --- a/src/test/ui/const-generics/infer/uninferred-consts.min.stderr +++ b/src/test/ui/const-generics/infer/uninferred-consts.min.stderr @@ -1,5 +1,5 @@ error[E0282]: type annotations needed - --> $DIR/uninferred-consts.rs:14:9 + --> $DIR/uninferred-consts.rs:13:9 | LL | Foo.foo(); | ^^^ cannot infer the value of const parameter `A` declared on the associated function `foo` diff --git a/src/test/ui/const-generics/infer/uninferred-consts.rs b/src/test/ui/const-generics/infer/uninferred-consts.rs index 00fb6eac992..bcd9aadb78a 100644 --- a/src/test/ui/const-generics/infer/uninferred-consts.rs +++ b/src/test/ui/const-generics/infer/uninferred-consts.rs @@ -3,7 +3,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] // taken from https://github.com/rust-lang/rust/issues/70507#issuecomment-615268893 struct Foo; diff --git a/src/test/ui/const-generics/infer_arg_from_pat.rs b/src/test/ui/const-generics/infer_arg_from_pat.rs index 609fdb35cf1..5e2a3eaff54 100644 --- a/src/test/ui/const-generics/infer_arg_from_pat.rs +++ b/src/test/ui/const-generics/infer_arg_from_pat.rs @@ -5,7 +5,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] struct A { arr: [u8; N], diff --git a/src/test/ui/const-generics/infer_arr_len_from_pat.rs b/src/test/ui/const-generics/infer_arr_len_from_pat.rs index cbf48e3d249..0273383856f 100644 --- a/src/test/ui/const-generics/infer_arr_len_from_pat.rs +++ b/src/test/ui/const-generics/infer_arr_len_from_pat.rs @@ -5,7 +5,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] fn as_chunks() -> [u8; N] { loop {} diff --git a/src/test/ui/const-generics/integer-literal-generic-arg-in-where-clause.rs b/src/test/ui/const-generics/integer-literal-generic-arg-in-where-clause.rs index bdbf338295c..96e5976e44b 100644 --- a/src/test/ui/const-generics/integer-literal-generic-arg-in-where-clause.rs +++ b/src/test/ui/const-generics/integer-literal-generic-arg-in-where-clause.rs @@ -3,7 +3,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] fn takes_closure_of_array_3(f: F) where F: Fn([i32; 3]) { f([1, 2, 3]); diff --git a/src/test/ui/const-generics/intrinsics-type_name-as-const-argument.full.stderr b/src/test/ui/const-generics/intrinsics-type_name-as-const-argument.full.stderr index c09d16d0ab0..3e90dbeece9 100644 --- a/src/test/ui/const-generics/intrinsics-type_name-as-const-argument.full.stderr +++ b/src/test/ui/const-generics/intrinsics-type_name-as-const-argument.full.stderr @@ -1,5 +1,5 @@ error: constant expression depends on a generic parameter - --> $DIR/intrinsics-type_name-as-const-argument.rs:15:8 + --> $DIR/intrinsics-type_name-as-const-argument.rs:14:8 | LL | T: Trait<{std::intrinsics::type_name::()}> | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/const-generics/intrinsics-type_name-as-const-argument.min.stderr b/src/test/ui/const-generics/intrinsics-type_name-as-const-argument.min.stderr index 02467df193c..4c2aaef3493 100644 --- a/src/test/ui/const-generics/intrinsics-type_name-as-const-argument.min.stderr +++ b/src/test/ui/const-generics/intrinsics-type_name-as-const-argument.min.stderr @@ -1,5 +1,5 @@ error: generic parameters may not be used in const operations - --> $DIR/intrinsics-type_name-as-const-argument.rs:15:44 + --> $DIR/intrinsics-type_name-as-const-argument.rs:14:44 | LL | T: Trait<{std::intrinsics::type_name::()}> | ^ cannot perform const operation using `T` @@ -8,7 +8,7 @@ LL | T: Trait<{std::intrinsics::type_name::()}> = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: `&'static str` is forbidden as the type of a const generic parameter - --> $DIR/intrinsics-type_name-as-const-argument.rs:10:22 + --> $DIR/intrinsics-type_name-as-const-argument.rs:9:22 | LL | trait Trait {} | ^^^^^^^^^^^^ diff --git a/src/test/ui/const-generics/intrinsics-type_name-as-const-argument.rs b/src/test/ui/const-generics/intrinsics-type_name-as-const-argument.rs index 8971c00ed5a..f24dd42eb2d 100644 --- a/src/test/ui/const-generics/intrinsics-type_name-as-const-argument.rs +++ b/src/test/ui/const-generics/intrinsics-type_name-as-const-argument.rs @@ -2,7 +2,6 @@ #![cfg_attr(full, allow(incomplete_features))] #![cfg_attr(full, feature(const_generics))] -#![cfg_attr(min, feature(min_const_generics))] #![feature(core_intrinsics)] #![feature(const_type_name)] diff --git a/src/test/ui/const-generics/issue-61522-array-len-succ.full.stderr b/src/test/ui/const-generics/issue-61522-array-len-succ.full.stderr index 8855f187e97..56deec16548 100644 --- a/src/test/ui/const-generics/issue-61522-array-len-succ.full.stderr +++ b/src/test/ui/const-generics/issue-61522-array-len-succ.full.stderr @@ -1,5 +1,5 @@ error: constant expression depends on a generic parameter - --> $DIR/issue-61522-array-len-succ.rs:7:40 + --> $DIR/issue-61522-array-len-succ.rs:6:40 | LL | pub struct MyArray([u8; COUNT + 1]); | ^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | pub struct MyArray([u8; COUNT + 1]); = note: this may fail depending on what value the parameter takes error: constant expression depends on a generic parameter - --> $DIR/issue-61522-array-len-succ.rs:12:24 + --> $DIR/issue-61522-array-len-succ.rs:11:24 | LL | fn inner(&self) -> &[u8; COUNT + 1] { | ^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/const-generics/issue-61522-array-len-succ.min.stderr b/src/test/ui/const-generics/issue-61522-array-len-succ.min.stderr index 2eaef95c232..36a0a37ae9c 100644 --- a/src/test/ui/const-generics/issue-61522-array-len-succ.min.stderr +++ b/src/test/ui/const-generics/issue-61522-array-len-succ.min.stderr @@ -1,5 +1,5 @@ error: generic parameters may not be used in const operations - --> $DIR/issue-61522-array-len-succ.rs:7:45 + --> $DIR/issue-61522-array-len-succ.rs:6:45 | LL | pub struct MyArray([u8; COUNT + 1]); | ^^^^^ cannot perform const operation using `COUNT` @@ -8,7 +8,7 @@ LL | pub struct MyArray([u8; COUNT + 1]); = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: generic parameters may not be used in const operations - --> $DIR/issue-61522-array-len-succ.rs:12:30 + --> $DIR/issue-61522-array-len-succ.rs:11:30 | LL | fn inner(&self) -> &[u8; COUNT + 1] { | ^^^^^ cannot perform const operation using `COUNT` diff --git a/src/test/ui/const-generics/issue-61522-array-len-succ.rs b/src/test/ui/const-generics/issue-61522-array-len-succ.rs index 8c0a3a03774..d4a948b9259 100644 --- a/src/test/ui/const-generics/issue-61522-array-len-succ.rs +++ b/src/test/ui/const-generics/issue-61522-array-len-succ.rs @@ -2,7 +2,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] pub struct MyArray([u8; COUNT + 1]); //[full]~^ ERROR constant expression depends on a generic parameter diff --git a/src/test/ui/const-generics/issue-66596-impl-trait-for-str-const-arg.min.stderr b/src/test/ui/const-generics/issue-66596-impl-trait-for-str-const-arg.min.stderr index 1c2e7e069a1..b6c6e6fe374 100644 --- a/src/test/ui/const-generics/issue-66596-impl-trait-for-str-const-arg.min.stderr +++ b/src/test/ui/const-generics/issue-66596-impl-trait-for-str-const-arg.min.stderr @@ -1,5 +1,5 @@ error: `&'static str` is forbidden as the type of a const generic parameter - --> $DIR/issue-66596-impl-trait-for-str-const-arg.rs:9:25 + --> $DIR/issue-66596-impl-trait-for-str-const-arg.rs:8:25 | LL | trait Trait { | ^^^^^^^^^^^^ diff --git a/src/test/ui/const-generics/issue-66596-impl-trait-for-str-const-arg.rs b/src/test/ui/const-generics/issue-66596-impl-trait-for-str-const-arg.rs index 11d4bf4c3e6..2a741ba87a9 100644 --- a/src/test/ui/const-generics/issue-66596-impl-trait-for-str-const-arg.rs +++ b/src/test/ui/const-generics/issue-66596-impl-trait-for-str-const-arg.rs @@ -3,7 +3,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] trait Trait { diff --git a/src/test/ui/const-generics/issue-67375.full.stderr b/src/test/ui/const-generics/issue-67375.full.stderr index e15d65f197e..2f004f75de5 100644 --- a/src/test/ui/const-generics/issue-67375.full.stderr +++ b/src/test/ui/const-generics/issue-67375.full.stderr @@ -1,5 +1,5 @@ warning: cannot use constants which depend on generic parameters in types - --> $DIR/issue-67375.rs:9:12 + --> $DIR/issue-67375.rs:8:12 | LL | inner: [(); { [|_: &T| {}; 0].len() }], | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -9,7 +9,7 @@ LL | inner: [(); { [|_: &T| {}; 0].len() }], = note: for more information, see issue #76200 error[E0392]: parameter `T` is never used - --> $DIR/issue-67375.rs:7:12 + --> $DIR/issue-67375.rs:6:12 | LL | struct Bug { | ^ unused parameter diff --git a/src/test/ui/const-generics/issue-67375.min.stderr b/src/test/ui/const-generics/issue-67375.min.stderr index da96b5374a5..337e7bc1409 100644 --- a/src/test/ui/const-generics/issue-67375.min.stderr +++ b/src/test/ui/const-generics/issue-67375.min.stderr @@ -1,5 +1,5 @@ error: generic parameters may not be used in const operations - --> $DIR/issue-67375.rs:9:25 + --> $DIR/issue-67375.rs:8:25 | LL | inner: [(); { [|_: &T| {}; 0].len() }], | ^ cannot perform const operation using `T` @@ -8,7 +8,7 @@ LL | inner: [(); { [|_: &T| {}; 0].len() }], = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error[E0392]: parameter `T` is never used - --> $DIR/issue-67375.rs:7:12 + --> $DIR/issue-67375.rs:6:12 | LL | struct Bug { | ^ unused parameter diff --git a/src/test/ui/const-generics/issue-67375.rs b/src/test/ui/const-generics/issue-67375.rs index ecc76bcae06..a8875b8b6bf 100644 --- a/src/test/ui/const-generics/issue-67375.rs +++ b/src/test/ui/const-generics/issue-67375.rs @@ -2,7 +2,6 @@ #![cfg_attr(full, allow(incomplete_features))] #![cfg_attr(full, feature(const_generics))] -#![cfg_attr(min, feature(min_const_generics))] struct Bug { //~^ ERROR parameter `T` is never used diff --git a/src/test/ui/const-generics/issue-67945-1.full.stderr b/src/test/ui/const-generics/issue-67945-1.full.stderr index e79c4f5374e..5cdcefe3501 100644 --- a/src/test/ui/const-generics/issue-67945-1.full.stderr +++ b/src/test/ui/const-generics/issue-67945-1.full.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/issue-67945-1.rs:14:20 + --> $DIR/issue-67945-1.rs:13:20 | LL | struct Bug { | - this type parameter @@ -13,7 +13,7 @@ LL | let x: S = MaybeUninit::uninit(); found union `MaybeUninit<_>` error[E0392]: parameter `S` is never used - --> $DIR/issue-67945-1.rs:11:12 + --> $DIR/issue-67945-1.rs:10:12 | LL | struct Bug { | ^ unused parameter diff --git a/src/test/ui/const-generics/issue-67945-1.min.stderr b/src/test/ui/const-generics/issue-67945-1.min.stderr index 8fea130baa5..a3e086ea954 100644 --- a/src/test/ui/const-generics/issue-67945-1.min.stderr +++ b/src/test/ui/const-generics/issue-67945-1.min.stderr @@ -1,5 +1,5 @@ error: generic parameters may not be used in const operations - --> $DIR/issue-67945-1.rs:14:16 + --> $DIR/issue-67945-1.rs:13:16 | LL | let x: S = MaybeUninit::uninit(); | ^ cannot perform const operation using `S` @@ -8,7 +8,7 @@ LL | let x: S = MaybeUninit::uninit(); = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: generic parameters may not be used in const operations - --> $DIR/issue-67945-1.rs:17:45 + --> $DIR/issue-67945-1.rs:16:45 | LL | let b = &*(&x as *const _ as *const S); | ^ cannot perform const operation using `S` @@ -17,7 +17,7 @@ LL | let b = &*(&x as *const _ as *const S); = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error[E0392]: parameter `S` is never used - --> $DIR/issue-67945-1.rs:11:12 + --> $DIR/issue-67945-1.rs:10:12 | LL | struct Bug { | ^ unused parameter diff --git a/src/test/ui/const-generics/issue-67945-1.rs b/src/test/ui/const-generics/issue-67945-1.rs index 6771603f259..84737e4e985 100644 --- a/src/test/ui/const-generics/issue-67945-1.rs +++ b/src/test/ui/const-generics/issue-67945-1.rs @@ -2,7 +2,6 @@ #![cfg_attr(full, allow(incomplete_features))] #![cfg_attr(full, feature(const_generics))] -#![cfg_attr(min, feature(min_const_generics))] use std::marker::PhantomData; diff --git a/src/test/ui/const-generics/issue-67945-2.full.stderr b/src/test/ui/const-generics/issue-67945-2.full.stderr index 2f54b802df8..4d96058b395 100644 --- a/src/test/ui/const-generics/issue-67945-2.full.stderr +++ b/src/test/ui/const-generics/issue-67945-2.full.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/issue-67945-2.rs:12:20 + --> $DIR/issue-67945-2.rs:11:20 | LL | struct Bug { | - this type parameter @@ -13,7 +13,7 @@ LL | let x: S = MaybeUninit::uninit(); found union `MaybeUninit<_>` error[E0392]: parameter `S` is never used - --> $DIR/issue-67945-2.rs:9:12 + --> $DIR/issue-67945-2.rs:8:12 | LL | struct Bug { | ^ unused parameter diff --git a/src/test/ui/const-generics/issue-67945-2.min.stderr b/src/test/ui/const-generics/issue-67945-2.min.stderr index 50633772b75..860be4a9b6a 100644 --- a/src/test/ui/const-generics/issue-67945-2.min.stderr +++ b/src/test/ui/const-generics/issue-67945-2.min.stderr @@ -1,5 +1,5 @@ error: generic parameters may not be used in const operations - --> $DIR/issue-67945-2.rs:12:16 + --> $DIR/issue-67945-2.rs:11:16 | LL | let x: S = MaybeUninit::uninit(); | ^ cannot perform const operation using `S` @@ -8,7 +8,7 @@ LL | let x: S = MaybeUninit::uninit(); = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: generic parameters may not be used in const operations - --> $DIR/issue-67945-2.rs:15:45 + --> $DIR/issue-67945-2.rs:14:45 | LL | let b = &*(&x as *const _ as *const S); | ^ cannot perform const operation using `S` @@ -17,7 +17,7 @@ LL | let b = &*(&x as *const _ as *const S); = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error[E0392]: parameter `S` is never used - --> $DIR/issue-67945-2.rs:9:12 + --> $DIR/issue-67945-2.rs:8:12 | LL | struct Bug { | ^ unused parameter diff --git a/src/test/ui/const-generics/issue-67945-2.rs b/src/test/ui/const-generics/issue-67945-2.rs index 72dbb674e66..4a46786e9a9 100644 --- a/src/test/ui/const-generics/issue-67945-2.rs +++ b/src/test/ui/const-generics/issue-67945-2.rs @@ -2,7 +2,6 @@ #![cfg_attr(full, allow(incomplete_features))] #![cfg_attr(full, feature(const_generics))] -#![cfg_attr(min, feature(min_const_generics))] use std::mem::MaybeUninit; diff --git a/src/test/ui/const-generics/issue-67945-3.full.stderr b/src/test/ui/const-generics/issue-67945-3.full.stderr index c33b88588c0..fa66252bd69 100644 --- a/src/test/ui/const-generics/issue-67945-3.full.stderr +++ b/src/test/ui/const-generics/issue-67945-3.full.stderr @@ -1,5 +1,5 @@ error: constant expression depends on a generic parameter - --> $DIR/issue-67945-3.rs:8:8 + --> $DIR/issue-67945-3.rs:7:8 | LL | A: [(); { | ________^ diff --git a/src/test/ui/const-generics/issue-67945-3.min.stderr b/src/test/ui/const-generics/issue-67945-3.min.stderr index 9c6e101ece8..5c30429c895 100644 --- a/src/test/ui/const-generics/issue-67945-3.min.stderr +++ b/src/test/ui/const-generics/issue-67945-3.min.stderr @@ -1,5 +1,5 @@ error: generic `Self` types are currently not permitted in anonymous constants - --> $DIR/issue-67945-3.rs:10:27 + --> $DIR/issue-67945-3.rs:9:27 | LL | let x: Option> = None; | ^^^^ diff --git a/src/test/ui/const-generics/issue-67945-3.rs b/src/test/ui/const-generics/issue-67945-3.rs index bca079101e2..5bad61cfc76 100644 --- a/src/test/ui/const-generics/issue-67945-3.rs +++ b/src/test/ui/const-generics/issue-67945-3.rs @@ -2,7 +2,6 @@ #![cfg_attr(full, allow(incomplete_features))] #![cfg_attr(full, feature(const_generics))] -#![cfg_attr(min, feature(min_const_generics))] struct Bug { A: [(); { diff --git a/src/test/ui/const-generics/issue-68104-print-stack-overflow.rs b/src/test/ui/const-generics/issue-68104-print-stack-overflow.rs index eab63d3a6e6..43c3999133c 100644 --- a/src/test/ui/const-generics/issue-68104-print-stack-overflow.rs +++ b/src/test/ui/const-generics/issue-68104-print-stack-overflow.rs @@ -4,7 +4,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] extern crate impl_const; diff --git a/src/test/ui/const-generics/issue-70180-1-stalled_on.rs b/src/test/ui/const-generics/issue-70180-1-stalled_on.rs index 9cfa57006d5..f0554823273 100644 --- a/src/test/ui/const-generics/issue-70180-1-stalled_on.rs +++ b/src/test/ui/const-generics/issue-70180-1-stalled_on.rs @@ -3,7 +3,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] pub fn works() { let array/*: [_; _]*/ = default_array(); diff --git a/src/test/ui/const-generics/issue-70180-2-stalled_on.rs b/src/test/ui/const-generics/issue-70180-2-stalled_on.rs index bbde404966c..21cefc09c25 100644 --- a/src/test/ui/const-generics/issue-70180-2-stalled_on.rs +++ b/src/test/ui/const-generics/issue-70180-2-stalled_on.rs @@ -3,7 +3,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] fn works() { let array/*: [u8; _]*/ = default_byte_array(); diff --git a/src/test/ui/const-generics/issue-71986.rs b/src/test/ui/const-generics/issue-71986.rs index d4c962452d1..6bfdba5711e 100644 --- a/src/test/ui/const-generics/issue-71986.rs +++ b/src/test/ui/const-generics/issue-71986.rs @@ -3,7 +3,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] pub trait Foo {} pub fn bar>() {} diff --git a/src/test/ui/const-generics/issue-74906.rs b/src/test/ui/const-generics/issue-74906.rs index 9162d1142b6..dc3c33736da 100644 --- a/src/test/ui/const-generics/issue-74906.rs +++ b/src/test/ui/const-generics/issue-74906.rs @@ -3,7 +3,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] const SIZE: usize = 16; diff --git a/src/test/ui/const-generics/issues/auxiliary/const_generic_issues_lib.rs b/src/test/ui/const-generics/issues/auxiliary/const_generic_issues_lib.rs index 7ea8d936d61..f59eb60cb38 100644 --- a/src/test/ui/const-generics/issues/auxiliary/const_generic_issues_lib.rs +++ b/src/test/ui/const-generics/issues/auxiliary/const_generic_issues_lib.rs @@ -1,6 +1,5 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] // All of these three items must be in `lib2` to reproduce the error diff --git a/src/test/ui/const-generics/issues/issue-56445.full.stderr b/src/test/ui/const-generics/issues/issue-56445.full.stderr index 50e91418551..61fba92c196 100644 --- a/src/test/ui/const-generics/issues/issue-56445.full.stderr +++ b/src/test/ui/const-generics/issues/issue-56445.full.stderr @@ -6,10 +6,9 @@ LL | #![cfg_attr(full, feature(const_generics))] | = note: `#[warn(incomplete_features)]` on by default = note: see issue #44580 for more information - = help: consider using `min_const_generics` instead, which is more stable and complete error[E0771]: use of non-static lifetime `'a` in const generic - --> $DIR/issue-56445.rs:9:26 + --> $DIR/issue-56445.rs:8:26 | LL | struct Bug<'a, const S: &'a str>(PhantomData<&'a ()>); | ^^ diff --git a/src/test/ui/const-generics/issues/issue-56445.min.stderr b/src/test/ui/const-generics/issues/issue-56445.min.stderr index bcb27d8d1e1..80702dd4bc3 100644 --- a/src/test/ui/const-generics/issues/issue-56445.min.stderr +++ b/src/test/ui/const-generics/issues/issue-56445.min.stderr @@ -1,5 +1,5 @@ error[E0771]: use of non-static lifetime `'a` in const generic - --> $DIR/issue-56445.rs:9:26 + --> $DIR/issue-56445.rs:8:26 | LL | struct Bug<'a, const S: &'a str>(PhantomData<&'a ()>); | ^^ diff --git a/src/test/ui/const-generics/issues/issue-56445.rs b/src/test/ui/const-generics/issues/issue-56445.rs index 0bcde348b05..bc9e1dee853 100644 --- a/src/test/ui/const-generics/issues/issue-56445.rs +++ b/src/test/ui/const-generics/issues/issue-56445.rs @@ -1,7 +1,6 @@ // Regression test for https://github.com/rust-lang/rust/issues/56445#issuecomment-518402995. // revisions: full min #![cfg_attr(full, feature(const_generics))] //[full]~WARN the feature `const_generics` is incomplete -#![cfg_attr(min, feature(min_const_generics))] #![crate_type = "lib"] use std::marker::PhantomData; diff --git a/src/test/ui/const-generics/issues/issue-60263.rs b/src/test/ui/const-generics/issues/issue-60263.rs deleted file mode 100644 index 70cbc242c41..00000000000 --- a/src/test/ui/const-generics/issues/issue-60263.rs +++ /dev/null @@ -1,9 +0,0 @@ -struct B; //~ ERROR const generics are unstable - -impl B<0> { - fn bug() -> Self { - panic!() - } -} - -fn main() {} diff --git a/src/test/ui/const-generics/issues/issue-60263.stderr b/src/test/ui/const-generics/issues/issue-60263.stderr deleted file mode 100644 index aeef296f385..00000000000 --- a/src/test/ui/const-generics/issues/issue-60263.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0658]: const generics are unstable - --> $DIR/issue-60263.rs:1:16 - | -LL | struct B; - | ^ - | - = note: see issue #74878 for more information - = help: add `#![feature(min_const_generics)]` to the crate attributes to enable - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/const-generics/issues/issue-60818-struct-constructors.full.stderr b/src/test/ui/const-generics/issues/issue-60818-struct-constructors.full.stderr index cc014ea429d..c03b7252a3c 100644 --- a/src/test/ui/const-generics/issues/issue-60818-struct-constructors.full.stderr +++ b/src/test/ui/const-generics/issues/issue-60818-struct-constructors.full.stderr @@ -6,7 +6,6 @@ LL | #![cfg_attr(full, feature(const_generics))] | = note: `#[warn(incomplete_features)]` on by default = note: see issue #44580 for more information - = help: consider using `min_const_generics` instead, which is more stable and complete warning: 1 warning emitted diff --git a/src/test/ui/const-generics/issues/issue-60818-struct-constructors.rs b/src/test/ui/const-generics/issues/issue-60818-struct-constructors.rs index ae2b0520fb1..6e64c78cd8c 100644 --- a/src/test/ui/const-generics/issues/issue-60818-struct-constructors.rs +++ b/src/test/ui/const-generics/issues/issue-60818-struct-constructors.rs @@ -1,7 +1,6 @@ // check-pass // revisions: full min #![cfg_attr(full, feature(const_generics))] //[full]~WARN the feature `const_generics` is incomplete -#![cfg_attr(min, feature(min_const_generics))] struct Generic; diff --git a/src/test/ui/const-generics/issues/issue-61336-1.full.stderr b/src/test/ui/const-generics/issues/issue-61336-1.full.stderr index 3a9f819a626..f18728eabbb 100644 --- a/src/test/ui/const-generics/issues/issue-61336-1.full.stderr +++ b/src/test/ui/const-generics/issues/issue-61336-1.full.stderr @@ -6,7 +6,6 @@ LL | #![cfg_attr(full, feature(const_generics))] | = note: `#[warn(incomplete_features)]` on by default = note: see issue #44580 for more information - = help: consider using `min_const_generics` instead, which is more stable and complete warning: 1 warning emitted diff --git a/src/test/ui/const-generics/issues/issue-61336-1.rs b/src/test/ui/const-generics/issues/issue-61336-1.rs index 201c0d039d9..c93b296dbb5 100644 --- a/src/test/ui/const-generics/issues/issue-61336-1.rs +++ b/src/test/ui/const-generics/issues/issue-61336-1.rs @@ -1,7 +1,6 @@ // build-pass // revisions: full min #![cfg_attr(full, feature(const_generics))] //[full]~WARN the feature `const_generics` is incomplete -#![cfg_attr(min, feature(min_const_generics))] fn f(x: T) -> [T; N] { [x; N] diff --git a/src/test/ui/const-generics/issues/issue-61336-2.full.stderr b/src/test/ui/const-generics/issues/issue-61336-2.full.stderr index 883ebbef3e8..9f8e68d211d 100644 --- a/src/test/ui/const-generics/issues/issue-61336-2.full.stderr +++ b/src/test/ui/const-generics/issues/issue-61336-2.full.stderr @@ -6,10 +6,9 @@ LL | #![cfg_attr(full, feature(const_generics))] | = note: `#[warn(incomplete_features)]` on by default = note: see issue #44580 for more information - = help: consider using `min_const_generics` instead, which is more stable and complete error[E0277]: the trait bound `T: Copy` is not satisfied - --> $DIR/issue-61336-2.rs:10:5 + --> $DIR/issue-61336-2.rs:9:5 | LL | [x; { N }] | ^^^^^^^^^^ the trait `Copy` is not implemented for `T` diff --git a/src/test/ui/const-generics/issues/issue-61336-2.min.stderr b/src/test/ui/const-generics/issues/issue-61336-2.min.stderr index 40863a4f718..82d17a87e0a 100644 --- a/src/test/ui/const-generics/issues/issue-61336-2.min.stderr +++ b/src/test/ui/const-generics/issues/issue-61336-2.min.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `T: Copy` is not satisfied - --> $DIR/issue-61336-2.rs:10:5 + --> $DIR/issue-61336-2.rs:9:5 | LL | [x; { N }] | ^^^^^^^^^^ the trait `Copy` is not implemented for `T` diff --git a/src/test/ui/const-generics/issues/issue-61336-2.rs b/src/test/ui/const-generics/issues/issue-61336-2.rs index 44995157cc9..a1cf641ff74 100644 --- a/src/test/ui/const-generics/issues/issue-61336-2.rs +++ b/src/test/ui/const-generics/issues/issue-61336-2.rs @@ -1,6 +1,5 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] //[full]~WARN the feature `const_generics` is incomplete -#![cfg_attr(min, feature(min_const_generics))] fn f(x: T) -> [T; N] { [x; { N }] diff --git a/src/test/ui/const-generics/issues/issue-61336.full.stderr b/src/test/ui/const-generics/issues/issue-61336.full.stderr index 3863da8da05..974e2af6fd2 100644 --- a/src/test/ui/const-generics/issues/issue-61336.full.stderr +++ b/src/test/ui/const-generics/issues/issue-61336.full.stderr @@ -6,10 +6,9 @@ LL | #![cfg_attr(full, feature(const_generics))] | = note: `#[warn(incomplete_features)]` on by default = note: see issue #44580 for more information - = help: consider using `min_const_generics` instead, which is more stable and complete error[E0277]: the trait bound `T: Copy` is not satisfied - --> $DIR/issue-61336.rs:10:5 + --> $DIR/issue-61336.rs:9:5 | LL | [x; N] | ^^^^^^ the trait `Copy` is not implemented for `T` diff --git a/src/test/ui/const-generics/issues/issue-61336.min.stderr b/src/test/ui/const-generics/issues/issue-61336.min.stderr index 6c57f9ccbf5..19c7153582c 100644 --- a/src/test/ui/const-generics/issues/issue-61336.min.stderr +++ b/src/test/ui/const-generics/issues/issue-61336.min.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `T: Copy` is not satisfied - --> $DIR/issue-61336.rs:10:5 + --> $DIR/issue-61336.rs:9:5 | LL | [x; N] | ^^^^^^ the trait `Copy` is not implemented for `T` diff --git a/src/test/ui/const-generics/issues/issue-61336.rs b/src/test/ui/const-generics/issues/issue-61336.rs index 7c34250e6b2..c0106ee38c2 100644 --- a/src/test/ui/const-generics/issues/issue-61336.rs +++ b/src/test/ui/const-generics/issues/issue-61336.rs @@ -1,6 +1,5 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] //[full]~WARN the feature `const_generics` is incomplete -#![cfg_attr(min, feature(min_const_generics))] fn f(x: T) -> [T; N] { [x; N] diff --git a/src/test/ui/const-generics/issues/issue-61422.full.stderr b/src/test/ui/const-generics/issues/issue-61422.full.stderr index 294378a6690..ac6c378295d 100644 --- a/src/test/ui/const-generics/issues/issue-61422.full.stderr +++ b/src/test/ui/const-generics/issues/issue-61422.full.stderr @@ -6,7 +6,6 @@ LL | #![cfg_attr(full, feature(const_generics))] | = note: `#[warn(incomplete_features)]` on by default = note: see issue #44580 for more information - = help: consider using `min_const_generics` instead, which is more stable and complete warning: 1 warning emitted diff --git a/src/test/ui/const-generics/issues/issue-61422.rs b/src/test/ui/const-generics/issues/issue-61422.rs index 649f8b4255b..421f696f3fd 100644 --- a/src/test/ui/const-generics/issues/issue-61422.rs +++ b/src/test/ui/const-generics/issues/issue-61422.rs @@ -1,7 +1,6 @@ // check-pass // revisions: full min #![cfg_attr(full, feature(const_generics))] //[full]~WARN the feature `const_generics` is incomplete -#![cfg_attr(min, feature(min_const_generics))] use std::mem; diff --git a/src/test/ui/const-generics/issues/issue-61432.full.stderr b/src/test/ui/const-generics/issues/issue-61432.full.stderr index eec1b20254e..82b36de45a2 100644 --- a/src/test/ui/const-generics/issues/issue-61432.full.stderr +++ b/src/test/ui/const-generics/issues/issue-61432.full.stderr @@ -6,7 +6,6 @@ LL | #![cfg_attr(full, feature(const_generics))] | = note: `#[warn(incomplete_features)]` on by default = note: see issue #44580 for more information - = help: consider using `min_const_generics` instead, which is more stable and complete warning: 1 warning emitted diff --git a/src/test/ui/const-generics/issues/issue-61432.rs b/src/test/ui/const-generics/issues/issue-61432.rs index 91a4794099c..0e228126d77 100644 --- a/src/test/ui/const-generics/issues/issue-61432.rs +++ b/src/test/ui/const-generics/issues/issue-61432.rs @@ -1,7 +1,6 @@ // run-pass // revisions: full min #![cfg_attr(full, feature(const_generics))] //[full]~WARN the feature `const_generics` is incomplete -#![cfg_attr(min, feature(min_const_generics))] fn promote() { // works: diff --git a/src/test/ui/const-generics/issues/issue-61747.full.stderr b/src/test/ui/const-generics/issues/issue-61747.full.stderr index 3a266c8e974..b7f66345c4a 100644 --- a/src/test/ui/const-generics/issues/issue-61747.full.stderr +++ b/src/test/ui/const-generics/issues/issue-61747.full.stderr @@ -6,10 +6,9 @@ LL | #![cfg_attr(full, feature(const_generics))] | = note: `#[warn(incomplete_features)]` on by default = note: see issue #44580 for more information - = help: consider using `min_const_generics` instead, which is more stable and complete error: constant expression depends on a generic parameter - --> $DIR/issue-61747.rs:8:23 + --> $DIR/issue-61747.rs:7:23 | LL | fn successor() -> Const<{C + 1}> { | ^^^^^^^^^^^^^^ diff --git a/src/test/ui/const-generics/issues/issue-61747.min.stderr b/src/test/ui/const-generics/issues/issue-61747.min.stderr index 1de9e71b6eb..b85533ccb46 100644 --- a/src/test/ui/const-generics/issues/issue-61747.min.stderr +++ b/src/test/ui/const-generics/issues/issue-61747.min.stderr @@ -1,5 +1,5 @@ error: generic parameters may not be used in const operations - --> $DIR/issue-61747.rs:8:30 + --> $DIR/issue-61747.rs:7:30 | LL | fn successor() -> Const<{C + 1}> { | ^ cannot perform const operation using `C` diff --git a/src/test/ui/const-generics/issues/issue-61747.rs b/src/test/ui/const-generics/issues/issue-61747.rs index 3a4dd1cdd18..3aa2e6a5c31 100644 --- a/src/test/ui/const-generics/issues/issue-61747.rs +++ b/src/test/ui/const-generics/issues/issue-61747.rs @@ -1,6 +1,5 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] //[full]~WARN the feature `const_generics` is incomplete -#![cfg_attr(min, feature(min_const_generics))] struct Const; diff --git a/src/test/ui/const-generics/issues/issue-61935.full.stderr b/src/test/ui/const-generics/issues/issue-61935.full.stderr index b805bc0db7e..b970f4e4c8e 100644 --- a/src/test/ui/const-generics/issues/issue-61935.full.stderr +++ b/src/test/ui/const-generics/issues/issue-61935.full.stderr @@ -1,5 +1,5 @@ error: constant expression depends on a generic parameter - --> $DIR/issue-61935.rs:10:14 + --> $DIR/issue-61935.rs:9:14 | LL | Self:FooImpl<{N==0}> | ^^^^^^^^^^^^^^^ diff --git a/src/test/ui/const-generics/issues/issue-61935.min.stderr b/src/test/ui/const-generics/issues/issue-61935.min.stderr index b1d92056a54..9382dca3153 100644 --- a/src/test/ui/const-generics/issues/issue-61935.min.stderr +++ b/src/test/ui/const-generics/issues/issue-61935.min.stderr @@ -1,5 +1,5 @@ error: generic parameters may not be used in const operations - --> $DIR/issue-61935.rs:10:23 + --> $DIR/issue-61935.rs:9:23 | LL | Self:FooImpl<{N==0}> | ^ cannot perform const operation using `N` diff --git a/src/test/ui/const-generics/issues/issue-61935.rs b/src/test/ui/const-generics/issues/issue-61935.rs index 9fa02329a71..ed861c63bf1 100644 --- a/src/test/ui/const-generics/issues/issue-61935.rs +++ b/src/test/ui/const-generics/issues/issue-61935.rs @@ -1,7 +1,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] trait Foo {} diff --git a/src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.rs b/src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.rs index a8fa3780356..1a0e46e599d 100644 --- a/src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.rs +++ b/src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.rs @@ -3,7 +3,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] pub trait BitLen: Sized { const BIT_LEN: usize; diff --git a/src/test/ui/const-generics/issues/issue-62220.full.stderr b/src/test/ui/const-generics/issues/issue-62220.full.stderr index 120aa8e4af5..373360c7ced 100644 --- a/src/test/ui/const-generics/issues/issue-62220.full.stderr +++ b/src/test/ui/const-generics/issues/issue-62220.full.stderr @@ -1,5 +1,5 @@ error: constant expression depends on a generic parameter - --> $DIR/issue-62220.rs:13:27 + --> $DIR/issue-62220.rs:12:27 | LL | pub fn trunc(self) -> (TruncatedVector, T) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/const-generics/issues/issue-62220.min.stderr b/src/test/ui/const-generics/issues/issue-62220.min.stderr index b338cdb87e1..72311d030cf 100644 --- a/src/test/ui/const-generics/issues/issue-62220.min.stderr +++ b/src/test/ui/const-generics/issues/issue-62220.min.stderr @@ -1,5 +1,5 @@ error: generic parameters may not be used in const operations - --> $DIR/issue-62220.rs:8:59 + --> $DIR/issue-62220.rs:7:59 | LL | pub type TruncatedVector = Vector; | ^ cannot perform const operation using `N` diff --git a/src/test/ui/const-generics/issues/issue-62220.rs b/src/test/ui/const-generics/issues/issue-62220.rs index 2017473fa9e..c26784c9813 100644 --- a/src/test/ui/const-generics/issues/issue-62220.rs +++ b/src/test/ui/const-generics/issues/issue-62220.rs @@ -1,7 +1,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] pub struct Vector([T; N]); diff --git a/src/test/ui/const-generics/issues/issue-62456.full.stderr b/src/test/ui/const-generics/issues/issue-62456.full.stderr index a8d44074db9..833e70ca6d3 100644 --- a/src/test/ui/const-generics/issues/issue-62456.full.stderr +++ b/src/test/ui/const-generics/issues/issue-62456.full.stderr @@ -1,5 +1,5 @@ error: constant expression depends on a generic parameter - --> $DIR/issue-62456.rs:7:20 + --> $DIR/issue-62456.rs:6:20 | LL | let _ = [0u64; N + 1]; | ^^^^^ diff --git a/src/test/ui/const-generics/issues/issue-62456.min.stderr b/src/test/ui/const-generics/issues/issue-62456.min.stderr index a4b501a7bb1..920318fa0ac 100644 --- a/src/test/ui/const-generics/issues/issue-62456.min.stderr +++ b/src/test/ui/const-generics/issues/issue-62456.min.stderr @@ -1,5 +1,5 @@ error: generic parameters may not be used in const operations - --> $DIR/issue-62456.rs:7:20 + --> $DIR/issue-62456.rs:6:20 | LL | let _ = [0u64; N + 1]; | ^ cannot perform const operation using `N` diff --git a/src/test/ui/const-generics/issues/issue-62456.rs b/src/test/ui/const-generics/issues/issue-62456.rs index cbb2a11a931..e24cf36c8ce 100644 --- a/src/test/ui/const-generics/issues/issue-62456.rs +++ b/src/test/ui/const-generics/issues/issue-62456.rs @@ -1,7 +1,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] fn foo() { let _ = [0u64; N + 1]; diff --git a/src/test/ui/const-generics/issues/issue-62504.full.stderr b/src/test/ui/const-generics/issues/issue-62504.full.stderr index 9c84f06ce9f..f09af76325e 100644 --- a/src/test/ui/const-generics/issues/issue-62504.full.stderr +++ b/src/test/ui/const-generics/issues/issue-62504.full.stderr @@ -1,5 +1,5 @@ error: constant expression depends on a generic parameter - --> $DIR/issue-62504.rs:19:25 + --> $DIR/issue-62504.rs:18:25 | LL | ArrayHolder([0; Self::SIZE]) | ^^^^^^^^^^ diff --git a/src/test/ui/const-generics/issues/issue-62504.min.stderr b/src/test/ui/const-generics/issues/issue-62504.min.stderr index 865eaf74932..5d45e302888 100644 --- a/src/test/ui/const-generics/issues/issue-62504.min.stderr +++ b/src/test/ui/const-generics/issues/issue-62504.min.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/issue-62504.rs:19:21 + --> $DIR/issue-62504.rs:18:21 | LL | ArrayHolder([0; Self::SIZE]) | ^^^^^^^^^^^^^^^ expected `X`, found `Self::SIZE` @@ -8,7 +8,7 @@ LL | ArrayHolder([0; Self::SIZE]) found array `[u32; _]` error: constant expression depends on a generic parameter - --> $DIR/issue-62504.rs:19:25 + --> $DIR/issue-62504.rs:18:25 | LL | ArrayHolder([0; Self::SIZE]) | ^^^^^^^^^^ diff --git a/src/test/ui/const-generics/issues/issue-62504.rs b/src/test/ui/const-generics/issues/issue-62504.rs index 5630962ff53..0b95754cab4 100644 --- a/src/test/ui/const-generics/issues/issue-62504.rs +++ b/src/test/ui/const-generics/issues/issue-62504.rs @@ -2,7 +2,6 @@ #![allow(incomplete_features)] #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] trait HasSize { const SIZE: usize; diff --git a/src/test/ui/const-generics/issues/issue-62579-no-match.min.stderr b/src/test/ui/const-generics/issues/issue-62579-no-match.min.stderr index 5117e20d626..a0aee4821c6 100644 --- a/src/test/ui/const-generics/issues/issue-62579-no-match.min.stderr +++ b/src/test/ui/const-generics/issues/issue-62579-no-match.min.stderr @@ -1,5 +1,5 @@ error: `NoMatch` is forbidden as the type of a const generic parameter - --> $DIR/issue-62579-no-match.rs:10:17 + --> $DIR/issue-62579-no-match.rs:9:17 | LL | fn foo() -> bool { | ^^^^^^^ diff --git a/src/test/ui/const-generics/issues/issue-62579-no-match.rs b/src/test/ui/const-generics/issues/issue-62579-no-match.rs index c9853aa9162..46813f5256e 100644 --- a/src/test/ui/const-generics/issues/issue-62579-no-match.rs +++ b/src/test/ui/const-generics/issues/issue-62579-no-match.rs @@ -2,7 +2,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] #[derive(PartialEq, Eq)] struct NoMatch; diff --git a/src/test/ui/const-generics/issues/issue-62878.full.stderr b/src/test/ui/const-generics/issues/issue-62878.full.stderr index dce2e27c71a..6e6aa196633 100644 --- a/src/test/ui/const-generics/issues/issue-62878.full.stderr +++ b/src/test/ui/const-generics/issues/issue-62878.full.stderr @@ -1,11 +1,11 @@ error[E0770]: the type of const parameters must not depend on other generic parameters - --> $DIR/issue-62878.rs:6:38 + --> $DIR/issue-62878.rs:5:38 | LL | fn foo() {} | ^ the type must not depend on the parameter `N` error[E0747]: type provided when a constant was expected - --> $DIR/issue-62878.rs:11:11 + --> $DIR/issue-62878.rs:10:11 | LL | foo::<_, {[1]}>(); | ^ @@ -13,7 +13,7 @@ LL | foo::<_, {[1]}>(); = help: const arguments cannot yet be inferred with `_` error[E0308]: mismatched types - --> $DIR/issue-62878.rs:11:15 + --> $DIR/issue-62878.rs:10:15 | LL | foo::<_, {[1]}>(); | ^^^ expected `usize`, found array `[{integer}; 1]` diff --git a/src/test/ui/const-generics/issues/issue-62878.min.stderr b/src/test/ui/const-generics/issues/issue-62878.min.stderr index 9f95e5d8862..920d7e43b9b 100644 --- a/src/test/ui/const-generics/issues/issue-62878.min.stderr +++ b/src/test/ui/const-generics/issues/issue-62878.min.stderr @@ -1,11 +1,11 @@ error[E0770]: the type of const parameters must not depend on other generic parameters - --> $DIR/issue-62878.rs:6:38 + --> $DIR/issue-62878.rs:5:38 | LL | fn foo() {} | ^ the type must not depend on the parameter `N` error: `[u8; _]` is forbidden as the type of a const generic parameter - --> $DIR/issue-62878.rs:6:33 + --> $DIR/issue-62878.rs:5:33 | LL | fn foo() {} | ^^^^^^^ diff --git a/src/test/ui/const-generics/issues/issue-62878.rs b/src/test/ui/const-generics/issues/issue-62878.rs index c087711e5f9..a70606c4a7d 100644 --- a/src/test/ui/const-generics/issues/issue-62878.rs +++ b/src/test/ui/const-generics/issues/issue-62878.rs @@ -1,7 +1,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] fn foo() {} //~^ ERROR the type of const parameters must not diff --git a/src/test/ui/const-generics/issues/issue-63322-forbid-dyn.full.stderr b/src/test/ui/const-generics/issues/issue-63322-forbid-dyn.full.stderr index a20c7264acf..e1c20e6ae78 100644 --- a/src/test/ui/const-generics/issues/issue-63322-forbid-dyn.full.stderr +++ b/src/test/ui/const-generics/issues/issue-63322-forbid-dyn.full.stderr @@ -1,5 +1,5 @@ error[E0741]: `&'static (dyn A + 'static)` must be annotated with `#[derive(PartialEq, Eq)]` to be used as the type of a const parameter - --> $DIR/issue-63322-forbid-dyn.rs:10:18 + --> $DIR/issue-63322-forbid-dyn.rs:9:18 | LL | fn test() { | ^^^^^^^^^^^^^^ `&'static (dyn A + 'static)` doesn't derive both `PartialEq` and `Eq` diff --git a/src/test/ui/const-generics/issues/issue-63322-forbid-dyn.min.stderr b/src/test/ui/const-generics/issues/issue-63322-forbid-dyn.min.stderr index 5dbfdc6d652..543e4b29a16 100644 --- a/src/test/ui/const-generics/issues/issue-63322-forbid-dyn.min.stderr +++ b/src/test/ui/const-generics/issues/issue-63322-forbid-dyn.min.stderr @@ -1,5 +1,5 @@ error: `&'static (dyn A + 'static)` is forbidden as the type of a const generic parameter - --> $DIR/issue-63322-forbid-dyn.rs:10:18 + --> $DIR/issue-63322-forbid-dyn.rs:9:18 | LL | fn test() { | ^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | fn test() { = help: more complex types are supported with `#[feature(const_generics)]` error[E0741]: `&'static (dyn A + 'static)` must be annotated with `#[derive(PartialEq, Eq)]` to be used as the type of a const parameter - --> $DIR/issue-63322-forbid-dyn.rs:10:18 + --> $DIR/issue-63322-forbid-dyn.rs:9:18 | LL | fn test() { | ^^^^^^^^^^^^^^ `&'static (dyn A + 'static)` doesn't derive both `PartialEq` and `Eq` diff --git a/src/test/ui/const-generics/issues/issue-63322-forbid-dyn.rs b/src/test/ui/const-generics/issues/issue-63322-forbid-dyn.rs index 2194eb97a41..334e2aac02a 100644 --- a/src/test/ui/const-generics/issues/issue-63322-forbid-dyn.rs +++ b/src/test/ui/const-generics/issues/issue-63322-forbid-dyn.rs @@ -1,7 +1,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] trait A {} struct B; diff --git a/src/test/ui/const-generics/issues/issue-64494.full.stderr b/src/test/ui/const-generics/issues/issue-64494.full.stderr index a97ec9308f8..abb26d6cf17 100644 --- a/src/test/ui/const-generics/issues/issue-64494.full.stderr +++ b/src/test/ui/const-generics/issues/issue-64494.full.stderr @@ -1,5 +1,5 @@ error: constant expression depends on a generic parameter - --> $DIR/issue-64494.rs:16:53 + --> $DIR/issue-64494.rs:15:53 | LL | impl MyTrait for T where Is<{T::VAL == 5}>: True {} | ^^^^ @@ -7,7 +7,7 @@ LL | impl MyTrait for T where Is<{T::VAL == 5}>: True {} = note: this may fail depending on what value the parameter takes error: constant expression depends on a generic parameter - --> $DIR/issue-64494.rs:19:53 + --> $DIR/issue-64494.rs:18:53 | LL | impl MyTrait for T where Is<{T::VAL == 6}>: True {} | ^^^^ diff --git a/src/test/ui/const-generics/issues/issue-64494.min.stderr b/src/test/ui/const-generics/issues/issue-64494.min.stderr index 681166b1d2b..936ab7f6e7e 100644 --- a/src/test/ui/const-generics/issues/issue-64494.min.stderr +++ b/src/test/ui/const-generics/issues/issue-64494.min.stderr @@ -1,5 +1,5 @@ error: generic parameters may not be used in const operations - --> $DIR/issue-64494.rs:16:38 + --> $DIR/issue-64494.rs:15:38 | LL | impl MyTrait for T where Is<{T::VAL == 5}>: True {} | ^^^^^^ cannot perform const operation using `T` @@ -8,7 +8,7 @@ LL | impl MyTrait for T where Is<{T::VAL == 5}>: True {} = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: generic parameters may not be used in const operations - --> $DIR/issue-64494.rs:19:38 + --> $DIR/issue-64494.rs:18:38 | LL | impl MyTrait for T where Is<{T::VAL == 6}>: True {} | ^^^^^^ cannot perform const operation using `T` @@ -17,7 +17,7 @@ LL | impl MyTrait for T where Is<{T::VAL == 6}>: True {} = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error[E0119]: conflicting implementations of trait `MyTrait`: - --> $DIR/issue-64494.rs:19:1 + --> $DIR/issue-64494.rs:18:1 | LL | impl MyTrait for T where Is<{T::VAL == 5}>: True {} | ------------------------------------ first implementation here diff --git a/src/test/ui/const-generics/issues/issue-64494.rs b/src/test/ui/const-generics/issues/issue-64494.rs index 014742be03d..96d19203109 100644 --- a/src/test/ui/const-generics/issues/issue-64494.rs +++ b/src/test/ui/const-generics/issues/issue-64494.rs @@ -1,7 +1,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] trait Foo { const VAL: usize; diff --git a/src/test/ui/const-generics/issues/issue-64519.rs b/src/test/ui/const-generics/issues/issue-64519.rs index 1ca709d0975..8c603b74b90 100644 --- a/src/test/ui/const-generics/issues/issue-64519.rs +++ b/src/test/ui/const-generics/issues/issue-64519.rs @@ -2,7 +2,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] struct Foo { state: Option<[u8; D]>, diff --git a/src/test/ui/const-generics/issues/issue-66205.full.stderr b/src/test/ui/const-generics/issues/issue-66205.full.stderr index a1520912e4e..7e150f5f6db 100644 --- a/src/test/ui/const-generics/issues/issue-66205.full.stderr +++ b/src/test/ui/const-generics/issues/issue-66205.full.stderr @@ -1,5 +1,5 @@ error: constant expression depends on a generic parameter - --> $DIR/issue-66205.rs:8:12 + --> $DIR/issue-66205.rs:7:12 | LL | fact::<{ N - 1 }>(); | ^^^^^^^^^ diff --git a/src/test/ui/const-generics/issues/issue-66205.min.stderr b/src/test/ui/const-generics/issues/issue-66205.min.stderr index ecd96ac37e4..b41793b62d2 100644 --- a/src/test/ui/const-generics/issues/issue-66205.min.stderr +++ b/src/test/ui/const-generics/issues/issue-66205.min.stderr @@ -1,5 +1,5 @@ error: generic parameters may not be used in const operations - --> $DIR/issue-66205.rs:8:14 + --> $DIR/issue-66205.rs:7:14 | LL | fact::<{ N - 1 }>(); | ^ cannot perform const operation using `N` diff --git a/src/test/ui/const-generics/issues/issue-66205.rs b/src/test/ui/const-generics/issues/issue-66205.rs index 4e37c247d00..14249b62cee 100644 --- a/src/test/ui/const-generics/issues/issue-66205.rs +++ b/src/test/ui/const-generics/issues/issue-66205.rs @@ -1,7 +1,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] #![allow(dead_code, unconditional_recursion)] fn fact() { diff --git a/src/test/ui/const-generics/issues/issue-66906.rs b/src/test/ui/const-generics/issues/issue-66906.rs index 3e048593c9b..a871b118dcc 100644 --- a/src/test/ui/const-generics/issues/issue-66906.rs +++ b/src/test/ui/const-generics/issues/issue-66906.rs @@ -2,7 +2,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] pub struct Tuple; diff --git a/src/test/ui/const-generics/issues/issue-67185-1.rs b/src/test/ui/const-generics/issues/issue-67185-1.rs index 09d88ef89a3..ed35a5f7c0a 100644 --- a/src/test/ui/const-generics/issues/issue-67185-1.rs +++ b/src/test/ui/const-generics/issues/issue-67185-1.rs @@ -2,7 +2,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] trait Baz { type Quaks; diff --git a/src/test/ui/const-generics/issues/issue-67185-2.full.stderr b/src/test/ui/const-generics/issues/issue-67185-2.full.stderr index 78c7ebff059..fa9c680d4b8 100644 --- a/src/test/ui/const-generics/issues/issue-67185-2.full.stderr +++ b/src/test/ui/const-generics/issues/issue-67185-2.full.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `[u16; 3]: Bar` is not satisfied - --> $DIR/issue-67185-2.rs:17:1 + --> $DIR/issue-67185-2.rs:16:1 | LL | / trait Foo LL | | @@ -17,7 +17,7 @@ LL | | } = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable error[E0277]: the trait bound `[[u16; 3]; 2]: Bar` is not satisfied - --> $DIR/issue-67185-2.rs:17:1 + --> $DIR/issue-67185-2.rs:16:1 | LL | / trait Foo LL | | @@ -35,7 +35,7 @@ LL | | } = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable error[E0277]: the trait bound `[u16; 3]: Bar` is not satisfied - --> $DIR/issue-67185-2.rs:27:6 + --> $DIR/issue-67185-2.rs:26:6 | LL | trait Foo | --- required by a bound in this @@ -51,7 +51,7 @@ LL | impl Foo for FooImpl {} <[u16; 4] as Bar> error[E0277]: the trait bound `[[u16; 3]; 2]: Bar` is not satisfied - --> $DIR/issue-67185-2.rs:27:6 + --> $DIR/issue-67185-2.rs:26:6 | LL | trait Foo | --- required by a bound in this @@ -67,7 +67,7 @@ LL | impl Foo for FooImpl {} <[u16; 4] as Bar> error[E0277]: the trait bound `[[u16; 3]; 2]: Bar` is not satisfied - --> $DIR/issue-67185-2.rs:31:14 + --> $DIR/issue-67185-2.rs:30:14 | LL | trait Foo | --- required by a bound in this @@ -83,7 +83,7 @@ LL | fn f(_: impl Foo) {} <[u16; 4] as Bar> error[E0277]: the trait bound `[u16; 3]: Bar` is not satisfied - --> $DIR/issue-67185-2.rs:31:14 + --> $DIR/issue-67185-2.rs:30:14 | LL | trait Foo | --- required by a bound in this diff --git a/src/test/ui/const-generics/issues/issue-67185-2.min.stderr b/src/test/ui/const-generics/issues/issue-67185-2.min.stderr index 78c7ebff059..fa9c680d4b8 100644 --- a/src/test/ui/const-generics/issues/issue-67185-2.min.stderr +++ b/src/test/ui/const-generics/issues/issue-67185-2.min.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `[u16; 3]: Bar` is not satisfied - --> $DIR/issue-67185-2.rs:17:1 + --> $DIR/issue-67185-2.rs:16:1 | LL | / trait Foo LL | | @@ -17,7 +17,7 @@ LL | | } = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable error[E0277]: the trait bound `[[u16; 3]; 2]: Bar` is not satisfied - --> $DIR/issue-67185-2.rs:17:1 + --> $DIR/issue-67185-2.rs:16:1 | LL | / trait Foo LL | | @@ -35,7 +35,7 @@ LL | | } = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable error[E0277]: the trait bound `[u16; 3]: Bar` is not satisfied - --> $DIR/issue-67185-2.rs:27:6 + --> $DIR/issue-67185-2.rs:26:6 | LL | trait Foo | --- required by a bound in this @@ -51,7 +51,7 @@ LL | impl Foo for FooImpl {} <[u16; 4] as Bar> error[E0277]: the trait bound `[[u16; 3]; 2]: Bar` is not satisfied - --> $DIR/issue-67185-2.rs:27:6 + --> $DIR/issue-67185-2.rs:26:6 | LL | trait Foo | --- required by a bound in this @@ -67,7 +67,7 @@ LL | impl Foo for FooImpl {} <[u16; 4] as Bar> error[E0277]: the trait bound `[[u16; 3]; 2]: Bar` is not satisfied - --> $DIR/issue-67185-2.rs:31:14 + --> $DIR/issue-67185-2.rs:30:14 | LL | trait Foo | --- required by a bound in this @@ -83,7 +83,7 @@ LL | fn f(_: impl Foo) {} <[u16; 4] as Bar> error[E0277]: the trait bound `[u16; 3]: Bar` is not satisfied - --> $DIR/issue-67185-2.rs:31:14 + --> $DIR/issue-67185-2.rs:30:14 | LL | trait Foo | --- required by a bound in this diff --git a/src/test/ui/const-generics/issues/issue-67185-2.rs b/src/test/ui/const-generics/issues/issue-67185-2.rs index 1176d0c6904..94a713d7cf9 100644 --- a/src/test/ui/const-generics/issues/issue-67185-2.rs +++ b/src/test/ui/const-generics/issues/issue-67185-2.rs @@ -1,7 +1,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] trait Baz { type Quaks; diff --git a/src/test/ui/const-generics/issues/issue-67739.full.stderr b/src/test/ui/const-generics/issues/issue-67739.full.stderr index 27a56b8eb02..dcbe5b94a62 100644 --- a/src/test/ui/const-generics/issues/issue-67739.full.stderr +++ b/src/test/ui/const-generics/issues/issue-67739.full.stderr @@ -1,5 +1,5 @@ error: constant expression depends on a generic parameter - --> $DIR/issue-67739.rs:12:15 + --> $DIR/issue-67739.rs:11:15 | LL | [0u8; mem::size_of::()]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/const-generics/issues/issue-67739.min.stderr b/src/test/ui/const-generics/issues/issue-67739.min.stderr index 27a56b8eb02..dcbe5b94a62 100644 --- a/src/test/ui/const-generics/issues/issue-67739.min.stderr +++ b/src/test/ui/const-generics/issues/issue-67739.min.stderr @@ -1,5 +1,5 @@ error: constant expression depends on a generic parameter - --> $DIR/issue-67739.rs:12:15 + --> $DIR/issue-67739.rs:11:15 | LL | [0u8; mem::size_of::()]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/const-generics/issues/issue-67739.rs b/src/test/ui/const-generics/issues/issue-67739.rs index 0f5860f22fd..e4960e56c9e 100644 --- a/src/test/ui/const-generics/issues/issue-67739.rs +++ b/src/test/ui/const-generics/issues/issue-67739.rs @@ -1,7 +1,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] use std::mem; diff --git a/src/test/ui/const-generics/issues/issue-68366.full.stderr b/src/test/ui/const-generics/issues/issue-68366.full.stderr index ac774f50c74..4015fb090b9 100644 --- a/src/test/ui/const-generics/issues/issue-68366.full.stderr +++ b/src/test/ui/const-generics/issues/issue-68366.full.stderr @@ -1,5 +1,5 @@ error[E0207]: the const parameter `N` is not constrained by the impl trait, self type, or predicates - --> $DIR/issue-68366.rs:12:13 + --> $DIR/issue-68366.rs:11:13 | LL | impl Collatz<{Some(N)}> {} | ^ unconstrained const parameter @@ -8,7 +8,7 @@ LL | impl Collatz<{Some(N)}> {} = note: proving the result of expressions other than the parameter are unique is not supported error[E0207]: the const parameter `N` is not constrained by the impl trait, self type, or predicates - --> $DIR/issue-68366.rs:18:12 + --> $DIR/issue-68366.rs:17:12 | LL | impl Foo {} | ^ unconstrained const parameter diff --git a/src/test/ui/const-generics/issues/issue-68366.min.stderr b/src/test/ui/const-generics/issues/issue-68366.min.stderr index acaf4a33ee0..da4cbd3081f 100644 --- a/src/test/ui/const-generics/issues/issue-68366.min.stderr +++ b/src/test/ui/const-generics/issues/issue-68366.min.stderr @@ -1,5 +1,5 @@ error: generic parameters may not be used in const operations - --> $DIR/issue-68366.rs:12:37 + --> $DIR/issue-68366.rs:11:37 | LL | impl Collatz<{Some(N)}> {} | ^ cannot perform const operation using `N` @@ -8,7 +8,7 @@ LL | impl Collatz<{Some(N)}> {} = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error[E0207]: the const parameter `N` is not constrained by the impl trait, self type, or predicates - --> $DIR/issue-68366.rs:12:13 + --> $DIR/issue-68366.rs:11:13 | LL | impl Collatz<{Some(N)}> {} | ^ unconstrained const parameter @@ -17,7 +17,7 @@ LL | impl Collatz<{Some(N)}> {} = note: proving the result of expressions other than the parameter are unique is not supported error[E0207]: the const parameter `N` is not constrained by the impl trait, self type, or predicates - --> $DIR/issue-68366.rs:18:12 + --> $DIR/issue-68366.rs:17:12 | LL | impl Foo {} | ^ unconstrained const parameter diff --git a/src/test/ui/const-generics/issues/issue-68366.rs b/src/test/ui/const-generics/issues/issue-68366.rs index 474cdb7258d..37afed62327 100644 --- a/src/test/ui/const-generics/issues/issue-68366.rs +++ b/src/test/ui/const-generics/issues/issue-68366.rs @@ -5,7 +5,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] struct Collatz>; diff --git a/src/test/ui/const-generics/issues/issue-68596.rs b/src/test/ui/const-generics/issues/issue-68596.rs index 3b27d4d68c5..0bb23be1eb4 100644 --- a/src/test/ui/const-generics/issues/issue-68596.rs +++ b/src/test/ui/const-generics/issues/issue-68596.rs @@ -2,7 +2,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] pub struct S(u8); diff --git a/src/test/ui/const-generics/issues/issue-68615-adt.min.stderr b/src/test/ui/const-generics/issues/issue-68615-adt.min.stderr index 59653114a6b..2de8ada2766 100644 --- a/src/test/ui/const-generics/issues/issue-68615-adt.min.stderr +++ b/src/test/ui/const-generics/issues/issue-68615-adt.min.stderr @@ -1,5 +1,5 @@ error: `[usize; 0]` is forbidden as the type of a const generic parameter - --> $DIR/issue-68615-adt.rs:7:23 + --> $DIR/issue-68615-adt.rs:6:23 | LL | struct Const {} | ^^^^^^^^^^ diff --git a/src/test/ui/const-generics/issues/issue-68615-adt.rs b/src/test/ui/const-generics/issues/issue-68615-adt.rs index d616f3ab95a..ddea3e8ab65 100644 --- a/src/test/ui/const-generics/issues/issue-68615-adt.rs +++ b/src/test/ui/const-generics/issues/issue-68615-adt.rs @@ -2,7 +2,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] struct Const {} //[min]~^ ERROR `[usize; 0]` is forbidden as the type of a const generic parameter diff --git a/src/test/ui/const-generics/issues/issue-68615-array.min.stderr b/src/test/ui/const-generics/issues/issue-68615-array.min.stderr index 1ee881b96ec..0d17b04a5cd 100644 --- a/src/test/ui/const-generics/issues/issue-68615-array.min.stderr +++ b/src/test/ui/const-generics/issues/issue-68615-array.min.stderr @@ -1,5 +1,5 @@ error: `[usize; 0]` is forbidden as the type of a const generic parameter - --> $DIR/issue-68615-array.rs:7:21 + --> $DIR/issue-68615-array.rs:6:21 | LL | struct Foo {} | ^^^^^^^^^^ diff --git a/src/test/ui/const-generics/issues/issue-68615-array.rs b/src/test/ui/const-generics/issues/issue-68615-array.rs index 24c9a59a185..56afd9b2a15 100644 --- a/src/test/ui/const-generics/issues/issue-68615-array.rs +++ b/src/test/ui/const-generics/issues/issue-68615-array.rs @@ -2,7 +2,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] struct Foo {} //[min]~^ ERROR `[usize; 0]` is forbidden as the type of a const generic parameter diff --git a/src/test/ui/const-generics/issues/issue-68977.full.stderr b/src/test/ui/const-generics/issues/issue-68977.full.stderr index 3690bac3eb3..25dcd88a4af 100644 --- a/src/test/ui/const-generics/issues/issue-68977.full.stderr +++ b/src/test/ui/const-generics/issues/issue-68977.full.stderr @@ -1,5 +1,5 @@ error: constant expression depends on a generic parameter - --> $DIR/issue-68977.rs:35:44 + --> $DIR/issue-68977.rs:34:44 | LL | FxpStorageHelper: FxpStorage, | ^^^^^^^^^^ diff --git a/src/test/ui/const-generics/issues/issue-68977.min.stderr b/src/test/ui/const-generics/issues/issue-68977.min.stderr index ea91df1e0bf..0b3d5b9a760 100644 --- a/src/test/ui/const-generics/issues/issue-68977.min.stderr +++ b/src/test/ui/const-generics/issues/issue-68977.min.stderr @@ -1,5 +1,5 @@ error: generic parameters may not be used in const operations - --> $DIR/issue-68977.rs:29:17 + --> $DIR/issue-68977.rs:28:17 | LL | PhantomU8<{(INT_BITS + FRAC_BITS + 7) / 8}>; | ^^^^^^^^ cannot perform const operation using `INT_BITS` @@ -8,7 +8,7 @@ LL | PhantomU8<{(INT_BITS + FRAC_BITS + 7) / 8}>; = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: generic parameters may not be used in const operations - --> $DIR/issue-68977.rs:29:28 + --> $DIR/issue-68977.rs:28:28 | LL | PhantomU8<{(INT_BITS + FRAC_BITS + 7) / 8}>; | ^^^^^^^^^ cannot perform const operation using `FRAC_BITS` diff --git a/src/test/ui/const-generics/issues/issue-68977.rs b/src/test/ui/const-generics/issues/issue-68977.rs index 4fea94cb465..a0ffcc84c7a 100644 --- a/src/test/ui/const-generics/issues/issue-68977.rs +++ b/src/test/ui/const-generics/issues/issue-68977.rs @@ -1,7 +1,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] struct PhantomU8; diff --git a/src/test/ui/const-generics/issues/issue-70125-1.rs b/src/test/ui/const-generics/issues/issue-70125-1.rs index 04175089dc0..5c118d245a1 100644 --- a/src/test/ui/const-generics/issues/issue-70125-1.rs +++ b/src/test/ui/const-generics/issues/issue-70125-1.rs @@ -2,7 +2,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] const L: usize = 4; diff --git a/src/test/ui/const-generics/issues/issue-70125-2.rs b/src/test/ui/const-generics/issues/issue-70125-2.rs index ceefc2dcb32..f82131262d6 100644 --- a/src/test/ui/const-generics/issues/issue-70125-2.rs +++ b/src/test/ui/const-generics/issues/issue-70125-2.rs @@ -2,7 +2,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] fn main() { <()>::foo(); diff --git a/src/test/ui/const-generics/issues/issue-70167.rs b/src/test/ui/const-generics/issues/issue-70167.rs index 04c76a4dcaf..9e912b69177 100644 --- a/src/test/ui/const-generics/issues/issue-70167.rs +++ b/src/test/ui/const-generics/issues/issue-70167.rs @@ -2,7 +2,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] pub trait Trait: From<>::Item> { type Item; diff --git a/src/test/ui/const-generics/issues/issue-71169.full.stderr b/src/test/ui/const-generics/issues/issue-71169.full.stderr index b87825d20ce..7b1a2f98dfe 100644 --- a/src/test/ui/const-generics/issues/issue-71169.full.stderr +++ b/src/test/ui/const-generics/issues/issue-71169.full.stderr @@ -1,11 +1,11 @@ error[E0770]: the type of const parameters must not depend on other generic parameters - --> $DIR/issue-71169.rs:6:43 + --> $DIR/issue-71169.rs:5:43 | LL | fn foo() {} | ^^^ the type must not depend on the parameter `LEN` error: constant expression depends on a generic parameter - --> $DIR/issue-71169.rs:11:14 + --> $DIR/issue-71169.rs:10:14 | LL | foo::<4, DATA>(); | ^^^^ diff --git a/src/test/ui/const-generics/issues/issue-71169.min.stderr b/src/test/ui/const-generics/issues/issue-71169.min.stderr index 9b0a2946ca6..68ac47460b3 100644 --- a/src/test/ui/const-generics/issues/issue-71169.min.stderr +++ b/src/test/ui/const-generics/issues/issue-71169.min.stderr @@ -1,11 +1,11 @@ error[E0770]: the type of const parameters must not depend on other generic parameters - --> $DIR/issue-71169.rs:6:43 + --> $DIR/issue-71169.rs:5:43 | LL | fn foo() {} | ^^^ the type must not depend on the parameter `LEN` error: `[u8; _]` is forbidden as the type of a const generic parameter - --> $DIR/issue-71169.rs:6:38 + --> $DIR/issue-71169.rs:5:38 | LL | fn foo() {} | ^^^^^^^^^ diff --git a/src/test/ui/const-generics/issues/issue-71169.rs b/src/test/ui/const-generics/issues/issue-71169.rs index 7007ec222ca..a574da4b6b3 100644 --- a/src/test/ui/const-generics/issues/issue-71169.rs +++ b/src/test/ui/const-generics/issues/issue-71169.rs @@ -1,7 +1,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] fn foo() {} //~^ ERROR the type of const parameters must not diff --git a/src/test/ui/const-generics/issues/issue-71381.full.stderr b/src/test/ui/const-generics/issues/issue-71381.full.stderr index 453ef00e6dc..3950317b370 100644 --- a/src/test/ui/const-generics/issues/issue-71381.full.stderr +++ b/src/test/ui/const-generics/issues/issue-71381.full.stderr @@ -1,23 +1,23 @@ error[E0770]: the type of const parameters must not depend on other generic parameters - --> $DIR/issue-71381.rs:15:82 + --> $DIR/issue-71381.rs:14:82 | LL | pub fn call_me(&self) { | ^^^^ the type must not depend on the parameter `Args` error[E0770]: the type of const parameters must not depend on other generic parameters - --> $DIR/issue-71381.rs:24:40 + --> $DIR/issue-71381.rs:23:40 | LL | const FN: unsafe extern "C" fn(Args), | ^^^^ the type must not depend on the parameter `Args` error: using function pointers as const generic parameters is forbidden - --> $DIR/issue-71381.rs:15:61 + --> $DIR/issue-71381.rs:14:61 | LL | pub fn call_me(&self) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: using function pointers as const generic parameters is forbidden - --> $DIR/issue-71381.rs:24:19 + --> $DIR/issue-71381.rs:23:19 | LL | const FN: unsafe extern "C" fn(Args), | ^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/const-generics/issues/issue-71381.min.stderr b/src/test/ui/const-generics/issues/issue-71381.min.stderr index 453ef00e6dc..3950317b370 100644 --- a/src/test/ui/const-generics/issues/issue-71381.min.stderr +++ b/src/test/ui/const-generics/issues/issue-71381.min.stderr @@ -1,23 +1,23 @@ error[E0770]: the type of const parameters must not depend on other generic parameters - --> $DIR/issue-71381.rs:15:82 + --> $DIR/issue-71381.rs:14:82 | LL | pub fn call_me(&self) { | ^^^^ the type must not depend on the parameter `Args` error[E0770]: the type of const parameters must not depend on other generic parameters - --> $DIR/issue-71381.rs:24:40 + --> $DIR/issue-71381.rs:23:40 | LL | const FN: unsafe extern "C" fn(Args), | ^^^^ the type must not depend on the parameter `Args` error: using function pointers as const generic parameters is forbidden - --> $DIR/issue-71381.rs:15:61 + --> $DIR/issue-71381.rs:14:61 | LL | pub fn call_me(&self) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: using function pointers as const generic parameters is forbidden - --> $DIR/issue-71381.rs:24:19 + --> $DIR/issue-71381.rs:23:19 | LL | const FN: unsafe extern "C" fn(Args), | ^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/const-generics/issues/issue-71381.rs b/src/test/ui/const-generics/issues/issue-71381.rs index 65d88e553b9..f015d694695 100644 --- a/src/test/ui/const-generics/issues/issue-71381.rs +++ b/src/test/ui/const-generics/issues/issue-71381.rs @@ -1,7 +1,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] struct Test(*const usize); diff --git a/src/test/ui/const-generics/issues/issue-71382.full.stderr b/src/test/ui/const-generics/issues/issue-71382.full.stderr index 3da85ee040d..715037bd5f1 100644 --- a/src/test/ui/const-generics/issues/issue-71382.full.stderr +++ b/src/test/ui/const-generics/issues/issue-71382.full.stderr @@ -1,5 +1,5 @@ error: using function pointers as const generic parameters is forbidden - --> $DIR/issue-71382.rs:17:23 + --> $DIR/issue-71382.rs:16:23 | LL | fn test(&self) { | ^^^^ diff --git a/src/test/ui/const-generics/issues/issue-71382.min.stderr b/src/test/ui/const-generics/issues/issue-71382.min.stderr index 3da85ee040d..715037bd5f1 100644 --- a/src/test/ui/const-generics/issues/issue-71382.min.stderr +++ b/src/test/ui/const-generics/issues/issue-71382.min.stderr @@ -1,5 +1,5 @@ error: using function pointers as const generic parameters is forbidden - --> $DIR/issue-71382.rs:17:23 + --> $DIR/issue-71382.rs:16:23 | LL | fn test(&self) { | ^^^^ diff --git a/src/test/ui/const-generics/issues/issue-71382.rs b/src/test/ui/const-generics/issues/issue-71382.rs index 12a7d08382a..3a56db937de 100644 --- a/src/test/ui/const-generics/issues/issue-71382.rs +++ b/src/test/ui/const-generics/issues/issue-71382.rs @@ -1,7 +1,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] struct Test(); diff --git a/src/test/ui/const-generics/issues/issue-71611.full.stderr b/src/test/ui/const-generics/issues/issue-71611.full.stderr index 48d4bb361a1..01a85b745ce 100644 --- a/src/test/ui/const-generics/issues/issue-71611.full.stderr +++ b/src/test/ui/const-generics/issues/issue-71611.full.stderr @@ -1,11 +1,11 @@ error[E0770]: the type of const parameters must not depend on other generic parameters - --> $DIR/issue-71611.rs:6:31 + --> $DIR/issue-71611.rs:5:31 | LL | fn func(outer: A) { | ^ the type must not depend on the parameter `A` error: using function pointers as const generic parameters is forbidden - --> $DIR/issue-71611.rs:6:21 + --> $DIR/issue-71611.rs:5:21 | LL | fn func(outer: A) { | ^^^^^^^^^^^^ diff --git a/src/test/ui/const-generics/issues/issue-71611.min.stderr b/src/test/ui/const-generics/issues/issue-71611.min.stderr index 48d4bb361a1..01a85b745ce 100644 --- a/src/test/ui/const-generics/issues/issue-71611.min.stderr +++ b/src/test/ui/const-generics/issues/issue-71611.min.stderr @@ -1,11 +1,11 @@ error[E0770]: the type of const parameters must not depend on other generic parameters - --> $DIR/issue-71611.rs:6:31 + --> $DIR/issue-71611.rs:5:31 | LL | fn func(outer: A) { | ^ the type must not depend on the parameter `A` error: using function pointers as const generic parameters is forbidden - --> $DIR/issue-71611.rs:6:21 + --> $DIR/issue-71611.rs:5:21 | LL | fn func(outer: A) { | ^^^^^^^^^^^^ diff --git a/src/test/ui/const-generics/issues/issue-71611.rs b/src/test/ui/const-generics/issues/issue-71611.rs index 9b8e8be6bc6..6468d0b6bda 100644 --- a/src/test/ui/const-generics/issues/issue-71611.rs +++ b/src/test/ui/const-generics/issues/issue-71611.rs @@ -1,7 +1,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] fn func(outer: A) { //~^ ERROR: using function pointers as const generic parameters is forbidden diff --git a/src/test/ui/const-generics/issues/issue-72352.full.stderr b/src/test/ui/const-generics/issues/issue-72352.full.stderr index 51f94678467..eedd73c4dcc 100644 --- a/src/test/ui/const-generics/issues/issue-72352.full.stderr +++ b/src/test/ui/const-generics/issues/issue-72352.full.stderr @@ -1,5 +1,5 @@ error: using function pointers as const generic parameters is forbidden - --> $DIR/issue-72352.rs:8:42 + --> $DIR/issue-72352.rs:7:42 | LL | unsafe fn unsafely_do_the_thing usize>(ptr: *const i8) -> usize { | ^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/const-generics/issues/issue-72352.min.stderr b/src/test/ui/const-generics/issues/issue-72352.min.stderr index 51f94678467..eedd73c4dcc 100644 --- a/src/test/ui/const-generics/issues/issue-72352.min.stderr +++ b/src/test/ui/const-generics/issues/issue-72352.min.stderr @@ -1,5 +1,5 @@ error: using function pointers as const generic parameters is forbidden - --> $DIR/issue-72352.rs:8:42 + --> $DIR/issue-72352.rs:7:42 | LL | unsafe fn unsafely_do_the_thing usize>(ptr: *const i8) -> usize { | ^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/const-generics/issues/issue-72352.rs b/src/test/ui/const-generics/issues/issue-72352.rs index 1517f3dae4f..9cd95c11026 100644 --- a/src/test/ui/const-generics/issues/issue-72352.rs +++ b/src/test/ui/const-generics/issues/issue-72352.rs @@ -1,7 +1,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] use std::ffi::{CStr, CString}; diff --git a/src/test/ui/const-generics/issues/issue-72787.full.stderr b/src/test/ui/const-generics/issues/issue-72787.full.stderr index b4c79d4171b..fbb7ae59bef 100644 --- a/src/test/ui/const-generics/issues/issue-72787.full.stderr +++ b/src/test/ui/const-generics/issues/issue-72787.full.stderr @@ -1,5 +1,5 @@ error: constant expression depends on a generic parameter - --> $DIR/issue-72787.rs:11:32 + --> $DIR/issue-72787.rs:10:32 | LL | Condition<{ LHS <= RHS }>: True | ^^^^ @@ -7,7 +7,7 @@ LL | Condition<{ LHS <= RHS }>: True = note: this may fail depending on what value the parameter takes error: constant expression depends on a generic parameter - --> $DIR/issue-72787.rs:26:42 + --> $DIR/issue-72787.rs:25:42 | LL | IsLessOrEqual<{ 8 - I }, { 8 - J }>: True, | ^^^^ @@ -15,7 +15,7 @@ LL | IsLessOrEqual<{ 8 - I }, { 8 - J }>: True, = note: this may fail depending on what value the parameter takes error: constant expression depends on a generic parameter - --> $DIR/issue-72787.rs:26:42 + --> $DIR/issue-72787.rs:25:42 | LL | IsLessOrEqual<{ 8 - I }, { 8 - J }>: True, | ^^^^ @@ -23,7 +23,7 @@ LL | IsLessOrEqual<{ 8 - I }, { 8 - J }>: True, = note: this may fail depending on what value the parameter takes error: constant expression depends on a generic parameter - --> $DIR/issue-72787.rs:26:42 + --> $DIR/issue-72787.rs:25:42 | LL | IsLessOrEqual<{ 8 - I }, { 8 - J }>: True, | ^^^^ @@ -31,7 +31,7 @@ LL | IsLessOrEqual<{ 8 - I }, { 8 - J }>: True, = note: this may fail depending on what value the parameter takes error: constant expression depends on a generic parameter - --> $DIR/issue-72787.rs:26:42 + --> $DIR/issue-72787.rs:25:42 | LL | IsLessOrEqual<{ 8 - I }, { 8 - J }>: True, | ^^^^ diff --git a/src/test/ui/const-generics/issues/issue-72787.min.stderr b/src/test/ui/const-generics/issues/issue-72787.min.stderr index 27bbc28011f..aadf19ba6b6 100644 --- a/src/test/ui/const-generics/issues/issue-72787.min.stderr +++ b/src/test/ui/const-generics/issues/issue-72787.min.stderr @@ -1,5 +1,5 @@ error: generic parameters may not be used in const operations - --> $DIR/issue-72787.rs:11:17 + --> $DIR/issue-72787.rs:10:17 | LL | Condition<{ LHS <= RHS }>: True | ^^^ cannot perform const operation using `LHS` @@ -8,7 +8,7 @@ LL | Condition<{ LHS <= RHS }>: True = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: generic parameters may not be used in const operations - --> $DIR/issue-72787.rs:11:24 + --> $DIR/issue-72787.rs:10:24 | LL | Condition<{ LHS <= RHS }>: True | ^^^ cannot perform const operation using `RHS` @@ -17,7 +17,7 @@ LL | Condition<{ LHS <= RHS }>: True = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: generic parameters may not be used in const operations - --> $DIR/issue-72787.rs:26:25 + --> $DIR/issue-72787.rs:25:25 | LL | IsLessOrEqual<{ 8 - I }, { 8 - J }>: True, | ^ cannot perform const operation using `I` @@ -26,7 +26,7 @@ LL | IsLessOrEqual<{ 8 - I }, { 8 - J }>: True, = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: generic parameters may not be used in const operations - --> $DIR/issue-72787.rs:26:36 + --> $DIR/issue-72787.rs:25:36 | LL | IsLessOrEqual<{ 8 - I }, { 8 - J }>: True, | ^ cannot perform const operation using `J` @@ -35,7 +35,7 @@ LL | IsLessOrEqual<{ 8 - I }, { 8 - J }>: True, = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error[E0283]: type annotations needed - --> $DIR/issue-72787.rs:22:26 + --> $DIR/issue-72787.rs:21:26 | LL | pub trait True {} | -------------- required by this bound in `True` @@ -46,7 +46,7 @@ LL | IsLessOrEqual: True, = note: cannot satisfy `IsLessOrEqual: True` error[E0283]: type annotations needed - --> $DIR/issue-72787.rs:22:26 + --> $DIR/issue-72787.rs:21:26 | LL | pub trait True {} | -------------- required by this bound in `True` diff --git a/src/test/ui/const-generics/issues/issue-72787.rs b/src/test/ui/const-generics/issues/issue-72787.rs index 57572e23aa4..16bc9470470 100644 --- a/src/test/ui/const-generics/issues/issue-72787.rs +++ b/src/test/ui/const-generics/issues/issue-72787.rs @@ -1,7 +1,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] pub struct IsLessOrEqual; pub struct Condition; diff --git a/src/test/ui/const-generics/issues/issue-72819-generic-in-const-eval.full.stderr b/src/test/ui/const-generics/issues/issue-72819-generic-in-const-eval.full.stderr index b4994004721..82f9b9d346d 100644 --- a/src/test/ui/const-generics/issues/issue-72819-generic-in-const-eval.full.stderr +++ b/src/test/ui/const-generics/issues/issue-72819-generic-in-const-eval.full.stderr @@ -1,5 +1,5 @@ error: constant expression depends on a generic parameter - --> $DIR/issue-72819-generic-in-const-eval.rs:9:39 + --> $DIR/issue-72819-generic-in-const-eval.rs:8:39 | LL | where Assert::<{N < usize::MAX / 2}>: IsTrue, | ^^^^^^ diff --git a/src/test/ui/const-generics/issues/issue-72819-generic-in-const-eval.min.stderr b/src/test/ui/const-generics/issues/issue-72819-generic-in-const-eval.min.stderr index 8df3c85ec1f..6646be47b31 100644 --- a/src/test/ui/const-generics/issues/issue-72819-generic-in-const-eval.min.stderr +++ b/src/test/ui/const-generics/issues/issue-72819-generic-in-const-eval.min.stderr @@ -1,5 +1,5 @@ error: generic parameters may not be used in const operations - --> $DIR/issue-72819-generic-in-const-eval.rs:9:17 + --> $DIR/issue-72819-generic-in-const-eval.rs:8:17 | LL | where Assert::<{N < usize::MAX / 2}>: IsTrue, | ^ cannot perform const operation using `N` diff --git a/src/test/ui/const-generics/issues/issue-72819-generic-in-const-eval.rs b/src/test/ui/const-generics/issues/issue-72819-generic-in-const-eval.rs index 4c0004795f0..f612d8bd3f6 100644 --- a/src/test/ui/const-generics/issues/issue-72819-generic-in-const-eval.rs +++ b/src/test/ui/const-generics/issues/issue-72819-generic-in-const-eval.rs @@ -3,7 +3,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] struct Arr where Assert::<{N < usize::MAX / 2}>: IsTrue, diff --git a/src/test/ui/const-generics/issues/issue-73491.min.stderr b/src/test/ui/const-generics/issues/issue-73491.min.stderr index 3ff0563acc7..aeab9e26772 100644 --- a/src/test/ui/const-generics/issues/issue-73491.min.stderr +++ b/src/test/ui/const-generics/issues/issue-73491.min.stderr @@ -1,5 +1,5 @@ error: `[u32; _]` is forbidden as the type of a const generic parameter - --> $DIR/issue-73491.rs:9:19 + --> $DIR/issue-73491.rs:8:19 | LL | fn hoge() {} | ^^^^^^^^^^ diff --git a/src/test/ui/const-generics/issues/issue-73491.rs b/src/test/ui/const-generics/issues/issue-73491.rs index 4f6c44ad2cd..c7cb92baf30 100644 --- a/src/test/ui/const-generics/issues/issue-73491.rs +++ b/src/test/ui/const-generics/issues/issue-73491.rs @@ -2,7 +2,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] const LEN: usize = 1024; diff --git a/src/test/ui/const-generics/issues/issue-73508.full.stderr b/src/test/ui/const-generics/issues/issue-73508.full.stderr index 0816bad35b2..81691a14ef6 100644 --- a/src/test/ui/const-generics/issues/issue-73508.full.stderr +++ b/src/test/ui/const-generics/issues/issue-73508.full.stderr @@ -1,5 +1,5 @@ error: using raw pointers as const generic parameters is forbidden - --> $DIR/issue-73508.rs:6:33 + --> $DIR/issue-73508.rs:5:33 | LL | pub const fn func_name() {} | ^^^^^^^^^^ diff --git a/src/test/ui/const-generics/issues/issue-73508.min.stderr b/src/test/ui/const-generics/issues/issue-73508.min.stderr index 0816bad35b2..81691a14ef6 100644 --- a/src/test/ui/const-generics/issues/issue-73508.min.stderr +++ b/src/test/ui/const-generics/issues/issue-73508.min.stderr @@ -1,5 +1,5 @@ error: using raw pointers as const generic parameters is forbidden - --> $DIR/issue-73508.rs:6:33 + --> $DIR/issue-73508.rs:5:33 | LL | pub const fn func_name() {} | ^^^^^^^^^^ diff --git a/src/test/ui/const-generics/issues/issue-73508.rs b/src/test/ui/const-generics/issues/issue-73508.rs index 21b87f7f901..f02c4161dc1 100644 --- a/src/test/ui/const-generics/issues/issue-73508.rs +++ b/src/test/ui/const-generics/issues/issue-73508.rs @@ -1,7 +1,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] pub const fn func_name() {} //~^ ERROR using raw pointers diff --git a/src/test/ui/const-generics/issues/issue-74101.min.stderr b/src/test/ui/const-generics/issues/issue-74101.min.stderr index 1351246667e..6561183f7ca 100644 --- a/src/test/ui/const-generics/issues/issue-74101.min.stderr +++ b/src/test/ui/const-generics/issues/issue-74101.min.stderr @@ -1,5 +1,5 @@ error: `[u8; _]` is forbidden as the type of a const generic parameter - --> $DIR/issue-74101.rs:7:18 + --> $DIR/issue-74101.rs:6:18 | LL | fn test() {} | ^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | fn test() {} = help: more complex types are supported with `#[feature(const_generics)]` error: `[u8; _]` is forbidden as the type of a const generic parameter - --> $DIR/issue-74101.rs:10:21 + --> $DIR/issue-74101.rs:9:21 | LL | struct Foo; | ^^^^^^^^^^^ diff --git a/src/test/ui/const-generics/issues/issue-74101.rs b/src/test/ui/const-generics/issues/issue-74101.rs index 2a7d31ac8dd..d4fd72eb6da 100644 --- a/src/test/ui/const-generics/issues/issue-74101.rs +++ b/src/test/ui/const-generics/issues/issue-74101.rs @@ -2,7 +2,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] fn test() {} //[min]~^ ERROR `[u8; _]` is forbidden as the type of a const generic parameter diff --git a/src/test/ui/const-generics/issues/issue-74255.min.stderr b/src/test/ui/const-generics/issues/issue-74255.min.stderr index e3e8502ae63..2b6aa7dad97 100644 --- a/src/test/ui/const-generics/issues/issue-74255.min.stderr +++ b/src/test/ui/const-generics/issues/issue-74255.min.stderr @@ -1,5 +1,5 @@ error: `IceEnum` is forbidden as the type of a const generic parameter - --> $DIR/issue-74255.rs:15:31 + --> $DIR/issue-74255.rs:14:31 | LL | fn ice_struct_fn() {} | ^^^^^^^ diff --git a/src/test/ui/const-generics/issues/issue-74255.rs b/src/test/ui/const-generics/issues/issue-74255.rs index b277c273461..75a876c27e5 100644 --- a/src/test/ui/const-generics/issues/issue-74255.rs +++ b/src/test/ui/const-generics/issues/issue-74255.rs @@ -2,7 +2,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] #[derive(PartialEq, Eq)] enum IceEnum { diff --git a/src/test/ui/const-generics/issues/issue-74950.min.stderr b/src/test/ui/const-generics/issues/issue-74950.min.stderr index 12947a2ab37..27393d38c6b 100644 --- a/src/test/ui/const-generics/issues/issue-74950.min.stderr +++ b/src/test/ui/const-generics/issues/issue-74950.min.stderr @@ -1,5 +1,5 @@ error: `Inner` is forbidden as the type of a const generic parameter - --> $DIR/issue-74950.rs:18:23 + --> $DIR/issue-74950.rs:17:23 | LL | struct Outer; | ^^^^^ @@ -8,7 +8,7 @@ LL | struct Outer; = help: more complex types are supported with `#[feature(const_generics)]` error: `Inner` is forbidden as the type of a const generic parameter - --> $DIR/issue-74950.rs:18:23 + --> $DIR/issue-74950.rs:17:23 | LL | struct Outer; | ^^^^^ @@ -17,7 +17,7 @@ LL | struct Outer; = help: more complex types are supported with `#[feature(const_generics)]` error: `Inner` is forbidden as the type of a const generic parameter - --> $DIR/issue-74950.rs:18:23 + --> $DIR/issue-74950.rs:17:23 | LL | struct Outer; | ^^^^^ @@ -26,7 +26,7 @@ LL | struct Outer; = help: more complex types are supported with `#[feature(const_generics)]` error: `Inner` is forbidden as the type of a const generic parameter - --> $DIR/issue-74950.rs:18:23 + --> $DIR/issue-74950.rs:17:23 | LL | struct Outer; | ^^^^^ @@ -35,7 +35,7 @@ LL | struct Outer; = help: more complex types are supported with `#[feature(const_generics)]` error: `Inner` is forbidden as the type of a const generic parameter - --> $DIR/issue-74950.rs:18:23 + --> $DIR/issue-74950.rs:17:23 | LL | struct Outer; | ^^^^^ diff --git a/src/test/ui/const-generics/issues/issue-74950.rs b/src/test/ui/const-generics/issues/issue-74950.rs index 39f91f2b83d..91e5cc776fa 100644 --- a/src/test/ui/const-generics/issues/issue-74950.rs +++ b/src/test/ui/const-generics/issues/issue-74950.rs @@ -2,7 +2,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] #[derive(PartialEq, Eq)] diff --git a/src/test/ui/const-generics/issues/issue-75047.min.stderr b/src/test/ui/const-generics/issues/issue-75047.min.stderr index b87bb18a5a6..4ab90dd1ec6 100644 --- a/src/test/ui/const-generics/issues/issue-75047.min.stderr +++ b/src/test/ui/const-generics/issues/issue-75047.min.stderr @@ -1,5 +1,5 @@ error: `[u8; _]` is forbidden as the type of a const generic parameter - --> $DIR/issue-75047.rs:15:21 + --> $DIR/issue-75047.rs:14:21 | LL | struct Foo::value()]>; | ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/const-generics/issues/issue-75047.rs b/src/test/ui/const-generics/issues/issue-75047.rs index 7bab7cdd098..97437748177 100644 --- a/src/test/ui/const-generics/issues/issue-75047.rs +++ b/src/test/ui/const-generics/issues/issue-75047.rs @@ -2,7 +2,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] struct Bar(T); diff --git a/src/test/ui/const-generics/issues/issue-76701-ty-param-in-const.full.stderr b/src/test/ui/const-generics/issues/issue-76701-ty-param-in-const.full.stderr index 089937e66ca..88b8ff89ffe 100644 --- a/src/test/ui/const-generics/issues/issue-76701-ty-param-in-const.full.stderr +++ b/src/test/ui/const-generics/issues/issue-76701-ty-param-in-const.full.stderr @@ -1,5 +1,5 @@ error: constant expression depends on a generic parameter - --> $DIR/issue-76701-ty-param-in-const.rs:6:21 + --> $DIR/issue-76701-ty-param-in-const.rs:5:21 | LL | fn ty_param() -> [u8; std::mem::size_of::()] { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | fn ty_param() -> [u8; std::mem::size_of::()] { = note: this may fail depending on what value the parameter takes error: constant expression depends on a generic parameter - --> $DIR/issue-76701-ty-param-in-const.rs:12:37 + --> $DIR/issue-76701-ty-param-in-const.rs:11:37 | LL | fn const_param() -> [u8; N + 1] { | ^^^^^^^^^^^ diff --git a/src/test/ui/const-generics/issues/issue-76701-ty-param-in-const.min.stderr b/src/test/ui/const-generics/issues/issue-76701-ty-param-in-const.min.stderr index 551b8e43e1d..32f70fa3007 100644 --- a/src/test/ui/const-generics/issues/issue-76701-ty-param-in-const.min.stderr +++ b/src/test/ui/const-generics/issues/issue-76701-ty-param-in-const.min.stderr @@ -1,5 +1,5 @@ error: generic parameters may not be used in const operations - --> $DIR/issue-76701-ty-param-in-const.rs:6:46 + --> $DIR/issue-76701-ty-param-in-const.rs:5:46 | LL | fn ty_param() -> [u8; std::mem::size_of::()] { | ^ cannot perform const operation using `T` @@ -8,7 +8,7 @@ LL | fn ty_param() -> [u8; std::mem::size_of::()] { = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: generic parameters may not be used in const operations - --> $DIR/issue-76701-ty-param-in-const.rs:12:42 + --> $DIR/issue-76701-ty-param-in-const.rs:11:42 | LL | fn const_param() -> [u8; N + 1] { | ^ cannot perform const operation using `N` diff --git a/src/test/ui/const-generics/issues/issue-76701-ty-param-in-const.rs b/src/test/ui/const-generics/issues/issue-76701-ty-param-in-const.rs index 9051c36fe81..99489826563 100644 --- a/src/test/ui/const-generics/issues/issue-76701-ty-param-in-const.rs +++ b/src/test/ui/const-generics/issues/issue-76701-ty-param-in-const.rs @@ -1,7 +1,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] fn ty_param() -> [u8; std::mem::size_of::()] { //[full]~^ ERROR constant expression depends on a generic parameter diff --git a/src/test/ui/const-generics/issues/issue-80062.rs b/src/test/ui/const-generics/issues/issue-80062.rs new file mode 100644 index 00000000000..56dc53298fb --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-80062.rs @@ -0,0 +1,10 @@ +// Regression test for issue #80062 (fixed by `min_const_generics`) + +fn sof() -> T { unimplemented!() } + +fn test() { + let _: [u8; sof::()]; + //~^ ERROR generic parameters may not be used in const operations +} + +fn main() {} diff --git a/src/test/ui/const-generics/issues/issue-80062.stderr b/src/test/ui/const-generics/issues/issue-80062.stderr new file mode 100644 index 00000000000..aad8907bda2 --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-80062.stderr @@ -0,0 +1,11 @@ +error: generic parameters may not be used in const operations + --> $DIR/issue-80062.rs:6:23 + | +LL | let _: [u8; sof::()]; + | ^ cannot perform const operation using `T` + | + = note: type parameters may not be used in const expressions + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions + +error: aborting due to previous error + diff --git a/src/test/ui/const-generics/issues/issue-80375.rs b/src/test/ui/const-generics/issues/issue-80375.rs new file mode 100644 index 00000000000..c906bb2c4d9 --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-80375.rs @@ -0,0 +1,4 @@ +struct MyArray([u8; COUNT + 1]); +//~^ ERROR generic parameters may not be used in const operations + +fn main() {} diff --git a/src/test/ui/const-generics/issues/issue-80375.stderr b/src/test/ui/const-generics/issues/issue-80375.stderr new file mode 100644 index 00000000000..9765a639a48 --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-80375.stderr @@ -0,0 +1,11 @@ +error: generic parameters may not be used in const operations + --> $DIR/issue-80375.rs:1:41 + | +LL | struct MyArray([u8; COUNT + 1]); + | ^^^^^ cannot perform const operation using `COUNT` + | + = help: const parameters may only be used as standalone arguments, i.e. `COUNT` + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions + +error: aborting due to previous error + diff --git a/src/test/ui/const-generics/issues/issue70273-assoc-fn.rs b/src/test/ui/const-generics/issues/issue70273-assoc-fn.rs index 28f80702dcf..189a32570f7 100644 --- a/src/test/ui/const-generics/issues/issue70273-assoc-fn.rs +++ b/src/test/ui/const-generics/issues/issue70273-assoc-fn.rs @@ -2,7 +2,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] trait T { fn f(); diff --git a/src/test/ui/const-generics/macro_rules-braces.full.stderr b/src/test/ui/const-generics/macro_rules-braces.full.stderr index 3c9d4c9b470..1883f454e60 100644 --- a/src/test/ui/const-generics/macro_rules-braces.full.stderr +++ b/src/test/ui/const-generics/macro_rules-braces.full.stderr @@ -1,5 +1,5 @@ error: expressions must be enclosed in braces to be used as const generic arguments - --> $DIR/macro_rules-braces.rs:49:17 + --> $DIR/macro_rules-braces.rs:48:17 | LL | let _: baz!(m::P); | ^^^^ @@ -10,7 +10,7 @@ LL | let _: baz!({ m::P }); | ^ ^ error: expressions must be enclosed in braces to be used as const generic arguments - --> $DIR/macro_rules-braces.rs:69:17 + --> $DIR/macro_rules-braces.rs:68:17 | LL | let _: baz!(10 + 7); | ^^^^^^ @@ -21,7 +21,7 @@ LL | let _: baz!({ 10 + 7 }); | ^ ^ error: constant expression depends on a generic parameter - --> $DIR/macro_rules-braces.rs:16:13 + --> $DIR/macro_rules-braces.rs:15:13 | LL | [u8; $x] | ^^^^^^^^ @@ -33,7 +33,7 @@ LL | let _: foo!({{ N }}); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: constant expression depends on a generic parameter - --> $DIR/macro_rules-braces.rs:21:13 + --> $DIR/macro_rules-braces.rs:20:13 | LL | [u8; { $x }] | ^^^^^^^^^^^^ @@ -45,7 +45,7 @@ LL | let _: bar!({ N }); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: constant expression depends on a generic parameter - --> $DIR/macro_rules-braces.rs:26:13 + --> $DIR/macro_rules-braces.rs:25:13 | LL | Foo<$x> | ^^^^^^^ @@ -57,7 +57,7 @@ LL | let _: baz!({{ N }}); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: constant expression depends on a generic parameter - --> $DIR/macro_rules-braces.rs:31:13 + --> $DIR/macro_rules-braces.rs:30:13 | LL | Foo<{ $x }> | ^^^^^^^^^^^ diff --git a/src/test/ui/const-generics/macro_rules-braces.min.stderr b/src/test/ui/const-generics/macro_rules-braces.min.stderr index c400e2c814d..60583d43c01 100644 --- a/src/test/ui/const-generics/macro_rules-braces.min.stderr +++ b/src/test/ui/const-generics/macro_rules-braces.min.stderr @@ -1,5 +1,5 @@ error: expressions must be enclosed in braces to be used as const generic arguments - --> $DIR/macro_rules-braces.rs:49:17 + --> $DIR/macro_rules-braces.rs:48:17 | LL | let _: baz!(m::P); | ^^^^ @@ -10,7 +10,7 @@ LL | let _: baz!({ m::P }); | ^ ^ error: expressions must be enclosed in braces to be used as const generic arguments - --> $DIR/macro_rules-braces.rs:69:17 + --> $DIR/macro_rules-braces.rs:68:17 | LL | let _: baz!(10 + 7); | ^^^^^^ @@ -21,7 +21,7 @@ LL | let _: baz!({ 10 + 7 }); | ^ ^ error: generic parameters may not be used in const operations - --> $DIR/macro_rules-braces.rs:37:20 + --> $DIR/macro_rules-braces.rs:36:20 | LL | let _: foo!({{ N }}); | ^ cannot perform const operation using `N` @@ -30,7 +30,7 @@ LL | let _: foo!({{ N }}); = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: generic parameters may not be used in const operations - --> $DIR/macro_rules-braces.rs:41:19 + --> $DIR/macro_rules-braces.rs:40:19 | LL | let _: bar!({ N }); | ^ cannot perform const operation using `N` @@ -39,7 +39,7 @@ LL | let _: bar!({ N }); = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: generic parameters may not be used in const operations - --> $DIR/macro_rules-braces.rs:46:20 + --> $DIR/macro_rules-braces.rs:45:20 | LL | let _: baz!({{ N }}); | ^ cannot perform const operation using `N` @@ -48,7 +48,7 @@ LL | let _: baz!({{ N }}); = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: generic parameters may not be used in const operations - --> $DIR/macro_rules-braces.rs:51:19 + --> $DIR/macro_rules-braces.rs:50:19 | LL | let _: biz!({ N }); | ^ cannot perform const operation using `N` diff --git a/src/test/ui/const-generics/macro_rules-braces.rs b/src/test/ui/const-generics/macro_rules-braces.rs index c6b43bec243..605a10880bb 100644 --- a/src/test/ui/const-generics/macro_rules-braces.rs +++ b/src/test/ui/const-generics/macro_rules-braces.rs @@ -1,7 +1,6 @@ // revisions: full min #![cfg_attr(full, allow(incomplete_features))] #![cfg_attr(full, feature(const_generics))] -#![cfg_attr(min, feature(min_const_generics))] mod m { pub const P: usize = 0; diff --git a/src/test/ui/const-generics/min-and-full-same-time.rs b/src/test/ui/const-generics/min-and-full-same-time.rs deleted file mode 100644 index 2365adc3a86..00000000000 --- a/src/test/ui/const-generics/min-and-full-same-time.rs +++ /dev/null @@ -1,7 +0,0 @@ -#![feature(const_generics)] -//~^ ERROR features `const_generics` and `min_const_generics` are incompatible -#![allow(incomplete_features)] -#![feature(min_const_generics)] - - -fn main() {} diff --git a/src/test/ui/const-generics/min-and-full-same-time.stderr b/src/test/ui/const-generics/min-and-full-same-time.stderr deleted file mode 100644 index 907fec9bbe1..00000000000 --- a/src/test/ui/const-generics/min-and-full-same-time.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error: features `const_generics` and `min_const_generics` are incompatible, using them at the same time is not allowed - --> $DIR/min-and-full-same-time.rs:1:12 - | -LL | #![feature(const_generics)] - | ^^^^^^^^^^^^^^ -... -LL | #![feature(min_const_generics)] - | ^^^^^^^^^^^^^^^^^^ - | - = help: remove one of these features - -error: aborting due to previous error - diff --git a/src/test/ui/const-generics/min_const_generics/assoc_const.rs b/src/test/ui/const-generics/min_const_generics/assoc_const.rs index fa75613d9dd..27e971b5b6f 100644 --- a/src/test/ui/const-generics/min_const_generics/assoc_const.rs +++ b/src/test/ui/const-generics/min_const_generics/assoc_const.rs @@ -1,6 +1,4 @@ // check-pass -#![feature(min_const_generics)] - struct Foo; impl Foo { diff --git a/src/test/ui/const-generics/min_const_generics/complex-expression.rs b/src/test/ui/const-generics/min_const_generics/complex-expression.rs index 686ce98fcdf..7840989cb08 100644 --- a/src/test/ui/const-generics/min_const_generics/complex-expression.rs +++ b/src/test/ui/const-generics/min_const_generics/complex-expression.rs @@ -1,5 +1,3 @@ -#![feature(min_const_generics)] - use std::mem::size_of; fn test() {} diff --git a/src/test/ui/const-generics/min_const_generics/complex-expression.stderr b/src/test/ui/const-generics/min_const_generics/complex-expression.stderr index 2ea66279d46..17669244849 100644 --- a/src/test/ui/const-generics/min_const_generics/complex-expression.stderr +++ b/src/test/ui/const-generics/min_const_generics/complex-expression.stderr @@ -1,5 +1,5 @@ error: generic parameters may not be used in const operations - --> $DIR/complex-expression.rs:11:38 + --> $DIR/complex-expression.rs:9:38 | LL | struct Break0([u8; { N + 1 }]); | ^ cannot perform const operation using `N` @@ -8,7 +8,7 @@ LL | struct Break0([u8; { N + 1 }]); = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: generic parameters may not be used in const operations - --> $DIR/complex-expression.rs:14:40 + --> $DIR/complex-expression.rs:12:40 | LL | struct Break1([u8; { { N } }]); | ^ cannot perform const operation using `N` @@ -17,7 +17,7 @@ LL | struct Break1([u8; { { N } }]); = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: generic parameters may not be used in const operations - --> $DIR/complex-expression.rs:18:17 + --> $DIR/complex-expression.rs:16:17 | LL | let _: [u8; N + 1]; | ^ cannot perform const operation using `N` @@ -26,7 +26,7 @@ LL | let _: [u8; N + 1]; = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: generic parameters may not be used in const operations - --> $DIR/complex-expression.rs:23:17 + --> $DIR/complex-expression.rs:21:17 | LL | let _ = [0; N + 1]; | ^ cannot perform const operation using `N` @@ -35,7 +35,7 @@ LL | let _ = [0; N + 1]; = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: generic parameters may not be used in const operations - --> $DIR/complex-expression.rs:27:45 + --> $DIR/complex-expression.rs:25:45 | LL | struct BreakTy0(T, [u8; { size_of::<*mut T>() }]); | ^ cannot perform const operation using `T` @@ -44,7 +44,7 @@ LL | struct BreakTy0(T, [u8; { size_of::<*mut T>() }]); = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: generic parameters may not be used in const operations - --> $DIR/complex-expression.rs:30:47 + --> $DIR/complex-expression.rs:28:47 | LL | struct BreakTy1(T, [u8; { { size_of::<*mut T>() } }]); | ^ cannot perform const operation using `T` @@ -53,7 +53,7 @@ LL | struct BreakTy1(T, [u8; { { size_of::<*mut T>() } }]); = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: generic parameters may not be used in const operations - --> $DIR/complex-expression.rs:34:32 + --> $DIR/complex-expression.rs:32:32 | LL | let _: [u8; size_of::<*mut T>() + 1]; | ^ cannot perform const operation using `T` @@ -62,7 +62,7 @@ LL | let _: [u8; size_of::<*mut T>() + 1]; = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions warning: cannot use constants which depend on generic parameters in types - --> $DIR/complex-expression.rs:39:17 + --> $DIR/complex-expression.rs:37:17 | LL | let _ = [0; size_of::<*mut T>() + 1]; | ^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/const-generics/min_const_generics/complex-types.rs b/src/test/ui/const-generics/min_const_generics/complex-types.rs index 2aaf2c39875..057bd5af89e 100644 --- a/src/test/ui/const-generics/min_const_generics/complex-types.rs +++ b/src/test/ui/const-generics/min_const_generics/complex-types.rs @@ -1,4 +1,3 @@ -#![feature(min_const_generics)] #![feature(never_type)] struct Foo; diff --git a/src/test/ui/const-generics/min_const_generics/complex-types.stderr b/src/test/ui/const-generics/min_const_generics/complex-types.stderr index 5d473f1f876..20d498f9c93 100644 --- a/src/test/ui/const-generics/min_const_generics/complex-types.stderr +++ b/src/test/ui/const-generics/min_const_generics/complex-types.stderr @@ -1,5 +1,5 @@ error: `[u8; 0]` is forbidden as the type of a const generic parameter - --> $DIR/complex-types.rs:4:21 + --> $DIR/complex-types.rs:3:21 | LL | struct Foo; | ^^^^^^^ @@ -8,7 +8,7 @@ LL | struct Foo; = help: more complex types are supported with `#[feature(const_generics)]` error: `()` is forbidden as the type of a const generic parameter - --> $DIR/complex-types.rs:7:21 + --> $DIR/complex-types.rs:6:21 | LL | struct Bar; | ^^ @@ -17,7 +17,7 @@ LL | struct Bar; = help: more complex types are supported with `#[feature(const_generics)]` error: `No` is forbidden as the type of a const generic parameter - --> $DIR/complex-types.rs:12:21 + --> $DIR/complex-types.rs:11:21 | LL | struct Fez; | ^^ @@ -26,7 +26,7 @@ LL | struct Fez; = help: more complex types are supported with `#[feature(const_generics)]` error: `&'static u8` is forbidden as the type of a const generic parameter - --> $DIR/complex-types.rs:15:21 + --> $DIR/complex-types.rs:14:21 | LL | struct Faz; | ^^^^^^^^^^^ @@ -35,7 +35,7 @@ LL | struct Faz; = help: more complex types are supported with `#[feature(const_generics)]` error: `!` is forbidden as the type of a const generic parameter - --> $DIR/complex-types.rs:18:21 + --> $DIR/complex-types.rs:17:21 | LL | struct Fiz; | ^ @@ -44,7 +44,7 @@ LL | struct Fiz; = help: more complex types are supported with `#[feature(const_generics)]` error: `()` is forbidden as the type of a const generic parameter - --> $DIR/complex-types.rs:21:19 + --> $DIR/complex-types.rs:20:19 | LL | enum Goo { A, B } | ^^ @@ -53,7 +53,7 @@ LL | enum Goo { A, B } = help: more complex types are supported with `#[feature(const_generics)]` error: `()` is forbidden as the type of a const generic parameter - --> $DIR/complex-types.rs:24:20 + --> $DIR/complex-types.rs:23:20 | LL | union Boo { a: () } | ^^ diff --git a/src/test/ui/const-generics/min_const_generics/const-evaluatable-unchecked.rs b/src/test/ui/const-generics/min_const_generics/const-evaluatable-unchecked.rs index dd82be33a8e..71d13ca61c9 100644 --- a/src/test/ui/const-generics/min_const_generics/const-evaluatable-unchecked.rs +++ b/src/test/ui/const-generics/min_const_generics/const-evaluatable-unchecked.rs @@ -1,5 +1,4 @@ // check-pass -#![feature(min_const_generics)] #![allow(dead_code)] fn foo() { diff --git a/src/test/ui/const-generics/min_const_generics/const-evaluatable-unchecked.stderr b/src/test/ui/const-generics/min_const_generics/const-evaluatable-unchecked.stderr index 4d0cab012f9..f9f6660f6b8 100644 --- a/src/test/ui/const-generics/min_const_generics/const-evaluatable-unchecked.stderr +++ b/src/test/ui/const-generics/min_const_generics/const-evaluatable-unchecked.stderr @@ -1,5 +1,5 @@ warning: cannot use constants which depend on generic parameters in types - --> $DIR/const-evaluatable-unchecked.rs:6:9 + --> $DIR/const-evaluatable-unchecked.rs:5:9 | LL | [0; std::mem::size_of::<*mut T>()]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -9,7 +9,7 @@ LL | [0; std::mem::size_of::<*mut T>()]; = note: for more information, see issue #76200 warning: cannot use constants which depend on generic parameters in types - --> $DIR/const-evaluatable-unchecked.rs:17:21 + --> $DIR/const-evaluatable-unchecked.rs:16:21 | LL | let _ = [0; Self::ASSOC]; | ^^^^^^^^^^^ @@ -18,7 +18,7 @@ LL | let _ = [0; Self::ASSOC]; = note: for more information, see issue #76200 warning: cannot use constants which depend on generic parameters in types - --> $DIR/const-evaluatable-unchecked.rs:29:21 + --> $DIR/const-evaluatable-unchecked.rs:28:21 | LL | let _ = [0; Self::ASSOC]; | ^^^^^^^^^^^ diff --git a/src/test/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces-without-turbofish.rs b/src/test/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces-without-turbofish.rs index b9afd226430..fac3777cf21 100644 --- a/src/test/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces-without-turbofish.rs +++ b/src/test/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces-without-turbofish.rs @@ -1,5 +1,3 @@ -#![feature(min_const_generics)] - fn foo() {} const BAR: usize = 42; diff --git a/src/test/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces-without-turbofish.stderr b/src/test/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces-without-turbofish.stderr index 13742238a20..beea0acac60 100644 --- a/src/test/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces-without-turbofish.stderr +++ b/src/test/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces-without-turbofish.stderr @@ -1,5 +1,5 @@ error: comparison operators cannot be chained - --> $DIR/const-expression-suggest-missing-braces-without-turbofish.rs:8:8 + --> $DIR/const-expression-suggest-missing-braces-without-turbofish.rs:6:8 | LL | foo(); | ^ ^ @@ -10,7 +10,7 @@ LL | foo::(); | ^^ error: comparison operators cannot be chained - --> $DIR/const-expression-suggest-missing-braces-without-turbofish.rs:11:8 + --> $DIR/const-expression-suggest-missing-braces-without-turbofish.rs:9:8 | LL | foo(); | ^ ^ @@ -21,7 +21,7 @@ LL | foo::(); | ^^ error: comparison operators cannot be chained - --> $DIR/const-expression-suggest-missing-braces-without-turbofish.rs:14:8 + --> $DIR/const-expression-suggest-missing-braces-without-turbofish.rs:12:8 | LL | foo<3 + 3>(); | ^ ^ @@ -32,7 +32,7 @@ LL | foo::<3 + 3>(); | ^^ error: comparison operators cannot be chained - --> $DIR/const-expression-suggest-missing-braces-without-turbofish.rs:17:8 + --> $DIR/const-expression-suggest-missing-braces-without-turbofish.rs:15:8 | LL | foo(); | ^ ^ @@ -43,7 +43,7 @@ LL | foo::(); | ^^ error: comparison operators cannot be chained - --> $DIR/const-expression-suggest-missing-braces-without-turbofish.rs:20:8 + --> $DIR/const-expression-suggest-missing-braces-without-turbofish.rs:18:8 | LL | foo(); | ^ ^ @@ -54,7 +54,7 @@ LL | foo::(); | ^^ error: comparison operators cannot be chained - --> $DIR/const-expression-suggest-missing-braces-without-turbofish.rs:23:8 + --> $DIR/const-expression-suggest-missing-braces-without-turbofish.rs:21:8 | LL | foo<100 - BAR>(); | ^ ^ @@ -65,7 +65,7 @@ LL | foo::<100 - BAR>(); | ^^ error: comparison operators cannot be chained - --> $DIR/const-expression-suggest-missing-braces-without-turbofish.rs:26:8 + --> $DIR/const-expression-suggest-missing-braces-without-turbofish.rs:24:8 | LL | foo()>(); | ^ ^ @@ -76,13 +76,13 @@ LL | foo::()>(); | ^^ error: expected one of `;` or `}`, found `>` - --> $DIR/const-expression-suggest-missing-braces-without-turbofish.rs:26:19 + --> $DIR/const-expression-suggest-missing-braces-without-turbofish.rs:24:19 | LL | foo()>(); | ^ expected one of `;` or `}` error: comparison operators cannot be chained - --> $DIR/const-expression-suggest-missing-braces-without-turbofish.rs:30:8 + --> $DIR/const-expression-suggest-missing-braces-without-turbofish.rs:28:8 | LL | foo()>(); | ^ ^ @@ -93,7 +93,7 @@ LL | foo::()>(); | ^^ error: comparison operators cannot be chained - --> $DIR/const-expression-suggest-missing-braces-without-turbofish.rs:33:8 + --> $DIR/const-expression-suggest-missing-braces-without-turbofish.rs:31:8 | LL | foo() + BAR>(); | ^ ^ @@ -104,7 +104,7 @@ LL | foo::() + BAR>(); | ^^ error: comparison operators cannot be chained - --> $DIR/const-expression-suggest-missing-braces-without-turbofish.rs:36:8 + --> $DIR/const-expression-suggest-missing-braces-without-turbofish.rs:34:8 | LL | foo() - BAR>(); | ^ ^ @@ -115,7 +115,7 @@ LL | foo::() - BAR>(); | ^^ error: comparison operators cannot be chained - --> $DIR/const-expression-suggest-missing-braces-without-turbofish.rs:39:8 + --> $DIR/const-expression-suggest-missing-braces-without-turbofish.rs:37:8 | LL | foo()>(); | ^ ^ @@ -126,7 +126,7 @@ LL | foo::()>(); | ^^ error: comparison operators cannot be chained - --> $DIR/const-expression-suggest-missing-braces-without-turbofish.rs:42:8 + --> $DIR/const-expression-suggest-missing-braces-without-turbofish.rs:40:8 | LL | foo()>(); | ^ ^ diff --git a/src/test/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces.rs b/src/test/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces.rs index b96d5c561ff..f8b9d7adbfe 100644 --- a/src/test/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces.rs +++ b/src/test/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces.rs @@ -1,5 +1,3 @@ -#![feature(min_const_generics)] - fn foo() {} const BAR: usize = 42; diff --git a/src/test/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces.stderr b/src/test/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces.stderr index 6adcf6a3e36..ad451fcf65d 100644 --- a/src/test/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces.stderr +++ b/src/test/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces.stderr @@ -1,5 +1,5 @@ error: expected one of `,` or `>`, found `3` - --> $DIR/const-expression-suggest-missing-braces.rs:8:17 + --> $DIR/const-expression-suggest-missing-braces.rs:6:17 | LL | foo::(); | ^ expected one of `,` or `>` @@ -10,7 +10,7 @@ LL | foo::<{ BAR + 3 }>(); | ^ ^ error: expressions must be enclosed in braces to be used as const generic arguments - --> $DIR/const-expression-suggest-missing-braces.rs:20:11 + --> $DIR/const-expression-suggest-missing-braces.rs:18:11 | LL | foo::<3 + 3>(); | ^^^^^ @@ -21,7 +21,7 @@ LL | foo::<{ 3 + 3 }>(); | ^ ^ error: expected one of `,` or `>`, found `-` - --> $DIR/const-expression-suggest-missing-braces.rs:23:15 + --> $DIR/const-expression-suggest-missing-braces.rs:21:15 | LL | foo::(); | ^ expected one of `,` or `>` @@ -32,7 +32,7 @@ LL | foo::<{ BAR - 3 }>(); | ^ ^ error: expected one of `,` or `>`, found `-` - --> $DIR/const-expression-suggest-missing-braces.rs:26:15 + --> $DIR/const-expression-suggest-missing-braces.rs:24:15 | LL | foo::(); | ^ expected one of `,` or `>` @@ -43,7 +43,7 @@ LL | foo::<{ BAR - BAR }>(); | ^ ^ error: expressions must be enclosed in braces to be used as const generic arguments - --> $DIR/const-expression-suggest-missing-braces.rs:29:11 + --> $DIR/const-expression-suggest-missing-braces.rs:27:11 | LL | foo::<100 - BAR>(); | ^^^^^^^^^ @@ -54,7 +54,7 @@ LL | foo::<{ 100 - BAR }>(); | ^ ^ error: expected one of `,` or `>`, found `(` - --> $DIR/const-expression-suggest-missing-braces.rs:32:19 + --> $DIR/const-expression-suggest-missing-braces.rs:30:19 | LL | foo::()>(); | ^ expected one of `,` or `>` @@ -65,7 +65,7 @@ LL | foo::<{ bar() }>(); | ^ ^ error: expected one of `,` or `>`, found `(` - --> $DIR/const-expression-suggest-missing-braces.rs:35:21 + --> $DIR/const-expression-suggest-missing-braces.rs:33:21 | LL | foo::()>(); | ^ expected one of `,` or `>` @@ -76,7 +76,7 @@ LL | foo::<{ bar::() }>(); | ^ ^ error: expected one of `,` or `>`, found `(` - --> $DIR/const-expression-suggest-missing-braces.rs:38:21 + --> $DIR/const-expression-suggest-missing-braces.rs:36:21 | LL | foo::() + BAR>(); | ^ expected one of `,` or `>` @@ -87,7 +87,7 @@ LL | foo::<{ bar::() + BAR }>(); | ^ ^ error: expected one of `,` or `>`, found `(` - --> $DIR/const-expression-suggest-missing-braces.rs:41:21 + --> $DIR/const-expression-suggest-missing-braces.rs:39:21 | LL | foo::() - BAR>(); | ^ expected one of `,` or `>` @@ -98,7 +98,7 @@ LL | foo::<{ bar::() - BAR }>(); | ^ ^ error: expected one of `,` or `>`, found `-` - --> $DIR/const-expression-suggest-missing-braces.rs:44:15 + --> $DIR/const-expression-suggest-missing-braces.rs:42:15 | LL | foo::()>(); | ^ expected one of `,` or `>` @@ -109,7 +109,7 @@ LL | foo::<{ BAR - bar::() }>(); | ^ ^ error: expected one of `,` or `>`, found `-` - --> $DIR/const-expression-suggest-missing-braces.rs:47:15 + --> $DIR/const-expression-suggest-missing-braces.rs:45:15 | LL | foo::()>(); | ^ expected one of `,` or `>` @@ -120,19 +120,19 @@ LL | foo::<{ BAR - bar::() }>(); | ^ ^ error[E0404]: expected trait, found constant `BAR` - --> $DIR/const-expression-suggest-missing-braces.rs:13:11 + --> $DIR/const-expression-suggest-missing-braces.rs:11:11 | LL | foo::(); | ^^^ not a trait error[E0404]: expected trait, found constant `BAR` - --> $DIR/const-expression-suggest-missing-braces.rs:13:17 + --> $DIR/const-expression-suggest-missing-braces.rs:11:17 | LL | foo::(); | ^^^ not a trait warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/const-expression-suggest-missing-braces.rs:13:11 + --> $DIR/const-expression-suggest-missing-braces.rs:11:11 | LL | foo::(); | ^^^^^^^^^ help: use `dyn`: `dyn BAR + BAR` @@ -140,7 +140,7 @@ LL | foo::(); = note: `#[warn(bare_trait_objects)]` on by default error[E0747]: type provided when a constant was expected - --> $DIR/const-expression-suggest-missing-braces.rs:13:11 + --> $DIR/const-expression-suggest-missing-braces.rs:11:11 | LL | foo::(); | ^^^^^^^^^ diff --git a/src/test/ui/const-generics/min_const_generics/const_fn_in_generics.rs b/src/test/ui/const-generics/min_const_generics/const_fn_in_generics.rs index 3370666cc5c..0c10af6c43f 100644 --- a/src/test/ui/const-generics/min_const_generics/const_fn_in_generics.rs +++ b/src/test/ui/const-generics/min_const_generics/const_fn_in_generics.rs @@ -1,7 +1,5 @@ // run-pass -#![feature(min_const_generics)] - const fn identity() -> u32 { T } #[derive(Eq, PartialEq, Debug)] diff --git a/src/test/ui/const-generics/min_const_generics/default_function_param.rs b/src/test/ui/const-generics/min_const_generics/default_function_param.rs index 7e0c1c2ed9f..d7918a73ab8 100644 --- a/src/test/ui/const-generics/min_const_generics/default_function_param.rs +++ b/src/test/ui/const-generics/min_const_generics/default_function_param.rs @@ -1,5 +1,3 @@ -#![feature(min_const_generics)] - fn foo() {} //~^ ERROR expected one of `!`, `(`, `+`, `,`, `::`, `<`, or `>`, found `=` diff --git a/src/test/ui/const-generics/min_const_generics/default_function_param.stderr b/src/test/ui/const-generics/min_const_generics/default_function_param.stderr index ed1a83b6a4d..8eb796d9bb7 100644 --- a/src/test/ui/const-generics/min_const_generics/default_function_param.stderr +++ b/src/test/ui/const-generics/min_const_generics/default_function_param.stderr @@ -1,5 +1,5 @@ error: expected one of `!`, `(`, `+`, `,`, `::`, `<`, or `>`, found `=` - --> $DIR/default_function_param.rs:3:26 + --> $DIR/default_function_param.rs:1:26 | LL | fn foo() {} | ^ expected one of 7 possible tokens diff --git a/src/test/ui/const-generics/min_const_generics/default_trait_param.rs b/src/test/ui/const-generics/min_const_generics/default_trait_param.rs index 322ddccbf18..c8003ad5d44 100644 --- a/src/test/ui/const-generics/min_const_generics/default_trait_param.rs +++ b/src/test/ui/const-generics/min_const_generics/default_trait_param.rs @@ -1,5 +1,3 @@ -#![feature(min_const_generics)] - trait Foo {} //~^ ERROR expected one of `!`, `(`, `+`, `,`, `::`, `<`, or `>`, found `=` diff --git a/src/test/ui/const-generics/min_const_generics/default_trait_param.stderr b/src/test/ui/const-generics/min_const_generics/default_trait_param.stderr index 49c3ac86744..6d112ef1de0 100644 --- a/src/test/ui/const-generics/min_const_generics/default_trait_param.stderr +++ b/src/test/ui/const-generics/min_const_generics/default_trait_param.stderr @@ -1,5 +1,5 @@ error: expected one of `!`, `(`, `+`, `,`, `::`, `<`, or `>`, found `=` - --> $DIR/default_trait_param.rs:3:28 + --> $DIR/default_trait_param.rs:1:28 | LL | trait Foo {} | ^ expected one of 7 possible tokens diff --git a/src/test/ui/const-generics/min_const_generics/feature-gate-min_const_generics.rs b/src/test/ui/const-generics/min_const_generics/feature-gate-min_const_generics.rs deleted file mode 100644 index 423deae4600..00000000000 --- a/src/test/ui/const-generics/min_const_generics/feature-gate-min_const_generics.rs +++ /dev/null @@ -1,4 +0,0 @@ -fn test() {} -//~^ ERROR const generics are unstable - -fn main() {} diff --git a/src/test/ui/const-generics/min_const_generics/feature-gate-min_const_generics.stderr b/src/test/ui/const-generics/min_const_generics/feature-gate-min_const_generics.stderr deleted file mode 100644 index 7f82a960da2..00000000000 --- a/src/test/ui/const-generics/min_const_generics/feature-gate-min_const_generics.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0658]: const generics are unstable - --> $DIR/feature-gate-min_const_generics.rs:1:15 - | -LL | fn test() {} - | ^ - | - = note: see issue #74878 for more information - = help: add `#![feature(min_const_generics)]` to the crate attributes to enable - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/const-generics/min_const_generics/forbid-non-static-lifetimes.rs b/src/test/ui/const-generics/min_const_generics/forbid-non-static-lifetimes.rs index 02944e2bff2..881f8b98aad 100644 --- a/src/test/ui/const-generics/min_const_generics/forbid-non-static-lifetimes.rs +++ b/src/test/ui/const-generics/min_const_generics/forbid-non-static-lifetimes.rs @@ -1,5 +1,3 @@ -#![feature(min_const_generics)] - // This test checks that non-static lifetimes are prohibited under `min_const_generics`. It // currently emits an error with `min_const_generics`. This will ICE under `const_generics`. diff --git a/src/test/ui/const-generics/min_const_generics/forbid-non-static-lifetimes.stderr b/src/test/ui/const-generics/min_const_generics/forbid-non-static-lifetimes.stderr index cdfd491e395..5def54ca26d 100644 --- a/src/test/ui/const-generics/min_const_generics/forbid-non-static-lifetimes.stderr +++ b/src/test/ui/const-generics/min_const_generics/forbid-non-static-lifetimes.stderr @@ -1,5 +1,5 @@ error[E0658]: a non-static lifetime is not allowed in a `const` - --> $DIR/forbid-non-static-lifetimes.rs:9:22 + --> $DIR/forbid-non-static-lifetimes.rs:7:22 | LL | test::<{ let _: &'a (); 3 },>(); | ^^ @@ -8,7 +8,7 @@ LL | test::<{ let _: &'a (); 3 },>(); = help: add `#![feature(const_generics)]` to the crate attributes to enable error[E0658]: a non-static lifetime is not allowed in a `const` - --> $DIR/forbid-non-static-lifetimes.rs:23:16 + --> $DIR/forbid-non-static-lifetimes.rs:21:16 | LL | [(); (|_: &'a u8| (), 0).1]; | ^^ diff --git a/src/test/ui/const-generics/min_const_generics/invalid-patterns.rs b/src/test/ui/const-generics/min_const_generics/invalid-patterns.rs index e59b97922be..a120eee67ee 100644 --- a/src/test/ui/const-generics/min_const_generics/invalid-patterns.rs +++ b/src/test/ui/const-generics/min_const_generics/invalid-patterns.rs @@ -1,4 +1,3 @@ -#![feature(min_const_generics)] use std::mem::transmute; fn get_flag() -> Option { diff --git a/src/test/ui/const-generics/min_const_generics/invalid-patterns.stderr b/src/test/ui/const-generics/min_const_generics/invalid-patterns.stderr index a3157c6b564..04f716fa733 100644 --- a/src/test/ui/const-generics/min_const_generics/invalid-patterns.stderr +++ b/src/test/ui/const-generics/min_const_generics/invalid-patterns.stderr @@ -1,29 +1,29 @@ error[E0308]: mismatched types - --> $DIR/invalid-patterns.rs:29:21 + --> $DIR/invalid-patterns.rs:28:21 | LL | get_flag::(); | ^^^^ expected `char`, found `u8` error[E0308]: mismatched types - --> $DIR/invalid-patterns.rs:31:14 + --> $DIR/invalid-patterns.rs:30:14 | LL | get_flag::<7, 'c'>(); | ^ expected `bool`, found integer error[E0308]: mismatched types - --> $DIR/invalid-patterns.rs:33:14 + --> $DIR/invalid-patterns.rs:32:14 | LL | get_flag::<42, 0x5ad>(); | ^^ expected `bool`, found integer error[E0308]: mismatched types - --> $DIR/invalid-patterns.rs:33:18 + --> $DIR/invalid-patterns.rs:32:18 | LL | get_flag::<42, 0x5ad>(); | ^^^^^ expected `char`, found `u8` error[E0080]: it is undefined behavior to use this value - --> $DIR/invalid-patterns.rs:38:21 + --> $DIR/invalid-patterns.rs:37:21 | LL | get_flag::(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, but expected a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`) @@ -31,7 +31,7 @@ LL | get_flag::(); = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/invalid-patterns.rs:40:14 + --> $DIR/invalid-patterns.rs:39:14 | LL | get_flag::<{ unsafe { bool_raw.boolean } }, 'z'>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0x42, but expected a boolean @@ -39,7 +39,7 @@ LL | get_flag::<{ unsafe { bool_raw.boolean } }, 'z'>(); = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/invalid-patterns.rs:42:14 + --> $DIR/invalid-patterns.rs:41:14 | LL | get_flag::<{ unsafe { bool_raw.boolean } }, { unsafe { char_raw.character } }>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0x42, but expected a boolean @@ -47,7 +47,7 @@ LL | get_flag::<{ unsafe { bool_raw.boolean } }, { unsafe { char_raw.character = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/invalid-patterns.rs:42:47 + --> $DIR/invalid-patterns.rs:41:47 | LL | get_flag::<{ unsafe { bool_raw.boolean } }, { unsafe { char_raw.character } }>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, but expected a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`) diff --git a/src/test/ui/const-generics/min_const_generics/macro-fail.rs b/src/test/ui/const-generics/min_const_generics/macro-fail.rs index 1bd0c46f55e..f83518fc9d4 100644 --- a/src/test/ui/const-generics/min_const_generics/macro-fail.rs +++ b/src/test/ui/const-generics/min_const_generics/macro-fail.rs @@ -1,5 +1,3 @@ -#![feature(min_const_generics)] - struct Example; macro_rules! external_macro { diff --git a/src/test/ui/const-generics/min_const_generics/macro-fail.stderr b/src/test/ui/const-generics/min_const_generics/macro-fail.stderr index a5dedf6fe20..22930a352a8 100644 --- a/src/test/ui/const-generics/min_const_generics/macro-fail.stderr +++ b/src/test/ui/const-generics/min_const_generics/macro-fail.stderr @@ -1,5 +1,5 @@ error: expected type, found `{` - --> $DIR/macro-fail.rs:31:27 + --> $DIR/macro-fail.rs:29:27 | LL | fn make_marker() -> impl Marker { | ---------------------- @@ -13,7 +13,7 @@ LL | ($rusty: ident) => {{ let $rusty = 3; *&$rusty }} = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: expected type, found `{` - --> $DIR/macro-fail.rs:31:27 + --> $DIR/macro-fail.rs:29:27 | LL | Example:: | ---------------------- @@ -27,7 +27,7 @@ LL | ($rusty: ident) => {{ let $rusty = 3; *&$rusty }} = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: expected type, found `{` - --> $DIR/macro-fail.rs:6:10 + --> $DIR/macro-fail.rs:4:10 | LL | () => {{ | __________^ @@ -46,7 +46,7 @@ LL | let _fail = Example::; = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: unexpected end of macro invocation - --> $DIR/macro-fail.rs:41:25 + --> $DIR/macro-fail.rs:39:25 | LL | macro_rules! gimme_a_const { | -------------------------- when calling this macro @@ -55,25 +55,25 @@ LL | let _fail = Example::; | ^^^^^^^^^^^^^^^^ missing tokens in macro arguments error[E0747]: type provided when a constant was expected - --> $DIR/macro-fail.rs:16:33 + --> $DIR/macro-fail.rs:14:33 | LL | fn make_marker() -> impl Marker { | ^^^^^^^^^^^^^^^^^^^^^^ error[E0747]: type provided when a constant was expected - --> $DIR/macro-fail.rs:18:13 + --> $DIR/macro-fail.rs:16:13 | LL | Example:: | ^^^^^^^^^^^^^^^^^^^^^^ error[E0747]: type provided when a constant was expected - --> $DIR/macro-fail.rs:38:25 + --> $DIR/macro-fail.rs:36:25 | LL | let _fail = Example::; | ^^^^^^^^^^^^^^^^^ error[E0747]: type provided when a constant was expected - --> $DIR/macro-fail.rs:41:25 + --> $DIR/macro-fail.rs:39:25 | LL | let _fail = Example::; | ^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/const-generics/min_const_generics/macro.rs b/src/test/ui/const-generics/min_const_generics/macro.rs index 575fbd33572..9b63f76987a 100644 --- a/src/test/ui/const-generics/min_const_generics/macro.rs +++ b/src/test/ui/const-generics/min_const_generics/macro.rs @@ -1,6 +1,4 @@ // run-pass -#![feature(min_const_generics)] - struct Example; macro_rules! external_macro { diff --git a/src/test/ui/const-generics/min_const_generics/self-ty-in-const-1.rs b/src/test/ui/const-generics/min_const_generics/self-ty-in-const-1.rs index 0973b373c12..9ef619365a0 100644 --- a/src/test/ui/const-generics/min_const_generics/self-ty-in-const-1.rs +++ b/src/test/ui/const-generics/min_const_generics/self-ty-in-const-1.rs @@ -1,5 +1,3 @@ -#![feature(min_const_generics)] - trait Foo { fn t1() -> [u8; std::mem::size_of::()]; //~ERROR generic parameters } diff --git a/src/test/ui/const-generics/min_const_generics/self-ty-in-const-1.stderr b/src/test/ui/const-generics/min_const_generics/self-ty-in-const-1.stderr index 40c73f0b951..4fdfb5fbcb1 100644 --- a/src/test/ui/const-generics/min_const_generics/self-ty-in-const-1.stderr +++ b/src/test/ui/const-generics/min_const_generics/self-ty-in-const-1.stderr @@ -1,5 +1,5 @@ error: generic parameters may not be used in const operations - --> $DIR/self-ty-in-const-1.rs:4:41 + --> $DIR/self-ty-in-const-1.rs:2:41 | LL | fn t1() -> [u8; std::mem::size_of::()]; | ^^^^ cannot perform const operation using `Self` @@ -8,13 +8,13 @@ LL | fn t1() -> [u8; std::mem::size_of::()]; = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: generic `Self` types are currently not permitted in anonymous constants - --> $DIR/self-ty-in-const-1.rs:14:41 + --> $DIR/self-ty-in-const-1.rs:12:41 | LL | fn t3() -> [u8; std::mem::size_of::()] {} | ^^^^ | note: not a concrete type - --> $DIR/self-ty-in-const-1.rs:13:9 + --> $DIR/self-ty-in-const-1.rs:11:9 | LL | impl Bar { | ^^^^^^ diff --git a/src/test/ui/const-generics/min_const_generics/self-ty-in-const-2.rs b/src/test/ui/const-generics/min_const_generics/self-ty-in-const-2.rs index e7f80d50082..286ec2d2450 100644 --- a/src/test/ui/const-generics/min_const_generics/self-ty-in-const-2.rs +++ b/src/test/ui/const-generics/min_const_generics/self-ty-in-const-2.rs @@ -1,5 +1,3 @@ -#![feature(min_const_generics)] - struct Bar(T); trait Baz { diff --git a/src/test/ui/const-generics/min_const_generics/self-ty-in-const-2.stderr b/src/test/ui/const-generics/min_const_generics/self-ty-in-const-2.stderr index 9ac6410a290..41546292c47 100644 --- a/src/test/ui/const-generics/min_const_generics/self-ty-in-const-2.stderr +++ b/src/test/ui/const-generics/min_const_generics/self-ty-in-const-2.stderr @@ -1,11 +1,11 @@ error: generic `Self` types are currently not permitted in anonymous constants - --> $DIR/self-ty-in-const-2.rs:17:41 + --> $DIR/self-ty-in-const-2.rs:15:41 | LL | let _: [u8; std::mem::size_of::()]; | ^^^^ | note: not a concrete type - --> $DIR/self-ty-in-const-2.rs:15:17 + --> $DIR/self-ty-in-const-2.rs:13:17 | LL | impl Baz for Bar { | ^^^^^^ diff --git a/src/test/ui/const-generics/min_const_generics/static-reference-array-const-param.rs b/src/test/ui/const-generics/min_const_generics/static-reference-array-const-param.rs index 0ef17109bed..7518dc59e59 100644 --- a/src/test/ui/const-generics/min_const_generics/static-reference-array-const-param.rs +++ b/src/test/ui/const-generics/min_const_generics/static-reference-array-const-param.rs @@ -1,5 +1,3 @@ -#![feature(min_const_generics)] - fn a() {} //~^ ERROR `&'static [u32]` is forbidden as the type of a const generic parameter diff --git a/src/test/ui/const-generics/min_const_generics/static-reference-array-const-param.stderr b/src/test/ui/const-generics/min_const_generics/static-reference-array-const-param.stderr index 6c39f6b4c1d..05939b05bba 100644 --- a/src/test/ui/const-generics/min_const_generics/static-reference-array-const-param.stderr +++ b/src/test/ui/const-generics/min_const_generics/static-reference-array-const-param.stderr @@ -1,5 +1,5 @@ error: `&'static [u32]` is forbidden as the type of a const generic parameter - --> $DIR/static-reference-array-const-param.rs:3:15 + --> $DIR/static-reference-array-const-param.rs:1:15 | LL | fn a() {} | ^^^^^^^^^^^^^^ diff --git a/src/test/ui/const-generics/min_const_generics/transmute-const-param-static-reference.rs b/src/test/ui/const-generics/min_const_generics/transmute-const-param-static-reference.rs index dfa1ece2f36..560795a51f5 100644 --- a/src/test/ui/const-generics/min_const_generics/transmute-const-param-static-reference.rs +++ b/src/test/ui/const-generics/min_const_generics/transmute-const-param-static-reference.rs @@ -1,5 +1,3 @@ -#![feature(min_const_generics)] - struct Const; //~^ ERROR `&'static ()` is forbidden as the type of a const generic parameter diff --git a/src/test/ui/const-generics/min_const_generics/transmute-const-param-static-reference.stderr b/src/test/ui/const-generics/min_const_generics/transmute-const-param-static-reference.stderr index 6b90329b72c..8724c7e33b1 100644 --- a/src/test/ui/const-generics/min_const_generics/transmute-const-param-static-reference.stderr +++ b/src/test/ui/const-generics/min_const_generics/transmute-const-param-static-reference.stderr @@ -1,5 +1,5 @@ error: `&'static ()` is forbidden as the type of a const generic parameter - --> $DIR/transmute-const-param-static-reference.rs:3:23 + --> $DIR/transmute-const-param-static-reference.rs:1:23 | LL | struct Const; | ^^^^^^^^^^^ diff --git a/src/test/ui/const-generics/mut-ref-const-param-array.rs b/src/test/ui/const-generics/mut-ref-const-param-array.rs index cf24cbe7e82..6a5739db3ae 100644 --- a/src/test/ui/const-generics/mut-ref-const-param-array.rs +++ b/src/test/ui/const-generics/mut-ref-const-param-array.rs @@ -3,7 +3,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] use std::ops::AddAssign; diff --git a/src/test/ui/const-generics/nested-type.full.stderr b/src/test/ui/const-generics/nested-type.full.stderr index 06ab9a6ff29..9d7ca36545c 100644 --- a/src/test/ui/const-generics/nested-type.full.stderr +++ b/src/test/ui/const-generics/nested-type.full.stderr @@ -1,5 +1,5 @@ error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants - --> $DIR/nested-type.rs:16:5 + --> $DIR/nested-type.rs:15:5 | LL | Foo::<17>::value() | ^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/const-generics/nested-type.min.stderr b/src/test/ui/const-generics/nested-type.min.stderr index 369e387508e..dabb3f245f5 100644 --- a/src/test/ui/const-generics/nested-type.min.stderr +++ b/src/test/ui/const-generics/nested-type.min.stderr @@ -1,5 +1,5 @@ error: `[u8; _]` is forbidden as the type of a const generic parameter - --> $DIR/nested-type.rs:7:21 + --> $DIR/nested-type.rs:6:21 | LL | struct Foo; = help: more complex types are supported with `#[feature(const_generics)]` error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants - --> $DIR/nested-type.rs:16:5 + --> $DIR/nested-type.rs:15:5 | LL | Foo::<17>::value() | ^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/const-generics/nested-type.rs b/src/test/ui/const-generics/nested-type.rs index c5660983985..be8ebb7f401 100644 --- a/src/test/ui/const-generics/nested-type.rs +++ b/src/test/ui/const-generics/nested-type.rs @@ -2,7 +2,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] struct Foo; diff --git a/src/test/ui/const-generics/occurs-check/unify-fixpoint.stderr b/src/test/ui/const-generics/occurs-check/unify-fixpoint.stderr index 8a1462c59e8..671f1103dcc 100644 --- a/src/test/ui/const-generics/occurs-check/unify-fixpoint.stderr +++ b/src/test/ui/const-generics/occurs-check/unify-fixpoint.stderr @@ -6,7 +6,6 @@ LL | #![feature(const_generics)] | = note: `#[warn(incomplete_features)]` on by default = note: see issue #44580 for more information - = help: consider using `min_const_generics` instead, which is more stable and complete error: constant expression depends on a generic parameter --> $DIR/unify-fixpoint.rs:9:32 diff --git a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr index 3dccfd73dcc..debb272da36 100644 --- a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr +++ b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr @@ -1,5 +1,5 @@ error: type parameters with a default must be trailing - --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:12:12 + --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:11:12 | LL | struct Bar(T); | ^ @@ -7,13 +7,13 @@ LL | struct Bar(T); = note: using type defaults and const parameters in the same parameter list is currently not permitted error: constant values inside of type parameter defaults must not depend on generic parameters - --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:7:44 + --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:6:44 | LL | struct Foo()]>(T, U); | ^ the anonymous constant must not depend on the parameter `T` error: constant values inside of type parameter defaults must not depend on generic parameters - --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:12:21 + --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:11:21 | LL | struct Bar(T); | ^ the anonymous constant must not depend on the parameter `N` diff --git a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr index 9e0837a0a62..171efca1938 100644 --- a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr +++ b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr @@ -1,5 +1,5 @@ error: type parameters with a default must be trailing - --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:12:12 + --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:11:12 | LL | struct Bar(T); | ^ @@ -7,7 +7,7 @@ LL | struct Bar(T); = note: using type defaults and const parameters in the same parameter list is currently not permitted error: generic parameters may not be used in const operations - --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:7:44 + --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:6:44 | LL | struct Foo()]>(T, U); | ^ cannot perform const operation using `T` @@ -16,7 +16,7 @@ LL | struct Foo()]>(T, U); = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: constant values inside of type parameter defaults must not depend on generic parameters - --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:12:21 + --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:11:21 | LL | struct Bar(T); | ^ the anonymous constant must not depend on the parameter `N` diff --git a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs index 51f0cff3f21..845c6111b59 100644 --- a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs +++ b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs @@ -2,7 +2,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] struct Foo()]>(T, U); //[full]~^ ERROR constant values inside of type parameter defaults diff --git a/src/test/ui/const-generics/promotion.rs b/src/test/ui/const-generics/promotion.rs index ac568bb75f0..ce9a1a0feb4 100644 --- a/src/test/ui/const-generics/promotion.rs +++ b/src/test/ui/const-generics/promotion.rs @@ -1,7 +1,5 @@ // run-pass // tests that promoting expressions containing const parameters is allowed. -#![feature(min_const_generics)] - fn promotion_test() -> &'static usize { &(3 + N) } diff --git a/src/test/ui/const-generics/raw-ptr-const-param-deref.full.stderr b/src/test/ui/const-generics/raw-ptr-const-param-deref.full.stderr index ffaab51f766..04bc46cb4ab 100644 --- a/src/test/ui/const-generics/raw-ptr-const-param-deref.full.stderr +++ b/src/test/ui/const-generics/raw-ptr-const-param-deref.full.stderr @@ -1,11 +1,11 @@ error: using raw pointers as const generic parameters is forbidden - --> $DIR/raw-ptr-const-param-deref.rs:10:23 + --> $DIR/raw-ptr-const-param-deref.rs:9:23 | LL | struct Const; | ^^^^^^^^^^ error: using raw pointers as const generic parameters is forbidden - --> $DIR/raw-ptr-const-param-deref.rs:12:15 + --> $DIR/raw-ptr-const-param-deref.rs:11:15 | LL | impl Const

{ | ^^^^^^^^^^ diff --git a/src/test/ui/const-generics/raw-ptr-const-param-deref.min.stderr b/src/test/ui/const-generics/raw-ptr-const-param-deref.min.stderr index ffaab51f766..04bc46cb4ab 100644 --- a/src/test/ui/const-generics/raw-ptr-const-param-deref.min.stderr +++ b/src/test/ui/const-generics/raw-ptr-const-param-deref.min.stderr @@ -1,11 +1,11 @@ error: using raw pointers as const generic parameters is forbidden - --> $DIR/raw-ptr-const-param-deref.rs:10:23 + --> $DIR/raw-ptr-const-param-deref.rs:9:23 | LL | struct Const; | ^^^^^^^^^^ error: using raw pointers as const generic parameters is forbidden - --> $DIR/raw-ptr-const-param-deref.rs:12:15 + --> $DIR/raw-ptr-const-param-deref.rs:11:15 | LL | impl Const

{ | ^^^^^^^^^^ diff --git a/src/test/ui/const-generics/raw-ptr-const-param-deref.rs b/src/test/ui/const-generics/raw-ptr-const-param-deref.rs index 20cc62ebc17..ca7d33c0eb9 100644 --- a/src/test/ui/const-generics/raw-ptr-const-param-deref.rs +++ b/src/test/ui/const-generics/raw-ptr-const-param-deref.rs @@ -3,7 +3,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] const A: u32 = 3; diff --git a/src/test/ui/const-generics/raw-ptr-const-param.full.stderr b/src/test/ui/const-generics/raw-ptr-const-param.full.stderr index d317aa0f585..310422aafcd 100644 --- a/src/test/ui/const-generics/raw-ptr-const-param.full.stderr +++ b/src/test/ui/const-generics/raw-ptr-const-param.full.stderr @@ -1,5 +1,5 @@ error: using raw pointers as const generic parameters is forbidden - --> $DIR/raw-ptr-const-param.rs:7:23 + --> $DIR/raw-ptr-const-param.rs:6:23 | LL | struct Const; | ^^^^^^^^^^ diff --git a/src/test/ui/const-generics/raw-ptr-const-param.min.stderr b/src/test/ui/const-generics/raw-ptr-const-param.min.stderr index d317aa0f585..310422aafcd 100644 --- a/src/test/ui/const-generics/raw-ptr-const-param.min.stderr +++ b/src/test/ui/const-generics/raw-ptr-const-param.min.stderr @@ -1,5 +1,5 @@ error: using raw pointers as const generic parameters is forbidden - --> $DIR/raw-ptr-const-param.rs:7:23 + --> $DIR/raw-ptr-const-param.rs:6:23 | LL | struct Const; | ^^^^^^^^^^ diff --git a/src/test/ui/const-generics/raw-ptr-const-param.rs b/src/test/ui/const-generics/raw-ptr-const-param.rs index 36e593aa210..a04c6d5e64e 100644 --- a/src/test/ui/const-generics/raw-ptr-const-param.rs +++ b/src/test/ui/const-generics/raw-ptr-const-param.rs @@ -2,7 +2,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] struct Const; //~ ERROR: using raw pointers as const generic parameters diff --git a/src/test/ui/const-generics/slice-const-param-mismatch.full.stderr b/src/test/ui/const-generics/slice-const-param-mismatch.full.stderr index d06da2ef063..80dd1be33c2 100644 --- a/src/test/ui/const-generics/slice-const-param-mismatch.full.stderr +++ b/src/test/ui/const-generics/slice-const-param-mismatch.full.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/slice-const-param-mismatch.rs:15:35 + --> $DIR/slice-const-param-mismatch.rs:14:35 | LL | let _: ConstString<"Hello"> = ConstString::<"World">; | -------------------- ^^^^^^^^^^^^^^^^^^^^^^ expected `"Hello"`, found `"World"` @@ -10,7 +10,7 @@ LL | let _: ConstString<"Hello"> = ConstString::<"World">; found struct `ConstString<"World">` error[E0308]: mismatched types - --> $DIR/slice-const-param-mismatch.rs:17:33 + --> $DIR/slice-const-param-mismatch.rs:16:33 | LL | let _: ConstString<"ℇ㇈↦"> = ConstString::<"ℇ㇈↥">; | ------------------- ^^^^^^^^^^^^^^^^^^^^^ expected `"ℇ㇈↦"`, found `"ℇ㇈↥"` @@ -21,7 +21,7 @@ LL | let _: ConstString<"ℇ㇈↦"> = ConstString::<"ℇ㇈↥">; found struct `ConstString<"ℇ㇈↥">` error[E0308]: mismatched types - --> $DIR/slice-const-param-mismatch.rs:19:33 + --> $DIR/slice-const-param-mismatch.rs:18:33 | LL | let _: ConstBytes = ConstBytes::; | ------------------ ^^^^^^^^^^^^^^^^^^^^ expected `b"AAA"`, found `b"BBB"` diff --git a/src/test/ui/const-generics/slice-const-param-mismatch.min.stderr b/src/test/ui/const-generics/slice-const-param-mismatch.min.stderr index 46997fed770..13d0b217ed2 100644 --- a/src/test/ui/const-generics/slice-const-param-mismatch.min.stderr +++ b/src/test/ui/const-generics/slice-const-param-mismatch.min.stderr @@ -1,5 +1,5 @@ error: `&'static str` is forbidden as the type of a const generic parameter - --> $DIR/slice-const-param-mismatch.rs:8:29 + --> $DIR/slice-const-param-mismatch.rs:7:29 | LL | struct ConstString; | ^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | struct ConstString; = help: more complex types are supported with `#[feature(const_generics)]` error: `&'static [u8]` is forbidden as the type of a const generic parameter - --> $DIR/slice-const-param-mismatch.rs:10:28 + --> $DIR/slice-const-param-mismatch.rs:9:28 | LL | struct ConstBytes; | ^^^^^^^^^^^^^ diff --git a/src/test/ui/const-generics/slice-const-param-mismatch.rs b/src/test/ui/const-generics/slice-const-param-mismatch.rs index 0f8ae9bac4a..f020e2bf66f 100644 --- a/src/test/ui/const-generics/slice-const-param-mismatch.rs +++ b/src/test/ui/const-generics/slice-const-param-mismatch.rs @@ -2,7 +2,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] struct ConstString; diff --git a/src/test/ui/const-generics/slice-const-param.min.stderr b/src/test/ui/const-generics/slice-const-param.min.stderr index 7a9f65233e7..821c6e3995a 100644 --- a/src/test/ui/const-generics/slice-const-param.min.stderr +++ b/src/test/ui/const-generics/slice-const-param.min.stderr @@ -1,5 +1,5 @@ error: `&'static str` is forbidden as the type of a const generic parameter - --> $DIR/slice-const-param.rs:8:40 + --> $DIR/slice-const-param.rs:7:40 | LL | pub fn function_with_str() -> &'static str { | ^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | pub fn function_with_str() -> &'static str { = help: more complex types are supported with `#[feature(const_generics)]` error: `&'static [u8]` is forbidden as the type of a const generic parameter - --> $DIR/slice-const-param.rs:13:41 + --> $DIR/slice-const-param.rs:12:41 | LL | pub fn function_with_bytes() -> &'static [u8] { | ^^^^^^^^^^^^^ diff --git a/src/test/ui/const-generics/slice-const-param.rs b/src/test/ui/const-generics/slice-const-param.rs index f76e948c4af..bf1bf8af922 100644 --- a/src/test/ui/const-generics/slice-const-param.rs +++ b/src/test/ui/const-generics/slice-const-param.rs @@ -3,7 +3,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] pub fn function_with_str() -> &'static str { //[min]~^ ERROR `&'static str` is forbidden diff --git a/src/test/ui/const-generics/std/const-generics-range.min.stderr b/src/test/ui/const-generics/std/const-generics-range.min.stderr index 9274ccd2b92..d7d2a8447e9 100644 --- a/src/test/ui/const-generics/std/const-generics-range.min.stderr +++ b/src/test/ui/const-generics/std/const-generics-range.min.stderr @@ -1,5 +1,5 @@ error: `std::ops::Range` is forbidden as the type of a const generic parameter - --> $DIR/const-generics-range.rs:8:24 + --> $DIR/const-generics-range.rs:7:24 | LL | struct _Range>; | ^^^^^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | struct _Range>; = help: more complex types are supported with `#[feature(const_generics)]` error: `RangeFrom` is forbidden as the type of a const generic parameter - --> $DIR/const-generics-range.rs:13:28 + --> $DIR/const-generics-range.rs:12:28 | LL | struct _RangeFrom>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | struct _RangeFrom>; = help: more complex types are supported with `#[feature(const_generics)]` error: `RangeFull` is forbidden as the type of a const generic parameter - --> $DIR/const-generics-range.rs:18:28 + --> $DIR/const-generics-range.rs:17:28 | LL | struct _RangeFull; | ^^^^^^^^^^^^^^^^^^^ @@ -26,7 +26,7 @@ LL | struct _RangeFull; = help: more complex types are supported with `#[feature(const_generics)]` error: `RangeInclusive` is forbidden as the type of a const generic parameter - --> $DIR/const-generics-range.rs:24:33 + --> $DIR/const-generics-range.rs:23:33 | LL | struct _RangeInclusive>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -35,7 +35,7 @@ LL | struct _RangeInclusive>; = help: more complex types are supported with `#[feature(const_generics)]` error: `RangeTo` is forbidden as the type of a const generic parameter - --> $DIR/const-generics-range.rs:29:26 + --> $DIR/const-generics-range.rs:28:26 | LL | struct _RangeTo>; | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -44,7 +44,7 @@ LL | struct _RangeTo>; = help: more complex types are supported with `#[feature(const_generics)]` error: `RangeToInclusive` is forbidden as the type of a const generic parameter - --> $DIR/const-generics-range.rs:34:35 + --> $DIR/const-generics-range.rs:33:35 | LL | struct _RangeToInclusive>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/const-generics/std/const-generics-range.rs b/src/test/ui/const-generics/std/const-generics-range.rs index 136ac352890..deaab830e91 100644 --- a/src/test/ui/const-generics/std/const-generics-range.rs +++ b/src/test/ui/const-generics/std/const-generics-range.rs @@ -2,7 +2,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] // `Range` should be usable within const generics: struct _Range>; diff --git a/src/test/ui/const-generics/struct-with-invalid-const-param.full.stderr b/src/test/ui/const-generics/struct-with-invalid-const-param.full.stderr index e73a297c878..db998033c0a 100644 --- a/src/test/ui/const-generics/struct-with-invalid-const-param.full.stderr +++ b/src/test/ui/const-generics/struct-with-invalid-const-param.full.stderr @@ -1,5 +1,5 @@ error[E0573]: expected type, found const parameter `C` - --> $DIR/struct-with-invalid-const-param.rs:8:23 + --> $DIR/struct-with-invalid-const-param.rs:7:23 | LL | struct S(C); | ^ not a type diff --git a/src/test/ui/const-generics/struct-with-invalid-const-param.min.stderr b/src/test/ui/const-generics/struct-with-invalid-const-param.min.stderr index e73a297c878..db998033c0a 100644 --- a/src/test/ui/const-generics/struct-with-invalid-const-param.min.stderr +++ b/src/test/ui/const-generics/struct-with-invalid-const-param.min.stderr @@ -1,5 +1,5 @@ error[E0573]: expected type, found const parameter `C` - --> $DIR/struct-with-invalid-const-param.rs:8:23 + --> $DIR/struct-with-invalid-const-param.rs:7:23 | LL | struct S(C); | ^ not a type diff --git a/src/test/ui/const-generics/struct-with-invalid-const-param.rs b/src/test/ui/const-generics/struct-with-invalid-const-param.rs index f0122ace3ae..32970ccaa5d 100644 --- a/src/test/ui/const-generics/struct-with-invalid-const-param.rs +++ b/src/test/ui/const-generics/struct-with-invalid-const-param.rs @@ -3,7 +3,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] struct S(C); //~ ERROR expected type, found const parameter diff --git a/src/test/ui/const-generics/trait-const-args.rs b/src/test/ui/const-generics/trait-const-args.rs index b66d79845f9..30d05c708e1 100644 --- a/src/test/ui/const-generics/trait-const-args.rs +++ b/src/test/ui/const-generics/trait-const-args.rs @@ -3,7 +3,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] struct Const; trait Foo {} diff --git a/src/test/ui/const-generics/transparent-maybeunit-array-wrapper.rs b/src/test/ui/const-generics/transparent-maybeunit-array-wrapper.rs index e041e9709d0..bf855d4dcaa 100644 --- a/src/test/ui/const-generics/transparent-maybeunit-array-wrapper.rs +++ b/src/test/ui/const-generics/transparent-maybeunit-array-wrapper.rs @@ -3,7 +3,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] use std::mem::MaybeUninit; diff --git a/src/test/ui/const-generics/type-after-const-ok.min.stderr b/src/test/ui/const-generics/type-after-const-ok.min.stderr index 67a44d2c5b4..ad38754c741 100644 --- a/src/test/ui/const-generics/type-after-const-ok.min.stderr +++ b/src/test/ui/const-generics/type-after-const-ok.min.stderr @@ -1,5 +1,5 @@ error: type parameters must be declared prior to const parameters - --> $DIR/type-after-const-ok.rs:9:26 + --> $DIR/type-after-const-ok.rs:8:26 | LL | struct A(T); | -----------------^- help: reorder the parameters: lifetimes, then types, then consts: `` diff --git a/src/test/ui/const-generics/type-after-const-ok.rs b/src/test/ui/const-generics/type-after-const-ok.rs index 69227cdf19c..920c067dc1a 100644 --- a/src/test/ui/const-generics/type-after-const-ok.rs +++ b/src/test/ui/const-generics/type-after-const-ok.rs @@ -3,7 +3,6 @@ // Verifies that having generic parameters after constants is permitted #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] #[allow(dead_code)] struct A(T); diff --git a/src/test/ui/const-generics/type-dependent/auxiliary/type_dependent_lib.rs b/src/test/ui/const-generics/type-dependent/auxiliary/type_dependent_lib.rs index aa85376bf0d..cd9c3ae7bbc 100644 --- a/src/test/ui/const-generics/type-dependent/auxiliary/type_dependent_lib.rs +++ b/src/test/ui/const-generics/type-dependent/auxiliary/type_dependent_lib.rs @@ -1,6 +1,5 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] pub struct Struct(()); diff --git a/src/test/ui/const-generics/type-dependent/const-arg-in-const-arg.rs b/src/test/ui/const-generics/type-dependent/const-arg-in-const-arg.rs index 3ccdd472613..4997d493bbb 100644 --- a/src/test/ui/const-generics/type-dependent/const-arg-in-const-arg.rs +++ b/src/test/ui/const-generics/type-dependent/const-arg-in-const-arg.rs @@ -1,7 +1,6 @@ // run-pass // revisions: full min #![cfg_attr(full, feature(const_generics))] -#![cfg_attr(min, feature(min_const_generics))] #![allow(incomplete_features)] struct Foo; diff --git a/src/test/ui/const-generics/type-dependent/issue-61936.rs b/src/test/ui/const-generics/type-dependent/issue-61936.rs index f3b19109a7c..417fe2501ae 100644 --- a/src/test/ui/const-generics/type-dependent/issue-61936.rs +++ b/src/test/ui/const-generics/type-dependent/issue-61936.rs @@ -2,7 +2,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] trait SliceExt { fn array_windows_example<'a, const N: usize>(&'a self) -> ArrayWindowsExample<'a, T, N>; diff --git a/src/test/ui/const-generics/type-dependent/issue-63695.rs b/src/test/ui/const-generics/type-dependent/issue-63695.rs index 465b66b09ce..2ece25bb41b 100644 --- a/src/test/ui/const-generics/type-dependent/issue-63695.rs +++ b/src/test/ui/const-generics/type-dependent/issue-63695.rs @@ -2,7 +2,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] trait T { fn test(&self) -> i32 { A } diff --git a/src/test/ui/const-generics/type-dependent/issue-67144-1.rs b/src/test/ui/const-generics/type-dependent/issue-67144-1.rs index 3d4910e9e4b..4a2c303095e 100644 --- a/src/test/ui/const-generics/type-dependent/issue-67144-1.rs +++ b/src/test/ui/const-generics/type-dependent/issue-67144-1.rs @@ -2,7 +2,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] struct X; diff --git a/src/test/ui/const-generics/type-dependent/issue-67144-2.rs b/src/test/ui/const-generics/type-dependent/issue-67144-2.rs index 0868d309b33..a1163fca8d4 100644 --- a/src/test/ui/const-generics/type-dependent/issue-67144-2.rs +++ b/src/test/ui/const-generics/type-dependent/issue-67144-2.rs @@ -2,7 +2,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] struct A; diff --git a/src/test/ui/const-generics/type-dependent/issue-69816.rs b/src/test/ui/const-generics/type-dependent/issue-69816.rs index 4a374dc1db6..75ddd839f66 100644 --- a/src/test/ui/const-generics/type-dependent/issue-69816.rs +++ b/src/test/ui/const-generics/type-dependent/issue-69816.rs @@ -2,7 +2,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] trait IterExt: Sized + Iterator { fn default_for_size(self) -> [Self::Item; N] diff --git a/src/test/ui/const-generics/type-dependent/issue-70217.rs b/src/test/ui/const-generics/type-dependent/issue-70217.rs index ba5a42e47e9..b3585d5fc10 100644 --- a/src/test/ui/const-generics/type-dependent/issue-70217.rs +++ b/src/test/ui/const-generics/type-dependent/issue-70217.rs @@ -3,7 +3,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] struct Struct; diff --git a/src/test/ui/const-generics/type-dependent/issue-70507.rs b/src/test/ui/const-generics/type-dependent/issue-70507.rs index 234c09e04ae..df7c277f605 100644 --- a/src/test/ui/const-generics/type-dependent/issue-70507.rs +++ b/src/test/ui/const-generics/type-dependent/issue-70507.rs @@ -2,7 +2,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] trait ConstChunksExactTrait { fn const_chunks_exact(&self) -> ConstChunksExact<'_, T, {N}>; diff --git a/src/test/ui/const-generics/type-dependent/issue-70586.rs b/src/test/ui/const-generics/type-dependent/issue-70586.rs index fd52373cee2..5fb571f2394 100644 --- a/src/test/ui/const-generics/type-dependent/issue-70586.rs +++ b/src/test/ui/const-generics/type-dependent/issue-70586.rs @@ -2,7 +2,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] use std::marker::PhantomData; diff --git a/src/test/ui/const-generics/type-dependent/issue-71348.min.stderr b/src/test/ui/const-generics/type-dependent/issue-71348.min.stderr index 8f240f0d930..92f5d815a0f 100644 --- a/src/test/ui/const-generics/type-dependent/issue-71348.min.stderr +++ b/src/test/ui/const-generics/type-dependent/issue-71348.min.stderr @@ -1,5 +1,5 @@ error: `&'static str` is forbidden as the type of a const generic parameter - --> $DIR/issue-71348.rs:11:24 + --> $DIR/issue-71348.rs:10:24 | LL | trait Get<'a, const N: &'static str> { | ^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | trait Get<'a, const N: &'static str> { = help: more complex types are supported with `#[feature(const_generics)]` error: `&'static str` is forbidden as the type of a const generic parameter - --> $DIR/issue-71348.rs:19:25 + --> $DIR/issue-71348.rs:18:25 | LL | fn ask<'a, const N: &'static str>(&'a self) -> &'a >::Target | ^^^^^^^^^^^^ diff --git a/src/test/ui/const-generics/type-dependent/issue-71348.rs b/src/test/ui/const-generics/type-dependent/issue-71348.rs index 772e179746d..33735ef87c5 100644 --- a/src/test/ui/const-generics/type-dependent/issue-71348.rs +++ b/src/test/ui/const-generics/type-dependent/issue-71348.rs @@ -2,7 +2,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] struct Foo { i: i32, diff --git a/src/test/ui/const-generics/type-dependent/issue-71382.full.stderr b/src/test/ui/const-generics/type-dependent/issue-71382.full.stderr index da1d3270b7c..8ac9bab6320 100644 --- a/src/test/ui/const-generics/type-dependent/issue-71382.full.stderr +++ b/src/test/ui/const-generics/type-dependent/issue-71382.full.stderr @@ -1,5 +1,5 @@ error: using function pointers as const generic parameters is forbidden - --> $DIR/issue-71382.rs:17:23 + --> $DIR/issue-71382.rs:16:23 | LL | fn test u8>(&self) -> u8 { | ^^^^^^^^^^ diff --git a/src/test/ui/const-generics/type-dependent/issue-71382.min.stderr b/src/test/ui/const-generics/type-dependent/issue-71382.min.stderr index da1d3270b7c..8ac9bab6320 100644 --- a/src/test/ui/const-generics/type-dependent/issue-71382.min.stderr +++ b/src/test/ui/const-generics/type-dependent/issue-71382.min.stderr @@ -1,5 +1,5 @@ error: using function pointers as const generic parameters is forbidden - --> $DIR/issue-71382.rs:17:23 + --> $DIR/issue-71382.rs:16:23 | LL | fn test u8>(&self) -> u8 { | ^^^^^^^^^^ diff --git a/src/test/ui/const-generics/type-dependent/issue-71382.rs b/src/test/ui/const-generics/type-dependent/issue-71382.rs index 497fd1381de..b3677613dbc 100644 --- a/src/test/ui/const-generics/type-dependent/issue-71382.rs +++ b/src/test/ui/const-generics/type-dependent/issue-71382.rs @@ -1,7 +1,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] struct Test; diff --git a/src/test/ui/const-generics/type-dependent/issue-71805.rs b/src/test/ui/const-generics/type-dependent/issue-71805.rs index 2aaf12cea4f..3701e14eadc 100644 --- a/src/test/ui/const-generics/type-dependent/issue-71805.rs +++ b/src/test/ui/const-generics/type-dependent/issue-71805.rs @@ -2,7 +2,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] use std::mem::MaybeUninit; diff --git a/src/test/ui/const-generics/type-dependent/issue-73730.rs b/src/test/ui/const-generics/type-dependent/issue-73730.rs index 3e53190ee48..5d7dcb9c458 100644 --- a/src/test/ui/const-generics/type-dependent/issue-73730.rs +++ b/src/test/ui/const-generics/type-dependent/issue-73730.rs @@ -2,7 +2,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] trait Foo<'a, A>: Iterator { fn bar(&mut self) -> *const [A; N]; diff --git a/src/test/ui/const-generics/type-dependent/non-local.rs b/src/test/ui/const-generics/type-dependent/non-local.rs index 747664a0962..9e4afba3114 100644 --- a/src/test/ui/const-generics/type-dependent/non-local.rs +++ b/src/test/ui/const-generics/type-dependent/non-local.rs @@ -3,7 +3,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] extern crate type_dependent_lib; diff --git a/src/test/ui/const-generics/type-dependent/qpath.rs b/src/test/ui/const-generics/type-dependent/qpath.rs index ec23ff1d221..b61e970cfb3 100644 --- a/src/test/ui/const-generics/type-dependent/qpath.rs +++ b/src/test/ui/const-generics/type-dependent/qpath.rs @@ -2,7 +2,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] struct A; impl A { diff --git a/src/test/ui/const-generics/type-dependent/simple.rs b/src/test/ui/const-generics/type-dependent/simple.rs index 70af6550923..a4776a43b21 100644 --- a/src/test/ui/const-generics/type-dependent/simple.rs +++ b/src/test/ui/const-generics/type-dependent/simple.rs @@ -2,7 +2,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] struct R; diff --git a/src/test/ui/const-generics/type-dependent/type-mismatch.full.stderr b/src/test/ui/const-generics/type-dependent/type-mismatch.full.stderr index a530e63449d..b942c397a8d 100644 --- a/src/test/ui/const-generics/type-dependent/type-mismatch.full.stderr +++ b/src/test/ui/const-generics/type-dependent/type-mismatch.full.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/type-mismatch.rs:12:27 + --> $DIR/type-mismatch.rs:11:27 | LL | assert_eq!(R.method::<1u16>(), 1); | ^^^^ expected `u8`, found `u16` diff --git a/src/test/ui/const-generics/type-dependent/type-mismatch.min.stderr b/src/test/ui/const-generics/type-dependent/type-mismatch.min.stderr index a530e63449d..b942c397a8d 100644 --- a/src/test/ui/const-generics/type-dependent/type-mismatch.min.stderr +++ b/src/test/ui/const-generics/type-dependent/type-mismatch.min.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/type-mismatch.rs:12:27 + --> $DIR/type-mismatch.rs:11:27 | LL | assert_eq!(R.method::<1u16>(), 1); | ^^^^ expected `u8`, found `u16` diff --git a/src/test/ui/const-generics/type-dependent/type-mismatch.rs b/src/test/ui/const-generics/type-dependent/type-mismatch.rs index 67d80973f03..7fba1afe918 100644 --- a/src/test/ui/const-generics/type-dependent/type-mismatch.rs +++ b/src/test/ui/const-generics/type-dependent/type-mismatch.rs @@ -1,7 +1,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] struct R; diff --git a/src/test/ui/const-generics/type_of_anon_const.rs b/src/test/ui/const-generics/type_of_anon_const.rs index f424fd03341..9a2e9f09319 100644 --- a/src/test/ui/const-generics/type_of_anon_const.rs +++ b/src/test/ui/const-generics/type_of_anon_const.rs @@ -3,7 +3,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] trait T { fn l() -> usize; diff --git a/src/test/ui/const-generics/types-mismatch-const-args.full.stderr b/src/test/ui/const-generics/types-mismatch-const-args.full.stderr index 265e9ee618b..480ecdb3873 100644 --- a/src/test/ui/const-generics/types-mismatch-const-args.full.stderr +++ b/src/test/ui/const-generics/types-mismatch-const-args.full.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/types-mismatch-const-args.rs:15:41 + --> $DIR/types-mismatch-const-args.rs:14:41 | LL | let _: A<'a, u32, {2u32}, {3u32}> = A::<'a, u32, {4u32}, {3u32}> { data: PhantomData }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `2_u32`, found `4_u32` @@ -8,7 +8,7 @@ LL | let _: A<'a, u32, {2u32}, {3u32}> = A::<'a, u32, {4u32}, {3u32}> { data found type `4_u32` error[E0308]: mismatched types - --> $DIR/types-mismatch-const-args.rs:17:41 + --> $DIR/types-mismatch-const-args.rs:16:41 | LL | let _: A<'a, u16, {2u32}, {3u32}> = A::<'b, u32, {2u32}, {3u32}> { data: PhantomData }; | -------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `u16`, found `u32` diff --git a/src/test/ui/const-generics/types-mismatch-const-args.min.stderr b/src/test/ui/const-generics/types-mismatch-const-args.min.stderr index 27277f0c0be..c19c8db737a 100644 --- a/src/test/ui/const-generics/types-mismatch-const-args.min.stderr +++ b/src/test/ui/const-generics/types-mismatch-const-args.min.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/types-mismatch-const-args.rs:15:41 + --> $DIR/types-mismatch-const-args.rs:14:41 | LL | let _: A<'a, u32, {2u32}, {3u32}> = A::<'a, u32, {4u32}, {3u32}> { data: PhantomData }; | -------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `2_u32`, found `4_u32` @@ -10,7 +10,7 @@ LL | let _: A<'a, u32, {2u32}, {3u32}> = A::<'a, u32, {4u32}, {3u32}> { data found struct `A<'_, _, 4_u32, _>` error[E0308]: mismatched types - --> $DIR/types-mismatch-const-args.rs:17:41 + --> $DIR/types-mismatch-const-args.rs:16:41 | LL | let _: A<'a, u16, {2u32}, {3u32}> = A::<'b, u32, {2u32}, {3u32}> { data: PhantomData }; | -------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `u16`, found `u32` diff --git a/src/test/ui/const-generics/types-mismatch-const-args.rs b/src/test/ui/const-generics/types-mismatch-const-args.rs index 34b85304cc4..14cef083d83 100644 --- a/src/test/ui/const-generics/types-mismatch-const-args.rs +++ b/src/test/ui/const-generics/types-mismatch-const-args.rs @@ -1,7 +1,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] // tests the diagnostic output of type mismatches for types that have const generics arguments. diff --git a/src/test/ui/const-generics/uninferred-consts-during-codegen-1.rs b/src/test/ui/const-generics/uninferred-consts-during-codegen-1.rs index 45afbdc9ab1..9592f266230 100644 --- a/src/test/ui/const-generics/uninferred-consts-during-codegen-1.rs +++ b/src/test/ui/const-generics/uninferred-consts-during-codegen-1.rs @@ -2,7 +2,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] use std::fmt; diff --git a/src/test/ui/const-generics/uninferred-consts-during-codegen-2.rs b/src/test/ui/const-generics/uninferred-consts-during-codegen-2.rs index 65ae05e1198..4bab2bb5a77 100644 --- a/src/test/ui/const-generics/uninferred-consts-during-codegen-2.rs +++ b/src/test/ui/const-generics/uninferred-consts-during-codegen-2.rs @@ -2,7 +2,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] use std::fmt; diff --git a/src/test/ui/const-generics/unknown_adt.full.stderr b/src/test/ui/const-generics/unknown_adt.full.stderr index 94f3165eaec..b8b2e90aa66 100644 --- a/src/test/ui/const-generics/unknown_adt.full.stderr +++ b/src/test/ui/const-generics/unknown_adt.full.stderr @@ -1,5 +1,5 @@ error[E0412]: cannot find type `UnknownStruct` in this scope - --> $DIR/unknown_adt.rs:8:12 + --> $DIR/unknown_adt.rs:7:12 | LL | let _: UnknownStruct<7>; | ^^^^^^^^^^^^^ not found in this scope diff --git a/src/test/ui/const-generics/unknown_adt.min.stderr b/src/test/ui/const-generics/unknown_adt.min.stderr index 94f3165eaec..b8b2e90aa66 100644 --- a/src/test/ui/const-generics/unknown_adt.min.stderr +++ b/src/test/ui/const-generics/unknown_adt.min.stderr @@ -1,5 +1,5 @@ error[E0412]: cannot find type `UnknownStruct` in this scope - --> $DIR/unknown_adt.rs:8:12 + --> $DIR/unknown_adt.rs:7:12 | LL | let _: UnknownStruct<7>; | ^^^^^^^^^^^^^ not found in this scope diff --git a/src/test/ui/const-generics/unknown_adt.rs b/src/test/ui/const-generics/unknown_adt.rs index c6131402aeb..977f90aad11 100644 --- a/src/test/ui/const-generics/unknown_adt.rs +++ b/src/test/ui/const-generics/unknown_adt.rs @@ -2,7 +2,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] fn main() { let _: UnknownStruct<7>; diff --git a/src/test/ui/const-generics/unused-const-param.rs b/src/test/ui/const-generics/unused-const-param.rs index 3c305167b4b..2918e399dc8 100644 --- a/src/test/ui/const-generics/unused-const-param.rs +++ b/src/test/ui/const-generics/unused-const-param.rs @@ -3,7 +3,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] struct A; // ok diff --git a/src/test/ui/const-generics/unused_braces.full.fixed b/src/test/ui/const-generics/unused_braces.full.fixed index 1b075ade16a..46d57e0dcfc 100644 --- a/src/test/ui/const-generics/unused_braces.full.fixed +++ b/src/test/ui/const-generics/unused_braces.full.fixed @@ -4,7 +4,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] #![warn(unused_braces)] diff --git a/src/test/ui/const-generics/unused_braces.full.stderr b/src/test/ui/const-generics/unused_braces.full.stderr index 1752779a60a..8899139aa6b 100644 --- a/src/test/ui/const-generics/unused_braces.full.stderr +++ b/src/test/ui/const-generics/unused_braces.full.stderr @@ -1,11 +1,11 @@ warning: unnecessary braces around const expression - --> $DIR/unused_braces.rs:15:14 + --> $DIR/unused_braces.rs:14:14 | LL | let _: A<{ 7 }>; | ^^^^^ help: remove these braces | note: the lint level is defined here - --> $DIR/unused_braces.rs:8:9 + --> $DIR/unused_braces.rs:7:9 | LL | #![warn(unused_braces)] | ^^^^^^^^^^^^^ diff --git a/src/test/ui/const-generics/unused_braces.min.fixed b/src/test/ui/const-generics/unused_braces.min.fixed index 1b075ade16a..46d57e0dcfc 100644 --- a/src/test/ui/const-generics/unused_braces.min.fixed +++ b/src/test/ui/const-generics/unused_braces.min.fixed @@ -4,7 +4,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] #![warn(unused_braces)] diff --git a/src/test/ui/const-generics/unused_braces.min.stderr b/src/test/ui/const-generics/unused_braces.min.stderr index 1752779a60a..8899139aa6b 100644 --- a/src/test/ui/const-generics/unused_braces.min.stderr +++ b/src/test/ui/const-generics/unused_braces.min.stderr @@ -1,11 +1,11 @@ warning: unnecessary braces around const expression - --> $DIR/unused_braces.rs:15:14 + --> $DIR/unused_braces.rs:14:14 | LL | let _: A<{ 7 }>; | ^^^^^ help: remove these braces | note: the lint level is defined here - --> $DIR/unused_braces.rs:8:9 + --> $DIR/unused_braces.rs:7:9 | LL | #![warn(unused_braces)] | ^^^^^^^^^^^^^ diff --git a/src/test/ui/const-generics/unused_braces.rs b/src/test/ui/const-generics/unused_braces.rs index 31c4caf7ab8..0348bbacaab 100644 --- a/src/test/ui/const-generics/unused_braces.rs +++ b/src/test/ui/const-generics/unused_braces.rs @@ -4,7 +4,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] #![warn(unused_braces)] diff --git a/src/test/ui/const-generics/wf-misc.full.stderr b/src/test/ui/const-generics/wf-misc.full.stderr index 4af48fa1590..dfb593a9507 100644 --- a/src/test/ui/const-generics/wf-misc.full.stderr +++ b/src/test/ui/const-generics/wf-misc.full.stderr @@ -1,5 +1,5 @@ error: constant expression depends on a generic parameter - --> $DIR/wf-misc.rs:9:12 + --> $DIR/wf-misc.rs:8:12 | LL | let _: [u8; N + 1]; | ^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | let _: [u8; N + 1]; = note: this may fail depending on what value the parameter takes error: constant expression depends on a generic parameter - --> $DIR/wf-misc.rs:17:12 + --> $DIR/wf-misc.rs:16:12 | LL | let _: Const::<{N + 1}>; | ^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/const-generics/wf-misc.min.stderr b/src/test/ui/const-generics/wf-misc.min.stderr index 99142cb6ce7..9967a2218f6 100644 --- a/src/test/ui/const-generics/wf-misc.min.stderr +++ b/src/test/ui/const-generics/wf-misc.min.stderr @@ -1,5 +1,5 @@ error: generic parameters may not be used in const operations - --> $DIR/wf-misc.rs:9:17 + --> $DIR/wf-misc.rs:8:17 | LL | let _: [u8; N + 1]; | ^ cannot perform const operation using `N` @@ -8,7 +8,7 @@ LL | let _: [u8; N + 1]; = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: generic parameters may not be used in const operations - --> $DIR/wf-misc.rs:17:21 + --> $DIR/wf-misc.rs:16:21 | LL | let _: Const::<{N + 1}>; | ^ cannot perform const operation using `N` diff --git a/src/test/ui/const-generics/wf-misc.rs b/src/test/ui/const-generics/wf-misc.rs index 103c580f28f..8a5b6ddfe26 100644 --- a/src/test/ui/const-generics/wf-misc.rs +++ b/src/test/ui/const-generics/wf-misc.rs @@ -3,7 +3,6 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] pub fn arr_len() { let _: [u8; N + 1]; diff --git a/src/test/ui/const-generics/where-clauses.rs b/src/test/ui/const-generics/where-clauses.rs index cdcaf250942..dc09cad3180 100644 --- a/src/test/ui/const-generics/where-clauses.rs +++ b/src/test/ui/const-generics/where-clauses.rs @@ -2,7 +2,6 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] -#![cfg_attr(min, feature(min_const_generics))] trait Bar { fn bar() {} } trait Foo: Bar {} diff --git a/src/test/ui/const-ptr/out_of_bounds_read.rs b/src/test/ui/const-ptr/out_of_bounds_read.rs new file mode 100644 index 00000000000..183aa9e5122 --- /dev/null +++ b/src/test/ui/const-ptr/out_of_bounds_read.rs @@ -0,0 +1,16 @@ +// error-pattern: any use of this value will cause an error + +#![feature(const_ptr_read)] +#![feature(const_ptr_offset)] + +fn main() { + use std::ptr; + + const DATA: [u32; 1] = [42]; + + const PAST_END_PTR: *const u32 = unsafe { DATA.as_ptr().add(1) }; + + const _READ: u32 = unsafe { ptr::read(PAST_END_PTR) }; + const _CONST_READ: u32 = unsafe { PAST_END_PTR.read() }; + const _MUT_READ: u32 = unsafe { (PAST_END_PTR as *mut u32).read() }; +} diff --git a/src/test/ui/const-ptr/out_of_bounds_read.stderr b/src/test/ui/const-ptr/out_of_bounds_read.stderr new file mode 100644 index 00000000000..ca65a079947 --- /dev/null +++ b/src/test/ui/const-ptr/out_of_bounds_read.stderr @@ -0,0 +1,54 @@ +error: any use of this value will cause an error + --> $SRC_DIR/core/src/intrinsics.rs:LL:COL + | +LL | unsafe { copy_nonoverlapping(src, dst, count) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | memory access failed: pointer must be in-bounds at offset 8, but is outside bounds of alloc6 which has size 4 + | inside `copy_nonoverlapping::` at $SRC_DIR/core/src/intrinsics.rs:LL:COL + | inside `std::ptr::read::` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL + | inside `_READ` at $DIR/out_of_bounds_read.rs:13:33 + | + ::: $DIR/out_of_bounds_read.rs:13:5 + | +LL | const _READ: u32 = unsafe { ptr::read(PAST_END_PTR) }; + | ------------------------------------------------------ + | + = note: `#[deny(const_err)]` on by default + +error: any use of this value will cause an error + --> $SRC_DIR/core/src/intrinsics.rs:LL:COL + | +LL | unsafe { copy_nonoverlapping(src, dst, count) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | memory access failed: pointer must be in-bounds at offset 8, but is outside bounds of alloc6 which has size 4 + | inside `copy_nonoverlapping::` at $SRC_DIR/core/src/intrinsics.rs:LL:COL + | inside `std::ptr::read::` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL + | inside `ptr::const_ptr::::read` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL + | inside `_CONST_READ` at $DIR/out_of_bounds_read.rs:14:39 + | + ::: $DIR/out_of_bounds_read.rs:14:5 + | +LL | const _CONST_READ: u32 = unsafe { PAST_END_PTR.read() }; + | -------------------------------------------------------- + +error: any use of this value will cause an error + --> $SRC_DIR/core/src/intrinsics.rs:LL:COL + | +LL | unsafe { copy_nonoverlapping(src, dst, count) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | memory access failed: pointer must be in-bounds at offset 8, but is outside bounds of alloc6 which has size 4 + | inside `copy_nonoverlapping::` at $SRC_DIR/core/src/intrinsics.rs:LL:COL + | inside `std::ptr::read::` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL + | inside `ptr::mut_ptr::::read` at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL + | inside `_MUT_READ` at $DIR/out_of_bounds_read.rs:15:37 + | + ::: $DIR/out_of_bounds_read.rs:15:5 + | +LL | const _MUT_READ: u32 = unsafe { (PAST_END_PTR as *mut u32).read() }; + | -------------------------------------------------------------------- + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/consts/const-fn-error.rs b/src/test/ui/consts/const-fn-error.rs new file mode 100644 index 00000000000..68a4d414ff3 --- /dev/null +++ b/src/test/ui/consts/const-fn-error.rs @@ -0,0 +1,21 @@ +#![feature(const_fn)] + +const X : usize = 2; + +const fn f(x: usize) -> usize { + let mut sum = 0; + for i in 0..x { + //~^ ERROR mutable references + //~| ERROR calls in constant functions + //~| ERROR calls in constant functions + //~| ERROR E0080 + //~| ERROR E0744 + sum += i; + } + sum +} + +#[allow(unused_variables)] +fn main() { + let a : [i32; f(X)]; +} diff --git a/src/test/ui/consts/const-fn-error.stderr b/src/test/ui/consts/const-fn-error.stderr new file mode 100644 index 00000000000..86b1eebcb2c --- /dev/null +++ b/src/test/ui/consts/const-fn-error.stderr @@ -0,0 +1,49 @@ +error[E0744]: `for` is not allowed in a `const fn` + --> $DIR/const-fn-error.rs:7:5 + | +LL | / for i in 0..x { +LL | | +LL | | +LL | | +... | +LL | | sum += i; +LL | | } + | |_____^ + +error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants + --> $DIR/const-fn-error.rs:7:14 + | +LL | for i in 0..x { + | ^^^^ + +error[E0658]: mutable references are not allowed in constant functions + --> $DIR/const-fn-error.rs:7:14 + | +LL | for i in 0..x { + | ^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants + --> $DIR/const-fn-error.rs:7:14 + | +LL | for i in 0..x { + | ^^^^ + +error[E0080]: evaluation of constant value failed + --> $DIR/const-fn-error.rs:7:14 + | +LL | for i in 0..x { + | ^^^^ + | | + | calling non-const function ` as IntoIterator>::into_iter` + | inside `f` at $DIR/const-fn-error.rs:7:14 +... +LL | let a : [i32; f(X)]; + | ---- inside `main::{constant#0}` at $DIR/const-fn-error.rs:20:19 + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0015, E0080, E0658, E0744. +For more information about an error, try `rustc --explain E0015`. diff --git a/src/test/ui/consts/const-size_of_val-align_of_val.rs b/src/test/ui/consts/const-size_of_val-align_of_val.rs index e8e6f1d3900..5c0d7d94d64 100644 --- a/src/test/ui/consts/const-size_of_val-align_of_val.rs +++ b/src/test/ui/consts/const-size_of_val-align_of_val.rs @@ -1,6 +1,7 @@ // run-pass #![feature(const_size_of_val, const_align_of_val)] +#![feature(const_size_of_val_raw, const_align_of_val_raw, layout_for_ptr)] use std::mem; @@ -32,6 +33,9 @@ union Ugh { const SIZE_OF_SLICE: usize = mem::size_of_val("foobar".as_bytes()); +const SIZE_OF_DANGLING: usize = unsafe { mem::size_of_val_raw(0x100 as *const i32) }; +const ALIGN_OF_DANGLING: usize = unsafe { mem::align_of_val_raw(0x100 as *const i16) }; + fn main() { assert_eq!(SIZE_OF_FOO, mem::size_of::()); assert_eq!(SIZE_OF_BAR, mem::size_of::()); @@ -41,5 +45,8 @@ fn main() { assert_eq!(ALIGN_OF_BAR, mem::align_of::()); assert_eq!(ALIGN_OF_UGH, mem::align_of::()); + assert_eq!(SIZE_OF_DANGLING, mem::size_of::()); + assert_eq!(ALIGN_OF_DANGLING, mem::align_of::()); + assert_eq!(SIZE_OF_SLICE, "foobar".len()); } diff --git a/src/test/ui/consts/issue-44415.rs b/src/test/ui/consts/issue-44415.rs new file mode 100644 index 00000000000..71e764620d1 --- /dev/null +++ b/src/test/ui/consts/issue-44415.rs @@ -0,0 +1,11 @@ +#![feature(core_intrinsics)] + +use std::intrinsics; + +struct Foo { + bytes: [u8; unsafe { intrinsics::size_of::() }], + //~^ ERROR cycle detected when simplifying constant for the type system + x: usize, +} + +fn main() {} diff --git a/src/test/ui/consts/issue-44415.stderr b/src/test/ui/consts/issue-44415.stderr new file mode 100644 index 00000000000..38841e99a72 --- /dev/null +++ b/src/test/ui/consts/issue-44415.stderr @@ -0,0 +1,28 @@ +error[E0391]: cycle detected when simplifying constant for the type system `Foo::bytes::{constant#0}` + --> $DIR/issue-44415.rs:6:17 + | +LL | bytes: [u8; unsafe { intrinsics::size_of::() }], + | ^^^^^^ + | +note: ...which requires simplifying constant for the type system `Foo::bytes::{constant#0}`... + --> $DIR/issue-44415.rs:6:17 + | +LL | bytes: [u8; unsafe { intrinsics::size_of::() }], + | ^^^^^^ +note: ...which requires const-evaluating + checking `Foo::bytes::{constant#0}`... + --> $DIR/issue-44415.rs:6:17 + | +LL | bytes: [u8; unsafe { intrinsics::size_of::() }], + | ^^^^^^ + = note: ...which requires computing layout of `Foo`... + = note: ...which requires normalizing `[u8; _]`... + = note: ...which again requires simplifying constant for the type system `Foo::bytes::{constant#0}`, completing the cycle +note: cycle used when checking that `Foo` is well-formed + --> $DIR/issue-44415.rs:5:1 + | +LL | struct Foo { + | ^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0391`. diff --git a/src/test/ui/consts/issue-55878.rs b/src/test/ui/consts/issue-55878.rs new file mode 100644 index 00000000000..c1c54646db8 --- /dev/null +++ b/src/test/ui/consts/issue-55878.rs @@ -0,0 +1,8 @@ +// build-fail +// normalize-stderr-64bit "18446744073709551615" -> "SIZE" +// normalize-stderr-32bit "4294967295" -> "SIZE" + +// error-pattern: are too big for the current architecture +fn main() { + println!("Size: {}", std::mem::size_of::<[u8; u64::MAX as usize]>()); +} diff --git a/src/test/ui/consts/issue-55878.stderr b/src/test/ui/consts/issue-55878.stderr new file mode 100644 index 00000000000..924910e9cb6 --- /dev/null +++ b/src/test/ui/consts/issue-55878.stderr @@ -0,0 +1,25 @@ +error[E0080]: values of the type `[u8; SIZE]` are too big for the current architecture + --> $SRC_DIR/core/src/mem/mod.rs:LL:COL + | +LL | intrinsics::size_of::() + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | inside `std::mem::size_of::<[u8; SIZE]>` at $SRC_DIR/core/src/mem/mod.rs:LL:COL + | inside `main` at $DIR/issue-55878.rs:7:26 + | + ::: $DIR/issue-55878.rs:7:26 + | +LL | println!("Size: {}", std::mem::size_of::<[u8; u64::MAX as usize]>()); + | ---------------------------------------------- + +error: erroneous constant used + --> $DIR/issue-55878.rs:7:26 + | +LL | println!("Size: {}", std::mem::size_of::<[u8; u64::MAX as usize]>()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors + | + = note: `#[deny(const_err)]` on by default + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/crate-loading/auxiliary/crateresolve1-1.rs b/src/test/ui/crate-loading/auxiliary/crateresolve1-1.rs new file mode 100644 index 00000000000..a00a19e46d5 --- /dev/null +++ b/src/test/ui/crate-loading/auxiliary/crateresolve1-1.rs @@ -0,0 +1,5 @@ +// compile-flags:-C extra-filename=-1 +#![crate_name = "crateresolve1"] +#![crate_type = "lib"] + +pub fn f() -> isize { 10 } diff --git a/src/test/ui/crate-loading/auxiliary/crateresolve1-2.rs b/src/test/ui/crate-loading/auxiliary/crateresolve1-2.rs new file mode 100644 index 00000000000..71cc0a12ea3 --- /dev/null +++ b/src/test/ui/crate-loading/auxiliary/crateresolve1-2.rs @@ -0,0 +1,5 @@ +// compile-flags:-C extra-filename=-2 +#![crate_name = "crateresolve1"] +#![crate_type = "lib"] + +pub fn f() -> isize { 20 } diff --git a/src/test/ui/crate-loading/auxiliary/crateresolve1-3.rs b/src/test/ui/crate-loading/auxiliary/crateresolve1-3.rs new file mode 100644 index 00000000000..921687d4c3b --- /dev/null +++ b/src/test/ui/crate-loading/auxiliary/crateresolve1-3.rs @@ -0,0 +1,5 @@ +// compile-flags:-C extra-filename=-3 +#![crate_name = "crateresolve1"] +#![crate_type = "lib"] + +pub fn f() -> isize { 30 } diff --git a/src/test/ui/crate-loading/crateresolve1.rs b/src/test/ui/crate-loading/crateresolve1.rs new file mode 100644 index 00000000000..49e47dacc3d --- /dev/null +++ b/src/test/ui/crate-loading/crateresolve1.rs @@ -0,0 +1,10 @@ +// dont-check-compiler-stderr +// aux-build:crateresolve1-1.rs +// aux-build:crateresolve1-2.rs +// aux-build:crateresolve1-3.rs +// error-pattern:multiple matching crates for `crateresolve1` + +extern crate crateresolve1; + +fn main() { +} diff --git a/src/test/ui/dropck/dropck_trait_cycle_checked.rs b/src/test/ui/dropck/dropck_trait_cycle_checked.rs index bea77dc9f5c..be6ec3e4ed1 100644 --- a/src/test/ui/dropck/dropck_trait_cycle_checked.rs +++ b/src/test/ui/dropck/dropck_trait_cycle_checked.rs @@ -1,7 +1,7 @@ // Reject mixing cyclic structure and Drop when using trait // objects to hide the cross-references. // -// (Compare against compile-fail/dropck_vec_cycle_checked.rs) +// (Compare against ui/span/dropck_vec_cycle_checked.rs) use std::cell::Cell; use id::Id; diff --git a/src/test/ui/dropck/reject-specialized-drops-8142.rs b/src/test/ui/dropck/reject-specialized-drops-8142.rs index 02e8665cd2e..c9599f6e805 100644 --- a/src/test/ui/dropck/reject-specialized-drops-8142.rs +++ b/src/test/ui/dropck/reject-specialized-drops-8142.rs @@ -1,7 +1,5 @@ // Issue 8142: Test that Drop impls cannot be specialized beyond the // predicates attached to the type definition itself. -#![feature(min_const_generics)] - trait Bound { fn foo(&self) { } } struct K<'l1,'l2> { x: &'l1 i8, y: &'l2 u8 } struct L<'l1,'l2> { x: &'l1 i8, y: &'l2 u8 } diff --git a/src/test/ui/dropck/reject-specialized-drops-8142.stderr b/src/test/ui/dropck/reject-specialized-drops-8142.stderr index 284cf59c822..cb4d97a8b20 100644 --- a/src/test/ui/dropck/reject-specialized-drops-8142.stderr +++ b/src/test/ui/dropck/reject-specialized-drops-8142.stderr @@ -1,108 +1,108 @@ error[E0367]: `Drop` impl requires `'adds_bnd: 'al` but the struct it is implemented for does not - --> $DIR/reject-specialized-drops-8142.rs:26:20 + --> $DIR/reject-specialized-drops-8142.rs:24:20 | LL | impl<'al,'adds_bnd:'al> Drop for K<'al,'adds_bnd> { // REJECT | ^^^ | note: the implementor must specify the same requirement - --> $DIR/reject-specialized-drops-8142.rs:6:1 + --> $DIR/reject-specialized-drops-8142.rs:4:1 | LL | struct K<'l1,'l2> { x: &'l1 i8, y: &'l2 u8 } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0367]: `Drop` impl requires `'adds_bnd: 'al` but the struct it is implemented for does not - --> $DIR/reject-specialized-drops-8142.rs:30:67 + --> $DIR/reject-specialized-drops-8142.rs:28:67 | LL | impl<'al,'adds_bnd> Drop for L<'al,'adds_bnd> where 'adds_bnd:'al { // REJECT | ^^^ | note: the implementor must specify the same requirement - --> $DIR/reject-specialized-drops-8142.rs:7:1 + --> $DIR/reject-specialized-drops-8142.rs:5:1 | LL | struct L<'l1,'l2> { x: &'l1 i8, y: &'l2 u8 } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0308]: mismatched types - --> $DIR/reject-specialized-drops-8142.rs:36:1 + --> $DIR/reject-specialized-drops-8142.rs:34:1 | LL | impl Drop for N<'static> { fn drop(&mut self) { } } // REJECT | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch | = note: expected struct `N<'n>` found struct `N<'static>` -note: the lifetime `'n` as defined on the struct at 9:10... - --> $DIR/reject-specialized-drops-8142.rs:9:10 +note: the lifetime `'n` as defined on the struct at 7:10... + --> $DIR/reject-specialized-drops-8142.rs:7:10 | LL | struct N<'n> { x: &'n i8 } | ^^ = note: ...does not necessarily outlive the static lifetime error[E0366]: `Drop` impls cannot be specialized - --> $DIR/reject-specialized-drops-8142.rs:43:1 + --> $DIR/reject-specialized-drops-8142.rs:41:1 | LL | impl Drop for P { fn drop(&mut self) { } } // REJECT | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: use the same sequence of generic type, lifetime and const parameters as the struct definition - --> $DIR/reject-specialized-drops-8142.rs:11:1 + --> $DIR/reject-specialized-drops-8142.rs:9:1 | LL | struct P { x: *const Tp } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0367]: `Drop` impl requires `AddsBnd: Bound` but the struct it is implemented for does not - --> $DIR/reject-specialized-drops-8142.rs:46:14 + --> $DIR/reject-specialized-drops-8142.rs:44:14 | LL | impl Drop for Q { fn drop(&mut self) { } } // REJECT | ^^^^^ | note: the implementor must specify the same requirement - --> $DIR/reject-specialized-drops-8142.rs:12:1 + --> $DIR/reject-specialized-drops-8142.rs:10:1 | LL | struct Q { x: *const Tq } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0367]: `Drop` impl requires `AddsRBnd: 'rbnd` but the struct it is implemented for does not - --> $DIR/reject-specialized-drops-8142.rs:49:21 + --> $DIR/reject-specialized-drops-8142.rs:47:21 | LL | impl<'rbnd,AddsRBnd:'rbnd> Drop for R { fn drop(&mut self) { } } // REJECT | ^^^^^ | note: the implementor must specify the same requirement - --> $DIR/reject-specialized-drops-8142.rs:13:1 + --> $DIR/reject-specialized-drops-8142.rs:11:1 | LL | struct R { x: *const Tr } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0366]: `Drop` impls cannot be specialized - --> $DIR/reject-specialized-drops-8142.rs:58:1 + --> $DIR/reject-specialized-drops-8142.rs:56:1 | LL | impl Drop for V { fn drop(&mut self) { } } // REJECT | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: use the same sequence of generic type, lifetime and const parameters as the struct definition - --> $DIR/reject-specialized-drops-8142.rs:17:1 + --> $DIR/reject-specialized-drops-8142.rs:15:1 | LL | struct V { x: *const Tva, y: *const Tvb } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'lw` due to conflicting requirements - --> $DIR/reject-specialized-drops-8142.rs:61:1 + --> $DIR/reject-specialized-drops-8142.rs:59:1 | LL | impl<'lw> Drop for W<'lw,'lw> { fn drop(&mut self) { } } // REJECT | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: first, the lifetime cannot outlive the lifetime `'l1` as defined on the struct at 18:10... - --> $DIR/reject-specialized-drops-8142.rs:18:10 +note: first, the lifetime cannot outlive the lifetime `'l1` as defined on the struct at 16:10... + --> $DIR/reject-specialized-drops-8142.rs:16:10 | LL | struct W<'l1, 'l2> { x: &'l1 i8, y: &'l2 u8 } | ^^^ -note: ...but the lifetime must also be valid for the lifetime `'l2` as defined on the struct at 18:15... - --> $DIR/reject-specialized-drops-8142.rs:18:15 +note: ...but the lifetime must also be valid for the lifetime `'l2` as defined on the struct at 16:15... + --> $DIR/reject-specialized-drops-8142.rs:16:15 | LL | struct W<'l1, 'l2> { x: &'l1 i8, y: &'l2 u8 } | ^^^ note: ...so that the types are compatible - --> $DIR/reject-specialized-drops-8142.rs:61:1 + --> $DIR/reject-specialized-drops-8142.rs:59:1 | LL | impl<'lw> Drop for W<'lw,'lw> { fn drop(&mut self) { } } // REJECT | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -110,61 +110,61 @@ LL | impl<'lw> Drop for W<'lw,'lw> { fn drop(&mut self) { } } // REJ found `W<'_, '_>` error[E0366]: `Drop` impls cannot be specialized - --> $DIR/reject-specialized-drops-8142.rs:64:1 + --> $DIR/reject-specialized-drops-8142.rs:62:1 | LL | impl Drop for X<3> { fn drop(&mut self) { } } // REJECT | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: use the same sequence of generic type, lifetime and const parameters as the struct definition - --> $DIR/reject-specialized-drops-8142.rs:19:1 + --> $DIR/reject-specialized-drops-8142.rs:17:1 | LL | struct X; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0366]: `Drop` impls cannot be specialized - --> $DIR/reject-specialized-drops-8142.rs:67:1 + --> $DIR/reject-specialized-drops-8142.rs:65:1 | LL | impl Drop for Y { fn drop(&mut self) { } } // REJECT | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: use the same sequence of generic type, lifetime and const parameters as the struct definition - --> $DIR/reject-specialized-drops-8142.rs:20:1 + --> $DIR/reject-specialized-drops-8142.rs:18:1 | LL | struct Y; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0367]: `Drop` impl requires `AddsBnd: Bound` but the enum it is implemented for does not - --> $DIR/reject-specialized-drops-8142.rs:70:14 + --> $DIR/reject-specialized-drops-8142.rs:68:14 | LL | impl Drop for Enum { fn drop(&mut self) { } } // REJECT | ^^^^^ | note: the implementor must specify the same requirement - --> $DIR/reject-specialized-drops-8142.rs:22:1 + --> $DIR/reject-specialized-drops-8142.rs:20:1 | LL | enum Enum { Variant(T) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0367]: `Drop` impl requires `AddsBnd: Bound` but the struct it is implemented for does not - --> $DIR/reject-specialized-drops-8142.rs:73:14 + --> $DIR/reject-specialized-drops-8142.rs:71:14 | LL | impl Drop for TupleStruct { fn drop(&mut self) { } } // REJECT | ^^^^^ | note: the implementor must specify the same requirement - --> $DIR/reject-specialized-drops-8142.rs:23:1 + --> $DIR/reject-specialized-drops-8142.rs:21:1 | LL | struct TupleStruct(T); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0367]: `Drop` impl requires `AddsBnd: Bound` but the union it is implemented for does not - --> $DIR/reject-specialized-drops-8142.rs:76:21 + --> $DIR/reject-specialized-drops-8142.rs:74:21 | LL | impl Drop for Union { fn drop(&mut self) { } } // REJECT | ^^^^^ | note: the implementor must specify the same requirement - --> $DIR/reject-specialized-drops-8142.rs:24:1 + --> $DIR/reject-specialized-drops-8142.rs:22:1 | LL | union Union { f: T } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/enum-discriminant/issue-70453-generics-in-discr-ice-2.rs b/src/test/ui/enum-discriminant/issue-70453-generics-in-discr-ice-2.rs index 0cfb93d4668..f927dd18903 100644 --- a/src/test/ui/enum-discriminant/issue-70453-generics-in-discr-ice-2.rs +++ b/src/test/ui/enum-discriminant/issue-70453-generics-in-discr-ice-2.rs @@ -7,7 +7,7 @@ enum MyWeirdOption { None = 0, Some(T) = std::mem::size_of::(), - //~^ ERROR constant expression depends on a generic parameter + //~^ ERROR generic parameters may not be used in const operations } fn main() { diff --git a/src/test/ui/enum-discriminant/issue-70453-generics-in-discr-ice-2.stderr b/src/test/ui/enum-discriminant/issue-70453-generics-in-discr-ice-2.stderr index 91d488a07cc..4d57765e13f 100644 --- a/src/test/ui/enum-discriminant/issue-70453-generics-in-discr-ice-2.stderr +++ b/src/test/ui/enum-discriminant/issue-70453-generics-in-discr-ice-2.stderr @@ -1,10 +1,11 @@ -error: constant expression depends on a generic parameter - --> $DIR/issue-70453-generics-in-discr-ice-2.rs:9:15 +error: generic parameters may not be used in const operations + --> $DIR/issue-70453-generics-in-discr-ice-2.rs:9:35 | LL | Some(T) = std::mem::size_of::(), - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^ cannot perform const operation using `T` | - = note: this may fail depending on what value the parameter takes + = note: type parameters may not be used in const expressions + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: aborting due to previous error diff --git a/src/test/ui/enum-discriminant/issue-70453-generics-in-discr-ice.rs b/src/test/ui/enum-discriminant/issue-70453-generics-in-discr-ice.rs index 676f1115dde..a0fb788a510 100644 --- a/src/test/ui/enum-discriminant/issue-70453-generics-in-discr-ice.rs +++ b/src/test/ui/enum-discriminant/issue-70453-generics-in-discr-ice.rs @@ -8,7 +8,7 @@ enum MyWeirdOption { //~^ ERROR parameter `T` is never used None = 0, Some = std::mem::size_of::(), - //~^ ERROR constant expression depends on a generic parameter + //~^ ERROR generic parameters may not be used in const operations } fn main() { diff --git a/src/test/ui/enum-discriminant/issue-70453-generics-in-discr-ice.stderr b/src/test/ui/enum-discriminant/issue-70453-generics-in-discr-ice.stderr index 0dc5432d28c..1d43903928b 100644 --- a/src/test/ui/enum-discriminant/issue-70453-generics-in-discr-ice.stderr +++ b/src/test/ui/enum-discriminant/issue-70453-generics-in-discr-ice.stderr @@ -1,10 +1,11 @@ -error: constant expression depends on a generic parameter - --> $DIR/issue-70453-generics-in-discr-ice.rs:10:12 +error: generic parameters may not be used in const operations + --> $DIR/issue-70453-generics-in-discr-ice.rs:10:32 | LL | Some = std::mem::size_of::(), - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^ cannot perform const operation using `T` | - = note: this may fail depending on what value the parameter takes + = note: type parameters may not be used in const expressions + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error[E0392]: parameter `T` is never used --> $DIR/issue-70453-generics-in-discr-ice.rs:7:20 diff --git a/src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.rs b/src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.rs index cdc1db4c0b4..e62582fb516 100644 --- a/src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.rs +++ b/src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.rs @@ -1,4 +1,3 @@ -// run-pass #![feature(arbitrary_enum_discriminant, core_intrinsics)] extern crate core; @@ -8,8 +7,7 @@ enum MyWeirdOption { None = 0, Some(T) = core::mem::size_of::<*mut T>(), - //~^ WARN cannot use constants which depend on generic parameters in types - //~| WARN this was previously accepted by the compiler but is being phased out + //~^ ERROR generic parameters may not be used } fn main() { diff --git a/src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.stderr b/src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.stderr index 906927e705e..8c97af263b2 100644 --- a/src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.stderr +++ b/src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.stderr @@ -1,12 +1,11 @@ -warning: cannot use constants which depend on generic parameters in types - --> $DIR/issue-70453-polymorphic-ctfe.rs:10:15 +error: generic parameters may not be used in const operations + --> $DIR/issue-70453-polymorphic-ctfe.rs:9:41 | LL | Some(T) = core::mem::size_of::<*mut T>(), - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^ cannot perform const operation using `T` | - = note: `#[warn(const_evaluatable_unchecked)]` on by default - = 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 #76200 + = note: type parameters may not be used in const expressions + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions -warning: 1 warning emitted +error: aborting due to previous error diff --git a/src/test/ui/enum/issue-67945-1.rs b/src/test/ui/enum/issue-67945-1.rs index 7977bddae7b..f4697344cc7 100644 --- a/src/test/ui/enum/issue-67945-1.rs +++ b/src/test/ui/enum/issue-67945-1.rs @@ -1,6 +1,6 @@ -enum Bug { +enum Bug { //~ ERROR parameter `S` is never used Var = { - let x: S = 0; //~ ERROR: mismatched types + let x: S = 0; //~ ERROR generic parameters may not be used 0 }, } diff --git a/src/test/ui/enum/issue-67945-1.stderr b/src/test/ui/enum/issue-67945-1.stderr index 6583fe13d0c..32ca94203e6 100644 --- a/src/test/ui/enum/issue-67945-1.stderr +++ b/src/test/ui/enum/issue-67945-1.stderr @@ -1,17 +1,20 @@ -error[E0308]: mismatched types - --> $DIR/issue-67945-1.rs:3:20 +error: generic parameters may not be used in const operations + --> $DIR/issue-67945-1.rs:3:16 | -LL | enum Bug { - | - this type parameter -LL | Var = { LL | let x: S = 0; - | - ^ expected type parameter `S`, found integer - | | - | expected due to this + | ^ cannot perform const operation using `S` + | + = note: type parameters may not be used in const expressions + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions + +error[E0392]: parameter `S` is never used + --> $DIR/issue-67945-1.rs:1:10 + | +LL | enum Bug { + | ^ unused parameter | - = note: expected type parameter `S` - found type `{integer}` + = help: consider removing `S`, referring to it in a field, or using a marker such as `PhantomData` -error: aborting due to previous error +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0392`. diff --git a/src/test/ui/enum/issue-67945-2.rs b/src/test/ui/enum/issue-67945-2.rs index 16bd8530ab3..e5044468da1 100644 --- a/src/test/ui/enum/issue-67945-2.rs +++ b/src/test/ui/enum/issue-67945-2.rs @@ -1,9 +1,8 @@ #![feature(type_ascription)] -enum Bug { +enum Bug { //~ ERROR parameter `S` is never used Var = 0: S, - //~^ ERROR: mismatched types - //~| ERROR: mismatched types + //~^ ERROR generic parameters may not be used } fn main() {} diff --git a/src/test/ui/enum/issue-67945-2.stderr b/src/test/ui/enum/issue-67945-2.stderr index c40506d59ed..a738d3b15a5 100644 --- a/src/test/ui/enum/issue-67945-2.stderr +++ b/src/test/ui/enum/issue-67945-2.stderr @@ -1,25 +1,20 @@ -error[E0308]: mismatched types - --> $DIR/issue-67945-2.rs:4:11 +error: generic parameters may not be used in const operations + --> $DIR/issue-67945-2.rs:4:14 | -LL | enum Bug { - | - this type parameter LL | Var = 0: S, - | ^ expected type parameter `S`, found integer + | ^ cannot perform const operation using `S` | - = note: expected type parameter `S` - found type `{integer}` + = note: type parameters may not be used in const expressions + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions -error[E0308]: mismatched types - --> $DIR/issue-67945-2.rs:4:11 +error[E0392]: parameter `S` is never used + --> $DIR/issue-67945-2.rs:3:10 | LL | enum Bug { - | - this type parameter -LL | Var = 0: S, - | ^^^^ expected `isize`, found type parameter `S` + | ^ unused parameter | - = note: expected type `isize` - found type parameter `S` + = help: consider removing `S`, referring to it in a field, or using a marker such as `PhantomData` error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0392`. diff --git a/src/test/ui/error-codes/E0730.stderr b/src/test/ui/error-codes/E0730.stderr index 356e4f36042..f915f6edef5 100644 --- a/src/test/ui/error-codes/E0730.stderr +++ b/src/test/ui/error-codes/E0730.stderr @@ -6,7 +6,6 @@ LL | #![feature(const_generics)] | = note: `#[warn(incomplete_features)]` on by default = note: see issue #44580 for more information - = help: consider using `min_const_generics` instead, which is more stable and complete error[E0730]: cannot pattern-match on an array without a fixed length --> $DIR/E0730.rs:6:9 diff --git a/src/test/ui/error-codes/E0771.stderr b/src/test/ui/error-codes/E0771.stderr index b184b599817..60220be6b57 100644 --- a/src/test/ui/error-codes/E0771.stderr +++ b/src/test/ui/error-codes/E0771.stderr @@ -6,7 +6,6 @@ LL | #![feature(const_generics)] | = note: `#[warn(incomplete_features)]` on by default = note: see issue #44580 for more information - = help: consider using `min_const_generics` instead, which is more stable and complete error[E0771]: use of non-static lifetime `'a` in const generic --> $DIR/E0771.rs:4:41 diff --git a/src/test/ui/extern-flag/empty-extern-arg.rs b/src/test/ui/extern-flag/empty-extern-arg.rs new file mode 100644 index 00000000000..d3cb5aaaeba --- /dev/null +++ b/src/test/ui/extern-flag/empty-extern-arg.rs @@ -0,0 +1,4 @@ +// compile-flags: --extern std= +// error-pattern: extern location for std does not exist + +fn main() {} diff --git a/src/test/ui/extern-flag/empty-extern-arg.stderr b/src/test/ui/extern-flag/empty-extern-arg.stderr new file mode 100644 index 00000000000..199c4fb616b --- /dev/null +++ b/src/test/ui/extern-flag/empty-extern-arg.stderr @@ -0,0 +1,4 @@ +error: extern location for std does not exist: + +error: aborting due to previous error + diff --git a/src/test/ui/feature-gates/feature-gate-const_generics-ptr.rs b/src/test/ui/feature-gates/feature-gate-const_generics-ptr.rs deleted file mode 100644 index dc602ba7e6f..00000000000 --- a/src/test/ui/feature-gates/feature-gate-const_generics-ptr.rs +++ /dev/null @@ -1,9 +0,0 @@ -struct ConstFn; -//~^ ERROR const generics are unstable -//~^^ ERROR using function pointers as const generic parameters is forbidden - -struct ConstPtr; -//~^ ERROR const generics are unstable -//~^^ ERROR using raw pointers as const generic parameters is forbidden - -fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-const_generics-ptr.stderr b/src/test/ui/feature-gates/feature-gate-const_generics-ptr.stderr deleted file mode 100644 index eef465318a3..00000000000 --- a/src/test/ui/feature-gates/feature-gate-const_generics-ptr.stderr +++ /dev/null @@ -1,33 +0,0 @@ -error[E0658]: const generics are unstable - --> $DIR/feature-gate-const_generics-ptr.rs:1:22 - | -LL | struct ConstFn; - | ^ - | - = note: see issue #74878 for more information - = help: add `#![feature(min_const_generics)]` to the crate attributes to enable - -error[E0658]: const generics are unstable - --> $DIR/feature-gate-const_generics-ptr.rs:5:23 - | -LL | struct ConstPtr; - | ^ - | - = note: see issue #74878 for more information - = help: add `#![feature(min_const_generics)]` to the crate attributes to enable - -error: using function pointers as const generic parameters is forbidden - --> $DIR/feature-gate-const_generics-ptr.rs:1:25 - | -LL | struct ConstFn; - | ^^^^ - -error: using raw pointers as const generic parameters is forbidden - --> $DIR/feature-gate-const_generics-ptr.rs:5:26 - | -LL | struct ConstPtr; - | ^^^^^^^^^^ - -error: aborting due to 4 previous errors - -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gates/feature-gate-const_generics.rs b/src/test/ui/feature-gates/feature-gate-const_generics.rs index fe1ded1c4bb..06364eebef9 100644 --- a/src/test/ui/feature-gates/feature-gate-const_generics.rs +++ b/src/test/ui/feature-gates/feature-gate-const_generics.rs @@ -1,5 +1,5 @@ -fn foo() {} //~ ERROR const generics are unstable +fn foo() {} //~ ERROR `()` is forbidden as the type of a const generic parameter -struct Foo([(); X]); //~ ERROR const generics are unstable +struct Foo([(); X]); fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-const_generics.stderr b/src/test/ui/feature-gates/feature-gate-const_generics.stderr index f80362252f9..b2b7e4576bf 100644 --- a/src/test/ui/feature-gates/feature-gate-const_generics.stderr +++ b/src/test/ui/feature-gates/feature-gate-const_generics.stderr @@ -1,21 +1,11 @@ -error[E0658]: const generics are unstable - --> $DIR/feature-gate-const_generics.rs:1:14 +error: `()` is forbidden as the type of a const generic parameter + --> $DIR/feature-gate-const_generics.rs:1:17 | LL | fn foo() {} - | ^ + | ^^ | - = note: see issue #74878 for more information - = help: add `#![feature(min_const_generics)]` to the crate attributes to enable + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#[feature(const_generics)]` -error[E0658]: const generics are unstable - --> $DIR/feature-gate-const_generics.rs:3:18 - | -LL | struct Foo([(); X]); - | ^ - | - = note: see issue #74878 for more information - = help: add `#![feature(min_const_generics)]` to the crate attributes to enable - -error: aborting due to 2 previous errors +error: aborting due to previous error -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/fn/issue-80179.rs b/src/test/ui/fn/issue-80179.rs new file mode 100644 index 00000000000..7609b1525cc --- /dev/null +++ b/src/test/ui/fn/issue-80179.rs @@ -0,0 +1,27 @@ +// Functions with a type placeholder `_` as the return type should +// show a function pointer suggestion when given a function item +// and suggest how to return closures correctly from a function. +// This is a regression test of #80179 + +fn returns_i32() -> i32 { + 0 +} + +fn returns_fn_ptr() -> _ { +//~^ ERROR the type placeholder `_` is not allowed within types on item signatures [E0121] +//~| NOTE not allowed in type signatures +//~| HELP replace with the correct return type +//~| SUGGESTION fn() -> i32 + returns_i32 +} + +fn returns_closure() -> _ { +//~^ ERROR the type placeholder `_` is not allowed within types on item signatures [E0121] +//~| NOTE not allowed in type signatures +//~| HELP consider using an `Fn`, `FnMut`, or `FnOnce` trait bound +//~| NOTE for more information on `Fn` traits and closure types, see +// https://doc.rust-lang.org/book/ch13-01-closures.html + || 0 +} + +fn main() {} diff --git a/src/test/ui/fn/issue-80179.stderr b/src/test/ui/fn/issue-80179.stderr new file mode 100644 index 00000000000..63571e71b34 --- /dev/null +++ b/src/test/ui/fn/issue-80179.stderr @@ -0,0 +1,21 @@ +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/issue-80179.rs:10:24 + | +LL | fn returns_fn_ptr() -> _ { + | ^ + | | + | not allowed in type signatures + | help: replace with the correct return type: `fn() -> i32` + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/issue-80179.rs:18:25 + | +LL | fn returns_closure() -> _ { + | ^ not allowed in type signatures + | + = help: consider using an `Fn`, `FnMut`, or `FnOnce` trait bound + = note: for more information on `Fn` traits and closure types, see https://doc.rust-lang.org/book/ch13-01-closures.html + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0121`. diff --git a/src/test/ui/fsu-moves-and-copies.rs b/src/test/ui/fsu-moves-and-copies.rs index c41bcc73fa5..6a0b4ed17b9 100644 --- a/src/test/ui/fsu-moves-and-copies.rs +++ b/src/test/ui/fsu-moves-and-copies.rs @@ -36,7 +36,7 @@ impl Drop for DropMoveFoo { fn drop(&mut self) { } } fn test0() { // just copy implicitly copyable fields from `f`, no moves // (and thus it is okay that these are Drop; compare against - // compile-fail test: borrowck-struct-update-with-dtor.rs). + // test ui/borrowck/borrowck-struct-update-with-dtor.rs). // Case 1: Nocopyable let f = DropNoFoo::new(1, 2); diff --git a/src/test/ui/functions-closures/closure-expected-type/README.md b/src/test/ui/functions-closures/closure-expected-type/README.md index fd493e1ff37..11d2c9b7fb7 100644 --- a/src/test/ui/functions-closures/closure-expected-type/README.md +++ b/src/test/ui/functions-closures/closure-expected-type/README.md @@ -5,4 +5,4 @@ inputs. This investigation was kicked off by #38714, which revealed some pretty deep flaws in the ad-hoc way that we were doing things before. -See also `src/test/compile-fail/closure-expected-type`. +See also `src/test/ui/closure-expected-type`. diff --git a/src/test/ui/generic-associated-types/issue-74824.rs b/src/test/ui/generic-associated-types/issue-74824.rs new file mode 100644 index 00000000000..00761a97d00 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-74824.rs @@ -0,0 +1,27 @@ +#![feature(generic_associated_types)] +#![feature(associated_type_defaults)] +#![allow(incomplete_features)] + +use std::ops::Deref; + +trait UnsafeCopy { + type Copy: Copy = Box; + //~^ ERROR the trait bound `Box: Copy` is not satisfied + //~^^ ERROR the trait bound `T: Clone` is not satisfied + fn copy(x: &Self::Copy) -> Self::Copy { + *x + } +} + +impl UnsafeCopy for T {} + +fn main() { + let b = Box::new(42usize); + let copy = <()>::copy(&b); + + let raw_b = Box::deref(&b) as *const _; + let raw_copy = Box::deref(©) as *const _; + + // assert the addresses. + assert_eq!(raw_b, raw_copy); +} diff --git a/src/test/ui/generic-associated-types/issue-74824.stderr b/src/test/ui/generic-associated-types/issue-74824.stderr new file mode 100644 index 00000000000..34a2c1932eb --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-74824.stderr @@ -0,0 +1,27 @@ +error[E0277]: the trait bound `Box: Copy` is not satisfied + --> $DIR/issue-74824.rs:8:5 + | +LL | type Copy: Copy = Box; + | ^^^^^^^^^^^^^^----^^^^^^^^^^ + | | | + | | required by this bound in `UnsafeCopy::Copy` + | the trait `Copy` is not implemented for `Box` + +error[E0277]: the trait bound `T: Clone` is not satisfied + --> $DIR/issue-74824.rs:8:5 + | +LL | type Copy: Copy = Box; + | ^^^^^^^^^^^^^^----^^^^^^^^^^ + | | | + | | required by this bound in `UnsafeCopy::Copy` + | the trait `Clone` is not implemented for `T` + | + = note: required because of the requirements on the impl of `Clone` for `Box` +help: consider restricting type parameter `T` + | +LL | type Copy: Copy = Box; + | ^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/generics/param-in-ct-in-ty-param-default.rs b/src/test/ui/generics/param-in-ct-in-ty-param-default.rs index dd89bc0f7a0..3c62e47381c 100644 --- a/src/test/ui/generics/param-in-ct-in-ty-param-default.rs +++ b/src/test/ui/generics/param-in-ct-in-ty-param-default.rs @@ -1,4 +1,4 @@ struct Foo()]>(T, U); -//~^ ERROR constant values inside of type parameter defaults +//~^ ERROR generic parameters may not be used in const operations fn main() {} diff --git a/src/test/ui/generics/param-in-ct-in-ty-param-default.stderr b/src/test/ui/generics/param-in-ct-in-ty-param-default.stderr index ea867240269..41a0a03ff66 100644 --- a/src/test/ui/generics/param-in-ct-in-ty-param-default.stderr +++ b/src/test/ui/generics/param-in-ct-in-ty-param-default.stderr @@ -1,8 +1,11 @@ -error: constant values inside of type parameter defaults must not depend on generic parameters +error: generic parameters may not be used in const operations --> $DIR/param-in-ct-in-ty-param-default.rs:1:44 | LL | struct Foo()]>(T, U); - | ^ the anonymous constant must not depend on the parameter `T` + | ^ cannot perform const operation using `T` + | + = note: type parameters may not be used in const expressions + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: aborting due to previous error diff --git a/src/test/ui/hygiene/generic_params.stderr b/src/test/ui/hygiene/generic_params.stderr index 6de36deb597..4ca6d199835 100644 --- a/src/test/ui/hygiene/generic_params.stderr +++ b/src/test/ui/hygiene/generic_params.stderr @@ -6,7 +6,6 @@ LL | #![feature(decl_macro, rustc_attrs, const_generics)] | = note: `#[warn(incomplete_features)]` on by default = note: see issue #44580 for more information - = help: consider using `min_const_generics` instead, which is more stable and complete warning: 1 warning emitted diff --git a/src/test/ui/hygiene/issue-61574-const-parameters.stderr b/src/test/ui/hygiene/issue-61574-const-parameters.stderr index 3f85383eb33..b351b8b73a0 100644 --- a/src/test/ui/hygiene/issue-61574-const-parameters.stderr +++ b/src/test/ui/hygiene/issue-61574-const-parameters.stderr @@ -6,7 +6,6 @@ LL | #![feature(const_generics)] | = note: `#[warn(incomplete_features)]` on by default = note: see issue #44580 for more information - = help: consider using `min_const_generics` instead, which is more stable and complete warning: 1 warning emitted diff --git a/src/test/ui/issues/issue-20433.stderr b/src/test/ui/issues/issue-20433.stderr index 3f7226c79bf..5fed02164b5 100644 --- a/src/test/ui/issues/issue-20433.stderr +++ b/src/test/ui/issues/issue-20433.stderr @@ -4,7 +4,7 @@ error[E0277]: the size for values of type `[i32]` cannot be known at compilation LL | fn iceman(c: Vec<[i32]>) {} | ^^^^^^^^^^ doesn't have a size known at compile-time | - ::: $SRC_DIR/alloc/src/vec.rs:LL:COL + ::: $SRC_DIR/alloc/src/vec/mod.rs:LL:COL | LL | pub struct Vec { | - required by this bound in `Vec` diff --git a/src/test/ui/issues/issue-21475.rs b/src/test/ui/issues/issue-21475.rs index ab0a1886963..b028fcae077 100644 --- a/src/test/ui/issues/issue-21475.rs +++ b/src/test/ui/issues/issue-21475.rs @@ -1,5 +1,5 @@ // run-pass -#![allow(unused_imports, overlapping_patterns)] +#![allow(unused_imports, overlapping_range_endpoints)] // pretty-expanded FIXME #23616 use m::{START, END}; diff --git a/src/test/ui/issues/issue-23122-2.stderr b/src/test/ui/issues/issue-23122-2.stderr index ce3bffe602c..ff7e884ea6f 100644 --- a/src/test/ui/issues/issue-23122-2.stderr +++ b/src/test/ui/issues/issue-23122-2.stderr @@ -1,11 +1,10 @@ -error[E0275]: overflow evaluating the requirement `<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next: Sized` +error[E0275]: overflow evaluating the requirement `<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next` --> $DIR/issue-23122-2.rs:9:5 | LL | type Next = as Next>::Next; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`issue_23122_2`) - = note: required because of the requirements on the impl of `Next` for `GetNext<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next>` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-26251.rs b/src/test/ui/issues/issue-26251.rs index edb06fea8ad..a3e26a41232 100644 --- a/src/test/ui/issues/issue-26251.rs +++ b/src/test/ui/issues/issue-26251.rs @@ -1,5 +1,5 @@ // run-pass -#![allow(overlapping_patterns)] +#![allow(overlapping_range_endpoints)] fn main() { let x = 'a'; diff --git a/src/test/ui/issues/issue-26996.rs b/src/test/ui/issues/issue-26996.rs index 04382be27d7..84037b72a27 100644 --- a/src/test/ui/issues/issue-26996.rs +++ b/src/test/ui/issues/issue-26996.rs @@ -1,6 +1,6 @@ // run-pass -// This test is bogus (i.e., should be compile-fail) during the period +// This test is bogus (i.e., should be check-fail) during the period // where #54986 is implemented and #54987 is *not* implemented. For // now: just ignore it // diff --git a/src/test/ui/issues/issue-27021.rs b/src/test/ui/issues/issue-27021.rs index 30551375450..ef3b114a5fa 100644 --- a/src/test/ui/issues/issue-27021.rs +++ b/src/test/ui/issues/issue-27021.rs @@ -1,6 +1,6 @@ // run-pass -// This test is bogus (i.e., should be compile-fail) during the period +// This test is bogus (i.e., should be check-fail) during the period // where #54986 is implemented and #54987 is *not* implemented. For // now: just ignore it // diff --git a/src/test/ui/issues/issue-28498-ugeh-with-lifetime-param.rs b/src/test/ui/issues/issue-28498-ugeh-with-lifetime-param.rs index aea9fde5309..43c0bfb26cd 100644 --- a/src/test/ui/issues/issue-28498-ugeh-with-lifetime-param.rs +++ b/src/test/ui/issues/issue-28498-ugeh-with-lifetime-param.rs @@ -3,7 +3,7 @@ // Demonstrate the use of the unguarded escape hatch with a lifetime param // to assert that destructor will not access any dead data. // -// Compare with compile-fail/issue28498-reject-lifetime-param.rs +// Compare with ui/span/issue28498-reject-lifetime-param.rs #![feature(dropck_eyepatch)] diff --git a/src/test/ui/issues/issue-28498-ugeh-with-passed-to-fn.rs b/src/test/ui/issues/issue-28498-ugeh-with-passed-to-fn.rs index 91ef5a7c98d..23fd86a093b 100644 --- a/src/test/ui/issues/issue-28498-ugeh-with-passed-to-fn.rs +++ b/src/test/ui/issues/issue-28498-ugeh-with-passed-to-fn.rs @@ -3,7 +3,7 @@ // Demonstrate the use of the unguarded escape hatch with a type param in negative position // to assert that destructor will not access any dead data. // -// Compare with compile-fail/issue28498-reject-lifetime-param.rs +// Compare with ui/span/issue28498-reject-lifetime-param.rs // Demonstrate that a type param in negative position causes dropck to reject code // that might indirectly access previously dropped value. diff --git a/src/test/ui/issues/issue-28498-ugeh-with-trait-bound.rs b/src/test/ui/issues/issue-28498-ugeh-with-trait-bound.rs index 808f3b6e81e..61d11cf3834 100644 --- a/src/test/ui/issues/issue-28498-ugeh-with-trait-bound.rs +++ b/src/test/ui/issues/issue-28498-ugeh-with-trait-bound.rs @@ -3,7 +3,7 @@ // Demonstrate the use of the unguarded escape hatch with a trait bound // to assert that destructor will not access any dead data. // -// Compare with compile-fail/issue28498-reject-trait-bound.rs +// Compare with ui/span/issue28498-reject-trait-bound.rs #![feature(dropck_eyepatch)] diff --git a/src/test/ui/issues/issue-39559.rs b/src/test/ui/issues/issue-39559.rs index 3a75956af52..58d25940733 100644 --- a/src/test/ui/issues/issue-39559.rs +++ b/src/test/ui/issues/issue-39559.rs @@ -12,7 +12,7 @@ fn dim() -> usize { pub struct Vector { entries: [T; D::dim()], - //~^ ERROR no function or associated item named `dim` found + //~^ ERROR generic parameters may not be used _dummy: D, } diff --git a/src/test/ui/issues/issue-39559.stderr b/src/test/ui/issues/issue-39559.stderr index 5e8d487f416..91e31ca0bd8 100644 --- a/src/test/ui/issues/issue-39559.stderr +++ b/src/test/ui/issues/issue-39559.stderr @@ -1,11 +1,11 @@ -error[E0599]: no function or associated item named `dim` found for type parameter `D` in the current scope - --> $DIR/issue-39559.rs:14:21 +error: generic parameters may not be used in const operations + --> $DIR/issue-39559.rs:14:18 | LL | entries: [T; D::dim()], - | ^^^ function or associated item not found in `D` + | ^^^^^^ cannot perform const operation using `D` | - = help: items from traits can only be used if the type parameter is bounded by the trait + = note: type parameters may not be used in const expressions + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: aborting due to previous error -For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/issues/issue-43733.rs b/src/test/ui/issues/issue-43733.rs deleted file mode 100644 index a602d7667c4..00000000000 --- a/src/test/ui/issues/issue-43733.rs +++ /dev/null @@ -1,31 +0,0 @@ -#![feature(const_fn)] -#![feature(thread_local)] -#![feature(cfg_target_thread_local, thread_local_internals)] - -type Foo = std::cell::RefCell; - -#[cfg(target_thread_local)] -#[thread_local] -static __KEY: std::thread::__FastLocalKeyInner = - std::thread::__FastLocalKeyInner::new(); - -#[cfg(not(target_thread_local))] -static __KEY: std::thread::__OsLocalKeyInner = - std::thread::__OsLocalKeyInner::new(); - -fn __getit() -> std::option::Option<&'static Foo> -{ - __KEY.get(Default::default) //~ ERROR call to unsafe function is unsafe -} - -static FOO: std::thread::LocalKey = - std::thread::LocalKey::new(__getit); -//~^ ERROR call to unsafe function is unsafe - -fn main() { - FOO.with(|foo| println!("{}", foo.borrow())); - std::thread::spawn(|| { - FOO.with(|foo| *foo.borrow_mut() += "foo"); - }).join().unwrap(); - FOO.with(|foo| println!("{}", foo.borrow())); -} diff --git a/src/test/ui/issues/issue-43733.stderr b/src/test/ui/issues/issue-43733.stderr deleted file mode 100644 index ee6a3b065d6..00000000000 --- a/src/test/ui/issues/issue-43733.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error[E0133]: call to unsafe function is unsafe and requires unsafe function or block - --> $DIR/issue-43733.rs:18:5 - | -LL | __KEY.get(Default::default) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function - | - = note: consult the function's documentation for information on how to avoid undefined behavior - -error[E0133]: call to unsafe function is unsafe and requires unsafe function or block - --> $DIR/issue-43733.rs:22:5 - | -LL | std::thread::LocalKey::new(__getit); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function - | - = note: consult the function's documentation for information on how to avoid undefined behavior - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0133`. diff --git a/src/test/ui/issues/issue-49298.rs b/src/test/ui/issues/issue-49298.rs index 697a160b4ec..e3ffa8e7c6e 100644 --- a/src/test/ui/issues/issue-49298.rs +++ b/src/test/ui/issues/issue-49298.rs @@ -2,7 +2,7 @@ #![feature(test)] #![allow(unused_mut)] // under NLL we get warning about `x` below: rust-lang/rust#54499 -// This test is bogus (i.e., should be compile-fail) during the period +// This test is bogus (i.e., should be check-fail) during the period // where #54986 is implemented and #54987 is *not* implemented. For // now: just ignore it // diff --git a/src/test/ui/issues/issue-59508-1.stderr b/src/test/ui/issues/issue-59508-1.stderr index 2a4ccda8929..5e97339f148 100644 --- a/src/test/ui/issues/issue-59508-1.stderr +++ b/src/test/ui/issues/issue-59508-1.stderr @@ -12,7 +12,6 @@ LL | #![feature(const_generics)] | = note: `#[warn(incomplete_features)]` on by default = note: see issue #44580 for more information - = help: consider using `min_const_generics` instead, which is more stable and complete error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/issues/issue-59508.stderr b/src/test/ui/issues/issue-59508.stderr index c0fdb2ef34a..33e967cebff 100644 --- a/src/test/ui/issues/issue-59508.stderr +++ b/src/test/ui/issues/issue-59508.stderr @@ -2,7 +2,7 @@ error: lifetime parameters must be declared prior to type parameters --> $DIR/issue-59508.rs:10:25 | LL | pub fn do_things() { - | ----^^--^^----- help: reorder the parameters: lifetimes, then types: `<'a, 'b: 'a, T>` + | ----^^--^^----- help: reorder the parameters: lifetimes, then types, then consts: `<'a, 'b: 'a, T>` error: aborting due to previous error diff --git a/src/test/ui/lazy_normalization_consts/feature-gate-lazy_normalization_consts.rs b/src/test/ui/lazy_normalization_consts/feature-gate-lazy_normalization_consts.rs index 44cb74815c6..46ae9403c03 100644 --- a/src/test/ui/lazy_normalization_consts/feature-gate-lazy_normalization_consts.rs +++ b/src/test/ui/lazy_normalization_consts/feature-gate-lazy_normalization_consts.rs @@ -4,7 +4,7 @@ pub const fn sof() -> usize { fn test() { let _: [u8; sof::()]; - //~^ ERROR the size for values of type `T` + //~^ ERROR generic parameters may not be used in const operations } fn main() {} diff --git a/src/test/ui/lazy_normalization_consts/feature-gate-lazy_normalization_consts.stderr b/src/test/ui/lazy_normalization_consts/feature-gate-lazy_normalization_consts.stderr index 5a6c86d133b..5c167ea0834 100644 --- a/src/test/ui/lazy_normalization_consts/feature-gate-lazy_normalization_consts.stderr +++ b/src/test/ui/lazy_normalization_consts/feature-gate-lazy_normalization_consts.stderr @@ -1,19 +1,11 @@ -error[E0277]: the size for values of type `T` cannot be known at compilation time +error: generic parameters may not be used in const operations --> $DIR/feature-gate-lazy_normalization_consts.rs:6:23 | -LL | pub const fn sof() -> usize { - | - required by this bound in `sof` -... -LL | fn test() { - | - this type parameter needs to be `Sized` LL | let _: [u8; sof::()]; - | ^ doesn't have a size known at compile-time + | ^ cannot perform const operation using `T` | -help: consider relaxing the implicit `Sized` restriction - | -LL | pub const fn sof() -> usize { - | ^^^^^^^^ + = note: type parameters may not be used in const expressions + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: aborting due to previous error -For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/lifetime-before-type-params.stderr b/src/test/ui/lifetime-before-type-params.stderr index 76d7d0f024d..047bc7f6d90 100644 --- a/src/test/ui/lifetime-before-type-params.stderr +++ b/src/test/ui/lifetime-before-type-params.stderr @@ -2,25 +2,25 @@ error: lifetime parameters must be declared prior to type parameters --> $DIR/lifetime-before-type-params.rs:2:13 | LL | fn first() {} - | ----^^--^^- help: reorder the parameters: lifetimes, then types: `<'a, 'b, T>` + | ----^^--^^- help: reorder the parameters: lifetimes, then types, then consts: `<'a, 'b, T>` error: lifetime parameters must be declared prior to type parameters --> $DIR/lifetime-before-type-params.rs:4:18 | LL | fn second<'a, T, 'b>() {} - | --------^^- help: reorder the parameters: lifetimes, then types: `<'a, 'b, T>` + | --------^^- help: reorder the parameters: lifetimes, then types, then consts: `<'a, 'b, T>` error: lifetime parameters must be declared prior to type parameters --> $DIR/lifetime-before-type-params.rs:6:16 | LL | fn third() {} - | -------^^- help: reorder the parameters: lifetimes, then types: `<'a, T, U>` + | -------^^- help: reorder the parameters: lifetimes, then types, then consts: `<'a, T, U>` error: lifetime parameters must be declared prior to type parameters --> $DIR/lifetime-before-type-params.rs:8:18 | LL | fn fourth<'a, T, 'b, U, 'c, V>() {} - | --------^^-----^^---- help: reorder the parameters: lifetimes, then types: `<'a, 'b, 'c, T, U, V>` + | --------^^-----^^---- help: reorder the parameters: lifetimes, then types, then consts: `<'a, 'b, 'c, T, U, V>` error: aborting due to 4 previous errors diff --git a/src/test/ui/linkage-attr/invalid-link-args.rs b/src/test/ui/linkage-attr/invalid-link-args.rs new file mode 100644 index 00000000000..5eb1c637f09 --- /dev/null +++ b/src/test/ui/linkage-attr/invalid-link-args.rs @@ -0,0 +1,14 @@ +// build-fail +// dont-check-compiler-stderr +// ignore-msvc due to linker-flavor=ld +// error-pattern:aFdEfSeVEEE +// compile-flags: -C linker-flavor=ld + +/* Make sure invalid link_args are printed to stderr. */ + +#![feature(link_args)] + +#[link_args = "aFdEfSeVEEE"] +extern {} + +fn main() { } diff --git a/src/test/ui/linkage-attr/issue-10755.rs b/src/test/ui/linkage-attr/issue-10755.rs new file mode 100644 index 00000000000..5ce69bceed3 --- /dev/null +++ b/src/test/ui/linkage-attr/issue-10755.rs @@ -0,0 +1,7 @@ +// build-fail +// dont-check-compiler-stderr +// compile-flags: -C linker=llllll -C linker-flavor=ld +// error-pattern: linker `llllll` not found + +fn main() { +} diff --git a/src/test/ui/lint/expansion-time.rs b/src/test/ui/lint/expansion-time.rs index a9c7ac363b0..f23c7cb0dca 100644 --- a/src/test/ui/lint/expansion-time.rs +++ b/src/test/ui/lint/expansion-time.rs @@ -5,6 +5,10 @@ macro_rules! foo { ( $($i:ident)* ) => { $($i)+ }; //~ WARN meta-variable repeats with different Kleene operator } +#[warn(missing_fragment_specifier)] +macro_rules! m { ($i) => {} } //~ WARN missing fragment specifier + //~| WARN this was previously accepted + #[warn(soft_unstable)] mod benches { #[bench] //~ WARN use of unstable library feature 'test' diff --git a/src/test/ui/lint/expansion-time.stderr b/src/test/ui/lint/expansion-time.stderr index 24e2733064e..b0fc1f8e5ee 100644 --- a/src/test/ui/lint/expansion-time.stderr +++ b/src/test/ui/lint/expansion-time.stderr @@ -12,14 +12,28 @@ note: the lint level is defined here LL | #[warn(meta_variable_misuse)] | ^^^^^^^^^^^^^^^^^^^^ +warning: missing fragment specifier + --> $DIR/expansion-time.rs:9:19 + | +LL | macro_rules! m { ($i) => {} } + | ^^ + | +note: the lint level is defined here + --> $DIR/expansion-time.rs:8:8 + | +LL | #[warn(missing_fragment_specifier)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + = 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 #40107 + warning: use of unstable library feature 'test': `bench` is a part of custom test frameworks which are unstable - --> $DIR/expansion-time.rs:10:7 + --> $DIR/expansion-time.rs:14:7 | LL | #[bench] | ^^^^^ | note: the lint level is defined here - --> $DIR/expansion-time.rs:8:8 + --> $DIR/expansion-time.rs:12:8 | LL | #[warn(soft_unstable)] | ^^^^^^^^^^^^^ @@ -33,10 +47,10 @@ LL | 2 | ^ | note: the lint level is defined here - --> $DIR/expansion-time.rs:25:8 + --> $DIR/expansion-time.rs:29:8 | LL | #[warn(incomplete_include)] | ^^^^^^^^^^^^^^^^^^ -warning: 3 warnings emitted +warning: 4 warnings emitted diff --git a/src/test/ui/lint/function-item-references.rs b/src/test/ui/lint/function-item-references.rs index 5f7f5e66eaa..05213f4ed4b 100644 --- a/src/test/ui/lint/function-item-references.rs +++ b/src/test/ui/lint/function-item-references.rs @@ -1,5 +1,5 @@ // check-pass -#![feature(c_variadic, min_const_generics)] +#![feature(c_variadic)] #![warn(function_item_references)] use std::fmt::Pointer; use std::fmt::Formatter; diff --git a/src/test/ui/lint/lint-const-item-mutation.stderr b/src/test/ui/lint/lint-const-item-mutation.stderr index 74505eeb987..3973af540c8 100644 --- a/src/test/ui/lint/lint-const-item-mutation.stderr +++ b/src/test/ui/lint/lint-const-item-mutation.stderr @@ -107,7 +107,7 @@ LL | VEC.push(0); = note: each usage of a `const` item creates a new temporary = note: the mutable reference will refer to this temporary, not the original `const` item note: mutable reference created due to call to this method - --> $SRC_DIR/alloc/src/vec.rs:LL:COL + --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL | LL | / pub fn push(&mut self, value: T) { LL | | // This will panic or abort if we would allocate > isize::MAX bytes diff --git a/src/test/ui/lint/must_use-in-stdlib-traits.rs b/src/test/ui/lint/must_use-in-stdlib-traits.rs new file mode 100644 index 00000000000..70dddf61fb7 --- /dev/null +++ b/src/test/ui/lint/must_use-in-stdlib-traits.rs @@ -0,0 +1,47 @@ +#![deny(unused_must_use)] +#![feature(arbitrary_self_types)] + +use std::iter::Iterator; +use std::future::Future; + +use std::task::{Context, Poll}; +use std::pin::Pin; +use std::unimplemented; + +struct MyFuture; + +impl Future for MyFuture { + type Output = u32; + + fn poll(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll { + Poll::Pending + } +} + +fn iterator() -> impl Iterator { + std::iter::empty::() +} + +fn future() -> impl Future { + MyFuture +} + +fn square_fn_once() -> impl FnOnce(u32) -> u32 { + |x| x * x +} + +fn square_fn_mut() -> impl FnMut(u32) -> u32 { + |x| x * x +} + +fn square_fn() -> impl Fn(u32) -> u32 { + |x| x * x +} + +fn main() { + iterator(); //~ ERROR unused implementer of `Iterator` that must be used + future(); //~ ERROR unused implementer of `Future` that must be used + square_fn_once(); //~ ERROR unused implementer of `FnOnce` that must be used + square_fn_mut(); //~ ERROR unused implementer of `FnMut` that must be used + square_fn(); //~ ERROR unused implementer of `Fn` that must be used +} diff --git a/src/test/ui/lint/must_use-in-stdlib-traits.stderr b/src/test/ui/lint/must_use-in-stdlib-traits.stderr new file mode 100644 index 00000000000..76978d29dc8 --- /dev/null +++ b/src/test/ui/lint/must_use-in-stdlib-traits.stderr @@ -0,0 +1,47 @@ +error: unused implementer of `Iterator` that must be used + --> $DIR/must_use-in-stdlib-traits.rs:42:4 + | +LL | iterator(); + | ^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/must_use-in-stdlib-traits.rs:1:9 + | +LL | #![deny(unused_must_use)] + | ^^^^^^^^^^^^^^^ + = note: iterators are lazy and do nothing unless consumed + +error: unused implementer of `Future` that must be used + --> $DIR/must_use-in-stdlib-traits.rs:43:4 + | +LL | future(); + | ^^^^^^^^^ + | + = note: futures do nothing unless you `.await` or poll them + +error: unused implementer of `FnOnce` that must be used + --> $DIR/must_use-in-stdlib-traits.rs:44:4 + | +LL | square_fn_once(); + | ^^^^^^^^^^^^^^^^^ + | + = note: closures are lazy and do nothing unless called + +error: unused implementer of `FnMut` that must be used + --> $DIR/must_use-in-stdlib-traits.rs:45:4 + | +LL | square_fn_mut(); + | ^^^^^^^^^^^^^^^^ + | + = note: closures are lazy and do nothing unless called + +error: unused implementer of `Fn` that must be used + --> $DIR/must_use-in-stdlib-traits.rs:46:4 + | +LL | square_fn(); + | ^^^^^^^^^^^^ + | + = note: closures are lazy and do nothing unless called + +error: aborting due to 5 previous errors + diff --git a/src/test/ui/lint/redundant-semicolon/item-stmt-semi.rs b/src/test/ui/lint/redundant-semicolon/item-stmt-semi.rs index 4592bc31a39..8c79630b7fd 100644 --- a/src/test/ui/lint/redundant-semicolon/item-stmt-semi.rs +++ b/src/test/ui/lint/redundant-semicolon/item-stmt-semi.rs @@ -1,10 +1,6 @@ -// check-pass -// This test should stop compiling -// we decide to enable this lint for item statements. - #![deny(redundant_semicolons)] fn main() { - fn inner() {}; - struct Bar {}; + fn inner() {}; //~ ERROR unnecessary + struct Bar {}; //~ ERROR unnecessary } diff --git a/src/test/ui/lint/redundant-semicolon/item-stmt-semi.stderr b/src/test/ui/lint/redundant-semicolon/item-stmt-semi.stderr new file mode 100644 index 00000000000..451b152cbe5 --- /dev/null +++ b/src/test/ui/lint/redundant-semicolon/item-stmt-semi.stderr @@ -0,0 +1,20 @@ +error: unnecessary trailing semicolon + --> $DIR/item-stmt-semi.rs:4:18 + | +LL | fn inner() {}; + | ^ help: remove this semicolon + | +note: the lint level is defined here + --> $DIR/item-stmt-semi.rs:1:9 + | +LL | #![deny(redundant_semicolons)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unnecessary trailing semicolon + --> $DIR/item-stmt-semi.rs:5:18 + | +LL | struct Bar {}; + | ^ help: remove this semicolon + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/llvm-asm/asm-src-loc-codegen-units.rs b/src/test/ui/llvm-asm/asm-src-loc-codegen-units.rs new file mode 100644 index 00000000000..387822d00f6 --- /dev/null +++ b/src/test/ui/llvm-asm/asm-src-loc-codegen-units.rs @@ -0,0 +1,12 @@ +// build-fail +// dont-check-compiler-stderr +// compile-flags: -C codegen-units=2 +// ignore-emscripten + +#![feature(llvm_asm)] + +fn main() { + unsafe { + llvm_asm!("nowayisthisavalidinstruction"); //~ ERROR instruction + } +} diff --git a/src/test/ui/llvm-asm/asm-src-loc.rs b/src/test/ui/llvm-asm/asm-src-loc.rs new file mode 100644 index 00000000000..063066df11c --- /dev/null +++ b/src/test/ui/llvm-asm/asm-src-loc.rs @@ -0,0 +1,11 @@ +// build-fail +// dont-check-compiler-stderr +// ignore-emscripten + +#![feature(llvm_asm)] + +fn main() { + unsafe { + llvm_asm!("nowayisthisavalidinstruction"); //~ ERROR instruction + } +} diff --git a/src/test/ui/macros/issue-39404.rs b/src/test/ui/macros/issue-39404.rs index 054958ba00b..2229f2c3900 100644 --- a/src/test/ui/macros/issue-39404.rs +++ b/src/test/ui/macros/issue-39404.rs @@ -2,5 +2,6 @@ macro_rules! m { ($i) => {} } //~^ ERROR missing fragment specifier +//~| WARN previously accepted fn main() {} diff --git a/src/test/ui/macros/issue-39404.stderr b/src/test/ui/macros/issue-39404.stderr index 645f06e59d8..d2f2a823c2a 100644 --- a/src/test/ui/macros/issue-39404.stderr +++ b/src/test/ui/macros/issue-39404.stderr @@ -3,6 +3,10 @@ error: missing fragment specifier | LL | macro_rules! m { ($i) => {} } | ^^ + | + = note: `#[deny(missing_fragment_specifier)]` on by default + = 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 #40107 error: aborting due to previous error diff --git a/src/test/ui/macros/macro-comma-behavior-rpass.rs b/src/test/ui/macros/macro-comma-behavior-rpass.rs index e5e656de6fa..c46274d59b6 100644 --- a/src/test/ui/macros/macro-comma-behavior-rpass.rs +++ b/src/test/ui/macros/macro-comma-behavior-rpass.rs @@ -8,7 +8,7 @@ // to it being e.g., a place where the addition of an argument // causes it to go down a code path with subtly different behavior). // -// There is a companion test in compile-fail. +// There is a companion failing test. // compile-flags: --test -C debug_assertions=yes // revisions: std core @@ -68,26 +68,26 @@ fn to_format_or_not_to_format() { assert!(true, "{}",); - // assert_eq!(1, 1, "{}",); // see compile-fail - // assert_ne!(1, 2, "{}",); // see compile-fail + // assert_eq!(1, 1, "{}",); // see check-fail + // assert_ne!(1, 2, "{}",); // see check-fail debug_assert!(true, "{}",); - // debug_assert_eq!(1, 1, "{}",); // see compile-fail - // debug_assert_ne!(1, 2, "{}",); // see compile-fail - // eprint!("{}",); // see compile-fail - // eprintln!("{}",); // see compile-fail - // format!("{}",); // see compile-fail - // format_args!("{}",); // see compile-fail + // debug_assert_eq!(1, 1, "{}",); // see check-fail + // debug_assert_ne!(1, 2, "{}",); // see check-fail + // eprint!("{}",); // see check-fail + // eprintln!("{}",); // see check-fail + // format!("{}",); // see check-fail + // format_args!("{}",); // see check-fail if falsum() { panic!("{}",); } - // print!("{}",); // see compile-fail - // println!("{}",); // see compile-fail - // unimplemented!("{}",); // see compile-fail + // print!("{}",); // see check-fail + // println!("{}",); // see check-fail + // unimplemented!("{}",); // see check-fail if falsum() { unreachable!("{}",); } - // write!(&mut stdout, "{}",); // see compile-fail - // writeln!(&mut stdout, "{}",); // see compile-fail + // write!(&mut stdout, "{}",); // see check-fail + // writeln!(&mut stdout, "{}",); // see check-fail } diff --git a/src/test/ui/macros/macro-comma-behavior.core.stderr b/src/test/ui/macros/macro-comma-behavior.core.stderr index dd0cac659fd..ac15e9fa8ea 100644 --- a/src/test/ui/macros/macro-comma-behavior.core.stderr +++ b/src/test/ui/macros/macro-comma-behavior.core.stderr @@ -23,22 +23,28 @@ LL | debug_assert_ne!(1, 2, "{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:54:19 + --> $DIR/macro-comma-behavior.rs:52:19 | LL | format_args!("{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:72:21 + --> $DIR/macro-comma-behavior.rs:68:21 | LL | unimplemented!("{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:81:24 + --> $DIR/macro-comma-behavior.rs:77:24 | LL | write!(f, "{}",)?; | ^^ -error: aborting due to 7 previous errors +error: 1 positional argument in format string, but no arguments were given + --> $DIR/macro-comma-behavior.rs:81:26 + | +LL | writeln!(f, "{}",)?; + | ^^ + +error: aborting due to 8 previous errors diff --git a/src/test/ui/macros/macro-comma-behavior.rs b/src/test/ui/macros/macro-comma-behavior.rs index 0bfe0683078..27d50ff3d57 100644 --- a/src/test/ui/macros/macro-comma-behavior.rs +++ b/src/test/ui/macros/macro-comma-behavior.rs @@ -40,10 +40,8 @@ fn to_format_or_not_to_format() { } #[cfg(std)] { - // FIXME: compile-fail says "expected error not found" even though - // rustc does emit an error - // eprintln!("{}",); - // [std]~^ ERROR no arguments + eprintln!("{}",); + //[std]~^ ERROR no arguments } #[cfg(std)] { @@ -63,10 +61,8 @@ fn to_format_or_not_to_format() { } #[cfg(std)] { - // FIXME: compile-fail says "expected error not found" even though - // rustc does emit an error - // println!("{}",); - // [std]~^ ERROR no arguments + println!("{}",); + //[std]~^ ERROR no arguments } unimplemented!("{}",); @@ -82,11 +78,9 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { //[core]~^ ERROR no arguments //[std]~^^ ERROR no arguments - // FIXME: compile-fail says "expected error not found" even though - // rustc does emit an error - // writeln!(f, "{}",)?; - // [core]~^ ERROR no arguments - // [std]~^^ ERROR no arguments + writeln!(f, "{}",)?; + //[core]~^ ERROR no arguments + //[std]~^^ ERROR no arguments Ok(()) } } diff --git a/src/test/ui/macros/macro-comma-behavior.std.stderr b/src/test/ui/macros/macro-comma-behavior.std.stderr index 4372d89fbf5..7fd060e2224 100644 --- a/src/test/ui/macros/macro-comma-behavior.std.stderr +++ b/src/test/ui/macros/macro-comma-behavior.std.stderr @@ -29,34 +29,52 @@ LL | eprint!("{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:50:18 + --> $DIR/macro-comma-behavior.rs:43:20 + | +LL | eprintln!("{}",); + | ^^ + +error: 1 positional argument in format string, but no arguments were given + --> $DIR/macro-comma-behavior.rs:48:18 | LL | format!("{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:54:19 + --> $DIR/macro-comma-behavior.rs:52:19 | LL | format_args!("{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:61:17 + --> $DIR/macro-comma-behavior.rs:59:17 | LL | print!("{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:72:21 + --> $DIR/macro-comma-behavior.rs:64:19 + | +LL | println!("{}",); + | ^^ + +error: 1 positional argument in format string, but no arguments were given + --> $DIR/macro-comma-behavior.rs:68:21 | LL | unimplemented!("{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:81:24 + --> $DIR/macro-comma-behavior.rs:77:24 | LL | write!(f, "{}",)?; | ^^ -error: aborting due to 10 previous errors +error: 1 positional argument in format string, but no arguments were given + --> $DIR/macro-comma-behavior.rs:81:26 + | +LL | writeln!(f, "{}",)?; + | ^^ + +error: aborting due to 13 previous errors diff --git a/src/test/ui/macros/macro-comma-support-rpass.rs b/src/test/ui/macros/macro-comma-support-rpass.rs index 50c0ef3451d..f6c4f896d67 100644 --- a/src/test/ui/macros/macro-comma-support-rpass.rs +++ b/src/test/ui/macros/macro-comma-support-rpass.rs @@ -68,7 +68,7 @@ fn column() { let _ = column!(); } -// compile_error! is in a companion to this test in compile-fail +// compile_error! is in a check-fail companion to this test #[test] fn concat() { diff --git a/src/test/ui/macros/macro-match-nonterminal.rs b/src/test/ui/macros/macro-match-nonterminal.rs index 6b023e41372..b23e5c71c03 100644 --- a/src/test/ui/macros/macro-match-nonterminal.rs +++ b/src/test/ui/macros/macro-match-nonterminal.rs @@ -2,6 +2,7 @@ macro_rules! test { ($a, $b) => { //~^ ERROR missing fragment //~| ERROR missing fragment + //~| WARN this was previously accepted () }; } diff --git a/src/test/ui/macros/macro-match-nonterminal.stderr b/src/test/ui/macros/macro-match-nonterminal.stderr index 334d62812cd..674ce3434aa 100644 --- a/src/test/ui/macros/macro-match-nonterminal.stderr +++ b/src/test/ui/macros/macro-match-nonterminal.stderr @@ -9,6 +9,10 @@ error: missing fragment specifier | LL | ($a, $b) => { | ^^ + | + = note: `#[deny(missing_fragment_specifier)]` on by default + = 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 #40107 error: aborting due to 2 previous errors diff --git a/src/test/ui/macros/not-utf8.bin b/src/test/ui/macros/not-utf8.bin new file mode 100644 index 00000000000..4148e5b88fe Binary files /dev/null and b/src/test/ui/macros/not-utf8.bin differ diff --git a/src/test/ui/macros/not-utf8.rs b/src/test/ui/macros/not-utf8.rs new file mode 100644 index 00000000000..1cb1fdcb8c9 --- /dev/null +++ b/src/test/ui/macros/not-utf8.rs @@ -0,0 +1,5 @@ +// error-pattern: did not contain valid UTF-8 + +fn foo() { + include!("not-utf8.bin") +} diff --git a/src/test/ui/macros/not-utf8.stderr b/src/test/ui/macros/not-utf8.stderr new file mode 100644 index 00000000000..f47be14fae3 --- /dev/null +++ b/src/test/ui/macros/not-utf8.stderr @@ -0,0 +1,10 @@ +error: couldn't read $DIR/not-utf8.bin: stream did not contain valid UTF-8 + --> $DIR/not-utf8.rs:4:5 + | +LL | include!("not-utf8.bin") + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/src/test/ui/meta/meta-expected-error-wrong-rev.a.stderr b/src/test/ui/meta/meta-expected-error-wrong-rev.a.stderr new file mode 100644 index 00000000000..583b2c4cfe0 --- /dev/null +++ b/src/test/ui/meta/meta-expected-error-wrong-rev.a.stderr @@ -0,0 +1,16 @@ +error[E0308]: mismatched types + --> $DIR/meta-expected-error-wrong-rev.rs:13:18 + | +LL | let x: u32 = 22_usize; + | --- ^^^^^^^^ expected `u32`, found `usize` + | | + | expected due to this + | +help: change the type of the numeric literal from `usize` to `u32` + | +LL | let x: u32 = 22_u32; + | ^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/meta/meta-expected-error-wrong-rev.rs b/src/test/ui/meta/meta-expected-error-wrong-rev.rs new file mode 100644 index 00000000000..7e49434142b --- /dev/null +++ b/src/test/ui/meta/meta-expected-error-wrong-rev.rs @@ -0,0 +1,16 @@ +// ignore-compare-mode-nll + +// revisions: a +// should-fail + +// This is a "meta-test" of the compilertest framework itself. In +// particular, it includes the right error message, but the message +// targets the wrong revision, so we expect the execution to fail. +// See also `meta-expected-error-correct-rev.rs`. + +#[cfg(a)] +fn foo() { + let x: u32 = 22_usize; //[b]~ ERROR mismatched types +} + +fn main() { } diff --git a/src/test/ui/mir/mir-inlining/array-clone-with-generic-size.rs b/src/test/ui/mir/mir-inlining/array-clone-with-generic-size.rs index 8a96303e6b9..eec0a4599c3 100644 --- a/src/test/ui/mir/mir-inlining/array-clone-with-generic-size.rs +++ b/src/test/ui/mir/mir-inlining/array-clone-with-generic-size.rs @@ -3,8 +3,6 @@ // // build-pass // compile-flags: -Zmir-opt-level=2 -Zvalidate-mir -#![feature(min_const_generics)] - #[derive(Clone)] struct Array([T; N]); diff --git a/src/test/ui/never_type/issue-52443.rs b/src/test/ui/never_type/issue-52443.rs new file mode 100644 index 00000000000..4519833b864 --- /dev/null +++ b/src/test/ui/never_type/issue-52443.rs @@ -0,0 +1,14 @@ +fn main() { + [(); & { loop { continue } } ]; //~ ERROR mismatched types + + [(); loop { break }]; //~ ERROR mismatched types + + [(); {while true {break}; 0}]; + //~^ WARN denote infinite loops with + + [(); { for _ in 0usize.. {}; 0}]; + //~^ ERROR `for` is not allowed in a `const` + //~| ERROR calls in constants are limited to constant functions + //~| ERROR mutable references are not allowed in constants + //~| ERROR calls in constants are limited to constant functions +} diff --git a/src/test/ui/never_type/issue-52443.stderr b/src/test/ui/never_type/issue-52443.stderr new file mode 100644 index 00000000000..051896cb89c --- /dev/null +++ b/src/test/ui/never_type/issue-52443.stderr @@ -0,0 +1,57 @@ +warning: denote infinite loops with `loop { ... }` + --> $DIR/issue-52443.rs:6:11 + | +LL | [(); {while true {break}; 0}]; + | ^^^^^^^^^^ help: use `loop` + | + = note: `#[warn(while_true)]` on by default + +error[E0744]: `for` is not allowed in a `const` + --> $DIR/issue-52443.rs:9:12 + | +LL | [(); { for _ in 0usize.. {}; 0}]; + | ^^^^^^^^^^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/issue-52443.rs:2:10 + | +LL | [(); & { loop { continue } } ]; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expected `usize`, found reference + | help: consider removing the borrow: `{ loop { continue } }` + | + = note: expected type `usize` + found reference `&_` + +error[E0308]: mismatched types + --> $DIR/issue-52443.rs:4:17 + | +LL | [(); loop { break }]; + | ^^^^^ + | | + | expected `usize`, found `()` + | help: give it a value of the expected type: `break 42` + +error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants + --> $DIR/issue-52443.rs:9:21 + | +LL | [(); { for _ in 0usize.. {}; 0}]; + | ^^^^^^^^ + +error[E0764]: mutable references are not allowed in constants + --> $DIR/issue-52443.rs:9:21 + | +LL | [(); { for _ in 0usize.. {}; 0}]; + | ^^^^^^^^ `&mut` is only allowed in `const fn` + +error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants + --> $DIR/issue-52443.rs:9:21 + | +LL | [(); { for _ in 0usize.. {}; 0}]; + | ^^^^^^^^ + +error: aborting due to 6 previous errors; 1 warning emitted + +Some errors have detailed explanations: E0015, E0308, E0744, E0764. +For more information about an error, try `rustc --explain E0015`. diff --git a/src/test/ui/nll/closures-in-loops.stderr b/src/test/ui/nll/closures-in-loops.stderr index 37638a93d77..2f134f83ced 100644 --- a/src/test/ui/nll/closures-in-loops.stderr +++ b/src/test/ui/nll/closures-in-loops.stderr @@ -15,7 +15,7 @@ error[E0499]: cannot borrow `x` as mutable more than once at a time LL | v.push(|| x = String::new()); | ^^ - borrows occur due to use of `x` in closure | | - | mutable borrow starts here in previous iteration of loop + | `x` was mutably borrowed here in the previous iteration of the loop error[E0524]: two closures require unique access to `x` at the same time --> $DIR/closures-in-loops.rs:20:16 diff --git a/src/test/ui/nll/issue-62007-assign-const-index.stderr b/src/test/ui/nll/issue-62007-assign-const-index.stderr index 758a14d0177..0db9fe62c38 100644 --- a/src/test/ui/nll/issue-62007-assign-const-index.stderr +++ b/src/test/ui/nll/issue-62007-assign-const-index.stderr @@ -5,7 +5,7 @@ LL | fn to_refs(mut list: [&mut List; 2]) -> Vec<&mut T> { | - let's call the lifetime of this reference `'1` ... LL | result.push(&mut list[0].value); - | ^^^^^^^^^^^^^^^^^^ mutable borrow starts here in previous iteration of loop + | ^^^^^^^^^^^^^^^^^^ `list[_].value` was mutably borrowed here in the previous iteration of the loop ... LL | return result; | ------ returning this value requires that `list[_].value` is borrowed for `'1` @@ -19,7 +19,7 @@ LL | fn to_refs(mut list: [&mut List; 2]) -> Vec<&mut T> { LL | if let Some(n) = list[0].next.as_mut() { | ^^^^^^^^^^^^--------- | | - | mutable borrow starts here in previous iteration of loop + | `list[_].next` was mutably borrowed here in the previous iteration of the loop | argument requires that `list[_].next` is borrowed for `'1` error: aborting due to 2 previous errors diff --git a/src/test/ui/nll/issue-62007-assign-differing-fields.stderr b/src/test/ui/nll/issue-62007-assign-differing-fields.stderr index f942d7628b5..f1af2e855af 100644 --- a/src/test/ui/nll/issue-62007-assign-differing-fields.stderr +++ b/src/test/ui/nll/issue-62007-assign-differing-fields.stderr @@ -5,7 +5,7 @@ LL | fn to_refs<'a, T>(mut list: (&'a mut List, &'a mut List)) -> Vec<&'a | -- lifetime `'a` defined here ... LL | result.push(&mut (list.0).value); - | ^^^^^^^^^^^^^^^^^^^ mutable borrow starts here in previous iteration of loop + | ^^^^^^^^^^^^^^^^^^^ `list.0.value` was mutably borrowed here in the previous iteration of the loop ... LL | return result; | ------ returning this value requires that `list.0.value` is borrowed for `'a` @@ -19,7 +19,7 @@ LL | fn to_refs<'a, T>(mut list: (&'a mut List, &'a mut List)) -> Vec<&'a LL | if let Some(n) = (list.0).next.as_mut() { | ^^^^^^^^^^^^^--------- | | - | mutable borrow starts here in previous iteration of loop + | `list.0.next` was mutably borrowed here in the previous iteration of the loop | argument requires that `list.0.next` is borrowed for `'a` error: aborting due to 2 previous errors diff --git a/src/test/ui/nll/polonius/assignment-to-differing-field.stderr b/src/test/ui/nll/polonius/assignment-to-differing-field.stderr index 07ca021b53b..2fe6a53a49a 100644 --- a/src/test/ui/nll/polonius/assignment-to-differing-field.stderr +++ b/src/test/ui/nll/polonius/assignment-to-differing-field.stderr @@ -5,7 +5,7 @@ LL | fn assignment_to_field_projection<'a, T>( | -- lifetime `'a` defined here ... LL | result.push(&mut (list.0).value); - | ^^^^^^^^^^^^^^^^^^^ mutable borrow starts here in previous iteration of loop + | ^^^^^^^^^^^^^^^^^^^ `list.0.value` was mutably borrowed here in the previous iteration of the loop ... LL | return result; | ------ returning this value requires that `list.0.value` is borrowed for `'a` @@ -19,7 +19,7 @@ LL | fn assignment_to_field_projection<'a, T>( LL | if let Some(n) = (list.0).next.as_mut() { | ^^^^^^^^^^^^^--------- | | - | mutable borrow starts here in previous iteration of loop + | `list.0.next` was mutably borrowed here in the previous iteration of the loop | argument requires that `list.0.next` is borrowed for `'a` error[E0499]: cannot borrow `list.0.0.0.0.0.value` as mutable more than once at a time @@ -29,7 +29,7 @@ LL | fn assignment_through_projection_chain<'a, T>( | -- lifetime `'a` defined here ... LL | result.push(&mut ((((list.0).0).0).0).0.value); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ mutable borrow starts here in previous iteration of loop + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `list.0.0.0.0.0.value` was mutably borrowed here in the previous iteration of the loop ... LL | return result; | ------ returning this value requires that `list.0.0.0.0.0.value` is borrowed for `'a` @@ -43,7 +43,7 @@ LL | fn assignment_through_projection_chain<'a, T>( LL | if let Some(n) = ((((list.0).0).0).0).0.next.as_mut() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^--------- | | - | mutable borrow starts here in previous iteration of loop + | `list.0.0.0.0.0.next` was mutably borrowed here in the previous iteration of the loop | argument requires that `list.0.0.0.0.0.next` is borrowed for `'a` error: aborting due to 4 previous errors diff --git a/src/test/ui/object-lifetime-default-from-rptr-box.rs b/src/test/ui/object-lifetime-default-from-rptr-box.rs index 8ac45b3db71..b61083078cc 100644 --- a/src/test/ui/object-lifetime-default-from-rptr-box.rs +++ b/src/test/ui/object-lifetime-default-from-rptr-box.rs @@ -23,7 +23,7 @@ fn b<'a>(t: &'a Box, mut ss: SomeStruct<'a>) { ss.u = t; } -// see also compile-fail/object-lifetime-default-from-rptr-box-error.rs +// see also ui/object-lifetime/object-lifetime-default-from-rptr-box-error.rs fn d<'a>(t: &'a Box, mut ss: SomeStruct<'a>) { ss.u = t; diff --git a/src/test/ui/panic-handler/auxiliary/weak-lang-items.rs b/src/test/ui/panic-handler/auxiliary/weak-lang-items.rs new file mode 100644 index 00000000000..7a698cf76ae --- /dev/null +++ b/src/test/ui/panic-handler/auxiliary/weak-lang-items.rs @@ -0,0 +1,22 @@ +// no-prefer-dynamic + +// This aux-file will require the eh_personality function to be codegen'd, but +// it hasn't been defined just yet. Make sure we don't explode. + +#![no_std] +#![crate_type = "rlib"] + +struct A; + +impl core::ops::Drop for A { + fn drop(&mut self) {} +} + +pub fn foo() { + let _a = A; + panic!("wut"); +} + +mod std { + pub use core::{option, fmt}; +} diff --git a/src/test/ui/panic-handler/panic-handler-missing.rs b/src/test/ui/panic-handler/panic-handler-missing.rs new file mode 100644 index 00000000000..6bb062ba657 --- /dev/null +++ b/src/test/ui/panic-handler/panic-handler-missing.rs @@ -0,0 +1,9 @@ +// dont-check-compiler-stderr +// error-pattern: `#[panic_handler]` function required, but not found + +#![feature(lang_items)] +#![no_main] +#![no_std] + +#[lang = "eh_personality"] +fn eh() {} diff --git a/src/test/ui/panic-handler/panic-handler-twice.rs b/src/test/ui/panic-handler/panic-handler-twice.rs new file mode 100644 index 00000000000..05bef66d849 --- /dev/null +++ b/src/test/ui/panic-handler/panic-handler-twice.rs @@ -0,0 +1,19 @@ +// dont-check-compiler-stderr +// aux-build:some-panic-impl.rs + +#![feature(lang_items)] +#![no_std] +#![no_main] + +extern crate some_panic_impl; + +use core::panic::PanicInfo; + +#[panic_handler] +fn panic(info: &PanicInfo) -> ! { + //~^ ERROR found duplicate lang item `panic_impl` + loop {} +} + +#[lang = "eh_personality"] +fn eh() {} diff --git a/src/test/ui/panic-handler/weak-lang-item.rs b/src/test/ui/panic-handler/weak-lang-item.rs new file mode 100644 index 00000000000..3fa3822831b --- /dev/null +++ b/src/test/ui/panic-handler/weak-lang-item.rs @@ -0,0 +1,11 @@ +// aux-build:weak-lang-items.rs +// error-pattern: `#[panic_handler]` function required, but not found +// error-pattern: language item required, but not found: `eh_personality` +// ignore-emscripten compiled with panic=abort, personality not required + +#![no_std] + +extern crate core; +extern crate weak_lang_items; + +fn main() {} diff --git a/src/test/ui/panic-handler/weak-lang-item.stderr b/src/test/ui/panic-handler/weak-lang-item.stderr new file mode 100644 index 00000000000..b7c040c7a85 --- /dev/null +++ b/src/test/ui/panic-handler/weak-lang-item.stderr @@ -0,0 +1,19 @@ +error[E0259]: the name `core` is defined multiple times + --> $DIR/weak-lang-item.rs:8:1 + | +LL | extern crate core; + | ^^^^^^^^^^^^^^^^^^ `core` reimported here + | + = note: `core` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | extern crate core as other_core; + | + +error: `#[panic_handler]` function required, but not found + +error: language item required, but not found: `eh_personality` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0259`. diff --git a/src/test/ui/panic-runtime/auxiliary/depends.rs b/src/test/ui/panic-runtime/auxiliary/depends.rs new file mode 100644 index 00000000000..e9bc2f4893e --- /dev/null +++ b/src/test/ui/panic-runtime/auxiliary/depends.rs @@ -0,0 +1,8 @@ +// no-prefer-dynamic + +#![feature(panic_runtime)] +#![crate_type = "rlib"] +#![panic_runtime] +#![no_std] + +extern crate needs_panic_runtime; diff --git a/src/test/ui/panic-runtime/auxiliary/needs-panic-runtime.rs b/src/test/ui/panic-runtime/auxiliary/needs-panic-runtime.rs new file mode 100644 index 00000000000..3f030c169f6 --- /dev/null +++ b/src/test/ui/panic-runtime/auxiliary/needs-panic-runtime.rs @@ -0,0 +1,6 @@ +// no-prefer-dynamic + +#![feature(needs_panic_runtime)] +#![crate_type = "rlib"] +#![needs_panic_runtime] +#![no_std] diff --git a/src/test/ui/panic-runtime/runtime-depend-on-needs-runtime.rs b/src/test/ui/panic-runtime/runtime-depend-on-needs-runtime.rs new file mode 100644 index 00000000000..d57f1643e98 --- /dev/null +++ b/src/test/ui/panic-runtime/runtime-depend-on-needs-runtime.rs @@ -0,0 +1,8 @@ +// dont-check-compiler-stderr +// aux-build:needs-panic-runtime.rs +// aux-build:depends.rs +// error-pattern:cannot depend on a crate that needs a panic runtime + +extern crate depends; + +fn main() {} diff --git a/src/test/ui/panic-runtime/two-panic-runtimes.rs b/src/test/ui/panic-runtime/two-panic-runtimes.rs new file mode 100644 index 00000000000..c968b5ea1e1 --- /dev/null +++ b/src/test/ui/panic-runtime/two-panic-runtimes.rs @@ -0,0 +1,16 @@ +// build-fail +// dont-check-compiler-stderr +// error-pattern:cannot link together two panic runtimes: panic_runtime_unwind and panic_runtime_unwind2 +// ignore-tidy-linelength +// aux-build:panic-runtime-unwind.rs +// aux-build:panic-runtime-unwind2.rs +// aux-build:panic-runtime-lang-items.rs + +#![no_std] +#![no_main] + +extern crate panic_runtime_unwind; +extern crate panic_runtime_unwind2; +extern crate panic_runtime_lang_items; + +fn main() {} diff --git a/src/test/ui/panic-runtime/unwind-tables-panic-required.rs b/src/test/ui/panic-runtime/unwind-tables-panic-required.rs new file mode 100644 index 00000000000..6393a27046b --- /dev/null +++ b/src/test/ui/panic-runtime/unwind-tables-panic-required.rs @@ -0,0 +1,11 @@ +// Tests that the compiler errors if the user tries to turn off unwind tables +// when they are required. +// +// dont-check-compiler-stderr +// compile-flags: -C panic=unwind -C force-unwind-tables=no +// ignore-tidy-linelength +// +// error-pattern: panic=unwind requires unwind tables, they cannot be disabled with `-C force-unwind-tables=no`. + +pub fn main() { +} diff --git a/src/test/ui/panic-runtime/unwind-tables-target-required.rs b/src/test/ui/panic-runtime/unwind-tables-target-required.rs new file mode 100644 index 00000000000..14c17893764 --- /dev/null +++ b/src/test/ui/panic-runtime/unwind-tables-target-required.rs @@ -0,0 +1,11 @@ +// Tests that the compiler errors if the user tries to turn off unwind tables +// when they are required. +// +// only-x86_64-windows-msvc +// compile-flags: -C force-unwind-tables=no +// ignore-tidy-linelength +// +// error-pattern: target requires unwind tables, they cannot be disabled with `-C force-unwind-tables=no`. + +pub fn main() { +} diff --git a/src/test/ui/panic-runtime/want-abort-got-unwind.rs b/src/test/ui/panic-runtime/want-abort-got-unwind.rs new file mode 100644 index 00000000000..e33c3bcc3f0 --- /dev/null +++ b/src/test/ui/panic-runtime/want-abort-got-unwind.rs @@ -0,0 +1,9 @@ +// build-fail +// dont-check-compiler-stderr +// error-pattern:is not compiled with this crate's panic strategy `abort` +// aux-build:panic-runtime-unwind.rs +// compile-flags:-C panic=abort + +extern crate panic_runtime_unwind; + +fn main() {} diff --git a/src/test/ui/panic-runtime/want-abort-got-unwind2.rs b/src/test/ui/panic-runtime/want-abort-got-unwind2.rs new file mode 100644 index 00000000000..438f1d85a28 --- /dev/null +++ b/src/test/ui/panic-runtime/want-abort-got-unwind2.rs @@ -0,0 +1,10 @@ +// build-fail +// dont-check-compiler-stderr +// error-pattern:is not compiled with this crate's panic strategy `abort` +// aux-build:panic-runtime-unwind.rs +// aux-build:wants-panic-runtime-unwind.rs +// compile-flags:-C panic=abort + +extern crate wants_panic_runtime_unwind; + +fn main() {} diff --git a/src/test/ui/parser/incorrect-move-async-order-issue-79694.fixed b/src/test/ui/parser/incorrect-move-async-order-issue-79694.fixed new file mode 100644 index 00000000000..055800d23b6 --- /dev/null +++ b/src/test/ui/parser/incorrect-move-async-order-issue-79694.fixed @@ -0,0 +1,8 @@ +// run-rustfix +// edition:2018 + +// Regression test for issue 79694 + +fn main() { + let _ = async move { }; //~ ERROR 7:13: 7:23: the order of `move` and `async` is incorrect +} diff --git a/src/test/ui/parser/incorrect-move-async-order-issue-79694.rs b/src/test/ui/parser/incorrect-move-async-order-issue-79694.rs new file mode 100644 index 00000000000..e8be16516d6 --- /dev/null +++ b/src/test/ui/parser/incorrect-move-async-order-issue-79694.rs @@ -0,0 +1,8 @@ +// run-rustfix +// edition:2018 + +// Regression test for issue 79694 + +fn main() { + let _ = move async { }; //~ ERROR 7:13: 7:23: the order of `move` and `async` is incorrect +} diff --git a/src/test/ui/parser/incorrect-move-async-order-issue-79694.stderr b/src/test/ui/parser/incorrect-move-async-order-issue-79694.stderr new file mode 100644 index 00000000000..2add9fb33c7 --- /dev/null +++ b/src/test/ui/parser/incorrect-move-async-order-issue-79694.stderr @@ -0,0 +1,13 @@ +error: the order of `move` and `async` is incorrect + --> $DIR/incorrect-move-async-order-issue-79694.rs:7:13 + | +LL | let _ = move async { }; + | ^^^^^^^^^^ + | +help: try switching the order + | +LL | let _ = async move { }; + | ^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/parser/issue-14303-enum.stderr b/src/test/ui/parser/issue-14303-enum.stderr index 46f16ea0cc4..bcecd75b1ab 100644 --- a/src/test/ui/parser/issue-14303-enum.stderr +++ b/src/test/ui/parser/issue-14303-enum.stderr @@ -2,7 +2,7 @@ error: lifetime parameters must be declared prior to type parameters --> $DIR/issue-14303-enum.rs:1:15 | LL | enum X<'a, T, 'b> { - | --------^^- help: reorder the parameters: lifetimes, then types: `<'a, 'b, T>` + | --------^^- help: reorder the parameters: lifetimes, then types, then consts: `<'a, 'b, T>` error: aborting due to previous error diff --git a/src/test/ui/parser/issue-14303-fn-def.stderr b/src/test/ui/parser/issue-14303-fn-def.stderr index 8cbab4b9653..082c37e0be7 100644 --- a/src/test/ui/parser/issue-14303-fn-def.stderr +++ b/src/test/ui/parser/issue-14303-fn-def.stderr @@ -2,7 +2,7 @@ error: lifetime parameters must be declared prior to type parameters --> $DIR/issue-14303-fn-def.rs:1:15 | LL | fn foo<'a, T, 'b>(x: &'a T) {} - | --------^^- help: reorder the parameters: lifetimes, then types: `<'a, 'b, T>` + | --------^^- help: reorder the parameters: lifetimes, then types, then consts: `<'a, 'b, T>` error: aborting due to previous error diff --git a/src/test/ui/parser/issue-14303-impl.stderr b/src/test/ui/parser/issue-14303-impl.stderr index 56cd4fb3810..3b5615d2a9e 100644 --- a/src/test/ui/parser/issue-14303-impl.stderr +++ b/src/test/ui/parser/issue-14303-impl.stderr @@ -2,7 +2,7 @@ error: lifetime parameters must be declared prior to type parameters --> $DIR/issue-14303-impl.rs:3:13 | LL | impl<'a, T, 'b> X {} - | --------^^- help: reorder the parameters: lifetimes, then types: `<'a, 'b, T>` + | --------^^- help: reorder the parameters: lifetimes, then types, then consts: `<'a, 'b, T>` error: aborting due to previous error diff --git a/src/test/ui/parser/issue-14303-struct.stderr b/src/test/ui/parser/issue-14303-struct.stderr index f31cb92ad66..dbd0b987dd1 100644 --- a/src/test/ui/parser/issue-14303-struct.stderr +++ b/src/test/ui/parser/issue-14303-struct.stderr @@ -2,7 +2,7 @@ error: lifetime parameters must be declared prior to type parameters --> $DIR/issue-14303-struct.rs:1:17 | LL | struct X<'a, T, 'b> { - | --------^^- help: reorder the parameters: lifetimes, then types: `<'a, 'b, T>` + | --------^^- help: reorder the parameters: lifetimes, then types, then consts: `<'a, 'b, T>` error: aborting due to previous error diff --git a/src/test/ui/parser/issue-14303-trait.stderr b/src/test/ui/parser/issue-14303-trait.stderr index 0e7399102bf..7dfa62d823f 100644 --- a/src/test/ui/parser/issue-14303-trait.stderr +++ b/src/test/ui/parser/issue-14303-trait.stderr @@ -2,7 +2,7 @@ error: lifetime parameters must be declared prior to type parameters --> $DIR/issue-14303-trait.rs:1:18 | LL | trait Foo<'a, T, 'b> {} - | --------^^- help: reorder the parameters: lifetimes, then types: `<'a, 'b, T>` + | --------^^- help: reorder the parameters: lifetimes, then types, then consts: `<'a, 'b, T>` error: aborting due to previous error diff --git a/src/test/ui/parser/macro/issue-33569.rs b/src/test/ui/parser/macro/issue-33569.rs index cf81f0480a2..80e2d7c6545 100644 --- a/src/test/ui/parser/macro/issue-33569.rs +++ b/src/test/ui/parser/macro/issue-33569.rs @@ -2,7 +2,6 @@ macro_rules! foo { { $+ } => { //~ ERROR expected identifier, found `+` //~^ ERROR missing fragment specifier $(x)(y) //~ ERROR expected one of: `*`, `+`, or `?` - //~^ ERROR attempted to repeat an expression containing no syntax variables } } diff --git a/src/test/ui/parser/macro/issue-33569.stderr b/src/test/ui/parser/macro/issue-33569.stderr index f54efaa6996..b4d38d3ce48 100644 --- a/src/test/ui/parser/macro/issue-33569.stderr +++ b/src/test/ui/parser/macro/issue-33569.stderr @@ -4,23 +4,17 @@ error: expected identifier, found `+` LL | { $+ } => { | ^ -error: missing fragment specifier - --> $DIR/issue-33569.rs:2:8 - | -LL | { $+ } => { - | ^ - error: expected one of: `*`, `+`, or `?` --> $DIR/issue-33569.rs:4:13 | LL | $(x)(y) | ^^^ -error: attempted to repeat an expression containing no syntax variables matched as repeating at this depth - --> $DIR/issue-33569.rs:4:10 +error: missing fragment specifier + --> $DIR/issue-33569.rs:2:8 | -LL | $(x)(y) - | ^^^ +LL | { $+ } => { + | ^ -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors diff --git a/src/test/ui/parser/multibyte-char-use-seperator-issue-80134.rs b/src/test/ui/parser/multibyte-char-use-seperator-issue-80134.rs new file mode 100644 index 00000000000..f3ae3aba9b9 --- /dev/null +++ b/src/test/ui/parser/multibyte-char-use-seperator-issue-80134.rs @@ -0,0 +1,12 @@ +// Regression test for #80134. + +fn main() { + (()é); + //~^ ERROR: expected one of `)`, `,`, `.`, `?`, or an operator + //~| ERROR: cannot find value `é` in this scope + //~| ERROR: non-ascii idents are not fully supported + (()æ°·); + //~^ ERROR: expected one of `)`, `,`, `.`, `?`, or an operator + //~| ERROR: cannot find value `æ°·` in this scope + //~| ERROR: non-ascii idents are not fully supported +} diff --git a/src/test/ui/parser/multibyte-char-use-seperator-issue-80134.stderr b/src/test/ui/parser/multibyte-char-use-seperator-issue-80134.stderr new file mode 100644 index 00000000000..892cc92b1bd --- /dev/null +++ b/src/test/ui/parser/multibyte-char-use-seperator-issue-80134.stderr @@ -0,0 +1,52 @@ +error: expected one of `)`, `,`, `.`, `?`, or an operator, found `é` + --> $DIR/multibyte-char-use-seperator-issue-80134.rs:4:8 + | +LL | (()é); + | ^ + | | + | expected one of `)`, `,`, `.`, `?`, or an operator + | help: missing `,` + +error: expected one of `)`, `,`, `.`, `?`, or an operator, found `æ°·` + --> $DIR/multibyte-char-use-seperator-issue-80134.rs:8:8 + | +LL | (()æ°·); + | -^ + | | + | expected one of `)`, `,`, `.`, `?`, or an operator + | help: missing `,` + +error[E0425]: cannot find value `é` in this scope + --> $DIR/multibyte-char-use-seperator-issue-80134.rs:4:8 + | +LL | (()é); + | ^ not found in this scope + +error[E0425]: cannot find value `æ°·` in this scope + --> $DIR/multibyte-char-use-seperator-issue-80134.rs:8:8 + | +LL | (()æ°·); + | ^^ not found in this scope + +error[E0658]: non-ascii idents are not fully supported + --> $DIR/multibyte-char-use-seperator-issue-80134.rs:4:8 + | +LL | (()é); + | ^ + | + = note: see issue #55467 for more information + = help: add `#![feature(non_ascii_idents)]` to the crate attributes to enable + +error[E0658]: non-ascii idents are not fully supported + --> $DIR/multibyte-char-use-seperator-issue-80134.rs:8:8 + | +LL | (()æ°·); + | ^^ + | + = note: see issue #55467 for more information + = help: add `#![feature(non_ascii_idents)]` to the crate attributes to enable + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0425, E0658. +For more information about an error, try `rustc --explain E0425`. diff --git a/src/test/ui/pattern/usefulness/consts-opaque.rs b/src/test/ui/pattern/usefulness/consts-opaque.rs index f87f96e34fc..ca4fcd85bb6 100644 --- a/src/test/ui/pattern/usefulness/consts-opaque.rs +++ b/src/test/ui/pattern/usefulness/consts-opaque.rs @@ -25,10 +25,6 @@ enum Baz { impl Eq for Baz {} const BAZ: Baz = Baz::Baz1; -type Quux = fn(usize, usize) -> usize; -fn quux(a: usize, b: usize) -> usize { a + b } -const QUUX: Quux = quux; - fn main() { match FOO { FOO => {} @@ -106,9 +102,44 @@ fn main() { //~^ ERROR unreachable pattern } + type Quux = fn(usize, usize) -> usize; + fn quux(a: usize, b: usize) -> usize { a + b } + const QUUX: Quux = quux; + match QUUX { QUUX => {} QUUX => {} _ => {} } + + #[derive(PartialEq, Eq)] + struct Wrap(T); + const WRAPQUUX: Wrap = Wrap(quux); + + match WRAPQUUX { + WRAPQUUX => {} + WRAPQUUX => {} + Wrap(_) => {} + } + + match WRAPQUUX { + Wrap(_) => {} + WRAPQUUX => {} // detected unreachable because we do inspect the `Wrap` layer + //~^ ERROR unreachable pattern + } + + #[derive(PartialEq, Eq)] + enum WhoKnows { + Yay(T), + Nope, + }; + const WHOKNOWSQUUX: WhoKnows = WhoKnows::Yay(quux); + + match WHOKNOWSQUUX { + WHOKNOWSQUUX => {} + WhoKnows::Yay(_) => {} + WHOKNOWSQUUX => {} // detected unreachable because we do inspect the `WhoKnows` layer + //~^ ERROR unreachable pattern + WhoKnows::Nope => {} + } } diff --git a/src/test/ui/pattern/usefulness/consts-opaque.stderr b/src/test/ui/pattern/usefulness/consts-opaque.stderr index f10166d5a35..68451043cf5 100644 --- a/src/test/ui/pattern/usefulness/consts-opaque.stderr +++ b/src/test/ui/pattern/usefulness/consts-opaque.stderr @@ -1,11 +1,11 @@ error: to use a constant of type `Foo` in a pattern, `Foo` must be annotated with `#[derive(PartialEq, Eq)]` - --> $DIR/consts-opaque.rs:34:9 + --> $DIR/consts-opaque.rs:30:9 | LL | FOO => {} | ^^^ error: unreachable pattern - --> $DIR/consts-opaque.rs:36:9 + --> $DIR/consts-opaque.rs:32:9 | LL | _ => {} // should not be emitting unreachable warning | ^ @@ -17,19 +17,19 @@ LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ error: to use a constant of type `Foo` in a pattern, `Foo` must be annotated with `#[derive(PartialEq, Eq)]` - --> $DIR/consts-opaque.rs:41:9 + --> $DIR/consts-opaque.rs:37:9 | LL | FOO_REF => {} | ^^^^^^^ error: unreachable pattern - --> $DIR/consts-opaque.rs:43:9 + --> $DIR/consts-opaque.rs:39:9 | LL | Foo(_) => {} // should not be emitting unreachable warning | ^^^^^^ warning: to use a constant of type `Foo` in a pattern, `Foo` must be annotated with `#[derive(PartialEq, Eq)]` - --> $DIR/consts-opaque.rs:49:9 + --> $DIR/consts-opaque.rs:45:9 | LL | FOO_REF_REF => {} | ^^^^^^^^^^^ @@ -39,13 +39,13 @@ LL | FOO_REF_REF => {} = note: for more information, see issue #62411 error: to use a constant of type `Bar` in a pattern, `Bar` must be annotated with `#[derive(PartialEq, Eq)]` - --> $DIR/consts-opaque.rs:57:9 + --> $DIR/consts-opaque.rs:53:9 | LL | BAR => {} // should not be emitting unreachable warning | ^^^ error: unreachable pattern - --> $DIR/consts-opaque.rs:57:9 + --> $DIR/consts-opaque.rs:53:9 | LL | Bar => {} | --- matches any value @@ -53,7 +53,7 @@ LL | BAR => {} // should not be emitting unreachable warning | ^^^ unreachable pattern error: unreachable pattern - --> $DIR/consts-opaque.rs:60:9 + --> $DIR/consts-opaque.rs:56:9 | LL | Bar => {} | --- matches any value @@ -62,19 +62,19 @@ LL | _ => {} | ^ unreachable pattern error: to use a constant of type `Bar` in a pattern, `Bar` must be annotated with `#[derive(PartialEq, Eq)]` - --> $DIR/consts-opaque.rs:65:9 + --> $DIR/consts-opaque.rs:61:9 | LL | BAR => {} | ^^^ error: unreachable pattern - --> $DIR/consts-opaque.rs:67:9 + --> $DIR/consts-opaque.rs:63:9 | LL | Bar => {} // should not be emitting unreachable warning | ^^^ error: unreachable pattern - --> $DIR/consts-opaque.rs:69:9 + --> $DIR/consts-opaque.rs:65:9 | LL | Bar => {} // should not be emitting unreachable warning | --- matches any value @@ -83,76 +83,88 @@ LL | _ => {} | ^ unreachable pattern error: to use a constant of type `Bar` in a pattern, `Bar` must be annotated with `#[derive(PartialEq, Eq)]` - --> $DIR/consts-opaque.rs:74:9 + --> $DIR/consts-opaque.rs:70:9 | LL | BAR => {} | ^^^ error: to use a constant of type `Bar` in a pattern, `Bar` must be annotated with `#[derive(PartialEq, Eq)]` - --> $DIR/consts-opaque.rs:76:9 + --> $DIR/consts-opaque.rs:72:9 | LL | BAR => {} // should not be emitting unreachable warning | ^^^ error: unreachable pattern - --> $DIR/consts-opaque.rs:76:9 + --> $DIR/consts-opaque.rs:72:9 | LL | BAR => {} // should not be emitting unreachable warning | ^^^ error: unreachable pattern - --> $DIR/consts-opaque.rs:79:9 + --> $DIR/consts-opaque.rs:75:9 | LL | _ => {} // should not be emitting unreachable warning | ^ error: to use a constant of type `Baz` in a pattern, `Baz` must be annotated with `#[derive(PartialEq, Eq)]` - --> $DIR/consts-opaque.rs:84:9 + --> $DIR/consts-opaque.rs:80:9 | LL | BAZ => {} | ^^^ error: unreachable pattern - --> $DIR/consts-opaque.rs:86:9 + --> $DIR/consts-opaque.rs:82:9 | LL | Baz::Baz1 => {} // should not be emitting unreachable warning | ^^^^^^^^^ error: unreachable pattern - --> $DIR/consts-opaque.rs:88:9 + --> $DIR/consts-opaque.rs:84:9 | LL | _ => {} | ^ error: to use a constant of type `Baz` in a pattern, `Baz` must be annotated with `#[derive(PartialEq, Eq)]` - --> $DIR/consts-opaque.rs:94:9 + --> $DIR/consts-opaque.rs:90:9 | LL | BAZ => {} | ^^^ error: unreachable pattern - --> $DIR/consts-opaque.rs:96:9 + --> $DIR/consts-opaque.rs:92:9 | LL | _ => {} | ^ error: to use a constant of type `Baz` in a pattern, `Baz` must be annotated with `#[derive(PartialEq, Eq)]` - --> $DIR/consts-opaque.rs:101:9 + --> $DIR/consts-opaque.rs:97:9 | LL | BAZ => {} | ^^^ error: unreachable pattern - --> $DIR/consts-opaque.rs:103:9 + --> $DIR/consts-opaque.rs:99:9 | LL | Baz::Baz2 => {} // should not be emitting unreachable warning | ^^^^^^^^^ error: unreachable pattern - --> $DIR/consts-opaque.rs:105:9 + --> $DIR/consts-opaque.rs:101:9 | LL | _ => {} // should not be emitting unreachable warning | ^ -error: aborting due to 22 previous errors; 1 warning emitted +error: unreachable pattern + --> $DIR/consts-opaque.rs:127:9 + | +LL | WRAPQUUX => {} // detected unreachable because we do inspect the `Wrap` layer + | ^^^^^^^^ + +error: unreachable pattern + --> $DIR/consts-opaque.rs:141:9 + | +LL | WHOKNOWSQUUX => {} // detected unreachable because we do inspect the `WhoKnows` layer + | ^^^^^^^^^^^^ + +error: aborting due to 24 previous errors; 1 warning emitted diff --git a/src/test/ui/pattern/usefulness/integer-ranges/exhaustiveness.rs b/src/test/ui/pattern/usefulness/integer-ranges/exhaustiveness.rs index 5a44dfc28bb..ef573db8210 100644 --- a/src/test/ui/pattern/usefulness/integer-ranges/exhaustiveness.rs +++ b/src/test/ui/pattern/usefulness/integer-ranges/exhaustiveness.rs @@ -1,5 +1,6 @@ #![feature(exclusive_range_pattern)] #![feature(assoc_char_consts)] +#![allow(overlapping_range_endpoints)] #![deny(unreachable_patterns)] macro_rules! m { diff --git a/src/test/ui/pattern/usefulness/integer-ranges/exhaustiveness.stderr b/src/test/ui/pattern/usefulness/integer-ranges/exhaustiveness.stderr index 2e0023348e4..b1440375494 100644 --- a/src/test/ui/pattern/usefulness/integer-ranges/exhaustiveness.stderr +++ b/src/test/ui/pattern/usefulness/integer-ranges/exhaustiveness.stderr @@ -1,5 +1,5 @@ error[E0004]: non-exhaustive patterns: `u8::MAX` not covered - --> $DIR/exhaustiveness.rs:47:8 + --> $DIR/exhaustiveness.rs:48:8 | LL | m!(0u8, 0..255); | ^^^ pattern `u8::MAX` not covered @@ -8,7 +8,7 @@ LL | m!(0u8, 0..255); = note: the matched value is of type `u8` error[E0004]: non-exhaustive patterns: `u8::MAX` not covered - --> $DIR/exhaustiveness.rs:48:8 + --> $DIR/exhaustiveness.rs:49:8 | LL | m!(0u8, 0..=254); | ^^^ pattern `u8::MAX` not covered @@ -17,7 +17,7 @@ LL | m!(0u8, 0..=254); = note: the matched value is of type `u8` error[E0004]: non-exhaustive patterns: `0_u8` not covered - --> $DIR/exhaustiveness.rs:49:8 + --> $DIR/exhaustiveness.rs:50:8 | LL | m!(0u8, 1..=255); | ^^^ pattern `0_u8` not covered @@ -26,7 +26,7 @@ LL | m!(0u8, 1..=255); = note: the matched value is of type `u8` error[E0004]: non-exhaustive patterns: `42_u8` not covered - --> $DIR/exhaustiveness.rs:50:8 + --> $DIR/exhaustiveness.rs:51:8 | LL | m!(0u8, 0..42 | 43..=255); | ^^^ pattern `42_u8` not covered @@ -35,7 +35,7 @@ LL | m!(0u8, 0..42 | 43..=255); = note: the matched value is of type `u8` error[E0004]: non-exhaustive patterns: `i8::MAX` not covered - --> $DIR/exhaustiveness.rs:51:8 + --> $DIR/exhaustiveness.rs:52:8 | LL | m!(0i8, -128..127); | ^^^ pattern `i8::MAX` not covered @@ -44,7 +44,7 @@ LL | m!(0i8, -128..127); = note: the matched value is of type `i8` error[E0004]: non-exhaustive patterns: `i8::MAX` not covered - --> $DIR/exhaustiveness.rs:52:8 + --> $DIR/exhaustiveness.rs:53:8 | LL | m!(0i8, -128..=126); | ^^^ pattern `i8::MAX` not covered @@ -53,7 +53,7 @@ LL | m!(0i8, -128..=126); = note: the matched value is of type `i8` error[E0004]: non-exhaustive patterns: `i8::MIN` not covered - --> $DIR/exhaustiveness.rs:53:8 + --> $DIR/exhaustiveness.rs:54:8 | LL | m!(0i8, -127..=127); | ^^^ pattern `i8::MIN` not covered @@ -62,7 +62,7 @@ LL | m!(0i8, -127..=127); = note: the matched value is of type `i8` error[E0004]: non-exhaustive patterns: `0_i8` not covered - --> $DIR/exhaustiveness.rs:54:11 + --> $DIR/exhaustiveness.rs:55:11 | LL | match 0i8 { | ^^^ pattern `0_i8` not covered @@ -71,7 +71,7 @@ LL | match 0i8 { = note: the matched value is of type `i8` error[E0004]: non-exhaustive patterns: `u128::MAX` not covered - --> $DIR/exhaustiveness.rs:59:8 + --> $DIR/exhaustiveness.rs:60:8 | LL | m!(0u128, 0..=ALMOST_MAX); | ^^^^^ pattern `u128::MAX` not covered @@ -80,7 +80,7 @@ LL | m!(0u128, 0..=ALMOST_MAX); = note: the matched value is of type `u128` error[E0004]: non-exhaustive patterns: `5_u128..=u128::MAX` not covered - --> $DIR/exhaustiveness.rs:60:8 + --> $DIR/exhaustiveness.rs:61:8 | LL | m!(0u128, 0..=4); | ^^^^^ pattern `5_u128..=u128::MAX` not covered @@ -89,7 +89,7 @@ LL | m!(0u128, 0..=4); = note: the matched value is of type `u128` error[E0004]: non-exhaustive patterns: `0_u128` not covered - --> $DIR/exhaustiveness.rs:61:8 + --> $DIR/exhaustiveness.rs:62:8 | LL | m!(0u128, 1..=u128::MAX); | ^^^^^ pattern `0_u128` not covered @@ -98,7 +98,7 @@ LL | m!(0u128, 1..=u128::MAX); = note: the matched value is of type `u128` error[E0004]: non-exhaustive patterns: `(126_u8..=127_u8, false)` not covered - --> $DIR/exhaustiveness.rs:69:11 + --> $DIR/exhaustiveness.rs:70:11 | LL | match (0u8, true) { | ^^^^^^^^^^^ pattern `(126_u8..=127_u8, false)` not covered diff --git a/src/test/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.rs b/src/test/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.rs index af720a05693..5ea92b07081 100644 --- a/src/test/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.rs +++ b/src/test/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.rs @@ -1,5 +1,5 @@ #![feature(exclusive_range_pattern)] -#![deny(overlapping_patterns)] +#![deny(overlapping_range_endpoints)] macro_rules! m { ($s:expr, $t1:pat, $t2:pat) => { @@ -12,27 +12,33 @@ macro_rules! m { } fn main() { - m!(0u8, 20..=30, 30..=40); //~ ERROR multiple patterns covering the same range - m!(0u8, 30..=40, 20..=30); //~ ERROR multiple patterns covering the same range + m!(0u8, 20..=30, 30..=40); //~ ERROR multiple patterns overlap on their endpoints + m!(0u8, 30..=40, 20..=30); //~ ERROR multiple patterns overlap on their endpoints m!(0u8, 20..=30, 31..=40); m!(0u8, 20..=30, 29..=40); - m!(0u8, 20.. 30, 29..=40); //~ ERROR multiple patterns covering the same range + m!(0u8, 20.. 30, 29..=40); //~ ERROR multiple patterns overlap on their endpoints m!(0u8, 20.. 30, 28..=40); m!(0u8, 20.. 30, 30..=40); m!(0u8, 20..=30, 30..=30); - m!(0u8, 20..=30, 30..=31); //~ ERROR multiple patterns covering the same range + m!(0u8, 20..=30, 30..=31); //~ ERROR multiple patterns overlap on their endpoints m!(0u8, 20..=30, 29..=30); m!(0u8, 20..=30, 20..=20); m!(0u8, 20..=30, 20..=21); - m!(0u8, 20..=30, 19..=20); //~ ERROR multiple patterns covering the same range + m!(0u8, 20..=30, 19..=20); //~ ERROR multiple patterns overlap on their endpoints m!(0u8, 20..=30, 20); m!(0u8, 20..=30, 25); m!(0u8, 20..=30, 30); m!(0u8, 20.. 30, 29); - m!(0u8, 20, 20..=30); //~ ERROR multiple patterns covering the same range + m!(0u8, 20, 20..=30); m!(0u8, 25, 20..=30); - m!(0u8, 30, 20..=30); //~ ERROR multiple patterns covering the same range + m!(0u8, 30, 20..=30); + match 0u8 { + 0..=10 => {} + 20..=30 => {} + 10..=20 => {} //~ ERROR multiple patterns overlap on their endpoints + _ => {} + } match (0u8, true) { (0..=10, true) => {} (10..20, true) => {} // not detected @@ -41,13 +47,13 @@ fn main() { } match (true, 0u8) { (true, 0..=10) => {} - (true, 10..20) => {} //~ ERROR multiple patterns covering the same range + (true, 10..20) => {} //~ ERROR multiple patterns overlap on their endpoints (false, 10..20) => {} _ => {} } match Some(0u8) { Some(0..=10) => {} - Some(10..20) => {} //~ ERROR multiple patterns covering the same range + Some(10..20) => {} //~ ERROR multiple patterns overlap on their endpoints _ => {} } } diff --git a/src/test/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.stderr b/src/test/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.stderr index 7bb747cdf6f..24c0419e1dd 100644 --- a/src/test/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.stderr +++ b/src/test/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.stderr @@ -1,80 +1,89 @@ -error: multiple patterns covering the same range +error: multiple patterns overlap on their endpoints --> $DIR/overlapping_range_endpoints.rs:15:22 | LL | m!(0u8, 20..=30, 30..=40); - | ------- ^^^^^^^ overlapping patterns + | ------- ^^^^^^^ ... with this range | | - | this range overlaps on `30_u8` + | this range overlaps on `30_u8`... | note: the lint level is defined here --> $DIR/overlapping_range_endpoints.rs:2:9 | -LL | #![deny(overlapping_patterns)] - | ^^^^^^^^^^^^^^^^^^^^ +LL | #![deny(overlapping_range_endpoints)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: you likely meant to write mutually exclusive ranges -error: multiple patterns covering the same range +error: multiple patterns overlap on their endpoints --> $DIR/overlapping_range_endpoints.rs:16:22 | LL | m!(0u8, 30..=40, 20..=30); - | ------- ^^^^^^^ overlapping patterns + | ------- ^^^^^^^ ... with this range | | - | this range overlaps on `30_u8` + | this range overlaps on `30_u8`... + | + = note: you likely meant to write mutually exclusive ranges -error: multiple patterns covering the same range +error: multiple patterns overlap on their endpoints --> $DIR/overlapping_range_endpoints.rs:19:22 | LL | m!(0u8, 20.. 30, 29..=40); - | ------- ^^^^^^^ overlapping patterns + | ------- ^^^^^^^ ... with this range | | - | this range overlaps on `29_u8` + | this range overlaps on `29_u8`... + | + = note: you likely meant to write mutually exclusive ranges -error: multiple patterns covering the same range +error: multiple patterns overlap on their endpoints --> $DIR/overlapping_range_endpoints.rs:23:22 | LL | m!(0u8, 20..=30, 30..=31); - | ------- ^^^^^^^ overlapping patterns + | ------- ^^^^^^^ ... with this range | | - | this range overlaps on `30_u8` + | this range overlaps on `30_u8`... + | + = note: you likely meant to write mutually exclusive ranges -error: multiple patterns covering the same range +error: multiple patterns overlap on their endpoints --> $DIR/overlapping_range_endpoints.rs:27:22 | LL | m!(0u8, 20..=30, 19..=20); - | ------- ^^^^^^^ overlapping patterns + | ------- ^^^^^^^ ... with this range | | - | this range overlaps on `20_u8` - -error: multiple patterns covering the same range - --> $DIR/overlapping_range_endpoints.rs:32:17 + | this range overlaps on `20_u8`... | -LL | m!(0u8, 20, 20..=30); - | -- ^^^^^^^ overlapping patterns - | | - | this range overlaps on `20_u8` + = note: you likely meant to write mutually exclusive ranges -error: multiple patterns covering the same range - --> $DIR/overlapping_range_endpoints.rs:34:17 +error: multiple patterns overlap on their endpoints + --> $DIR/overlapping_range_endpoints.rs:39:9 | -LL | m!(0u8, 30, 20..=30); - | -- ^^^^^^^ overlapping patterns - | | - | this range overlaps on `30_u8` +LL | 0..=10 => {} + | ------ this range overlaps on `10_u8`... +LL | 20..=30 => {} + | ------- this range overlaps on `20_u8`... +LL | 10..=20 => {} + | ^^^^^^^ ... with this range + | + = note: you likely meant to write mutually exclusive ranges -error: multiple patterns covering the same range - --> $DIR/overlapping_range_endpoints.rs:44:16 +error: multiple patterns overlap on their endpoints + --> $DIR/overlapping_range_endpoints.rs:50:16 | LL | (true, 0..=10) => {} - | ------ this range overlaps on `10_u8` + | ------ this range overlaps on `10_u8`... LL | (true, 10..20) => {} - | ^^^^^^ overlapping patterns + | ^^^^^^ ... with this range + | + = note: you likely meant to write mutually exclusive ranges -error: multiple patterns covering the same range - --> $DIR/overlapping_range_endpoints.rs:50:14 +error: multiple patterns overlap on their endpoints + --> $DIR/overlapping_range_endpoints.rs:56:14 | LL | Some(0..=10) => {} - | ------ this range overlaps on `10_u8` + | ------ this range overlaps on `10_u8`... LL | Some(10..20) => {} - | ^^^^^^ overlapping patterns + | ^^^^^^ ... with this range + | + = note: you likely meant to write mutually exclusive ranges -error: aborting due to 9 previous errors +error: aborting due to 8 previous errors diff --git a/src/test/ui/pattern/usefulness/integer-ranges/reachability.rs b/src/test/ui/pattern/usefulness/integer-ranges/reachability.rs index 6516925e939..fb4d59b0578 100644 --- a/src/test/ui/pattern/usefulness/integer-ranges/reachability.rs +++ b/src/test/ui/pattern/usefulness/integer-ranges/reachability.rs @@ -1,4 +1,5 @@ #![feature(exclusive_range_pattern)] +#![allow(overlapping_range_endpoints)] #![deny(unreachable_patterns)] macro_rules! m { diff --git a/src/test/ui/pattern/usefulness/integer-ranges/reachability.stderr b/src/test/ui/pattern/usefulness/integer-ranges/reachability.stderr index e6878d950d6..9a02fac6a75 100644 --- a/src/test/ui/pattern/usefulness/integer-ranges/reachability.stderr +++ b/src/test/ui/pattern/usefulness/integer-ranges/reachability.stderr @@ -1,149 +1,149 @@ error: unreachable pattern - --> $DIR/reachability.rs:16:17 + --> $DIR/reachability.rs:17:17 | LL | m!(0u8, 42, 42); | ^^ | note: the lint level is defined here - --> $DIR/reachability.rs:2:9 + --> $DIR/reachability.rs:3:9 | LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ error: unreachable pattern - --> $DIR/reachability.rs:20:22 + --> $DIR/reachability.rs:21:22 | LL | m!(0u8, 20..=30, 20); | ^^ error: unreachable pattern - --> $DIR/reachability.rs:21:22 + --> $DIR/reachability.rs:22:22 | LL | m!(0u8, 20..=30, 21); | ^^ error: unreachable pattern - --> $DIR/reachability.rs:22:22 + --> $DIR/reachability.rs:23:22 | LL | m!(0u8, 20..=30, 25); | ^^ error: unreachable pattern - --> $DIR/reachability.rs:23:22 + --> $DIR/reachability.rs:24:22 | LL | m!(0u8, 20..=30, 29); | ^^ error: unreachable pattern - --> $DIR/reachability.rs:24:22 + --> $DIR/reachability.rs:25:22 | LL | m!(0u8, 20..=30, 30); | ^^ error: unreachable pattern - --> $DIR/reachability.rs:27:21 + --> $DIR/reachability.rs:28:21 | LL | m!(0u8, 20..30, 20); | ^^ error: unreachable pattern - --> $DIR/reachability.rs:28:21 + --> $DIR/reachability.rs:29:21 | LL | m!(0u8, 20..30, 21); | ^^ error: unreachable pattern - --> $DIR/reachability.rs:29:21 + --> $DIR/reachability.rs:30:21 | LL | m!(0u8, 20..30, 25); | ^^ error: unreachable pattern - --> $DIR/reachability.rs:30:21 + --> $DIR/reachability.rs:31:21 | LL | m!(0u8, 20..30, 29); | ^^ error: unreachable pattern - --> $DIR/reachability.rs:34:22 + --> $DIR/reachability.rs:35:22 | LL | m!(0u8, 20..=30, 20..=30); | ^^^^^^^ error: unreachable pattern - --> $DIR/reachability.rs:35:22 + --> $DIR/reachability.rs:36:22 | LL | m!(0u8, 20.. 30, 20.. 30); | ^^^^^^^ error: unreachable pattern - --> $DIR/reachability.rs:36:22 + --> $DIR/reachability.rs:37:22 | LL | m!(0u8, 20..=30, 20.. 30); | ^^^^^^^ error: unreachable pattern - --> $DIR/reachability.rs:38:22 + --> $DIR/reachability.rs:39:22 | LL | m!(0u8, 20..=30, 21..=30); | ^^^^^^^ error: unreachable pattern - --> $DIR/reachability.rs:39:22 + --> $DIR/reachability.rs:40:22 | LL | m!(0u8, 20..=30, 20..=29); | ^^^^^^^ error: unreachable pattern - --> $DIR/reachability.rs:41:24 + --> $DIR/reachability.rs:42:24 | LL | m!('a', 'A'..='z', 'a'..='z'); | ^^^^^^^^^ error: unreachable pattern - --> $DIR/reachability.rs:48:9 + --> $DIR/reachability.rs:49:9 | LL | 5..=8 => {}, | ^^^^^ error: unreachable pattern - --> $DIR/reachability.rs:54:9 + --> $DIR/reachability.rs:55:9 | LL | 5..15 => {}, | ^^^^^ error: unreachable pattern - --> $DIR/reachability.rs:61:9 + --> $DIR/reachability.rs:62:9 | LL | 5..25 => {}, | ^^^^^ error: unreachable pattern - --> $DIR/reachability.rs:69:9 + --> $DIR/reachability.rs:70:9 | LL | 5..25 => {}, | ^^^^^ error: unreachable pattern - --> $DIR/reachability.rs:75:9 + --> $DIR/reachability.rs:76:9 | LL | 5..15 => {}, | ^^^^^ error: unreachable pattern - --> $DIR/reachability.rs:82:9 + --> $DIR/reachability.rs:83:9 | LL | '\u{D7FF}'..='\u{E000}' => {}, | ^^^^^^^^^^^^^^^^^^^^^^^ error: unreachable pattern - --> $DIR/reachability.rs:103:9 + --> $DIR/reachability.rs:104:9 | LL | &FOO => {} | ^^^^ error: unreachable pattern - --> $DIR/reachability.rs:104:9 + --> $DIR/reachability.rs:105:9 | LL | BAR => {} | ^^^ diff --git a/src/test/ui/polymorphization/const_parameters/closures.stderr b/src/test/ui/polymorphization/const_parameters/closures.stderr index 63335586b76..266b6e62afd 100644 --- a/src/test/ui/polymorphization/const_parameters/closures.stderr +++ b/src/test/ui/polymorphization/const_parameters/closures.stderr @@ -6,7 +6,6 @@ LL | #![feature(const_generics, rustc_attrs)] | = note: `#[warn(incomplete_features)]` on by default = note: see issue #44580 for more information - = help: consider using `min_const_generics` instead, which is more stable and complete error: item has unused generic parameters --> $DIR/closures.rs:19:19 diff --git a/src/test/ui/polymorphization/const_parameters/functions.stderr b/src/test/ui/polymorphization/const_parameters/functions.stderr index c976a5b62aa..e379e32c1fc 100644 --- a/src/test/ui/polymorphization/const_parameters/functions.stderr +++ b/src/test/ui/polymorphization/const_parameters/functions.stderr @@ -6,7 +6,6 @@ LL | #![feature(const_generics, rustc_attrs)] | = note: `#[warn(incomplete_features)]` on by default = note: see issue #44580 for more information - = help: consider using `min_const_generics` instead, which is more stable and complete error: item has unused generic parameters --> $DIR/functions.rs:15:8 diff --git a/src/test/ui/polymorphization/generators.stderr b/src/test/ui/polymorphization/generators.stderr index b2b32db045d..c59055ba9d6 100644 --- a/src/test/ui/polymorphization/generators.stderr +++ b/src/test/ui/polymorphization/generators.stderr @@ -6,7 +6,6 @@ LL | #![feature(const_generics, generators, generator_trait, rustc_attrs)] | = note: `#[warn(incomplete_features)]` on by default = note: see issue #44580 for more information - = help: consider using `min_const_generics` instead, which is more stable and complete error: item has unused generic parameters --> $DIR/generators.rs:36:5 diff --git a/src/test/ui/privacy/issue-46209-private-enum-variant-reexport.rs b/src/test/ui/privacy/issue-46209-private-enum-variant-reexport.rs new file mode 100644 index 00000000000..d54c9931479 --- /dev/null +++ b/src/test/ui/privacy/issue-46209-private-enum-variant-reexport.rs @@ -0,0 +1,41 @@ +#![feature(crate_visibility_modifier)] + +mod rank { + pub use self::Professor::*; + //~^ ERROR enum is private and its variants cannot be re-exported + pub use self::Lieutenant::{JuniorGrade, Full}; + //~^ ERROR variant `JuniorGrade` is private and cannot be re-exported + //~| ERROR variant `Full` is private and cannot be re-exported + pub use self::PettyOfficer::*; + //~^ ERROR enum is private and its variants cannot be re-exported + pub use self::Crewman::*; + //~^ ERROR enum is private and its variants cannot be re-exported + + enum Professor { + Adjunct, + Assistant, + Associate, + Full + } + + enum Lieutenant { + JuniorGrade, + Full, + } + + pub(in rank) enum PettyOfficer { + SecondClass, + FirstClass, + Chief, + MasterChief + } + + crate enum Crewman { + Recruit, + Apprentice, + Full + } + +} + +fn main() {} diff --git a/src/test/ui/privacy/issue-46209-private-enum-variant-reexport.stderr b/src/test/ui/privacy/issue-46209-private-enum-variant-reexport.stderr new file mode 100644 index 00000000000..b876bab6c54 --- /dev/null +++ b/src/test/ui/privacy/issue-46209-private-enum-variant-reexport.stderr @@ -0,0 +1,44 @@ +error: variant `JuniorGrade` is private and cannot be re-exported + --> $DIR/issue-46209-private-enum-variant-reexport.rs:6:32 + | +LL | pub use self::Lieutenant::{JuniorGrade, Full}; + | ^^^^^^^^^^^ +... +LL | enum Lieutenant { + | --------------- help: consider making the enum public: `pub enum Lieutenant` + +error: variant `Full` is private and cannot be re-exported + --> $DIR/issue-46209-private-enum-variant-reexport.rs:6:45 + | +LL | pub use self::Lieutenant::{JuniorGrade, Full}; + | ^^^^ + +error: enum is private and its variants cannot be re-exported + --> $DIR/issue-46209-private-enum-variant-reexport.rs:4:13 + | +LL | pub use self::Professor::*; + | ^^^^^^^^^^^^^^^^^^ +... +LL | enum Professor { + | -------------- help: consider making the enum public: `pub enum Professor` + +error: enum is private and its variants cannot be re-exported + --> $DIR/issue-46209-private-enum-variant-reexport.rs:9:13 + | +LL | pub use self::PettyOfficer::*; + | ^^^^^^^^^^^^^^^^^^^^^ +... +LL | pub(in rank) enum PettyOfficer { + | ------------------------------ help: consider making the enum public: `pub enum PettyOfficer` + +error: enum is private and its variants cannot be re-exported + --> $DIR/issue-46209-private-enum-variant-reexport.rs:11:13 + | +LL | pub use self::Crewman::*; + | ^^^^^^^^^^^^^^^^ +... +LL | crate enum Crewman { + | ------------------ help: consider making the enum public: `pub enum Crewman` + +error: aborting due to 5 previous errors + diff --git a/src/test/ui/regions/regions-early-bound-trait-param.rs b/src/test/ui/regions/regions-early-bound-trait-param.rs index cc2bde78d85..276a64b8e9a 100644 --- a/src/test/ui/regions/regions-early-bound-trait-param.rs +++ b/src/test/ui/regions/regions-early-bound-trait-param.rs @@ -117,7 +117,7 @@ pub fn main() { let m : Box = make_val(); // assert_eq!(object_invoke1(&*m), (4,5)); // ~~~~~~~~~~~~~~~~~~~ - // this call yields a compilation error; see compile-fail/dropck-object-cycle.rs + // this call yields a compilation error; see ui/span/dropck-object-cycle.rs // for details. assert_eq!(object_invoke2(&*m), 5); diff --git a/src/test/ui/regions/regions-variance-contravariant-use-contravariant.rs b/src/test/ui/regions/regions-variance-contravariant-use-contravariant.rs index f10d5a25f16..e6377867018 100644 --- a/src/test/ui/regions/regions-variance-contravariant-use-contravariant.rs +++ b/src/test/ui/regions/regions-variance-contravariant-use-contravariant.rs @@ -4,7 +4,7 @@ // Test that a type which is contravariant with respect to its region // parameter compiles successfully when used in a contravariant way. // -// Note: see compile-fail/variance-regions-*.rs for the tests that check that the +// Note: see ui/variance/variance-regions-*.rs for the tests that check that the // variance inference works in the first place. // pretty-expanded FIXME #23616 diff --git a/src/test/ui/regions/regions-variance-covariant-use-covariant.rs b/src/test/ui/regions/regions-variance-covariant-use-covariant.rs index 9316aa15d32..c5c80ce54f1 100644 --- a/src/test/ui/regions/regions-variance-covariant-use-covariant.rs +++ b/src/test/ui/regions/regions-variance-covariant-use-covariant.rs @@ -3,7 +3,7 @@ // Test that a type which is covariant with respect to its region // parameter is successful when used in a covariant way. // -// Note: see compile-fail/variance-regions-*.rs for the tests that +// Note: see ui/variance/variance-regions-*.rs for the tests that // check that the variance inference works in the first place. // This is covariant with respect to 'a, meaning that diff --git a/src/test/ui/resolve/issue-65035-static-with-parent-generics.stderr b/src/test/ui/resolve/issue-65035-static-with-parent-generics.stderr index 5de8eb21582..7f8151db06f 100644 --- a/src/test/ui/resolve/issue-65035-static-with-parent-generics.stderr +++ b/src/test/ui/resolve/issue-65035-static-with-parent-generics.stderr @@ -48,7 +48,6 @@ LL | #![feature(const_generics)] | = note: `#[warn(incomplete_features)]` on by default = note: see issue #44580 for more information - = help: consider using `min_const_generics` instead, which is more stable and complete error: aborting due to 5 previous errors; 1 warning emitted diff --git a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr index 11155038a91..861a4a80ad6 100644 --- a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr +++ b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr @@ -521,7 +521,6 @@ LL | #![feature(const_generics)] | = note: `#[warn(incomplete_features)]` on by default = note: see issue #44580 for more information - = help: consider using `min_const_generics` instead, which is more stable and complete warning: the feature `let_chains` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/disallowed-positions.rs:22:12 diff --git a/src/test/ui/simd/simd-array-type.rs b/src/test/ui/simd/simd-array-type.rs index e84186a42ad..7d66395a3c8 100644 --- a/src/test/ui/simd/simd-array-type.rs +++ b/src/test/ui/simd/simd-array-type.rs @@ -3,7 +3,7 @@ // pretty-expanded FIXME #23616 -#![feature(repr_simd, platform_intrinsics, min_const_generics)] +#![feature(repr_simd, platform_intrinsics)] #[repr(simd)] #[derive(Copy, Clone)] diff --git a/src/test/ui/simd/simd-generics.rs b/src/test/ui/simd/simd-generics.rs index dedca6276cd..50a4bfd9f51 100644 --- a/src/test/ui/simd/simd-generics.rs +++ b/src/test/ui/simd/simd-generics.rs @@ -1,6 +1,6 @@ // run-pass #![allow(non_camel_case_types)] -#![feature(repr_simd, platform_intrinsics, min_const_generics)] +#![feature(repr_simd, platform_intrinsics)] use std::ops; diff --git a/src/test/ui/simd/simd-intrinsic-generic-arithmetic-saturating.rs b/src/test/ui/simd/simd-intrinsic-generic-arithmetic-saturating.rs index 4c459fa4bc8..c11d14b99d4 100644 --- a/src/test/ui/simd/simd-intrinsic-generic-arithmetic-saturating.rs +++ b/src/test/ui/simd/simd-intrinsic-generic-arithmetic-saturating.rs @@ -2,7 +2,7 @@ // ignore-emscripten #![allow(non_camel_case_types)] -#![feature(repr_simd, platform_intrinsics, min_const_generics)] +#![feature(repr_simd, platform_intrinsics)] #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] diff --git a/src/test/ui/simd/simd-intrinsic-generic-arithmetic.rs b/src/test/ui/simd/simd-intrinsic-generic-arithmetic.rs index 5b0ff88432e..96c2c6c5399 100644 --- a/src/test/ui/simd/simd-intrinsic-generic-arithmetic.rs +++ b/src/test/ui/simd/simd-intrinsic-generic-arithmetic.rs @@ -3,7 +3,7 @@ // ignore-emscripten FIXME(#45351) hits an LLVM assert -#![feature(repr_simd, platform_intrinsics, min_const_generics)] +#![feature(repr_simd, platform_intrinsics)] #[repr(simd)] #[derive(Copy, Clone)] diff --git a/src/test/ui/similar-tokens.fixed b/src/test/ui/similar-tokens.fixed deleted file mode 100644 index addba76ae3b..00000000000 --- a/src/test/ui/similar-tokens.fixed +++ /dev/null @@ -1,13 +0,0 @@ -// run-rustfix - -#![allow(unused_imports)] - -pub mod x { - pub struct A; - pub struct B; -} - -// `.` is similar to `,` so list parsing should continue to closing `}` -use x::{A, B}; //~ ERROR expected one of `,`, `::`, `as`, or `}`, found `.` - -fn main() {} diff --git a/src/test/ui/similar-tokens.rs b/src/test/ui/similar-tokens.rs index 3d1bf5fe54a..e3024c61ad2 100644 --- a/src/test/ui/similar-tokens.rs +++ b/src/test/ui/similar-tokens.rs @@ -1,5 +1,3 @@ -// run-rustfix - #![allow(unused_imports)] pub mod x { diff --git a/src/test/ui/similar-tokens.stderr b/src/test/ui/similar-tokens.stderr index 6a8d09ebae6..90acfc052dd 100644 --- a/src/test/ui/similar-tokens.stderr +++ b/src/test/ui/similar-tokens.stderr @@ -1,5 +1,5 @@ error: expected one of `,`, `::`, `as`, or `}`, found `.` - --> $DIR/similar-tokens.rs:11:10 + --> $DIR/similar-tokens.rs:9:10 | LL | use x::{A. B}; | ^ diff --git a/src/test/ui/span/dropck_arr_cycle_checked.rs b/src/test/ui/span/dropck_arr_cycle_checked.rs index ac31e4910d5..a14db5ff089 100644 --- a/src/test/ui/span/dropck_arr_cycle_checked.rs +++ b/src/test/ui/span/dropck_arr_cycle_checked.rs @@ -1,7 +1,7 @@ // Reject mixing cyclic structure and Drop when using fixed length // arrays. // -// (Compare against compile-fail/dropck_vec_cycle_checked.rs) +// (Compare against ui/span/dropck_vec_cycle_checked.rs) diff --git a/src/test/ui/span/dropck_vec_cycle_checked.rs b/src/test/ui/span/dropck_vec_cycle_checked.rs index bacd99c6825..c5d21507d76 100644 --- a/src/test/ui/span/dropck_vec_cycle_checked.rs +++ b/src/test/ui/span/dropck_vec_cycle_checked.rs @@ -1,6 +1,6 @@ // Reject mixing cyclic structure and Drop when using Vec. // -// (Compare against compile-fail/dropck_arr_cycle_checked.rs) +// (Compare against ui/span/dropck_arr_cycle_checked.rs) use std::cell::Cell; use id::Id; diff --git a/src/test/ui/specialization/defaultimpl/projection.rs b/src/test/ui/specialization/defaultimpl/projection.rs index 4a914096932..f19c55b043b 100644 --- a/src/test/ui/specialization/defaultimpl/projection.rs +++ b/src/test/ui/specialization/defaultimpl/projection.rs @@ -4,7 +4,7 @@ #![feature(specialization)] //~ WARN the feature `specialization` is incomplete // Make sure we *can* project non-defaulted associated types -// cf compile-fail/specialization-default-projection.rs +// cf ui/specialization/specialization-default-projection.rs // First, do so without any use of specialization diff --git a/src/test/ui/specialization/issue-50452-fail.rs b/src/test/ui/specialization/issue-50452-fail.rs new file mode 100644 index 00000000000..fe21e9b6ede --- /dev/null +++ b/src/test/ui/specialization/issue-50452-fail.rs @@ -0,0 +1,21 @@ +#![feature(specialization)] +//~^ WARN the feature `specialization` is incomplete + +pub trait Foo { + fn foo(); +} + +impl Foo for i32 {} +impl Foo for i64 { + fn foo() {} + //~^ERROR `foo` specializes an item from a parent `impl` +} +impl Foo for T { + fn foo() {} +} + +fn main() { + i32::foo(); + i64::foo(); + u8::foo(); +} diff --git a/src/test/ui/specialization/issue-50452-fail.stderr b/src/test/ui/specialization/issue-50452-fail.stderr new file mode 100644 index 00000000000..8e7c5037eff --- /dev/null +++ b/src/test/ui/specialization/issue-50452-fail.stderr @@ -0,0 +1,26 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-50452-fail.rs:1:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + +error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default` + --> $DIR/issue-50452-fail.rs:10:5 + | +LL | fn foo() {} + | ^^^^^^^^^^^ cannot specialize default item `foo` +... +LL | / impl Foo for T { +LL | | fn foo() {} +LL | | } + | |_- parent `impl` is here + | + = note: to specialize, `foo` in the parent `impl` must be marked `default` + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0520`. diff --git a/src/test/ui/specialization/specialization-projection.rs b/src/test/ui/specialization/specialization-projection.rs index 700975e3b82..78afe7a9495 100644 --- a/src/test/ui/specialization/specialization-projection.rs +++ b/src/test/ui/specialization/specialization-projection.rs @@ -4,7 +4,7 @@ #![feature(specialization)] //~ WARN the feature `specialization` is incomplete // Make sure we *can* project non-defaulted associated types -// cf compile-fail/specialization-default-projection.rs +// cf ui/specialization/specialization-default-projection.rs // First, do so without any use of specialization diff --git a/src/test/ui/structs-enums/discrim-explicit-23030.rs b/src/test/ui/structs-enums/discrim-explicit-23030.rs index af7ab865e32..e17025e9e88 100644 --- a/src/test/ui/structs-enums/discrim-explicit-23030.rs +++ b/src/test/ui/structs-enums/discrim-explicit-23030.rs @@ -2,7 +2,7 @@ // Issue 23030: Workaround overflowing discriminant // with explicit assignments. -// See also compile-fail/overflow-discrim.rs, which shows what +// See also ui/discrim/discrim-overflow.rs, which shows what // happens if you leave the OhNo explicit cases out here. fn f_i8() { diff --git a/src/test/ui/structs-enums/object-lifetime-default-from-rptr-struct.rs b/src/test/ui/structs-enums/object-lifetime-default-from-rptr-struct.rs index 1fc52ead48e..d3e92e16246 100644 --- a/src/test/ui/structs-enums/object-lifetime-default-from-rptr-struct.rs +++ b/src/test/ui/structs-enums/object-lifetime-default-from-rptr-struct.rs @@ -27,7 +27,7 @@ fn b<'a>(t: &'a MyBox, mut ss: SomeStruct<'a>) { ss.u = t; } -// see also compile-fail/object-lifetime-default-from-rptr-box-error.rs +// see also ui/object-lifetime/object-lifetime-default-from-rptr-box-error.rs fn d<'a>(t: &'a MyBox, mut ss: SomeStruct<'a>) { ss.u = t; diff --git a/src/test/ui/suggestions/suggest-move-lifetimes.stderr b/src/test/ui/suggestions/suggest-move-lifetimes.stderr index 1851c8deaa8..657914d1c8c 100644 --- a/src/test/ui/suggestions/suggest-move-lifetimes.stderr +++ b/src/test/ui/suggestions/suggest-move-lifetimes.stderr @@ -2,25 +2,25 @@ error: lifetime parameters must be declared prior to type parameters --> $DIR/suggest-move-lifetimes.rs:1:13 | LL | struct A { - | ----^^- help: reorder the parameters: lifetimes, then types: `<'a, T>` + | ----^^- help: reorder the parameters: lifetimes, then types, then consts: `<'a, T>` error: lifetime parameters must be declared prior to type parameters --> $DIR/suggest-move-lifetimes.rs:5:13 | LL | struct B { - | ----^^---- help: reorder the parameters: lifetimes, then types: `<'a, T, U>` + | ----^^---- help: reorder the parameters: lifetimes, then types, then consts: `<'a, T, U>` error: lifetime parameters must be declared prior to type parameters --> $DIR/suggest-move-lifetimes.rs:10:16 | LL | struct C { - | -------^^- help: reorder the parameters: lifetimes, then types: `<'a, T, U>` + | -------^^- help: reorder the parameters: lifetimes, then types, then consts: `<'a, T, U>` error: lifetime parameters must be declared prior to type parameters --> $DIR/suggest-move-lifetimes.rs:15:16 | LL | struct D { - | -------^^--^^-----^^- help: reorder the parameters: lifetimes, then types: `<'a, 'b, 'c, T, U, V>` + | -------^^--^^-----^^- help: reorder the parameters: lifetimes, then types, then consts: `<'a, 'b, 'c, T, U, V>` error: aborting due to 4 previous errors diff --git a/src/test/ui/svh/auxiliary/svh-uta-base.rs b/src/test/ui/svh/auxiliary/svh-uta-base.rs index c138f1a5ba8..221a096e083 100644 --- a/src/test/ui/svh/auxiliary/svh-uta-base.rs +++ b/src/test/ui/svh/auxiliary/svh-uta-base.rs @@ -1,4 +1,4 @@ -//! "compile-fail/svh-uta-trait.rs" is checking that we detect a +//! "svh-uta-trait.rs" is checking that we detect a //! change from `use foo::TraitB` to use `foo::TraitB` in the hash //! (SVH) computation (#14132), since that will affect method //! resolution. diff --git a/src/test/ui/svh/auxiliary/svh-uta-change-use-trait.rs b/src/test/ui/svh/auxiliary/svh-uta-change-use-trait.rs index 76a472b5b26..823d29571aa 100644 --- a/src/test/ui/svh/auxiliary/svh-uta-change-use-trait.rs +++ b/src/test/ui/svh/auxiliary/svh-uta-change-use-trait.rs @@ -1,4 +1,4 @@ -//! "compile-fail/svh-uta-trait.rs" is checking that we detect a +//! "svh-uta-trait.rs" is checking that we detect a //! change from `use foo::TraitB` to use `foo::TraitB` in the hash //! (SVH) computation (#14132), since that will affect method //! resolution. diff --git a/src/test/ui/svh/auxiliary/svh-utb.rs b/src/test/ui/svh/auxiliary/svh-utb.rs index 2f27e99a961..a03e29dcedc 100644 --- a/src/test/ui/svh/auxiliary/svh-utb.rs +++ b/src/test/ui/svh/auxiliary/svh-utb.rs @@ -1,4 +1,4 @@ -//! "compile-fail/svh-uta-trait.rs" is checking that we detect a +//! "svh-uta-trait.rs" is checking that we detect a //! change from `use foo::TraitB` to use `foo::TraitB` in the hash //! (SVH) computation (#14132), since that will affect method //! resolution. diff --git a/src/test/ui/svh/svh-use-trait.rs b/src/test/ui/svh/svh-use-trait.rs index 93daca034c0..e5c427e096a 100644 --- a/src/test/ui/svh/svh-use-trait.rs +++ b/src/test/ui/svh/svh-use-trait.rs @@ -6,7 +6,7 @@ // aux-build:svh-uta-change-use-trait.rs // normalize-stderr-test: "(crate `(\w+)`:) .*" -> "$1 $$PATH_$2" -//! "compile-fail/svh-uta-trait.rs" is checking that we detect a +//! "svh-uta-trait.rs" is checking that we detect a //! change from `use foo::TraitB` to use `foo::TraitB` in the hash //! (SVH) computation (#14132), since that will affect method //! resolution. diff --git a/src/test/ui/symbol-names/const-generics-demangling.rs b/src/test/ui/symbol-names/const-generics-demangling.rs index e002124059f..55ab17fcd5a 100644 --- a/src/test/ui/symbol-names/const-generics-demangling.rs +++ b/src/test/ui/symbol-names/const-generics-demangling.rs @@ -1,7 +1,6 @@ // build-fail // compile-flags: -Z symbol-mangling-version=v0 - -#![feature(min_const_generics, rustc_attrs)] +#![feature(rustc_attrs)] pub struct Unsigned; diff --git a/src/test/ui/symbol-names/const-generics-demangling.stderr b/src/test/ui/symbol-names/const-generics-demangling.stderr index 022b3188373..a9574cacea3 100644 --- a/src/test/ui/symbol-names/const-generics-demangling.stderr +++ b/src/test/ui/symbol-names/const-generics-demangling.stderr @@ -1,71 +1,71 @@ error: symbol-name(_RMCs4fqI2P2rA04_25const_generics_demanglingINtB0_8UnsignedKhb_E) - --> $DIR/const-generics-demangling.rs:8:1 + --> $DIR/const-generics-demangling.rs:7:1 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ error: demangling(>) - --> $DIR/const-generics-demangling.rs:8:1 + --> $DIR/const-generics-demangling.rs:7:1 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ error: demangling-alt(>) - --> $DIR/const-generics-demangling.rs:8:1 + --> $DIR/const-generics-demangling.rs:7:1 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ error: symbol-name(_RMs_Cs4fqI2P2rA04_25const_generics_demanglingINtB2_6SignedKsn98_E) - --> $DIR/const-generics-demangling.rs:16:1 + --> $DIR/const-generics-demangling.rs:15:1 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ error: demangling(>) - --> $DIR/const-generics-demangling.rs:16:1 + --> $DIR/const-generics-demangling.rs:15:1 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ error: demangling-alt(>) - --> $DIR/const-generics-demangling.rs:16:1 + --> $DIR/const-generics-demangling.rs:15:1 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ error: symbol-name(_RMs0_Cs4fqI2P2rA04_25const_generics_demanglingINtB3_4BoolKb1_E) - --> $DIR/const-generics-demangling.rs:24:1 + --> $DIR/const-generics-demangling.rs:23:1 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ error: demangling(>) - --> $DIR/const-generics-demangling.rs:24:1 + --> $DIR/const-generics-demangling.rs:23:1 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ error: demangling-alt(>) - --> $DIR/const-generics-demangling.rs:24:1 + --> $DIR/const-generics-demangling.rs:23:1 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ error: symbol-name(_RMs1_Cs4fqI2P2rA04_25const_generics_demanglingINtB3_4CharKc2202_E) - --> $DIR/const-generics-demangling.rs:32:1 + --> $DIR/const-generics-demangling.rs:31:1 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ error: demangling(>) - --> $DIR/const-generics-demangling.rs:32:1 + --> $DIR/const-generics-demangling.rs:31:1 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ error: demangling-alt(>) - --> $DIR/const-generics-demangling.rs:32:1 + --> $DIR/const-generics-demangling.rs:31:1 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/symbol-names/const-generics.rs b/src/test/ui/symbol-names/const-generics.rs index 823995e5be3..2d136e6a99a 100644 --- a/src/test/ui/symbol-names/const-generics.rs +++ b/src/test/ui/symbol-names/const-generics.rs @@ -1,87 +1,85 @@ // check-pass // revisions: legacy v0 //[legacy]compile-flags: -Z symbol-mangling-version=legacy --crate-type=lib - //[v0]compile-flags: -Z symbol-mangling-version=v0 --crate-type=lib +//[v0]compile-flags: -Z symbol-mangling-version=v0 --crate-type=lib - #![feature(min_const_generics)] +// `char` +pub struct Char; - // `char` - pub struct Char; +impl Char<'A'> { + pub fn foo() {} +} - impl Char<'A'> { - pub fn foo() {} - } +impl Char { + pub fn bar() {} +} - impl Char { - pub fn bar() {} - } +// `i8` +pub struct I8; - // `i8` - pub struct I8; +impl I8<{i8::MIN}> { + pub fn foo() {} +} - impl I8<{i8::MIN}> { - pub fn foo() {} - } +impl I8<{i8::MAX}> { + pub fn foo() {} +} - impl I8<{i8::MAX}> { - pub fn foo() {} - } +impl I8 { + pub fn bar() {} +} - impl I8 { - pub fn bar() {} - } +// `i16` +pub struct I16; - // `i16` - pub struct I16; +impl I16<{i16::MIN}> { + pub fn foo() {} +} - impl I16<{i16::MIN}> { - pub fn foo() {} - } +impl I16 { + pub fn bar() {} +} - impl I16 { - pub fn bar() {} - } +// `i32` +pub struct I32; - // `i32` - pub struct I32; +impl I32<{i32::MIN}> { + pub fn foo() {} +} - impl I32<{i32::MIN}> { - pub fn foo() {} - } +impl I32 { + pub fn bar() {} +} - impl I32 { - pub fn bar() {} - } +// `i64` +pub struct I64; - // `i64` - pub struct I64; +impl I64<{i64::MIN}> { + pub fn foo() {} +} - impl I64<{i64::MIN}> { - pub fn foo() {} - } +impl I64 { + pub fn bar() {} +} - impl I64 { - pub fn bar() {} - } +// `i128` +pub struct I128; - // `i128` - pub struct I128; +impl I128<{i128::MIN}> { + pub fn foo() {} +} - impl I128<{i128::MIN}> { - pub fn foo() {} - } +impl I128 { + pub fn bar() {} +} - impl I128 { - pub fn bar() {} - } +// `isize` +pub struct ISize; - // `isize` - pub struct ISize; +impl ISize<3> { + pub fn foo() {} +} - impl ISize<3> { - pub fn foo() {} - } - - impl ISize { - pub fn bar() {} - } +impl ISize { + pub fn bar() {} +} diff --git a/src/test/ui/symbol-names/issue-76365.rs b/src/test/ui/symbol-names/issue-76365.rs index 61ba255dac0..c2e9f92f7b5 100644 --- a/src/test/ui/symbol-names/issue-76365.rs +++ b/src/test/ui/symbol-names/issue-76365.rs @@ -1,9 +1,8 @@ // check-pass // revisions: legacy v0 //[legacy]compile-flags: -Z symbol-mangling-version=legacy --crate-type=lib - //[v0]compile-flags: -Z symbol-mangling-version=v0 --crate-type=lib +//[v0]compile-flags: -Z symbol-mangling-version=v0 --crate-type=lib -#![feature(min_const_generics)] pub struct Bar; diff --git a/src/test/ui/threads-sendsync/issue-43733-2.rs b/src/test/ui/threads-sendsync/issue-43733-2.rs new file mode 100644 index 00000000000..21ea8e9a209 --- /dev/null +++ b/src/test/ui/threads-sendsync/issue-43733-2.rs @@ -0,0 +1,30 @@ +// dont-check-compiler-stderr + +#![feature(cfg_target_thread_local, thread_local_internals)] + +// On platforms *without* `#[thread_local]`, use +// a custom non-`Sync` type to fake the same error. +#[cfg(not(target_thread_local))] +struct Key { + _data: std::cell::UnsafeCell>, + _flag: std::cell::Cell<()>, +} + +#[cfg(not(target_thread_local))] +impl Key { + const fn new() -> Self { + Key { + _data: std::cell::UnsafeCell::new(None), + _flag: std::cell::Cell::new(()), + } + } +} + +#[cfg(target_thread_local)] +use std::thread::__FastLocalKeyInner as Key; + +static __KEY: Key<()> = Key::new(); +//~^ ERROR `UnsafeCell>` cannot be shared between threads +//~| ERROR cannot be shared between threads safely [E0277] + +fn main() {} diff --git a/src/test/ui/threads-sendsync/issue-43733.rs b/src/test/ui/threads-sendsync/issue-43733.rs new file mode 100644 index 00000000000..a602d7667c4 --- /dev/null +++ b/src/test/ui/threads-sendsync/issue-43733.rs @@ -0,0 +1,31 @@ +#![feature(const_fn)] +#![feature(thread_local)] +#![feature(cfg_target_thread_local, thread_local_internals)] + +type Foo = std::cell::RefCell; + +#[cfg(target_thread_local)] +#[thread_local] +static __KEY: std::thread::__FastLocalKeyInner = + std::thread::__FastLocalKeyInner::new(); + +#[cfg(not(target_thread_local))] +static __KEY: std::thread::__OsLocalKeyInner = + std::thread::__OsLocalKeyInner::new(); + +fn __getit() -> std::option::Option<&'static Foo> +{ + __KEY.get(Default::default) //~ ERROR call to unsafe function is unsafe +} + +static FOO: std::thread::LocalKey = + std::thread::LocalKey::new(__getit); +//~^ ERROR call to unsafe function is unsafe + +fn main() { + FOO.with(|foo| println!("{}", foo.borrow())); + std::thread::spawn(|| { + FOO.with(|foo| *foo.borrow_mut() += "foo"); + }).join().unwrap(); + FOO.with(|foo| println!("{}", foo.borrow())); +} diff --git a/src/test/ui/threads-sendsync/issue-43733.stderr b/src/test/ui/threads-sendsync/issue-43733.stderr new file mode 100644 index 00000000000..ee6a3b065d6 --- /dev/null +++ b/src/test/ui/threads-sendsync/issue-43733.stderr @@ -0,0 +1,19 @@ +error[E0133]: call to unsafe function is unsafe and requires unsafe function or block + --> $DIR/issue-43733.rs:18:5 + | +LL | __KEY.get(Default::default) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error[E0133]: call to unsafe function is unsafe and requires unsafe function or block + --> $DIR/issue-43733.rs:22:5 + | +LL | std::thread::LocalKey::new(__getit); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0133`. diff --git a/src/test/ui/traits/traits-repeated-supertrait.rs b/src/test/ui/traits/traits-repeated-supertrait.rs index 391d19c4385..339f9c37eea 100644 --- a/src/test/ui/traits/traits-repeated-supertrait.rs +++ b/src/test/ui/traits/traits-repeated-supertrait.rs @@ -2,7 +2,7 @@ // Test a case of a trait which extends the same supertrait twice, but // with difference type parameters. Test that we can invoke the // various methods in various ways successfully. -// See also `compile-fail/trait-repeated-supertrait-ambig.rs`. +// See also `ui/traits/trait-repeated-supertrait-ambig.rs`. trait CompareTo { diff --git a/src/test/ui/type-alias-impl-trait/assoc-type-const.stderr b/src/test/ui/type-alias-impl-trait/assoc-type-const.stderr index c5b22f0026d..e0c1b023861 100644 --- a/src/test/ui/type-alias-impl-trait/assoc-type-const.stderr +++ b/src/test/ui/type-alias-impl-trait/assoc-type-const.stderr @@ -6,7 +6,6 @@ LL | #![feature(const_generics)] | = note: `#[warn(incomplete_features)]` on by default = note: see issue #44580 for more information - = help: consider using `min_const_generics` instead, which is more stable and complete warning: 1 warning emitted diff --git a/src/test/ui/unsafe-fn-called-from-unsafe-blk.rs b/src/test/ui/unsafe-fn-called-from-unsafe-blk.rs index 38271cc3c78..3713a7065f5 100644 --- a/src/test/ui/unsafe-fn-called-from-unsafe-blk.rs +++ b/src/test/ui/unsafe-fn-called-from-unsafe-blk.rs @@ -2,7 +2,7 @@ #![allow(dead_code)] // -// See also: compile-fail/unsafe-fn-called-from-safe.rs +// See also: ui/unsafe/unsafe-fn-called-from-safe.rs // pretty-expanded FIXME #23616 diff --git a/src/test/ui/unsafe-fn-called-from-unsafe-fn.rs b/src/test/ui/unsafe-fn-called-from-unsafe-fn.rs index 26acc913e87..5e953107686 100644 --- a/src/test/ui/unsafe-fn-called-from-unsafe-fn.rs +++ b/src/test/ui/unsafe-fn-called-from-unsafe-fn.rs @@ -2,7 +2,7 @@ #![allow(dead_code)] // -// See also: compile-fail/unsafe-fn-called-from-safe.rs +// See also: ui/unsafe/unsafe-fn-called-from-safe.rs // pretty-expanded FIXME #23616 diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index 0462efaa9b0..73a4cbd0792 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -299,6 +299,7 @@ fn add_packages_to(&mut self, manifest: &mut Manifest) { let mut package = |name, targets| self.package(name, &mut manifest.pkg, targets); package("rustc", HOSTS); package("rustc-dev", HOSTS); + package("reproducible-artifacts", HOSTS); package("rustc-docs", HOSTS); package("cargo", HOSTS); package("rust-mingw", MINGW); diff --git a/src/tools/cargo b/src/tools/cargo index a3c2627fbc2..75d5d8cffe3 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit a3c2627fbc2f5391c65ba45ab53b81bf71fa323c +Subproject commit 75d5d8cffe3464631f82dcd3c470b78dc1dda8bb diff --git a/src/tools/clippy/Cargo.toml b/src/tools/clippy/Cargo.toml index 7f9d22e594b..a765390c603 100644 --- a/src/tools/clippy/Cargo.toml +++ b/src/tools/clippy/Cargo.toml @@ -20,6 +20,7 @@ publish = false [[bin]] name = "cargo-clippy" +test = false path = "src/main.rs" [[bin]] diff --git a/src/tools/clippy/README.md b/src/tools/clippy/README.md index dc931963726..aaa55e11c7d 100644 --- a/src/tools/clippy/README.md +++ b/src/tools/clippy/README.md @@ -208,6 +208,7 @@ the lint(s) you are interested in: ```terminal cargo clippy -- -A clippy::all -W clippy::useless_format -W clippy::... ``` +Note that if you've run clippy before, this may only take effect after you've modified a file or ran `cargo clean`. ### Specifying the minimum supported Rust version diff --git a/src/tools/clippy/clippy_lints/src/lifetimes.rs b/src/tools/clippy/clippy_lints/src/lifetimes.rs index 4d737b3f49b..e84c8b4e5b3 100644 --- a/src/tools/clippy/clippy_lints/src/lifetimes.rs +++ b/src/tools/clippy/clippy_lints/src/lifetimes.rs @@ -501,7 +501,7 @@ impl<'tcx> Visitor<'tcx> for BodyLifetimeChecker { // for lifetimes as parameters of generics fn visit_lifetime(&mut self, lifetime: &'tcx Lifetime) { - if lifetime.name.ident().name != kw::Invalid && lifetime.name.ident().name != kw::StaticLifetime { + if lifetime.name.ident().name != kw::Empty && lifetime.name.ident().name != kw::StaticLifetime { self.lifetimes_used_in_body = true; } } diff --git a/src/tools/clippy/src/driver.rs b/src/tools/clippy/src/driver.rs index 40f1b802e60..e490ee54c0b 100644 --- a/src/tools/clippy/src/driver.rs +++ b/src/tools/clippy/src/driver.rs @@ -1,6 +1,5 @@ #![feature(rustc_private)] #![feature(once_cell)] -#![feature(bool_to_option)] #![cfg_attr(feature = "deny-warnings", deny(warnings))] // warn on lints, that are included in `rust-lang/rust`s bootstrap #![warn(rust_2018_idioms, unused_lifetimes)] @@ -20,7 +19,6 @@ use std::borrow::Cow; use std::env; -use std::iter; use std::lazy::SyncLazy; use std::ops::Deref; use std::panic; @@ -49,6 +47,20 @@ fn arg_value<'a, T: Deref>( None } +#[test] +fn test_arg_value() { + let args = &["--bar=bar", "--foobar", "123", "--foo"]; + + assert_eq!(arg_value(&[] as &[&str], "--foobar", |_| true), None); + assert_eq!(arg_value(args, "--bar", |_| false), None); + assert_eq!(arg_value(args, "--bar", |_| true), Some("bar")); + assert_eq!(arg_value(args, "--bar", |p| p == "bar"), Some("bar")); + assert_eq!(arg_value(args, "--bar", |p| p == "foo"), None); + assert_eq!(arg_value(args, "--foobar", |p| p == "foo"), None); + assert_eq!(arg_value(args, "--foobar", |p| p == "123"), Some("123")); + assert_eq!(arg_value(args, "--foo", |_| true), None); +} + struct DefaultCallbacks; impl rustc_driver::Callbacks for DefaultCallbacks {} @@ -170,28 +182,6 @@ fn toolchain_path(home: Option, toolchain: Option) -> Option(args: &mut Vec, clippy_args: I) -where - T: AsRef, - U: AsRef + ?Sized + 'a, - I: Iterator + Clone, -{ - let args_iter = clippy_args.map(AsRef::as_ref); - let args_count = args_iter.clone().count(); - - if args_count > 0 { - if let Some(start) = args.windows(args_count).enumerate().find_map(|(current, window)| { - window - .iter() - .map(AsRef::as_ref) - .eq(args_iter.clone()) - .then_some(current) - }) { - args.drain(start..start + args_count); - } - } -} - #[allow(clippy::too_many_lines)] pub fn main() { rustc_driver::init_rustc_env_logger(); @@ -288,9 +278,20 @@ pub fn main() { args.extend(vec!["--sysroot".into(), sys_root]); }; - let clippy_args = env::var("CLIPPY_ARGS").unwrap_or_default(); - let clippy_args = clippy_args.split_whitespace(); - let no_deps = clippy_args.clone().any(|flag| flag == "--no-deps"); + let mut no_deps = false; + let clippy_args = env::var("CLIPPY_ARGS") + .unwrap_or_default() + .split("__CLIPPY_HACKERY__") + .filter_map(|s| match s { + "" => None, + "--no-deps" => { + no_deps = true; + None + }, + _ => Some(s.to_string()), + }) + .chain(vec!["--cfg".into(), r#"feature="cargo-clippy""#.into()]) + .collect::>(); // We enable Clippy if one of the following conditions is met // - IF Clippy is run on its test suite OR @@ -303,11 +304,7 @@ pub fn main() { let clippy_enabled = clippy_tests_set || (!cap_lints_allow && (!no_deps || in_primary_package)); if clippy_enabled { - remove_clippy_args(&mut args, iter::once("--no-deps")); - args.extend(vec!["--cfg".into(), r#"feature="cargo-clippy""#.into()]); - } else { - // Remove all flags passed through RUSTFLAGS if Clippy is not enabled. - remove_clippy_args(&mut args, clippy_args); + args.extend(clippy_args); } let mut clippy = ClippyCallbacks; @@ -318,58 +315,3 @@ pub fn main() { rustc_driver::RunCompiler::new(&args, callbacks).run() })) } - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_arg_value() { - let args = &["--bar=bar", "--foobar", "123", "--foo"]; - - assert_eq!(arg_value(&[] as &[&str], "--foobar", |_| true), None); - assert_eq!(arg_value(args, "--bar", |_| false), None); - assert_eq!(arg_value(args, "--bar", |_| true), Some("bar")); - assert_eq!(arg_value(args, "--bar", |p| p == "bar"), Some("bar")); - assert_eq!(arg_value(args, "--bar", |p| p == "foo"), None); - assert_eq!(arg_value(args, "--foobar", |p| p == "foo"), None); - assert_eq!(arg_value(args, "--foobar", |p| p == "123"), Some("123")); - assert_eq!(arg_value(args, "--foo", |_| true), None); - } - - #[test] - fn removes_clippy_args_from_start() { - let mut args = vec!["-D", "clippy::await_holding_lock", "--cfg", r#"feature="some_feat""#]; - let clippy_args = ["-D", "clippy::await_holding_lock"].iter(); - - remove_clippy_args(&mut args, clippy_args); - assert_eq!(args, &["--cfg", r#"feature="some_feat""#]); - } - - #[test] - fn removes_clippy_args_from_end() { - let mut args = vec!["-Zui-testing", "-A", "clippy::empty_loop", "--no-deps"]; - let clippy_args = ["-A", "clippy::empty_loop", "--no-deps"].iter(); - - remove_clippy_args(&mut args, clippy_args); - assert_eq!(args, &["-Zui-testing"]); - } - - #[test] - fn removes_clippy_args_from_middle() { - let mut args = vec!["-Zui-testing", "-W", "clippy::filter_map", "-L", "serde"]; - let clippy_args = ["-W", "clippy::filter_map"].iter(); - - remove_clippy_args(&mut args, clippy_args); - assert_eq!(args, &["-Zui-testing", "-L", "serde"]); - } - - #[test] - fn no_clippy_args_to_remove() { - let mut args = vec!["-Zui-testing", "-L", "serde"]; - let clippy_args: [&str; 0] = []; - - remove_clippy_args(&mut args, clippy_args.iter()); - assert_eq!(args, &["-Zui-testing", "-L", "serde"]); - } -} diff --git a/src/tools/clippy/src/main.rs b/src/tools/clippy/src/main.rs index 1c0e04689a9..ea06743394d 100644 --- a/src/tools/clippy/src/main.rs +++ b/src/tools/clippy/src/main.rs @@ -1,5 +1,3 @@ -#![feature(bool_to_option)] -#![feature(command_access)] #![cfg_attr(feature = "deny-warnings", deny(warnings))] // warn on lints, that are included in `rust-lang/rust`s bootstrap #![warn(rust_2018_idioms, unused_lifetimes)] @@ -64,7 +62,7 @@ struct ClippyCmd { unstable_options: bool, cargo_subcommand: &'static str, args: Vec, - clippy_args: Option, + clippy_args: Vec, } impl ClippyCmd { @@ -101,17 +99,16 @@ fn new(mut old_args: I) -> Self args.insert(0, "+nightly".to_string()); } - let mut clippy_args = old_args.collect::>().join(" "); - if cargo_subcommand == "fix" && !clippy_args.contains("--no-deps") { - clippy_args = format!("{} --no-deps", clippy_args); + let mut clippy_args: Vec = old_args.collect(); + if cargo_subcommand == "fix" && !clippy_args.iter().any(|arg| arg == "--no-deps") { + clippy_args.push("--no-deps".into()); } - let has_args = !clippy_args.is_empty(); ClippyCmd { unstable_options, cargo_subcommand, args, - clippy_args: has_args.then_some(clippy_args), + clippy_args, } } @@ -151,24 +148,20 @@ fn target_dir() -> Option<(&'static str, OsString)> { .map(|p| ("CARGO_TARGET_DIR", p)) } - fn into_std_cmd(self, rustflags: Option) -> Command { + fn into_std_cmd(self) -> Command { let mut cmd = Command::new("cargo"); + let clippy_args: String = self + .clippy_args + .iter() + .map(|arg| format!("{}__CLIPPY_HACKERY__", arg)) + .collect(); cmd.env(self.path_env(), Self::path()) .envs(ClippyCmd::target_dir()) + .env("CLIPPY_ARGS", clippy_args) .arg(self.cargo_subcommand) .args(&self.args); - // HACK: pass Clippy args to the driver *also* through RUSTFLAGS. - // This guarantees that new builds will be triggered when Clippy flags change. - if let Some(clippy_args) = self.clippy_args { - cmd.env( - "RUSTFLAGS", - rustflags.map_or(clippy_args.clone(), |flags| format!("{} {}", clippy_args, flags)), - ); - cmd.env("CLIPPY_ARGS", clippy_args); - } - cmd } } @@ -179,7 +172,7 @@ fn process(old_args: I) -> Result<(), i32> { let cmd = ClippyCmd::new(old_args); - let mut cmd = cmd.into_std_cmd(env::var("RUSTFLAGS").ok()); + let mut cmd = cmd.into_std_cmd(); let exit_status = cmd .spawn() @@ -197,7 +190,6 @@ fn process(old_args: I) -> Result<(), i32> #[cfg(test)] mod tests { use super::ClippyCmd; - use std::ffi::OsStr; #[test] #[should_panic] @@ -212,7 +204,6 @@ fn fix_unstable() { .split_whitespace() .map(ToString::to_string); let cmd = ClippyCmd::new(args); - assert_eq!("fix", cmd.cargo_subcommand); assert_eq!("RUSTC_WORKSPACE_WRAPPER", cmd.path_env()); assert!(cmd.args.iter().any(|arg| arg.ends_with("unstable-options"))); @@ -224,8 +215,7 @@ fn fix_implies_no_deps() { .split_whitespace() .map(ToString::to_string); let cmd = ClippyCmd::new(args); - - assert!(cmd.clippy_args.unwrap().contains("--no-deps")); + assert!(cmd.clippy_args.iter().any(|arg| arg == "--no-deps")); } #[test] @@ -234,15 +224,13 @@ fn no_deps_not_duplicated_with_fix() { .split_whitespace() .map(ToString::to_string); let cmd = ClippyCmd::new(args); - - assert_eq!(1, cmd.clippy_args.unwrap().matches("--no-deps").count()); + assert_eq!(cmd.clippy_args.iter().filter(|arg| *arg == "--no-deps").count(), 1); } #[test] fn check() { let args = "cargo clippy".split_whitespace().map(ToString::to_string); let cmd = ClippyCmd::new(args); - assert_eq!("check", cmd.cargo_subcommand); assert_eq!("RUSTC_WRAPPER", cmd.path_env()); } @@ -253,63 +241,7 @@ fn check_unstable() { .split_whitespace() .map(ToString::to_string); let cmd = ClippyCmd::new(args); - assert_eq!("check", cmd.cargo_subcommand); assert_eq!("RUSTC_WORKSPACE_WRAPPER", cmd.path_env()); } - - #[test] - fn clippy_args_into_rustflags() { - let args = "cargo clippy -- -W clippy::as_conversions" - .split_whitespace() - .map(ToString::to_string); - let cmd = ClippyCmd::new(args); - - let rustflags = None; - let cmd = cmd.into_std_cmd(rustflags); - - assert!(cmd - .get_envs() - .any(|(key, val)| key == "RUSTFLAGS" && val == Some(OsStr::new("-W clippy::as_conversions")))); - } - - #[test] - fn clippy_args_respect_existing_rustflags() { - let args = "cargo clippy -- -D clippy::await_holding_lock" - .split_whitespace() - .map(ToString::to_string); - let cmd = ClippyCmd::new(args); - - let rustflags = Some(r#"--cfg feature="some_feat""#.into()); - let cmd = cmd.into_std_cmd(rustflags); - - assert!(cmd.get_envs().any(|(key, val)| key == "RUSTFLAGS" - && val == Some(OsStr::new(r#"-D clippy::await_holding_lock --cfg feature="some_feat""#)))); - } - - #[test] - fn no_env_change_if_no_clippy_args() { - let args = "cargo clippy".split_whitespace().map(ToString::to_string); - let cmd = ClippyCmd::new(args); - - let rustflags = Some(r#"--cfg feature="some_feat""#.into()); - let cmd = cmd.into_std_cmd(rustflags); - - assert!(!cmd - .get_envs() - .any(|(key, _)| key == "RUSTFLAGS" || key == "CLIPPY_ARGS")); - } - - #[test] - fn no_env_change_if_no_clippy_args_nor_rustflags() { - let args = "cargo clippy".split_whitespace().map(ToString::to_string); - let cmd = ClippyCmd::new(args); - - let rustflags = None; - let cmd = cmd.into_std_cmd(rustflags); - - assert!(!cmd - .get_envs() - .any(|(key, _)| key == "RUSTFLAGS" || key == "CLIPPY_ARGS")) - } } diff --git a/src/tools/clippy/tests/dogfood.rs b/src/tools/clippy/tests/dogfood.rs index fda1413868e..052223d6d6f 100644 --- a/src/tools/clippy/tests/dogfood.rs +++ b/src/tools/clippy/tests/dogfood.rs @@ -23,7 +23,7 @@ fn dogfood_clippy() { .current_dir(root_dir) .env("CLIPPY_DOGFOOD", "1") .env("CARGO_INCREMENTAL", "0") - .arg("clippy") + .arg("clippy-preview") .arg("--all-targets") .arg("--all-features") .arg("--") diff --git a/src/tools/clippy/tests/ui/match_expr_like_matches_macro.fixed b/src/tools/clippy/tests/ui/match_expr_like_matches_macro.fixed index 7f4ebf56673..84981a52597 100644 --- a/src/tools/clippy/tests/ui/match_expr_like_matches_macro.fixed +++ b/src/tools/clippy/tests/ui/match_expr_like_matches_macro.fixed @@ -39,7 +39,7 @@ fn main() { B(i32), C, D, - }; + } let x = E::A(2); { // lint diff --git a/src/tools/clippy/tests/ui/match_expr_like_matches_macro.rs b/src/tools/clippy/tests/ui/match_expr_like_matches_macro.rs index aee56dd4a5e..94c7c3cadac 100644 --- a/src/tools/clippy/tests/ui/match_expr_like_matches_macro.rs +++ b/src/tools/clippy/tests/ui/match_expr_like_matches_macro.rs @@ -51,7 +51,7 @@ enum E { B(i32), C, D, - }; + } let x = E::A(2); { // lint diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 80fbb06b946..43dbaeb4655 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -10,8 +10,6 @@ #[derive(Clone, Copy, PartialEq, Debug)] pub enum Mode { - CompileFail, - RunFail, RunPassValgrind, Pretty, DebugInfo, @@ -42,8 +40,6 @@ impl FromStr for Mode { type Err = (); fn from_str(s: &str) -> Result { match s { - "compile-fail" => Ok(CompileFail), - "run-fail" => Ok(RunFail), "run-pass-valgrind" => Ok(RunPassValgrind), "pretty" => Ok(Pretty), "debuginfo" => Ok(DebugInfo), @@ -65,8 +61,6 @@ fn from_str(s: &str) -> Result { impl fmt::Display for Mode { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let s = match *self { - CompileFail => "compile-fail", - RunFail => "run-fail", RunPassValgrind => "run-pass-valgrind", Pretty => "pretty", DebugInfo => "debuginfo", @@ -230,7 +224,7 @@ pub struct Config { /// The name of the stage being built (stage1, etc) pub stage_id: String, - /// The test mode, compile-fail, run-fail, ui + /// The test mode, e.g. ui or debuginfo. pub mode: Mode, /// The test suite (essentially which directory is running, but without the diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index a1be0a19f68..2eba91fd1f4 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -542,10 +542,7 @@ fn load_from(&mut self, testfile: &Path, cfg: Option<&str>, config: &Config) { } if self.failure_status == -1 { - self.failure_status = match config.mode { - Mode::RunFail => 101, - _ => 1, - }; + self.failure_status = 1; } if self.should_ice { self.failure_status = 101; diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index c63bbaf70d3..aefcfe222e5 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -71,7 +71,7 @@ pub fn parse_config(args: Vec) -> Config { "", "mode", "which sort of compile tests to run", - "compile-fail | run-fail | run-pass-valgrind | pretty | debug-info | codegen | rustdoc \ + "run-pass-valgrind | pretty | debug-info | codegen | rustdoc \ | rustdoc-json | codegen-units | incremental | run-make | ui | js-doc-test | mir-opt | assembly", ) .reqopt( diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 828c4e89f0b..9f31b3ae1b1 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -5,8 +5,8 @@ use crate::common::{Assembly, Incremental, JsDocTest, MirOpt, RunMake, RustdocJson, Ui}; use crate::common::{Codegen, CodegenUnits, DebugInfo, Debugger, Rustdoc}; use crate::common::{CompareMode, FailMode, PassMode}; -use crate::common::{CompileFail, Pretty, RunFail, RunPassValgrind}; use crate::common::{Config, TestPaths}; +use crate::common::{Pretty, RunPassValgrind}; use crate::common::{UI_RUN_STDERR, UI_RUN_STDOUT}; use crate::errors::{self, Error, ErrorKind}; use crate::header::TestProps; @@ -330,13 +330,11 @@ impl<'test> TestCx<'test> { /// revisions, exactly once, with revision == None). fn run_revision(&self) { if self.props.should_ice { - if self.config.mode != CompileFail && self.config.mode != Incremental { + if self.config.mode != Incremental { self.fatal("cannot use should-ice in a test that is not cfail"); } } match self.config.mode { - CompileFail => self.run_cfail_test(), - RunFail => self.run_rfail_test(), RunPassValgrind => self.run_valgrind_test(), Pretty => self.run_pretty_test(), DebugInfo => self.run_debuginfo_test(), @@ -377,7 +375,6 @@ fn should_run_successfully(&self, pm: Option) -> bool { fn should_compile_successfully(&self, pm: Option) -> bool { match self.config.mode { - CompileFail => false, JsDocTest => true, Ui => pm.is_some() || self.props.fail_mode > Some(FailMode::Build), Incremental => { @@ -1537,8 +1534,8 @@ fn compile_test_general( }; let allow_unused = match self.config.mode { - CompileFail | Ui => { - // compile-fail and ui tests tend to have tons of unused code as + Ui => { + // UI tests tend to have tons of unused code as // it's just testing various pieces of the compile, but we don't // want to actually assert warnings about all this code. Instead // let's just ignore unused code warnings by defaults and tests @@ -1940,7 +1937,7 @@ fn make_compile_args( } match self.config.mode { - CompileFail | Incremental => { + Incremental => { // If we are extracting and matching errors in the new // fashion, then you want JSON mode. Old-skool error // patterns still match the raw compiler output. @@ -1975,8 +1972,8 @@ fn make_compile_args( rustc.arg(dir_opt); } - RunFail | RunPassValgrind | Pretty | DebugInfo | Codegen | Rustdoc | RustdocJson - | RunMake | CodegenUnits | JsDocTest | Assembly => { + RunPassValgrind | Pretty | DebugInfo | Codegen | Rustdoc | RustdocJson | RunMake + | CodegenUnits | JsDocTest | Assembly => { // do not use JSON output } } diff --git a/src/tools/lint-docs/src/groups.rs b/src/tools/lint-docs/src/groups.rs index 0a69b18a332..e8fd19a6381 100644 --- a/src/tools/lint-docs/src/groups.rs +++ b/src/tools/lint-docs/src/groups.rs @@ -116,13 +116,23 @@ fn make_groups_table( result.push('\n'); result.push_str("[warn-by-default]: listing/warn-by-default.md\n"); for lint_name in to_link { - let lint_def = - lints.iter().find(|l| l.name == lint_name.replace("-", "_")).ok_or_else(|| { - format!( - "`rustc -W help` defined lint `{}` but that lint does not appear to exist", + let lint_def = match lints.iter().find(|l| l.name == lint_name.replace("-", "_")) { + Some(def) => def, + None => { + let msg = format!( + "`rustc -W help` defined lint `{}` but that lint does not \ + appear to exist\n\ + Check that the lint definition includes the appropriate doc comments.", lint_name - ) - })?; + ); + if self.validate { + return Err(msg.into()); + } else { + eprintln!("warning: {}", msg); + continue; + } + } + }; write!( result, "[{}]: listing/{}#{}\n", diff --git a/src/tools/rust-installer b/src/tools/rust-installer index d66f476b4d5..5254dbfd25d 160000 --- a/src/tools/rust-installer +++ b/src/tools/rust-installer @@ -1 +1 @@ -Subproject commit d66f476b4d5e7fdf1ec215c9ac16c923dc292324 +Subproject commit 5254dbfd25d5284728ab624dca1969d61427a0db diff --git a/src/tools/rustc-workspace-hack/Cargo.toml b/src/tools/rustc-workspace-hack/Cargo.toml index 11b175f9e80..1cde0e25ced 100644 --- a/src/tools/rustc-workspace-hack/Cargo.toml +++ b/src/tools/rustc-workspace-hack/Cargo.toml @@ -65,6 +65,8 @@ byteorder = { version = "1", features = ['default', 'std'] } curl-sys = { version = "0.4.13", features = ["http2", "libnghttp2-sys"], optional = true } crossbeam-utils = { version = "0.7.2", features = ["nightly"] } libc = { version = "0.2.79", features = ["align"] } +# Ensure default features of libz-sys, which are disabled in some scenarios. +libz-sys = { version = "1.1.2" } proc-macro2 = { version = "1", features = ["default"] } quote = { version = "1", features = ["default"] } serde = { version = "1.0.82", features = ['derive'] } diff --git a/src/tools/rustfmt b/src/tools/rustfmt index 70ce18255f4..acd94866fd0 160000 --- a/src/tools/rustfmt +++ b/src/tools/rustfmt @@ -1 +1 @@ -Subproject commit 70ce18255f429caf0d75ecfed8c1464535ee779b +Subproject commit acd94866fd0ff5eacb7e184ae21c19e5440fc5fb diff --git a/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs index d78af2cd616..384a291a777 100644 --- a/src/tools/tidy/src/features.rs +++ b/src/tools/tidy/src/features.rs @@ -85,11 +85,7 @@ pub fn check( assert!(!lib_features.is_empty()); super::walk_many( - &[ - &src_path.join("test/ui"), - &src_path.join("test/ui-fulldeps"), - &src_path.join("test/compile-fail"), - ], + &[&src_path.join("test/ui"), &src_path.join("test/ui-fulldeps")], &mut |path| super::filter_dirs(path), &mut |entry, contents| { let file = entry.path(); diff --git a/src/tools/x/README.md b/src/tools/x/README.md index 3b3cf2847c2..80bf02e8a0e 100644 --- a/src/tools/x/README.md +++ b/src/tools/x/README.md @@ -1,3 +1,10 @@ # x `x` invokes `x.py` from any subdirectory. + +To install, run the following commands: + +``` +$ cd rust/src/tools/x/ +$ cargo install --path . +``` diff --git a/src/version b/src/version index 5a5c7211dc6..ba0a719118c 100644 --- a/src/version +++ b/src/version @@ -1 +1 @@ -1.50.0 +1.51.0 diff --git a/triagebot.toml b/triagebot.toml index fc733b9e45f..c0cf50e5167 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -90,7 +90,7 @@ exclude_labels = [ [notify-zulip."I-prioritize"] zulip_stream = 245100 # #t-compiler/wg-prioritization/alerts -topic = "I-prioritize #{number} {title}" +topic = "#{number} {title}" message_on_add = """\ @*WG-prioritization/alerts* issue #{number} has been requested for prioritization.