diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:20:39 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:20:39 +0000 |
commit | 1376c5a617be5c25655d0d7cb63e3beaa5a6e026 (patch) | |
tree | 3bb8d61aee02bc7a15eab3f36e3b921afc2075d0 /library/core/src/iter | |
parent | Releasing progress-linux version 1.69.0+dfsg1-1~progress7.99u1. (diff) | |
download | rustc-1376c5a617be5c25655d0d7cb63e3beaa5a6e026.tar.xz rustc-1376c5a617be5c25655d0d7cb63e3beaa5a6e026.zip |
Merging upstream version 1.70.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'library/core/src/iter')
-rw-r--r-- | library/core/src/iter/adapters/by_ref_sized.rs | 5 | ||||
-rw-r--r-- | library/core/src/iter/adapters/chain.rs | 73 | ||||
-rw-r--r-- | library/core/src/iter/adapters/cloned.rs | 14 | ||||
-rw-r--r-- | library/core/src/iter/adapters/copied.rs | 19 | ||||
-rw-r--r-- | library/core/src/iter/adapters/cycle.rs | 26 | ||||
-rw-r--r-- | library/core/src/iter/adapters/enumerate.rs | 36 | ||||
-rw-r--r-- | library/core/src/iter/adapters/flatten.rs | 39 | ||||
-rw-r--r-- | library/core/src/iter/adapters/fuse.rs | 15 | ||||
-rw-r--r-- | library/core/src/iter/adapters/rev.rs | 19 | ||||
-rw-r--r-- | library/core/src/iter/adapters/skip.rs | 54 | ||||
-rw-r--r-- | library/core/src/iter/adapters/take.rs | 34 | ||||
-rw-r--r-- | library/core/src/iter/mod.rs | 2 | ||||
-rw-r--r-- | library/core/src/iter/range.rs | 25 | ||||
-rw-r--r-- | library/core/src/iter/sources/repeat.rs | 5 | ||||
-rw-r--r-- | library/core/src/iter/sources/repeat_n.rs | 8 | ||||
-rw-r--r-- | library/core/src/iter/sources/repeat_with.rs | 1 | ||||
-rw-r--r-- | library/core/src/iter/traits/accum.rs | 40 | ||||
-rw-r--r-- | library/core/src/iter/traits/double_ended.rs | 26 | ||||
-rw-r--r-- | library/core/src/iter/traits/iterator.rs | 45 |
19 files changed, 318 insertions, 168 deletions
diff --git a/library/core/src/iter/adapters/by_ref_sized.rs b/library/core/src/iter/adapters/by_ref_sized.rs index 477e7117c..4e0e19ddc 100644 --- a/library/core/src/iter/adapters/by_ref_sized.rs +++ b/library/core/src/iter/adapters/by_ref_sized.rs @@ -1,3 +1,4 @@ +use crate::num::NonZeroUsize; use crate::ops::{NeverShortCircuit, Try}; /// Like `Iterator::by_ref`, but requiring `Sized` so it can forward generics. @@ -26,7 +27,7 @@ impl<I: Iterator> Iterator for ByRefSized<'_, I> { } #[inline] - fn advance_by(&mut self, n: usize) -> Result<(), usize> { + fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { I::advance_by(self.0, n) } @@ -62,7 +63,7 @@ impl<I: DoubleEndedIterator> DoubleEndedIterator for ByRefSized<'_, I> { } #[inline] - fn advance_back_by(&mut self, n: usize) -> Result<(), usize> { + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { I::advance_back_by(self.0, n) } diff --git a/library/core/src/iter/adapters/chain.rs b/library/core/src/iter/adapters/chain.rs index 60eb3a6da..75727c3a2 100644 --- a/library/core/src/iter/adapters/chain.rs +++ b/library/core/src/iter/adapters/chain.rs @@ -1,4 +1,5 @@ use crate::iter::{DoubleEndedIterator, FusedIterator, Iterator, TrustedLen}; +use crate::num::NonZeroUsize; use crate::ops::Try; /// An iterator that links two iterators together, in a chain. @@ -95,38 +96,33 @@ where } #[inline] - fn advance_by(&mut self, n: usize) -> Result<(), usize> { - let mut rem = n; - + fn advance_by(&mut self, mut n: usize) -> Result<(), NonZeroUsize> { if let Some(ref mut a) = self.a { - match a.advance_by(rem) { + n = match a.advance_by(n) { Ok(()) => return Ok(()), - Err(k) => rem -= k, - } + Err(k) => k.get(), + }; self.a = None; } if let Some(ref mut b) = self.b { - match b.advance_by(rem) { - Ok(()) => return Ok(()), - Err(k) => rem -= k, - } + return b.advance_by(n); // we don't fuse the second iterator } - if rem == 0 { Ok(()) } else { Err(n - rem) } + NonZeroUsize::new(n).map_or(Ok(()), Err) } #[inline] fn nth(&mut self, mut n: usize) -> Option<Self::Item> { if let Some(ref mut a) = self.a { - match a.advance_by(n) { + n = match a.advance_by(n) { Ok(()) => match a.next() { - None => n = 0, + None => 0, x => return x, }, - Err(k) => n -= k, - } + Err(k) => k.get(), + }; self.a = None; } @@ -186,38 +182,33 @@ where } #[inline] - fn advance_back_by(&mut self, n: usize) -> Result<(), usize> { - let mut rem = n; - + fn advance_back_by(&mut self, mut n: usize) -> Result<(), NonZeroUsize> { if let Some(ref mut b) = self.b { - match b.advance_back_by(rem) { + n = match b.advance_back_by(n) { Ok(()) => return Ok(()), - Err(k) => rem -= k, - } + Err(k) => k.get(), + }; self.b = None; } if let Some(ref mut a) = self.a { - match a.advance_back_by(rem) { - Ok(()) => return Ok(()), - Err(k) => rem -= k, - } + return a.advance_back_by(n); // we don't fuse the second iterator } - if rem == 0 { Ok(()) } else { Err(n - rem) } + NonZeroUsize::new(n).map_or(Ok(()), Err) } #[inline] fn nth_back(&mut self, mut n: usize) -> Option<Self::Item> { if let Some(ref mut b) = self.b { - match b.advance_back_by(n) { + n = match b.advance_back_by(n) { Ok(()) => match b.next_back() { - None => n = 0, + None => 0, x => return x, }, - Err(k) => n -= k, - } + Err(k) => k.get(), + }; self.b = None; } @@ -282,6 +273,28 @@ where { } +#[stable(feature = "default_iters", since = "1.70.0")] +impl<A: Default, B: Default> Default for Chain<A, B> { + /// Creates a `Chain` from the default values for `A` and `B`. + /// + /// ``` + /// # use core::iter::Chain; + /// # use core::slice; + /// # use std::collections::{btree_set, BTreeSet}; + /// # use std::mem; + /// struct Foo<'a>(Chain<slice::Iter<'a, u8>, btree_set::Iter<'a, u8>>); + /// + /// let set = BTreeSet::<u8>::new(); + /// let slice: &[u8] = &[]; + /// let mut foo = Foo(slice.iter().chain(set.iter())); + /// + /// // take requires `Default` + /// let _: Chain<_, _> = mem::take(&mut foo.0); + fn default() -> Self { + Chain::new(Default::default(), Default::default()) + } +} + #[inline] fn and_then_or_clear<T, U>(opt: &mut Option<T>, f: impl FnOnce(&mut T) -> Option<U>) -> Option<U> { let x = f(opt.as_mut()?); diff --git a/library/core/src/iter/adapters/cloned.rs b/library/core/src/iter/adapters/cloned.rs index 914ff86c1..d3cceb8d4 100644 --- a/library/core/src/iter/adapters/cloned.rs +++ b/library/core/src/iter/adapters/cloned.rs @@ -153,3 +153,17 @@ where item.clone() } } + +#[stable(feature = "default_iters", since = "1.70.0")] +impl<I: Default> Default for Cloned<I> { + /// Creates a `Cloned` iterator from the default value of `I` + /// ``` + /// # use core::slice; + /// # use core::iter::Cloned; + /// let iter: Cloned<slice::Iter<'_, u8>> = Default::default(); + /// assert_eq!(iter.len(), 0); + /// ``` + fn default() -> Self { + Self::new(Default::default()) + } +} diff --git a/library/core/src/iter/adapters/copied.rs b/library/core/src/iter/adapters/copied.rs index 62d3afb81..8f6b2904e 100644 --- a/library/core/src/iter/adapters/copied.rs +++ b/library/core/src/iter/adapters/copied.rs @@ -4,6 +4,7 @@ use crate::iter::adapters::{ use crate::iter::{FusedIterator, TrustedLen}; use crate::mem::MaybeUninit; use crate::mem::SizedTypeProperties; +use crate::num::NonZeroUsize; use crate::ops::Try; use crate::{array, ptr}; @@ -89,7 +90,7 @@ where } #[inline] - fn advance_by(&mut self, n: usize) -> Result<(), usize> { + fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { self.it.advance_by(n) } @@ -130,7 +131,7 @@ where } #[inline] - fn advance_back_by(&mut self, n: usize) -> Result<(), usize> { + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { self.it.advance_back_by(n) } } @@ -240,3 +241,17 @@ where } } } + +#[stable(feature = "default_iters", since = "1.70.0")] +impl<I: Default> Default for Copied<I> { + /// Creates a `Copied` iterator from the default value of `I` + /// ``` + /// # use core::slice; + /// # use core::iter::Copied; + /// let iter: Copied<slice::Iter<'_, u8>> = Default::default(); + /// assert_eq!(iter.len(), 0); + /// ``` + fn default() -> Self { + Self::new(Default::default()) + } +} diff --git a/library/core/src/iter/adapters/cycle.rs b/library/core/src/iter/adapters/cycle.rs index 02b593907..51bd09b6e 100644 --- a/library/core/src/iter/adapters/cycle.rs +++ b/library/core/src/iter/adapters/cycle.rs @@ -1,3 +1,4 @@ +use crate::num::NonZeroUsize; use crate::{iter::FusedIterator, ops::Try}; /// An iterator that repeats endlessly. @@ -81,23 +82,22 @@ where #[inline] #[rustc_inherit_overflow_checks] - fn advance_by(&mut self, n: usize) -> Result<(), usize> { - let mut rem = n; - match self.iter.advance_by(rem) { - ret @ Ok(_) => return ret, - Err(advanced) => rem -= advanced, - } + fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { + let mut n = match self.iter.advance_by(n) { + Ok(()) => return Ok(()), + Err(rem) => rem.get(), + }; - while rem > 0 { + while n > 0 { self.iter = self.orig.clone(); - match self.iter.advance_by(rem) { - ret @ Ok(_) => return ret, - Err(0) => return Err(n - rem), - Err(advanced) => rem -= advanced, - } + n = match self.iter.advance_by(n) { + Ok(()) => return Ok(()), + e @ Err(rem) if rem.get() == n => return e, + Err(rem) => rem.get(), + }; } - Ok(()) + NonZeroUsize::new(n).map_or(Ok(()), Err) } // No `fold` override, because `fold` doesn't make much sense for `Cycle`, diff --git a/library/core/src/iter/adapters/enumerate.rs b/library/core/src/iter/adapters/enumerate.rs index 14a126951..00c1c377b 100644 --- a/library/core/src/iter/adapters/enumerate.rs +++ b/library/core/src/iter/adapters/enumerate.rs @@ -2,6 +2,7 @@ use crate::iter::adapters::{ zip::try_get_unchecked, SourceIter, TrustedRandomAccess, TrustedRandomAccessNoCoerce, }; use crate::iter::{FusedIterator, InPlaceIterable, TrustedLen}; +use crate::num::NonZeroUsize; use crate::ops::Try; /// An iterator that yields the current count and the element during iteration. @@ -114,17 +115,14 @@ where #[inline] #[rustc_inherit_overflow_checks] - fn advance_by(&mut self, n: usize) -> Result<(), usize> { - match self.iter.advance_by(n) { - ret @ Ok(_) => { - self.count += n; - ret - } - ret @ Err(advanced) => { - self.count += advanced; - ret - } - } + fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { + let remaining = self.iter.advance_by(n); + let advanced = match remaining { + Ok(()) => n, + Err(rem) => n - rem.get(), + }; + self.count += advanced; + remaining } #[rustc_inherit_overflow_checks] @@ -208,7 +206,7 @@ where } #[inline] - fn advance_back_by(&mut self, n: usize) -> Result<(), usize> { + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { // we do not need to update the count since that only tallies the number of items // consumed from the front. consuming items from the back can never reduce that. self.iter.advance_back_by(n) @@ -264,3 +262,17 @@ where #[unstable(issue = "none", feature = "inplace_iteration")] unsafe impl<I: InPlaceIterable> InPlaceIterable for Enumerate<I> {} + +#[stable(feature = "default_iters", since = "1.70.0")] +impl<I: Default> Default for Enumerate<I> { + /// Creates an `Enumerate` iterator from the default value of `I` + /// ``` + /// # use core::slice; + /// # use std::iter::Enumerate; + /// let iter: Enumerate<slice::Iter<'_, u8>> = Default::default(); + /// assert_eq!(iter.len(), 0); + /// ``` + fn default() -> Self { + Enumerate::new(Default::default()) + } +} diff --git a/library/core/src/iter/adapters/flatten.rs b/library/core/src/iter/adapters/flatten.rs index b040a0ea9..2fd8a5c1d 100644 --- a/library/core/src/iter/adapters/flatten.rs +++ b/library/core/src/iter/adapters/flatten.rs @@ -1,5 +1,6 @@ use crate::fmt; use crate::iter::{DoubleEndedIterator, Fuse, FusedIterator, Iterator, Map, TrustedLen}; +use crate::num::NonZeroUsize; use crate::ops::{ControlFlow, Try}; /// An iterator that maps each element to an iterator, and yields the elements @@ -75,7 +76,7 @@ where } #[inline] - fn advance_by(&mut self, n: usize) -> Result<(), usize> { + fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { self.inner.advance_by(n) } @@ -120,7 +121,7 @@ where } #[inline] - fn advance_back_by(&mut self, n: usize) -> Result<(), usize> { + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { self.inner.advance_back_by(n) } } @@ -236,7 +237,7 @@ where } #[inline] - fn advance_by(&mut self, n: usize) -> Result<(), usize> { + fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { self.inner.advance_by(n) } @@ -281,7 +282,7 @@ where } #[inline] - fn advance_back_by(&mut self, n: usize) -> Result<(), usize> { + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { self.inner.advance_back_by(n) } } @@ -302,6 +303,24 @@ where { } +#[stable(feature = "default_iters", since = "1.70.0")] +impl<I> Default for Flatten<I> +where + I: Default + Iterator<Item: IntoIterator>, +{ + /// Creates a `Flatten` iterator from the default value of `I`. + /// + /// ``` + /// # use core::slice; + /// # use std::iter::Flatten; + /// let iter: Flatten<slice::Iter<'_, [u8; 4]>> = Default::default(); + /// assert_eq!(iter.count(), 0); + /// ``` + fn default() -> Self { + Flatten::new(Default::default()) + } +} + /// Real logic of both `Flatten` and `FlatMap` which simply delegate to /// this type. #[derive(Clone, Debug)] @@ -534,18 +553,18 @@ where #[inline] #[rustc_inherit_overflow_checks] - fn advance_by(&mut self, n: usize) -> Result<(), usize> { + fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { #[inline] #[rustc_inherit_overflow_checks] fn advance<U: Iterator>(n: usize, iter: &mut U) -> ControlFlow<(), usize> { match iter.advance_by(n) { Ok(()) => ControlFlow::Break(()), - Err(advanced) => ControlFlow::Continue(n - advanced), + Err(remaining) => ControlFlow::Continue(remaining.get()), } } match self.iter_try_fold(n, advance) { - ControlFlow::Continue(remaining) if remaining > 0 => Err(n - remaining), + ControlFlow::Continue(remaining) => NonZeroUsize::new(remaining).map_or(Ok(()), Err), _ => Ok(()), } } @@ -624,18 +643,18 @@ where #[inline] #[rustc_inherit_overflow_checks] - fn advance_back_by(&mut self, n: usize) -> Result<(), usize> { + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { #[inline] #[rustc_inherit_overflow_checks] fn advance<U: DoubleEndedIterator>(n: usize, iter: &mut U) -> ControlFlow<(), usize> { match iter.advance_back_by(n) { Ok(()) => ControlFlow::Break(()), - Err(advanced) => ControlFlow::Continue(n - advanced), + Err(remaining) => ControlFlow::Continue(remaining.get()), } } match self.iter_try_rfold(n, advance) { - ControlFlow::Continue(remaining) if remaining > 0 => Err(n - remaining), + ControlFlow::Continue(remaining) => NonZeroUsize::new(remaining).map_or(Ok(()), Err), _ => Ok(()), } } diff --git a/library/core/src/iter/adapters/fuse.rs b/library/core/src/iter/adapters/fuse.rs index c93144542..b1fa4f921 100644 --- a/library/core/src/iter/adapters/fuse.rs +++ b/library/core/src/iter/adapters/fuse.rs @@ -181,6 +181,21 @@ where } } +#[stable(feature = "default_iters", since = "1.70.0")] +impl<I: Default> Default for Fuse<I> { + /// Creates a `Fuse` iterator from the default value of `I`. + /// + /// ``` + /// # use core::slice; + /// # use std::iter::Fuse; + /// let iter: Fuse<slice::Iter<'_, u8>> = Default::default(); + /// assert_eq!(iter.len(), 0); + /// ``` + fn default() -> Self { + Fuse { iter: Default::default() } + } +} + #[unstable(feature = "trusted_len", issue = "37572")] // SAFETY: `TrustedLen` requires that an accurate length is reported via `size_hint()`. As `Fuse` // is just forwarding this to the wrapped iterator `I` this property is preserved and it is safe to diff --git a/library/core/src/iter/adapters/rev.rs b/library/core/src/iter/adapters/rev.rs index 139fb7bbd..4aaf7c61f 100644 --- a/library/core/src/iter/adapters/rev.rs +++ b/library/core/src/iter/adapters/rev.rs @@ -1,4 +1,5 @@ use crate::iter::{FusedIterator, TrustedLen}; +use crate::num::NonZeroUsize; use crate::ops::Try; /// A double-ended iterator with the direction inverted. @@ -38,7 +39,7 @@ where } #[inline] - fn advance_by(&mut self, n: usize) -> Result<(), usize> { + fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { self.iter.advance_back_by(n) } @@ -83,7 +84,7 @@ where } #[inline] - fn advance_back_by(&mut self, n: usize) -> Result<(), usize> { + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { self.iter.advance_by(n) } @@ -135,3 +136,17 @@ impl<I> FusedIterator for Rev<I> where I: FusedIterator + DoubleEndedIterator {} #[unstable(feature = "trusted_len", issue = "37572")] unsafe impl<I> TrustedLen for Rev<I> where I: TrustedLen + DoubleEndedIterator {} + +#[stable(feature = "default_iters", since = "1.70.0")] +impl<I: Default> Default for Rev<I> { + /// Creates a `Rev` iterator from the default value of `I` + /// ``` + /// # use core::slice; + /// # use core::iter::Rev; + /// let iter: Rev<slice::Iter<'_, u8>> = Default::default(); + /// assert_eq!(iter.len(), 0); + /// ``` + fn default() -> Self { + Rev::new(Default::default()) + } +} diff --git a/library/core/src/iter/adapters/skip.rs b/library/core/src/iter/adapters/skip.rs index c6334880d..306338bc7 100644 --- a/library/core/src/iter/adapters/skip.rs +++ b/library/core/src/iter/adapters/skip.rs @@ -1,5 +1,6 @@ use crate::intrinsics::unlikely; use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable}; +use crate::num::NonZeroUsize; use crate::ops::{ControlFlow, Try}; /// An iterator that skips over `n` elements of `iter`. @@ -128,34 +129,27 @@ where #[inline] #[rustc_inherit_overflow_checks] - fn advance_by(&mut self, n: usize) -> Result<(), usize> { - let mut rem = n; - let step_one = self.n.saturating_add(rem); - - match self.iter.advance_by(step_one) { - Ok(_) => { - rem -= step_one - self.n; - self.n = 0; - } - Err(advanced) => { - let advanced_without_skip = advanced.saturating_sub(self.n); - self.n = self.n.saturating_sub(advanced); - return if n == 0 { Ok(()) } else { Err(advanced_without_skip) }; - } - } + fn advance_by(&mut self, mut n: usize) -> Result<(), NonZeroUsize> { + let skip_inner = self.n; + let skip_and_advance = skip_inner.saturating_add(n); - // step_one calculation may have saturated - if unlikely(rem > 0) { - return match self.iter.advance_by(rem) { - ret @ Ok(_) => ret, - Err(advanced) => { - rem -= advanced; - Err(n - rem) - } - }; + let remainder = match self.iter.advance_by(skip_and_advance) { + Ok(()) => 0, + Err(n) => n.get(), + }; + let advanced_inner = skip_and_advance - remainder; + n -= advanced_inner.saturating_sub(skip_inner); + self.n = self.n.saturating_sub(advanced_inner); + + // skip_and_advance may have saturated + if unlikely(remainder == 0 && n > 0) { + n = match self.iter.advance_by(n) { + Ok(()) => 0, + Err(n) => n.get(), + } } - Ok(()) + NonZeroUsize::new(n).map_or(Ok(()), Err) } } @@ -209,13 +203,11 @@ where impl_fold_via_try_fold! { rfold -> try_rfold } #[inline] - fn advance_back_by(&mut self, n: usize) -> Result<(), usize> { + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { let min = crate::cmp::min(self.len(), n); - return match self.iter.advance_back_by(min) { - ret @ Ok(_) if n <= min => ret, - Ok(_) => Err(min), - _ => panic!("ExactSizeIterator contract violation"), - }; + let rem = self.iter.advance_back_by(min); + assert!(rem.is_ok(), "ExactSizeIterator contract violation"); + NonZeroUsize::new(n - min).map_or(Ok(()), Err) } } diff --git a/library/core/src/iter/adapters/take.rs b/library/core/src/iter/adapters/take.rs index d947c7b0e..ce18bffe7 100644 --- a/library/core/src/iter/adapters/take.rs +++ b/library/core/src/iter/adapters/take.rs @@ -1,5 +1,6 @@ use crate::cmp; use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable, TrustedLen}; +use crate::num::NonZeroUsize; use crate::ops::{ControlFlow, Try}; /// An iterator that only iterates over the first `n` iterations of `iter`. @@ -121,18 +122,15 @@ where #[inline] #[rustc_inherit_overflow_checks] - fn advance_by(&mut self, n: usize) -> Result<(), usize> { + fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { let min = self.n.min(n); - match self.iter.advance_by(min) { - Ok(_) => { - self.n -= min; - if min < n { Err(min) } else { Ok(()) } - } - ret @ Err(advanced) => { - self.n -= advanced; - ret - } - } + let rem = match self.iter.advance_by(min) { + Ok(()) => 0, + Err(rem) => rem.get(), + }; + let advanced = min - rem; + self.n -= advanced; + NonZeroUsize::new(n - advanced).map_or(Ok(()), Err) } } @@ -223,7 +221,7 @@ where #[inline] #[rustc_inherit_overflow_checks] - fn advance_back_by(&mut self, n: usize) -> Result<(), usize> { + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { // The amount by which the inner iterator needs to be shortened for it to be // at most as long as the take() amount. let trim_inner = self.iter.len().saturating_sub(self.n); @@ -232,12 +230,14 @@ where // about having to advance more than usize::MAX here. let advance_by = trim_inner.saturating_add(n); - let advanced = match self.iter.advance_back_by(advance_by) { - Ok(_) => advance_by - trim_inner, - Err(advanced) => advanced - trim_inner, + let remainder = match self.iter.advance_back_by(advance_by) { + Ok(()) => 0, + Err(rem) => rem.get(), }; - self.n -= advanced; - return if advanced < n { Err(advanced) } else { Ok(()) }; + let advanced_by_inner = advance_by - remainder; + let advanced_by = advanced_by_inner - trim_inner; + self.n -= advanced_by; + NonZeroUsize::new(n - advanced_by).map_or(Ok(()), Err) } } diff --git a/library/core/src/iter/mod.rs b/library/core/src/iter/mod.rs index ae00232c1..de638552f 100644 --- a/library/core/src/iter/mod.rs +++ b/library/core/src/iter/mod.rs @@ -278,7 +278,7 @@ //! //! ``` //! # #![allow(unused_must_use)] -//! # #![cfg_attr(not(bootstrap), allow(map_unit_fn))] +//! # #![allow(map_unit_fn)] //! let v = vec![1, 2, 3, 4, 5]; //! v.iter().map(|x| println!("{x}")); //! ``` diff --git a/library/core/src/iter/range.rs b/library/core/src/iter/range.rs index 78e27d730..37db07429 100644 --- a/library/core/src/iter/range.rs +++ b/library/core/src/iter/range.rs @@ -1,5 +1,6 @@ use crate::convert::TryFrom; use crate::mem; +use crate::num::NonZeroUsize; use crate::ops::{self, Try}; use super::{ @@ -520,12 +521,12 @@ trait RangeIteratorImpl { // Iterator fn spec_next(&mut self) -> Option<Self::Item>; fn spec_nth(&mut self, n: usize) -> Option<Self::Item>; - fn spec_advance_by(&mut self, n: usize) -> Result<(), usize>; + fn spec_advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize>; // DoubleEndedIterator fn spec_next_back(&mut self) -> Option<Self::Item>; fn spec_nth_back(&mut self, n: usize) -> Option<Self::Item>; - fn spec_advance_back_by(&mut self, n: usize) -> Result<(), usize>; + fn spec_advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize>; } impl<A: Step> RangeIteratorImpl for ops::Range<A> { @@ -557,7 +558,7 @@ impl<A: Step> RangeIteratorImpl for ops::Range<A> { } #[inline] - default fn spec_advance_by(&mut self, n: usize) -> Result<(), usize> { + 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 { @@ -569,7 +570,7 @@ impl<A: Step> RangeIteratorImpl for ops::Range<A> { self.start = Step::forward_checked(self.start.clone(), taken).expect("`Step` invariants not upheld"); - if taken < n { Err(taken) } else { Ok(()) } + NonZeroUsize::new(n - taken).map_or(Ok(()), Err) } #[inline] @@ -598,7 +599,7 @@ impl<A: Step> RangeIteratorImpl for ops::Range<A> { } #[inline] - default fn spec_advance_back_by(&mut self, n: usize) -> Result<(), usize> { + 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 { @@ -610,7 +611,7 @@ impl<A: Step> RangeIteratorImpl for ops::Range<A> { self.end = Step::backward_checked(self.end.clone(), taken).expect("`Step` invariants not upheld"); - if taken < n { Err(taken) } else { Ok(()) } + NonZeroUsize::new(n - taken).map_or(Ok(()), Err) } } @@ -641,7 +642,7 @@ impl<T: TrustedStep> RangeIteratorImpl for ops::Range<T> { } #[inline] - fn spec_advance_by(&mut self, n: usize) -> Result<(), usize> { + 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 { @@ -656,7 +657,7 @@ impl<T: TrustedStep> RangeIteratorImpl for ops::Range<T> { // Otherwise 0 is returned which always safe to use. self.start = unsafe { Step::forward_unchecked(self.start.clone(), taken) }; - if taken < n { Err(taken) } else { Ok(()) } + NonZeroUsize::new(n - taken).map_or(Ok(()), Err) } #[inline] @@ -685,7 +686,7 @@ impl<T: TrustedStep> RangeIteratorImpl for ops::Range<T> { } #[inline] - fn spec_advance_back_by(&mut self, n: usize) -> Result<(), usize> { + 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 { @@ -697,7 +698,7 @@ impl<T: TrustedStep> RangeIteratorImpl for ops::Range<T> { // SAFETY: same as the spec_advance_by() implementation self.end = unsafe { Step::backward_unchecked(self.end.clone(), taken) }; - if taken < n { Err(taken) } else { Ok(()) } + NonZeroUsize::new(n - taken).map_or(Ok(()), Err) } } @@ -746,7 +747,7 @@ impl<A: Step> Iterator for ops::Range<A> { } #[inline] - fn advance_by(&mut self, n: usize) -> Result<(), usize> { + fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { self.spec_advance_by(n) } @@ -824,7 +825,7 @@ impl<A: Step> DoubleEndedIterator for ops::Range<A> { } #[inline] - fn advance_back_by(&mut self, n: usize) -> Result<(), usize> { + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { self.spec_advance_back_by(n) } } diff --git a/library/core/src/iter/sources/repeat.rs b/library/core/src/iter/sources/repeat.rs index 733142ed0..67051f6e9 100644 --- a/library/core/src/iter/sources/repeat.rs +++ b/library/core/src/iter/sources/repeat.rs @@ -1,4 +1,5 @@ use crate::iter::{FusedIterator, TrustedLen}; +use crate::num::NonZeroUsize; /// Creates a new iterator that endlessly repeats a single element. /// @@ -80,7 +81,7 @@ impl<A: Clone> Iterator for Repeat<A> { } #[inline] - fn advance_by(&mut self, n: usize) -> Result<(), usize> { + fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { // Advancing an infinite iterator of a single element is a no-op. let _ = n; Ok(()) @@ -109,7 +110,7 @@ impl<A: Clone> DoubleEndedIterator for Repeat<A> { } #[inline] - fn advance_back_by(&mut self, n: usize) -> Result<(), usize> { + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { // Advancing an infinite iterator of a single element is a no-op. let _ = n; Ok(()) diff --git a/library/core/src/iter/sources/repeat_n.rs b/library/core/src/iter/sources/repeat_n.rs index dc61d6065..0b0445850 100644 --- a/library/core/src/iter/sources/repeat_n.rs +++ b/library/core/src/iter/sources/repeat_n.rs @@ -1,5 +1,6 @@ use crate::iter::{FusedIterator, TrustedLen}; use crate::mem::ManuallyDrop; +use crate::num::NonZeroUsize; /// Creates a new iterator that repeats a single element a given number of times. /// @@ -137,7 +138,7 @@ impl<A: Clone> Iterator for RepeatN<A> { } #[inline] - fn advance_by(&mut self, skip: usize) -> Result<(), usize> { + fn advance_by(&mut self, skip: usize) -> Result<(), NonZeroUsize> { let len = self.count; if skip >= len { @@ -145,7 +146,8 @@ impl<A: Clone> Iterator for RepeatN<A> { } if skip > len { - Err(len) + // SAFETY: we just checked that the difference is positive + Err(unsafe { NonZeroUsize::new_unchecked(skip - len) }) } else { self.count = len - skip; Ok(()) @@ -178,7 +180,7 @@ impl<A: Clone> DoubleEndedIterator for RepeatN<A> { } #[inline] - fn advance_back_by(&mut self, n: usize) -> Result<(), usize> { + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { self.advance_by(n) } diff --git a/library/core/src/iter/sources/repeat_with.rs b/library/core/src/iter/sources/repeat_with.rs index 3f34105a3..d3cd74a44 100644 --- a/library/core/src/iter/sources/repeat_with.rs +++ b/library/core/src/iter/sources/repeat_with.rs @@ -19,7 +19,6 @@ use crate::ops::Try; /// please open a GitHub issue explaining your use case. /// /// [`repeat()`]: crate::iter::repeat -/// [`DoubleEndedIterator`]: crate::iter::DoubleEndedIterator /// /// # Examples /// diff --git a/library/core/src/iter/traits/accum.rs b/library/core/src/iter/traits/accum.rs index e31669b39..f9c7eb8f9 100644 --- a/library/core/src/iter/traits/accum.rs +++ b/library/core/src/iter/traits/accum.rs @@ -164,12 +164,13 @@ where /// element is encountered: /// /// ``` + /// let f = |&x: &i32| if x < 0 { Err("Negative element found") } else { Ok(x) }; /// let v = vec![1, 2]; - /// let res: Result<i32, &'static str> = v.iter().map(|&x: &i32| - /// if x < 0 { Err("Negative element found") } - /// else { Ok(x) } - /// ).sum(); + /// let res: Result<i32, _> = v.iter().map(f).sum(); /// assert_eq!(res, Ok(3)); + /// let v = vec![1, -2]; + /// let res: Result<i32, _> = v.iter().map(f).sum(); + /// assert_eq!(res, Err("Negative element found")); /// ``` fn sum<I>(iter: I) -> Result<T, E> where @@ -187,6 +188,20 @@ where /// Takes each element in the [`Iterator`]: if it is an [`Err`], no further /// elements are taken, and the [`Err`] is returned. Should no [`Err`] /// occur, the product of all elements is returned. + /// + /// # Examples + /// + /// This multiplies each number in a vector of strings, + /// if a string could not be parsed the operation returns `Err`: + /// + /// ``` + /// let nums = vec!["5", "10", "1", "2"]; + /// let total: Result<usize, _> = nums.iter().map(|w| w.parse::<usize>()).product(); + /// assert_eq!(total, Ok(100)); + /// let nums = vec!["5", "10", "one", "2"]; + /// let total: Result<usize, _> = nums.iter().map(|w| w.parse::<usize>()).product(); + /// assert!(total.is_err()); + /// ``` fn product<I>(iter: I) -> Result<T, E> where I: Iterator<Item = Result<U, E>>, @@ -213,6 +228,9 @@ where /// let words = vec!["have", "a", "great", "day"]; /// let total: Option<usize> = words.iter().map(|w| w.find('a')).sum(); /// assert_eq!(total, Some(5)); + /// let words = vec!["have", "a", "good", "day"]; + /// let total: Option<usize> = words.iter().map(|w| w.find('a')).sum(); + /// assert_eq!(total, None); /// ``` fn sum<I>(iter: I) -> Option<T> where @@ -230,6 +248,20 @@ where /// Takes each element in the [`Iterator`]: if it is a [`None`], no further /// elements are taken, and the [`None`] is returned. Should no [`None`] /// occur, the product of all elements is returned. + /// + /// # Examples + /// + /// This multiplies each number in a vector of strings, + /// if a string could not be parsed the operation returns `None`: + /// + /// ``` + /// let nums = vec!["5", "10", "1", "2"]; + /// let total: Option<usize> = nums.iter().map(|w| w.parse::<usize>().ok()).product(); + /// assert_eq!(total, Some(100)); + /// let nums = vec!["5", "10", "one", "2"]; + /// let total: Option<usize> = nums.iter().map(|w| w.parse::<usize>().ok()).product(); + /// assert_eq!(total, None); + /// ``` fn product<I>(iter: I) -> Option<T> where I: Iterator<Item = Option<U>>, diff --git a/library/core/src/iter/traits/double_ended.rs b/library/core/src/iter/traits/double_ended.rs index ed23873cd..182d9f758 100644 --- a/library/core/src/iter/traits/double_ended.rs +++ b/library/core/src/iter/traits/double_ended.rs @@ -1,3 +1,4 @@ +use crate::num::NonZeroUsize; use crate::ops::{ControlFlow, Try}; /// An iterator able to yield elements from both ends. @@ -98,10 +99,11 @@ pub trait DoubleEndedIterator: Iterator { /// eagerly skip `n` elements starting from the back by calling [`next_back`] up /// to `n` times until [`None`] is encountered. /// - /// `advance_back_by(n)` will return [`Ok(())`] if the iterator successfully advances by - /// `n` elements, or [`Err(k)`] if [`None`] is encountered, where `k` is the number of - /// elements the iterator is advanced by before running out of elements (i.e. the length - /// of the iterator). Note that `k` is always less than `n`. + /// `advance_back_by(n)` will return `Ok(())` if the iterator successfully advances by + /// `n` elements, or a `Err(NonZeroUsize)` with value `k` if [`None`] is encountered, where `k` + /// is remaining number of steps that could not be advanced because the iterator ran out. + /// If `self` is empty and `n` is non-zero, then this returns `Err(n)`. + /// Otherwise, `k` is always less than `n`. /// /// Calling `advance_back_by(0)` can do meaningful work, for example [`Flatten`] can advance its /// outer iterator until it finds an inner iterator that is not empty, which then often @@ -118,22 +120,26 @@ pub trait DoubleEndedIterator: Iterator { /// ``` /// #![feature(iter_advance_by)] /// + /// use std::num::NonZeroUsize; /// let a = [3, 4, 5, 6]; /// let mut iter = a.iter(); /// /// assert_eq!(iter.advance_back_by(2), Ok(())); /// assert_eq!(iter.next_back(), Some(&4)); /// assert_eq!(iter.advance_back_by(0), Ok(())); - /// assert_eq!(iter.advance_back_by(100), Err(1)); // only `&3` was skipped + /// assert_eq!(iter.advance_back_by(100), Err(NonZeroUsize::new(99).unwrap())); // only `&3` was skipped /// ``` /// /// [`Ok(())`]: Ok /// [`Err(k)`]: Err #[inline] #[unstable(feature = "iter_advance_by", reason = "recently added", issue = "77404")] - fn advance_back_by(&mut self, n: usize) -> Result<(), usize> { + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { for i in 0..n { - self.next_back().ok_or(i)?; + if self.next_back().is_none() { + // SAFETY: `i` is always less than `n`. + return Err(unsafe { NonZeroUsize::new_unchecked(n - i) }); + } } Ok(()) } @@ -182,7 +188,9 @@ pub trait DoubleEndedIterator: Iterator { #[inline] #[stable(feature = "iter_nth_back", since = "1.37.0")] fn nth_back(&mut self, n: usize) -> Option<Self::Item> { - self.advance_back_by(n).ok()?; + if self.advance_back_by(n).is_err() { + return None; + } self.next_back() } @@ -365,7 +373,7 @@ impl<'a, I: DoubleEndedIterator + ?Sized> DoubleEndedIterator for &'a mut I { fn next_back(&mut self) -> Option<I::Item> { (**self).next_back() } - fn advance_back_by(&mut self, n: usize) -> Result<(), usize> { + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { (**self).advance_back_by(n) } fn nth_back(&mut self, n: usize) -> Option<I::Item> { diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index b8e7d0a68..028776042 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -1,5 +1,6 @@ use crate::array; use crate::cmp::{self, Ordering}; +use crate::num::NonZeroUsize; use crate::ops::{ChangeOutputType, ControlFlow, FromResidual, Residual, Try}; use super::super::try_process; @@ -69,7 +70,7 @@ fn _assert_is_object_safe(_: &dyn Iterator<Item = ()>) {} #[doc(notable_trait)] #[rustc_diagnostic_item = "Iterator"] #[must_use = "iterators are lazy and do nothing unless consumed"] -#[cfg_attr(not(bootstrap), const_trait)] +#[const_trait] pub trait Iterator { /// The type of the elements being iterated over. #[rustc_diagnostic_item = "IteratorItem"] @@ -307,10 +308,11 @@ pub trait Iterator { /// This method will eagerly skip `n` elements by calling [`next`] up to `n` /// times until [`None`] is encountered. /// - /// `advance_by(n)` will return [`Ok(())`][Ok] if the iterator successfully advances by - /// `n` elements, or [`Err(k)`][Err] if [`None`] is encountered, where `k` is the number - /// of elements the iterator is advanced by before running out of elements (i.e. the - /// length of the iterator). Note that `k` is always less than `n`. + /// `advance_by(n)` will return `Ok(())` if the iterator successfully advances by + /// `n` elements, or a `Err(NonZeroUsize)` with value `k` if [`None`] is encountered, + /// where `k` is remaining number of steps that could not be advanced because the iterator ran out. + /// If `self` is empty and `n` is non-zero, then this returns `Err(n)`. + /// Otherwise, `k` is always less than `n`. /// /// Calling `advance_by(0)` can do meaningful work, for example [`Flatten`] /// can advance its outer iterator until it finds an inner iterator that is not empty, which @@ -326,20 +328,24 @@ pub trait Iterator { /// ``` /// #![feature(iter_advance_by)] /// + /// use std::num::NonZeroUsize; /// let a = [1, 2, 3, 4]; /// let mut iter = a.iter(); /// /// assert_eq!(iter.advance_by(2), Ok(())); /// assert_eq!(iter.next(), Some(&3)); /// assert_eq!(iter.advance_by(0), Ok(())); - /// assert_eq!(iter.advance_by(100), Err(1)); // only `&4` was skipped + /// assert_eq!(iter.advance_by(100), Err(NonZeroUsize::new(99).unwrap())); // only `&4` was skipped /// ``` #[inline] #[unstable(feature = "iter_advance_by", reason = "recently added", issue = "77404")] #[rustc_do_not_const_check] - fn advance_by(&mut self, n: usize) -> Result<(), usize> { + fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { for i in 0..n { - self.next().ok_or(i)?; + if self.next().is_none() { + // SAFETY: `i` is always less than `n`. + return Err(unsafe { NonZeroUsize::new_unchecked(n - i) }); + } } Ok(()) } @@ -758,7 +764,6 @@ pub trait Iterator { /// more idiomatic to use [`for`] than `map()`. /// /// [`for`]: ../../book/ch03-05-control-flow.html#looping-through-a-collection-with-for - /// [`FnMut`]: crate::ops::FnMut /// /// # Examples /// @@ -1998,7 +2003,7 @@ pub trait Iterator { /// a.iter().map(|&x| x * 2).collect_into(&mut vec); /// a.iter().map(|&x| x * 10).collect_into(&mut vec); /// - /// assert_eq!(vec![0, 1, 2, 4, 6, 10, 20, 30], vec); + /// assert_eq!(vec, vec![0, 1, 2, 4, 6, 10, 20, 30]); /// ``` /// /// `Vec` can have a manual set capacity to avoid reallocating it: @@ -2013,7 +2018,7 @@ pub trait Iterator { /// a.iter().map(|&x| x * 10).collect_into(&mut vec); /// /// assert_eq!(6, vec.capacity()); - /// println!("{:?}", vec); + /// assert_eq!(vec, vec![2, 4, 6, 10, 20, 30]); /// ``` /// /// The returned mutable reference can be used to continue the call chain: @@ -2027,12 +2032,12 @@ pub trait Iterator { /// let count = a.iter().collect_into(&mut vec).iter().count(); /// /// assert_eq!(count, vec.len()); - /// println!("Vec len is {}", count); + /// assert_eq!(vec, vec![1, 2, 3]); /// /// let count = a.iter().collect_into(&mut vec).iter().count(); /// /// assert_eq!(count, vec.len()); - /// println!("Vec len now is {}", count); + /// assert_eq!(vec, vec![1, 2, 3, 1, 2, 3]); /// ``` #[inline] #[unstable(feature = "iter_collect_into", reason = "new API", issue = "94780")] @@ -2109,8 +2114,8 @@ pub trait Iterator { /// /// # Current implementation /// - /// Current algorithms tries finding the first element for which the predicate evaluates - /// to false, and the last element for which it evaluates to true and repeatedly swaps them. + /// The current algorithm tries to find the first element for which the predicate evaluates + /// to false and the last element for which it evaluates to true, and repeatedly swaps them. /// /// Time complexity: *O*(*n*) /// @@ -3443,6 +3448,9 @@ pub trait Iterator { /// /// An empty iterator returns the zero value of the type. /// + /// `sum()` can be used to sum any type implementing [`Sum`][`core::iter::Sum`], + /// including [`Option`][`Option::sum`] and [`Result`][`Result::sum`]. + /// /// # Panics /// /// When calling `sum()` and a primitive integer type is being returned, this @@ -3473,6 +3481,9 @@ pub trait Iterator { /// /// An empty iterator returns the one value of the type. /// + /// `product()` can be used to multiply any type implementing [`Product`][`core::iter::Product`], + /// including [`Option`][`Option::product`] and [`Result`][`Result::product`]. + /// /// # Panics /// /// When calling `product()` and a primitive integer type is being returned, @@ -3721,7 +3732,7 @@ pub trait Iterator { } } - /// Determines if the elements of this [`Iterator`] are unequal to those of + /// Determines if the elements of this [`Iterator`] are not equal to those of /// another. /// /// # Examples @@ -4002,7 +4013,7 @@ impl<I: Iterator + ?Sized> Iterator for &mut I { fn size_hint(&self) -> (usize, Option<usize>) { (**self).size_hint() } - fn advance_by(&mut self, n: usize) -> Result<(), usize> { + fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { (**self).advance_by(n) } fn nth(&mut self, n: usize) -> Option<Self::Item> { |