summaryrefslogtreecommitdiffstats
path: root/library/core/src/iter
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-07 05:48:48 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-07 05:48:48 +0000
commitef24de24a82fe681581cc130f342363c47c0969a (patch)
tree0d494f7e1a38b95c92426f58fe6eaa877303a86c /library/core/src/iter
parentReleasing progress-linux version 1.74.1+dfsg1-1~progress7.99u1. (diff)
downloadrustc-ef24de24a82fe681581cc130f342363c47c0969a.tar.xz
rustc-ef24de24a82fe681581cc130f342363c47c0969a.zip
Merging upstream version 1.75.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/peekable.rs1
-rw-r--r--library/core/src/iter/adapters/zip.rs90
-rw-r--r--library/core/src/iter/mod.rs6
-rw-r--r--library/core/src/iter/sources.rs8
-rw-r--r--library/core/src/iter/sources/empty.rs1
-rw-r--r--library/core/src/iter/sources/from_coroutine.rs59
-rw-r--r--library/core/src/iter/sources/from_generator.rs58
-rw-r--r--library/core/src/iter/sources/once.rs1
-rw-r--r--library/core/src/iter/sources/once_with.rs2
-rw-r--r--library/core/src/iter/sources/successors.rs2
-rw-r--r--library/core/src/iter/traits/collect.rs1
-rw-r--r--library/core/src/iter/traits/iterator.rs11
12 files changed, 168 insertions, 72 deletions
diff --git a/library/core/src/iter/adapters/peekable.rs b/library/core/src/iter/adapters/peekable.rs
index 20aca323b..65ba42920 100644
--- a/library/core/src/iter/adapters/peekable.rs
+++ b/library/core/src/iter/adapters/peekable.rs
@@ -12,6 +12,7 @@ use crate::ops::{ControlFlow, Try};
#[derive(Clone, Debug)]
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_diagnostic_item = "IterPeekable"]
pub struct Peekable<I: Iterator> {
iter: I,
/// Remember a peeked value, even if it was None.
diff --git a/library/core/src/iter/adapters/zip.rs b/library/core/src/iter/adapters/zip.rs
index b6b0c90cb..77ccf5085 100644
--- a/library/core/src/iter/adapters/zip.rs
+++ b/library/core/src/iter/adapters/zip.rs
@@ -95,6 +95,14 @@ where
}
#[inline]
+ fn fold<Acc, F>(self, init: Acc, f: F) -> Acc
+ where
+ F: FnMut(Acc, Self::Item) -> Acc,
+ {
+ ZipImpl::fold(self, init, f)
+ }
+
+ #[inline]
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item
where
Self: TrustedRandomAccessNoCoerce,
@@ -129,6 +137,9 @@ trait ZipImpl<A, B> {
where
A: DoubleEndedIterator + ExactSizeIterator,
B: DoubleEndedIterator + ExactSizeIterator;
+ fn fold<Acc, F>(self, init: Acc, f: F) -> Acc
+ where
+ F: FnMut(Acc, Self::Item) -> Acc;
// This has the same safety requirements as `Iterator::__iterator_get_unchecked`
unsafe fn get_unchecked(&mut self, idx: usize) -> <Self as Iterator>::Item
where
@@ -228,6 +239,14 @@ where
{
unreachable!("Always specialized");
}
+
+ #[inline]
+ default fn fold<Acc, F>(self, init: Acc, f: F) -> Acc
+ where
+ F: FnMut(Acc, Self::Item) -> Acc,
+ {
+ SpecFold::spec_fold(self, init, f)
+ }
}
#[doc(hidden)]
@@ -251,6 +270,24 @@ where
// `Iterator::__iterator_get_unchecked`.
unsafe { (self.a.__iterator_get_unchecked(idx), self.b.__iterator_get_unchecked(idx)) }
}
+
+ #[inline]
+ fn fold<Acc, F>(mut self, init: Acc, mut f: F) -> Acc
+ where
+ F: FnMut(Acc, Self::Item) -> Acc,
+ {
+ let mut accum = init;
+ let len = ZipImpl::size_hint(&self).0;
+ for i in 0..len {
+ // SAFETY: since Self: TrustedRandomAccessNoCoerce we can trust the size-hint to
+ // calculate the length and then use that to do unchecked iteration.
+ // fold consumes the iterator so we don't need to fixup any state.
+ unsafe {
+ accum = f(accum, self.get_unchecked(i));
+ }
+ }
+ accum
+ }
}
#[doc(hidden)]
@@ -590,3 +627,56 @@ unsafe impl<I: Iterator + TrustedRandomAccessNoCoerce> SpecTrustedRandomAccess f
unsafe { self.__iterator_get_unchecked(index) }
}
}
+
+trait SpecFold: Iterator {
+ fn spec_fold<B, F>(self, init: B, f: F) -> B
+ where
+ Self: Sized,
+ F: FnMut(B, Self::Item) -> B;
+}
+
+impl<A: Iterator, B: Iterator> SpecFold for Zip<A, B> {
+ // Adapted from default impl from the Iterator trait
+ #[inline]
+ default fn spec_fold<Acc, F>(mut self, init: Acc, mut f: F) -> Acc
+ where
+ F: FnMut(Acc, Self::Item) -> Acc,
+ {
+ let mut accum = init;
+ while let Some(x) = ZipImpl::next(&mut self) {
+ accum = f(accum, x);
+ }
+ accum
+ }
+}
+
+impl<A: TrustedLen, B: TrustedLen> SpecFold for Zip<A, B> {
+ #[inline]
+ fn spec_fold<Acc, F>(mut self, init: Acc, mut f: F) -> Acc
+ where
+ F: FnMut(Acc, Self::Item) -> Acc,
+ {
+ let mut accum = init;
+ loop {
+ let (upper, more) = if let Some(upper) = ZipImpl::size_hint(&self).1 {
+ (upper, false)
+ } else {
+ // Per TrustedLen contract a None upper bound means more than usize::MAX items
+ (usize::MAX, true)
+ };
+
+ for _ in 0..upper {
+ let pair =
+ // SAFETY: TrustedLen guarantees that at least `upper` many items are available
+ // therefore we know they can't be None
+ unsafe { (self.a.next().unwrap_unchecked(), self.b.next().unwrap_unchecked()) };
+ accum = f(accum, pair);
+ }
+
+ if !more {
+ break;
+ }
+ }
+ accum
+ }
+}
diff --git a/library/core/src/iter/mod.rs b/library/core/src/iter/mod.rs
index ca977d1ef..937a149ac 100644
--- a/library/core/src/iter/mod.rs
+++ b/library/core/src/iter/mod.rs
@@ -391,11 +391,11 @@ pub use self::traits::Iterator;
pub use self::range::Step;
#[unstable(
- feature = "iter_from_generator",
+ feature = "iter_from_coroutine",
issue = "43122",
- reason = "generators are unstable"
+ reason = "coroutines are unstable"
)]
-pub use self::sources::from_generator;
+pub use self::sources::from_coroutine;
#[stable(feature = "iter_empty", since = "1.2.0")]
pub use self::sources::{empty, Empty};
#[stable(feature = "iter_from_fn", since = "1.34.0")]
diff --git a/library/core/src/iter/sources.rs b/library/core/src/iter/sources.rs
index 3ec426a3a..56c1f8607 100644
--- a/library/core/src/iter/sources.rs
+++ b/library/core/src/iter/sources.rs
@@ -1,6 +1,6 @@
mod empty;
+mod from_coroutine;
mod from_fn;
-mod from_generator;
mod once;
mod once_with;
mod repeat;
@@ -27,11 +27,11 @@ pub use self::repeat_with::{repeat_with, RepeatWith};
pub use self::from_fn::{from_fn, FromFn};
#[unstable(
- feature = "iter_from_generator",
+ feature = "iter_from_coroutine",
issue = "43122",
- reason = "generators are unstable"
+ reason = "coroutines are unstable"
)]
-pub use self::from_generator::from_generator;
+pub use self::from_coroutine::from_coroutine;
#[stable(feature = "iter_successors", since = "1.34.0")]
pub use self::successors::{successors, Successors};
diff --git a/library/core/src/iter/sources/empty.rs b/library/core/src/iter/sources/empty.rs
index 243df015f..438e046a4 100644
--- a/library/core/src/iter/sources/empty.rs
+++ b/library/core/src/iter/sources/empty.rs
@@ -27,6 +27,7 @@ pub const fn empty<T>() -> Empty<T> {
/// This `struct` is created by the [`empty()`] function. See its documentation for more.
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "iter_empty", since = "1.2.0")]
+#[rustc_diagnostic_item = "IterEmpty"]
pub struct Empty<T>(marker::PhantomData<fn() -> T>);
#[stable(feature = "core_impl_debug", since = "1.9.0")]
diff --git a/library/core/src/iter/sources/from_coroutine.rs b/library/core/src/iter/sources/from_coroutine.rs
new file mode 100644
index 000000000..16fbca9b6
--- /dev/null
+++ b/library/core/src/iter/sources/from_coroutine.rs
@@ -0,0 +1,59 @@
+use crate::fmt;
+use crate::ops::{Coroutine, CoroutineState};
+use crate::pin::Pin;
+
+/// Creates a new iterator where each iteration calls the provided coroutine.
+///
+/// Similar to [`iter::from_fn`].
+///
+/// [`iter::from_fn`]: crate::iter::from_fn
+///
+/// # Examples
+///
+/// ```
+/// #![cfg_attr(bootstrap, feature(generators))]
+/// #![cfg_attr(not(bootstrap), feature(coroutines))]
+/// #![feature(iter_from_coroutine)]
+///
+/// let it = std::iter::from_coroutine(|| {
+/// yield 1;
+/// yield 2;
+/// yield 3;
+/// });
+/// let v: Vec<_> = it.collect();
+/// assert_eq!(v, [1, 2, 3]);
+/// ```
+#[inline]
+#[unstable(feature = "iter_from_coroutine", issue = "43122", reason = "coroutines are unstable")]
+pub fn from_coroutine<G: Coroutine<Return = ()> + Unpin>(coroutine: G) -> FromCoroutine<G> {
+ FromCoroutine(coroutine)
+}
+
+/// An iterator over the values yielded by an underlying coroutine.
+///
+/// This `struct` is created by the [`iter::from_coroutine()`] function. See its documentation for
+/// more.
+///
+/// [`iter::from_coroutine()`]: from_coroutine
+#[unstable(feature = "iter_from_coroutine", issue = "43122", reason = "coroutines are unstable")]
+#[derive(Clone)]
+pub struct FromCoroutine<G>(G);
+
+#[unstable(feature = "iter_from_coroutine", issue = "43122", reason = "coroutines are unstable")]
+impl<G: Coroutine<Return = ()> + Unpin> Iterator for FromCoroutine<G> {
+ type Item = G::Yield;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ match Pin::new(&mut self.0).resume(()) {
+ CoroutineState::Yielded(n) => Some(n),
+ CoroutineState::Complete(()) => None,
+ }
+ }
+}
+
+#[unstable(feature = "iter_from_coroutine", issue = "43122", reason = "coroutines are unstable")]
+impl<G> fmt::Debug for FromCoroutine<G> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_struct("FromCoroutine").finish()
+ }
+}
diff --git a/library/core/src/iter/sources/from_generator.rs b/library/core/src/iter/sources/from_generator.rs
deleted file mode 100644
index 4cbe731b2..000000000
--- a/library/core/src/iter/sources/from_generator.rs
+++ /dev/null
@@ -1,58 +0,0 @@
-use crate::fmt;
-use crate::ops::{Generator, GeneratorState};
-use crate::pin::Pin;
-
-/// Creates a new iterator where each iteration calls the provided generator.
-///
-/// Similar to [`iter::from_fn`].
-///
-/// [`iter::from_fn`]: crate::iter::from_fn
-///
-/// # Examples
-///
-/// ```
-/// #![feature(generators)]
-/// #![feature(iter_from_generator)]
-///
-/// let it = std::iter::from_generator(|| {
-/// yield 1;
-/// yield 2;
-/// yield 3;
-/// });
-/// let v: Vec<_> = it.collect();
-/// assert_eq!(v, [1, 2, 3]);
-/// ```
-#[inline]
-#[unstable(feature = "iter_from_generator", issue = "43122", reason = "generators are unstable")]
-pub fn from_generator<G: Generator<Return = ()> + Unpin>(generator: G) -> FromGenerator<G> {
- FromGenerator(generator)
-}
-
-/// An iterator over the values yielded by an underlying generator.
-///
-/// This `struct` is created by the [`iter::from_generator()`] function. See its documentation for
-/// more.
-///
-/// [`iter::from_generator()`]: from_generator
-#[unstable(feature = "iter_from_generator", issue = "43122", reason = "generators are unstable")]
-#[derive(Clone)]
-pub struct FromGenerator<G>(G);
-
-#[unstable(feature = "iter_from_generator", issue = "43122", reason = "generators are unstable")]
-impl<G: Generator<Return = ()> + Unpin> Iterator for FromGenerator<G> {
- type Item = G::Yield;
-
- fn next(&mut self) -> Option<Self::Item> {
- match Pin::new(&mut self.0).resume(()) {
- GeneratorState::Yielded(n) => Some(n),
- GeneratorState::Complete(()) => None,
- }
- }
-}
-
-#[unstable(feature = "iter_from_generator", issue = "43122", reason = "generators are unstable")]
-impl<G> fmt::Debug for FromGenerator<G> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.debug_struct("FromGenerator").finish()
- }
-}
diff --git a/library/core/src/iter/sources/once.rs b/library/core/src/iter/sources/once.rs
index 6e9ed0d3c..21be4377d 100644
--- a/library/core/src/iter/sources/once.rs
+++ b/library/core/src/iter/sources/once.rs
@@ -61,6 +61,7 @@ pub fn once<T>(value: T) -> Once<T> {
/// This `struct` is created by the [`once()`] function. See its documentation for more.
#[derive(Clone, Debug)]
#[stable(feature = "iter_once", since = "1.2.0")]
+#[rustc_diagnostic_item = "IterOnce"]
pub struct Once<T> {
inner: crate::option::IntoIter<T>,
}
diff --git a/library/core/src/iter/sources/once_with.rs b/library/core/src/iter/sources/once_with.rs
index 9309a06c8..8b31ab2ff 100644
--- a/library/core/src/iter/sources/once_with.rs
+++ b/library/core/src/iter/sources/once_with.rs
@@ -4,7 +4,7 @@ use crate::iter::{FusedIterator, TrustedLen};
/// Creates an iterator that lazily generates a value exactly once by invoking
/// the provided closure.
///
-/// This is commonly used to adapt a single value generator into a [`chain()`] of
+/// This is commonly used to adapt a single value coroutine into a [`chain()`] of
/// other kinds of iteration. Maybe you have an iterator that covers almost
/// everything, but you need an extra special case. Maybe you have a function
/// which works on iterators, but you only need to process one value.
diff --git a/library/core/src/iter/sources/successors.rs b/library/core/src/iter/sources/successors.rs
index 6a6cbe905..7f7b2c775 100644
--- a/library/core/src/iter/sources/successors.rs
+++ b/library/core/src/iter/sources/successors.rs
@@ -17,7 +17,7 @@ where
F: FnMut(&T) -> Option<T>,
{
// If this function returned `impl Iterator<Item=T>`
- // it could be based on `unfold` and not need a dedicated type.
+ // it could be based on `from_fn` and not need a dedicated type.
// However having a named `Successors<T, F>` type allows it to be `Clone` when `T` and `F` are.
Successors { next: first, succ }
}
diff --git a/library/core/src/iter/traits/collect.rs b/library/core/src/iter/traits/collect.rs
index e0ef5071c..0d1cf7941 100644
--- a/library/core/src/iter/traits/collect.rs
+++ b/library/core/src/iter/traits/collect.rs
@@ -146,6 +146,7 @@ pub trait FromIterator<A>: Sized {
/// assert_eq!(v, vec![5, 5, 5, 5, 5]);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_diagnostic_item = "from_iter_fn"]
fn from_iter<T: IntoIterator<Item = A>>(iter: T) -> Self;
}
diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs
index ac1fc26a1..6adea4442 100644
--- a/library/core/src/iter/traits/iterator.rs
+++ b/library/core/src/iter/traits/iterator.rs
@@ -27,13 +27,13 @@ fn _assert_is_object_safe(_: &dyn Iterator<Item = ()>) {}
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_on_unimplemented(
on(
- any(_Self = "core::ops::RangeTo<Idx>", _Self = "std::ops::RangeTo<Idx>"),
+ _Self = "core::ops::range::RangeTo<Idx>",
label = "if you meant to iterate until a value, add a starting value",
note = "`..end` is a `RangeTo`, which cannot be iterated on; you might have meant to have a \
bounded `Range`: `0..end`"
),
on(
- any(_Self = "core::ops::RangeToInclusive<Idx>", _Self = "std::ops::RangeToInclusive<Idx>"),
+ _Self = "core::ops::range::RangeToInclusive<Idx>",
label = "if you meant to iterate until a value (including it), add a starting value",
note = "`..=end` is a `RangeToInclusive`, which cannot be iterated on; you might have meant \
to have a bounded `RangeInclusive`: `0..=end`"
@@ -44,7 +44,7 @@ fn _assert_is_object_safe(_: &dyn Iterator<Item = ()>) {}
),
on(_Self = "&[]", label = "`{Self}` is not an iterator; try calling `.iter()`"),
on(
- any(_Self = "alloc::vec::Vec<T, A>", _Self = "std::vec::Vec<T, A>"),
+ _Self = "alloc::vec::Vec<T, A>",
label = "`{Self}` is not an iterator; try calling `.into_iter()` or `.iter()`"
),
on(
@@ -52,7 +52,7 @@ fn _assert_is_object_safe(_: &dyn Iterator<Item = ()>) {}
label = "`{Self}` is not an iterator; try calling `.chars()` or `.bytes()`"
),
on(
- any(_Self = "alloc::string::String", _Self = "std::string::String"),
+ _Self = "alloc::string::String",
label = "`{Self}` is not an iterator; try calling `.chars()` or `.bytes()`"
),
on(
@@ -69,6 +69,7 @@ fn _assert_is_object_safe(_: &dyn Iterator<Item = ()>) {}
message = "`{Self}` is not an iterator"
)]
#[doc(notable_trait)]
+#[cfg_attr(not(bootstrap), lang = "iterator")]
#[rustc_diagnostic_item = "Iterator"]
#[must_use = "iterators are lazy and do nothing unless consumed"]
pub trait Iterator {
@@ -2141,7 +2142,7 @@ pub trait Iterator {
/// passed collection. The collection is then returned, so the call chain
/// can be continued.
///
- /// This is useful when you already have a collection and wants to add
+ /// This is useful when you already have a collection and want to add
/// the iterator items to it.
///
/// This method is a convenience method to call [Extend::extend](trait.Extend.html),