summaryrefslogtreecommitdiffstats
path: root/library/core/src/iter
diff options
context:
space:
mode:
Diffstat (limited to 'library/core/src/iter')
-rw-r--r--library/core/src/iter/adapters/by_ref_sized.rs5
-rw-r--r--library/core/src/iter/adapters/chain.rs73
-rw-r--r--library/core/src/iter/adapters/cloned.rs14
-rw-r--r--library/core/src/iter/adapters/copied.rs19
-rw-r--r--library/core/src/iter/adapters/cycle.rs26
-rw-r--r--library/core/src/iter/adapters/enumerate.rs36
-rw-r--r--library/core/src/iter/adapters/flatten.rs39
-rw-r--r--library/core/src/iter/adapters/fuse.rs15
-rw-r--r--library/core/src/iter/adapters/rev.rs19
-rw-r--r--library/core/src/iter/adapters/skip.rs54
-rw-r--r--library/core/src/iter/adapters/take.rs34
-rw-r--r--library/core/src/iter/mod.rs2
-rw-r--r--library/core/src/iter/range.rs25
-rw-r--r--library/core/src/iter/sources/repeat.rs5
-rw-r--r--library/core/src/iter/sources/repeat_n.rs8
-rw-r--r--library/core/src/iter/sources/repeat_with.rs1
-rw-r--r--library/core/src/iter/traits/accum.rs40
-rw-r--r--library/core/src/iter/traits/double_ended.rs26
-rw-r--r--library/core/src/iter/traits/iterator.rs45
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> {