From 1824371178cad329ae2c407cc81def539d8e8415 Mon Sep 17 00:00:00 2001 From: Peter Jaszkowiak Date: Tue, 5 Dec 2023 21:26:57 -0700 Subject: [PATCH 1/6] range changes --- library/alloc/src/collections/btree/node.rs | 2 +- .../alloc/src/collections/vec_deque/tests.rs | 7 +- library/alloc/tests/str.rs | 4 +- library/core/benches/iter.rs | 12 +- library/core/src/array/iter.rs | 4 +- library/core/src/escape.rs | 9 +- library/core/src/iter/adapters/step_by.rs | 145 +- library/core/src/iter/mod.rs | 2 +- library/core/src/iter/range.rs | 1308 +++++++++++------ library/core/src/iter/range/legacy.rs | 784 ++++++++++ library/core/src/iter/traits/exact_size.rs | 2 +- library/core/src/iter/traits/iterator.rs | 8 +- library/core/src/ops/control_flow.rs | 2 +- library/core/src/ops/mod.rs | 10 +- library/core/src/ops/range.rs | 818 +++++------ library/core/src/ops/range/legacy.rs | 497 +++++++ library/core/src/slice/index.rs | 144 +- library/core/src/str/pattern.rs | 5 +- library/core/src/str/traits.rs | 150 +- library/core/tests/iter/adapters/chain.rs | 6 +- library/core/tests/iter/adapters/filter.rs | 4 +- library/core/tests/iter/adapters/flat_map.rs | 6 +- library/core/tests/iter/adapters/flatten.rs | 6 +- library/core/tests/iter/adapters/fuse.rs | 2 +- library/core/tests/iter/adapters/map.rs | 4 +- library/core/tests/iter/adapters/mod.rs | 7 +- library/core/tests/iter/adapters/peekable.rs | 8 +- library/core/tests/iter/adapters/skip.rs | 4 +- .../core/tests/iter/adapters/skip_while.rs | 4 +- library/core/tests/iter/adapters/take.rs | 12 +- .../core/tests/iter/adapters/take_while.rs | 2 +- library/core/tests/iter/mod.rs | 2 +- library/core/tests/iter/range.rs | 290 ++-- .../core/tests/iter/traits/double_ended.rs | 4 +- library/core/tests/iter/traits/iterator.rs | 6 +- library/core/tests/ops.rs | 8 +- library/core/tests/slice.rs | 8 +- 37 files changed, 3139 insertions(+), 1157 deletions(-) create mode 100644 library/core/src/iter/range/legacy.rs create mode 100644 library/core/src/ops/range/legacy.rs diff --git a/library/alloc/src/collections/btree/node.rs b/library/alloc/src/collections/btree/node.rs index 3233a575ecf25..0e82cf4009e61 100644 --- a/library/alloc/src/collections/btree/node.rs +++ b/library/alloc/src/collections/btree/node.rs @@ -546,7 +546,7 @@ impl<'a, K: 'a, V: 'a, Type> NodeRef, K, V, Type> { impl<'a, K, V> NodeRef, K, V, marker::Internal> { /// # Safety /// Every item returned by `range` is a valid edge index for the node. - unsafe fn correct_childrens_parent_links>(&mut self, range: R) { + unsafe fn correct_childrens_parent_links>(&mut self, range: R) { for i in range { debug_assert!(i <= self.len()); unsafe { Handle::new_edge(self.reborrow_mut(), i) }.correct_parent_link(); diff --git a/library/alloc/src/collections/vec_deque/tests.rs b/library/alloc/src/collections/vec_deque/tests.rs index b7fdebfa60b2a..517f945657c51 100644 --- a/library/alloc/src/collections/vec_deque/tests.rs +++ b/library/alloc/src/collections/vec_deque/tests.rs @@ -899,10 +899,13 @@ fn test_extend_impl(trusted_len: bool) { Self { test: VecDeque::new(), expected: VecDeque::new(), trusted_len } } - fn test_extend(&mut self, iter: I) + fn test_extend(&mut self, iter: I) where - I: Iterator + TrustedLen + Clone, + I: IntoIterator, + IntoIter: Iterator + TrustedLen + Clone, { + let iter = iter.into_iter(); + struct BasicIterator(I); impl Iterator for BasicIterator where diff --git a/library/alloc/tests/str.rs b/library/alloc/tests/str.rs index df8a260624a28..f164bcd2e34ba 100644 --- a/library/alloc/tests/str.rs +++ b/library/alloc/tests/str.rs @@ -590,7 +590,7 @@ mod slice_index { good: data[0..=5] == "abcdef"; good: data[{ - let mut iter = 0..=5; + let mut iter = core::ops::range::legacy::RangeInclusive::from(0..=5); iter.by_ref().count(); // exhaust it iter }] == ""; @@ -598,7 +598,7 @@ mod slice_index { // 0..=6 is out of bounds before exhaustion, so it // stands to reason that it still would be after. bad: data[{ - let mut iter = 0..=6; + let mut iter = core::ops::range::legacy::RangeInclusive::from(0..=6); iter.by_ref().count(); // exhaust it iter }]; diff --git a/library/core/benches/iter.rs b/library/core/benches/iter.rs index 05fec0c4b9d26..99fe5dd989290 100644 --- a/library/core/benches/iter.rs +++ b/library/core/benches/iter.rs @@ -493,42 +493,42 @@ fn bench_next_chunk_trusted_random_access(b: &mut Bencher) { #[bench] fn bench_next_chunk_filter_even(b: &mut Bencher) { - let a = (0..1024).next_chunk::<1024>().unwrap(); + let a = (0..1024).into_iter().next_chunk::<1024>().unwrap(); b.iter(|| black_box(&a).iter().filter(|&&i| i % 2 == 0).next_chunk::<32>()) } #[bench] fn bench_next_chunk_filter_predictably_true(b: &mut Bencher) { - let a = (0..1024).next_chunk::<1024>().unwrap(); + let a = (0..1024).into_iter().next_chunk::<1024>().unwrap(); b.iter(|| black_box(&a).iter().filter(|&&i| i < 100).next_chunk::<32>()) } #[bench] fn bench_next_chunk_filter_mostly_false(b: &mut Bencher) { - let a = (0..1024).next_chunk::<1024>().unwrap(); + let a = (0..1024).into_iter().next_chunk::<1024>().unwrap(); b.iter(|| black_box(&a).iter().filter(|&&i| i > 900).next_chunk::<32>()) } #[bench] fn bench_next_chunk_filter_map_even(b: &mut Bencher) { - let a = (0..1024).next_chunk::<1024>().unwrap(); + let a = (0..1024).into_iter().next_chunk::<1024>().unwrap(); b.iter(|| black_box(&a).iter().filter_map(|&i| (i % 2 == 0).then(|| i)).next_chunk::<32>()) } #[bench] fn bench_next_chunk_filter_map_predictably_true(b: &mut Bencher) { - let a = (0..1024).next_chunk::<1024>().unwrap(); + let a = (0..1024).into_iter().next_chunk::<1024>().unwrap(); b.iter(|| black_box(&a).iter().filter_map(|&i| (i < 100).then(|| i)).next_chunk::<32>()) } #[bench] fn bench_next_chunk_filter_map_mostly_false(b: &mut Bencher) { - let a = (0..1024).next_chunk::<1024>().unwrap(); + let a = (0..1024).into_iter().next_chunk::<1024>().unwrap(); b.iter(|| black_box(&a).iter().filter_map(|&i| (i > 900).then(|| i)).next_chunk::<32>()) } diff --git a/library/core/src/array/iter.rs b/library/core/src/array/iter.rs index 321357a15bf04..27aeadf821760 100644 --- a/library/core/src/array/iter.rs +++ b/library/core/src/array/iter.rs @@ -132,9 +132,9 @@ impl IntoIter { /// unsafe { Ok(buffer.transpose().assume_init()) } /// } /// - /// let r: [_; 4] = next_chunk(&mut (10..16)).unwrap(); + /// let r: [_; 4] = next_chunk(&mut (10..16).into_iter()).unwrap(); /// assert_eq!(r, [10, 11, 12, 13]); - /// let r: IntoIter<_, 40> = next_chunk(&mut (10..16)).unwrap_err(); + /// let r: IntoIter<_, 40> = next_chunk(&mut (10..16).into_iter()).unwrap_err(); /// assert_eq!(r.collect::>(), vec![10, 11, 12, 13, 14, 15]); /// ``` #[unstable(feature = "array_into_iter_constructors", issue = "91583")] diff --git a/library/core/src/escape.rs b/library/core/src/escape.rs index 60b5df752ca85..4244c0083d3ed 100644 --- a/library/core/src/escape.rs +++ b/library/core/src/escape.rs @@ -1,6 +1,7 @@ //! Helper code for character escaping. use crate::ascii; +use crate::iter::range::RangeIter; use crate::num::NonZeroUsize; use crate::ops::Range; @@ -68,14 +69,14 @@ pub(crate) struct EscapeIterInner { pub(crate) data: [ascii::Char; N], // Invariant: alive.start <= alive.end <= N. - pub(crate) alive: Range, + pub(crate) alive: RangeIter, } impl EscapeIterInner { pub fn new(data: [ascii::Char; N], alive: Range) -> Self { const { assert!(N < 256) }; debug_assert!(alive.start <= alive.end && usize::from(alive.end) <= N, "{alive:?}"); - Self { data, alive } + Self { data, alive: alive.into_iter() } } pub fn from_array(array: [ascii::Char; M]) -> Self { @@ -87,7 +88,7 @@ impl EscapeIterInner { } pub fn as_ascii(&self) -> &[ascii::Char] { - &self.data[usize::from(self.alive.start)..usize::from(self.alive.end)] + &self.data[usize::from(self.alive.inner.start)..usize::from(self.alive.inner.end)] } pub fn as_str(&self) -> &str { @@ -95,7 +96,7 @@ impl EscapeIterInner { } pub fn len(&self) -> usize { - usize::from(self.alive.end - self.alive.start) + usize::from(self.alive.inner.end - self.alive.inner.start) } pub fn next(&mut self) -> Option { diff --git a/library/core/src/iter/adapters/step_by.rs b/library/core/src/iter/adapters/step_by.rs index 9e83584e3f3db..26595a6c36187 100644 --- a/library/core/src/iter/adapters/step_by.rs +++ b/library/core/src/iter/adapters/step_by.rs @@ -1,8 +1,8 @@ use crate::convert::TryFrom; use crate::{ intrinsics, - iter::{from_fn, TrustedLen}, - ops::{Range, Try}, + iter::{from_fn, range::RangeIter, TrustedLen}, + ops::{range::legacy::Range, Try}, }; /// An iterator for stepping iterators by a custom amount. @@ -486,6 +486,89 @@ macro_rules! spec_int_ranges { /// the outer length calculation won't encounter clamped values #[unstable(feature = "trusted_len", issue = "37572")] unsafe impl TrustedLen for StepBy> {} + + impl SpecRangeSetup> for RangeIter<$t> { + #[inline] + fn setup(mut r: RangeIter<$t>, step: usize) -> RangeIter<$t> { + r.inner = as SpecRangeSetup::>>::setup(r.inner.clone(), step); + r + } + } + + unsafe impl StepByImpl> for StepBy> { + #[inline] + fn spec_next(&mut self) -> Option<$t> { + // if a step size larger than the type has been specified fall back to + // t::MAX, in which case remaining will be at most 1. + // The `+ 1` can't overflow since the constructor substracted 1 from the original value. + let step = <$t>::try_from(self.step + 1).unwrap_or(<$t>::MAX); + let remaining = self.iter.inner.end; + if remaining > 0 { + let val = self.iter.inner.start; + // this can only overflow during the last step, after which the value + // will not be used + self.iter.inner.start = val.wrapping_add(step); + self.iter.inner.end = remaining - 1; + Some(val) + } else { + None + } + } + + #[inline] + fn spec_size_hint(&self) -> (usize, Option) { + let remaining = self.iter.inner.end as usize; + (remaining, Some(remaining)) + } + + // The methods below are all copied from the Iterator trait default impls. + // We have to repeat them here so that the specialization overrides the StepByImpl defaults + + #[inline] + fn spec_nth(&mut self, n: usize) -> Option { + self.advance_by(n).ok()?; + self.next() + } + + #[inline] + fn spec_try_fold(&mut self, init: Acc, mut f: F) -> R + where + F: FnMut(Acc, Self::Item) -> R, + R: Try + { + let mut accum = init; + while let Some(x) = self.next() { + accum = f(accum, x)?; + } + try { accum } + } + + #[inline] + fn spec_fold(self, init: Acc, mut f: F) -> Acc + where + F: FnMut(Acc, Self::Item) -> Acc + { + // if a step size larger than the type has been specified fall back to + // t::MAX, in which case remaining will be at most 1. + let step = <$t>::try_from(self.step + 1).unwrap_or(<$t>::MAX); + let remaining = self.iter.inner.end; + let mut acc = init; + let mut val = self.iter.inner.start; + for _ in 0..remaining { + acc = f(acc, val); + // this can only overflow during the last step, after which the value + // will no longer be used + val = val.wrapping_add(step); + } + acc + } + } + + /// Safety: This macro is only applied to ranges over types <= usize + /// which means the inner length is guaranteed to fit into a usize and so + /// the outer length calculation won't encounter clamped values + #[unstable(feature = "trusted_len", issue = "37572")] + unsafe impl TrustedLen for StepBy> {} )*) } @@ -550,6 +633,64 @@ macro_rules! spec_int_ranges_r { accum } } + + unsafe impl StepByBackImpl> for StepBy> { + + #[inline] + fn spec_next_back(&mut self) -> Option + where RangeIter<$t>: DoubleEndedIterator + ExactSizeIterator, + { + let step = (self.step + 1) as $t; + let remaining = self.iter.inner.end; + if remaining > 0 { + let start = self.iter.inner.start; + self.iter.inner.end = remaining - 1; + Some(start + step * (remaining - 1)) + } else { + None + } + } + + // The methods below are all copied from the Iterator trait default impls. + // We have to repeat them here so that the specialization overrides the StepByImplBack defaults + + #[inline] + fn spec_nth_back(&mut self, n: usize) -> Option + where Self: DoubleEndedIterator, + { + if self.advance_back_by(n).is_err() { + return None; + } + self.next_back() + } + + #[inline] + fn spec_try_rfold(&mut self, init: Acc, mut f: F) -> R + where + Self: DoubleEndedIterator, + F: FnMut(Acc, Self::Item) -> R, + R: Try + { + let mut accum = init; + while let Some(x) = self.next_back() { + accum = f(accum, x)?; + } + try { accum } + } + + #[inline] + fn spec_rfold(mut self, init: Acc, mut f: F) -> Acc + where + Self: DoubleEndedIterator, + F: FnMut(Acc, Self::Item) -> Acc + { + let mut accum = init; + while let Some(x) = self.next_back() { + accum = f(accum, x); + } + accum + } + } )*) } diff --git a/library/core/src/iter/mod.rs b/library/core/src/iter/mod.rs index 44fef3e145b78..d1c7d761eb4ad 100644 --- a/library/core/src/iter/mod.rs +++ b/library/core/src/iter/mod.rs @@ -464,6 +464,6 @@ pub(crate) use self::adapters::try_process; pub(crate) use self::traits::UncheckedIterator; mod adapters; -mod range; +pub(crate) mod range; mod sources; mod traits; diff --git a/library/core/src/iter/range.rs b/library/core/src/iter/range.rs index 0e03d0c2d4e4f..cdbb0f0e4b3df 100644 --- a/library/core/src/iter/range.rs +++ b/library/core/src/iter/range.rs @@ -1,14 +1,17 @@ use crate::ascii::Char as AsciiChar; +use crate::cmp::Ordering; use crate::convert::TryFrom; -use crate::mem; use crate::net::{Ipv4Addr, Ipv6Addr}; use crate::num::NonZeroUsize; use crate::ops::{self, Try}; use super::{ - FusedIterator, TrustedLen, TrustedRandomAccess, TrustedRandomAccessNoCoerce, TrustedStep, + FromIterator, FusedIterator, TrustedLen, TrustedRandomAccess, TrustedRandomAccessNoCoerce, + TrustedStep, }; +mod legacy; + // Safety: All invariants are upheld. macro_rules! unsafe_impl_trusted_step { ($($type:ty)*) => {$( @@ -595,7 +598,7 @@ impl Step for Ipv6Addr { macro_rules! range_exact_iter_impl { ($($t:ty)*) => ($( #[stable(feature = "rust1", since = "1.0.0")] - impl ExactSizeIterator for ops::Range<$t> { } + impl ExactSizeIterator for RangeIter<$t> { } )*) } @@ -605,11 +608,11 @@ macro_rules! unsafe_range_trusted_random_access_impl { ($($t:ty)*) => ($( #[doc(hidden)] #[unstable(feature = "trusted_random_access", issue = "none")] - unsafe impl TrustedRandomAccess for ops::Range<$t> {} + unsafe impl TrustedRandomAccess for RangeIter<$t> {} #[doc(hidden)] #[unstable(feature = "trusted_random_access", issue = "none")] - unsafe impl TrustedRandomAccessNoCoerce for ops::Range<$t> { + unsafe impl TrustedRandomAccessNoCoerce for RangeIter<$t> { const MAY_HAVE_SIDE_EFFECT: bool = false; } )*) @@ -618,235 +621,52 @@ macro_rules! unsafe_range_trusted_random_access_impl { macro_rules! range_incl_exact_iter_impl { ($($t:ty)*) => ($( #[stable(feature = "inclusive_range", since = "1.26.0")] - impl ExactSizeIterator for ops::RangeInclusive<$t> { } + impl ExactSizeIterator for RangeInclusiveIter<$t> { } )*) } -/// Specialization implementations for `Range`. -trait RangeIteratorImpl { - type Item; - - // Iterator - fn spec_next(&mut self) -> Option; - fn spec_nth(&mut self, n: usize) -> Option; - fn spec_advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize>; - - // DoubleEndedIterator - fn spec_next_back(&mut self) -> Option; - fn spec_nth_back(&mut self, n: usize) -> Option; - fn spec_advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize>; +/// Iterator type for [`ops::range::Range`] +#[stable(feature = "rust1", since = "1.0.0")] +#[derive(Clone, Debug)] +pub struct RangeIter { + pub(crate) inner: ops::range::legacy::Range, } -impl RangeIteratorImpl for ops::Range { - type Item = A; - - #[inline] - default fn spec_next(&mut self) -> Option { - if self.start < self.end { - let n = - Step::forward_checked(self.start.clone(), 1).expect("`Step` invariants not upheld"); - Some(mem::replace(&mut self.start, n)) - } else { - None - } - } - - #[inline] - default fn spec_nth(&mut self, n: usize) -> Option { - if let Some(plus_n) = Step::forward_checked(self.start.clone(), n) { - if plus_n < self.end { - self.start = - Step::forward_checked(plus_n.clone(), 1).expect("`Step` invariants not upheld"); - return Some(plus_n); - } - } - - self.start = self.end.clone(); - None - } - - #[inline] - default fn spec_advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { - let available = if self.start <= self.end { - Step::steps_between(&self.start, &self.end).unwrap_or(usize::MAX) - } else { - 0 - }; - - let taken = available.min(n); - - self.start = - Step::forward_checked(self.start.clone(), taken).expect("`Step` invariants not upheld"); - - NonZeroUsize::new(n - taken).map_or(Ok(()), Err) - } - - #[inline] - default fn spec_next_back(&mut self) -> Option { - if self.start < self.end { - self.end = - Step::backward_checked(self.end.clone(), 1).expect("`Step` invariants not upheld"); - Some(self.end.clone()) - } else { - None - } - } - - #[inline] - default fn spec_nth_back(&mut self, n: usize) -> Option { - if let Some(minus_n) = Step::backward_checked(self.end.clone(), n) { - if minus_n > self.start { - self.end = - Step::backward_checked(minus_n, 1).expect("`Step` invariants not upheld"); - return Some(self.end.clone()); - } - } - - self.end = self.start.clone(); - None - } - - #[inline] - default fn spec_advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { - let available = if self.start <= self.end { - Step::steps_between(&self.start, &self.end).unwrap_or(usize::MAX) - } else { - 0 - }; - - let taken = available.min(n); - - self.end = - Step::backward_checked(self.end.clone(), taken).expect("`Step` invariants not upheld"); - - NonZeroUsize::new(n - taken).map_or(Ok(()), Err) - } -} - -impl RangeIteratorImpl for ops::Range { - #[inline] - fn spec_next(&mut self) -> Option { - if self.start < self.end { - let old = self.start; - // SAFETY: just checked precondition - self.start = unsafe { Step::forward_unchecked(old, 1) }; - Some(old) - } else { - None - } - } - - #[inline] - fn spec_nth(&mut self, n: usize) -> Option { - if let Some(plus_n) = Step::forward_checked(self.start, n) { - if plus_n < self.end { - // SAFETY: just checked precondition - self.start = unsafe { Step::forward_unchecked(plus_n, 1) }; - return Some(plus_n); - } - } - - self.start = self.end; - None - } - - #[inline] - fn spec_advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { - let available = if self.start <= self.end { - Step::steps_between(&self.start, &self.end).unwrap_or(usize::MAX) - } else { - 0 - }; - - let taken = available.min(n); - - // SAFETY: the conditions above ensure that the count is in bounds. If start <= end - // then steps_between either returns a bound to which we clamp or returns None which - // together with the initial inequality implies more than usize::MAX steps. - // Otherwise 0 is returned which always safe to use. - self.start = unsafe { Step::forward_unchecked(self.start, taken) }; - - NonZeroUsize::new(n - taken).map_or(Ok(()), Err) - } - - #[inline] - fn spec_next_back(&mut self) -> Option { - if self.start < self.end { - // SAFETY: just checked precondition - self.end = unsafe { Step::backward_unchecked(self.end, 1) }; - Some(self.end) - } else { - None - } - } - - #[inline] - fn spec_nth_back(&mut self, n: usize) -> Option { - if let Some(minus_n) = Step::backward_checked(self.end, n) { - if minus_n > self.start { - // SAFETY: just checked precondition - self.end = unsafe { Step::backward_unchecked(minus_n, 1) }; - return Some(self.end); - } - } - - self.end = self.start; - None - } - - #[inline] - fn spec_advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { - let available = if self.start <= self.end { - Step::steps_between(&self.start, &self.end).unwrap_or(usize::MAX) - } else { - 0 - }; - - let taken = available.min(n); - - // SAFETY: same as the spec_advance_by() implementation - self.end = unsafe { Step::backward_unchecked(self.end, taken) }; - - NonZeroUsize::new(n - taken).map_or(Ok(()), Err) +impl RangeIter { + #[doc(hidden)] + #[stable(feature = "new_range", since = "1.0.0")] + pub fn inner(&self) -> &ops::range::legacy::Range { + &self.inner } } #[stable(feature = "rust1", since = "1.0.0")] -impl Iterator for ops::Range { +impl Iterator for RangeIter { type Item = A; #[inline] fn next(&mut self) -> Option { - self.spec_next() + self.inner.next() } #[inline] fn size_hint(&self) -> (usize, Option) { - if self.start < self.end { - let hint = Step::steps_between(&self.start, &self.end); - (hint.unwrap_or(usize::MAX), hint) - } else { - (0, Some(0)) - } + self.inner.size_hint() } #[inline] fn count(self) -> usize { - if self.start < self.end { - Step::steps_between(&self.start, &self.end).expect("count overflowed usize") - } else { - 0 - } + self.inner.count() } #[inline] fn nth(&mut self, n: usize) -> Option { - self.spec_nth(n) + self.inner.nth(n) } #[inline] fn last(mut self) -> Option { - self.next_back() + self.inner.next_back() } #[inline] @@ -854,7 +674,7 @@ impl Iterator for ops::Range { where A: Ord, { - self.next() + self.inner.next() } #[inline] @@ -862,17 +682,17 @@ impl Iterator for ops::Range { where A: Ord, { - self.next_back() + self.inner.next_back() } #[inline] fn is_sorted(self) -> bool { - true + self.inner.is_sorted() } #[inline] fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { - self.spec_advance_by(n) + self.inner.advance_by(n) } #[inline] @@ -884,7 +704,7 @@ impl Iterator for ops::Range { // that is in bounds. // Additionally Self: TrustedRandomAccess is only implemented for Copy types // which means even repeated reads of the same index would be safe. - unsafe { Step::forward_unchecked(self.start.clone(), idx) } + unsafe { Step::forward_unchecked(self.inner.start.clone(), idx) } } } @@ -937,20 +757,20 @@ range_incl_exact_iter_impl! { } #[stable(feature = "rust1", since = "1.0.0")] -impl DoubleEndedIterator for ops::Range { +impl DoubleEndedIterator for RangeIter { #[inline] fn next_back(&mut self) -> Option { - self.spec_next_back() + self.inner.next_back() } #[inline] fn nth_back(&mut self, n: usize) -> Option { - self.spec_nth_back(n) + self.inner.nth_back(n) } #[inline] fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { - self.spec_advance_back_by(n) + self.inner.advance_back_by(n) } } @@ -971,400 +791,928 @@ impl DoubleEndedIterator for ops::Range { // // The second invariant logically follows the first so long as the `PartialOrd` // implementation is correct; regardless it is explicitly stated. If `a < b` -// then `(0, Some(0))` is returned by `ops::Range::size_hint`. As such +// then `(0, Some(0))` is returned by `ops::range::Range::size_hint`. As such // the second invariant is upheld. #[unstable(feature = "trusted_len", issue = "37572")] -unsafe impl TrustedLen for ops::Range {} +unsafe impl TrustedLen for RangeIter {} #[stable(feature = "fused", since = "1.26.0")] -impl FusedIterator for ops::Range {} +impl FusedIterator for RangeIter {} + +#[stable(feature = "new_range", since = "1.0.0")] +impl IntoIterator for ops::range::Range { + type Item = Idx; + type IntoIter = RangeIter; + + fn into_iter(self) -> Self::IntoIter { + RangeIter { inner: ops::range::legacy::Range { start: self.start, end: self.end } } + } +} + +#[stable(feature = "new_range", since = "1.0.0")] +impl IntoIterator for &ops::range::Range { + type Item = Idx; + type IntoIter = RangeIter; + + fn into_iter(self) -> Self::IntoIter { + (*self).into_iter() + } +} + +#[stable(feature = "new_range", since = "1.0.0")] +impl IntoIterator for &mut ops::range::Range { + type Item = Idx; + type IntoIter = RangeIter; + + fn into_iter(self) -> Self::IntoIter { + (*self).into_iter() + } +} + +impl ops::range::Range { + /// Returns and advances `start` unless the range is empty. + /// + /// This differs from `.into_iter().next()` because + /// that copies the range before advancing the iterator + /// but this modifies the range in place. + #[stable(feature = "new_range", since = "1.0.0")] + #[deprecated(since = "1.0.0", note = "can cause subtle bugs")] + pub fn next(&mut self) -> Option { + let mut iter = self.clone().into_iter(); + let out = iter.next(); + + self.start = iter.inner.start; + self.end = iter.inner.end; + + out + } +} +/// Iterator type for [`ops::range::RangeFrom`] #[stable(feature = "rust1", since = "1.0.0")] -impl Iterator for ops::RangeFrom { +#[derive(Clone, Debug)] +pub struct RangeFromIter { + inner: ops::range::legacy::RangeFrom, +} + +impl RangeFromIter { + #[doc(hidden)] + #[stable(feature = "new_range", since = "1.0.0")] + pub fn inner(&self) -> &ops::range::legacy::RangeFrom { + &self.inner + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Iterator for RangeFromIter { type Item = A; #[inline] fn next(&mut self) -> Option { - let n = Step::forward(self.start.clone(), 1); - Some(mem::replace(&mut self.start, n)) + self.inner.next() } #[inline] fn size_hint(&self) -> (usize, Option) { - (usize::MAX, None) + self.inner.size_hint() } #[inline] fn nth(&mut self, n: usize) -> Option { - let plus_n = Step::forward(self.start.clone(), n); - self.start = Step::forward(plus_n.clone(), 1); - Some(plus_n) + self.inner.nth(n) } } -// Safety: See above implementation for `ops::Range` +// Safety: See above implementation for `ops::range::Range` #[unstable(feature = "trusted_len", issue = "37572")] -unsafe impl TrustedLen for ops::RangeFrom {} +unsafe impl TrustedLen for RangeFromIter {} #[stable(feature = "fused", since = "1.26.0")] -impl FusedIterator for ops::RangeFrom {} +impl FusedIterator for RangeFromIter {} -trait RangeInclusiveIteratorImpl { - type Item; +#[stable(feature = "new_range", since = "1.0.0")] +impl IntoIterator for ops::range::RangeFrom { + type Item = A; + type IntoIter = RangeFromIter; - // Iterator - fn spec_next(&mut self) -> Option; - fn spec_try_fold(&mut self, init: B, f: F) -> R - where - Self: Sized, - F: FnMut(B, Self::Item) -> R, - R: Try; + fn into_iter(self) -> Self::IntoIter { + RangeFromIter { inner: ops::range::legacy::RangeFrom { start: self.start } } + } +} - // DoubleEndedIterator - fn spec_next_back(&mut self) -> Option; - fn spec_try_rfold(&mut self, init: B, f: F) -> R - where - Self: Sized, - F: FnMut(B, Self::Item) -> R, - R: Try; +#[stable(feature = "new_range", since = "1.0.0")] +impl IntoIterator for &ops::range::RangeFrom { + type Item = A; + type IntoIter = RangeFromIter; + + fn into_iter(self) -> Self::IntoIter { + (*self).into_iter() + } +} + +#[stable(feature = "new_range", since = "1.0.0")] +impl IntoIterator for &mut ops::range::RangeFrom { + type Item = A; + type IntoIter = RangeFromIter; + + fn into_iter(self) -> Self::IntoIter { + (*self).into_iter() + } +} + +impl ops::range::RangeFrom { + /// Returns and advances `start` unless the range is empty. + /// + /// This differs from `.into_iter().next()` because + /// that copies the range before advancing the iterator + /// but this modifies the range in place. + #[stable(feature = "new_range", since = "1.0.0")] + #[deprecated(since = "1.0.0", note = "can cause subtle bugs")] + pub fn next(&mut self) -> Option { + let mut iter = self.clone().into_iter(); + let out = iter.next(); + + self.start = iter.inner.start; + + out + } } -impl RangeInclusiveIteratorImpl for ops::RangeInclusive { +/// Iterator type for [`ops::range::RangeInclusive`] +#[stable(feature = "rust1", since = "1.0.0")] +#[derive(Clone, Debug)] +pub struct RangeInclusiveIter { + pub(crate) inner: ops::range::legacy::RangeInclusive, +} + +impl RangeInclusiveIter { + #[doc(hidden)] + #[stable(feature = "new_range", since = "1.0.0")] + pub fn inner(&self) -> &ops::range::legacy::RangeInclusive { + &self.inner + } +} + +#[stable(feature = "inclusive_range", since = "1.26.0")] +impl Iterator for RangeInclusiveIter { type Item = A; #[inline] - default fn spec_next(&mut self) -> Option { - if self.is_empty() { - return None; - } - let is_iterating = self.start < self.end; - Some(if is_iterating { - let n = - Step::forward_checked(self.start.clone(), 1).expect("`Step` invariants not upheld"); - mem::replace(&mut self.start, n) - } else { - self.exhausted = true; - self.start.clone() - }) + fn next(&mut self) -> Option { + self.inner.next() } #[inline] - default fn spec_try_fold(&mut self, init: B, mut f: F) -> R + fn size_hint(&self) -> (usize, Option) { + self.inner.size_hint() + } + + #[inline] + fn count(self) -> usize { + self.inner.count() + } + + #[inline] + fn nth(&mut self, n: usize) -> Option { + self.inner.nth(n) + } + + #[inline] + fn try_fold(&mut self, init: B, f: F) -> R where Self: Sized, - F: FnMut(B, A) -> R, + F: FnMut(B, Self::Item) -> R, R: Try, { - if self.is_empty() { - return try { init }; - } + self.inner.try_fold(init, f) + } - let mut accum = init; + fn fold(self, init: B, f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + self.inner.fold(init, f) + } - while self.start < self.end { - let n = - Step::forward_checked(self.start.clone(), 1).expect("`Step` invariants not upheld"); - let n = mem::replace(&mut self.start, n); - accum = f(accum, n)?; - } + #[inline] + fn last(self) -> Option { + self.inner.last() + } - self.exhausted = true; + #[inline] + fn min(self) -> Option + where + A: Ord, + { + self.inner.min() + } - if self.start == self.end { - accum = f(accum, self.start.clone())?; - } + #[inline] + fn max(self) -> Option + where + A: Ord, + { + self.inner.max() + } - try { accum } + #[inline] + fn is_sorted(self) -> bool { + self.inner.is_sorted() } +} +#[stable(feature = "inclusive_range", since = "1.26.0")] +impl DoubleEndedIterator for RangeInclusiveIter { #[inline] - default fn spec_next_back(&mut self) -> Option { - if self.is_empty() { - return None; - } - let is_iterating = self.start < self.end; - Some(if is_iterating { - let n = - Step::backward_checked(self.end.clone(), 1).expect("`Step` invariants not upheld"); - mem::replace(&mut self.end, n) - } else { - self.exhausted = true; - self.end.clone() - }) + fn next_back(&mut self) -> Option { + self.inner.next_back() } #[inline] - default fn spec_try_rfold(&mut self, init: B, mut f: F) -> R + fn nth_back(&mut self, n: usize) -> Option { + self.inner.nth_back(n) + } + + #[inline] + fn try_rfold(&mut self, init: B, f: F) -> R where Self: Sized, - F: FnMut(B, A) -> R, + F: FnMut(B, Self::Item) -> R, R: Try, { - if self.is_empty() { - return try { init }; - } + self.inner.try_rfold(init, f) + } - let mut accum = init; + fn rfold(self, init: B, f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + self.inner.rfold(init, f) + } +} - while self.start < self.end { - let n = - Step::backward_checked(self.end.clone(), 1).expect("`Step` invariants not upheld"); - let n = mem::replace(&mut self.end, n); - accum = f(accum, n)?; - } +// Safety: See above implementation for `ops::range::Range` +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for RangeInclusiveIter {} - self.exhausted = true; +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for RangeInclusiveIter {} - if self.start == self.end { - accum = f(accum, self.start.clone())?; +#[stable(feature = "new_range", since = "1.0.0")] +impl IntoIterator for ops::range::RangeInclusive { + type Item = A; + type IntoIter = RangeInclusiveIter; + + fn into_iter(self) -> Self::IntoIter { + RangeInclusiveIter { + inner: ops::range::legacy::RangeInclusive { + start: self.start, + end: self.end, + exhausted: false, + }, } + } +} - try { accum } +#[stable(feature = "new_range", since = "1.0.0")] +impl IntoIterator for &ops::range::RangeInclusive { + type Item = A; + type IntoIter = RangeInclusiveIter; + + fn into_iter(self) -> Self::IntoIter { + (*self).into_iter() } } -impl RangeInclusiveIteratorImpl for ops::RangeInclusive { - #[inline] - fn spec_next(&mut self) -> Option { - if self.is_empty() { - return None; - } - let is_iterating = self.start < self.end; - Some(if is_iterating { - // SAFETY: just checked precondition - let n = unsafe { Step::forward_unchecked(self.start.clone(), 1) }; - mem::replace(&mut self.start, n) +#[stable(feature = "new_range", since = "1.0.0")] +impl IntoIterator for &mut ops::range::RangeInclusive { + type Item = A; + type IntoIter = RangeInclusiveIter; + + fn into_iter(self) -> Self::IntoIter { + (*self).into_iter() + } +} + +impl ops::range::RangeInclusive { + /// Returns and advances `start` unless the range is empty. + /// + /// This differs from `.into_iter().next()` because + /// that copies the range before advancing the iterator + /// but this modifies the range in place. + #[stable(feature = "new_range", since = "1.0.0")] + #[deprecated(since = "1.0.0", note = "can cause subtle bugs")] + pub fn next(&mut self) -> Option { + let mut iter = self.clone().into_iter(); + let out = iter.next(); + + if iter.inner.exhausted { + // When exhausted, attempt to put end before start so the range is empty + // If end is the minimum value (`start = end = 0`), set start past end + if let Some(n) = Step::backward_checked(iter.inner.start.clone(), 1) { + self.end = n; + self.start = iter.inner.start; + } else { + self.start = Step::forward(iter.inner.end.clone(), 1); + self.end = iter.inner.end; + } } else { - self.exhausted = true; - self.start.clone() - }) + // Not exhausted, so just set new start and end + self.start = iter.inner.start; + self.end = iter.inner.end; + } + + out } +} - #[inline] - fn spec_try_fold(&mut self, init: B, mut f: F) -> R +macro_rules! iter_methods { + ($($ty:ident),*) => {$( + +impl ops::range::$ty { + /// Shorthand for `.into_iter().size_hint()`. + /// + /// See [`Iterator::size_hint`] + #[stable(feature = "new_range", since = "1.0.0")] + pub fn size_hint(&self) -> (usize, Option) { + self.clone().into_iter().size_hint() + } + + /// Shorthand for `.into_iter().count()`. + /// + /// See [`Iterator::count`] + #[stable(feature = "new_range", since = "1.0.0")] + pub fn count(self) -> usize { + self.into_iter().count() + } + + /// Shorthand for `.into_iter().last()`. + /// + /// See [`Iterator::last`] + #[stable(feature = "new_range", since = "1.0.0")] + pub fn last(self) -> Option { + self.into_iter().last() + } + + /// Shorthand for `.into_iter().step_by(...)`. + /// + /// See [`Iterator::step_by`] + #[stable(feature = "new_range", since = "1.0.0")] + pub fn step_by(self, step: usize) -> crate::iter::StepBy<::IntoIter> { + self.into_iter().step_by(step) + } + + /// Shorthand for `.into_iter().chain(...)` + /// + /// See [`Iterator::chain`] + #[stable(feature = "new_range", since = "1.0.0")] + pub fn chain(self, other: U) -> crate::iter::Chain<::IntoIter, U::IntoIter> where - Self: Sized, - F: FnMut(B, T) -> R, - R: Try, + U: IntoIterator, { - if self.is_empty() { - return try { init }; - } + self.into_iter().chain(other) + } - let mut accum = init; + /// Shorthand for `.into_iter().zip(...)` + /// + /// See [`Iterator::zip`] + #[stable(feature = "new_range", since = "1.0.0")] + pub fn zip(self, other: U) -> crate::iter::Zip<::IntoIter, U::IntoIter> + where + U: IntoIterator, + { + self.into_iter().zip(other) + } - while self.start < self.end { - // SAFETY: just checked precondition - let n = unsafe { Step::forward_unchecked(self.start.clone(), 1) }; - let n = mem::replace(&mut self.start, n); - accum = f(accum, n)?; - } + /// Shorthand for `.into_iter().intersperse(...)` + /// + /// See [`Iterator::intersperse`] + #[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] + pub fn intersperse(self, separator: Idx) -> crate::iter::Intersperse<::IntoIter> + where + Idx: Clone, + { + self.into_iter().intersperse(separator) + } - self.exhausted = true; + /// Shorthand for `.into_iter().intersperse_with(...)` + /// + /// See [`Iterator::intersperse_with`] + #[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] + pub fn intersperse_with(self, separator: G) -> crate::iter::IntersperseWith<::IntoIter, G> + where + G: FnMut() -> Idx, + { + self.into_iter().intersperse_with(separator) + } - if self.start == self.end { - accum = f(accum, self.start.clone())?; - } + /// Shorthand for `.into_iter().map(...)` + /// + /// See [`Iterator::map`] + #[stable(feature = "new_range", since = "1.0.0")] + pub fn map(self, f: F) -> crate::iter::Map<::IntoIter, F> + where + F: FnMut(Idx) -> B, + { + self.into_iter().map(f) + } - try { accum } + /// Shorthand for `.into_iter().for_each(...)` + /// + /// See [`Iterator::for_each`] + #[stable(feature = "new_range", since = "1.0.0")] + pub fn for_each(self, f: F) + where + F: FnMut(Idx), + { + self.into_iter().for_each(f) } - #[inline] - fn spec_next_back(&mut self) -> Option { - if self.is_empty() { - return None; - } - let is_iterating = self.start < self.end; - Some(if is_iterating { - // SAFETY: just checked precondition - let n = unsafe { Step::backward_unchecked(self.end.clone(), 1) }; - mem::replace(&mut self.end, n) - } else { - self.exhausted = true; - self.end.clone() - }) + /// Shorthand for `.into_iter().filter(...)` + /// + /// See [`Iterator::filter`] + #[stable(feature = "new_range", since = "1.0.0")] + pub fn filter

(self, predicate: P) -> crate::iter::Filter<::IntoIter, P> + where P: + FnMut(&Idx) -> bool, + { + self.into_iter().filter(predicate) } - #[inline] - fn spec_try_rfold(&mut self, init: B, mut f: F) -> R + /// Shorthand for `.into_iter().filter_map(...)` + /// + /// See [`Iterator::filter_map`] + #[stable(feature = "new_range", since = "1.0.0")] + pub fn filter_map(self, f: F) -> crate::iter::FilterMap<::IntoIter, F> where - Self: Sized, - F: FnMut(B, T) -> R, - R: Try, + F: FnMut(Idx) -> Option, { - if self.is_empty() { - return try { init }; - } + self.into_iter().filter_map(f) + } - let mut accum = init; + /// Shorthand for `.into_iter().enumerate()` + /// + /// See [`Iterator::enumerate`] + #[stable(feature = "new_range", since = "1.0.0")] + pub fn enumerate(self) -> crate::iter::Enumerate<::IntoIter> { + self.into_iter().enumerate() + } - while self.start < self.end { - // SAFETY: just checked precondition - let n = unsafe { Step::backward_unchecked(self.end.clone(), 1) }; - let n = mem::replace(&mut self.end, n); - accum = f(accum, n)?; - } + /// Shorthand for `.into_iter().peekable()` + /// + /// See [`Iterator::peekable`] + #[stable(feature = "new_range", since = "1.0.0")] + pub fn peekable(self) -> crate::iter::Peekable<::IntoIter> { + self.into_iter().peekable() + } - self.exhausted = true; + /// Shorthand for `.into_iter().filter_map(...)` + /// + /// See [`Iterator::filter_map`] + #[stable(feature = "new_range", since = "1.0.0")] + pub fn skip_while

(self, predicate: P) -> crate::iter::SkipWhile<::IntoIter, P> + where + P: FnMut(&Idx) -> bool, + { + self.into_iter().skip_while(predicate) + } - if self.start == self.end { - accum = f(accum, self.start.clone())?; - } + /// Shorthand for `.into_iter().take_while(...)` + /// + /// See [`Iterator::take_while`] + #[stable(feature = "new_range", since = "1.0.0")] + pub fn take_while

(self, predicate: P) -> Option + where + P: FnMut(&Idx) -> bool, + { + self.into_iter().find(predicate) } - #[inline] - fn min(mut self) -> Option + /// Shorthand for `.into_iter().max()` + /// + /// See [`Iterator::max`] + #[stable(feature = "new_range", since = "1.0.0")] + pub fn max(self) -> Option where - A: Ord, + Idx: Ord, { - self.next() + self.into_iter().max() } - #[inline] - fn max(mut self) -> Option + /// Shorthand for `.into_iter().min()` + /// + /// See [`Iterator::min`] + #[stable(feature = "new_range", since = "1.0.0")] + pub fn min(self) -> Option where - A: Ord, + Idx: Ord, { - self.next_back() + self.into_iter().min() } - #[inline] - fn is_sorted(self) -> bool { - true + /// Shorthand for `.into_iter().max_by_key(...)` + /// + /// See [`Iterator::max_by_key`] + #[stable(feature = "new_range", since = "1.0.0")] + pub fn max_by_key(self, f: F) -> Option + where + F: FnMut(&Idx) -> B, + { + self.into_iter().max_by_key(f) } -} -#[stable(feature = "inclusive_range", since = "1.26.0")] -impl DoubleEndedIterator for ops::RangeInclusive { - #[inline] - fn next_back(&mut self) -> Option { - self.spec_next_back() + /// Shorthand for `.into_iter().max_by(...)` + /// + /// See [`Iterator::max_by`] + #[stable(feature = "new_range", since = "1.0.0")] + pub fn max_by(self, f: F) -> Option + where + F: FnMut(&Idx, &Idx) -> Ordering, + { + self.into_iter().max_by(f) } - #[inline] - fn nth_back(&mut self, n: usize) -> Option { - if self.is_empty() { - return None; - } + /// Shorthand for `.into_iter().min_by_key(...)` + /// + /// See [`Iterator::min_by_key`] + #[stable(feature = "new_range", since = "1.0.0")] + pub fn min_by_key(self, f: F) -> Option + where + F: FnMut(&Idx) -> B, + { + self.into_iter().min_by_key(f) + } - if let Some(minus_n) = Step::backward_checked(self.end.clone(), n) { - use crate::cmp::Ordering::*; + /// Shorthand for `.into_iter().min_by(...)` + /// + /// See [`Iterator::min_by`] + #[stable(feature = "new_range", since = "1.0.0")] + pub fn min_by(self, f: F) -> Option + where + F: FnMut(&Idx, &Idx) -> Ordering, + { + self.into_iter().min_by(f) + } - match minus_n.partial_cmp(&self.start) { - Some(Greater) => { - self.end = Step::backward(minus_n.clone(), 1); - return Some(minus_n); - } - Some(Equal) => { - self.end = minus_n.clone(); - self.exhausted = true; - return Some(minus_n); - } - _ => {} - } - } + /// Shorthand for `.into_iter().rev()` + /// + /// See [`Iterator::rev`] + #[stable(feature = "new_range", since = "1.0.0")] + pub fn rev(self) -> crate::iter::Rev<::IntoIter> + where ::IntoIter: DoubleEndedIterator + { + self.into_iter().rev() + } - self.end = self.start.clone(); - self.exhausted = true; - None + /// Shorthand for `.into_iter().cycle()` + /// + /// See [`Iterator::cycle`] + #[stable(feature = "new_range", since = "1.0.0")] + pub fn cycle(self) -> crate::iter::Cycle<::IntoIter> { + self.into_iter().cycle() } - #[inline] - fn try_rfold(&mut self, init: B, f: F) -> R + /// Shorthand for `.into_iter().array_chunks()` + /// + /// See [`Iterator::array_chunks`] + #[unstable(feature = "iter_array_chunks", reason = "recently added", issue = "100450")] + pub fn array_chunks(self) -> crate::iter::ArrayChunks<::IntoIter, N> { + self.into_iter().array_chunks() + } + + /// Shorthand for `.into_iter().sum()` + /// + /// See [`Iterator::sum`] + #[stable(feature = "new_range", since = "1.0.0")] + pub fn sum(self) -> S where - Self: Sized, - F: FnMut(B, Self::Item) -> R, - R: Try, + S: crate::iter::Sum, + { + self.into_iter().sum() + } + + /// Shorthand for `.into_iter().product()` + /// + /// See [`Iterator::product`] + #[stable(feature = "new_range", since = "1.0.0")] + pub fn product

(self) -> P + where + P: crate::iter::Product, { - self.spec_try_rfold(init, f) + self.into_iter().product() } - impl_fold_via_try_fold! { rfold -> try_rfold } + /// Shorthand for `.into_iter().cmp(...)` + /// + /// See [`Iterator::cmp`] + #[stable(feature = "new_range", since = "1.0.0")] + pub fn cmp(self, other: I) -> Ordering + where + I: IntoIterator, + Idx: Ord, + { + self.into_iter().cmp(other) + } + + /// Shorthand for `.into_iter().cmp_by(...)` + /// + /// See [`Iterator::cmp_by`] + #[stable(feature = "new_range", since = "1.0.0")] + pub fn cmp_by(self, other: I, cmp: F) -> Ordering + where + I: IntoIterator, + F: FnMut(Idx, I::Item) -> Ordering, + { + self.into_iter().cmp_by(other, cmp) + } + + /// Shorthand for `.into_iter().partial_cmp(...)` + /// + /// See [`Iterator::partial_cmp`] + #[stable(feature = "new_range", since = "1.0.0")] + pub fn partial_cmp(self, other: I) -> Option + where + I: IntoIterator, + Idx: Ord, + { + self.into_iter().partial_cmp(other) + } + + /// Shorthand for `.into_iter().partial_cmp_by(...)` + /// + /// See [`Iterator::partial_cmp_by`] + #[stable(feature = "new_range", since = "1.0.0")] + pub fn partial_cmp_by(self, other: I, partial_cmp: F) -> Option + where + I: IntoIterator, + F: FnMut(Idx, I::Item) -> Option, + { + self.into_iter().partial_cmp_by(other, partial_cmp) + } + + /// Shorthand for `.into_iter().eq(...)` + /// + /// See [`Iterator::eq`] + #[stable(feature = "new_range", since = "1.0.0")] + pub fn eq(self, other: I) -> bool + where + I: IntoIterator, + Idx: PartialEq, + { + self.into_iter().eq(other) + } + + /// Shorthand for `.into_iter().eq_by(...)` + /// + /// See [`Iterator::eq_by`] + #[stable(feature = "new_range", since = "1.0.0")] + pub fn eq_by(self, other: I, eq: F) -> bool + where + I: IntoIterator, + F: FnMut(Idx, I::Item) -> bool, + { + self.into_iter().eq_by(other, eq) + } + + /// Shorthand for `.into_iter().ne(...)` + /// + /// See [`Iterator::ne`] + #[stable(feature = "new_range", since = "1.0.0")] + pub fn ne(self, other: I) -> bool + where + I: IntoIterator, + Idx: PartialEq, + { + self.into_iter().ne(other) + } + + /// Shorthand for `.into_iter().lt(...)` + /// + /// See [`Iterator::lt`] + #[stable(feature = "new_range", since = "1.0.0")] + pub fn lt(self, other: I) -> bool + where + I: IntoIterator, + Idx: PartialOrd, + { + self.into_iter().lt(other) + } + + /// Shorthand for `.into_iter().le(...)` + /// + /// See [`Iterator::le`] + #[stable(feature = "new_range", since = "1.0.0")] + pub fn le(self, other: I) -> bool + where + I: IntoIterator, + Idx: PartialOrd, + { + self.into_iter().le(other) + } + + /// Shorthand for `.into_iter().gt(...)` + /// + /// See [`Iterator::gt`] + #[stable(feature = "new_range", since = "1.0.0")] + pub fn gt(self, other: I) -> bool + where + I: IntoIterator, + Idx: PartialOrd, + { + self.into_iter().gt(other) + } + + /// Shorthand for `.into_iter().ge(...)` + /// + /// See [`Iterator::ge`] + #[stable(feature = "new_range", since = "1.0.0")] + pub fn ge(self, other: I) -> bool + where + I: IntoIterator, + Idx: PartialOrd, + { + self.into_iter().ge(other) + } + + /// Shorthand for `.into_iter().is_sorted()` + /// + /// See [`Iterator::ge`] + #[unstable(feature = "is_sorted", reason = "new API", issue = "53485")] + pub fn is_sorted(self) -> bool + where + Idx: PartialOrd, + { + self.into_iter().is_sorted() + } + + /// Returns the length of the `Range`. + #[stable(feature = "new_range", since = "1.0.0")] + pub fn len(&self) -> usize + where ::IntoIter: ExactSizeIterator + { + ExactSizeIterator::len(&self.clone().into_iter()) + } } -// Safety: See above implementation for `ops::Range` -#[unstable(feature = "trusted_len", issue = "37572")] -unsafe impl TrustedLen for ops::RangeInclusive {} + )*} +} -#[stable(feature = "fused", since = "1.26.0")] -impl FusedIterator for ops::RangeInclusive {} +iter_methods!(Range, RangeFrom, RangeInclusive); diff --git a/library/core/src/iter/range/legacy.rs b/library/core/src/iter/range/legacy.rs new file mode 100644 index 0000000000000..dc09f0ad7b512 --- /dev/null +++ b/library/core/src/iter/range/legacy.rs @@ -0,0 +1,784 @@ +use crate::mem; +use crate::num::NonZeroUsize; +use crate::ops::{self, Try}; + +use super::{ + FusedIterator, Step, TrustedLen, TrustedRandomAccess, TrustedRandomAccessNoCoerce, TrustedStep, +}; + +macro_rules! range_exact_iter_impl { + ($($t:ty)*) => ($( + #[stable(feature = "rust1", since = "1.0.0")] + impl ExactSizeIterator for ops::range::legacy::Range<$t> { } + )*) +} + +/// Safety: This macro must only be used on types that are `Copy` and result in ranges +/// which have an exact `size_hint()` where the upper bound must not be `None`. +macro_rules! unsafe_range_trusted_random_access_impl { + ($($t:ty)*) => ($( + #[doc(hidden)] + #[unstable(feature = "trusted_random_access", issue = "none")] + unsafe impl TrustedRandomAccess for ops::range::legacy::Range<$t> {} + + #[doc(hidden)] + #[unstable(feature = "trusted_random_access", issue = "none")] + unsafe impl TrustedRandomAccessNoCoerce for ops::range::legacy::Range<$t> { + const MAY_HAVE_SIDE_EFFECT: bool = false; + } + )*) +} + +macro_rules! range_incl_exact_iter_impl { + ($($t:ty)*) => ($( + #[stable(feature = "inclusive_range", since = "1.26.0")] + impl ExactSizeIterator for ops::range::legacy::RangeInclusive<$t> { } + )*) +} + +/// Specialization implementations for `Range`. +trait RangeIteratorImpl { + type Item; + + // Iterator + fn spec_next(&mut self) -> Option; + fn spec_nth(&mut self, n: usize) -> Option; + fn spec_advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize>; + + // DoubleEndedIterator + fn spec_next_back(&mut self) -> Option; + fn spec_nth_back(&mut self, n: usize) -> Option; + fn spec_advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize>; +} + +impl RangeIteratorImpl for ops::range::legacy::Range { + type Item = A; + + #[inline] + default fn spec_next(&mut self) -> Option { + if self.start < self.end { + let n = + Step::forward_checked(self.start.clone(), 1).expect("`Step` invariants not upheld"); + Some(mem::replace(&mut self.start, n)) + } else { + None + } + } + + #[inline] + default fn spec_nth(&mut self, n: usize) -> Option { + if let Some(plus_n) = Step::forward_checked(self.start.clone(), n) { + if plus_n < self.end { + self.start = + Step::forward_checked(plus_n.clone(), 1).expect("`Step` invariants not upheld"); + return Some(plus_n); + } + } + + self.start = self.end.clone(); + None + } + + #[inline] + default fn spec_advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { + let available = if self.start <= self.end { + Step::steps_between(&self.start, &self.end).unwrap_or(usize::MAX) + } else { + 0 + }; + + let taken = available.min(n); + + self.start = + Step::forward_checked(self.start.clone(), taken).expect("`Step` invariants not upheld"); + + NonZeroUsize::new(n - taken).map_or(Ok(()), Err) + } + + #[inline] + default fn spec_next_back(&mut self) -> Option { + if self.start < self.end { + self.end = + Step::backward_checked(self.end.clone(), 1).expect("`Step` invariants not upheld"); + Some(self.end.clone()) + } else { + None + } + } + + #[inline] + default fn spec_nth_back(&mut self, n: usize) -> Option { + if let Some(minus_n) = Step::backward_checked(self.end.clone(), n) { + if minus_n > self.start { + self.end = + Step::backward_checked(minus_n, 1).expect("`Step` invariants not upheld"); + return Some(self.end.clone()); + } + } + + self.end = self.start.clone(); + None + } + + #[inline] + default fn spec_advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { + let available = if self.start <= self.end { + Step::steps_between(&self.start, &self.end).unwrap_or(usize::MAX) + } else { + 0 + }; + + let taken = available.min(n); + + self.end = + Step::backward_checked(self.end.clone(), taken).expect("`Step` invariants not upheld"); + + NonZeroUsize::new(n - taken).map_or(Ok(()), Err) + } +} + +impl RangeIteratorImpl for ops::range::legacy::Range { + #[inline] + fn spec_next(&mut self) -> Option { + if self.start < self.end { + let old = self.start; + // SAFETY: just checked precondition + self.start = unsafe { Step::forward_unchecked(old, 1) }; + Some(old) + } else { + None + } + } + + #[inline] + fn spec_nth(&mut self, n: usize) -> Option { + if let Some(plus_n) = Step::forward_checked(self.start, n) { + if plus_n < self.end { + // SAFETY: just checked precondition + self.start = unsafe { Step::forward_unchecked(plus_n, 1) }; + return Some(plus_n); + } + } + + self.start = self.end; + None + } + + #[inline] + fn spec_advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { + let available = if self.start <= self.end { + Step::steps_between(&self.start, &self.end).unwrap_or(usize::MAX) + } else { + 0 + }; + + let taken = available.min(n); + + // SAFETY: the conditions above ensure that the count is in bounds. If start <= end + // then steps_between either returns a bound to which we clamp or returns None which + // together with the initial inequality implies more than usize::MAX steps. + // Otherwise 0 is returned which always safe to use. + self.start = unsafe { Step::forward_unchecked(self.start, taken) }; + + NonZeroUsize::new(n - taken).map_or(Ok(()), Err) + } + + #[inline] + fn spec_next_back(&mut self) -> Option { + if self.start < self.end { + // SAFETY: just checked precondition + self.end = unsafe { Step::backward_unchecked(self.end, 1) }; + Some(self.end) + } else { + None + } + } + + #[inline] + fn spec_nth_back(&mut self, n: usize) -> Option { + if let Some(minus_n) = Step::backward_checked(self.end, n) { + if minus_n > self.start { + // SAFETY: just checked precondition + self.end = unsafe { Step::backward_unchecked(minus_n, 1) }; + return Some(self.end); + } + } + + self.end = self.start; + None + } + + #[inline] + fn spec_advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { + let available = if self.start <= self.end { + Step::steps_between(&self.start, &self.end).unwrap_or(usize::MAX) + } else { + 0 + }; + + let taken = available.min(n); + + // SAFETY: same as the spec_advance_by() implementation + self.end = unsafe { Step::backward_unchecked(self.end, taken) }; + + NonZeroUsize::new(n - taken).map_or(Ok(()), Err) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Iterator for ops::range::legacy::Range { + type Item = A; + + #[inline] + fn next(&mut self) -> Option { + self.spec_next() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + if self.start < self.end { + let hint = Step::steps_between(&self.start, &self.end); + (hint.unwrap_or(usize::MAX), hint) + } else { + (0, Some(0)) + } + } + + #[inline] + fn count(self) -> usize { + if self.start < self.end { + Step::steps_between(&self.start, &self.end).expect("count overflowed usize") + } else { + 0 + } + } + + #[inline] + fn nth(&mut self, n: usize) -> Option { + self.spec_nth(n) + } + + #[inline] + fn last(mut self) -> Option { + self.next_back() + } + + #[inline] + fn min(mut self) -> Option + where + A: Ord, + { + self.next() + } + + #[inline] + fn max(mut self) -> Option + where + A: Ord, + { + self.next_back() + } + + #[inline] + fn is_sorted(self) -> bool { + true + } + + #[inline] + fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { + self.spec_advance_by(n) + } + + #[inline] + unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item + where + Self: TrustedRandomAccessNoCoerce, + { + // SAFETY: The TrustedRandomAccess contract requires that callers only pass an index + // that is in bounds. + // Additionally Self: TrustedRandomAccess is only implemented for Copy types + // which means even repeated reads of the same index would be safe. + unsafe { Step::forward_unchecked(self.start.clone(), idx) } + } +} + +// These macros generate `ExactSizeIterator` impls for various range types. +// +// * `ExactSizeIterator::len` is required to always return an exact `usize`, +// so no range can be longer than `usize::MAX`. +// * For integer types in `Range<_>` this is the case for types narrower than or as wide as `usize`. +// For integer types in `RangeInclusive<_>` +// this is the case for types *strictly narrower* than `usize` +// since e.g. `(0..=u64::MAX).len()` would be `u64::MAX + 1`. +range_exact_iter_impl! { + usize u8 u16 + isize i8 i16 + + // These are incorrect per the reasoning above, + // but removing them would be a breaking change as they were stabilized in Rust 1.0.0. + // So e.g. `(0..66_000_u32).len()` for example will compile without error or warnings + // on 16-bit platforms, but continue to give a wrong result. + u32 + i32 +} + +unsafe_range_trusted_random_access_impl! { + usize u8 u16 + isize i8 i16 +} + +#[cfg(target_pointer_width = "32")] +unsafe_range_trusted_random_access_impl! { + u32 i32 +} + +#[cfg(target_pointer_width = "64")] +unsafe_range_trusted_random_access_impl! { + u32 i32 + u64 i64 +} + +range_incl_exact_iter_impl! { + u8 + i8 + + // These are incorrect per the reasoning above, + // but removing them would be a breaking change as they were stabilized in Rust 1.26.0. + // So e.g. `(0..=u16::MAX).len()` for example will compile without error or warnings + // on 16-bit platforms, but continue to give a wrong result. + u16 + i16 +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl DoubleEndedIterator for ops::range::legacy::Range { + #[inline] + fn next_back(&mut self) -> Option { + self.spec_next_back() + } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option { + self.spec_nth_back(n) + } + + #[inline] + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { + self.spec_advance_back_by(n) + } +} + +// Safety: +// The following invariants for `Step::steps_between` exist: +// +// > * `steps_between(&a, &b) == Some(n)` only if `a <= b` +// > * Note that `a <= b` does _not_ imply `steps_between(&a, &b) != None`; +// > this is the case when it would require more than `usize::MAX` steps to +// > get to `b` +// > * `steps_between(&a, &b) == None` if `a > b` +// +// The first invariant is what is generally required for `TrustedLen` to be +// sound. The note addendum satisfies an additional `TrustedLen` invariant. +// +// > The upper bound must only be `None` if the actual iterator length is larger +// > than `usize::MAX` +// +// The second invariant logically follows the first so long as the `PartialOrd` +// implementation is correct; regardless it is explicitly stated. If `a < b` +// then `(0, Some(0))` is returned by `ops::range::legacy::Range::size_hint`. As such +// the second invariant is upheld. +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for ops::range::legacy::Range {} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for ops::range::legacy::Range {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Iterator for ops::range::legacy::RangeFrom { + type Item = A; + + #[inline] + fn next(&mut self) -> Option { + let n = Step::forward(self.start.clone(), 1); + Some(mem::replace(&mut self.start, n)) + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + (usize::MAX, None) + } + + #[inline] + fn nth(&mut self, n: usize) -> Option { + let plus_n = Step::forward(self.start.clone(), n); + self.start = Step::forward(plus_n.clone(), 1); + Some(plus_n) + } +} + +// Safety: See above implementation for `ops::range::legacy::Range` +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for ops::range::legacy::RangeFrom {} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for ops::range::legacy::RangeFrom {} + +trait RangeInclusiveIteratorImpl { + type Item; + + // Iterator + fn spec_next(&mut self) -> Option; + fn spec_try_fold(&mut self, init: B, f: F) -> R + where + Self: Sized, + F: FnMut(B, Self::Item) -> R, + R: Try; + + // DoubleEndedIterator + fn spec_next_back(&mut self) -> Option; + fn spec_try_rfold(&mut self, init: B, f: F) -> R + where + Self: Sized, + F: FnMut(B, Self::Item) -> R, + R: Try; +} + +impl RangeInclusiveIteratorImpl for ops::range::legacy::RangeInclusive { + type Item = A; + + #[inline] + default fn spec_next(&mut self) -> Option { + if self.is_empty() { + return None; + } + let is_iterating = self.start < self.end; + Some(if is_iterating { + let n = + Step::forward_checked(self.start.clone(), 1).expect("`Step` invariants not upheld"); + mem::replace(&mut self.start, n) + } else { + self.exhausted = true; + self.start.clone() + }) + } + + #[inline] + default fn spec_try_fold(&mut self, init: B, mut f: F) -> R + where + Self: Sized, + F: FnMut(B, A) -> R, + R: Try, + { + if self.is_empty() { + return try { init }; + } + + let mut accum = init; + + while self.start < self.end { + let n = + Step::forward_checked(self.start.clone(), 1).expect("`Step` invariants not upheld"); + let n = mem::replace(&mut self.start, n); + accum = f(accum, n)?; + } + + self.exhausted = true; + + if self.start == self.end { + accum = f(accum, self.start.clone())?; + } + + try { accum } + } + + #[inline] + default fn spec_next_back(&mut self) -> Option { + if self.is_empty() { + return None; + } + let is_iterating = self.start < self.end; + Some(if is_iterating { + let n = + Step::backward_checked(self.end.clone(), 1).expect("`Step` invariants not upheld"); + mem::replace(&mut self.end, n) + } else { + self.exhausted = true; + self.end.clone() + }) + } + + #[inline] + default fn spec_try_rfold(&mut self, init: B, mut f: F) -> R + where + Self: Sized, + F: FnMut(B, A) -> R, + R: Try, + { + if self.is_empty() { + return try { init }; + } + + let mut accum = init; + + while self.start < self.end { + let n = + Step::backward_checked(self.end.clone(), 1).expect("`Step` invariants not upheld"); + let n = mem::replace(&mut self.end, n); + accum = f(accum, n)?; + } + + self.exhausted = true; + + if self.start == self.end { + accum = f(accum, self.start.clone())?; + } + + try { accum } + } +} + +impl RangeInclusiveIteratorImpl for ops::range::legacy::RangeInclusive { + #[inline] + fn spec_next(&mut self) -> Option { + if self.is_empty() { + return None; + } + let is_iterating = self.start < self.end; + Some(if is_iterating { + // SAFETY: just checked precondition + let n = unsafe { Step::forward_unchecked(self.start.clone(), 1) }; + mem::replace(&mut self.start, n) + } else { + self.exhausted = true; + self.start.clone() + }) + } + + #[inline] + fn spec_try_fold(&mut self, init: B, mut f: F) -> R + where + Self: Sized, + F: FnMut(B, T) -> R, + R: Try, + { + if self.is_empty() { + return try { init }; + } + + let mut accum = init; + + while self.start < self.end { + // SAFETY: just checked precondition + let n = unsafe { Step::forward_unchecked(self.start.clone(), 1) }; + let n = mem::replace(&mut self.start, n); + accum = f(accum, n)?; + } + + self.exhausted = true; + + if self.start == self.end { + accum = f(accum, self.start.clone())?; + } + + try { accum } + } + + #[inline] + fn spec_next_back(&mut self) -> Option { + if self.is_empty() { + return None; + } + let is_iterating = self.start < self.end; + Some(if is_iterating { + // SAFETY: just checked precondition + let n = unsafe { Step::backward_unchecked(self.end.clone(), 1) }; + mem::replace(&mut self.end, n) + } else { + self.exhausted = true; + self.end.clone() + }) + } + + #[inline] + fn spec_try_rfold(&mut self, init: B, mut f: F) -> R + where + Self: Sized, + F: FnMut(B, T) -> R, + R: Try, + { + if self.is_empty() { + return try { init }; + } + + let mut accum = init; + + while self.start < self.end { + // SAFETY: just checked precondition + let n = unsafe { Step::backward_unchecked(self.end.clone(), 1) }; + let n = mem::replace(&mut self.end, n); + accum = f(accum, n)?; + } + + self.exhausted = true; + + if self.start == self.end { + accum = f(accum, self.start.clone())?; + } + + try { accum } + } +} + +#[stable(feature = "inclusive_range", since = "1.26.0")] +impl Iterator for ops::range::legacy::RangeInclusive { + type Item = A; + + #[inline] + fn next(&mut self) -> Option { + self.spec_next() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + if self.is_empty() { + return (0, Some(0)); + } + + match Step::steps_between(&self.start, &self.end) { + Some(hint) => (hint.saturating_add(1), hint.checked_add(1)), + None => (usize::MAX, None), + } + } + + #[inline] + fn count(self) -> usize { + if self.is_empty() { + return 0; + } + + Step::steps_between(&self.start, &self.end) + .and_then(|steps| steps.checked_add(1)) + .expect("count overflowed usize") + } + + #[inline] + fn nth(&mut self, n: usize) -> Option { + if self.is_empty() { + return None; + } + + if let Some(plus_n) = Step::forward_checked(self.start.clone(), n) { + use crate::cmp::Ordering::*; + + match plus_n.partial_cmp(&self.end) { + Some(Less) => { + self.start = Step::forward(plus_n.clone(), 1); + return Some(plus_n); + } + Some(Equal) => { + self.start = plus_n.clone(); + self.exhausted = true; + return Some(plus_n); + } + _ => {} + } + } + + self.start = self.end.clone(); + self.exhausted = true; + None + } + + #[inline] + fn try_fold(&mut self, init: B, f: F) -> R + where + Self: Sized, + F: FnMut(B, Self::Item) -> R, + R: Try, + { + self.spec_try_fold(init, f) + } + + impl_fold_via_try_fold! { fold -> try_fold } + + #[inline] + fn last(mut self) -> Option { + self.next_back() + } + + #[inline] + fn min(mut self) -> Option + where + A: Ord, + { + self.next() + } + + #[inline] + fn max(mut self) -> Option + where + A: Ord, + { + self.next_back() + } + + #[inline] + fn is_sorted(self) -> bool { + true + } +} + +#[stable(feature = "inclusive_range", since = "1.26.0")] +impl DoubleEndedIterator for ops::range::legacy::RangeInclusive { + #[inline] + fn next_back(&mut self) -> Option { + self.spec_next_back() + } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option { + if self.is_empty() { + return None; + } + + if let Some(minus_n) = Step::backward_checked(self.end.clone(), n) { + use crate::cmp::Ordering::*; + + match minus_n.partial_cmp(&self.start) { + Some(Greater) => { + self.end = Step::backward(minus_n.clone(), 1); + return Some(minus_n); + } + Some(Equal) => { + self.end = minus_n.clone(); + self.exhausted = true; + return Some(minus_n); + } + _ => {} + } + } + + self.end = self.start.clone(); + self.exhausted = true; + None + } + + #[inline] + fn try_rfold(&mut self, init: B, f: F) -> R + where + Self: Sized, + F: FnMut(B, Self::Item) -> R, + R: Try, + { + self.spec_try_rfold(init, f) + } + + impl_fold_via_try_fold! { rfold -> try_rfold } +} + +// Safety: See above implementation for `ops::range::legacy::Range` +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for ops::range::legacy::RangeInclusive {} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for ops::range::legacy::RangeInclusive {} diff --git a/library/core/src/iter/traits/exact_size.rs b/library/core/src/iter/traits/exact_size.rs index 908830d8a9514..edef3f9c61c4e 100644 --- a/library/core/src/iter/traits/exact_size.rs +++ b/library/core/src/iter/traits/exact_size.rs @@ -105,7 +105,7 @@ pub trait ExactSizeIterator: Iterator { /// /// ``` /// // a finite range knows exactly how many times it will iterate - /// let mut range = 0..5; + /// let mut range = (0..5).into_iter(); /// /// assert_eq!(5, range.len()); /// let _ = range.next(); diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 8e2c887a161e0..b473e61f79e4d 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -216,7 +216,7 @@ pub trait Iterator { /// ``` /// // an infinite iterator has no upper bound /// // and the maximum possible lower bound - /// let iter = 0..; + /// let iter = (0..).into_iter(); /// /// assert_eq!((usize::MAX, None), iter.size_hint()); /// ``` @@ -2430,7 +2430,7 @@ pub trait Iterator { /// ``` /// use std::ops::ControlFlow; /// - /// let triangular = (1..30).try_fold(0_i8, |prev, x| { + /// let triangular = (1..30).into_iter().try_fold(0_i8, |prev, x| { /// if let Some(next) = prev.checked_add(x) { /// ControlFlow::Continue(next) /// } else { @@ -2439,7 +2439,7 @@ pub trait Iterator { /// }); /// assert_eq!(triangular, ControlFlow::Break(120)); /// - /// let triangular = (1..30).try_fold(0_u64, |prev, x| { + /// let triangular = (1..30).into_iter().try_fold(0_u64, |prev, x| { /// if let Some(next) = prev.checked_add(x) { /// ControlFlow::Continue(next) /// } else { @@ -2498,7 +2498,7 @@ pub trait Iterator { /// ``` /// use std::ops::ControlFlow; /// - /// let r = (2..100).try_for_each(|x| { + /// let r = (2..100).into_iter().try_for_each(|x| { /// if 323 % x == 0 { /// return ControlFlow::Break(x) /// } diff --git a/library/core/src/ops/control_flow.rs b/library/core/src/ops/control_flow.rs index e10c438ef4300..8f100c1c3abe7 100644 --- a/library/core/src/ops/control_flow.rs +++ b/library/core/src/ops/control_flow.rs @@ -17,7 +17,7 @@ use crate::{convert, ops}; /// ``` /// use std::ops::ControlFlow; /// -/// let r = (2..100).try_for_each(|x| { +/// let r = (2..100).into_iter().try_for_each(|x| { /// if 403 % x == 0 { /// return ControlFlow::Break(x) /// } diff --git a/library/core/src/ops/mod.rs b/library/core/src/ops/mod.rs index 35654d0b853b7..5689d05273805 100644 --- a/library/core/src/ops/mod.rs +++ b/library/core/src/ops/mod.rs @@ -147,7 +147,8 @@ mod drop; mod function; mod index; mod index_range; -mod range; +#[stable(feature = "new_range", since = "1.0.0")] +pub mod range; mod try_trait; mod unsize; @@ -182,10 +183,13 @@ pub use self::range::{Range, RangeFrom, RangeFull, RangeTo}; pub(crate) use self::index_range::IndexRange; #[stable(feature = "inclusive_range", since = "1.26.0")] -pub use self::range::{Bound, RangeBounds, RangeInclusive, RangeToInclusive}; +pub use self::range::{RangeInclusive, RangeToInclusive}; + +#[stable(feature = "inclusive_range", since = "1.26.0")] +pub use self::range::bounds::{Bound, RangeBounds}; #[unstable(feature = "one_sided_range", issue = "69780")] -pub use self::range::OneSidedRange; +pub use self::range::bounds::OneSidedRange; #[unstable(feature = "try_trait_v2", issue = "84277")] pub use self::try_trait::{FromResidual, Try}; diff --git a/library/core/src/ops/range.rs b/library/core/src/ops/range.rs index b419a738fbe3a..85b0d9e09f86d 100644 --- a/library/core/src/ops/range.rs +++ b/library/core/src/ops/range.rs @@ -1,6 +1,13 @@ +//! Range types that `..` resolves to after edition 2024. + use crate::fmt; use crate::hash::Hash; +#[stable(feature = "new_range", since = "1.0.0")] +pub mod legacy; + +use self::bounds::RangeBounds; + /// An unbounded range (`..`). /// /// `RangeFull` is primarily used as a [slicing index], its shorthand is `..`. @@ -75,7 +82,7 @@ impl fmt::Debug for RangeFull { /// ``` #[lang = "Range"] #[doc(alias = "..")] -#[derive(Clone, Default, PartialEq, Eq, Hash)] // not Copy -- see #27186 +#[derive(Copy, Clone, Default, PartialEq, Eq, Hash)] #[stable(feature = "rust1", since = "1.0.0")] pub struct Range { /// The lower bound of the range (inclusive). @@ -86,6 +93,32 @@ pub struct Range { pub end: Idx, } +#[stable(feature = "new_range", since = "1.0.0")] +impl From> for Range { + fn from(value: legacy::Range) -> Self { + Range { start: value.start, end: value.end } + } +} +#[stable(feature = "new_range", since = "1.0.0")] +impl From> for legacy::Range { + fn from(value: Range) -> Self { + legacy::Range { start: value.start, end: value.end } + } +} + +#[stable(feature = "new_range", since = "1.0.0")] +impl PartialEq> for Range { + fn eq(&self, other: &legacy::Range) -> bool { + other.start == self.start && other.end == self.end + } +} +#[stable(feature = "new_range", since = "1.0.0")] +impl PartialEq> for legacy::Range { + fn eq(&self, other: &Range) -> bool { + other.start == self.start && other.end == self.end + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Debug for Range { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -184,7 +217,7 @@ impl> Range { /// ``` #[lang = "RangeFrom"] #[doc(alias = "..")] -#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186 +#[derive(Copy, Clone, PartialEq, Eq, Hash)] #[stable(feature = "rust1", since = "1.0.0")] pub struct RangeFrom { /// The lower bound of the range (inclusive). @@ -192,6 +225,32 @@ pub struct RangeFrom { pub start: Idx, } +#[stable(feature = "new_range", since = "1.0.0")] +impl From> for RangeFrom { + fn from(value: legacy::RangeFrom) -> Self { + RangeFrom { start: value.start } + } +} +#[stable(feature = "new_range", since = "1.0.0")] +impl From> for legacy::RangeFrom { + fn from(value: RangeFrom) -> Self { + legacy::RangeFrom { start: value.start } + } +} + +#[stable(feature = "new_range", since = "1.0.0")] +impl PartialEq> for RangeFrom { + fn eq(&self, other: &legacy::RangeFrom) -> bool { + other.start == self.start + } +} +#[stable(feature = "new_range", since = "1.0.0")] +impl PartialEq> for legacy::RangeFrom { + fn eq(&self, other: &RangeFrom) -> bool { + other.start == self.start + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Debug for RangeFrom { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -340,107 +399,68 @@ impl> RangeTo { /// ``` #[lang = "RangeInclusive"] #[doc(alias = "..=")] -#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186 +#[derive(Copy, Clone, PartialEq, Eq, Hash)] #[stable(feature = "inclusive_range", since = "1.26.0")] pub struct RangeInclusive { - // Note that the fields here are not public to allow changing the - // representation in the future; in particular, while we could plausibly - // expose start/end, modifying them without changing (future/current) - // private fields may lead to incorrect behavior, so we don't want to - // support that mode. + /// The lower bound of the range (inclusive). + #[stable(feature = "new_range", since = "1.0.0")] pub(crate) start: Idx, + /// The upper bound of the range (inclusive). + #[stable(feature = "new_range", since = "1.0.0")] pub(crate) end: Idx, +} + +// FIXME: how to implement this soundly? +// impl From> for RangeInclusive - // This field is: - // - `false` upon construction - // - `false` when iteration has yielded an element and the iterator is not exhausted - // - `true` when iteration has been used to exhaust the iterator - // - // This is required to support PartialEq and Hash without a PartialOrd bound or specialization. - pub(crate) exhausted: bool, +#[stable(feature = "new_range", since = "1.0.0")] +impl From> for legacy::RangeInclusive { + fn from(value: RangeInclusive) -> Self { + legacy::RangeInclusive::new(value.start, value.end) + } +} + +#[stable(feature = "new_range", since = "1.0.0")] +impl PartialEq> for RangeInclusive { + fn eq(&self, other: &legacy::RangeInclusive) -> bool { + !other.exhausted && other.start == self.start && other.end == self.end + } +} +#[stable(feature = "new_range", since = "1.0.0")] +impl PartialEq> for legacy::RangeInclusive { + fn eq(&self, other: &RangeInclusive) -> bool { + !self.exhausted && other.start == self.start && other.end == self.end + } } impl RangeInclusive { - /// Creates a new inclusive range. Equivalent to writing `start..=end`. - /// - /// # Examples - /// - /// ``` - /// use std::ops::RangeInclusive; - /// - /// assert_eq!(3..=5, RangeInclusive::new(3, 5)); - /// ``` + #[doc(hidden)] #[lang = "range_inclusive_new"] - #[stable(feature = "inclusive_range_methods", since = "1.27.0")] + #[stable(feature = "new_range", since = "1.0.0")] #[inline] #[rustc_promotable] - #[rustc_const_stable(feature = "const_range_new", since = "1.32.0")] + #[rustc_const_stable(feature = "new_range", since = "1.0.0")] pub const fn new(start: Idx, end: Idx) -> Self { - Self { start, end, exhausted: false } + Self { start, end } } - /// Returns the lower bound of the range (inclusive). - /// - /// When using an inclusive range for iteration, the values of `start()` and - /// [`end()`] are unspecified after the iteration ended. To determine - /// whether the inclusive range is empty, use the [`is_empty()`] method - /// instead of comparing `start() > end()`. - /// - /// Note: the value returned by this method is unspecified after the range - /// has been iterated to exhaustion. - /// - /// [`end()`]: RangeInclusive::end - /// [`is_empty()`]: RangeInclusive::is_empty - /// - /// # Examples - /// - /// ``` - /// assert_eq!((3..=5).start(), &3); - /// ``` - #[stable(feature = "inclusive_range_methods", since = "1.27.0")] - #[rustc_const_stable(feature = "const_inclusive_range_methods", since = "1.32.0")] + #[doc(hidden)] + #[stable(feature = "new_range", since = "1.0.0")] + #[rustc_const_stable(feature = "new_range", since = "1.0.0")] #[inline] pub const fn start(&self) -> &Idx { &self.start } - /// Returns the upper bound of the range (inclusive). - /// - /// When using an inclusive range for iteration, the values of [`start()`] - /// and `end()` are unspecified after the iteration ended. To determine - /// whether the inclusive range is empty, use the [`is_empty()`] method - /// instead of comparing `start() > end()`. - /// - /// Note: the value returned by this method is unspecified after the range - /// has been iterated to exhaustion. - /// - /// [`start()`]: RangeInclusive::start - /// [`is_empty()`]: RangeInclusive::is_empty - /// - /// # Examples - /// - /// ``` - /// assert_eq!((3..=5).end(), &5); - /// ``` - #[stable(feature = "inclusive_range_methods", since = "1.27.0")] - #[rustc_const_stable(feature = "const_inclusive_range_methods", since = "1.32.0")] - #[inline] + #[doc(hidden)] + #[stable(feature = "new_range", since = "1.0.0")] + #[rustc_const_stable(feature = "new_range", since = "1.0.0")] pub const fn end(&self) -> &Idx { &self.end } - /// Destructures the `RangeInclusive` into (lower bound, upper (inclusive) bound). - /// - /// Note: the value returned by this method is unspecified after the range - /// has been iterated to exhaustion. - /// - /// # Examples - /// - /// ``` - /// assert_eq!((3..=5).into_inner(), (3, 5)); - /// ``` - #[stable(feature = "inclusive_range_methods", since = "1.27.0")] - #[inline] + #[doc(hidden)] + #[stable(feature = "new_range", since = "1.0.0")] #[rustc_const_unstable(feature = "const_range_bounds", issue = "108082")] pub const fn into_inner(self) -> (Idx, Idx) { (self.start, self.end) @@ -456,7 +476,7 @@ impl RangeInclusive { // If we are exhausted, then slicing with `end + 1..end + 1` gives us an // empty range that is still subject to bounds-checks for that endpoint. let exclusive_end = self.end + 1; - let start = if self.exhausted { exclusive_end } else { self.start }; + let start = self.start; start..exclusive_end } } @@ -467,9 +487,6 @@ impl fmt::Debug for RangeInclusive { self.start.fmt(fmt)?; write!(fmt, "..=")?; self.end.fmt(fmt)?; - if self.exhausted { - write!(fmt, " (exhausted)")?; - } Ok(()) } } @@ -494,16 +511,6 @@ impl> RangeInclusive { /// assert!(!(0.0..=f32::NAN).contains(&0.0)); /// assert!(!(f32::NAN..=1.0).contains(&1.0)); /// ``` - /// - /// This method always returns `false` after iteration has finished: - /// - /// ``` - /// let mut r = 3..=5; - /// assert!(r.contains(&3) && r.contains(&5)); - /// for _ in r.by_ref() {} - /// // Precise field values are unspecified here - /// assert!(!r.contains(&3) && !r.contains(&5)); - /// ``` #[inline] #[stable(feature = "range_contains", since = "1.35.0")] pub fn contains(&self, item: &U) -> bool @@ -531,19 +538,10 @@ impl> RangeInclusive { /// assert!( (3.0..=f32::NAN).is_empty()); /// assert!( (f32::NAN..=5.0).is_empty()); /// ``` - /// - /// This method returns `true` after iteration has finished: - /// - /// ``` - /// let mut r = 3..=5; - /// for _ in r.by_ref() {} - /// // Precise field values are unspecified here - /// assert!(r.is_empty()); - /// ``` #[stable(feature = "range_is_empty", since = "1.47.0")] #[inline] pub fn is_empty(&self) -> bool { - self.exhausted || !(self.start <= self.end) + !(self.start <= self.end) } } @@ -632,369 +630,367 @@ impl> RangeToInclusive { // RangeToInclusive cannot impl From> // because underflow would be possible with (..0).into() -/// An endpoint of a range of keys. -/// -/// # Examples -/// -/// `Bound`s are range endpoints: -/// -/// ``` -/// use std::ops::Bound::*; -/// use std::ops::RangeBounds; -/// -/// assert_eq!((..100).start_bound(), Unbounded); -/// assert_eq!((1..12).start_bound(), Included(&1)); -/// assert_eq!((1..12).end_bound(), Excluded(&12)); -/// ``` -/// -/// Using a tuple of `Bound`s as an argument to [`BTreeMap::range`]. -/// Note that in most cases, it's better to use range syntax (`1..5`) instead. -/// -/// ``` -/// use std::collections::BTreeMap; -/// use std::ops::Bound::{Excluded, Included, Unbounded}; -/// -/// let mut map = BTreeMap::new(); -/// map.insert(3, "a"); -/// map.insert(5, "b"); -/// map.insert(8, "c"); -/// -/// for (key, value) in map.range((Excluded(3), Included(8))) { -/// println!("{key}: {value}"); -/// } -/// -/// assert_eq!(Some((&3, &"a")), map.range((Unbounded, Included(5))).next()); -/// ``` -/// -/// [`BTreeMap::range`]: ../../std/collections/btree_map/struct.BTreeMap.html#method.range -#[stable(feature = "collections_bound", since = "1.17.0")] -#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] -pub enum Bound { - /// An inclusive bound. - #[stable(feature = "collections_bound", since = "1.17.0")] - Included(#[stable(feature = "collections_bound", since = "1.17.0")] T), - /// An exclusive bound. - #[stable(feature = "collections_bound", since = "1.17.0")] - Excluded(#[stable(feature = "collections_bound", since = "1.17.0")] T), - /// An infinite endpoint. Indicates that there is no bound in this direction. - #[stable(feature = "collections_bound", since = "1.17.0")] - Unbounded, -} - -impl Bound { - /// Converts from `&Bound` to `Bound<&T>`. - #[inline] - #[stable(feature = "bound_as_ref_shared", since = "1.65.0")] - pub fn as_ref(&self) -> Bound<&T> { - match *self { - Included(ref x) => Included(x), - Excluded(ref x) => Excluded(x), - Unbounded => Unbounded, - } - } - - /// Converts from `&mut Bound` to `Bound<&mut T>`. - #[inline] - #[unstable(feature = "bound_as_ref", issue = "80996")] - pub fn as_mut(&mut self) -> Bound<&mut T> { - match *self { - Included(ref mut x) => Included(x), - Excluded(ref mut x) => Excluded(x), - Unbounded => Unbounded, - } - } +pub(crate) mod bounds { + use super::*; - /// Maps a `Bound` to a `Bound` by applying a function to the contained value (including - /// both `Included` and `Excluded`), returning a `Bound` of the same kind. + /// An endpoint of a range of keys. /// /// # Examples /// - /// ``` - /// #![feature(bound_map)] - /// use std::ops::Bound::*; - /// - /// let bound_string = Included("Hello, World!"); - /// - /// assert_eq!(bound_string.map(|s| s.len()), Included(13)); - /// ``` - /// - /// ``` - /// #![feature(bound_map)] - /// use std::ops::Bound; - /// use Bound::*; - /// - /// let unbounded_string: Bound = Unbounded; - /// - /// assert_eq!(unbounded_string.map(|s| s.len()), Unbounded); - /// ``` - #[inline] - #[unstable(feature = "bound_map", issue = "86026")] - pub fn map U>(self, f: F) -> Bound { - match self { - Unbounded => Unbounded, - Included(x) => Included(f(x)), - Excluded(x) => Excluded(f(x)), - } - } -} - -impl Bound<&T> { - /// Map a `Bound<&T>` to a `Bound` by cloning the contents of the bound. - /// - /// # Examples + /// `Bound`s are range endpoints: /// /// ``` /// use std::ops::Bound::*; /// use std::ops::RangeBounds; /// + /// assert_eq!((..100).start_bound(), Unbounded); /// assert_eq!((1..12).start_bound(), Included(&1)); - /// assert_eq!((1..12).start_bound().cloned(), Included(1)); + /// assert_eq!((1..12).end_bound(), Excluded(&12)); /// ``` - #[must_use = "`self` will be dropped if the result is not used"] - #[stable(feature = "bound_cloned", since = "1.55.0")] - pub fn cloned(self) -> Bound { - match self { - Bound::Unbounded => Bound::Unbounded, - Bound::Included(x) => Bound::Included(x.clone()), - Bound::Excluded(x) => Bound::Excluded(x.clone()), - } - } -} - -/// `RangeBounds` is implemented by Rust's built-in range types, produced -/// by range syntax like `..`, `a..`, `..b`, `..=c`, `d..e`, or `f..=g`. -#[stable(feature = "collections_range", since = "1.28.0")] -#[rustc_diagnostic_item = "RangeBounds"] -pub trait RangeBounds { - /// Start index bound. /// - /// Returns the start value as a `Bound`. - /// - /// # Examples + /// Using a tuple of `Bound`s as an argument to [`BTreeMap::range`]. + /// Note that in most cases, it's better to use range syntax (`1..5`) instead. /// /// ``` - /// # fn main() { - /// use std::ops::Bound::*; - /// use std::ops::RangeBounds; + /// use std::collections::BTreeMap; + /// use std::ops::Bound::{Excluded, Included, Unbounded}; /// - /// assert_eq!((..10).start_bound(), Unbounded); - /// assert_eq!((3..10).start_bound(), Included(&3)); - /// # } - /// ``` - #[stable(feature = "collections_range", since = "1.28.0")] - fn start_bound(&self) -> Bound<&T>; - - /// End index bound. + /// let mut map = BTreeMap::new(); + /// map.insert(3, "a"); + /// map.insert(5, "b"); + /// map.insert(8, "c"); /// - /// Returns the end value as a `Bound`. - /// - /// # Examples - /// - /// ``` - /// # fn main() { - /// use std::ops::Bound::*; - /// use std::ops::RangeBounds; - /// - /// assert_eq!((3..).end_bound(), Unbounded); - /// assert_eq!((3..10).end_bound(), Excluded(&10)); - /// # } - /// ``` - #[stable(feature = "collections_range", since = "1.28.0")] - fn end_bound(&self) -> Bound<&T>; - - /// Returns `true` if `item` is contained in the range. - /// - /// # Examples + /// for (key, value) in map.range((Excluded(3), Included(8))) { + /// println!("{key}: {value}"); + /// } /// + /// assert_eq!(Some((&3, &"a")), map.range((Unbounded, Included(5))).next()); /// ``` - /// assert!( (3..5).contains(&4)); - /// assert!(!(3..5).contains(&2)); /// - /// assert!( (0.0..1.0).contains(&0.5)); - /// assert!(!(0.0..1.0).contains(&f32::NAN)); - /// assert!(!(0.0..f32::NAN).contains(&0.5)); - /// assert!(!(f32::NAN..1.0).contains(&0.5)); - #[inline] - #[stable(feature = "range_contains", since = "1.35.0")] - fn contains(&self, item: &U) -> bool - where - T: PartialOrd, - U: ?Sized + PartialOrd, - { - (match self.start_bound() { - Included(start) => start <= item, - Excluded(start) => start < item, - Unbounded => true, - }) && (match self.end_bound() { - Included(end) => item <= end, - Excluded(end) => item < end, - Unbounded => true, - }) - } -} + /// [`BTreeMap::range`]: ../../std/collections/btree_map/struct.BTreeMap.html#method.range + #[stable(feature = "collections_bound", since = "1.17.0")] + #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] + pub enum Bound { + /// An inclusive bound. + #[stable(feature = "collections_bound", since = "1.17.0")] + Included(#[stable(feature = "collections_bound", since = "1.17.0")] T), + /// An exclusive bound. + #[stable(feature = "collections_bound", since = "1.17.0")] + Excluded(#[stable(feature = "collections_bound", since = "1.17.0")] T), + /// An infinite endpoint. Indicates that there is no bound in this direction. + #[stable(feature = "collections_bound", since = "1.17.0")] + Unbounded, + } + + impl Bound { + /// Converts from `&Bound` to `Bound<&T>`. + #[inline] + #[stable(feature = "bound_as_ref_shared", since = "1.65.0")] + pub fn as_ref(&self) -> Bound<&T> { + match *self { + Included(ref x) => Included(x), + Excluded(ref x) => Excluded(x), + Unbounded => Unbounded, + } + } -use self::Bound::{Excluded, Included, Unbounded}; + /// Converts from `&mut Bound` to `Bound<&mut T>`. + #[inline] + #[unstable(feature = "bound_as_ref", issue = "80996")] + pub fn as_mut(&mut self) -> Bound<&mut T> { + match *self { + Included(ref mut x) => Included(x), + Excluded(ref mut x) => Excluded(x), + Unbounded => Unbounded, + } + } -#[stable(feature = "collections_range", since = "1.28.0")] -impl RangeBounds for RangeFull { - fn start_bound(&self) -> Bound<&T> { - Unbounded - } - fn end_bound(&self) -> Bound<&T> { - Unbounded + /// Maps a `Bound` to a `Bound` by applying a function to the contained value (including + /// both `Included` and `Excluded`), returning a `Bound` of the same kind. + /// + /// # Examples + /// + /// ``` + /// #![feature(bound_map)] + /// use std::ops::Bound::*; + /// + /// let bound_string = Included("Hello, World!"); + /// + /// assert_eq!(bound_string.map(|s| s.len()), Included(13)); + /// ``` + /// + /// ``` + /// #![feature(bound_map)] + /// use std::ops::Bound; + /// use Bound::*; + /// + /// let unbounded_string: Bound = Unbounded; + /// + /// assert_eq!(unbounded_string.map(|s| s.len()), Unbounded); + /// ``` + #[inline] + #[unstable(feature = "bound_map", issue = "86026")] + pub fn map U>(self, f: F) -> Bound { + match self { + Unbounded => Unbounded, + Included(x) => Included(f(x)), + Excluded(x) => Excluded(f(x)), + } + } } -} -#[stable(feature = "collections_range", since = "1.28.0")] -impl RangeBounds for RangeFrom { - fn start_bound(&self) -> Bound<&T> { - Included(&self.start) - } - fn end_bound(&self) -> Bound<&T> { - Unbounded + impl Bound<&T> { + /// Map a `Bound<&T>` to a `Bound` by cloning the contents of the bound. + /// + /// # Examples + /// + /// ``` + /// use std::ops::Bound::*; + /// use std::ops::RangeBounds; + /// + /// assert_eq!((1..12).start_bound(), Included(&1)); + /// assert_eq!((1..12).start_bound().cloned(), Included(1)); + /// ``` + #[must_use = "`self` will be dropped if the result is not used"] + #[stable(feature = "bound_cloned", since = "1.55.0")] + pub fn cloned(self) -> Bound { + match self { + Bound::Unbounded => Bound::Unbounded, + Bound::Included(x) => Bound::Included(x.clone()), + Bound::Excluded(x) => Bound::Excluded(x.clone()), + } + } } -} -#[stable(feature = "collections_range", since = "1.28.0")] -impl RangeBounds for RangeTo { - fn start_bound(&self) -> Bound<&T> { - Unbounded - } - fn end_bound(&self) -> Bound<&T> { - Excluded(&self.end) + /// `RangeBounds` is implemented by Rust's built-in range types, produced + /// by range syntax like `..`, `a..`, `..b`, `..=c`, `d..e`, or `f..=g`. + #[stable(feature = "collections_range", since = "1.28.0")] + #[rustc_diagnostic_item = "RangeBounds"] + pub trait RangeBounds { + /// Start index bound. + /// + /// Returns the start value as a `Bound`. + /// + /// # Examples + /// + /// ``` + /// # fn main() { + /// use std::ops::Bound::*; + /// use std::ops::RangeBounds; + /// + /// assert_eq!((..10).start_bound(), Unbounded); + /// assert_eq!((3..10).start_bound(), Included(&3)); + /// # } + /// ``` + #[stable(feature = "collections_range", since = "1.28.0")] + fn start_bound(&self) -> Bound<&T>; + + /// End index bound. + /// + /// Returns the end value as a `Bound`. + /// + /// # Examples + /// + /// ``` + /// # fn main() { + /// use std::ops::Bound::*; + /// use std::ops::RangeBounds; + /// + /// assert_eq!((3..).end_bound(), Unbounded); + /// assert_eq!((3..10).end_bound(), Excluded(&10)); + /// # } + /// ``` + #[stable(feature = "collections_range", since = "1.28.0")] + fn end_bound(&self) -> Bound<&T>; + + /// Returns `true` if `item` is contained in the range. + /// + /// # Examples + /// + /// ``` + /// assert!( (3..5).contains(&4)); + /// assert!(!(3..5).contains(&2)); + /// + /// assert!( (0.0..1.0).contains(&0.5)); + /// assert!(!(0.0..1.0).contains(&f32::NAN)); + /// assert!(!(0.0..f32::NAN).contains(&0.5)); + /// assert!(!(f32::NAN..1.0).contains(&0.5)); + #[inline] + #[stable(feature = "range_contains", since = "1.35.0")] + fn contains(&self, item: &U) -> bool + where + T: PartialOrd, + U: ?Sized + PartialOrd, + { + (match self.start_bound() { + Included(start) => start <= item, + Excluded(start) => start < item, + Unbounded => true, + }) && (match self.end_bound() { + Included(end) => item <= end, + Excluded(end) => item < end, + Unbounded => true, + }) + } } -} -#[stable(feature = "collections_range", since = "1.28.0")] -impl RangeBounds for Range { - fn start_bound(&self) -> Bound<&T> { - Included(&self.start) - } - fn end_bound(&self) -> Bound<&T> { - Excluded(&self.end) + use self::Bound::{Excluded, Included, Unbounded}; + + #[stable(feature = "collections_range", since = "1.28.0")] + impl RangeBounds for RangeFull { + fn start_bound(&self) -> Bound<&T> { + Unbounded + } + fn end_bound(&self) -> Bound<&T> { + Unbounded + } } -} -#[stable(feature = "collections_range", since = "1.28.0")] -impl RangeBounds for RangeInclusive { - fn start_bound(&self) -> Bound<&T> { - Included(&self.start) + #[stable(feature = "collections_range", since = "1.28.0")] + impl RangeBounds for RangeFrom { + fn start_bound(&self) -> Bound<&T> { + Included(&self.start) + } + fn end_bound(&self) -> Bound<&T> { + Unbounded + } } - fn end_bound(&self) -> Bound<&T> { - if self.exhausted { - // When the iterator is exhausted, we usually have start == end, - // but we want the range to appear empty, containing nothing. + + #[stable(feature = "collections_range", since = "1.28.0")] + impl RangeBounds for RangeTo { + fn start_bound(&self) -> Bound<&T> { + Unbounded + } + fn end_bound(&self) -> Bound<&T> { Excluded(&self.end) - } else { - Included(&self.end) } } -} -#[stable(feature = "collections_range", since = "1.28.0")] -impl RangeBounds for RangeToInclusive { - fn start_bound(&self) -> Bound<&T> { - Unbounded - } - fn end_bound(&self) -> Bound<&T> { - Included(&self.end) + #[stable(feature = "collections_range", since = "1.28.0")] + impl RangeBounds for Range { + fn start_bound(&self) -> Bound<&T> { + Included(&self.start) + } + fn end_bound(&self) -> Bound<&T> { + Excluded(&self.end) + } } -} -#[stable(feature = "collections_range", since = "1.28.0")] -impl RangeBounds for (Bound, Bound) { - fn start_bound(&self) -> Bound<&T> { - match *self { - (Included(ref start), _) => Included(start), - (Excluded(ref start), _) => Excluded(start), - (Unbounded, _) => Unbounded, + #[stable(feature = "collections_range", since = "1.28.0")] + impl RangeBounds for RangeInclusive { + fn start_bound(&self) -> Bound<&T> { + Included(&self.start) + } + fn end_bound(&self) -> Bound<&T> { + Included(&self.end) } } - fn end_bound(&self) -> Bound<&T> { - match *self { - (_, Included(ref end)) => Included(end), - (_, Excluded(ref end)) => Excluded(end), - (_, Unbounded) => Unbounded, + #[stable(feature = "collections_range", since = "1.28.0")] + impl RangeBounds for RangeToInclusive { + fn start_bound(&self) -> Bound<&T> { + Unbounded + } + fn end_bound(&self) -> Bound<&T> { + Included(&self.end) } } -} -#[stable(feature = "collections_range", since = "1.28.0")] -impl<'a, T: ?Sized + 'a> RangeBounds for (Bound<&'a T>, Bound<&'a T>) { - fn start_bound(&self) -> Bound<&T> { - self.0 - } + #[stable(feature = "collections_range", since = "1.28.0")] + impl RangeBounds for (Bound, Bound) { + fn start_bound(&self) -> Bound<&T> { + match *self { + (Included(ref start), _) => Included(start), + (Excluded(ref start), _) => Excluded(start), + (Unbounded, _) => Unbounded, + } + } - fn end_bound(&self) -> Bound<&T> { - self.1 + fn end_bound(&self) -> Bound<&T> { + match *self { + (_, Included(ref end)) => Included(end), + (_, Excluded(ref end)) => Excluded(end), + (_, Unbounded) => Unbounded, + } + } } -} -#[stable(feature = "collections_range", since = "1.28.0")] -impl RangeBounds for RangeFrom<&T> { - fn start_bound(&self) -> Bound<&T> { - Included(self.start) - } - fn end_bound(&self) -> Bound<&T> { - Unbounded - } -} + #[stable(feature = "collections_range", since = "1.28.0")] + impl<'a, T: ?Sized + 'a> RangeBounds for (Bound<&'a T>, Bound<&'a T>) { + fn start_bound(&self) -> Bound<&T> { + self.0 + } -#[stable(feature = "collections_range", since = "1.28.0")] -impl RangeBounds for RangeTo<&T> { - fn start_bound(&self) -> Bound<&T> { - Unbounded - } - fn end_bound(&self) -> Bound<&T> { - Excluded(self.end) + fn end_bound(&self) -> Bound<&T> { + self.1 + } } -} -#[stable(feature = "collections_range", since = "1.28.0")] -impl RangeBounds for Range<&T> { - fn start_bound(&self) -> Bound<&T> { - Included(self.start) - } - fn end_bound(&self) -> Bound<&T> { - Excluded(self.end) + #[stable(feature = "collections_range", since = "1.28.0")] + impl RangeBounds for RangeFrom<&T> { + fn start_bound(&self) -> Bound<&T> { + Included(self.start) + } + fn end_bound(&self) -> Bound<&T> { + Unbounded + } } -} -#[stable(feature = "collections_range", since = "1.28.0")] -impl RangeBounds for RangeInclusive<&T> { - fn start_bound(&self) -> Bound<&T> { - Included(self.start) + #[stable(feature = "collections_range", since = "1.28.0")] + impl RangeBounds for RangeTo<&T> { + fn start_bound(&self) -> Bound<&T> { + Unbounded + } + fn end_bound(&self) -> Bound<&T> { + Excluded(self.end) + } } - fn end_bound(&self) -> Bound<&T> { - Included(self.end) + + #[stable(feature = "collections_range", since = "1.28.0")] + impl RangeBounds for Range<&T> { + fn start_bound(&self) -> Bound<&T> { + Included(self.start) + } + fn end_bound(&self) -> Bound<&T> { + Excluded(self.end) + } } -} -#[stable(feature = "collections_range", since = "1.28.0")] -impl RangeBounds for RangeToInclusive<&T> { - fn start_bound(&self) -> Bound<&T> { - Unbounded + #[stable(feature = "collections_range", since = "1.28.0")] + impl RangeBounds for RangeInclusive<&T> { + fn start_bound(&self) -> Bound<&T> { + Included(self.start) + } + fn end_bound(&self) -> Bound<&T> { + Included(self.end) + } } - fn end_bound(&self) -> Bound<&T> { - Included(self.end) + + #[stable(feature = "collections_range", since = "1.28.0")] + impl RangeBounds for RangeToInclusive<&T> { + fn start_bound(&self) -> Bound<&T> { + Unbounded + } + fn end_bound(&self) -> Bound<&T> { + Included(self.end) + } } -} -/// `OneSidedRange` is implemented for built-in range types that are unbounded -/// on one side. For example, `a..`, `..b` and `..=c` implement `OneSidedRange`, -/// but `..`, `d..e`, and `f..=g` do not. -/// -/// Types that implement `OneSidedRange` must return `Bound::Unbounded` -/// from one of `RangeBounds::start_bound` or `RangeBounds::end_bound`. -#[unstable(feature = "one_sided_range", issue = "69780")] -pub trait OneSidedRange: RangeBounds {} + /// `OneSidedRange` is implemented for built-in range types that are unbounded + /// on one side. For example, `a..`, `..b` and `..=c` implement `OneSidedRange`, + /// but `..`, `d..e`, and `f..=g` do not. + /// + /// Types that implement `OneSidedRange` must return `Bound::Unbounded` + /// from one of `RangeBounds::start_bound` or `RangeBounds::end_bound`. + #[unstable(feature = "one_sided_range", issue = "69780")] + pub trait OneSidedRange: RangeBounds {} -#[unstable(feature = "one_sided_range", issue = "69780")] -impl OneSidedRange for RangeTo where Self: RangeBounds {} + #[unstable(feature = "one_sided_range", issue = "69780")] + impl OneSidedRange for RangeTo where Self: RangeBounds {} -#[unstable(feature = "one_sided_range", issue = "69780")] -impl OneSidedRange for RangeFrom where Self: RangeBounds {} + #[unstable(feature = "one_sided_range", issue = "69780")] + impl OneSidedRange for RangeFrom where Self: RangeBounds {} -#[unstable(feature = "one_sided_range", issue = "69780")] -impl OneSidedRange for RangeToInclusive where Self: RangeBounds {} + #[unstable(feature = "one_sided_range", issue = "69780")] + impl OneSidedRange for RangeToInclusive where Self: RangeBounds {} +} diff --git a/library/core/src/ops/range/legacy.rs b/library/core/src/ops/range/legacy.rs new file mode 100644 index 0000000000000..deb25f8873d90 --- /dev/null +++ b/library/core/src/ops/range/legacy.rs @@ -0,0 +1,497 @@ +//! Range types that `..` resolves to prior to edition 2024. + +use crate::fmt; +use crate::hash::Hash; + +use super::bounds::{ + Bound, + Bound::{Excluded, Included, Unbounded}, + OneSidedRange, RangeBounds, +}; + +/// A (half-open) range bounded inclusively below and exclusively above +/// (`start..end`). +/// +/// The range `start..end` contains all values with `start <= x < end`. +/// It is empty if `start >= end`. +/// +/// # Examples +/// +/// The `start..end` syntax is a `Range`: +/// +/// ``` +/// assert_eq!((3..5), std::ops::Range { start: 3, end: 5 }); +/// assert_eq!(3 + 4 + 5, (3..6).sum()); +/// ``` +/// +/// ``` +/// let arr = [0, 1, 2, 3, 4]; +/// assert_eq!(arr[ .. ], [0, 1, 2, 3, 4]); +/// assert_eq!(arr[ .. 3], [0, 1, 2 ]); +/// assert_eq!(arr[ ..=3], [0, 1, 2, 3 ]); +/// assert_eq!(arr[1.. ], [ 1, 2, 3, 4]); +/// assert_eq!(arr[1.. 3], [ 1, 2 ]); // This is a `Range` +/// assert_eq!(arr[1..=3], [ 1, 2, 3 ]); +/// ``` +// FIXME: #[lang = "LegacyRange"] +#[doc(alias = "..")] +#[derive(Clone, Default, PartialEq, Eq, Hash)] // not Copy -- see #27186 +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Range { + /// The lower bound of the range (inclusive). + #[stable(feature = "rust1", since = "1.0.0")] + pub start: Idx, + /// The upper bound of the range (exclusive). + #[stable(feature = "rust1", since = "1.0.0")] + pub end: Idx, +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for Range { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + self.start.fmt(fmt)?; + write!(fmt, "..")?; + self.end.fmt(fmt)?; + Ok(()) + } +} + +impl> Range { + /// Returns `true` if `item` is contained in the range. + /// + /// # Examples + /// + /// ``` + /// assert!(!(3..5).contains(&2)); + /// assert!( (3..5).contains(&3)); + /// assert!( (3..5).contains(&4)); + /// assert!(!(3..5).contains(&5)); + /// + /// assert!(!(3..3).contains(&3)); + /// assert!(!(3..2).contains(&3)); + /// + /// assert!( (0.0..1.0).contains(&0.5)); + /// assert!(!(0.0..1.0).contains(&f32::NAN)); + /// assert!(!(0.0..f32::NAN).contains(&0.5)); + /// assert!(!(f32::NAN..1.0).contains(&0.5)); + /// ``` + #[inline] + #[stable(feature = "range_contains", since = "1.35.0")] + pub fn contains(&self, item: &U) -> bool + where + Idx: PartialOrd, + U: ?Sized + PartialOrd, + { + >::contains(self, item) + } + + /// Returns `true` if the range contains no items. + /// + /// # Examples + /// + /// ``` + /// assert!(!(3..5).is_empty()); + /// assert!( (3..3).is_empty()); + /// assert!( (3..2).is_empty()); + /// ``` + /// + /// The range is empty if either side is incomparable: + /// + /// ``` + /// assert!(!(3.0..5.0).is_empty()); + /// assert!( (3.0..f32::NAN).is_empty()); + /// assert!( (f32::NAN..5.0).is_empty()); + /// ``` + #[inline] + #[stable(feature = "range_is_empty", since = "1.47.0")] + pub fn is_empty(&self) -> bool { + !(self.start < self.end) + } +} + +/// A range only bounded inclusively below (`start..`). +/// +/// The `RangeFrom` `start..` contains all values with `x >= start`. +/// +/// *Note*: Overflow in the [`Iterator`] implementation (when the contained +/// data type reaches its numerical limit) is allowed to panic, wrap, or +/// saturate. This behavior is defined by the implementation of the [`Step`] +/// trait. For primitive integers, this follows the normal rules, and respects +/// the overflow checks profile (panic in debug, wrap in release). Note also +/// that overflow happens earlier than you might assume: the overflow happens +/// in the call to `next` that yields the maximum value, as the range must be +/// set to a state to yield the next value. +/// +/// [`Step`]: crate::iter::Step +/// +/// # Examples +/// +/// The `start..` syntax is a `RangeFrom`: +/// +/// ``` +/// assert_eq!((2..), std::ops::RangeFrom { start: 2 }); +/// assert_eq!(2 + 3 + 4, (2..).take(3).sum()); +/// ``` +/// +/// ``` +/// let arr = [0, 1, 2, 3, 4]; +/// assert_eq!(arr[ .. ], [0, 1, 2, 3, 4]); +/// assert_eq!(arr[ .. 3], [0, 1, 2 ]); +/// assert_eq!(arr[ ..=3], [0, 1, 2, 3 ]); +/// assert_eq!(arr[1.. ], [ 1, 2, 3, 4]); // This is a `RangeFrom` +/// assert_eq!(arr[1.. 3], [ 1, 2 ]); +/// assert_eq!(arr[1..=3], [ 1, 2, 3 ]); +/// ``` +// FIXME: #[lang = "LegacyRangeFrom"] +#[doc(alias = "..")] +#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186 +#[stable(feature = "rust1", since = "1.0.0")] +pub struct RangeFrom { + /// The lower bound of the range (inclusive). + #[stable(feature = "rust1", since = "1.0.0")] + pub start: Idx, +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for RangeFrom { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + self.start.fmt(fmt)?; + write!(fmt, "..")?; + Ok(()) + } +} + +impl> RangeFrom { + /// Returns `true` if `item` is contained in the range. + /// + /// # Examples + /// + /// ``` + /// assert!(!(3..).contains(&2)); + /// assert!( (3..).contains(&3)); + /// assert!( (3..).contains(&1_000_000_000)); + /// + /// assert!( (0.0..).contains(&0.5)); + /// assert!(!(0.0..).contains(&f32::NAN)); + /// assert!(!(f32::NAN..).contains(&0.5)); + /// ``` + #[inline] + #[stable(feature = "range_contains", since = "1.35.0")] + pub fn contains(&self, item: &U) -> bool + where + Idx: PartialOrd, + U: ?Sized + PartialOrd, + { + >::contains(self, item) + } +} + +/// A range bounded inclusively below and above (`start..=end`). +/// +/// The `RangeInclusive` `start..=end` contains all values with `x >= start` +/// and `x <= end`. It is empty unless `start <= end`. +/// +/// This iterator is [fused], but the specific values of `start` and `end` after +/// iteration has finished are **unspecified** other than that [`.is_empty()`] +/// will return `true` once no more values will be produced. +/// +/// [fused]: crate::iter::FusedIterator +/// [`.is_empty()`]: RangeInclusive::is_empty +/// +/// # Examples +/// +/// The `start..=end` syntax is a `RangeInclusive`: +/// +/// ``` +/// assert_eq!((3..=5), std::ops::RangeInclusive::new(3, 5)); +/// assert_eq!(3 + 4 + 5, (3..=5).sum()); +/// ``` +/// +/// ``` +/// let arr = [0, 1, 2, 3, 4]; +/// assert_eq!(arr[ .. ], [0, 1, 2, 3, 4]); +/// assert_eq!(arr[ .. 3], [0, 1, 2 ]); +/// assert_eq!(arr[ ..=3], [0, 1, 2, 3 ]); +/// assert_eq!(arr[1.. ], [ 1, 2, 3, 4]); +/// assert_eq!(arr[1.. 3], [ 1, 2 ]); +/// assert_eq!(arr[1..=3], [ 1, 2, 3 ]); // This is a `RangeInclusive` +/// ``` +// FIXME: #[lang = "LegacyRangeInclusive"] +#[doc(alias = "..=")] +#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186 +#[stable(feature = "inclusive_range", since = "1.26.0")] +pub struct RangeInclusive { + // Note that the fields here are not public to allow changing the + // representation in the future; in particular, while we could plausibly + // expose start/end, modifying them without changing (future/current) + // private fields may lead to incorrect behavior, so we don't want to + // support that mode. + pub(crate) start: Idx, + pub(crate) end: Idx, + + // This field is: + // - `false` upon construction + // - `false` when iteration has yielded an element and the iterator is not exhausted + // - `true` when iteration has been used to exhaust the iterator + // + // This is required to support PartialEq and Hash without a PartialOrd bound or specialization. + pub(crate) exhausted: bool, +} + +impl RangeInclusive { + /// Creates a new inclusive range. Equivalent to writing `start..=end`. + /// + /// # Examples + /// + /// ``` + /// use std::ops::RangeInclusive; + /// + /// assert_eq!(3..=5, RangeInclusive::new(3, 5)); + /// ``` + // FIXME: #[lang = "legacy_range_inclusive_new"] + #[stable(feature = "inclusive_range_methods", since = "1.27.0")] + #[inline] + #[rustc_promotable] + #[rustc_const_stable(feature = "const_range_new", since = "1.32.0")] + pub const fn new(start: Idx, end: Idx) -> Self { + Self { start, end, exhausted: false } + } + + /// Returns the lower bound of the range (inclusive). + /// + /// When using an inclusive range for iteration, the values of `start()` and + /// [`end()`] are unspecified after the iteration ended. To determine + /// whether the inclusive range is empty, use the [`is_empty()`] method + /// instead of comparing `start() > end()`. + /// + /// Note: the value returned by this method is unspecified after the range + /// has been iterated to exhaustion. + /// + /// [`end()`]: RangeInclusive::end + /// [`is_empty()`]: RangeInclusive::is_empty + /// + /// # Examples + /// + /// ``` + /// assert_eq!((3..=5).start(), &3); + /// ``` + #[stable(feature = "inclusive_range_methods", since = "1.27.0")] + #[rustc_const_stable(feature = "const_inclusive_range_methods", since = "1.32.0")] + #[inline] + pub const fn start(&self) -> &Idx { + &self.start + } + + /// Returns the upper bound of the range (inclusive). + /// + /// When using an inclusive range for iteration, the values of [`start()`] + /// and `end()` are unspecified after the iteration ended. To determine + /// whether the inclusive range is empty, use the [`is_empty()`] method + /// instead of comparing `start() > end()`. + /// + /// Note: the value returned by this method is unspecified after the range + /// has been iterated to exhaustion. + /// + /// [`start()`]: RangeInclusive::start + /// [`is_empty()`]: RangeInclusive::is_empty + /// + /// # Examples + /// + /// ``` + /// assert_eq!((3..=5).end(), &5); + /// ``` + #[stable(feature = "inclusive_range_methods", since = "1.27.0")] + #[rustc_const_stable(feature = "const_inclusive_range_methods", since = "1.32.0")] + #[inline] + pub const fn end(&self) -> &Idx { + &self.end + } + + /// Destructures the `RangeInclusive` into (lower bound, upper (inclusive) bound). + /// + /// Note: the value returned by this method is unspecified after the range + /// has been iterated to exhaustion. + /// + /// # Examples + /// + /// ``` + /// assert_eq!((3..=5).into_inner(), (3, 5)); + /// ``` + #[stable(feature = "inclusive_range_methods", since = "1.27.0")] + #[inline] + #[rustc_const_unstable(feature = "const_range_bounds", issue = "108082")] + pub const fn into_inner(self) -> (Idx, Idx) { + (self.start, self.end) + } +} + +#[stable(feature = "inclusive_range", since = "1.26.0")] +impl fmt::Debug for RangeInclusive { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + self.start.fmt(fmt)?; + write!(fmt, "..=")?; + self.end.fmt(fmt)?; + if self.exhausted { + write!(fmt, " (exhausted)")?; + } + Ok(()) + } +} + +impl> RangeInclusive { + /// Returns `true` if `item` is contained in the range. + /// + /// # Examples + /// + /// ``` + /// assert!(!(3..=5).contains(&2)); + /// assert!( (3..=5).contains(&3)); + /// assert!( (3..=5).contains(&4)); + /// assert!( (3..=5).contains(&5)); + /// assert!(!(3..=5).contains(&6)); + /// + /// assert!( (3..=3).contains(&3)); + /// assert!(!(3..=2).contains(&3)); + /// + /// assert!( (0.0..=1.0).contains(&1.0)); + /// assert!(!(0.0..=1.0).contains(&f32::NAN)); + /// assert!(!(0.0..=f32::NAN).contains(&0.0)); + /// assert!(!(f32::NAN..=1.0).contains(&1.0)); + /// ``` + /// + /// This method always returns `false` after iteration has finished: + /// + /// ``` + /// # use core::ops::range::legacy; + /// let mut r = legacy::RangeInclusive::from(3..=5); + /// assert!(r.contains(&3) && r.contains(&5)); + /// for _ in r.by_ref() {} + /// // Precise field values are unspecified here + /// assert!(!r.contains(&3) && !r.contains(&5)); + /// ``` + #[inline] + #[stable(feature = "range_contains", since = "1.35.0")] + pub fn contains(&self, item: &U) -> bool + where + Idx: PartialOrd, + U: ?Sized + PartialOrd, + { + >::contains(self, item) + } + + /// Returns `true` if the range contains no items. + /// + /// # Examples + /// + /// ``` + /// assert!(!(3..=5).is_empty()); + /// assert!(!(3..=3).is_empty()); + /// assert!( (3..=2).is_empty()); + /// ``` + /// + /// The range is empty if either side is incomparable: + /// + /// ``` + /// assert!(!(3.0..=5.0).is_empty()); + /// assert!( (3.0..=f32::NAN).is_empty()); + /// assert!( (f32::NAN..=5.0).is_empty()); + /// ``` + /// + /// This method returns `true` after iteration has finished: + /// + /// ``` + /// # use core::ops::range::legacy; + /// let mut r = legacy::RangeInclusive::from(3..=5); + /// for _ in r.by_ref() {} + /// // Precise field values are unspecified here + /// assert!(r.is_empty()); + /// ``` + #[stable(feature = "range_is_empty", since = "1.47.0")] + #[inline] + pub fn is_empty(&self) -> bool { + self.exhausted || !(self.start <= self.end) + } +} + +impl RangeInclusive { + /// Converts to an exclusive `Range` for `SliceIndex` implementations. + /// The caller is responsible for dealing with `end == usize::MAX`. + #[inline] + pub(crate) const fn into_slice_range(self) -> super::Range { + // If we're not exhausted, we want to simply slice `start..end + 1`. + // If we are exhausted, then slicing with `end + 1..end + 1` gives us an + // empty range that is still subject to bounds-checks for that endpoint. + let exclusive_end = self.end + 1; + let start = if self.exhausted { exclusive_end } else { self.start }; + start..exclusive_end + } +} + +#[stable(feature = "collections_range", since = "1.28.0")] +impl RangeBounds for RangeFrom { + fn start_bound(&self) -> Bound<&T> { + Included(&self.start) + } + fn end_bound(&self) -> Bound<&T> { + Unbounded + } +} + +#[stable(feature = "collections_range", since = "1.28.0")] +impl RangeBounds for Range { + fn start_bound(&self) -> Bound<&T> { + Included(&self.start) + } + fn end_bound(&self) -> Bound<&T> { + Excluded(&self.end) + } +} + +#[stable(feature = "collections_range", since = "1.28.0")] +impl RangeBounds for RangeInclusive { + fn start_bound(&self) -> Bound<&T> { + Included(&self.start) + } + fn end_bound(&self) -> Bound<&T> { + if self.exhausted { + // When the iterator is exhausted, we usually have start == end, + // but we want the range to appear empty, containing nothing. + Excluded(&self.end) + } else { + Included(&self.end) + } + } +} + +#[stable(feature = "collections_range", since = "1.28.0")] +impl RangeBounds for RangeFrom<&T> { + fn start_bound(&self) -> Bound<&T> { + Included(self.start) + } + fn end_bound(&self) -> Bound<&T> { + Unbounded + } +} + +#[stable(feature = "collections_range", since = "1.28.0")] +impl RangeBounds for Range<&T> { + fn start_bound(&self) -> Bound<&T> { + Included(self.start) + } + fn end_bound(&self) -> Bound<&T> { + Excluded(self.end) + } +} + +#[stable(feature = "collections_range", since = "1.28.0")] +impl RangeBounds for RangeInclusive<&T> { + fn start_bound(&self) -> Bound<&T> { + Included(self.start) + } + fn end_bound(&self) -> Bound<&T> { + Included(self.end) + } +} + +#[unstable(feature = "one_sided_range", issue = "69780")] +impl OneSidedRange for RangeFrom where Self: RangeBounds {} diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs index 373b4aee47a06..96b41894f825b 100644 --- a/library/core/src/slice/index.rs +++ b/library/core/src/slice/index.rs @@ -126,17 +126,25 @@ mod private_slice_index { #[stable(feature = "slice_get_slice", since = "1.28.0")] impl Sealed for usize {} #[stable(feature = "slice_get_slice", since = "1.28.0")] - impl Sealed for ops::Range {} + impl Sealed for ops::range::legacy::Range {} #[stable(feature = "slice_get_slice", since = "1.28.0")] impl Sealed for ops::RangeTo {} #[stable(feature = "slice_get_slice", since = "1.28.0")] - impl Sealed for ops::RangeFrom {} + impl Sealed for ops::range::legacy::RangeFrom {} #[stable(feature = "slice_get_slice", since = "1.28.0")] impl Sealed for ops::RangeFull {} #[stable(feature = "slice_get_slice", since = "1.28.0")] - impl Sealed for ops::RangeInclusive {} + impl Sealed for ops::range::legacy::RangeInclusive {} #[stable(feature = "slice_get_slice", since = "1.28.0")] impl Sealed for ops::RangeToInclusive {} + + #[stable(feature = "new_range", since = "1.0.0")] + impl Sealed for ops::range::Range {} + #[stable(feature = "new_range", since = "1.0.0")] + impl Sealed for ops::range::RangeFrom {} + #[stable(feature = "new_range", since = "1.0.0")] + impl Sealed for ops::range::RangeInclusive {} + #[stable(feature = "slice_index_with_ops_bound_pair", since = "1.53.0")] impl Sealed for (ops::Bound, ops::Bound) {} @@ -332,9 +340,9 @@ unsafe impl SliceIndex<[T]> for ops::IndexRange { } } -#[stable(feature = "slice_get_slice_impls", since = "1.15.0")] +#[stable(feature = "new_range", since = "1.0.0")] #[rustc_const_unstable(feature = "const_slice_index", issue = "none")] -unsafe impl SliceIndex<[T]> for ops::Range { +unsafe impl SliceIndex<[T]> for ops::range::Range { type Output = [T]; #[inline] @@ -409,6 +417,44 @@ unsafe impl SliceIndex<[T]> for ops::Range { } } +#[stable(feature = "slice_get_slice_impls", since = "1.15.0")] +#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] +unsafe impl SliceIndex<[T]> for ops::range::legacy::Range { + type Output = [T]; + + #[inline] + fn get(self, slice: &[T]) -> Option<&[T]> { + ops::range::Range::from(self).get(slice) + } + + #[inline] + fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> { + ops::range::Range::from(self).get_mut(slice) + } + + #[inline] + unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] { + // SAFETY: delegates to new range impl + unsafe { ops::range::Range::from(self).get_unchecked(slice) } + } + + #[inline] + unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] { + // SAFETY: delegates to new range impl + unsafe { ops::range::Range::from(self).get_unchecked_mut(slice) } + } + + #[inline] + fn index(self, slice: &[T]) -> &[T] { + ops::range::Range::from(self).index(slice) + } + + #[inline] + fn index_mut(self, slice: &mut [T]) -> &mut [T] { + ops::range::Range::from(self).index_mut(slice) + } +} + #[stable(feature = "slice_get_slice_impls", since = "1.15.0")] #[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl SliceIndex<[T]> for ops::RangeTo { @@ -447,9 +493,9 @@ unsafe impl SliceIndex<[T]> for ops::RangeTo { } } -#[stable(feature = "slice_get_slice_impls", since = "1.15.0")] +#[stable(feature = "new_range", since = "1.0.0")] #[rustc_const_unstable(feature = "const_slice_index", issue = "none")] -unsafe impl SliceIndex<[T]> for ops::RangeFrom { +unsafe impl SliceIndex<[T]> for ops::range::RangeFrom { type Output = [T]; #[inline] @@ -493,6 +539,44 @@ unsafe impl SliceIndex<[T]> for ops::RangeFrom { } } +#[stable(feature = "slice_get_slice_impls", since = "1.15.0")] +#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] +unsafe impl SliceIndex<[T]> for ops::range::legacy::RangeFrom { + type Output = [T]; + + #[inline] + fn get(self, slice: &[T]) -> Option<&[T]> { + ops::range::RangeFrom::from(self).get(slice) + } + + #[inline] + fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> { + ops::range::RangeFrom::from(self).get_mut(slice) + } + + #[inline] + unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] { + // SAFETY: delegates to new range impl + unsafe { ops::range::RangeFrom::from(self).get_unchecked(slice) } + } + + #[inline] + unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] { + // SAFETY: delegates to new range impl + unsafe { ops::range::RangeFrom::from(self).get_unchecked_mut(slice) } + } + + #[inline] + fn index(self, slice: &[T]) -> &[T] { + ops::range::RangeFrom::from(self).index(slice) + } + + #[inline] + fn index_mut(self, slice: &mut [T]) -> &mut [T] { + ops::range::RangeFrom::from(self).index_mut(slice) + } +} + #[stable(feature = "slice_get_slice_impls", since = "1.15.0")] #[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl SliceIndex<[T]> for ops::RangeFull { @@ -531,7 +615,7 @@ unsafe impl SliceIndex<[T]> for ops::RangeFull { #[stable(feature = "inclusive_range", since = "1.26.0")] #[rustc_const_unstable(feature = "const_slice_index", issue = "none")] -unsafe impl SliceIndex<[T]> for ops::RangeInclusive { +unsafe impl SliceIndex<[T]> for ops::range::legacy::RangeInclusive { type Output = [T]; #[inline] @@ -573,6 +657,50 @@ unsafe impl SliceIndex<[T]> for ops::RangeInclusive { } } +#[stable(feature = "new_range", since = "1.0.0")] +#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] +unsafe impl SliceIndex<[T]> for ops::range::RangeInclusive { + type Output = [T]; + + #[inline] + fn get(self, slice: &[T]) -> Option<&[T]> { + if self.end == usize::MAX { None } else { self.into_slice_range().get(slice) } + } + + #[inline] + fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> { + if self.end == usize::MAX { None } else { self.into_slice_range().get_mut(slice) } + } + + #[inline] + unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] { + // SAFETY: the caller has to uphold the safety contract for `get_unchecked`. + unsafe { self.into_slice_range().get_unchecked(slice) } + } + + #[inline] + unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] { + // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`. + unsafe { self.into_slice_range().get_unchecked_mut(slice) } + } + + #[inline] + fn index(self, slice: &[T]) -> &[T] { + if self.end == usize::MAX { + slice_end_index_overflow_fail(); + } + self.into_slice_range().index(slice) + } + + #[inline] + fn index_mut(self, slice: &mut [T]) -> &mut [T] { + if self.end == usize::MAX { + slice_end_index_overflow_fail(); + } + self.into_slice_range().index_mut(slice) + } +} + #[stable(feature = "inclusive_range", since = "1.26.0")] #[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl SliceIndex<[T]> for ops::RangeToInclusive { diff --git a/library/core/src/str/pattern.rs b/library/core/src/str/pattern.rs index caa54e00f319f..883ff5631b992 100644 --- a/library/core/src/str/pattern.rs +++ b/library/core/src/str/pattern.rs @@ -1754,8 +1754,9 @@ fn simd_contains(needle: &str, haystack: &str) -> Option { 1 } else { // try a few bytes in case first and last byte of the needle are the same - let Some(second_probe_offset) = - (needle.len().saturating_sub(4)..needle.len()).rfind(|&idx| needle[idx] != first_probe) + let Some(second_probe_offset) = (needle.len().saturating_sub(4)..needle.len()) + .into_iter() + .rfind(|&idx| needle[idx] != first_probe) else { // fall back to other search methods if we can't find any different bytes // since we could otherwise hit some degenerate cases diff --git a/library/core/src/str/traits.rs b/library/core/src/str/traits.rs index 777ad0d818b50..71ef8fa4be2af 100644 --- a/library/core/src/str/traits.rs +++ b/library/core/src/str/traits.rs @@ -122,42 +122,7 @@ unsafe impl SliceIndex for ops::RangeFull { } } -/// Implements substring slicing with syntax `&self[begin .. end]` or `&mut -/// self[begin .. end]`. -/// -/// Returns a slice of the given string from the byte range -/// [`begin`, `end`). -/// -/// This operation is *O*(1). -/// -/// Prior to 1.20.0, these indexing operations were still supported by -/// direct implementation of `Index` and `IndexMut`. -/// -/// # Panics -/// -/// Panics if `begin` or `end` does not point to the starting byte offset of -/// a character (as defined by `is_char_boundary`), if `begin > end`, or if -/// `end > len`. -/// -/// # Examples -/// -/// ``` -/// let s = "Löwe 老虎 Léopard"; -/// assert_eq!(&s[0 .. 1], "L"); -/// -/// assert_eq!(&s[1 .. 9], "öwe 老"); -/// -/// // these will panic: -/// // byte 2 lies within `ö`: -/// // &s[2 ..3]; -/// -/// // byte 8 lies within `老` -/// // &s[1 .. 8]; -/// -/// // byte 100 is outside the string -/// // &s[3 .. 100]; -/// ``` -#[stable(feature = "str_checked_slicing", since = "1.20.0")] +#[stable(feature = "new_range", since = "1.0.0")] #[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl SliceIndex for ops::Range { type Output = str; @@ -248,6 +213,79 @@ unsafe impl SliceIndex for ops::Range { } } +/// Implements substring slicing with syntax `&self[begin .. end]` or `&mut +/// self[begin .. end]`. +/// +/// Returns a slice of the given string from the byte range +/// [`begin`, `end`). +/// +/// This operation is *O*(1). +/// +/// Prior to 1.20.0, these indexing operations were still supported by +/// direct implementation of `Index` and `IndexMut`. +/// +/// # Panics +/// +/// Panics if `begin` or `end` does not point to the starting byte offset of +/// a character (as defined by `is_char_boundary`), if `begin > end`, or if +/// `end > len`. +/// +/// # Examples +/// +/// ``` +/// let s = "Löwe 老虎 Léopard"; +/// assert_eq!(&s[0 .. 1], "L"); +/// +/// assert_eq!(&s[1 .. 9], "öwe 老"); +/// +/// // these will panic: +/// // byte 2 lies within `ö`: +/// // &s[2 ..3]; +/// +/// // byte 8 lies within `老` +/// // &s[1 .. 8]; +/// +/// // byte 100 is outside the string +/// // &s[3 .. 100]; +/// ``` +#[stable(feature = "str_checked_slicing", since = "1.20.0")] +#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] +unsafe impl SliceIndex for ops::range::legacy::Range { + type Output = str; + + #[inline] + fn get(self, slice: &str) -> Option<&str> { + ops::range::Range::from(self).get(slice) + } + + #[inline] + fn get_mut(self, slice: &mut str) -> Option<&mut str> { + ops::range::Range::from(self).get_mut(slice) + } + + #[inline] + unsafe fn get_unchecked(self, slice: *const str) -> *const str { + // SAFETY: delegates to new range impl + unsafe { ops::range::Range::from(self).get_unchecked(slice) } + } + + #[inline] + unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut str { + // SAFETY: delegates to new range impl + unsafe { ops::range::Range::from(self).get_unchecked_mut(slice) } + } + + #[inline] + fn index(self, slice: &str) -> &str { + ops::range::Range::from(self).index(slice) + } + + #[inline] + fn index_mut(self, slice: &mut str) -> &mut str { + ops::range::Range::from(self).index_mut(slice) + } +} + /// Implements substring slicing for arbitrary bounds. /// /// Returns a slice of the given string bounded by the byte indices @@ -458,7 +496,7 @@ unsafe impl SliceIndex for ops::RangeFrom { /// byte offset or equal to `len`), if `begin > end`, or if `end >= len`. #[stable(feature = "inclusive_range", since = "1.26.0")] #[rustc_const_unstable(feature = "const_slice_index", issue = "none")] -unsafe impl SliceIndex for ops::RangeInclusive { +unsafe impl SliceIndex for ops::range::legacy::RangeInclusive { type Output = str; #[inline] fn get(self, slice: &str) -> Option<&Self::Output> { @@ -494,6 +532,44 @@ unsafe impl SliceIndex for ops::RangeInclusive { } } +#[stable(feature = "new_range", since = "1.0.0")] +#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] +unsafe impl SliceIndex for ops::RangeInclusive { + type Output = str; + #[inline] + fn get(self, slice: &str) -> Option<&Self::Output> { + if self.end == usize::MAX { None } else { self.into_slice_range().get(slice) } + } + #[inline] + fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> { + if self.end == usize::MAX { None } else { self.into_slice_range().get_mut(slice) } + } + #[inline] + unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output { + // SAFETY: the caller must uphold the safety contract for `get_unchecked`. + unsafe { self.into_slice_range().get_unchecked(slice) } + } + #[inline] + unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output { + // SAFETY: the caller must uphold the safety contract for `get_unchecked_mut`. + unsafe { self.into_slice_range().get_unchecked_mut(slice) } + } + #[inline] + fn index(self, slice: &str) -> &Self::Output { + if self.end == usize::MAX { + str_index_overflow_fail(); + } + self.into_slice_range().index(slice) + } + #[inline] + fn index_mut(self, slice: &mut str) -> &mut Self::Output { + if self.end == usize::MAX { + str_index_overflow_fail(); + } + self.into_slice_range().index_mut(slice) + } +} + /// Implements substring slicing with syntax `&self[..= end]` or `&mut /// self[..= end]`. /// diff --git a/library/core/tests/iter/adapters/chain.rs b/library/core/tests/iter/adapters/chain.rs index 175a1b638e1a1..5868171fe7165 100644 --- a/library/core/tests/iter/adapters/chain.rs +++ b/library/core/tests/iter/adapters/chain.rs @@ -210,7 +210,7 @@ fn test_chain_try_folds() { let c = || (0..10).chain(10..20); let f = &|acc, x| i32::checked_add(2 * acc, x); - assert_eq!(c().try_fold(7, f), (0..20).try_fold(7, f)); + assert_eq!(c().try_fold(7, f), (0..20).into_iter().try_fold(7, f)); assert_eq!(c().try_rfold(7, f), (0..20).rev().try_fold(7, f)); let mut iter = c(); @@ -229,11 +229,11 @@ fn test_chain_try_folds() { let mut iter = c(); iter.by_ref().rev().nth(14); // skip the last 15, ending in state Front - assert_eq!(iter.try_fold(7, f), (0..5).try_fold(7, f)); + assert_eq!(iter.try_fold(7, f), (0..5).into_iter().try_fold(7, f)); let mut iter = c(); iter.nth(14); // skip the first 15, ending in state Back - assert_eq!(iter.try_rfold(7, f), (15..20).try_rfold(7, f)); + assert_eq!(iter.try_rfold(7, f), (15..20).into_iter().try_rfold(7, f)); } #[test] diff --git a/library/core/tests/iter/adapters/filter.rs b/library/core/tests/iter/adapters/filter.rs index a2050d89d8564..d2ae7bacecf00 100644 --- a/library/core/tests/iter/adapters/filter.rs +++ b/library/core/tests/iter/adapters/filter.rs @@ -31,8 +31,8 @@ fn test_filter_try_folds() { 0 <= x && x < 10 } let f = &|acc, x| i32::checked_add(2 * acc, x); - assert_eq!((-10..20).filter(p).try_fold(7, f), (0..10).try_fold(7, f)); - assert_eq!((-10..20).filter(p).try_rfold(7, f), (0..10).try_rfold(7, f)); + assert_eq!((-10..20).filter(p).try_fold(7, f), (0..10).into_iter().try_fold(7, f)); + assert_eq!((-10..20).filter(p).try_rfold(7, f), (0..10).into_iter().try_rfold(7, f)); let mut iter = (0..40).filter(|&x| x % 2 == 1); assert_eq!(iter.try_fold(0, i8::checked_add), None); diff --git a/library/core/tests/iter/adapters/flat_map.rs b/library/core/tests/iter/adapters/flat_map.rs index ee945e69801b8..da5123707b4d1 100644 --- a/library/core/tests/iter/adapters/flat_map.rs +++ b/library/core/tests/iter/adapters/flat_map.rs @@ -42,12 +42,12 @@ fn test_iterator_flat_map_fold() { fn test_flat_map_try_folds() { let f = &|acc, x| i32::checked_add(acc * 2 / 3, x); let mr = &|x| (5 * x)..(5 * x + 5); - assert_eq!((0..10).flat_map(mr).try_fold(7, f), (0..50).try_fold(7, f)); - assert_eq!((0..10).flat_map(mr).try_rfold(7, f), (0..50).try_rfold(7, f)); + assert_eq!((0..10).flat_map(mr).try_fold(7, f), (0..50).into_iter().try_fold(7, f)); + assert_eq!((0..10).flat_map(mr).try_rfold(7, f), (0..50).into_iter().try_rfold(7, f)); let mut iter = (0..10).flat_map(mr); iter.next(); iter.next_back(); // have front and back iters in progress - assert_eq!(iter.try_rfold(7, f), (1..49).try_rfold(7, f)); + assert_eq!(iter.try_rfold(7, f), (1..49).into_iter().try_rfold(7, f)); let mut iter = (0..10).flat_map(|x| (4 * x)..(4 * x + 4)); assert_eq!(iter.try_fold(0, i8::checked_add), None); diff --git a/library/core/tests/iter/adapters/flatten.rs b/library/core/tests/iter/adapters/flatten.rs index 91809c9e5fd5d..a851c26734ed5 100644 --- a/library/core/tests/iter/adapters/flatten.rs +++ b/library/core/tests/iter/adapters/flatten.rs @@ -45,12 +45,12 @@ fn test_iterator_flatten_fold() { fn test_flatten_try_folds() { let f = &|acc, x| i32::checked_add(acc * 2 / 3, x); let mr = &|x| (5 * x)..(5 * x + 5); - assert_eq!((0..10).map(mr).flatten().try_fold(7, f), (0..50).try_fold(7, f)); - assert_eq!((0..10).map(mr).flatten().try_rfold(7, f), (0..50).try_rfold(7, f)); + assert_eq!((0..10).map(mr).flatten().try_fold(7, f), (0..50).into_iter().try_fold(7, f)); + assert_eq!((0..10).map(mr).flatten().try_rfold(7, f), (0..50).into_iter().try_rfold(7, f)); let mut iter = (0..10).map(mr).flatten(); iter.next(); iter.next_back(); // have front and back iters in progress - assert_eq!(iter.try_rfold(7, f), (1..49).try_rfold(7, f)); + assert_eq!(iter.try_rfold(7, f), (1..49).into_iter().try_rfold(7, f)); let mut iter = (0..10).map(|x| (4 * x)..(4 * x + 4)).flatten(); assert_eq!(iter.try_fold(0, i8::checked_add), None); diff --git a/library/core/tests/iter/adapters/fuse.rs b/library/core/tests/iter/adapters/fuse.rs index f41b379b3ac7f..87f0d5aed42ee 100644 --- a/library/core/tests/iter/adapters/fuse.rs +++ b/library/core/tests/iter/adapters/fuse.rs @@ -58,7 +58,7 @@ fn test_fuse_fold() { #[test] fn test_fuse() { - let mut it = 0..3; + let mut it = (0..3).into_iter(); assert_eq!(it.len(), 3); assert_eq!(it.next(), Some(0)); assert_eq!(it.len(), 2); diff --git a/library/core/tests/iter/adapters/map.rs b/library/core/tests/iter/adapters/map.rs index 77ce3819b322e..7686cb2515baa 100644 --- a/library/core/tests/iter/adapters/map.rs +++ b/library/core/tests/iter/adapters/map.rs @@ -3,8 +3,8 @@ use core::iter::*; #[test] fn test_map_try_folds() { let f = &|acc, x| i32::checked_add(2 * acc, x); - assert_eq!((0..10).map(|x| x + 3).try_fold(7, f), (3..13).try_fold(7, f)); - assert_eq!((0..10).map(|x| x + 3).try_rfold(7, f), (3..13).try_rfold(7, f)); + assert_eq!((0..10).map(|x| x + 3).try_fold(7, f), (3..13).into_iter().try_fold(7, f)); + assert_eq!((0..10).map(|x| x + 3).try_rfold(7, f), (3..13).into_iter().try_rfold(7, f)); let mut iter = (0..40).map(|x| x + 10); assert_eq!(iter.try_fold(0, i8::checked_add), None); diff --git a/library/core/tests/iter/adapters/mod.rs b/library/core/tests/iter/adapters/mod.rs index dedb4c0a9dd5f..3dcf19c8adb88 100644 --- a/library/core/tests/iter/adapters/mod.rs +++ b/library/core/tests/iter/adapters/mod.rs @@ -35,8 +35,11 @@ pub struct NonFused { } impl NonFused { - pub fn new(iter: I) -> Self { - Self { iter, done: false } + pub fn new(iter: IntoIter) -> Self + where + IntoIter: IntoIterator, + { + Self { iter: iter.into_iter(), done: false } } } diff --git a/library/core/tests/iter/adapters/peekable.rs b/library/core/tests/iter/adapters/peekable.rs index c1a1c29b609b7..bfd56c2a32d7d 100644 --- a/library/core/tests/iter/adapters/peekable.rs +++ b/library/core/tests/iter/adapters/peekable.rs @@ -220,16 +220,16 @@ fn test_iterator_peekable_remember_peek_none_3() { fn test_peek_try_folds() { let f = &|acc, x| i32::checked_add(2 * acc, x); - assert_eq!((1..20).peekable().try_fold(7, f), (1..20).try_fold(7, f)); - assert_eq!((1..20).peekable().try_rfold(7, f), (1..20).try_rfold(7, f)); + assert_eq!((1..20).peekable().try_fold(7, f), (1..20).into_iter().try_fold(7, f)); + assert_eq!((1..20).peekable().try_rfold(7, f), (1..20).into_iter().try_rfold(7, f)); let mut iter = (1..20).peekable(); assert_eq!(iter.peek(), Some(&1)); - assert_eq!(iter.try_fold(7, f), (1..20).try_fold(7, f)); + assert_eq!(iter.try_fold(7, f), (1..20).into_iter().try_fold(7, f)); let mut iter = (1..20).peekable(); assert_eq!(iter.peek(), Some(&1)); - assert_eq!(iter.try_rfold(7, f), (1..20).try_rfold(7, f)); + assert_eq!(iter.try_rfold(7, f), (1..20).into_iter().try_rfold(7, f)); let mut iter = [100, 20, 30, 40, 50, 60, 70].iter().cloned().peekable(); assert_eq!(iter.peek(), Some(&100)); diff --git a/library/core/tests/iter/adapters/skip.rs b/library/core/tests/iter/adapters/skip.rs index e3e88a84fadf6..ce921e71d0ed9 100644 --- a/library/core/tests/iter/adapters/skip.rs +++ b/library/core/tests/iter/adapters/skip.rs @@ -153,8 +153,8 @@ fn test_iterator_skip_fold() { #[test] fn test_skip_try_folds() { let f = &|acc, x| i32::checked_add(2 * acc, x); - assert_eq!((1..20).skip(9).try_fold(7, f), (10..20).try_fold(7, f)); - assert_eq!((1..20).skip(9).try_rfold(7, f), (10..20).try_rfold(7, f)); + assert_eq!((1..20).skip(9).try_fold(7, f), (10..20).into_iter().try_fold(7, f)); + assert_eq!((1..20).skip(9).try_rfold(7, f), (10..20).into_iter().try_rfold(7, f)); let mut iter = (0..30).skip(10); assert_eq!(iter.try_fold(0, i8::checked_add), None); diff --git a/library/core/tests/iter/adapters/skip_while.rs b/library/core/tests/iter/adapters/skip_while.rs index 929d4f6e64fd0..41a39ff46d0e9 100644 --- a/library/core/tests/iter/adapters/skip_while.rs +++ b/library/core/tests/iter/adapters/skip_while.rs @@ -39,10 +39,10 @@ fn test_skip_while_try_fold() { fn p(&x: &i32) -> bool { (x % 10) <= 5 } - assert_eq!((1..20).skip_while(p).try_fold(7, f), (6..20).try_fold(7, f)); + assert_eq!((1..20).skip_while(p).try_fold(7, f), (6..20).into_iter().try_fold(7, f)); let mut iter = (1..20).skip_while(p); assert_eq!(iter.nth(5), Some(11)); - assert_eq!(iter.try_fold(7, f), (12..20).try_fold(7, f)); + assert_eq!(iter.try_fold(7, f), (12..20).into_iter().try_fold(7, f)); let mut iter = (0..50).skip_while(|&x| (x % 20) < 15); assert_eq!(iter.try_fold(0, i8::checked_add), None); diff --git a/library/core/tests/iter/adapters/take.rs b/library/core/tests/iter/adapters/take.rs index 3cad47c06de03..754fcdab31a44 100644 --- a/library/core/tests/iter/adapters/take.rs +++ b/library/core/tests/iter/adapters/take.rs @@ -126,8 +126,8 @@ fn test_iterator_take_short() { #[test] fn test_take_try_folds() { let f = &|acc, x| i32::checked_add(2 * acc, x); - assert_eq!((10..30).take(10).try_fold(7, f), (10..20).try_fold(7, f)); - assert_eq!((10..30).take(10).try_rfold(7, f), (10..20).try_rfold(7, f)); + assert_eq!((10..30).take(10).try_fold(7, f), (10..20).into_iter().try_fold(7, f)); + assert_eq!((10..30).take(10).try_rfold(7, f), (10..20).into_iter().try_rfold(7, f)); let mut iter = (10..30).take(20); assert_eq!(iter.try_fold(0, i8::checked_add), None); @@ -150,20 +150,20 @@ fn test_take_try_folds() { #[test] fn test_byref_take_consumed_items() { - let mut inner = 10..90; + let mut inner = (10..90).into_iter(); let mut count = 0; inner.by_ref().take(0).for_each(|_| count += 1); assert_eq!(count, 0); - assert_eq!(inner, 10..90); + assert_eq!(*inner.inner(), 10..90); let mut count = 0; inner.by_ref().take(10).for_each(|_| count += 1); assert_eq!(count, 10); - assert_eq!(inner, 20..90); + assert_eq!(*inner.inner(), 20..90); let mut count = 0; inner.by_ref().take(100).for_each(|_| count += 1); assert_eq!(count, 70); - assert_eq!(inner, 90..90); + assert_eq!(*inner.inner(), 90..90); } diff --git a/library/core/tests/iter/adapters/take_while.rs b/library/core/tests/iter/adapters/take_while.rs index 6f1ebab29b31c..7fa6d8da237fb 100644 --- a/library/core/tests/iter/adapters/take_while.rs +++ b/library/core/tests/iter/adapters/take_while.rs @@ -16,7 +16,7 @@ fn test_iterator_take_while() { #[test] fn test_take_while_folds() { let f = &|acc, x| i32::checked_add(2 * acc, x); - assert_eq!((1..20).take_while(|&x| x != 10).try_fold(7, f), (1..10).try_fold(7, f)); + assert_eq!((1..20).take_while(|&x| x != 10).try_fold(7, f), (1..10).into_iter().try_fold(7, f)); let mut iter = (1..20).take_while(|&x| x != 10); assert_eq!(iter.try_fold(0, |x, y| Some(x + y)), Some((1..10).sum())); assert_eq!(iter.next(), None, "flag should be set"); diff --git a/library/core/tests/iter/mod.rs b/library/core/tests/iter/mod.rs index 770b6f7601fa2..90c1d10bb69a4 100644 --- a/library/core/tests/iter/mod.rs +++ b/library/core/tests/iter/mod.rs @@ -78,7 +78,7 @@ fn test_monad_laws_right_identity() { #[test] fn test_monad_laws_associativity() { fn f(x: usize) -> impl Iterator { - 0..x + (0..x).into_iter() } fn g(x: usize) -> impl Iterator { (0..x).rev() diff --git a/library/core/tests/iter/range.rs b/library/core/tests/iter/range.rs index 5b87d6c1fa0e3..2af1c4299085e 100644 --- a/library/core/tests/iter/range.rs +++ b/library/core/tests/iter/range.rs @@ -12,16 +12,16 @@ fn test_range() { assert_eq!((200..200).count(), 0); assert_eq!((200..200).rev().count(), 0); - assert_eq!((0..100).size_hint(), (100, Some(100))); + assert_eq!((0..100).into_iter().into_iter().size_hint(), (100, Some(100))); // this test is only meaningful when sizeof usize < sizeof u64 - assert_eq!((usize::MAX - 1..usize::MAX).size_hint(), (1, Some(1))); - assert_eq!((-10..-1).size_hint(), (9, Some(9))); - assert_eq!((-1..-10).size_hint(), (0, Some(0))); + assert_eq!((usize::MAX - 1..usize::MAX).into_iter().into_iter().size_hint(), (1, Some(1))); + assert_eq!((-10..-1).into_iter().into_iter().size_hint(), (9, Some(9))); + assert_eq!((-1..-10).into_iter().into_iter().size_hint(), (0, Some(0))); - assert_eq!((-70..58).size_hint(), (128, Some(128))); - assert_eq!((-128..127).size_hint(), (255, Some(255))); + assert_eq!((-70..58).into_iter().into_iter().size_hint(), (128, Some(128))); + assert_eq!((-128..127).into_iter().into_iter().size_hint(), (255, Some(255))); assert_eq!( - (-2..isize::MAX).size_hint(), + (-2..isize::MAX).into_iter().into_iter().size_hint(), (isize::MAX as usize + 2, Some(isize::MAX as usize + 2)) ); } @@ -35,9 +35,9 @@ fn test_char_range() { assert!((from..=to).rev().eq((from as u32..=to as u32).filter_map(char::from_u32).rev())); assert_eq!(('\u{D7FF}'..='\u{E000}').count(), 2); - assert_eq!(('\u{D7FF}'..='\u{E000}').size_hint(), (2, Some(2))); + assert_eq!(('\u{D7FF}'..='\u{E000}').into_iter().size_hint(), (2, Some(2))); assert_eq!(('\u{D7FF}'..'\u{E000}').count(), 1); - assert_eq!(('\u{D7FF}'..'\u{E000}').size_hint(), (1, Some(1))); + assert_eq!(('\u{D7FF}'..'\u{E000}').into_iter().size_hint(), (1, Some(1))); } #[test] @@ -48,150 +48,150 @@ fn test_ascii_char_range() { assert!((from..=to).rev().eq((from as u8..=to as u8).filter_map(AsciiChar::from_u8).rev())); assert_eq!((AsciiChar::CapitalA..=AsciiChar::CapitalZ).count(), 26); - assert_eq!((AsciiChar::CapitalA..=AsciiChar::CapitalZ).size_hint(), (26, Some(26))); + assert_eq!((AsciiChar::CapitalA..=AsciiChar::CapitalZ).into_iter().size_hint(), (26, Some(26))); assert_eq!((AsciiChar::SmallA..=AsciiChar::SmallZ).count(), 26); - assert_eq!((AsciiChar::SmallA..=AsciiChar::SmallZ).size_hint(), (26, Some(26))); + assert_eq!((AsciiChar::SmallA..=AsciiChar::SmallZ).into_iter().size_hint(), (26, Some(26))); assert_eq!((AsciiChar::Digit0..=AsciiChar::Digit9).count(), 10); - assert_eq!((AsciiChar::Digit0..=AsciiChar::Digit9).size_hint(), (10, Some(10))); + assert_eq!((AsciiChar::Digit0..=AsciiChar::Digit9).into_iter().size_hint(), (10, Some(10))); } #[test] fn test_range_exhaustion() { - let mut r = 10..10; + let mut r = (10..10).into_iter(); assert!(r.is_empty()); assert_eq!(r.next(), None); assert_eq!(r.next_back(), None); - assert_eq!(r, 10..10); + assert_eq!(*r.inner(), 10..10); - let mut r = 10..12; + let mut r = (10..12).into_iter(); assert_eq!(r.next(), Some(10)); assert_eq!(r.next(), Some(11)); assert!(r.is_empty()); - assert_eq!(r, 12..12); + assert_eq!(*r.inner(), 12..12); assert_eq!(r.next(), None); - let mut r = 10..12; + let mut r = (10..12).into_iter(); assert_eq!(r.next_back(), Some(11)); assert_eq!(r.next_back(), Some(10)); assert!(r.is_empty()); - assert_eq!(r, 10..10); + assert_eq!(*r.inner(), 10..10); assert_eq!(r.next_back(), None); - let mut r = 100..10; + let mut r = (100..10).into_iter(); assert!(r.is_empty()); assert_eq!(r.next(), None); assert_eq!(r.next_back(), None); - assert_eq!(r, 100..10); + assert_eq!(*r.inner(), 100..10); } #[test] fn test_range_inclusive_exhaustion() { - let mut r = 10..=10; + let mut r = (10_u16..=10).into_iter(); assert_eq!(r.next(), Some(10)); assert!(r.is_empty()); assert_eq!(r.next(), None); assert_eq!(r.next(), None); - assert_eq!(*r.start(), 10); - assert_eq!(*r.end(), 10); - assert_ne!(r, 10..=10); + assert_eq!(*r.inner().start(), 10); + assert_eq!(*r.inner().end(), 10); + assert_ne!(*r.inner(), 10..=10); - let mut r = 10..=10; + let mut r = (10_u16..=10).into_iter(); assert_eq!(r.next_back(), Some(10)); assert!(r.is_empty()); assert_eq!(r.next_back(), None); - assert_eq!(*r.start(), 10); - assert_eq!(*r.end(), 10); - assert_ne!(r, 10..=10); + assert_eq!(*r.inner().start(), 10); + assert_eq!(*r.inner().end(), 10); + assert_ne!(*r.inner(), 10..=10); - let mut r = 10..=12; + let mut r = (10_u16..=12).into_iter(); assert_eq!(r.next(), Some(10)); assert_eq!(r.next(), Some(11)); assert_eq!(r.next(), Some(12)); assert!(r.is_empty()); assert_eq!(r.next(), None); - let mut r = 10..=12; + let mut r = (10_u16..=12).into_iter(); assert_eq!(r.next_back(), Some(12)); assert_eq!(r.next_back(), Some(11)); assert_eq!(r.next_back(), Some(10)); assert!(r.is_empty()); assert_eq!(r.next_back(), None); - let mut r = 10..=12; + let mut r = (10_u16..=12).into_iter(); assert_eq!(r.nth(2), Some(12)); assert!(r.is_empty()); assert_eq!(r.next(), None); - let mut r = 10..=12; + let mut r = (10_u16..=12).into_iter(); assert_eq!(r.nth(5), None); assert!(r.is_empty()); assert_eq!(r.next(), None); - let mut r = 100..=10; + let mut r = (100_u16..=10).into_iter(); assert_eq!(r.next(), None); assert!(r.is_empty()); assert_eq!(r.next(), None); assert_eq!(r.next(), None); - assert_eq!(r, 100..=10); + assert_eq!(*r.inner(), 100..=10); - let mut r = 100..=10; + let mut r = (100_u16..=10).into_iter(); assert_eq!(r.next_back(), None); assert!(r.is_empty()); assert_eq!(r.next_back(), None); assert_eq!(r.next_back(), None); - assert_eq!(r, 100..=10); + assert_eq!(*r.inner(), 100..=10); } #[test] fn test_range_nth() { - assert_eq!((10..15).nth(0), Some(10)); - assert_eq!((10..15).nth(1), Some(11)); - assert_eq!((10..15).nth(4), Some(14)); - assert_eq!((10..15).nth(5), None); + assert_eq!((10..15).into_iter().nth(0), Some(10)); + assert_eq!((10..15).into_iter().nth(1), Some(11)); + assert_eq!((10..15).into_iter().nth(4), Some(14)); + assert_eq!((10..15).into_iter().nth(5), None); - let mut r = 10..20; + let mut r = (10..20).into_iter(); assert_eq!(r.nth(2), Some(12)); - assert_eq!(r, 13..20); + assert_eq!(*r.inner(), 13..20); assert_eq!(r.nth(2), Some(15)); - assert_eq!(r, 16..20); + assert_eq!(*r.inner(), 16..20); assert_eq!(r.nth(10), None); - assert_eq!(r, 20..20); + assert_eq!(*r.inner(), 20..20); } #[test] fn test_range_nth_back() { - assert_eq!((10..15).nth_back(0), Some(14)); - assert_eq!((10..15).nth_back(1), Some(13)); - assert_eq!((10..15).nth_back(4), Some(10)); - assert_eq!((10..15).nth_back(5), None); - assert_eq!((-120..80_i8).nth_back(199), Some(-120)); + assert_eq!((10..15).into_iter().nth_back(0), Some(14)); + assert_eq!((10..15).into_iter().nth_back(1), Some(13)); + assert_eq!((10..15).into_iter().nth_back(4), Some(10)); + assert_eq!((10..15).into_iter().nth_back(5), None); + assert_eq!((-120..80_i8).into_iter().nth_back(199), Some(-120)); - let mut r = 10..20; + let mut r = (10..20).into_iter(); assert_eq!(r.nth_back(2), Some(17)); - assert_eq!(r, 10..17); + assert_eq!(*r.inner(), 10..17); assert_eq!(r.nth_back(2), Some(14)); - assert_eq!(r, 10..14); + assert_eq!(*r.inner(), 10..14); assert_eq!(r.nth_back(10), None); - assert_eq!(r, 10..10); + assert_eq!(*r.inner(), 10..10); } #[test] fn test_range_from_nth() { - assert_eq!((10..).nth(0), Some(10)); - assert_eq!((10..).nth(1), Some(11)); - assert_eq!((10..).nth(4), Some(14)); + assert_eq!((10..).into_iter().nth(0), Some(10)); + assert_eq!((10..).into_iter().nth(1), Some(11)); + assert_eq!((10..).into_iter().nth(4), Some(14)); - let mut r = 10..; + let mut r = (10..).into_iter(); assert_eq!(r.nth(2), Some(12)); - assert_eq!(r, 13..); + assert_eq!(*r.inner(), 13..); assert_eq!(r.nth(2), Some(15)); - assert_eq!(r, 16..); + assert_eq!(*r.inner(), 16..); assert_eq!(r.nth(10), Some(26)); - assert_eq!(r, 27..); + assert_eq!(*r.inner(), 27..); - assert_eq!((0..).size_hint(), (usize::MAX, None)); + assert_eq!((0..).into_iter().size_hint(), (usize::MAX, None)); } #[test] @@ -202,9 +202,9 @@ fn test_range_from_take() { assert_eq!(it.next(), Some(2)); assert_eq!(it.next(), None); is_trusted_len((0..).take(3)); - assert_eq!((0..).take(3).size_hint(), (3, Some(3))); - assert_eq!((0..).take(0).size_hint(), (0, Some(0))); - assert_eq!((0..).take(usize::MAX).size_hint(), (usize::MAX, Some(usize::MAX))); + assert_eq!((0..).take(3).into_iter().size_hint(), (3, Some(3))); + assert_eq!((0..).take(0).into_iter().size_hint(), (0, Some(0))); + assert_eq!((0..).take(usize::MAX).into_iter().size_hint(), (usize::MAX, Some(usize::MAX))); } #[test] @@ -215,48 +215,48 @@ fn test_range_from_take_collect() { #[test] fn test_range_inclusive_nth() { - assert_eq!((10..=15).nth(0), Some(10)); - assert_eq!((10..=15).nth(1), Some(11)); - assert_eq!((10..=15).nth(5), Some(15)); - assert_eq!((10..=15).nth(6), None); + assert_eq!((10..=15).into_iter().nth(0), Some(10)); + assert_eq!((10..=15).into_iter().nth(1), Some(11)); + assert_eq!((10..=15).into_iter().nth(5), Some(15)); + assert_eq!((10..=15).into_iter().nth(6), None); - let mut exhausted_via_next = 10_u8..=20; + let mut exhausted_via_next = (10_u8..=20).into_iter(); while exhausted_via_next.next().is_some() {} - let mut r = 10_u8..=20; + let mut r = (10_u8..=20).into_iter(); assert_eq!(r.nth(2), Some(12)); - assert_eq!(r, 13..=20); + assert_eq!(*r.inner(), 13..=20); assert_eq!(r.nth(2), Some(15)); - assert_eq!(r, 16..=20); + assert_eq!(*r.inner(), 16..=20); assert_eq!(r.is_empty(), false); assert_eq!(ExactSizeIterator::is_empty(&r), false); assert_eq!(r.nth(10), None); assert_eq!(r.is_empty(), true); - assert_eq!(r, exhausted_via_next); + assert_eq!(*r.inner(), *exhausted_via_next.inner()); assert_eq!(ExactSizeIterator::is_empty(&r), true); } #[test] fn test_range_inclusive_nth_back() { - assert_eq!((10..=15).nth_back(0), Some(15)); - assert_eq!((10..=15).nth_back(1), Some(14)); - assert_eq!((10..=15).nth_back(5), Some(10)); - assert_eq!((10..=15).nth_back(6), None); - assert_eq!((-120..=80_i8).nth_back(200), Some(-120)); + assert_eq!((10..=15).into_iter().nth_back(0), Some(15)); + assert_eq!((10..=15).into_iter().nth_back(1), Some(14)); + assert_eq!((10..=15).into_iter().nth_back(5), Some(10)); + assert_eq!((10..=15).into_iter().nth_back(6), None); + assert_eq!((-120..=80_i8).into_iter().nth_back(200), Some(-120)); - let mut exhausted_via_next_back = 10_u8..=20; + let mut exhausted_via_next_back = (10_u8..=20).into_iter(); while exhausted_via_next_back.next_back().is_some() {} - let mut r = 10_u8..=20; + let mut r = (10_u8..=20).into_iter(); assert_eq!(r.nth_back(2), Some(18)); - assert_eq!(r, 10..=17); + assert_eq!(*r.inner(), 10..=17); assert_eq!(r.nth_back(2), Some(15)); - assert_eq!(r, 10..=14); + assert_eq!(*r.inner(), 10..=14); assert_eq!(r.is_empty(), false); assert_eq!(ExactSizeIterator::is_empty(&r), false); assert_eq!(r.nth_back(10), None); assert_eq!(r.is_empty(), true); - assert_eq!(r, exhausted_via_next_back); + assert_eq!(*r.inner(), *exhausted_via_next_back.inner()); assert_eq!(ExactSizeIterator::is_empty(&r), true); } @@ -289,21 +289,21 @@ fn test_range_step() { assert_eq!((200..-5).step_by(1).collect::>(), []); assert_eq!((200..200).step_by(1).collect::>(), []); - assert_eq!((0..20).step_by(1).size_hint(), (20, Some(20))); - assert_eq!((0..20).step_by(21).size_hint(), (1, Some(1))); - assert_eq!((0..20).step_by(5).size_hint(), (4, Some(4))); - assert_eq!((1..21).rev().step_by(5).size_hint(), (4, Some(4))); - assert_eq!((1..21).rev().step_by(6).size_hint(), (4, Some(4))); - assert_eq!((20..-5).step_by(1).size_hint(), (0, Some(0))); - assert_eq!((20..20).step_by(1).size_hint(), (0, Some(0))); - assert_eq!((i8::MIN..i8::MAX).step_by(-(i8::MIN as i32) as usize).size_hint(), (2, Some(2))); - assert_eq!((i16::MIN..i16::MAX).step_by(i16::MAX as usize).size_hint(), (3, Some(3))); - assert_eq!((isize::MIN..isize::MAX).step_by(1).size_hint(), (usize::MAX, Some(usize::MAX))); + assert_eq!((0..20).step_by(1).into_iter().size_hint(), (20, Some(20))); + assert_eq!((0..20).step_by(21).into_iter().size_hint(), (1, Some(1))); + assert_eq!((0..20).step_by(5).into_iter().size_hint(), (4, Some(4))); + assert_eq!((1..21).rev().step_by(5).into_iter().size_hint(), (4, Some(4))); + assert_eq!((1..21).rev().step_by(6).into_iter().size_hint(), (4, Some(4))); + assert_eq!((20..-5).step_by(1).into_iter().size_hint(), (0, Some(0))); + assert_eq!((20..20).step_by(1).into_iter().size_hint(), (0, Some(0))); + assert_eq!((i8::MIN..i8::MAX).step_by(-(i8::MIN as i32) as usize).into_iter().size_hint(), (2, Some(2))); + assert_eq!((i16::MIN..i16::MAX).step_by(i16::MAX as usize).into_iter().size_hint(), (3, Some(3))); + assert_eq!((isize::MIN..isize::MAX).step_by(1).into_iter().size_hint(), (usize::MAX, Some(usize::MAX))); } #[test] fn test_range_advance_by() { - let mut r = 0..usize::MAX; + let mut r = (0..usize::MAX).into_iter(); assert_eq!(Ok(()), r.advance_by(0)); assert_eq!(Ok(()), r.advance_back_by(0)); @@ -312,19 +312,19 @@ fn test_range_advance_by() { assert_eq!(Ok(()), r.advance_by(1)); assert_eq!(Ok(()), r.advance_back_by(1)); - assert_eq!((r.start, r.end), (1, usize::MAX - 1)); + assert_eq!((r.inner().start, r.inner().end), (1, usize::MAX - 1)); assert_eq!(Err(NonZeroUsize::new(2).unwrap()), r.advance_by(usize::MAX)); assert_eq!(Ok(()), r.advance_by(0)); assert_eq!(Ok(()), r.advance_back_by(0)); - let mut r = 0u128..u128::MAX; + let mut r = (0u128..u128::MAX).into_iter(); assert_eq!(Ok(()), r.advance_by(usize::MAX)); assert_eq!(Ok(()), r.advance_back_by(usize::MAX)); - assert_eq!((r.start, r.end), (0u128 + usize::MAX as u128, u128::MAX - usize::MAX as u128)); + assert_eq!((r.inner().start, r.inner().end), (0u128 + usize::MAX as u128, u128::MAX - usize::MAX as u128)); } #[test] @@ -351,14 +351,14 @@ fn test_range_inclusive_last_max() { assert_eq!((0..=20).last(), Some(20)); assert_eq!((-20..=0).last(), Some(0)); assert_eq!((5..=5).last(), Some(5)); - let mut r = 10..=10; + let mut r = (10..=10).into_iter(); r.next(); assert_eq!(r.last(), None); assert_eq!((0..=20).max(), Some(20)); assert_eq!((-20..=0).max(), Some(0)); assert_eq!((5..=5).max(), Some(5)); - let mut r = 10..=10; + let mut r = (10..=10).into_iter(); r.next(); assert_eq!(r.max(), None); } @@ -375,7 +375,7 @@ fn test_range_inclusive_min() { assert_eq!((0..=20).min(), Some(0)); assert_eq!((-20..=0).min(), Some(-20)); assert_eq!((5..=5).min(), Some(5)); - let mut r = 10..=10; + let mut r = (10..=10).into_iter(); r.next(); assert_eq!(r.min(), None); } @@ -385,33 +385,33 @@ fn test_range_inclusive_folds() { assert_eq!((1..=10).sum::(), 55); assert_eq!((1..=10).rev().sum::(), 55); - let mut it = 44..=50; + let mut it = (44..=50).into_iter(); assert_eq!(it.try_fold(0, i8::checked_add), None); - assert_eq!(it, 47..=50); + assert_eq!(*it.inner(), 47..=50); assert_eq!(it.try_fold(0, i8::checked_add), None); - assert_eq!(it, 50..=50); + assert_eq!(*it.inner(), 50..=50); assert_eq!(it.try_fold(0, i8::checked_add), Some(50)); assert!(it.is_empty()); assert_eq!(it.try_fold(0, i8::checked_add), Some(0)); assert!(it.is_empty()); - let mut it = 40..=47; + let mut it = (40..=47).into_iter(); assert_eq!(it.try_rfold(0, i8::checked_add), None); - assert_eq!(it, 40..=44); + assert_eq!(*it.inner(), 40..=44); assert_eq!(it.try_rfold(0, i8::checked_add), None); - assert_eq!(it, 40..=41); + assert_eq!(*it.inner(), 40..=41); assert_eq!(it.try_rfold(0, i8::checked_add), Some(81)); assert!(it.is_empty()); assert_eq!(it.try_rfold(0, i8::checked_add), Some(0)); assert!(it.is_empty()); - let mut it = 10..=20; + let mut it = (10_u16..=20).into_iter(); assert_eq!(it.try_fold(0, |a, b| Some(a + b)), Some(165)); assert!(it.is_empty()); assert_eq!(it.try_fold(0, |a, b| Some(a + b)), Some(0)); assert!(it.is_empty()); - let mut it = 10..=20; + let mut it = (10_u16..=20).into_iter(); assert_eq!(it.try_rfold(0, |a, b| Some(a + b)), Some(165)); assert!(it.is_empty()); assert_eq!(it.try_rfold(0, |a, b| Some(a + b)), Some(0)); @@ -420,58 +420,58 @@ fn test_range_inclusive_folds() { #[test] fn test_range_size_hint() { - assert_eq!((0..0usize).size_hint(), (0, Some(0))); - assert_eq!((0..100usize).size_hint(), (100, Some(100))); - assert_eq!((0..usize::MAX).size_hint(), (usize::MAX, Some(usize::MAX))); + assert_eq!((0..0usize).into_iter().size_hint(), (0, Some(0))); + assert_eq!((0..100usize).into_iter().size_hint(), (100, Some(100))); + assert_eq!((0..usize::MAX).into_iter().size_hint(), (usize::MAX, Some(usize::MAX))); let umax = u128::try_from(usize::MAX).unwrap(); - assert_eq!((0..0u128).size_hint(), (0, Some(0))); - assert_eq!((0..100u128).size_hint(), (100, Some(100))); - assert_eq!((0..umax).size_hint(), (usize::MAX, Some(usize::MAX))); - assert_eq!((0..umax + 1).size_hint(), (usize::MAX, None)); + assert_eq!((0..0u128).into_iter().size_hint(), (0, Some(0))); + assert_eq!((0..100u128).into_iter().size_hint(), (100, Some(100))); + assert_eq!((0..umax).into_iter().size_hint(), (usize::MAX, Some(usize::MAX))); + assert_eq!((0..umax + 1).into_iter().size_hint(), (usize::MAX, None)); - assert_eq!((0..0isize).size_hint(), (0, Some(0))); - assert_eq!((-100..100isize).size_hint(), (200, Some(200))); - assert_eq!((isize::MIN..isize::MAX).size_hint(), (usize::MAX, Some(usize::MAX))); + assert_eq!((0..0isize).into_iter().size_hint(), (0, Some(0))); + assert_eq!((-100..100isize).into_iter().size_hint(), (200, Some(200))); + assert_eq!((isize::MIN..isize::MAX).into_iter().size_hint(), (usize::MAX, Some(usize::MAX))); let imin = i128::try_from(isize::MIN).unwrap(); let imax = i128::try_from(isize::MAX).unwrap(); - assert_eq!((0..0i128).size_hint(), (0, Some(0))); - assert_eq!((-100..100i128).size_hint(), (200, Some(200))); - assert_eq!((imin..imax).size_hint(), (usize::MAX, Some(usize::MAX))); - assert_eq!((imin..imax + 1).size_hint(), (usize::MAX, None)); + assert_eq!((0..0i128).into_iter().size_hint(), (0, Some(0))); + assert_eq!((-100..100i128).into_iter().size_hint(), (200, Some(200))); + assert_eq!((imin..imax).into_iter().size_hint(), (usize::MAX, Some(usize::MAX))); + assert_eq!((imin..imax + 1).into_iter().size_hint(), (usize::MAX, None)); } #[test] fn test_range_inclusive_size_hint() { - assert_eq!((1..=0usize).size_hint(), (0, Some(0))); - assert_eq!((0..=0usize).size_hint(), (1, Some(1))); - assert_eq!((0..=100usize).size_hint(), (101, Some(101))); - assert_eq!((0..=usize::MAX - 1).size_hint(), (usize::MAX, Some(usize::MAX))); - assert_eq!((0..=usize::MAX).size_hint(), (usize::MAX, None)); + assert_eq!((1..=0usize).into_iter().size_hint(), (0, Some(0))); + assert_eq!((0..=0usize).into_iter().size_hint(), (1, Some(1))); + assert_eq!((0..=100usize).into_iter().size_hint(), (101, Some(101))); + assert_eq!((0..=usize::MAX - 1).into_iter().size_hint(), (usize::MAX, Some(usize::MAX))); + assert_eq!((0..=usize::MAX).into_iter().size_hint(), (usize::MAX, None)); let umax = u128::try_from(usize::MAX).unwrap(); - assert_eq!((1..=0u128).size_hint(), (0, Some(0))); - assert_eq!((0..=0u128).size_hint(), (1, Some(1))); - assert_eq!((0..=100u128).size_hint(), (101, Some(101))); - assert_eq!((0..=umax - 1).size_hint(), (usize::MAX, Some(usize::MAX))); - assert_eq!((0..=umax).size_hint(), (usize::MAX, None)); - assert_eq!((0..=umax + 1).size_hint(), (usize::MAX, None)); - - assert_eq!((0..=-1isize).size_hint(), (0, Some(0))); - assert_eq!((0..=0isize).size_hint(), (1, Some(1))); - assert_eq!((-100..=100isize).size_hint(), (201, Some(201))); - assert_eq!((isize::MIN..=isize::MAX - 1).size_hint(), (usize::MAX, Some(usize::MAX))); - assert_eq!((isize::MIN..=isize::MAX).size_hint(), (usize::MAX, None)); + assert_eq!((1..=0u128).into_iter().size_hint(), (0, Some(0))); + assert_eq!((0..=0u128).into_iter().size_hint(), (1, Some(1))); + assert_eq!((0..=100u128).into_iter().size_hint(), (101, Some(101))); + assert_eq!((0..=umax - 1).into_iter().size_hint(), (usize::MAX, Some(usize::MAX))); + assert_eq!((0..=umax).into_iter().size_hint(), (usize::MAX, None)); + assert_eq!((0..=umax + 1).into_iter().size_hint(), (usize::MAX, None)); + + assert_eq!((0..=-1isize).into_iter().size_hint(), (0, Some(0))); + assert_eq!((0..=0isize).into_iter().size_hint(), (1, Some(1))); + assert_eq!((-100..=100isize).into_iter().size_hint(), (201, Some(201))); + assert_eq!((isize::MIN..=isize::MAX - 1).into_iter().size_hint(), (usize::MAX, Some(usize::MAX))); + assert_eq!((isize::MIN..=isize::MAX).into_iter().size_hint(), (usize::MAX, None)); let imin = i128::try_from(isize::MIN).unwrap(); let imax = i128::try_from(isize::MAX).unwrap(); - assert_eq!((0..=-1i128).size_hint(), (0, Some(0))); - assert_eq!((0..=0i128).size_hint(), (1, Some(1))); - assert_eq!((-100..=100i128).size_hint(), (201, Some(201))); - assert_eq!((imin..=imax - 1).size_hint(), (usize::MAX, Some(usize::MAX))); - assert_eq!((imin..=imax).size_hint(), (usize::MAX, None)); - assert_eq!((imin..=imax + 1).size_hint(), (usize::MAX, None)); + assert_eq!((0..=-1i128).into_iter().size_hint(), (0, Some(0))); + assert_eq!((0..=0i128).into_iter().size_hint(), (1, Some(1))); + assert_eq!((-100..=100i128).into_iter().size_hint(), (201, Some(201))); + assert_eq!((imin..=imax - 1).into_iter().size_hint(), (usize::MAX, Some(usize::MAX))); + assert_eq!((imin..=imax).into_iter().size_hint(), (usize::MAX, None)); + assert_eq!((imin..=imax + 1).into_iter().size_hint(), (usize::MAX, None)); } #[test] diff --git a/library/core/tests/iter/traits/double_ended.rs b/library/core/tests/iter/traits/double_ended.rs index 00ef4a6e6a987..57e2ffd8c543f 100644 --- a/library/core/tests/iter/traits/double_ended.rs +++ b/library/core/tests/iter/traits/double_ended.rs @@ -41,8 +41,8 @@ fn test_rev() { #[test] fn test_rev_try_folds() { let f = &|acc, x| i32::checked_add(2 * acc, x); - assert_eq!((1..10).rev().try_fold(7, f), (1..10).try_rfold(7, f)); - assert_eq!((1..10).rev().try_rfold(7, f), (1..10).try_fold(7, f)); + assert_eq!((1..10).rev().try_fold(7, f), (1..10).into_iter().try_rfold(7, f)); + assert_eq!((1..10).rev().try_rfold(7, f), (1..10).into_iter().try_fold(7, f)); let a = [10, 20, 30, 40, 100, 60, 70, 80, 90]; let mut iter = a.iter().rev(); diff --git a/library/core/tests/iter/traits/iterator.rs b/library/core/tests/iter/traits/iterator.rs index 995bbf0e26156..385aed41d5782 100644 --- a/library/core/tests/iter/traits/iterator.rs +++ b/library/core/tests/iter/traits/iterator.rs @@ -222,7 +222,7 @@ fn test_iterator_size_hint() { let v2 = &[10, 11, 12]; let vi = v.iter(); - assert_eq!((0..).size_hint(), (usize::MAX, None)); + assert_eq!((0..).into_iter().size_hint(), (usize::MAX, None)); assert_eq!(c.size_hint(), (usize::MAX, None)); assert_eq!(vi.clone().size_hint(), (10, Some(10))); @@ -363,7 +363,7 @@ fn test_min_by() { #[test] fn test_by_ref() { - let mut xs = 0..10; + let mut xs = (0..10).into_iter(); // sum the first five values let partial_sum = xs.by_ref().take(5).fold(0, |a, b| a + b); assert_eq!(partial_sum, 10); @@ -608,7 +608,7 @@ fn iter_try_collect_uses_try_fold_not_next() { #[test] fn test_next_chunk() { - let mut it = 0..12; + let mut it = (0..12).into_iter(); assert_eq!(it.next_chunk().unwrap(), [0, 1, 2, 3]); assert_eq!(it.next_chunk().unwrap(), []); assert_eq!(it.next_chunk().unwrap(), [4, 5, 6, 7, 8, 9]); diff --git a/library/core/tests/ops.rs b/library/core/tests/ops.rs index 0c81cba35b3df..0a2a55fa09b13 100644 --- a/library/core/tests/ops.rs +++ b/library/core/tests/ops.rs @@ -43,21 +43,21 @@ fn test_full_range() { #[test] fn test_range_inclusive() { - let mut r = RangeInclusive::new(1i8, 2); + let mut r = RangeInclusive::new(1i8, 2).into_iter(); assert_eq!(r.next(), Some(1)); assert_eq!(r.next(), Some(2)); assert_eq!(r.next(), None); - r = RangeInclusive::new(127i8, 127); + r = RangeInclusive::new(127i8, 127).into_iter(); assert_eq!(r.next(), Some(127)); assert_eq!(r.next(), None); - r = RangeInclusive::new(-128i8, -128); + r = RangeInclusive::new(-128i8, -128).into_iter(); assert_eq!(r.next_back(), Some(-128)); assert_eq!(r.next_back(), None); // degenerate - r = RangeInclusive::new(1, -1); + r = RangeInclusive::new(1, -1).into_iter(); assert_eq!(r.size_hint(), (0, Some(0))); assert_eq!(r.next(), None); } diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs index 666452ead3f5a..0c2d5cae7276a 100644 --- a/library/core/tests/slice.rs +++ b/library/core/tests/slice.rs @@ -1627,17 +1627,17 @@ mod slice_index { good: data[0..=5] == [0, 1, 2, 3, 4, 5]; good: data[{ - let mut iter = 0..=5; + let mut iter = (0..=5).into_iter(); iter.by_ref().count(); // exhaust it - iter + iter.inner().clone() }] == []; // 0..=6 is out of range before exhaustion, so it // stands to reason that it still would be after. bad: data[{ - let mut iter = 0..=6; + let mut iter = (0..=6).into_iter(); iter.by_ref().count(); // exhaust it - iter + iter.inner().clone() }]; message: "out of range"; } From f117f4cf18a892f6383e5b53d5f68e234c128fe4 Mon Sep 17 00:00:00 2001 From: Peter Jaszkowiak Date: Tue, 5 Dec 2023 21:27:12 -0700 Subject: [PATCH 2/6] fix compiler --- compiler/rustc_borrowck/src/borrow_set.rs | 2 +- compiler/rustc_borrowck/src/region_infer/mod.rs | 2 +- .../src/deriving/cmp/partial_ord.rs | 2 +- compiler/rustc_const_eval/src/interpret/projection.rs | 10 ++++++++-- compiler/rustc_metadata/src/rmeta/decoder.rs | 4 ++-- .../src/mir/interpret/allocation/init_mask.rs | 2 +- compiler/rustc_parse/src/parser/diagnostics.rs | 2 +- compiler/rustc_parse/src/parser/mod.rs | 2 +- 8 files changed, 16 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_borrowck/src/borrow_set.rs b/compiler/rustc_borrowck/src/borrow_set.rs index 948af03953718..0c333f857d62f 100644 --- a/compiler/rustc_borrowck/src/borrow_set.rs +++ b/compiler/rustc_borrowck/src/borrow_set.rs @@ -161,7 +161,7 @@ impl<'tcx> BorrowSet<'tcx> { } pub(crate) fn indices(&self) -> impl Iterator { - BorrowIndex::from_usize(0)..BorrowIndex::from_usize(self.len()) + (BorrowIndex::from_usize(0)..BorrowIndex::from_usize(self.len())).into_iter() } pub(crate) fn iter_enumerated(&self) -> impl Iterator)> { diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index b308cd82e547b..f03271f703bbe 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -2140,7 +2140,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { // we still want to screen for an "interesting" point to // highlight (e.g., a call site or something). let target_scc = self.constraint_sccs.scc(target_region); - let mut range = 0..path.len(); + let mut range = (0..path.len()).into_iter(); // As noted above, when reporting an error, there is typically a chain of constraints // leading from some "source" region which must outlive some "target" region. diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs index f3164bd2c2a74..189391de2940c 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs @@ -28,7 +28,7 @@ pub fn expand_deriving_partial_ord( // No data, placing the tag check first makes codegen simpler 0 => true, 1..=2 => false, - _ => (0..dataful.len() - 1).any(|i| { + _ => (0..dataful.len() - 1).into_iter().any(|i| { if dataful[i] && let Some(idx) = dataful[i + 1..].iter().position(|v| *v) { diff --git a/compiler/rustc_const_eval/src/interpret/projection.rs b/compiler/rustc_const_eval/src/interpret/projection.rs index 4d9e296d5441b..f1d8453c4a857 100644 --- a/compiler/rustc_const_eval/src/interpret/projection.rs +++ b/compiler/rustc_const_eval/src/interpret/projection.rs @@ -99,7 +99,7 @@ pub trait Projectable<'tcx, Prov: Provenance>: Sized + std::fmt::Debug { /// A type representing iteration over the elements of an array. pub struct ArrayIterator<'tcx, 'a, Prov: Provenance, P: Projectable<'tcx, Prov>> { base: &'a P, - range: Range, + range: as IntoIterator>::IntoIter, stride: Size, field_layout: TyAndLayout<'tcx>, _phantom: PhantomData, // otherwise it says `Prov` is never used... @@ -280,7 +280,13 @@ where debug!("project_array_fields: {base:?} {len}"); base.offset(len * stride, self.layout_of(self.tcx.types.unit).unwrap(), self)?; // Create the iterator. - Ok(ArrayIterator { base, range: 0..len, stride, field_layout, _phantom: PhantomData }) + Ok(ArrayIterator { + base, + range: (0..len).into_iter(), + stride, + field_layout, + _phantom: PhantomData, + }) } /// Subslicing diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 5725a759fef80..3b10ade7a5d29 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -261,7 +261,7 @@ impl LazyValue { } struct DecodeIterator<'a, 'tcx, T> { - elem_counter: std::ops::Range, + elem_counter: as IntoIterator>::IntoIter, dcx: DecodeContext<'a, 'tcx>, _phantom: PhantomData T>, } @@ -304,7 +304,7 @@ impl LazyArray { { let mut dcx = metadata.decoder(self.position.get()); dcx.lazy_state = LazyState::NodeStart(self.position); - DecodeIterator { elem_counter: (0..self.num_elems), dcx, _phantom: PhantomData } + DecodeIterator { elem_counter: (0..self.num_elems).into_iter(), dcx, _phantom: PhantomData } } } diff --git a/compiler/rustc_middle/src/mir/interpret/allocation/init_mask.rs b/compiler/rustc_middle/src/mir/interpret/allocation/init_mask.rs index 2c6bb908f39f6..6ee987c7b77fa 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation/init_mask.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation/init_mask.rs @@ -534,7 +534,7 @@ impl InitMaskMaterialized { end: Size, is_init: bool, ) -> Option { - (start..end).find(|&i| init_mask.get(i) == is_init) + (start..end).into_iter().find(|&i| init_mask.get(i) == is_init) } let result = find_bit_fast(self, start, end, is_init); diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 7ab0d3f35ea66..ca0fd36d2cf5a 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -2910,7 +2910,7 @@ impl<'a> Parser<'a> { } pub fn is_diff_marker(&mut self, long_kind: &TokenKind, short_kind: &TokenKind) -> bool { - (0..3).all(|i| self.look_ahead(i, |tok| tok == long_kind)) + (0..3).into_iter().all(|i| self.look_ahead(i, |tok| tok == long_kind)) && self.look_ahead(3, |tok| tok == short_kind) } diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 2816386cbad9f..a43bad1204886 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -1075,7 +1075,7 @@ impl<'a> Parser<'a> { // we are in has non-skipped delimiters. Look for skipped // delimiters in the lookahead range. let tree_cursor = &self.token_cursor.tree_cursor; - let all_normal = (0..dist).all(|i| { + let all_normal = (0..dist).into_iter().all(|i| { let token = tree_cursor.look_ahead(i); !matches!(token, Some(TokenTree::Delimited(_, Delimiter::Invisible, _))) }); From ebd9dfa6ac30eca0f46ee13d1b19ec7ec62d83ef Mon Sep 17 00:00:00 2001 From: Peter Jaszkowiak Date: Fri, 8 Dec 2023 19:25:59 -0700 Subject: [PATCH 3/6] fix tests --- .../src/error_codes/E0562.md | 4 +- library/alloc/src/vec/mod.rs | 2 +- library/core/src/iter/range.rs | 253 +++++++++++++----- src/librustdoc/html/length_limit/tests.rs | 2 +- src/tools/linkchecker/main.rs | 2 + ...ssue_107511.main.CopyProp.panic-abort.diff | 10 +- ...sue_107511.main.CopyProp.panic-unwind.diff | 10 +- .../loops.int_range.PreCodegen.after.mir | 134 +++++----- ...ward_loop.PreCodegen.after.panic-abort.mir | 150 ++++++----- ...ard_loop.PreCodegen.after.panic-unwind.mir | 150 ++++++----- ...sive_loop.PreCodegen.after.panic-abort.mir | 82 +++--- ...ive_loop.PreCodegen.after.panic-unwind.mir | 82 +++--- ...iter_next.PreCodegen.after.panic-abort.mir | 17 +- ...ter_next.PreCodegen.after.panic-unwind.mir | 17 +- ...iter_next.PreCodegen.after.panic-abort.mir | 61 +---- ...ter_next.PreCodegen.after.panic-unwind.mir | 61 +---- ...mut_range.PreCodegen.after.panic-abort.mir | 4 +- ...ut_range.PreCodegen.after.panic-unwind.mir | 4 +- ...ange_loop.PreCodegen.after.panic-abort.mir | 170 ++++++------ ...nge_loop.PreCodegen.after.panic-unwind.mir | 170 ++++++------ ...main.RemoveStorageMarkers.panic-abort.diff | 10 +- ...ain.RemoveStorageMarkers.panic-unwind.diff | 10 +- .../auxiliary/ret-pos-impl-trait-in-trait.rs | 4 +- .../ret-pos-impl-trait-in-trait.rs | 6 +- .../bounds-on-assoc-in-trait.rs | 2 +- .../dyn-impl-trait-type.rs | 2 +- .../dyn-rpit-and-let.rs | 4 +- tests/ui/associated-type-bounds/rpit.rs | 2 +- .../trait-alias-impl-trait.rs | 2 +- .../ui/associated-type-bounds/trait-params.rs | 34 +-- tests/ui/borrowck/borrowck-mut-uniq.rs | 2 +- .../std/const-generics-range.full.stderr | 4 +- .../std/const-generics-range.min.stderr | 4 +- .../std/const-generics-range.rs | 4 +- .../type-dependent/issue-69816.rs | 2 +- .../type-dependent/issue-73730.rs | 2 +- tests/ui/consts/const-fn-error.stderr | 4 +- tests/ui/consts/const-for.stderr | 4 +- tests/ui/impl-trait/example-calendar.rs | 2 +- tests/ui/impl-trait/issue-99642-2.rs | 2 +- tests/ui/impl-trait/issue-99642.rs | 2 +- tests/ui/issues/issue-13058.rs | 4 +- tests/ui/issues/issue-46771.rs | 2 +- tests/ui/issues/issue-46771.stderr | 10 +- tests/ui/issues/issue-76191.stderr | 4 +- tests/ui/iterators/collect-into-array.rs | 2 +- tests/ui/iterators/collect-into-array.stderr | 5 +- tests/ui/iterators/collect-into-slice.rs | 6 +- tests/ui/iterators/collect-into-slice.stderr | 15 +- .../into-iterator-type-inference-shift.rs | 2 +- .../ui/iterators/iter-map-fold-type-length.rs | 2 +- .../ui/iterators/iter-step-overflow-debug.rs | 1 + .../ui/iterators/iter-step-overflow-ndebug.rs | 1 + .../lifetimes/bare-trait-object-borrowck.rs | 2 +- ...losure-arg-type-mismatch-issue-45727.fixed | 4 +- .../closure-arg-type-mismatch-issue-45727.rs | 4 +- ...osure-arg-type-mismatch-issue-45727.stderr | 28 +- tests/ui/never_type/issue-52443.stderr | 6 +- tests/ui/nll/issue-51512.rs | 4 + tests/ui/nll/issue-51512.stderr | 6 +- tests/ui/range/issue-54505-no-literals.stderr | 8 +- tests/ui/range/issue-54505-no-std.stderr | 6 +- tests/ui/range/issue-54505.stderr | 4 +- tests/ui/range/range-1.rs | 2 +- tests/ui/range/range-1.stderr | 22 +- tests/ui/range/range_traits-1.stderr | 18 +- tests/ui/range/range_traits-2.rs | 7 +- tests/ui/range/range_traits-2.stderr | 6 +- tests/ui/range/range_traits-3.rs | 7 +- tests/ui/range/range_traits-3.stderr | 6 +- tests/ui/range/range_traits-6.rs | 7 +- tests/ui/range/range_traits-6.stderr | 6 +- tests/ui/range_inclusive.rs | 24 +- tests/ui/recursion/issue-83150.rs | 2 +- tests/ui/recursion/issue-83150.stderr | 6 +- tests/ui/suggestions/trait-hidden-method.rs | 2 +- .../ui/suggestions/trait-hidden-method.stderr | 10 +- ...sary_dot_for_floating_point_literal.stderr | 2 +- .../ui/type-alias-impl-trait/issue-58951-2.rs | 2 +- tests/ui/type-alias-impl-trait/issue-58951.rs | 2 +- .../typeck_type_placeholder_item.stderr | 2 +- 81 files changed, 943 insertions(+), 809 deletions(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0562.md b/compiler/rustc_error_codes/src/error_codes/E0562.md index 95f038df56d63..f8eafc274c72a 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0562.md +++ b/compiler/rustc_error_codes/src/error_codes/E0562.md @@ -5,7 +5,7 @@ Erroneous code example: ```compile_fail,E0562 fn main() { - let count_to_ten: impl Iterator = 0..10; + let count_to_ten: impl IntoIterator = 0..10; // error: `impl Trait` not allowed outside of function and inherent method // return types for i in count_to_ten { @@ -17,7 +17,7 @@ fn main() { Make sure `impl Trait` only appears in return-type position. ``` -fn count_to_n(n: usize) -> impl Iterator { +fn count_to_n(n: usize) -> impl IntoIterator { 0..n } diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index fca85c6123b3f..b7ab88835849b 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -1943,7 +1943,7 @@ impl Vec { /// #![feature(vec_push_within_capacity)] /// /// use std::collections::TryReserveError; - /// fn from_iter_fallible(iter: impl Iterator) -> Result, TryReserveError> { + /// fn from_iter_fallible(iter: impl IntoIterator) -> Result, TryReserveError> { /// let mut vec = Vec::new(); /// for value in iter { /// if let Err(value) = vec.push_within_capacity(value) { diff --git a/library/core/src/iter/range.rs b/library/core/src/iter/range.rs index cdbb0f0e4b3df..61cfffdb7d1ae 100644 --- a/library/core/src/iter/range.rs +++ b/library/core/src/iter/range.rs @@ -819,32 +819,64 @@ impl IntoIterator for &ops::range::Range { } } +/// Mutating iterator for `ops::Range`. #[stable(feature = "new_range", since = "1.0.0")] -impl IntoIterator for &mut ops::range::Range { +#[derive(Debug)] +pub struct RangeIterMut<'a, Idx> { + range: &'a mut ops::range::Range, +} + +#[stable(feature = "new_range", since = "1.0.0")] +impl<'a, Idx: Step> Iterator for RangeIterMut<'a, Idx> { type Item = Idx; - type IntoIter = RangeIter; - fn into_iter(self) -> Self::IntoIter { - (*self).into_iter() + fn next(&mut self) -> Option { + let mut iter = self.range.clone().into_iter(); + let out = iter.next(); + + self.range.start = iter.inner.start; + self.range.end = iter.inner.end; + + out + } +} +#[stable(feature = "new_range", since = "1.0.0")] +impl<'a, Idx: Step> DoubleEndedIterator for RangeIterMut<'a, Idx> { + fn next_back(&mut self) -> Option { + let mut iter = self.range.clone().into_iter(); + let out = iter.next_back(); + + self.range.start = iter.inner.start; + self.range.end = iter.inner.end; + + out } } impl ops::range::Range { - /// Returns and advances `start` unless the range is empty. + /// Returns an iterator which mutates this range in place, + /// rather than taking the range by value. + #[stable(feature = "new_range", since = "1.0.0")] + pub fn iter_mut(&mut self) -> RangeIterMut<'_, Idx> { + RangeIterMut { range: self } + } + + /// Shorthand for `.iter_mut().next_back()` /// - /// This differs from `.into_iter().next()` because - /// that copies the range before advancing the iterator - /// but this modifies the range in place. + /// See [`DoubleEndedIterator::next_back`] #[stable(feature = "new_range", since = "1.0.0")] - #[deprecated(since = "1.0.0", note = "can cause subtle bugs")] - pub fn next(&mut self) -> Option { - let mut iter = self.clone().into_iter(); - let out = iter.next(); + pub fn next_back(&mut self) -> Option { + self.iter_mut().next_back() + } +} - self.start = iter.inner.start; - self.end = iter.inner.end; +#[stable(feature = "new_range", since = "1.0.0")] +impl<'a, Idx: Step> IntoIterator for &'a mut ops::range::Range { + type Item = Idx; + type IntoIter = RangeIterMut<'a, Idx>; - out + fn into_iter(self) -> Self::IntoIter { + self.iter_mut() } } @@ -910,31 +942,43 @@ impl IntoIterator for &ops::range::RangeFrom { } } +/// Mutating iterator for `ops::RangeFrom`. #[stable(feature = "new_range", since = "1.0.0")] -impl IntoIterator for &mut ops::range::RangeFrom { - type Item = A; - type IntoIter = RangeFromIter; +#[derive(Debug)] +pub struct RangeFromIterMut<'a, Idx> { + range: &'a mut ops::range::RangeFrom, +} - fn into_iter(self) -> Self::IntoIter { - (*self).into_iter() +#[stable(feature = "new_range", since = "1.0.0")] +impl<'a, Idx: Step> Iterator for RangeFromIterMut<'a, Idx> { + type Item = Idx; + + fn next(&mut self) -> Option { + let mut iter = self.range.clone().into_iter(); + let out = iter.next(); + + self.range.start = iter.inner.start; + + out } } impl ops::range::RangeFrom { - /// Returns and advances `start` unless the range is empty. - /// - /// This differs from `.into_iter().next()` because - /// that copies the range before advancing the iterator - /// but this modifies the range in place. + /// Returns an iterator which mutates this range in place, + /// rather than taking the range by value. #[stable(feature = "new_range", since = "1.0.0")] - #[deprecated(since = "1.0.0", note = "can cause subtle bugs")] - pub fn next(&mut self) -> Option { - let mut iter = self.clone().into_iter(); - let out = iter.next(); + pub fn iter_mut(&mut self) -> RangeFromIterMut<'_, Idx> { + RangeFromIterMut { range: self } + } +} - self.start = iter.inner.start; +#[stable(feature = "new_range", since = "1.0.0")] +impl<'a, Idx: Step> IntoIterator for &'a mut ops::range::RangeFrom { + type Item = Idx; + type IntoIter = RangeFromIterMut<'a, Idx>; - out + fn into_iter(self) -> Self::IntoIter { + self.iter_mut() } } @@ -1086,52 +1130,106 @@ impl IntoIterator for &ops::range::RangeInclusive { } } +/// Mutating iterator for `ops::RangeInclusive`. #[stable(feature = "new_range", since = "1.0.0")] -impl IntoIterator for &mut ops::range::RangeInclusive { - type Item = A; - type IntoIter = RangeInclusiveIter; - - fn into_iter(self) -> Self::IntoIter { - (*self).into_iter() - } +#[derive(Debug)] +pub struct RangeInclusiveIterMut<'a, Idx> { + range: &'a mut ops::range::RangeInclusive, } -impl ops::range::RangeInclusive { - /// Returns and advances `start` unless the range is empty. - /// - /// This differs from `.into_iter().next()` because - /// that copies the range before advancing the iterator - /// but this modifies the range in place. - #[stable(feature = "new_range", since = "1.0.0")] - #[deprecated(since = "1.0.0", note = "can cause subtle bugs")] - pub fn next(&mut self) -> Option { - let mut iter = self.clone().into_iter(); +#[stable(feature = "new_range", since = "1.0.0")] +impl<'a, Idx: Step> Iterator for RangeInclusiveIterMut<'a, Idx> { + type Item = Idx; + + fn next(&mut self) -> Option { + let mut iter = self.range.clone().into_iter(); let out = iter.next(); if iter.inner.exhausted { // When exhausted, attempt to put end before start so the range is empty // If end is the minimum value (`start = end = 0`), set start past end if let Some(n) = Step::backward_checked(iter.inner.start.clone(), 1) { - self.end = n; - self.start = iter.inner.start; + self.range.end = n; + self.range.start = iter.inner.start; } else { - self.start = Step::forward(iter.inner.end.clone(), 1); - self.end = iter.inner.end; + self.range.start = Step::forward(iter.inner.end.clone(), 1); + self.range.end = iter.inner.end; } } else { // Not exhausted, so just set new start and end - self.start = iter.inner.start; - self.end = iter.inner.end; + self.range.start = iter.inner.start; + self.range.end = iter.inner.end; } out } } +#[stable(feature = "new_range", since = "1.0.0")] +impl<'a, Idx: Step> DoubleEndedIterator for RangeInclusiveIterMut<'a, Idx> { + fn next_back(&mut self) -> Option { + let mut iter = self.range.clone().into_iter(); + let out = iter.next_back(); + + if iter.inner.exhausted { + // When exhausted, attempt to put end before start so the range is empty + // If end is the minimum value (`start = end = 0`), set start past end + if let Some(n) = Step::backward_checked(iter.inner.start.clone(), 1) { + self.range.end = n; + self.range.start = iter.inner.start; + } else { + self.range.start = Step::forward(iter.inner.end.clone(), 1); + self.range.end = iter.inner.end; + } + } else { + // Not exhausted, so just set new start and end + self.range.start = iter.inner.start; + self.range.end = iter.inner.end; + } + + out + } +} + +impl ops::range::RangeInclusive { + /// Returns an iterator which mutates this range in place, + /// rather than taking the range by value. + #[stable(feature = "new_range", since = "1.0.0")] + pub fn iter_mut(&mut self) -> RangeInclusiveIterMut<'_, Idx> { + RangeInclusiveIterMut { range: self } + } + + /// Shorthand for `.iter_mut().next_back()` + /// + /// See [`DoubleEndedIterator::next_back`] + #[stable(feature = "new_range", since = "1.0.0")] + pub fn next_back(&mut self) -> Option { + self.iter_mut().next_back() + } +} + +#[stable(feature = "new_range", since = "1.0.0")] +impl<'a, Idx: Step> IntoIterator for &'a mut ops::range::RangeInclusive { + type Item = Idx; + type IntoIter = RangeInclusiveIterMut<'a, Idx>; + + fn into_iter(self) -> Self::IntoIter { + self.iter_mut() + } +} macro_rules! iter_methods { ($($ty:ident),*) => {$( impl ops::range::$ty { + /// Shorthand for `.iter_mut().next()`. + /// + /// See [`Iterator::next`] + #[stable(feature = "new_range", since = "1.0.0")] + #[deprecated(since = "1.0.0", note = "can cause subtle bugs")] + pub fn next(&mut self) -> Option { + self.iter_mut().next() + } + /// Shorthand for `.into_iter().size_hint()`. /// /// See [`Iterator::size_hint`] @@ -1164,6 +1262,14 @@ impl ops::range::$ty { self.into_iter().step_by(step) } + /// Shorthand for `.iter_mut().nth(...)`. + /// + /// See [`Iterator::nth`] + #[stable(feature = "new_range", since = "1.0.0")] + pub fn nth(&mut self, n: usize) -> Option { + self.iter_mut().nth(n) + } + /// Shorthand for `.into_iter().chain(...)` /// /// See [`Iterator::chain`] @@ -1379,6 +1485,18 @@ impl ops::range::$ty { self.into_iter().partition(f) } + /// Shorthand for `.into_iter().try_fold(...)` + /// + /// See [`Iterator::try_fold`] + #[stable(feature = "new_range", since = "1.0.0")] + pub fn try_fold(&mut self, init: B, f: F) -> R + where + F: FnMut(B, Idx) -> R, + R: Try, + { + self.iter_mut().try_fold(init, f) + } + /// Shorthand for `.into_iter().fold(...)` /// /// See [`Iterator::fold`] @@ -1401,49 +1519,40 @@ impl ops::range::$ty { self.into_iter().reduce(f) } - /// Shorthand for `.into_iter().all(...)` - /// - /// One noticeable difference is that this takes the - /// range by copy, rather than mutating it in place. + /// Shorthand for `.iter_mut().all(...)` /// /// See [`Iterator::all`] #[stable(feature = "new_range", since = "1.0.0")] #[deprecated(since = "1.0.0", note = "can cause subtle bugs")] - pub fn all(self, f: F) -> bool + pub fn all(&mut self, f: F) -> bool where F: FnMut(Idx) -> bool, { - self.into_iter().all(f) + self.iter_mut().all(f) } - /// Shorthand for `.into_iter().any(...)` - /// - /// One noticeable difference is that this takes the - /// range by copy, rather than mutating it in place. + /// Shorthand for `.iter_mut().any(...)` /// /// See [`Iterator::any`] #[stable(feature = "new_range", since = "1.0.0")] #[deprecated(since = "1.0.0", note = "can cause subtle bugs")] - pub fn any(self, f: F) -> bool + pub fn any(&mut self, f: F) -> bool where F: FnMut(Idx) -> bool, { - self.into_iter().any(f) + self.iter_mut().any(f) } - /// Shorthand for `.into_iter().find(...)` - /// - /// One noticeable difference is that this takes the - /// range by copy, rather than mutating it in place. + /// Shorthand for `.iter_mut().find(...)` /// /// See [`Iterator::find`] #[stable(feature = "new_range", since = "1.0.0")] #[deprecated(since = "1.0.0", note = "can cause subtle bugs")] - pub fn find

(self, predicate: P) -> Option + pub fn find

(&mut self, predicate: P) -> Option where P: FnMut(&Idx) -> bool, { - self.into_iter().find(predicate) + self.iter_mut().find(predicate) } /// Shorthand for `.into_iter().max()` diff --git a/src/librustdoc/html/length_limit/tests.rs b/src/librustdoc/html/length_limit/tests.rs index 2185c034890fa..f514dc1046305 100644 --- a/src/librustdoc/html/length_limit/tests.rs +++ b/src/librustdoc/html/length_limit/tests.rs @@ -78,7 +78,7 @@ fn forgot_to_close_tags() { fn past_the_limit() { let mut buf = HtmlWithLimit::new(20); buf.open_tag("p"); - (0..10).try_for_each(|n| { + (0..10).into_iter().try_for_each(|n| { buf.open_tag("strong"); buf.push("word#")?; buf.push(&n.to_string())?; diff --git a/src/tools/linkchecker/main.rs b/src/tools/linkchecker/main.rs index 7f73cac63cbd2..7b3ad90bdd6bb 100644 --- a/src/tools/linkchecker/main.rs +++ b/src/tools/linkchecker/main.rs @@ -58,6 +58,8 @@ const INTRA_DOC_LINK_EXCEPTIONS: &[(&str, &[&str])] = &[ // This is being used in the sense of 'inclusive range', not a markdown link ("core/ops/struct.RangeInclusive.html", &["begin, end"]), ("std/ops/struct.RangeInclusive.html", &["begin, end"]), + ("core/ops/range/legacy/struct.RangeInclusive.html", &["begin, end"]), + ("std/ops/range/legacy/struct.RangeInclusive.html", &["begin, end"]), ("core/slice/trait.SliceIndex.html", &["begin, end"]), ("alloc/slice/trait.SliceIndex.html", &["begin, end"]), ("std/slice/trait.SliceIndex.html", &["begin, end"]), diff --git a/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.panic-abort.diff b/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.panic-abort.diff index a802d0256d486..8d8d84535b207 100644 --- a/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.panic-abort.diff +++ b/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.panic-abort.diff @@ -4,7 +4,7 @@ fn main() -> () { let mut _0: (); let mut _1: i32; - let mut _3: std::ops::Range; + let mut _3: std::iter::range::RangeIter; let mut _4: std::ops::Range; let mut _5: usize; let mut _6: &[i32]; @@ -12,8 +12,8 @@ let mut _9: (); let _10: (); let mut _11: std::option::Option; - let mut _12: &mut std::ops::Range; - let mut _13: &mut std::ops::Range; + let mut _12: &mut std::iter::range::RangeIter; + let mut _13: &mut std::iter::range::RangeIter; let mut _14: isize; let mut _15: !; let mut _17: i32; @@ -25,7 +25,7 @@ let _2: [i32; 4]; scope 2 { debug a => _2; - let mut _8: std::ops::Range; + let mut _8: std::iter::range::RangeIter; scope 3 { debug iter => _8; let _16: usize; @@ -73,7 +73,7 @@ StorageLive(_13); _13 = &mut _8; _12 = &mut (*_13); - _11 = as Iterator>::next(move _12) -> [return: bb4, unwind unreachable]; + _11 = as Iterator>::next(move _12) -> [return: bb4, unwind unreachable]; } bb4: { diff --git a/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.panic-unwind.diff b/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.panic-unwind.diff index 35f852098c354..107ed69ee6b5c 100644 --- a/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.panic-unwind.diff +++ b/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.panic-unwind.diff @@ -4,7 +4,7 @@ fn main() -> () { let mut _0: (); let mut _1: i32; - let mut _3: std::ops::Range; + let mut _3: std::iter::range::RangeIter; let mut _4: std::ops::Range; let mut _5: usize; let mut _6: &[i32]; @@ -12,8 +12,8 @@ let mut _9: (); let _10: (); let mut _11: std::option::Option; - let mut _12: &mut std::ops::Range; - let mut _13: &mut std::ops::Range; + let mut _12: &mut std::iter::range::RangeIter; + let mut _13: &mut std::iter::range::RangeIter; let mut _14: isize; let mut _15: !; let mut _17: i32; @@ -25,7 +25,7 @@ let _2: [i32; 4]; scope 2 { debug a => _2; - let mut _8: std::ops::Range; + let mut _8: std::iter::range::RangeIter; scope 3 { debug iter => _8; let _16: usize; @@ -73,7 +73,7 @@ StorageLive(_13); _13 = &mut _8; _12 = &mut (*_13); - _11 = as Iterator>::next(move _12) -> [return: bb4, unwind continue]; + _11 = as Iterator>::next(move _12) -> [return: bb4, unwind continue]; } bb4: { diff --git a/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir index 73a3be7f30176..66f075595cd81 100644 --- a/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir @@ -4,113 +4,125 @@ fn int_range(_1: usize, _2: usize) -> () { debug start => _1; debug end => _2; let mut _0: (); - let mut _3: std::ops::Range; - let mut _4: std::ops::Range; - let mut _5: &mut std::ops::Range; - let mut _11: std::option::Option; - let mut _14: isize; - let _16: (); + let mut _4: std::iter::range::RangeIter; + let mut _5: std::iter::range::RangeIter; + let mut _6: &mut std::iter::range::RangeIter; + let mut _13: std::option::Option; + let mut _16: isize; + let _18: (); scope 1 { - debug iter => _4; - let _15: usize; + debug iter => _5; + let _17: usize; scope 2 { - debug i => _15; + debug i => _17; } - scope 4 (inlined iter::range::>::next) { - debug self => _5; - scope 5 (inlined as iter::range::RangeIteratorImpl>::spec_next) { - debug self => _5; - let mut _6: &usize; - let mut _7: &usize; - let mut _10: bool; - let _12: usize; - let mut _13: usize; - scope 6 { - debug old => _12; + scope 4 (inlined as Iterator>::next) { + debug self => _6; + let mut _7: &mut std::ops::range::legacy::Range; + scope 5 (inlined iter::range::legacy::>::next) { + debug self => _7; + scope 6 (inlined as iter::range::legacy::RangeIteratorImpl>::spec_next) { + debug self => _7; + let mut _8: &usize; + let mut _9: &usize; + let mut _12: bool; + let _14: usize; + let mut _15: usize; scope 7 { + debug old => _14; + scope 8 { + } + } + scope 9 (inlined std::cmp::impls::::lt) { + debug self => _8; + debug other => _9; + let mut _10: usize; + let mut _11: usize; } - } - scope 8 (inlined std::cmp::impls::::lt) { - debug self => _6; - debug other => _7; - let mut _8: usize; - let mut _9: usize; } } } } - scope 3 (inlined as IntoIterator>::into_iter) { - debug self => _3; + scope 3 (inlined iter::range::>::into_iter) { + debug ((self: std::ops::Range).0: usize) => _1; + debug ((self: std::ops::Range).1: usize) => _2; + let mut _3: std::ops::range::legacy::Range; } bb0: { - _3 = std::ops::Range:: { start: _1, end: _2 }; StorageLive(_4); - _4 = move _3; + StorageLive(_3); + _3 = std::ops::range::legacy::Range:: { start: _1, end: _2 }; + _4 = iter::range::RangeIter:: { inner: move _3 }; + StorageDead(_3); + StorageLive(_5); + _5 = move _4; goto -> bb1; } bb1: { - StorageLive(_11); - _5 = &mut _4; + StorageLive(_13); + _6 = &mut _5; + _7 = &mut (_5.0: std::ops::range::legacy::Range); + StorageLive(_14); StorageLive(_12); - StorageLive(_10); - StorageLive(_6); - _6 = &(_4.0: usize); - StorageLive(_7); - _7 = &(_4.1: usize); StorageLive(_8); - _8 = (_4.0: usize); + _8 = &((_5.0: std::ops::range::legacy::Range).0: usize); StorageLive(_9); - _9 = (_4.1: usize); - _10 = Lt(move _8, move _9); - StorageDead(_9); - StorageDead(_8); - switchInt(move _10) -> [0: bb2, otherwise: bb3]; + _9 = &((_5.0: std::ops::range::legacy::Range).1: usize); + StorageLive(_10); + _10 = ((_5.0: std::ops::range::legacy::Range).0: usize); + StorageLive(_11); + _11 = ((_5.0: std::ops::range::legacy::Range).1: usize); + _12 = Lt(move _10, move _11); + StorageDead(_11); + StorageDead(_10); + switchInt(move _12) -> [0: bb2, otherwise: bb3]; } bb2: { - StorageDead(_7); - StorageDead(_6); - _11 = Option::::None; + StorageDead(_9); + StorageDead(_8); + _13 = Option::::None; goto -> bb5; } bb3: { - StorageDead(_7); - StorageDead(_6); - _12 = (_4.0: usize); - StorageLive(_13); - _13 = ::forward_unchecked(_12, const 1_usize) -> [return: bb4, unwind continue]; + StorageDead(_9); + StorageDead(_8); + _14 = ((_5.0: std::ops::range::legacy::Range).0: usize); + StorageLive(_15); + _15 = ::forward_unchecked(_14, const 1_usize) -> [return: bb4, unwind continue]; } bb4: { - (_4.0: usize) = move _13; - StorageDead(_13); - _11 = Option::::Some(_12); + ((_5.0: std::ops::range::legacy::Range).0: usize) = move _15; + StorageDead(_15); + _13 = Option::::Some(_14); goto -> bb5; } bb5: { - StorageDead(_10); StorageDead(_12); - _14 = discriminant(_11); - switchInt(move _14) -> [0: bb6, 1: bb7, otherwise: bb9]; + StorageDead(_14); + _16 = discriminant(_13); + switchInt(move _16) -> [0: bb6, 1: bb7, otherwise: bb9]; } bb6: { - StorageDead(_11); + StorageDead(_13); + StorageDead(_5); StorageDead(_4); return; } bb7: { - _15 = ((_11 as Some).0: usize); - _16 = opaque::(move _15) -> [return: bb8, unwind continue]; + _17 = ((_13 as Some).0: usize); + _18 = opaque::(move _17) -> [return: bb8, unwind continue]; } bb8: { - StorageDead(_11); + StorageDead(_13); goto -> bb1; } diff --git a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir index cd734b10fea4f..949c10edc2281 100644 --- a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir @@ -5,104 +5,116 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { debug end => _2; debug f => _3; let mut _0: (); - let mut _4: std::ops::Range; - let mut _5: std::ops::Range; - let mut _6: &mut std::ops::Range; - let mut _12: std::option::Option; - let mut _15: isize; - let mut _17: &impl Fn(u32); - let mut _18: (u32,); - let _19: (); + let mut _5: std::iter::range::RangeIter; + let mut _6: std::iter::range::RangeIter; + let mut _7: &mut std::iter::range::RangeIter; + let mut _14: std::option::Option; + let mut _17: isize; + let mut _19: &impl Fn(u32); + let mut _20: (u32,); + let _21: (); scope 1 { - debug iter => _5; - let _16: u32; + debug iter => _6; + let _18: u32; scope 2 { - debug x => _16; + debug x => _18; } - scope 4 (inlined iter::range::>::next) { - debug self => _6; - scope 5 (inlined as iter::range::RangeIteratorImpl>::spec_next) { - debug self => _6; - let mut _7: &u32; - let mut _8: &u32; - let mut _11: bool; - let _13: u32; - let mut _14: u32; - scope 6 { - debug old => _13; + scope 4 (inlined as Iterator>::next) { + debug self => _7; + let mut _8: &mut std::ops::range::legacy::Range; + scope 5 (inlined iter::range::legacy::>::next) { + debug self => _8; + scope 6 (inlined as iter::range::legacy::RangeIteratorImpl>::spec_next) { + debug self => _8; + let mut _9: &u32; + let mut _10: &u32; + let mut _13: bool; + let _15: u32; + let mut _16: u32; scope 7 { + debug old => _15; + scope 8 { + } + } + scope 9 (inlined std::cmp::impls::::lt) { + debug self => _9; + debug other => _10; + let mut _11: u32; + let mut _12: u32; } - } - scope 8 (inlined std::cmp::impls::::lt) { - debug self => _7; - debug other => _8; - let mut _9: u32; - let mut _10: u32; } } } } - scope 3 (inlined as IntoIterator>::into_iter) { - debug self => _4; + scope 3 (inlined iter::range::>::into_iter) { + debug ((self: std::ops::Range).0: u32) => _1; + debug ((self: std::ops::Range).1: u32) => _2; + let mut _4: std::ops::range::legacy::Range; } bb0: { - _4 = std::ops::Range:: { start: _1, end: _2 }; StorageLive(_5); - _5 = move _4; + StorageLive(_4); + _4 = std::ops::range::legacy::Range:: { start: _1, end: _2 }; + _5 = iter::range::RangeIter:: { inner: move _4 }; + StorageDead(_4); + StorageLive(_6); + _6 = move _5; goto -> bb1; } bb1: { - StorageLive(_12); - _6 = &mut _5; + StorageLive(_14); + _7 = &mut _6; + _8 = &mut (_6.0: std::ops::range::legacy::Range); + StorageLive(_15); StorageLive(_13); - StorageLive(_11); - StorageLive(_7); - _7 = &(_5.0: u32); - StorageLive(_8); - _8 = &(_5.1: u32); StorageLive(_9); - _9 = (_5.0: u32); + _9 = &((_6.0: std::ops::range::legacy::Range).0: u32); StorageLive(_10); - _10 = (_5.1: u32); - _11 = Lt(move _9, move _10); - StorageDead(_10); - StorageDead(_9); - switchInt(move _11) -> [0: bb2, otherwise: bb3]; + _10 = &((_6.0: std::ops::range::legacy::Range).1: u32); + StorageLive(_11); + _11 = ((_6.0: std::ops::range::legacy::Range).0: u32); + StorageLive(_12); + _12 = ((_6.0: std::ops::range::legacy::Range).1: u32); + _13 = Lt(move _11, move _12); + StorageDead(_12); + StorageDead(_11); + switchInt(move _13) -> [0: bb2, otherwise: bb3]; } bb2: { - StorageDead(_8); - StorageDead(_7); - _12 = Option::::None; + StorageDead(_10); + StorageDead(_9); + _14 = Option::::None; goto -> bb5; } bb3: { - StorageDead(_8); - StorageDead(_7); - _13 = (_5.0: u32); - StorageLive(_14); - _14 = ::forward_unchecked(_13, const 1_usize) -> [return: bb4, unwind unreachable]; + StorageDead(_10); + StorageDead(_9); + _15 = ((_6.0: std::ops::range::legacy::Range).0: u32); + StorageLive(_16); + _16 = ::forward_unchecked(_15, const 1_usize) -> [return: bb4, unwind unreachable]; } bb4: { - (_5.0: u32) = move _14; - StorageDead(_14); - _12 = Option::::Some(_13); + ((_6.0: std::ops::range::legacy::Range).0: u32) = move _16; + StorageDead(_16); + _14 = Option::::Some(_15); goto -> bb5; } bb5: { - StorageDead(_11); StorageDead(_13); - _15 = discriminant(_12); - switchInt(move _15) -> [0: bb6, 1: bb8, otherwise: bb10]; + StorageDead(_15); + _17 = discriminant(_14); + switchInt(move _17) -> [0: bb6, 1: bb8, otherwise: bb10]; } bb6: { - StorageDead(_12); + StorageDead(_14); + StorageDead(_6); StorageDead(_5); drop(_3) -> [return: bb7, unwind unreachable]; } @@ -112,18 +124,18 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { } bb8: { - _16 = ((_12 as Some).0: u32); - StorageLive(_17); - _17 = &_3; - StorageLive(_18); - _18 = (_16,); - _19 = >::call(move _17, move _18) -> [return: bb9, unwind unreachable]; + _18 = ((_14 as Some).0: u32); + StorageLive(_19); + _19 = &_3; + StorageLive(_20); + _20 = (_18,); + _21 = >::call(move _19, move _20) -> [return: bb9, unwind unreachable]; } bb9: { - StorageDead(_18); - StorageDead(_17); - StorageDead(_12); + StorageDead(_20); + StorageDead(_19); + StorageDead(_14); goto -> bb1; } diff --git a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir index 3342da545aecc..9f03b805049a9 100644 --- a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir @@ -5,104 +5,116 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { debug end => _2; debug f => _3; let mut _0: (); - let mut _4: std::ops::Range; - let mut _5: std::ops::Range; - let mut _6: &mut std::ops::Range; - let mut _12: std::option::Option; - let mut _15: isize; - let mut _17: &impl Fn(u32); - let mut _18: (u32,); - let _19: (); + let mut _5: std::iter::range::RangeIter; + let mut _6: std::iter::range::RangeIter; + let mut _7: &mut std::iter::range::RangeIter; + let mut _14: std::option::Option; + let mut _17: isize; + let mut _19: &impl Fn(u32); + let mut _20: (u32,); + let _21: (); scope 1 { - debug iter => _5; - let _16: u32; + debug iter => _6; + let _18: u32; scope 2 { - debug x => _16; + debug x => _18; } - scope 4 (inlined iter::range::>::next) { - debug self => _6; - scope 5 (inlined as iter::range::RangeIteratorImpl>::spec_next) { - debug self => _6; - let mut _7: &u32; - let mut _8: &u32; - let mut _11: bool; - let _13: u32; - let mut _14: u32; - scope 6 { - debug old => _13; + scope 4 (inlined as Iterator>::next) { + debug self => _7; + let mut _8: &mut std::ops::range::legacy::Range; + scope 5 (inlined iter::range::legacy::>::next) { + debug self => _8; + scope 6 (inlined as iter::range::legacy::RangeIteratorImpl>::spec_next) { + debug self => _8; + let mut _9: &u32; + let mut _10: &u32; + let mut _13: bool; + let _15: u32; + let mut _16: u32; scope 7 { + debug old => _15; + scope 8 { + } + } + scope 9 (inlined std::cmp::impls::::lt) { + debug self => _9; + debug other => _10; + let mut _11: u32; + let mut _12: u32; } - } - scope 8 (inlined std::cmp::impls::::lt) { - debug self => _7; - debug other => _8; - let mut _9: u32; - let mut _10: u32; } } } } - scope 3 (inlined as IntoIterator>::into_iter) { - debug self => _4; + scope 3 (inlined iter::range::>::into_iter) { + debug ((self: std::ops::Range).0: u32) => _1; + debug ((self: std::ops::Range).1: u32) => _2; + let mut _4: std::ops::range::legacy::Range; } bb0: { - _4 = std::ops::Range:: { start: _1, end: _2 }; StorageLive(_5); - _5 = move _4; + StorageLive(_4); + _4 = std::ops::range::legacy::Range:: { start: _1, end: _2 }; + _5 = iter::range::RangeIter:: { inner: move _4 }; + StorageDead(_4); + StorageLive(_6); + _6 = move _5; goto -> bb1; } bb1: { - StorageLive(_12); - _6 = &mut _5; + StorageLive(_14); + _7 = &mut _6; + _8 = &mut (_6.0: std::ops::range::legacy::Range); + StorageLive(_15); StorageLive(_13); - StorageLive(_11); - StorageLive(_7); - _7 = &(_5.0: u32); - StorageLive(_8); - _8 = &(_5.1: u32); StorageLive(_9); - _9 = (_5.0: u32); + _9 = &((_6.0: std::ops::range::legacy::Range).0: u32); StorageLive(_10); - _10 = (_5.1: u32); - _11 = Lt(move _9, move _10); - StorageDead(_10); - StorageDead(_9); - switchInt(move _11) -> [0: bb2, otherwise: bb3]; + _10 = &((_6.0: std::ops::range::legacy::Range).1: u32); + StorageLive(_11); + _11 = ((_6.0: std::ops::range::legacy::Range).0: u32); + StorageLive(_12); + _12 = ((_6.0: std::ops::range::legacy::Range).1: u32); + _13 = Lt(move _11, move _12); + StorageDead(_12); + StorageDead(_11); + switchInt(move _13) -> [0: bb2, otherwise: bb3]; } bb2: { - StorageDead(_8); - StorageDead(_7); - _12 = Option::::None; + StorageDead(_10); + StorageDead(_9); + _14 = Option::::None; goto -> bb5; } bb3: { - StorageDead(_8); - StorageDead(_7); - _13 = (_5.0: u32); - StorageLive(_14); - _14 = ::forward_unchecked(_13, const 1_usize) -> [return: bb4, unwind: bb11]; + StorageDead(_10); + StorageDead(_9); + _15 = ((_6.0: std::ops::range::legacy::Range).0: u32); + StorageLive(_16); + _16 = ::forward_unchecked(_15, const 1_usize) -> [return: bb4, unwind: bb11]; } bb4: { - (_5.0: u32) = move _14; - StorageDead(_14); - _12 = Option::::Some(_13); + ((_6.0: std::ops::range::legacy::Range).0: u32) = move _16; + StorageDead(_16); + _14 = Option::::Some(_15); goto -> bb5; } bb5: { - StorageDead(_11); StorageDead(_13); - _15 = discriminant(_12); - switchInt(move _15) -> [0: bb6, 1: bb8, otherwise: bb10]; + StorageDead(_15); + _17 = discriminant(_14); + switchInt(move _17) -> [0: bb6, 1: bb8, otherwise: bb10]; } bb6: { - StorageDead(_12); + StorageDead(_14); + StorageDead(_6); StorageDead(_5); drop(_3) -> [return: bb7, unwind continue]; } @@ -112,18 +124,18 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { } bb8: { - _16 = ((_12 as Some).0: u32); - StorageLive(_17); - _17 = &_3; - StorageLive(_18); - _18 = (_16,); - _19 = >::call(move _17, move _18) -> [return: bb9, unwind: bb11]; + _18 = ((_14 as Some).0: u32); + StorageLive(_19); + _19 = &_3; + StorageLive(_20); + _20 = (_18,); + _21 = >::call(move _19, move _20) -> [return: bb9, unwind: bb11]; } bb9: { - StorageDead(_18); - StorageDead(_17); - StorageDead(_12); + StorageDead(_20); + StorageDead(_19); + StorageDead(_14); goto -> bb1; } diff --git a/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-abort.mir index 1b23e421368b6..4b98d618dedc6 100644 --- a/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-abort.mir @@ -5,54 +5,66 @@ fn inclusive_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { debug end => _2; debug f => _3; let mut _0: (); - let mut _4: std::ops::RangeInclusive; - let mut _5: std::ops::RangeInclusive; - let mut _6: &mut std::ops::RangeInclusive; - let mut _7: std::option::Option; - let mut _8: isize; - let mut _10: &impl Fn(u32); - let mut _11: (u32,); - let _12: (); + let mut _5: std::iter::range::RangeInclusiveIter; + let mut _6: std::iter::range::RangeInclusiveIter; + let mut _7: &mut std::iter::range::RangeInclusiveIter; + let mut _9: std::option::Option; + let mut _10: isize; + let mut _12: &impl Fn(u32); + let mut _13: (u32,); + let _14: (); scope 1 { - debug iter => _5; - let _9: u32; + debug iter => _6; + let _11: u32; scope 2 { - debug x => _9; + debug x => _11; } - scope 5 (inlined iter::range::>::next) { - debug self => _6; + scope 5 (inlined as Iterator>::next) { + debug self => _7; + let mut _8: &mut std::ops::range::legacy::RangeInclusive; + scope 6 (inlined iter::range::legacy::>::next) { + debug self => _8; + } } } - scope 3 (inlined RangeInclusive::::new) { + scope 3 (inlined std::ops::RangeInclusive::::new) { debug start => _1; debug end => _2; } - scope 4 (inlined as IntoIterator>::into_iter) { - debug self => _4; + scope 4 (inlined iter::range::>::into_iter) { + debug ((self: std::ops::RangeInclusive).0: u32) => _1; + debug ((self: std::ops::RangeInclusive).1: u32) => _2; + let mut _4: std::ops::range::legacy::RangeInclusive; } bb0: { - _4 = RangeInclusive:: { start: _1, end: _2, exhausted: const false }; StorageLive(_5); - _5 = move _4; + StorageLive(_4); + _4 = std::ops::range::legacy::RangeInclusive:: { start: _1, end: _2, exhausted: const false }; + _5 = iter::range::RangeInclusiveIter:: { inner: move _4 }; + StorageDead(_4); + StorageLive(_6); + _6 = move _5; goto -> bb1; } bb1: { - StorageLive(_7); - StorageLive(_6); - _6 = &mut _5; - _7 = as iter::range::RangeInclusiveIteratorImpl>::spec_next(move _6) -> [return: bb2, unwind unreachable]; + StorageLive(_9); + _7 = &mut _6; + StorageLive(_8); + _8 = &mut (_6.0: std::ops::range::legacy::RangeInclusive); + _9 = as iter::range::legacy::RangeInclusiveIteratorImpl>::spec_next(move _8) -> [return: bb2, unwind unreachable]; } bb2: { - StorageDead(_6); - _8 = discriminant(_7); - switchInt(move _8) -> [0: bb3, 1: bb5, otherwise: bb7]; + StorageDead(_8); + _10 = discriminant(_9); + switchInt(move _10) -> [0: bb3, 1: bb5, otherwise: bb7]; } bb3: { - StorageDead(_7); + StorageDead(_9); + StorageDead(_6); StorageDead(_5); drop(_3) -> [return: bb4, unwind unreachable]; } @@ -62,18 +74,18 @@ fn inclusive_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { } bb5: { - _9 = ((_7 as Some).0: u32); - StorageLive(_10); - _10 = &_3; - StorageLive(_11); - _11 = (_9,); - _12 = >::call(move _10, move _11) -> [return: bb6, unwind unreachable]; + _11 = ((_9 as Some).0: u32); + StorageLive(_12); + _12 = &_3; + StorageLive(_13); + _13 = (_11,); + _14 = >::call(move _12, move _13) -> [return: bb6, unwind unreachable]; } bb6: { - StorageDead(_11); - StorageDead(_10); - StorageDead(_7); + StorageDead(_13); + StorageDead(_12); + StorageDead(_9); goto -> bb1; } diff --git a/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-unwind.mir index a677e8b439fa0..9494bfbf74d7f 100644 --- a/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-unwind.mir @@ -5,54 +5,66 @@ fn inclusive_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { debug end => _2; debug f => _3; let mut _0: (); - let mut _4: std::ops::RangeInclusive; - let mut _5: std::ops::RangeInclusive; - let mut _6: &mut std::ops::RangeInclusive; - let mut _7: std::option::Option; - let mut _8: isize; - let mut _10: &impl Fn(u32); - let mut _11: (u32,); - let _12: (); + let mut _5: std::iter::range::RangeInclusiveIter; + let mut _6: std::iter::range::RangeInclusiveIter; + let mut _7: &mut std::iter::range::RangeInclusiveIter; + let mut _9: std::option::Option; + let mut _10: isize; + let mut _12: &impl Fn(u32); + let mut _13: (u32,); + let _14: (); scope 1 { - debug iter => _5; - let _9: u32; + debug iter => _6; + let _11: u32; scope 2 { - debug x => _9; + debug x => _11; } - scope 5 (inlined iter::range::>::next) { - debug self => _6; + scope 5 (inlined as Iterator>::next) { + debug self => _7; + let mut _8: &mut std::ops::range::legacy::RangeInclusive; + scope 6 (inlined iter::range::legacy::>::next) { + debug self => _8; + } } } - scope 3 (inlined RangeInclusive::::new) { + scope 3 (inlined std::ops::RangeInclusive::::new) { debug start => _1; debug end => _2; } - scope 4 (inlined as IntoIterator>::into_iter) { - debug self => _4; + scope 4 (inlined iter::range::>::into_iter) { + debug ((self: std::ops::RangeInclusive).0: u32) => _1; + debug ((self: std::ops::RangeInclusive).1: u32) => _2; + let mut _4: std::ops::range::legacy::RangeInclusive; } bb0: { - _4 = RangeInclusive:: { start: _1, end: _2, exhausted: const false }; StorageLive(_5); - _5 = move _4; + StorageLive(_4); + _4 = std::ops::range::legacy::RangeInclusive:: { start: _1, end: _2, exhausted: const false }; + _5 = iter::range::RangeInclusiveIter:: { inner: move _4 }; + StorageDead(_4); + StorageLive(_6); + _6 = move _5; goto -> bb1; } bb1: { - StorageLive(_7); - StorageLive(_6); - _6 = &mut _5; - _7 = as iter::range::RangeInclusiveIteratorImpl>::spec_next(move _6) -> [return: bb2, unwind: bb8]; + StorageLive(_9); + _7 = &mut _6; + StorageLive(_8); + _8 = &mut (_6.0: std::ops::range::legacy::RangeInclusive); + _9 = as iter::range::legacy::RangeInclusiveIteratorImpl>::spec_next(move _8) -> [return: bb2, unwind: bb8]; } bb2: { - StorageDead(_6); - _8 = discriminant(_7); - switchInt(move _8) -> [0: bb3, 1: bb5, otherwise: bb7]; + StorageDead(_8); + _10 = discriminant(_9); + switchInt(move _10) -> [0: bb3, 1: bb5, otherwise: bb7]; } bb3: { - StorageDead(_7); + StorageDead(_9); + StorageDead(_6); StorageDead(_5); drop(_3) -> [return: bb4, unwind continue]; } @@ -62,18 +74,18 @@ fn inclusive_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { } bb5: { - _9 = ((_7 as Some).0: u32); - StorageLive(_10); - _10 = &_3; - StorageLive(_11); - _11 = (_9,); - _12 = >::call(move _10, move _11) -> [return: bb6, unwind: bb8]; + _11 = ((_9 as Some).0: u32); + StorageLive(_12); + _12 = &_3; + StorageLive(_13); + _13 = (_11,); + _14 = >::call(move _12, move _13) -> [return: bb6, unwind: bb8]; } bb6: { - StorageDead(_11); - StorageDead(_10); - StorageDead(_7); + StorageDead(_13); + StorageDead(_12); + StorageDead(_9); goto -> bb1; } diff --git a/tests/mir-opt/pre-codegen/range_iter.range_inclusive_iter_next.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/range_iter.range_inclusive_iter_next.PreCodegen.after.panic-abort.mir index b0f475b4db7fc..3b22f7dcbafaf 100644 --- a/tests/mir-opt/pre-codegen/range_iter.range_inclusive_iter_next.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/range_iter.range_inclusive_iter_next.PreCodegen.after.panic-abort.mir @@ -1,17 +1,28 @@ // MIR for `range_inclusive_iter_next` after PreCodegen -fn range_inclusive_iter_next(_1: &mut RangeInclusive) -> Option { +fn range_inclusive_iter_next(_1: &mut std::ops::RangeInclusive) -> Option { debug it => _1; let mut _0: std::option::Option; - scope 1 (inlined iter::range::>::next) { + scope 1 (inlined iter::range::>::next) { debug self => _1; + let mut _2: std::iter::range::RangeInclusiveIterMut<'_, u32>; + let mut _3: &mut std::iter::range::RangeInclusiveIterMut<'_, u32>; + scope 2 (inlined iter::range::>::iter_mut) { + debug self => _1; + } } bb0: { - _0 = as iter::range::RangeInclusiveIteratorImpl>::spec_next(move _1) -> [return: bb1, unwind unreachable]; + StorageLive(_3); + StorageLive(_2); + _2 = iter::range::RangeInclusiveIterMut::<'_, u32> { range: _1 }; + _3 = &mut _2; + _0 = as Iterator>::next(move _3) -> [return: bb1, unwind unreachable]; } bb1: { + StorageDead(_3); + StorageDead(_2); return; } } diff --git a/tests/mir-opt/pre-codegen/range_iter.range_inclusive_iter_next.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/range_iter.range_inclusive_iter_next.PreCodegen.after.panic-unwind.mir index 663ec229f723c..4f119afe46ce8 100644 --- a/tests/mir-opt/pre-codegen/range_iter.range_inclusive_iter_next.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/range_iter.range_inclusive_iter_next.PreCodegen.after.panic-unwind.mir @@ -1,17 +1,28 @@ // MIR for `range_inclusive_iter_next` after PreCodegen -fn range_inclusive_iter_next(_1: &mut RangeInclusive) -> Option { +fn range_inclusive_iter_next(_1: &mut std::ops::RangeInclusive) -> Option { debug it => _1; let mut _0: std::option::Option; - scope 1 (inlined iter::range::>::next) { + scope 1 (inlined iter::range::>::next) { debug self => _1; + let mut _2: std::iter::range::RangeInclusiveIterMut<'_, u32>; + let mut _3: &mut std::iter::range::RangeInclusiveIterMut<'_, u32>; + scope 2 (inlined iter::range::>::iter_mut) { + debug self => _1; + } } bb0: { - _0 = as iter::range::RangeInclusiveIteratorImpl>::spec_next(move _1) -> [return: bb1, unwind continue]; + StorageLive(_3); + StorageLive(_2); + _2 = iter::range::RangeInclusiveIterMut::<'_, u32> { range: _1 }; + _3 = &mut _2; + _0 = as Iterator>::next(move _3) -> [return: bb1, unwind continue]; } bb1: { + StorageDead(_3); + StorageDead(_2); return; } } diff --git a/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-abort.mir index 6ed3d73b11d3c..f9a1a29e2bbaf 100644 --- a/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-abort.mir @@ -3,71 +3,26 @@ fn range_iter_next(_1: &mut std::ops::Range) -> Option { debug it => _1; let mut _0: std::option::Option; - scope 1 (inlined iter::range::>::next) { + scope 1 (inlined iter::range::>::next) { debug self => _1; - scope 2 (inlined as iter::range::RangeIteratorImpl>::spec_next) { + let mut _2: std::iter::range::RangeIterMut<'_, u32>; + let mut _3: &mut std::iter::range::RangeIterMut<'_, u32>; + scope 2 (inlined iter::range::>::iter_mut) { debug self => _1; - let mut _2: &u32; - let mut _3: &u32; - let mut _6: bool; - let _7: u32; - let mut _8: u32; - scope 3 { - debug old => _7; - scope 4 { - } - } - scope 5 (inlined std::cmp::impls::::lt) { - debug self => _2; - debug other => _3; - let mut _4: u32; - let mut _5: u32; - } } } bb0: { - StorageLive(_7); - StorageLive(_6); - StorageLive(_2); - _2 = &((*_1).0: u32); StorageLive(_3); - _3 = &((*_1).1: u32); - StorageLive(_4); - _4 = ((*_1).0: u32); - StorageLive(_5); - _5 = ((*_1).1: u32); - _6 = Lt(move _4, move _5); - StorageDead(_5); - StorageDead(_4); - switchInt(move _6) -> [0: bb1, otherwise: bb2]; + StorageLive(_2); + _2 = iter::range::RangeIterMut::<'_, u32> { range: _1 }; + _3 = &mut _2; + _0 = as Iterator>::next(move _3) -> [return: bb1, unwind unreachable]; } bb1: { StorageDead(_3); StorageDead(_2); - _0 = Option::::None; - goto -> bb4; - } - - bb2: { - StorageDead(_3); - StorageDead(_2); - _7 = ((*_1).0: u32); - StorageLive(_8); - _8 = ::forward_unchecked(_7, const 1_usize) -> [return: bb3, unwind unreachable]; - } - - bb3: { - ((*_1).0: u32) = move _8; - StorageDead(_8); - _0 = Option::::Some(_7); - goto -> bb4; - } - - bb4: { - StorageDead(_6); - StorageDead(_7); return; } } diff --git a/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-unwind.mir index a030647deae38..eac6421daccc0 100644 --- a/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-unwind.mir @@ -3,71 +3,26 @@ fn range_iter_next(_1: &mut std::ops::Range) -> Option { debug it => _1; let mut _0: std::option::Option; - scope 1 (inlined iter::range::>::next) { + scope 1 (inlined iter::range::>::next) { debug self => _1; - scope 2 (inlined as iter::range::RangeIteratorImpl>::spec_next) { + let mut _2: std::iter::range::RangeIterMut<'_, u32>; + let mut _3: &mut std::iter::range::RangeIterMut<'_, u32>; + scope 2 (inlined iter::range::>::iter_mut) { debug self => _1; - let mut _2: &u32; - let mut _3: &u32; - let mut _6: bool; - let _7: u32; - let mut _8: u32; - scope 3 { - debug old => _7; - scope 4 { - } - } - scope 5 (inlined std::cmp::impls::::lt) { - debug self => _2; - debug other => _3; - let mut _4: u32; - let mut _5: u32; - } } } bb0: { - StorageLive(_7); - StorageLive(_6); - StorageLive(_2); - _2 = &((*_1).0: u32); StorageLive(_3); - _3 = &((*_1).1: u32); - StorageLive(_4); - _4 = ((*_1).0: u32); - StorageLive(_5); - _5 = ((*_1).1: u32); - _6 = Lt(move _4, move _5); - StorageDead(_5); - StorageDead(_4); - switchInt(move _6) -> [0: bb1, otherwise: bb2]; + StorageLive(_2); + _2 = iter::range::RangeIterMut::<'_, u32> { range: _1 }; + _3 = &mut _2; + _0 = as Iterator>::next(move _3) -> [return: bb1, unwind continue]; } bb1: { StorageDead(_3); StorageDead(_2); - _0 = Option::::None; - goto -> bb4; - } - - bb2: { - StorageDead(_3); - StorageDead(_2); - _7 = ((*_1).0: u32); - StorageLive(_8); - _8 = ::forward_unchecked(_7, const 1_usize) -> [return: bb3, unwind continue]; - } - - bb3: { - ((*_1).0: u32) = move _8; - StorageDead(_8); - _0 = Option::::Some(_7); - goto -> bb4; - } - - bb4: { - StorageDead(_6); - StorageDead(_7); return; } } diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir index 0d95f81c37c54..d65d4ceb0fb4f 100644 --- a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir @@ -69,8 +69,8 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range) -> } bb0: { - _3 = move (_2.0: usize); - _4 = move (_2.1: usize); + _3 = (_2.0: usize); + _4 = (_2.1: usize); StorageLive(_5); _5 = &raw mut (*_1); StorageLive(_14); diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir index 0d95f81c37c54..d65d4ceb0fb4f 100644 --- a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir @@ -69,8 +69,8 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range) -> } bb0: { - _3 = move (_2.0: usize); - _4 = move (_2.1: usize); + _3 = (_2.0: usize); + _4 = (_2.1: usize); StorageLive(_5); _5 = &raw mut (*_1); StorageLive(_14); diff --git a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir index db6922968ae9c..9a5008a6e2c2e 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir @@ -5,113 +5,123 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { debug f => _2; let mut _0: (); let mut _3: usize; - let mut _4: std::ops::Range; - let mut _5: std::ops::Range; - let mut _6: &mut std::ops::Range; - let mut _12: std::option::Option; - let mut _15: isize; - let mut _17: usize; - let mut _18: bool; - let mut _20: &impl Fn(usize, &T); - let mut _21: (usize, &T); - let _22: (); + let mut _5: std::iter::range::RangeIter; + let mut _6: std::iter::range::RangeIter; + let mut _7: &mut std::iter::range::RangeIter; + let mut _14: std::option::Option; + let mut _17: isize; + let mut _19: usize; + let mut _20: bool; + let mut _22: &impl Fn(usize, &T); + let mut _23: (usize, &T); + let _24: (); scope 1 { - debug iter => _5; - let _16: usize; + debug iter => _6; + let _18: usize; scope 2 { - debug i => _16; - let _19: &T; + debug i => _18; + let _21: &T; scope 3 { - debug x => _19; + debug x => _21; } } - scope 5 (inlined iter::range::>::next) { - debug self => _6; - scope 6 (inlined as iter::range::RangeIteratorImpl>::spec_next) { - debug self => _6; - let mut _7: &usize; - let mut _8: &usize; - let mut _11: bool; - let _13: usize; - let mut _14: usize; - scope 7 { - debug old => _13; + scope 5 (inlined as Iterator>::next) { + debug self => _7; + let mut _8: &mut std::ops::range::legacy::Range; + scope 6 (inlined iter::range::legacy::>::next) { + debug self => _8; + scope 7 (inlined as iter::range::legacy::RangeIteratorImpl>::spec_next) { + debug self => _8; + let mut _9: &usize; + let mut _10: &usize; + let mut _13: bool; + let _15: usize; + let mut _16: usize; scope 8 { + debug old => _15; + scope 9 { + } + } + scope 10 (inlined std::cmp::impls::::lt) { + debug self => _9; + debug other => _10; + let mut _11: usize; + let mut _12: usize; } - } - scope 9 (inlined std::cmp::impls::::lt) { - debug self => _7; - debug other => _8; - let mut _9: usize; - let mut _10: usize; } } } } - scope 4 (inlined as IntoIterator>::into_iter) { - debug self => _4; + scope 4 (inlined iter::range::>::into_iter) { + debug ((self: std::ops::Range).0: usize) => const 0_usize; + debug ((self: std::ops::Range).1: usize) => _3; + let mut _4: std::ops::range::legacy::Range; } bb0: { - StorageLive(_3); - _3 = Len((*_1)); - _4 = std::ops::Range:: { start: const 0_usize, end: move _3 }; - StorageDead(_3); StorageLive(_5); - _5 = move _4; + _3 = Len((*_1)); + StorageLive(_4); + _4 = std::ops::range::legacy::Range:: { start: const 0_usize, end: move _3 }; + _5 = iter::range::RangeIter:: { inner: move _4 }; + StorageDead(_4); + StorageLive(_6); + _6 = move _5; goto -> bb1; } bb1: { - StorageLive(_12); - _6 = &mut _5; + StorageLive(_14); + _7 = &mut _6; + _8 = &mut (_6.0: std::ops::range::legacy::Range); + StorageLive(_15); StorageLive(_13); - StorageLive(_11); - StorageLive(_7); - _7 = &(_5.0: usize); - StorageLive(_8); - _8 = &(_5.1: usize); StorageLive(_9); - _9 = (_5.0: usize); + _9 = &((_6.0: std::ops::range::legacy::Range).0: usize); StorageLive(_10); - _10 = (_5.1: usize); - _11 = Lt(move _9, move _10); - StorageDead(_10); - StorageDead(_9); - switchInt(move _11) -> [0: bb2, otherwise: bb3]; + _10 = &((_6.0: std::ops::range::legacy::Range).1: usize); + StorageLive(_11); + _11 = ((_6.0: std::ops::range::legacy::Range).0: usize); + StorageLive(_12); + _12 = ((_6.0: std::ops::range::legacy::Range).1: usize); + _13 = Lt(move _11, move _12); + StorageDead(_12); + StorageDead(_11); + switchInt(move _13) -> [0: bb2, otherwise: bb3]; } bb2: { - StorageDead(_8); - StorageDead(_7); - _12 = Option::::None; + StorageDead(_10); + StorageDead(_9); + _14 = Option::::None; goto -> bb5; } bb3: { - StorageDead(_8); - StorageDead(_7); - _13 = (_5.0: usize); - StorageLive(_14); - _14 = ::forward_unchecked(_13, const 1_usize) -> [return: bb4, unwind unreachable]; + StorageDead(_10); + StorageDead(_9); + _15 = ((_6.0: std::ops::range::legacy::Range).0: usize); + StorageLive(_16); + _16 = ::forward_unchecked(_15, const 1_usize) -> [return: bb4, unwind unreachable]; } bb4: { - (_5.0: usize) = move _14; - StorageDead(_14); - _12 = Option::::Some(_13); + ((_6.0: std::ops::range::legacy::Range).0: usize) = move _16; + StorageDead(_16); + _14 = Option::::Some(_15); goto -> bb5; } bb5: { - StorageDead(_11); StorageDead(_13); - _15 = discriminant(_12); - switchInt(move _15) -> [0: bb6, 1: bb8, otherwise: bb11]; + StorageDead(_15); + _17 = discriminant(_14); + switchInt(move _17) -> [0: bb6, 1: bb8, otherwise: bb11]; } bb6: { - StorageDead(_12); + StorageDead(_14); + StorageDead(_6); StorageDead(_5); drop(_2) -> [return: bb7, unwind unreachable]; } @@ -121,25 +131,25 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { } bb8: { - _16 = ((_12 as Some).0: usize); - _17 = Len((*_1)); - _18 = Lt(_16, _17); - assert(move _18, "index out of bounds: the length is {} but the index is {}", move _17, _16) -> [success: bb9, unwind unreachable]; + _18 = ((_14 as Some).0: usize); + _19 = Len((*_1)); + _20 = Lt(_18, _19); + assert(move _20, "index out of bounds: the length is {} but the index is {}", move _19, _18) -> [success: bb9, unwind unreachable]; } bb9: { - _19 = &(*_1)[_16]; - StorageLive(_20); - _20 = &_2; - StorageLive(_21); - _21 = (_16, _19); - _22 = >::call(move _20, move _21) -> [return: bb10, unwind unreachable]; + _21 = &(*_1)[_18]; + StorageLive(_22); + _22 = &_2; + StorageLive(_23); + _23 = (_18, _21); + _24 = >::call(move _22, move _23) -> [return: bb10, unwind unreachable]; } bb10: { - StorageDead(_21); - StorageDead(_20); - StorageDead(_12); + StorageDead(_23); + StorageDead(_22); + StorageDead(_14); goto -> bb1; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir index 81d1832eebba2..16426575f00ca 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir @@ -5,113 +5,123 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { debug f => _2; let mut _0: (); let mut _3: usize; - let mut _4: std::ops::Range; - let mut _5: std::ops::Range; - let mut _6: &mut std::ops::Range; - let mut _12: std::option::Option; - let mut _15: isize; - let mut _17: usize; - let mut _18: bool; - let mut _20: &impl Fn(usize, &T); - let mut _21: (usize, &T); - let _22: (); + let mut _5: std::iter::range::RangeIter; + let mut _6: std::iter::range::RangeIter; + let mut _7: &mut std::iter::range::RangeIter; + let mut _14: std::option::Option; + let mut _17: isize; + let mut _19: usize; + let mut _20: bool; + let mut _22: &impl Fn(usize, &T); + let mut _23: (usize, &T); + let _24: (); scope 1 { - debug iter => _5; - let _16: usize; + debug iter => _6; + let _18: usize; scope 2 { - debug i => _16; - let _19: &T; + debug i => _18; + let _21: &T; scope 3 { - debug x => _19; + debug x => _21; } } - scope 5 (inlined iter::range::>::next) { - debug self => _6; - scope 6 (inlined as iter::range::RangeIteratorImpl>::spec_next) { - debug self => _6; - let mut _7: &usize; - let mut _8: &usize; - let mut _11: bool; - let _13: usize; - let mut _14: usize; - scope 7 { - debug old => _13; + scope 5 (inlined as Iterator>::next) { + debug self => _7; + let mut _8: &mut std::ops::range::legacy::Range; + scope 6 (inlined iter::range::legacy::>::next) { + debug self => _8; + scope 7 (inlined as iter::range::legacy::RangeIteratorImpl>::spec_next) { + debug self => _8; + let mut _9: &usize; + let mut _10: &usize; + let mut _13: bool; + let _15: usize; + let mut _16: usize; scope 8 { + debug old => _15; + scope 9 { + } + } + scope 10 (inlined std::cmp::impls::::lt) { + debug self => _9; + debug other => _10; + let mut _11: usize; + let mut _12: usize; } - } - scope 9 (inlined std::cmp::impls::::lt) { - debug self => _7; - debug other => _8; - let mut _9: usize; - let mut _10: usize; } } } } - scope 4 (inlined as IntoIterator>::into_iter) { - debug self => _4; + scope 4 (inlined iter::range::>::into_iter) { + debug ((self: std::ops::Range).0: usize) => const 0_usize; + debug ((self: std::ops::Range).1: usize) => _3; + let mut _4: std::ops::range::legacy::Range; } bb0: { - StorageLive(_3); - _3 = Len((*_1)); - _4 = std::ops::Range:: { start: const 0_usize, end: move _3 }; - StorageDead(_3); StorageLive(_5); - _5 = move _4; + _3 = Len((*_1)); + StorageLive(_4); + _4 = std::ops::range::legacy::Range:: { start: const 0_usize, end: move _3 }; + _5 = iter::range::RangeIter:: { inner: move _4 }; + StorageDead(_4); + StorageLive(_6); + _6 = move _5; goto -> bb1; } bb1: { - StorageLive(_12); - _6 = &mut _5; + StorageLive(_14); + _7 = &mut _6; + _8 = &mut (_6.0: std::ops::range::legacy::Range); + StorageLive(_15); StorageLive(_13); - StorageLive(_11); - StorageLive(_7); - _7 = &(_5.0: usize); - StorageLive(_8); - _8 = &(_5.1: usize); StorageLive(_9); - _9 = (_5.0: usize); + _9 = &((_6.0: std::ops::range::legacy::Range).0: usize); StorageLive(_10); - _10 = (_5.1: usize); - _11 = Lt(move _9, move _10); - StorageDead(_10); - StorageDead(_9); - switchInt(move _11) -> [0: bb2, otherwise: bb3]; + _10 = &((_6.0: std::ops::range::legacy::Range).1: usize); + StorageLive(_11); + _11 = ((_6.0: std::ops::range::legacy::Range).0: usize); + StorageLive(_12); + _12 = ((_6.0: std::ops::range::legacy::Range).1: usize); + _13 = Lt(move _11, move _12); + StorageDead(_12); + StorageDead(_11); + switchInt(move _13) -> [0: bb2, otherwise: bb3]; } bb2: { - StorageDead(_8); - StorageDead(_7); - _12 = Option::::None; + StorageDead(_10); + StorageDead(_9); + _14 = Option::::None; goto -> bb5; } bb3: { - StorageDead(_8); - StorageDead(_7); - _13 = (_5.0: usize); - StorageLive(_14); - _14 = ::forward_unchecked(_13, const 1_usize) -> [return: bb4, unwind: bb12]; + StorageDead(_10); + StorageDead(_9); + _15 = ((_6.0: std::ops::range::legacy::Range).0: usize); + StorageLive(_16); + _16 = ::forward_unchecked(_15, const 1_usize) -> [return: bb4, unwind: bb12]; } bb4: { - (_5.0: usize) = move _14; - StorageDead(_14); - _12 = Option::::Some(_13); + ((_6.0: std::ops::range::legacy::Range).0: usize) = move _16; + StorageDead(_16); + _14 = Option::::Some(_15); goto -> bb5; } bb5: { - StorageDead(_11); StorageDead(_13); - _15 = discriminant(_12); - switchInt(move _15) -> [0: bb6, 1: bb8, otherwise: bb11]; + StorageDead(_15); + _17 = discriminant(_14); + switchInt(move _17) -> [0: bb6, 1: bb8, otherwise: bb11]; } bb6: { - StorageDead(_12); + StorageDead(_14); + StorageDead(_6); StorageDead(_5); drop(_2) -> [return: bb7, unwind continue]; } @@ -121,25 +131,25 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { } bb8: { - _16 = ((_12 as Some).0: usize); - _17 = Len((*_1)); - _18 = Lt(_16, _17); - assert(move _18, "index out of bounds: the length is {} but the index is {}", move _17, _16) -> [success: bb9, unwind: bb12]; + _18 = ((_14 as Some).0: usize); + _19 = Len((*_1)); + _20 = Lt(_18, _19); + assert(move _20, "index out of bounds: the length is {} but the index is {}", move _19, _18) -> [success: bb9, unwind: bb12]; } bb9: { - _19 = &(*_1)[_16]; - StorageLive(_20); - _20 = &_2; - StorageLive(_21); - _21 = (_16, _19); - _22 = >::call(move _20, move _21) -> [return: bb10, unwind: bb12]; + _21 = &(*_1)[_18]; + StorageLive(_22); + _22 = &_2; + StorageLive(_23); + _23 = (_18, _21); + _24 = >::call(move _22, move _23) -> [return: bb10, unwind: bb12]; } bb10: { - StorageDead(_21); - StorageDead(_20); - StorageDead(_12); + StorageDead(_23); + StorageDead(_22); + StorageDead(_14); goto -> bb1; } diff --git a/tests/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.panic-abort.diff b/tests/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.panic-abort.diff index 8804e671527e8..40fc2e26da036 100644 --- a/tests/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.panic-abort.diff +++ b/tests/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.panic-abort.diff @@ -4,19 +4,19 @@ fn main() -> () { let mut _0: (); let mut _1: i32; - let mut _2: std::ops::Range; + let mut _2: std::iter::range::RangeIter; let mut _3: std::ops::Range; let mut _5: (); let _6: (); let mut _7: std::option::Option; - let mut _8: &mut std::ops::Range; - let mut _9: &mut std::ops::Range; + let mut _8: &mut std::iter::range::RangeIter; + let mut _9: &mut std::iter::range::RangeIter; let mut _10: isize; let mut _11: !; let mut _13: i32; scope 1 { debug sum => _1; - let mut _4: std::ops::Range; + let mut _4: std::iter::range::RangeIter; scope 2 { debug iter => _4; let _12: i32; @@ -49,7 +49,7 @@ - StorageLive(_9); _9 = &mut _4; _8 = &mut (*_9); - _7 = as Iterator>::next(move _8) -> [return: bb3, unwind unreachable]; + _7 = as Iterator>::next(move _8) -> [return: bb3, unwind unreachable]; } bb3: { diff --git a/tests/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.panic-unwind.diff b/tests/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.panic-unwind.diff index faaebc300efa2..69242990a9b14 100644 --- a/tests/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.panic-unwind.diff +++ b/tests/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.panic-unwind.diff @@ -4,19 +4,19 @@ fn main() -> () { let mut _0: (); let mut _1: i32; - let mut _2: std::ops::Range; + let mut _2: std::iter::range::RangeIter; let mut _3: std::ops::Range; let mut _5: (); let _6: (); let mut _7: std::option::Option; - let mut _8: &mut std::ops::Range; - let mut _9: &mut std::ops::Range; + let mut _8: &mut std::iter::range::RangeIter; + let mut _9: &mut std::iter::range::RangeIter; let mut _10: isize; let mut _11: !; let mut _13: i32; scope 1 { debug sum => _1; - let mut _4: std::ops::Range; + let mut _4: std::iter::range::RangeIter; scope 2 { debug iter => _4; let _12: i32; @@ -49,7 +49,7 @@ - StorageLive(_9); _9 = &mut _4; _8 = &mut (*_9); - _7 = as Iterator>::next(move _8) -> [return: bb3, unwind continue]; + _7 = as Iterator>::next(move _8) -> [return: bb3, unwind continue]; } bb3: { diff --git a/tests/rustdoc/inline_cross/auxiliary/ret-pos-impl-trait-in-trait.rs b/tests/rustdoc/inline_cross/auxiliary/ret-pos-impl-trait-in-trait.rs index 08a3f517671a3..febf8b3104d4a 100644 --- a/tests/rustdoc/inline_cross/auxiliary/ret-pos-impl-trait-in-trait.rs +++ b/tests/rustdoc/inline_cross/auxiliary/ret-pos-impl-trait-in-trait.rs @@ -1,5 +1,5 @@ pub trait Trait { - fn create() -> impl Iterator { + fn create() -> impl IntoIterator { std::iter::empty() } } @@ -19,7 +19,7 @@ impl Trait for Intermediate { } impl Trait for Advanced { - fn create() -> impl Iterator { // opaque return type + fn create() -> impl IntoIterator { // opaque return type std::iter::repeat(0) } } diff --git a/tests/rustdoc/inline_cross/ret-pos-impl-trait-in-trait.rs b/tests/rustdoc/inline_cross/ret-pos-impl-trait-in-trait.rs index 8e9ef90201533..9d62f27e5769f 100644 --- a/tests/rustdoc/inline_cross/ret-pos-impl-trait-in-trait.rs +++ b/tests/rustdoc/inline_cross/ret-pos-impl-trait-in-trait.rs @@ -8,13 +8,13 @@ // This is more robust than checking for the absence of the associated type. // @has user/trait.Trait.html -// @has - '//*[@id="method.create"]' 'fn create() -> impl Iterator' +// @has - '//*[@id="method.create"]' 'fn create() -> impl IntoIterator' // The class "method" is used for all three kinds of associated items at the time of writing. // @count - '//*[@id="main-content"]//section[@class="method"]' 1 pub use rpitit::Trait; // @has user/struct.Basic.html -// @has - '//*[@id="method.create"]' 'fn create() -> impl Iterator' +// @has - '//*[@id="method.create"]' 'fn create() -> impl IntoIterator' // @count - '//*[@id="trait-implementations-list"]//*[@class="impl-items"]' 1 pub use rpitit::Basic; @@ -24,7 +24,7 @@ pub use rpitit::Basic; pub use rpitit::Intermediate; // @has user/struct.Advanced.html -// @has - '//*[@id="method.create"]' 'fn create() -> impl Iterator' +// @has - '//*[@id="method.create"]' 'fn create() -> impl IntoIterator' // @count - '//*[@id="trait-implementations-list"]//*[@class="impl-items"]' 1 pub use rpitit::Advanced; diff --git a/tests/ui/associated-type-bounds/bounds-on-assoc-in-trait.rs b/tests/ui/associated-type-bounds/bounds-on-assoc-in-trait.rs index 23be735010bf3..8a52c68f1b154 100644 --- a/tests/ui/associated-type-bounds/bounds-on-assoc-in-trait.rs +++ b/tests/ui/associated-type-bounds/bounds-on-assoc-in-trait.rs @@ -18,7 +18,7 @@ trait Case1 { type A: Iterator; //~^ ERROR `<::A as Iterator>::Item` doesn't implement `Debug` - type B: Iterator; + type B: IntoIterator; } pub struct S1; diff --git a/tests/ui/associated-type-bounds/dyn-impl-trait-type.rs b/tests/ui/associated-type-bounds/dyn-impl-trait-type.rs index a3f4717791abd..ebb1661111315 100644 --- a/tests/ui/associated-type-bounds/dyn-impl-trait-type.rs +++ b/tests/ui/associated-type-bounds/dyn-impl-trait-type.rs @@ -24,7 +24,7 @@ type Et2 = Box>; fn def_et2() -> Et2 { Box::new(S1) } pub fn use_et2() { assert_static(def_et2().mk()); } -type Et3 = Box>>>>; +type Et3 = Box>>>>; fn def_et3() -> Et3 { struct A; impl Tr1 for A { diff --git a/tests/ui/associated-type-bounds/dyn-rpit-and-let.rs b/tests/ui/associated-type-bounds/dyn-rpit-and-let.rs index 52199124ea3b5..7eb9eb096a42e 100644 --- a/tests/ui/associated-type-bounds/dyn-rpit-and-let.rs +++ b/tests/ui/associated-type-bounds/dyn-rpit-and-let.rs @@ -30,13 +30,13 @@ fn def_et2() -> Box> { } pub fn use_et2() { assert_static(def_et2().mk()); } -fn def_et3() -> Box>>>> { +fn def_et3() -> Box>>>> { struct A; impl Tr1 for A { type As1 = core::ops::Range; fn mk(&self) -> Self::As1 { 0..10 } } - let x /* : Box>>>> */ + let x /* : Box>>>> */ = Box::new(A); x } diff --git a/tests/ui/associated-type-bounds/rpit.rs b/tests/ui/associated-type-bounds/rpit.rs index 59c7733fbe4ba..3e0abe395a16b 100644 --- a/tests/ui/associated-type-bounds/rpit.rs +++ b/tests/ui/associated-type-bounds/rpit.rs @@ -22,7 +22,7 @@ pub fn use_et1() { assert_copy(def_et1().mk()); } fn def_et2() -> impl Tr1 { S1 } pub fn use_et2() { assert_static(def_et2().mk()); } -fn def_et3() -> impl Tr1>>> { +fn def_et3() -> impl Tr1>>> { struct A; impl Tr1 for A { type As1 = core::ops::Range; diff --git a/tests/ui/associated-type-bounds/trait-alias-impl-trait.rs b/tests/ui/associated-type-bounds/trait-alias-impl-trait.rs index 93a44c01ce053..784efe4da6d1e 100644 --- a/tests/ui/associated-type-bounds/trait-alias-impl-trait.rs +++ b/tests/ui/associated-type-bounds/trait-alias-impl-trait.rs @@ -46,7 +46,7 @@ pub fn use_et2() { assert_static(def_et2().mk()); } -type Et3 = impl Tr1>>>; +type Et3 = impl Tr1>>>; fn def_et3() -> Et3 { struct A; impl Tr1 for A { diff --git a/tests/ui/associated-type-bounds/trait-params.rs b/tests/ui/associated-type-bounds/trait-params.rs index b0703a4ee22b3..60dccfc7b8bc9 100644 --- a/tests/ui/associated-type-bounds/trait-params.rs +++ b/tests/ui/associated-type-bounds/trait-params.rs @@ -7,7 +7,7 @@ use std::ops::Range; pub trait Three { type A; type B; type C; } pub fn assert_three() {} -pub fn assert_iterator() {} +pub fn assert_iterator() {} pub fn assert_copy() {} pub fn assert_static() {} pub fn assert_send() {} @@ -19,11 +19,11 @@ impl Three for B { type A = Range; type B = Range; type C = Range; } trait Case1 where - A: Iterator, - B: Iterator, - C: Iterator, - D: Iterator Into<&'a u8>>, - E: Three, B: Iterator, C: Iterator>, + A: IntoIterator, + B: IntoIterator, + C: IntoIterator, + D: IntoIterator Into<&'a u8>>, + E: Three, B: IntoIterator, C: IntoIterator>, Self: Three, { fn _a() { @@ -49,9 +49,9 @@ where assert_iterator::(); assert_iterator::(); assert_iterator::(); - assert_copy::<::Item>(); - assert_copy::<::Item>(); - assert_copy::<::Item>(); + assert_copy::<::Item>(); + assert_copy::<::Item>(); + assert_copy::<::Item>(); } fn _self() { assert_three::(); @@ -66,11 +66,11 @@ impl Three for DataCase1 { type A = u8; type B = u8; type C = u8; } impl Case1, Range, Range, Once, B> for DataCase1 {} trait Case2< - A: Iterator, - B: Iterator, - C: Iterator, - D: Iterator Into<&'a u8>>, - E: Three, B: Iterator, C: Iterator>, + A: IntoIterator, + B: IntoIterator, + C: IntoIterator, + D: IntoIterator Into<&'a u8>>, + E: Three, B: IntoIterator, C: IntoIterator>, >: Three { @@ -97,9 +97,9 @@ trait Case2< assert_iterator::(); assert_iterator::(); assert_iterator::(); - assert_copy::<::Item>(); - assert_copy::<::Item>(); - assert_copy::<::Item>(); + assert_copy::<::Item>(); + assert_copy::<::Item>(); + assert_copy::<::Item>(); } fn _self() { assert_three::(); diff --git a/tests/ui/borrowck/borrowck-mut-uniq.rs b/tests/ui/borrowck/borrowck-mut-uniq.rs index 255b4995b640d..0b9edd3f5bd6a 100644 --- a/tests/ui/borrowck/borrowck-mut-uniq.rs +++ b/tests/ui/borrowck/borrowck-mut-uniq.rs @@ -15,7 +15,7 @@ fn add_int(x: &mut Ints, v: isize) { fn iter_ints(x: &Ints, mut f: F) -> bool where F: FnMut(&isize) -> bool { let l = x.values.len(); - (0..l).all(|i| f(&x.values[i])) + (0..l).into_iter().all(|i| f(&x.values[i])) } pub fn main() { diff --git a/tests/ui/const-generics/std/const-generics-range.full.stderr b/tests/ui/const-generics/std/const-generics-range.full.stderr index 5bf48ad738587..2b5c63e6643d8 100644 --- a/tests/ui/const-generics/std/const-generics-range.full.stderr +++ b/tests/ui/const-generics/std/const-generics-range.full.stderr @@ -4,7 +4,7 @@ error[E0741]: `std::ops::Range` must implement `ConstParamTy` to be used LL | struct _Range>; | ^^^^^^^^^^^^^^^^^^^^^^ -error[E0741]: `RangeFrom` must implement `ConstParamTy` to be used as the type of a const generic parameter +error[E0741]: `std::ops::RangeFrom` must implement `ConstParamTy` to be used as the type of a const generic parameter --> $DIR/const-generics-range.rs:13:28 | LL | struct _RangeFrom>; @@ -16,7 +16,7 @@ error[E0741]: `RangeFull` must implement `ConstParamTy` to be used as the type o LL | struct _RangeFull; | ^^^^^^^^^^^^^^^^^^^ -error[E0741]: `RangeInclusive` must implement `ConstParamTy` to be used as the type of a const generic parameter +error[E0741]: `std::ops::RangeInclusive` must implement `ConstParamTy` to be used as the type of a const generic parameter --> $DIR/const-generics-range.rs:24:33 | LL | struct _RangeInclusive>; diff --git a/tests/ui/const-generics/std/const-generics-range.min.stderr b/tests/ui/const-generics/std/const-generics-range.min.stderr index d45f749246c8e..b16f3bfe9c580 100644 --- a/tests/ui/const-generics/std/const-generics-range.min.stderr +++ b/tests/ui/const-generics/std/const-generics-range.min.stderr @@ -7,7 +7,7 @@ LL | struct _Range>; = note: the only supported types are integers, `bool` and `char` = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types -error: `RangeFrom` is forbidden as the type of a const generic parameter +error: `std::ops::RangeFrom` is forbidden as the type of a const generic parameter --> $DIR/const-generics-range.rs:13:28 | LL | struct _RangeFrom>; @@ -25,7 +25,7 @@ LL | struct _RangeFull; = note: the only supported types are integers, `bool` and `char` = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types -error: `RangeInclusive` is forbidden as the type of a const generic parameter +error: `std::ops::RangeInclusive` is forbidden as the type of a const generic parameter --> $DIR/const-generics-range.rs:24:33 | LL | struct _RangeInclusive>; diff --git a/tests/ui/const-generics/std/const-generics-range.rs b/tests/ui/const-generics/std/const-generics-range.rs index bda59f3ec4590..9f77ecd56ea72 100644 --- a/tests/ui/const-generics/std/const-generics-range.rs +++ b/tests/ui/const-generics/std/const-generics-range.rs @@ -11,7 +11,7 @@ const RANGE : _Range<{ 0 .. 1000 }> = _Range; // `RangeFrom` should be usable within const generics: struct _RangeFrom>; -//[min]~^ ERROR `RangeFrom` is forbidden +//[min]~^ ERROR `std::ops::RangeFrom` is forbidden const RANGE_FROM : _RangeFrom<{ 0 .. }> = _RangeFrom; // `RangeFull` should be usable within const generics: @@ -22,7 +22,7 @@ const RANGE_FULL : _RangeFull<{ .. }> = _RangeFull; // Regression test for #70155 // `RangeInclusive` should be usable within const generics: struct _RangeInclusive>; -//[min]~^ ERROR `RangeInclusive` is forbidden +//[min]~^ ERROR `std::ops::RangeInclusive` is forbidden const RANGE_INCLUSIVE : _RangeInclusive<{ 0 ..= 999 }> = _RangeInclusive; // `RangeTo` should be usable within const generics: diff --git a/tests/ui/const-generics/type-dependent/issue-69816.rs b/tests/ui/const-generics/type-dependent/issue-69816.rs index cbb6b398e015b..e1d3315737a28 100644 --- a/tests/ui/const-generics/type-dependent/issue-69816.rs +++ b/tests/ui/const-generics/type-dependent/issue-69816.rs @@ -12,6 +12,6 @@ impl IterExt for T {} fn main(){ const N: usize = 10; - let arr = (0u32..10).default_for_size::(); + let arr = (0u32..10).into_iter().default_for_size::(); assert_eq!(arr, [0; 10]); } diff --git a/tests/ui/const-generics/type-dependent/issue-73730.rs b/tests/ui/const-generics/type-dependent/issue-73730.rs index 5e1b8c6353723..1c8f949bfa585 100644 --- a/tests/ui/const-generics/type-dependent/issue-73730.rs +++ b/tests/ui/const-generics/type-dependent/issue-73730.rs @@ -10,5 +10,5 @@ impl<'a, A, I: ?Sized> Foo<'a, A> for I where I: Iterator { } fn main() { - (0_u8 .. 10).bar::<10_usize>(); + (0_u8 .. 10).into_iter().bar::<10_usize>(); } diff --git a/tests/ui/consts/const-fn-error.stderr b/tests/ui/consts/const-fn-error.stderr index f735b3d53ce43..2fe467feadddd 100644 --- a/tests/ui/consts/const-fn-error.stderr +++ b/tests/ui/consts/const-fn-error.stderr @@ -20,7 +20,7 @@ LL | for i in 0..x { | ^^^^ | note: impl defined here, but it is not `const` - --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL + --> $SRC_DIR/core/src/iter/range.rs:LL:COL = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable @@ -33,7 +33,7 @@ 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]: cannot call non-const fn ` as Iterator>::next` in constant functions +error[E0015]: cannot call non-const fn ` as Iterator>::next` in constant functions --> $DIR/const-fn-error.rs:5:14 | LL | for i in 0..x { diff --git a/tests/ui/consts/const-for.stderr b/tests/ui/consts/const-for.stderr index 3fb9787c0d868..5734506a10fc9 100644 --- a/tests/ui/consts/const-for.stderr +++ b/tests/ui/consts/const-for.stderr @@ -5,11 +5,11 @@ LL | for _ in 0..5 {} | ^^^^ | note: impl defined here, but it is not `const` - --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL + --> $SRC_DIR/core/src/iter/range.rs:LL:COL = note: calls in constants are limited to constant functions, tuple structs and tuple variants = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable -error[E0015]: cannot call non-const fn ` as Iterator>::next` in constants +error[E0015]: cannot call non-const fn ` as Iterator>::next` in constants --> $DIR/const-for.rs:5:14 | LL | for _ in 0..5 {} diff --git a/tests/ui/impl-trait/example-calendar.rs b/tests/ui/impl-trait/example-calendar.rs index da45f0d133deb..35df593787919 100644 --- a/tests/ui/impl-trait/example-calendar.rs +++ b/tests/ui/impl-trait/example-calendar.rs @@ -316,7 +316,7 @@ fn test_spaces() { /// Returns an iterator of dates in a given year. fn dates_in_year(year: i32) -> impl Iterator+Clone { InGroup { - it: NaiveDate::from_ymd(year, 1, 1).., + it: (NaiveDate::from_ymd(year, 1, 1)..).into_iter(), f: |d: &NaiveDate| d.year(), g: year } diff --git a/tests/ui/impl-trait/issue-99642-2.rs b/tests/ui/impl-trait/issue-99642-2.rs index 0e88b363338a9..9e97df0d180bd 100644 --- a/tests/ui/impl-trait/issue-99642-2.rs +++ b/tests/ui/impl-trait/issue-99642-2.rs @@ -3,6 +3,6 @@ #![feature(type_alias_impl_trait)] type Opq = impl Sized; fn test() -> impl Iterator { - Box::new(0..) as Box> + Box::new((0..).into_iter()) as Box> } fn main(){} diff --git a/tests/ui/impl-trait/issue-99642.rs b/tests/ui/impl-trait/issue-99642.rs index 75af60491e438..6219785fe25b4 100644 --- a/tests/ui/impl-trait/issue-99642.rs +++ b/tests/ui/impl-trait/issue-99642.rs @@ -1,7 +1,7 @@ // check-pass fn test() -> impl Iterator { - Box::new(0..) as Box> + Box::new((0..).into_iter()) as Box> } fn main() {} diff --git a/tests/ui/issues/issue-13058.rs b/tests/ui/issues/issue-13058.rs index a5806feb720d6..ba294257ae2a1 100644 --- a/tests/ui/issues/issue-13058.rs +++ b/tests/ui/issues/issue-13058.rs @@ -1,11 +1,11 @@ -use std::ops::Range; +use std::ops::range::legacy::Range; trait Itble<'r, T, I: Iterator> { fn iter(&'r self) -> I; } impl<'r> Itble<'r, usize, Range> for (usize, usize) { fn iter(&'r self) -> Range { let &(min, max) = self; - min..max + Range::from(min..max) } } diff --git a/tests/ui/issues/issue-46771.rs b/tests/ui/issues/issue-46771.rs index 22be8d6af8a7f..32e7668a5a242 100644 --- a/tests/ui/issues/issue-46771.rs +++ b/tests/ui/issues/issue-46771.rs @@ -1,4 +1,4 @@ fn main() { struct Foo; - (1 .. 2).find(|_| Foo(0) == 0); //~ ERROR expected function, found `Foo` + (1 .. 2).into_iter().find(|_| Foo(0) == 0); //~ ERROR expected function, found `Foo` } diff --git a/tests/ui/issues/issue-46771.stderr b/tests/ui/issues/issue-46771.stderr index fab55fbfd704a..4000b1fef117d 100644 --- a/tests/ui/issues/issue-46771.stderr +++ b/tests/ui/issues/issue-46771.stderr @@ -1,12 +1,12 @@ error[E0618]: expected function, found `Foo` - --> $DIR/issue-46771.rs:3:23 + --> $DIR/issue-46771.rs:3:35 | LL | struct Foo; | ---------- `Foo` defined here -LL | (1 .. 2).find(|_| Foo(0) == 0); - | ^^^--- - | | - | call expression requires function +LL | (1 .. 2).into_iter().find(|_| Foo(0) == 0); + | ^^^--- + | | + | call expression requires function error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-76191.stderr b/tests/ui/issues/issue-76191.stderr index 32d9105b25997..4e65c5dac122c 100644 --- a/tests/ui/issues/issue-76191.stderr +++ b/tests/ui/issues/issue-76191.stderr @@ -13,7 +13,7 @@ LL | RANGE => {} | `RANGE` is interpreted as a constant, not a new binding | = note: expected type `i32` - found struct `RangeInclusive` + found struct `std::ops::RangeInclusive` help: you may want to move the range into the match block | LL | 0..=255 => {} @@ -35,7 +35,7 @@ LL | RANGE2 => {} | `RANGE2` is interpreted as a constant, not a new binding | = note: expected type `i32` - found struct `RangeInclusive` + found struct `std::ops::RangeInclusive` = note: constants only support matching by type, if you meant to match against a range of values, consider using a range pattern like `min ..= max` in the match block error: aborting due to 2 previous errors diff --git a/tests/ui/iterators/collect-into-array.rs b/tests/ui/iterators/collect-into-array.rs index 99d0d9bd73553..5504dc037f881 100644 --- a/tests/ui/iterators/collect-into-array.rs +++ b/tests/ui/iterators/collect-into-array.rs @@ -2,5 +2,5 @@ fn main() { let whatever: [u32; 10] = (0..10).collect(); //~^ ERROR an array of type `[u32; 10]` cannot be built directly from an iterator //~| NOTE try collecting into a `Vec<{integer}>`, then using `.try_into()` - //~| NOTE required by a bound in `collect` + //~| NOTE required by a bound in `iter::range::>::collect` } diff --git a/tests/ui/iterators/collect-into-array.stderr b/tests/ui/iterators/collect-into-array.stderr index 38e5de803ccf0..0542695f0d523 100644 --- a/tests/ui/iterators/collect-into-array.stderr +++ b/tests/ui/iterators/collect-into-array.stderr @@ -5,8 +5,9 @@ LL | let whatever: [u32; 10] = (0..10).collect(); | ^^^^^^^ try collecting into a `Vec<{integer}>`, then using `.try_into()` | = help: the trait `FromIterator<{integer}>` is not implemented for `[u32; 10]` -note: required by a bound in `collect` - --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL +note: required by a bound in `iter::range::>::collect` + --> $SRC_DIR/core/src/iter/range.rs:LL:COL + = note: this error originates in the macro `iter_methods` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/iterators/collect-into-slice.rs b/tests/ui/iterators/collect-into-slice.rs index 045d40a6f71ae..9ce6a745e05bc 100644 --- a/tests/ui/iterators/collect-into-slice.rs +++ b/tests/ui/iterators/collect-into-slice.rs @@ -8,8 +8,8 @@ fn main() { //~| ERROR the size for values of type `[i32]` cannot be known at compilation time //~| ERROR a slice of type `[i32]` cannot be built since `[i32]` has no definite size //~| NOTE try explicitly collecting into a `Vec<{integer}>` - //~| NOTE required by a bound in `collect` - //~| NOTE required by a bound in `collect` + //~| NOTE required by a bound in `iter::range::>::collect` + //~| NOTE required by a bound in `iter::range::>::collect` //~| NOTE all local variables must have a statically known size //~| NOTE doesn't have a size known at compile-time //~| NOTE doesn't have a size known at compile-time @@ -18,6 +18,6 @@ fn main() { let some_generated_vec = (0..10).collect(); //~^ ERROR a slice of type `&[i32]` cannot be built since we need to store the elements somewhere //~| NOTE try explicitly collecting into a `Vec<{integer}>` - //~| NOTE required by a bound in `collect` + //~| NOTE required by a bound in `iter::range::>::collect` process_slice(some_generated_vec); } diff --git a/tests/ui/iterators/collect-into-slice.stderr b/tests/ui/iterators/collect-into-slice.stderr index 45685ef0ce9cd..04ab5a30d8fb5 100644 --- a/tests/ui/iterators/collect-into-slice.stderr +++ b/tests/ui/iterators/collect-into-slice.stderr @@ -5,8 +5,9 @@ LL | let some_generated_vec = (0..10).collect(); | ^^^^^^^ try explicitly collecting into a `Vec<{integer}>` | = help: the trait `FromIterator<{integer}>` is not implemented for `[i32]` -note: required by a bound in `collect` - --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL +note: required by a bound in `iter::range::>::collect` + --> $SRC_DIR/core/src/iter/range.rs:LL:COL + = note: this error originates in the macro `iter_methods` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the size for values of type `[i32]` cannot be known at compilation time --> $DIR/collect-into-slice.rs:6:9 @@ -25,8 +26,9 @@ LL | let some_generated_vec = (0..10).collect(); | ^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[i32]` -note: required by a bound in `collect` - --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL +note: required by a bound in `iter::range::>::collect` + --> $SRC_DIR/core/src/iter/range.rs:LL:COL + = note: this error originates in the macro `iter_methods` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: a slice of type `&[i32]` cannot be built since we need to store the elements somewhere --> $DIR/collect-into-slice.rs:18:38 @@ -35,8 +37,9 @@ LL | let some_generated_vec = (0..10).collect(); | ^^^^^^^ try explicitly collecting into a `Vec<{integer}>` | = help: the trait `FromIterator<{integer}>` is not implemented for `&[i32]` -note: required by a bound in `collect` - --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL +note: required by a bound in `iter::range::>::collect` + --> $SRC_DIR/core/src/iter/range.rs:LL:COL + = note: this error originates in the macro `iter_methods` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 4 previous errors diff --git a/tests/ui/iterators/into-iterator-type-inference-shift.rs b/tests/ui/iterators/into-iterator-type-inference-shift.rs index 9151172fd15ed..e03aed704433d 100644 --- a/tests/ui/iterators/into-iterator-type-inference-shift.rs +++ b/tests/ui/iterators/into-iterator-type-inference-shift.rs @@ -26,7 +26,7 @@ impl IntoIterator for I where I: Iterator { fn desugared_for_loop_bad(byte: u8) -> u8 { let mut result = 0; - let mut x = IntoIterator::into_iter(0..8); + let mut x = IntoIterator::into_iter((0..8).into_iter()); let mut y = Iterator::next(&mut x); let mut z = y.unwrap(); byte >> z; diff --git a/tests/ui/iterators/iter-map-fold-type-length.rs b/tests/ui/iterators/iter-map-fold-type-length.rs index 8ce4fcd873174..8c1c36e12955b 100644 --- a/tests/ui/iterators/iter-map-fold-type-length.rs +++ b/tests/ui/iterators/iter-map-fold-type-length.rs @@ -20,7 +20,7 @@ where } fn main() { - let c = Iter(0i32..10) + let c = Iter((0i32..10).into_iter()) .map(|x| x) .map(|x| x) .map(|x| x) diff --git a/tests/ui/iterators/iter-step-overflow-debug.rs b/tests/ui/iterators/iter-step-overflow-debug.rs index 6aa349ebed29b..585774f56113c 100644 --- a/tests/ui/iterators/iter-step-overflow-debug.rs +++ b/tests/ui/iterators/iter-step-overflow-debug.rs @@ -4,6 +4,7 @@ use std::panic; +#[allow(deprecated)] fn main() { let r = panic::catch_unwind(|| { let mut it = u8::MAX..; diff --git a/tests/ui/iterators/iter-step-overflow-ndebug.rs b/tests/ui/iterators/iter-step-overflow-ndebug.rs index 33e708769badb..b5e636b5dd3aa 100644 --- a/tests/ui/iterators/iter-step-overflow-ndebug.rs +++ b/tests/ui/iterators/iter-step-overflow-ndebug.rs @@ -1,6 +1,7 @@ // run-pass // compile-flags: -C debug_assertions=no +#[allow(deprecated)] fn main() { let mut it = u8::MAX..; assert_eq!(it.next().unwrap(), 255); diff --git a/tests/ui/lifetimes/bare-trait-object-borrowck.rs b/tests/ui/lifetimes/bare-trait-object-borrowck.rs index 45f5e4ae129a1..4ac638b8df234 100644 --- a/tests/ui/lifetimes/bare-trait-object-borrowck.rs +++ b/tests/ui/lifetimes/bare-trait-object-borrowck.rs @@ -20,5 +20,5 @@ where } fn main() { - let _ = new_format(0..32, " | ", |i, f| f(&format_args!("0x{:x}", i))); + let _ = new_format((0..32).into_iter(), " | ", |i, f| f(&format_args!("0x{:x}", i))); } diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.fixed b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.fixed index 6315fcca2b8b0..72b354cf9cf78 100644 --- a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.fixed +++ b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.fixed @@ -1,5 +1,5 @@ // run-rustfix fn main() { - let _ = (-10..=10).find(|x: &i32| x.signum() == 0); //~ ERROR type mismatch in closure arguments - let _ = (-10..=10).find(|x: &i32| x.signum() == 0); //~ ERROR type mismatch in closure arguments + let _ = (-10..=10).into_iter().find(|x: &i32| x.signum() == 0); //~ ERROR type mismatch in closure arguments + let _ = (-10..=10).into_iter().find(|x: &i32| x.signum() == 0); //~ ERROR type mismatch in closure arguments } diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.rs b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.rs index c12c5362efcfe..b38fd25df3f4d 100644 --- a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.rs +++ b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.rs @@ -1,5 +1,5 @@ // run-rustfix fn main() { - let _ = (-10..=10).find(|x: i32| x.signum() == 0); //~ ERROR type mismatch in closure arguments - let _ = (-10..=10).find(|x: &&&i32| x.signum() == 0); //~ ERROR type mismatch in closure arguments + let _ = (-10..=10).into_iter().find(|x: i32| x.signum() == 0); //~ ERROR type mismatch in closure arguments + let _ = (-10..=10).into_iter().find(|x: &&&i32| x.signum() == 0); //~ ERROR type mismatch in closure arguments } diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.stderr b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.stderr index 452cba6b4de70..f823eade10550 100644 --- a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.stderr +++ b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.stderr @@ -1,10 +1,10 @@ error[E0631]: type mismatch in closure arguments - --> $DIR/closure-arg-type-mismatch-issue-45727.rs:3:24 + --> $DIR/closure-arg-type-mismatch-issue-45727.rs:3:36 | -LL | let _ = (-10..=10).find(|x: i32| x.signum() == 0); - | ^^^^ -------- found signature defined here - | | - | expected due to this +LL | let _ = (-10..=10).into_iter().find(|x: i32| x.signum() == 0); + | ^^^^ -------- found signature defined here + | | + | expected due to this | = note: expected closure signature `for<'a> fn(&'a {integer}) -> _` found closure signature `fn(i32) -> _` @@ -12,16 +12,16 @@ note: required by a bound in `find` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL help: consider adjusting the signature so it borrows its argument | -LL | let _ = (-10..=10).find(|x: &i32| x.signum() == 0); - | + +LL | let _ = (-10..=10).into_iter().find(|x: &i32| x.signum() == 0); + | + error[E0631]: type mismatch in closure arguments - --> $DIR/closure-arg-type-mismatch-issue-45727.rs:4:24 + --> $DIR/closure-arg-type-mismatch-issue-45727.rs:4:36 | -LL | let _ = (-10..=10).find(|x: &&&i32| x.signum() == 0); - | ^^^^ ----------- found signature defined here - | | - | expected due to this +LL | let _ = (-10..=10).into_iter().find(|x: &&&i32| x.signum() == 0); + | ^^^^ ----------- found signature defined here + | | + | expected due to this | = note: expected closure signature `for<'a> fn(&'a {integer}) -> _` found closure signature `for<'a, 'b, 'c> fn(&'a &'b &'c i32) -> _` @@ -29,8 +29,8 @@ note: required by a bound in `find` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL help: consider adjusting the signature so it does not borrow its argument | -LL - let _ = (-10..=10).find(|x: &&&i32| x.signum() == 0); -LL + let _ = (-10..=10).find(|x: &i32| x.signum() == 0); +LL - let _ = (-10..=10).into_iter().find(|x: &&&i32| x.signum() == 0); +LL + let _ = (-10..=10).into_iter().find(|x: &i32| x.signum() == 0); | error: aborting due to 2 previous errors diff --git a/tests/ui/never_type/issue-52443.stderr b/tests/ui/never_type/issue-52443.stderr index 59292ed68a306..8931aa1927ac1 100644 --- a/tests/ui/never_type/issue-52443.stderr +++ b/tests/ui/never_type/issue-52443.stderr @@ -40,14 +40,14 @@ help: give it a value of the expected type LL | [(); loop { break 42 }]; | ++ -error[E0015]: cannot convert `RangeFrom` into an iterator in constants +error[E0015]: cannot convert `std::ops::RangeFrom` into an iterator in constants --> $DIR/issue-52443.rs:9:21 | LL | [(); { for _ in 0usize.. {}; 0}]; | ^^^^^^^^ | note: impl defined here, but it is not `const` - --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL + --> $SRC_DIR/core/src/iter/range.rs:LL:COL = note: calls in constants are limited to constant functions, tuple structs and tuple variants = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable @@ -60,7 +60,7 @@ LL | [(); { for _ in 0usize.. {}; 0}]; = note: see issue #57349 for more information = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable -error[E0015]: cannot call non-const fn ` as Iterator>::next` in constants +error[E0015]: cannot call non-const fn ` as Iterator>::next` in constants --> $DIR/issue-52443.rs:9:21 | LL | [(); { for _ in 0usize.. {}; 0}]; diff --git a/tests/ui/nll/issue-51512.rs b/tests/ui/nll/issue-51512.rs index 691760eb91e52..71ef84d58471c 100644 --- a/tests/ui/nll/issue-51512.rs +++ b/tests/ui/nll/issue-51512.rs @@ -2,5 +2,9 @@ fn main() { let range = 0..1; let r = range; let x = range.start; + + let range = std::ops::range::legacy::Range::from(0..1); + let r = range; + let x = range.start; //~^ ERROR use of moved value: `range` [E0382] } diff --git a/tests/ui/nll/issue-51512.stderr b/tests/ui/nll/issue-51512.stderr index ed42899dc94fc..1aa2d75f0308c 100644 --- a/tests/ui/nll/issue-51512.stderr +++ b/tests/ui/nll/issue-51512.stderr @@ -1,8 +1,8 @@ error[E0382]: use of moved value: `range` - --> $DIR/issue-51512.rs:4:13 + --> $DIR/issue-51512.rs:8:13 | -LL | let range = 0..1; - | ----- move occurs because `range` has type `std::ops::Range`, which does not implement the `Copy` trait +LL | let range = std::ops::range::legacy::Range::from(0..1); + | ----- move occurs because `range` has type `std::ops::range::legacy::Range`, which does not implement the `Copy` trait LL | let r = range; | ----- value moved here LL | let x = range.start; diff --git a/tests/ui/range/issue-54505-no-literals.stderr b/tests/ui/range/issue-54505-no-literals.stderr index 5894bb6ba553f..c6d4384bcd33c 100644 --- a/tests/ui/range/issue-54505-no-literals.stderr +++ b/tests/ui/range/issue-54505-no-literals.stderr @@ -47,7 +47,7 @@ LL | take_range(std::ops::RangeFrom { start: 1 }); | arguments to this function are incorrect | = note: expected reference `&_` - found struct `RangeFrom<{integer}>` + found struct `std::ops::RangeFrom<{integer}>` note: function defined here --> $DIR/issue-54505-no-literals.rs:12:4 | @@ -67,7 +67,7 @@ LL | take_range(::std::ops::RangeFrom { start: 1 }); | arguments to this function are incorrect | = note: expected reference `&_` - found struct `RangeFrom<{integer}>` + found struct `std::ops::RangeFrom<{integer}>` note: function defined here --> $DIR/issue-54505-no-literals.rs:12:4 | @@ -127,7 +127,7 @@ LL | take_range(std::ops::RangeInclusive::new(0, 1)); | arguments to this function are incorrect | = note: expected reference `&_` - found struct `RangeInclusive<{integer}>` + found struct `std::ops::RangeInclusive<{integer}>` note: function defined here --> $DIR/issue-54505-no-literals.rs:12:4 | @@ -147,7 +147,7 @@ LL | take_range(::std::ops::RangeInclusive::new(0, 1)); | arguments to this function are incorrect | = note: expected reference `&_` - found struct `RangeInclusive<{integer}>` + found struct `std::ops::RangeInclusive<{integer}>` note: function defined here --> $DIR/issue-54505-no-literals.rs:12:4 | diff --git a/tests/ui/range/issue-54505-no-std.stderr b/tests/ui/range/issue-54505-no-std.stderr index 1694d514f4251..f15a0ae61389a 100644 --- a/tests/ui/range/issue-54505-no-std.stderr +++ b/tests/ui/range/issue-54505-no-std.stderr @@ -7,7 +7,7 @@ LL | take_range(0..1); | arguments to this function are incorrect | = note: expected reference `&_` - found struct `Range<{integer}>` + found struct `core::ops::Range<{integer}>` note: function defined here --> $DIR/issue-54505-no-std.rs:25:4 | @@ -27,7 +27,7 @@ LL | take_range(1..); | arguments to this function are incorrect | = note: expected reference `&_` - found struct `RangeFrom<{integer}>` + found struct `core::ops::RangeFrom<{integer}>` note: function defined here --> $DIR/issue-54505-no-std.rs:25:4 | @@ -67,7 +67,7 @@ LL | take_range(0..=1); | arguments to this function are incorrect | = note: expected reference `&_` - found struct `RangeInclusive<{integer}>` + found struct `core::ops::RangeInclusive<{integer}>` note: function defined here --> $DIR/issue-54505-no-std.rs:25:4 | diff --git a/tests/ui/range/issue-54505.stderr b/tests/ui/range/issue-54505.stderr index 0e959fc05e279..2137147a9465e 100644 --- a/tests/ui/range/issue-54505.stderr +++ b/tests/ui/range/issue-54505.stderr @@ -27,7 +27,7 @@ LL | take_range(1..); | arguments to this function are incorrect | = note: expected reference `&_` - found struct `RangeFrom<{integer}>` + found struct `std::ops::RangeFrom<{integer}>` note: function defined here --> $DIR/issue-54505.rs:10:4 | @@ -67,7 +67,7 @@ LL | take_range(0..=1); | arguments to this function are incorrect | = note: expected reference `&_` - found struct `RangeInclusive<{integer}>` + found struct `std::ops::RangeInclusive<{integer}>` note: function defined here --> $DIR/issue-54505.rs:10:4 | diff --git a/tests/ui/range/range-1.rs b/tests/ui/range/range-1.rs index 192426fe228fe..a64ddd9aeb262 100644 --- a/tests/ui/range/range-1.rs +++ b/tests/ui/range/range-1.rs @@ -7,7 +7,7 @@ pub fn main() { // Bool => does not implement iterator. for i in false..true {} - //~^ ERROR `bool: Step` is not satisfied + //~^ ERROR `std::ops::Range: IntoIterator` is not satisfied // Unsized type. let arr: &[_] = &[1, 2, 3]; diff --git a/tests/ui/range/range-1.stderr b/tests/ui/range/range-1.stderr index 96c1ffb2f7e32..7c0fff4e1e2fd 100644 --- a/tests/ui/range/range-1.stderr +++ b/tests/ui/range/range-1.stderr @@ -4,24 +4,16 @@ error[E0308]: mismatched types LL | let _ = 0u32..10i32; | ^^^^^ expected `u32`, found `i32` -error[E0277]: the trait bound `bool: Step` is not satisfied +error[E0277]: the trait bound `std::ops::Range: IntoIterator` is not satisfied --> $DIR/range-1.rs:9:14 | LL | for i in false..true {} - | ^^^^^^^^^^^ the trait `Step` is not implemented for `bool` + | ^^^^^^^^^^^ the trait `IntoIterator` is not implemented for `std::ops::Range` | - = help: the following other types implement trait `Step`: - char - isize - i8 - i16 - i32 - i64 - i128 - usize - and 8 others - = note: required for `std::ops::Range` to implement `Iterator` - = note: required for `std::ops::Range` to implement `IntoIterator` + = help: the following other types implement trait `IntoIterator`: + std::ops::Range + &'a mut std::ops::Range + &std::ops::Range error[E0277]: the size for values of type `[{integer}]` cannot be known at compilation time --> $DIR/range-1.rs:14:17 @@ -30,7 +22,7 @@ LL | let range = *arr..; | ^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[{integer}]` -note: required by a bound in `RangeFrom` +note: required by a bound in `std::ops::RangeFrom` --> $SRC_DIR/core/src/ops/range.rs:LL:COL error: aborting due to 3 previous errors diff --git a/tests/ui/range/range_traits-1.stderr b/tests/ui/range/range_traits-1.stderr index 617afc995305e..b55eb054f699c 100644 --- a/tests/ui/range/range_traits-1.stderr +++ b/tests/ui/range/range_traits-1.stderr @@ -1,13 +1,13 @@ -error[E0277]: can't compare `std::ops::Range` with `std::ops::Range` +error[E0277]: can't compare `std::ops::Range` with `_` --> $DIR/range_traits-1.rs:5:5 | LL | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] | ---------- in this derive macro expansion LL | struct AllTheRanges { LL | a: Range, - | ^^^^^^^^^^^^^^^ no implementation for `std::ops::Range < std::ops::Range` and `std::ops::Range > std::ops::Range` + | ^^^^^^^^^^^^^^^ no implementation for `std::ops::Range < _` and `std::ops::Range > _` | - = help: the trait `PartialOrd` is not implemented for `std::ops::Range` + = help: the trait `PartialOrd<_>` is not implemented for `std::ops::Range` = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: can't compare `std::ops::RangeTo` with `std::ops::RangeTo` @@ -22,16 +22,16 @@ LL | b: RangeTo, = help: the trait `PartialOrd` is not implemented for `std::ops::RangeTo` = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0277]: can't compare `std::ops::RangeFrom` with `std::ops::RangeFrom` +error[E0277]: can't compare `std::ops::RangeFrom` with `_` --> $DIR/range_traits-1.rs:11:5 | LL | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] | ---------- in this derive macro expansion ... LL | c: RangeFrom, - | ^^^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeFrom < std::ops::RangeFrom` and `std::ops::RangeFrom > std::ops::RangeFrom` + | ^^^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeFrom < _` and `std::ops::RangeFrom > _` | - = help: the trait `PartialOrd` is not implemented for `std::ops::RangeFrom` + = help: the trait `PartialOrd<_>` is not implemented for `std::ops::RangeFrom` = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: can't compare `std::ops::RangeFull` with `std::ops::RangeFull` @@ -46,16 +46,16 @@ LL | d: RangeFull, = help: the trait `PartialOrd` is not implemented for `std::ops::RangeFull` = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0277]: can't compare `std::ops::RangeInclusive` with `std::ops::RangeInclusive` +error[E0277]: can't compare `std::ops::RangeInclusive` with `_` --> $DIR/range_traits-1.rs:17:5 | LL | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] | ---------- in this derive macro expansion ... LL | e: RangeInclusive, - | ^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeInclusive < std::ops::RangeInclusive` and `std::ops::RangeInclusive > std::ops::RangeInclusive` + | ^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeInclusive < _` and `std::ops::RangeInclusive > _` | - = help: the trait `PartialOrd` is not implemented for `std::ops::RangeInclusive` + = help: the trait `PartialOrd<_>` is not implemented for `std::ops::RangeInclusive` = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: can't compare `std::ops::RangeToInclusive` with `std::ops::RangeToInclusive` diff --git a/tests/ui/range/range_traits-2.rs b/tests/ui/range/range_traits-2.rs index 234d7a64dc8b0..5b24d0e7fa46e 100644 --- a/tests/ui/range/range_traits-2.rs +++ b/tests/ui/range/range_traits-2.rs @@ -1,6 +1,9 @@ -use std::ops::*; +use std::ops::range; + +#[derive(Copy, Clone)] +struct R(range::Range); #[derive(Copy, Clone)] //~ ERROR Copy -struct R(Range); +struct S(range::legacy::Range); fn main() {} diff --git a/tests/ui/range/range_traits-2.stderr b/tests/ui/range/range_traits-2.stderr index 04778eecf569d..26b00e8ed29bf 100644 --- a/tests/ui/range/range_traits-2.stderr +++ b/tests/ui/range/range_traits-2.stderr @@ -1,10 +1,10 @@ error[E0204]: the trait `Copy` cannot be implemented for this type - --> $DIR/range_traits-2.rs:3:10 + --> $DIR/range_traits-2.rs:6:10 | LL | #[derive(Copy, Clone)] | ^^^^ -LL | struct R(Range); - | ------------ this field does not implement `Copy` +LL | struct S(range::legacy::Range); + | --------------------------- this field does not implement `Copy` | = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/range/range_traits-3.rs b/tests/ui/range/range_traits-3.rs index 2d597cce5ad56..70a4f827f2fb7 100644 --- a/tests/ui/range/range_traits-3.rs +++ b/tests/ui/range/range_traits-3.rs @@ -1,6 +1,9 @@ -use std::ops::*; +use std::ops::range; + +#[derive(Copy, Clone)] +struct R(range::RangeFrom); #[derive(Copy, Clone)] //~ ERROR Copy -struct R(RangeFrom); +struct S(range::legacy::RangeFrom); fn main() {} diff --git a/tests/ui/range/range_traits-3.stderr b/tests/ui/range/range_traits-3.stderr index 094cc146b6c1d..c99aef65bea40 100644 --- a/tests/ui/range/range_traits-3.stderr +++ b/tests/ui/range/range_traits-3.stderr @@ -1,10 +1,10 @@ error[E0204]: the trait `Copy` cannot be implemented for this type - --> $DIR/range_traits-3.rs:3:10 + --> $DIR/range_traits-3.rs:6:10 | LL | #[derive(Copy, Clone)] | ^^^^ -LL | struct R(RangeFrom); - | ---------------- this field does not implement `Copy` +LL | struct S(range::legacy::RangeFrom); + | ------------------------------- this field does not implement `Copy` | = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/range/range_traits-6.rs b/tests/ui/range/range_traits-6.rs index bce106bbfe79b..6b6af4bf9853b 100644 --- a/tests/ui/range/range_traits-6.rs +++ b/tests/ui/range/range_traits-6.rs @@ -1,6 +1,9 @@ -use std::ops::*; +use std::ops::range; + +#[derive(Copy, Clone)] +struct R(range::RangeInclusive); #[derive(Copy, Clone)] //~ ERROR Copy -struct R(RangeInclusive); +struct S(range::legacy::RangeInclusive); fn main() {} diff --git a/tests/ui/range/range_traits-6.stderr b/tests/ui/range/range_traits-6.stderr index 7c66d1c749c2e..a5b78bed51986 100644 --- a/tests/ui/range/range_traits-6.stderr +++ b/tests/ui/range/range_traits-6.stderr @@ -1,10 +1,10 @@ error[E0204]: the trait `Copy` cannot be implemented for this type - --> $DIR/range_traits-6.rs:3:10 + --> $DIR/range_traits-6.rs:6:10 | LL | #[derive(Copy, Clone)] | ^^^^ -LL | struct R(RangeInclusive); - | --------------------- this field does not implement `Copy` +LL | struct S(range::legacy::RangeInclusive); + | ------------------------------------ this field does not implement `Copy` | = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/range_inclusive.rs b/tests/ui/range_inclusive.rs index c9107d24ed092..1ecc4b6563354 100644 --- a/tests/ui/range_inclusive.rs +++ b/tests/ui/range_inclusive.rs @@ -68,15 +68,15 @@ pub fn main() { assert_eq!(&stir[ ..=6], "hello w"); // test the size hints and emptying - let mut long = 0..=255u8; - let mut short = 42..=42u8; + let mut long = (0..=255u8).into_iter(); + let mut short = (42..=42u8).into_iter(); assert_eq!(long.size_hint(), (256, Some(256))); assert_eq!(short.size_hint(), (1, Some(1))); long.next(); short.next(); assert_eq!(long.size_hint(), (255, Some(255))); assert_eq!(short.size_hint(), (0, Some(0))); - assert!(short.is_empty()); + assert!(short.inner().is_empty()); assert_eq!(long.len(), 255); assert_eq!(short.len(), 0); @@ -91,25 +91,25 @@ pub fn main() { for i in 3..=251 { assert_eq!(long.next(), Some(i)); } - assert!(long.is_empty()); + assert!(long.inner().is_empty()); // check underflow - let mut narrow = 1..=0; + let mut narrow = (1..=0).into_iter(); assert_eq!(narrow.next_back(), None); - assert!(narrow.is_empty()); - let mut zero = 0u8..=0; + assert!(narrow.inner().is_empty()); + let mut zero = (0u8..=0).into_iter(); assert_eq!(zero.next_back(), Some(0)); assert_eq!(zero.next_back(), None); - assert!(zero.is_empty()); - let mut high = 255u8..=255; + assert!(zero.inner().is_empty()); + let mut high = (255u8..=255).into_iter(); assert_eq!(high.next_back(), Some(255)); assert_eq!(high.next_back(), None); - assert!(high.is_empty()); + assert!(high.inner().is_empty()); // what happens if you have a nonsense range? - let mut nonsense = 10..=5; + let mut nonsense = (10..=5).into_iter(); assert_eq!(nonsense.next(), None); - assert!(nonsense.is_empty()); + assert!(nonsense.inner().is_empty()); // output assert_eq!(format!("{:?}", 0..=10), "0..=10"); diff --git a/tests/ui/recursion/issue-83150.rs b/tests/ui/recursion/issue-83150.rs index 75dcdc59f21c1..2f4b19817a7f7 100644 --- a/tests/ui/recursion/issue-83150.rs +++ b/tests/ui/recursion/issue-83150.rs @@ -5,7 +5,7 @@ // ignore-compare-mode-next-solver (hangs) fn main() { - let mut iter = 0u8..1; + let mut iter = (0u8..1).into_iter(); func(&mut iter) } diff --git a/tests/ui/recursion/issue-83150.stderr b/tests/ui/recursion/issue-83150.stderr index 783f9cf763254..5a6a0dca1a70e 100644 --- a/tests/ui/recursion/issue-83150.stderr +++ b/tests/ui/recursion/issue-83150.stderr @@ -9,12 +9,12 @@ LL | func(&mut iter.map(|x| x + 1)) = help: a `loop` may express intention better if this is on purpose = note: `#[warn(unconditional_recursion)]` on by default -error[E0275]: overflow evaluating the requirement `Map<&mut std::ops::Range, {closure@$DIR/issue-83150.rs:13:24: 13:27}>: Iterator` +error[E0275]: overflow evaluating the requirement `Map<&mut iter::range::RangeIter, {closure@$DIR/issue-83150.rs:13:24: 13:27}>: Iterator` | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_83150`) - = note: required for `&mut Map<&mut std::ops::Range, {closure@$DIR/issue-83150.rs:13:24: 13:27}>` to implement `Iterator` + = note: required for `&mut Map<&mut iter::range::RangeIter, {closure@$DIR/issue-83150.rs:13:24: 13:27}>` to implement `Iterator` = note: 65 redundant requirements hidden - = note: required for `&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut std::ops::Range, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>` to implement `Iterator` + = note: required for `&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut iter::range::RangeIter, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>` to implement `Iterator` error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/suggestions/trait-hidden-method.rs b/tests/ui/suggestions/trait-hidden-method.rs index ae7ef47e1d4de..af3837abdc565 100644 --- a/tests/ui/suggestions/trait-hidden-method.rs +++ b/tests/ui/suggestions/trait-hidden-method.rs @@ -3,7 +3,7 @@ pub fn i_can_has_iterator() -> impl Iterator { //~^ ERROR expected `Box` //~| HELP consider constraining the associated type - Box::new(1..=10) as Box + Box::new((1..=10).into_iter()) as Box //~^ ERROR the value of the associated type `Item` //~| HELP specify the associated type } diff --git a/tests/ui/suggestions/trait-hidden-method.stderr b/tests/ui/suggestions/trait-hidden-method.stderr index 5dec20718467c..5e888806706d5 100644 --- a/tests/ui/suggestions/trait-hidden-method.stderr +++ b/tests/ui/suggestions/trait-hidden-method.stderr @@ -1,8 +1,8 @@ error[E0191]: the value of the associated type `Item` in `Iterator` must be specified - --> $DIR/trait-hidden-method.rs:6:33 + --> $DIR/trait-hidden-method.rs:6:47 | -LL | Box::new(1..=10) as Box - | ^^^^^^^^ help: specify the associated type: `Iterator` +LL | Box::new((1..=10).into_iter()) as Box + | ^^^^^^^^ help: specify the associated type: `Iterator` error[E0271]: expected `Box` to be an iterator that yields `u32`, but it yields `::Item` --> $DIR/trait-hidden-method.rs:3:32 @@ -10,8 +10,8 @@ error[E0271]: expected `Box` to be an iterator that yields `u32`, LL | pub fn i_can_has_iterator() -> impl Iterator { | ^^^^^^^^^^^^^^^^^^^^^^^^^ expected associated type, found `u32` ... -LL | Box::new(1..=10) as Box - | ------------------------------------- return type was inferred to be `Box` here +LL | Box::new((1..=10).into_iter()) as Box + | --------------------------------------------------- return type was inferred to be `Box` here | = note: expected associated type `::Item` found type `u32` diff --git a/tests/ui/suggestions/unnecessary_dot_for_floating_point_literal.stderr b/tests/ui/suggestions/unnecessary_dot_for_floating_point_literal.stderr index 8b48ee9f1247b..c0162ec2cab84 100644 --- a/tests/ui/suggestions/unnecessary_dot_for_floating_point_literal.stderr +++ b/tests/ui/suggestions/unnecessary_dot_for_floating_point_literal.stderr @@ -22,7 +22,7 @@ LL | let _: f64 = 1..; | expected due to this | = note: expected type `f64` - found struct `RangeFrom<{integer}>` + found struct `std::ops::RangeFrom<{integer}>` help: remove the unnecessary `.` operator for a floating point literal | LL | let _: f64 = 1.; diff --git a/tests/ui/type-alias-impl-trait/issue-58951-2.rs b/tests/ui/type-alias-impl-trait/issue-58951-2.rs index e4ba7f8e2a623..e342bc9710c1c 100644 --- a/tests/ui/type-alias-impl-trait/issue-58951-2.rs +++ b/tests/ui/type-alias-impl-trait/issue-58951-2.rs @@ -6,7 +6,7 @@ mod defining_use_scope { pub type A = impl Iterator; pub fn def_a() -> A { - 0..1 + (0..1).into_iter() } } use defining_use_scope::*; diff --git a/tests/ui/type-alias-impl-trait/issue-58951.rs b/tests/ui/type-alias-impl-trait/issue-58951.rs index 7303cbab4a813..7e1a3097555eb 100644 --- a/tests/ui/type-alias-impl-trait/issue-58951.rs +++ b/tests/ui/type-alias-impl-trait/issue-58951.rs @@ -5,7 +5,7 @@ type A = impl Iterator; fn def_a() -> A { - 0..1 + (0..1).into_iter() } pub fn use_a() { diff --git a/tests/ui/typeck/typeck_type_placeholder_item.stderr b/tests/ui/typeck/typeck_type_placeholder_item.stderr index a4325b01f02c4..18d6cef818efb 100644 --- a/tests/ui/typeck/typeck_type_placeholder_item.stderr +++ b/tests/ui/typeck/typeck_type_placeholder_item.stderr @@ -443,7 +443,7 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x); | ^ not allowed in type signatures | -note: however, the inferred type `Map, {closure@typeck_type_placeholder_item.rs:229:29}>, {closure@typeck_type_placeholder_item.rs:229:49}>` cannot be named +note: however, the inferred type `Map, {closure@typeck_type_placeholder_item.rs:229:29}>, {closure@typeck_type_placeholder_item.rs:229:49}>` cannot be named --> $DIR/typeck_type_placeholder_item.rs:229:14 | LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x); From 51bb623494b158638ddf05c856ccd4f5210b540a Mon Sep 17 00:00:00 2001 From: Peter Jaszkowiak Date: Fri, 8 Dec 2023 20:31:32 -0700 Subject: [PATCH 4/6] dep fixes --- Cargo.lock | 35 ++++++++++++++++++++++------------- Cargo.toml | 3 +++ src/tools/tidy/src/extdeps.rs | 6 +++++- 3 files changed, 30 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7f627e2ce6ec1..b5b33de5262de 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3010,9 +3010,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro2" -version = "1.0.63" +version = "1.0.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b368fba921b0dce7e60f5e04ec15e565b3303972b42bcfde1d0713b881959eb" +checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" dependencies = [ "unicode-ident", ] @@ -3068,9 +3068,8 @@ checksum = "07589615d719a60c8dd8a4622e7946465dfef20d1a428f969e3443e7386d5f45" [[package]] name = "quote" -version = "1.0.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "573015e8ab27661678357f27dc26460738fd2b6c86e46f386fde94cb5d913105" +version = "1.0.33" +source = "git+https://github.com/pitaj/quote#44feebf0594b255a511ff20890a7acbf4d6aeed1" dependencies = [ "proc-macro2", ] @@ -3353,11 +3352,10 @@ dependencies = [ [[package]] name = "rustc-rayon" version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb81aadc8837ca6ecebe0fe1353f15df83b3b3cc2cf7a8afd571bc22aa121710" +source = "git+https://github.com/pitaj/rustc-rayon#e76e554512ce25abb48f4118576ede5d7a457918" dependencies = [ "either", - "rustc-rayon-core", + "rustc-rayon-core 0.5.0 (git+https://github.com/pitaj/rustc-rayon)", ] [[package]] @@ -3372,6 +3370,17 @@ dependencies = [ "num_cpus", ] +[[package]] +name = "rustc-rayon-core" +version = "0.5.0" +source = "git+https://github.com/pitaj/rustc-rayon#e76e554512ce25abb48f4118576ede5d7a457918" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-utils", + "num_cpus", +] + [[package]] name = "rustc-semver" version = "1.1.0" @@ -3701,7 +3710,7 @@ dependencies = [ "portable-atomic", "rustc-hash", "rustc-rayon", - "rustc-rayon-core", + "rustc-rayon-core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_arena", "rustc_graphviz", "rustc_index", @@ -4027,7 +4036,7 @@ version = "0.0.0" dependencies = [ "libloading 0.7.4", "rustc-rayon", - "rustc-rayon-core", + "rustc-rayon-core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_ast", "rustc_ast_lowering", "rustc_ast_passes", @@ -4192,7 +4201,7 @@ dependencies = [ "measureme", "polonius-engine", "rustc-rayon", - "rustc-rayon-core", + "rustc-rayon-core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_apfloat", "rustc_arena", "rustc_ast", @@ -4386,7 +4395,7 @@ version = "0.0.0" dependencies = [ "field-offset", "measureme", - "rustc-rayon-core", + "rustc-rayon-core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_data_structures", "rustc_errors", "rustc_hir", @@ -4405,7 +4414,7 @@ name = "rustc_query_system" version = "0.0.0" dependencies = [ "parking_lot 0.12.1", - "rustc-rayon-core", + "rustc-rayon-core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_ast", "rustc_data_structures", "rustc_errors", diff --git a/Cargo.toml b/Cargo.toml index 9b11ae8744b4f..ae3c0c6bb8045 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -111,5 +111,8 @@ rustc-std-workspace-core = { path = 'library/rustc-std-workspace-core' } rustc-std-workspace-alloc = { path = 'library/rustc-std-workspace-alloc' } rustc-std-workspace-std = { path = 'library/rustc-std-workspace-std' } +rustc-rayon = { git = "https://github.com/pitaj/rustc-rayon" } +quote = { git = "https://github.com/pitaj/quote" } + [patch."https://github.com/rust-lang/rust-clippy"] clippy_lints = { path = "src/tools/clippy/clippy_lints" } diff --git a/src/tools/tidy/src/extdeps.rs b/src/tools/tidy/src/extdeps.rs index ff71ca537256f..8b21e8bf7f534 100644 --- a/src/tools/tidy/src/extdeps.rs +++ b/src/tools/tidy/src/extdeps.rs @@ -4,7 +4,11 @@ use std::fs; use std::path::Path; /// List of allowed sources for packages. -const ALLOWED_SOURCES: &[&str] = &["\"registry+https://github.com/rust-lang/crates.io-index\""]; +const ALLOWED_SOURCES: &[&str] = &[ + "\"registry+https://github.com/rust-lang/crates.io-index\"", + "\"git+https://github.com/pitaj/rustc-rayon#e76e554512ce25abb48f4118576ede5d7a457918\"", + "\"git+https://github.com/pitaj/quote#44feebf0594b255a511ff20890a7acbf4d6aeed1\"", +]; /// Checks for external package sources. `root` is the path to the directory that contains the /// workspace `Cargo.toml`. From ab0c62a755cd314628bcf0377319085a67312797 Mon Sep 17 00:00:00 2001 From: Peter Jaszkowiak Date: Fri, 8 Dec 2023 22:43:54 -0700 Subject: [PATCH 5/6] more methods, just in case --- library/core/src/iter/range.rs | 295 ++++++++++++++++++++++++++++++--- 1 file changed, 269 insertions(+), 26 deletions(-) diff --git a/library/core/src/iter/range.rs b/library/core/src/iter/range.rs index 61cfffdb7d1ae..d0ad980d04f30 100644 --- a/library/core/src/iter/range.rs +++ b/library/core/src/iter/range.rs @@ -860,14 +860,6 @@ impl ops::range::Range { pub fn iter_mut(&mut self) -> RangeIterMut<'_, Idx> { RangeIterMut { range: self } } - - /// Shorthand for `.iter_mut().next_back()` - /// - /// See [`DoubleEndedIterator::next_back`] - #[stable(feature = "new_range", since = "1.0.0")] - pub fn next_back(&mut self) -> Option { - self.iter_mut().next_back() - } } #[stable(feature = "new_range", since = "1.0.0")] @@ -1197,14 +1189,6 @@ impl ops::range::RangeInclusive { pub fn iter_mut(&mut self) -> RangeInclusiveIterMut<'_, Idx> { RangeInclusiveIterMut { range: self } } - - /// Shorthand for `.iter_mut().next_back()` - /// - /// See [`DoubleEndedIterator::next_back`] - #[stable(feature = "new_range", since = "1.0.0")] - pub fn next_back(&mut self) -> Option { - self.iter_mut().next_back() - } } #[stable(feature = "new_range", since = "1.0.0")] @@ -1225,11 +1209,22 @@ impl ops::range::$ty { /// /// See [`Iterator::next`] #[stable(feature = "new_range", since = "1.0.0")] - #[deprecated(since = "1.0.0", note = "can cause subtle bugs")] + #[deprecated(since = "1.0.0", note = "range-experiment-mut-self")] pub fn next(&mut self) -> Option { self.iter_mut().next() } + /// Shorthand for `.iter_mut().next_chunk::()`. + /// + /// See [`Iterator::next_chunk`] + #[unstable(feature = "iter_next_chunk", reason = "recently added", issue = "98326")] + #[deprecated(since = "1.0.0", note = "range-experiment-mut-self")] + pub fn next_chunk( + &mut self, + ) -> Result<[Idx; N], crate::array::IntoIter> { + self.iter_mut().next_chunk() + } + /// Shorthand for `.into_iter().size_hint()`. /// /// See [`Iterator::size_hint`] @@ -1254,22 +1249,32 @@ impl ops::range::$ty { self.into_iter().last() } - /// Shorthand for `.into_iter().step_by(...)`. + /// Shorthand for `.iter_mut().advance_by(...)`. /// - /// See [`Iterator::step_by`] - #[stable(feature = "new_range", since = "1.0.0")] - pub fn step_by(self, step: usize) -> crate::iter::StepBy<::IntoIter> { - self.into_iter().step_by(step) + /// See [`Iterator::advance_by`] + #[unstable(feature = "iter_advance_by", reason = "recently added", issue = "77404")] + #[deprecated(since = "1.0.0", note = "range-experiment-mut-self")] + pub fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { + self.iter_mut().advance_by(n) } /// Shorthand for `.iter_mut().nth(...)`. /// /// See [`Iterator::nth`] #[stable(feature = "new_range", since = "1.0.0")] + #[deprecated(since = "1.0.0", note = "range-experiment-mut-self")] pub fn nth(&mut self, n: usize) -> Option { self.iter_mut().nth(n) } + /// Shorthand for `.into_iter().step_by(...)`. + /// + /// See [`Iterator::step_by`] + #[stable(feature = "new_range", since = "1.0.0")] + pub fn step_by(self, step: usize) -> crate::iter::StepBy<::IntoIter> { + self.into_iter().step_by(step) + } + /// Shorthand for `.into_iter().chain(...)` /// /// See [`Iterator::chain`] @@ -1446,6 +1451,28 @@ impl ops::range::$ty { self.into_iter().flat_map(f) } + /// Shorthand for `.into_iter().flatten()` + /// + /// See [`Iterator::flatten`] + #[stable(feature = "new_range", since = "1.0.0")] + pub fn flatten(self) -> crate::iter::Flatten<::IntoIter> + where + Idx: IntoIterator, + { + self.into_iter().flatten() + } + + /// Shorthand for `.into_iter().map_windows()` + /// + /// See [`Iterator::map_windows`] + #[unstable(feature = "iter_map_windows", reason = "recently added", issue = "87155")] + pub fn map_windows(self, f: F) -> crate::iter::MapWindows<::IntoIter, F, N> + where + F: FnMut(&[Idx; N]) -> R, + { + self.into_iter().map_windows(f) + } + /// Shorthand for `.into_iter().fuse()` /// /// See [`Iterator::fuse`] @@ -1465,6 +1492,15 @@ impl ops::range::$ty { self.into_iter().inspect(f) } + /// Alias for `.iter_mut()` + /// + /// See [`Iterator::iter_mut`] + #[stable(feature = "new_range", since = "1.0.0")] + #[deprecated(since = "1.0.0", note = "range-experiment-mut-self")] + pub fn by_ref(&mut self) -> <&mut Self as IntoIterator>::IntoIter { + self.iter_mut() + } + /// Shorthand for `.into_iter().collect()` /// /// See [`Iterator::collect`] @@ -1473,6 +1509,14 @@ impl ops::range::$ty { FromIterator::from_iter(self) } + /// Shorthand for `.into_iter().collect_into(...)` + /// + /// See [`Iterator::collect_into`] + #[unstable(feature = "iter_collect_into", reason = "new API", issue = "94780")] + pub fn collect_into>(self, collection: &mut E) -> &mut E { + self.into_iter().collect_into(collection) + } + /// Shorthand for `.into_iter().partition(...)` /// /// See [`Iterator::partition`] @@ -1485,10 +1529,34 @@ impl ops::range::$ty { self.into_iter().partition(f) } + /// Shorthand for `.into_iter().partition_in_place(...)` + /// + /// See [`Iterator::partition_in_place`] + #[unstable(feature = "iter_partition_in_place", reason = "new API", issue = "62543")] + pub fn partition_in_place<'a, T: 'a, P>(self, predicate: P) -> usize + where + ::IntoIter: DoubleEndedIterator, + P: FnMut(&T) -> bool, + { + self.into_iter().partition_in_place(predicate) + } + + /// Shorthand for `.into_iter().is_partitioned(...)` + /// + /// See [`Iterator::is_partitioned`] + #[unstable(feature = "iter_is_partitioned", reason = "new API", issue = "62544")] + pub fn is_partitioned

(self, predicate: P) -> bool + where + P: FnMut(Idx) -> bool, + { + self.into_iter().is_partitioned(predicate) + } + /// Shorthand for `.into_iter().try_fold(...)` /// /// See [`Iterator::try_fold`] #[stable(feature = "new_range", since = "1.0.0")] + #[deprecated(since = "1.0.0", note = "range-experiment-mut-self")] pub fn try_fold(&mut self, init: B, f: F) -> R where F: FnMut(B, Idx) -> R, @@ -1497,6 +1565,19 @@ impl ops::range::$ty { self.iter_mut().try_fold(init, f) } + /// Shorthand for `.into_iter().try_for_each(...)` + /// + /// See [`Iterator::try_for_each`] + #[stable(feature = "new_range", since = "1.0.0")] + #[deprecated(since = "1.0.0", note = "range-experiment-mut-self")] + pub fn try_for_each(&mut self, f: F) -> R + where + F: FnMut(Idx) -> R, + R: Try, + { + self.iter_mut().try_for_each(f) + } + /// Shorthand for `.into_iter().fold(...)` /// /// See [`Iterator::fold`] @@ -1519,11 +1600,25 @@ impl ops::range::$ty { self.into_iter().reduce(f) } + /// Shorthand for `.into_iter().try_reduce(...)` + /// + /// See [`Iterator::try_reduce`] + #[unstable(feature = "iterator_try_reduce", reason = "new API", issue = "87053")] + #[deprecated(since = "1.0.0", note = "range-experiment-mut-self")] + pub fn try_reduce(&mut self, f: F) -> ops::ChangeOutputType> + where + F: FnMut(Idx, Idx) -> R, + R: Try, + R::Residual: ops::Residual>, + { + self.iter_mut().try_reduce(f) + } + /// Shorthand for `.iter_mut().all(...)` /// /// See [`Iterator::all`] #[stable(feature = "new_range", since = "1.0.0")] - #[deprecated(since = "1.0.0", note = "can cause subtle bugs")] + #[deprecated(since = "1.0.0", note = "range-experiment-mut-self")] pub fn all(&mut self, f: F) -> bool where F: FnMut(Idx) -> bool, @@ -1535,7 +1630,7 @@ impl ops::range::$ty { /// /// See [`Iterator::any`] #[stable(feature = "new_range", since = "1.0.0")] - #[deprecated(since = "1.0.0", note = "can cause subtle bugs")] + #[deprecated(since = "1.0.0", note = "range-experiment-mut-self")] pub fn any(&mut self, f: F) -> bool where F: FnMut(Idx) -> bool, @@ -1547,7 +1642,7 @@ impl ops::range::$ty { /// /// See [`Iterator::find`] #[stable(feature = "new_range", since = "1.0.0")] - #[deprecated(since = "1.0.0", note = "can cause subtle bugs")] + #[deprecated(since = "1.0.0", note = "range-experiment-mut-self")] pub fn find

(&mut self, predicate: P) -> Option where P: FnMut(&Idx) -> bool, @@ -1555,6 +1650,44 @@ impl ops::range::$ty { self.iter_mut().find(predicate) } + /// Shorthand for `.into_iter().find_map(...)` + /// + /// See [`Iterator::find_map`] + #[stable(feature = "new_range", since = "1.0.0")] + #[deprecated(since = "1.0.0", note = "range-experiment-mut-self")] + pub fn find_map(&mut self, f: F) -> Option + where + F: FnMut(Idx) -> Option, + { + self.iter_mut().find_map(f) + } + + /// Shorthand for `.into_iter().try_find(...)` + /// + /// See [`Iterator::try_find`] + #[unstable(feature = "try_find", reason = "new API", issue = "63178")] + #[deprecated(since = "1.0.0", note = "range-experiment-mut-self")] + pub fn try_find(&mut self, f: F) -> ops::ChangeOutputType> + where + F: FnMut(&Idx) -> R, + R: Try, + R::Residual: ops::Residual>, + { + self.iter_mut().try_find(f) + } + + /// Shorthand for `.into_iter().position(...)` + /// + /// See [`Iterator::position`] + #[stable(feature = "new_range", since = "1.0.0")] + #[deprecated(since = "1.0.0", note = "range-experiment-mut-self")] + pub fn position

(&mut self, predicate: P) -> Option + where + P: FnMut(Idx) -> bool, + { + self.iter_mut().position(predicate) + } + /// Shorthand for `.into_iter().max()` /// /// See [`Iterator::max`] @@ -1803,7 +1936,7 @@ impl ops::range::$ty { /// Shorthand for `.into_iter().is_sorted()` /// - /// See [`Iterator::ge`] + /// See [`Iterator::is_sorted`] #[unstable(feature = "is_sorted", reason = "new API", issue = "53485")] pub fn is_sorted(self) -> bool where @@ -1812,6 +1945,30 @@ impl ops::range::$ty { self.into_iter().is_sorted() } + /// Shorthand for `.into_iter().is_sorted_by()` + /// + /// See [`Iterator::is_sorted_by`] + #[unstable(feature = "is_sorted", reason = "new API", issue = "53485")] + pub fn is_sorted_by(self, compare: F) -> bool + where + F: FnMut(&Idx, &Idx) -> Option, + { + self.into_iter().is_sorted_by(compare) + } + + /// Shorthand for `.into_iter().is_sorted()` + /// + /// See [`Iterator::ge`] + #[unstable(feature = "is_sorted", reason = "new API", issue = "53485")] + #[rustc_do_not_const_check] + pub fn is_sorted_by_key(self, f: F) -> bool + where + F: FnMut(Idx) -> K, + K: PartialOrd, + { + self.into_iter().is_sorted_by_key(f) + } + /// Returns the length of the `Range`. #[stable(feature = "new_range", since = "1.0.0")] pub fn len(&self) -> usize @@ -1825,3 +1982,89 @@ impl ops::range::$ty { } iter_methods!(Range, RangeFrom, RangeInclusive); + +macro_rules! de_iter_methods { + ($($ty:ident => $iter_mut:ident),*) => {$( + +impl ops::range::$ty { + /// Shorthand for `.iter_mut().next_back()` + /// + /// See [`DoubleEndedIterator::next_back`] + #[stable(feature = "new_range", since = "1.0.0")] + #[deprecated(since = "1.0.0", note = "range-experiment-mut-self")] + pub fn next_back(&mut self) -> Option { + self.iter_mut().next_back() + } + + /// Shorthand for `.iter_mut().advance_back_by(...)` + /// + /// See [`Iterator::advance_back_by`] + #[unstable(feature = "iter_advance_by", reason = "recently added", issue = "77404")] + #[deprecated(since = "1.0.0", note = "range-experiment-mut-self")] + pub fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { + self.iter_mut().advance_back_by(n) + } + + /// Shorthand for `.iter_mut().nth_back(...)` + /// + /// See [`Iterator::nth_back`] + #[stable(feature = "new_range", since = "1.0.0")] + #[deprecated(since = "1.0.0", note = "range-experiment-mut-self")] + pub fn nth_back(&mut self, n: usize) -> Option { + self.iter_mut().nth_back(n) + } + + /// Shorthand for `.iter_mut().try_rfold(...)` + /// + /// See [`Iterator::try_rfold`] + #[stable(feature = "new_range", since = "1.0.0")] + #[deprecated(since = "1.0.0", note = "range-experiment-mut-self")] + pub fn try_rfold(&mut self, init: B, f: F) -> R + where + F: FnMut(B, Idx) -> R, + R: Try, + { + self.iter_mut().try_rfold(init, f) + } + + /// Shorthand for `.into_iter().rfold(...)` + /// + /// See [`Iterator::rfold`] + #[stable(feature = "new_range", since = "1.0.0")] + pub fn rfold(self, init: B, f: F) -> B + where + F: FnMut(B, Idx) -> B, + { + self.into_iter().rfold(init, f) + } + + /// Shorthand for `.iter_mut().rfind(...)` + /// + /// See [`Iterator::rfind`] + #[stable(feature = "new_range", since = "1.0.0")] + #[deprecated(since = "1.0.0", note = "range-experiment-mut-self")] + pub fn rfind

(&mut self, predicate: P) -> Option + where + P: FnMut(&Idx) -> bool, + { + self.iter_mut().rfind(predicate) + } + + /// Shorthand for `.iter_mut().rposition(...)` + /// + /// See [`Iterator::rposition`] + #[stable(feature = "new_range", since = "1.0.0")] + #[deprecated(since = "1.0.0", note = "range-experiment-mut-self")] + pub fn rposition

(&mut self, predicate: P) -> Option + where + P: FnMut(<$iter_mut<'_, Idx> as Iterator>::Item) -> bool, + for<'a> $iter_mut<'a, Idx>: ExactSizeIterator, + { + self.iter_mut().rposition(predicate) + } +} + + )*} +} + +de_iter_methods!(Range => RangeIterMut, RangeInclusive => RangeInclusiveIterMut); From f74b74c6a9167061e26ee25c42262f8c339ef482 Mon Sep 17 00:00:00 2001 From: Peter Jaszkowiak Date: Fri, 8 Dec 2023 23:19:57 -0700 Subject: [PATCH 6/6] iter mut ExactSizeIterator --- library/core/src/iter/range.rs | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/library/core/src/iter/range.rs b/library/core/src/iter/range.rs index d0ad980d04f30..8f58da4a7ae1a 100644 --- a/library/core/src/iter/range.rs +++ b/library/core/src/iter/range.rs @@ -599,6 +599,9 @@ macro_rules! range_exact_iter_impl { ($($t:ty)*) => ($( #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for RangeIter<$t> { } + + #[stable(feature = "new_range", since = "1.0.0")] + impl ExactSizeIterator for RangeIterMut<'_, $t> { } )*) } @@ -622,6 +625,9 @@ macro_rules! range_incl_exact_iter_impl { ($($t:ty)*) => ($( #[stable(feature = "inclusive_range", since = "1.26.0")] impl ExactSizeIterator for RangeInclusiveIter<$t> { } + + #[stable(feature = "new_range", since = "1.0.0")] + impl ExactSizeIterator for RangeInclusiveIterMut<'_, $t> { } )*) } @@ -839,6 +845,10 @@ impl<'a, Idx: Step> Iterator for RangeIterMut<'a, Idx> { out } + + fn size_hint(&self) -> (usize, Option) { + self.range.size_hint() + } } #[stable(feature = "new_range", since = "1.0.0")] impl<'a, Idx: Step> DoubleEndedIterator for RangeIterMut<'a, Idx> { @@ -953,6 +963,10 @@ impl<'a, Idx: Step> Iterator for RangeFromIterMut<'a, Idx> { out } + + fn size_hint(&self) -> (usize, Option) { + self.range.size_hint() + } } impl ops::range::RangeFrom { @@ -1155,6 +1169,10 @@ impl<'a, Idx: Step> Iterator for RangeInclusiveIterMut<'a, Idx> { out } + + fn size_hint(&self) -> (usize, Option) { + self.range.size_hint() + } } #[stable(feature = "new_range", since = "1.0.0")] impl<'a, Idx: Step> DoubleEndedIterator for RangeInclusiveIterMut<'a, Idx> { @@ -1494,7 +1512,7 @@ impl ops::range::$ty { /// Alias for `.iter_mut()` /// - /// See [`Iterator::iter_mut`] + /// See [`iter_mut`](Self::iter_mut) #[stable(feature = "new_range", since = "1.0.0")] #[deprecated(since = "1.0.0", note = "range-experiment-mut-self")] pub fn by_ref(&mut self) -> <&mut Self as IntoIterator>::IntoIter { @@ -1998,7 +2016,7 @@ impl ops::range::$ty { /// Shorthand for `.iter_mut().advance_back_by(...)` /// - /// See [`Iterator::advance_back_by`] + /// See [`DoubleEndedIterator::advance_back_by`] #[unstable(feature = "iter_advance_by", reason = "recently added", issue = "77404")] #[deprecated(since = "1.0.0", note = "range-experiment-mut-self")] pub fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { @@ -2007,7 +2025,7 @@ impl ops::range::$ty { /// Shorthand for `.iter_mut().nth_back(...)` /// - /// See [`Iterator::nth_back`] + /// See [`DoubleEndedIterator::nth_back`] #[stable(feature = "new_range", since = "1.0.0")] #[deprecated(since = "1.0.0", note = "range-experiment-mut-self")] pub fn nth_back(&mut self, n: usize) -> Option { @@ -2016,7 +2034,7 @@ impl ops::range::$ty { /// Shorthand for `.iter_mut().try_rfold(...)` /// - /// See [`Iterator::try_rfold`] + /// See [`DoubleEndedIterator::try_rfold`] #[stable(feature = "new_range", since = "1.0.0")] #[deprecated(since = "1.0.0", note = "range-experiment-mut-self")] pub fn try_rfold(&mut self, init: B, f: F) -> R @@ -2029,7 +2047,7 @@ impl ops::range::$ty { /// Shorthand for `.into_iter().rfold(...)` /// - /// See [`Iterator::rfold`] + /// See [`DoubleEndedIterator::rfold`] #[stable(feature = "new_range", since = "1.0.0")] pub fn rfold(self, init: B, f: F) -> B where @@ -2040,7 +2058,7 @@ impl ops::range::$ty { /// Shorthand for `.iter_mut().rfind(...)` /// - /// See [`Iterator::rfind`] + /// See [`DoubleEndedIterator::rfind`] #[stable(feature = "new_range", since = "1.0.0")] #[deprecated(since = "1.0.0", note = "range-experiment-mut-self")] pub fn rfind

(&mut self, predicate: P) -> Option

(self, predicate: P) -> crate::iter::TakeWhile<::IntoIter, P> + where + P: FnMut(&Idx) -> bool, + { + self.into_iter().take_while(predicate) + } - try { accum } + /// Shorthand for `.into_iter().map_while(...)` + /// + /// See [`Iterator::map_while`] + #[stable(feature = "new_range", since = "1.0.0")] + pub fn map_while(self, predicate: P) -> crate::iter::MapWhile<::IntoIter, P> + where + P: FnMut(Idx) -> Option, + { + self.into_iter().map_while(predicate) } -} -#[stable(feature = "inclusive_range", since = "1.26.0")] -impl Iterator for ops::RangeInclusive { - type Item = A; + /// Shorthand for `.into_iter().skip(...)` + /// + /// See [`Iterator::skip`] + #[stable(feature = "new_range", since = "1.0.0")] + pub fn skip(self, n: usize) -> crate::iter::Skip<::IntoIter> { + self.into_iter().skip(n) + } - #[inline] - fn next(&mut self) -> Option { - self.spec_next() + /// Shorthand for `.into_iter().take(...)` + /// + /// See [`Iterator::take`] + #[stable(feature = "new_range", since = "1.0.0")] + pub fn take(self, n: usize) -> crate::iter::Take<::IntoIter> { + self.into_iter().take(n) } - #[inline] - fn size_hint(&self) -> (usize, Option) { - if self.is_empty() { - return (0, Some(0)); - } + /// Shorthand for `.into_iter().scan(...)` + /// + /// See [`Iterator::scan`] + #[stable(feature = "new_range", since = "1.0.0")] + pub fn scan(self, initial_state: St, f: F) -> crate::iter::Scan<::IntoIter, St, F> + where + F: FnMut(&mut St, Idx) -> Option, + { + self.into_iter().scan(initial_state, f) + } - match Step::steps_between(&self.start, &self.end) { - Some(hint) => (hint.saturating_add(1), hint.checked_add(1)), - None => (usize::MAX, None), - } + /// Shorthand for `.into_iter().flat_map(...)` + /// + /// See [`Iterator::flat_map`] + #[stable(feature = "new_range", since = "1.0.0")] + pub fn flat_map(self, f: F) -> crate::iter::FlatMap<::IntoIter, U, F> + where + U: IntoIterator, + F: FnMut(Idx) -> U, + { + self.into_iter().flat_map(f) } - #[inline] - fn count(self) -> usize { - if self.is_empty() { - return 0; - } + /// Shorthand for `.into_iter().fuse()` + /// + /// See [`Iterator::fuse`] + #[stable(feature = "new_range", since = "1.0.0")] + pub fn fuse(self) -> crate::iter::Fuse<::IntoIter> { + self.into_iter().fuse() + } - Step::steps_between(&self.start, &self.end) - .and_then(|steps| steps.checked_add(1)) - .expect("count overflowed usize") + /// Shorthand for `.into_iter().inspect(...)` + /// + /// See [`Iterator::inspect`] + #[stable(feature = "new_range", since = "1.0.0")] + pub fn inspect(self, f: F) -> crate::iter::Inspect<::IntoIter, F> + where + F: FnMut(&Idx), + { + self.into_iter().inspect(f) } - #[inline] - fn nth(&mut self, n: usize) -> Option { - if self.is_empty() { - return None; - } + /// Shorthand for `.into_iter().collect()` + /// + /// See [`Iterator::collect`] + #[stable(feature = "new_range", since = "1.0.0")] + pub fn collect>(self) -> B { + FromIterator::from_iter(self) + } - if let Some(plus_n) = Step::forward_checked(self.start.clone(), n) { - use crate::cmp::Ordering::*; + /// Shorthand for `.into_iter().partition(...)` + /// + /// See [`Iterator::partition`] + #[stable(feature = "new_range", since = "1.0.0")] + pub fn partition(self, f: F) -> (B, B) + where + B: Default + Extend, + F: FnMut(&Idx) -> bool, + { + self.into_iter().partition(f) + } - match plus_n.partial_cmp(&self.end) { - Some(Less) => { - self.start = Step::forward(plus_n.clone(), 1); - return Some(plus_n); - } - Some(Equal) => { - self.start = plus_n.clone(); - self.exhausted = true; - return Some(plus_n); - } - _ => {} - } - } + /// Shorthand for `.into_iter().fold(...)` + /// + /// See [`Iterator::fold`] + #[stable(feature = "new_range", since = "1.0.0")] + pub fn fold(self, init: B, f: F) -> B + where + F: FnMut(B, Idx) -> B, + { + self.into_iter().fold(init, f) + } - self.start = self.end.clone(); - self.exhausted = true; - None + /// Shorthand for `.into_iter().reduce(...)` + /// + /// See [`Iterator::reduce`] + #[stable(feature = "new_range", since = "1.0.0")] + pub fn reduce(self, f: F) -> Option + where + F: FnMut(Idx, Idx) -> Idx, + { + self.into_iter().reduce(f) } - #[inline] - fn try_fold(&mut self, init: B, f: F) -> R + /// Shorthand for `.into_iter().all(...)` + /// + /// One noticeable difference is that this takes the + /// range by copy, rather than mutating it in place. + /// + /// See [`Iterator::all`] + #[stable(feature = "new_range", since = "1.0.0")] + #[deprecated(since = "1.0.0", note = "can cause subtle bugs")] + pub fn all(self, f: F) -> bool where - Self: Sized, - F: FnMut(B, Self::Item) -> R, - R: Try, + F: FnMut(Idx) -> bool, { - self.spec_try_fold(init, f) + self.into_iter().all(f) } - impl_fold_via_try_fold! { fold -> try_fold } + /// Shorthand for `.into_iter().any(...)` + /// + /// One noticeable difference is that this takes the + /// range by copy, rather than mutating it in place. + /// + /// See [`Iterator::any`] + #[stable(feature = "new_range", since = "1.0.0")] + #[deprecated(since = "1.0.0", note = "can cause subtle bugs")] + pub fn any(self, f: F) -> bool + where + F: FnMut(Idx) -> bool, + { + self.into_iter().any(f) + } - #[inline] - fn last(mut self) -> Option { - self.next_back() + /// Shorthand for `.into_iter().find(...)` + /// + /// One noticeable difference is that this takes the + /// range by copy, rather than mutating it in place. + /// + /// See [`Iterator::find`] + #[stable(feature = "new_range", since = "1.0.0")] + #[deprecated(since = "1.0.0", note = "can cause subtle bugs")] + pub fn find