summaryrefslogtreecommitdiffstats
path: root/library/core/src/iter/traits
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:20:39 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:20:39 +0000
commit1376c5a617be5c25655d0d7cb63e3beaa5a6e026 (patch)
tree3bb8d61aee02bc7a15eab3f36e3b921afc2075d0 /library/core/src/iter/traits
parentReleasing progress-linux version 1.69.0+dfsg1-1~progress7.99u1. (diff)
downloadrustc-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/traits')
-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
3 files changed, 81 insertions, 30 deletions
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> {