diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-07 05:48:48 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-07 05:48:48 +0000 |
commit | ef24de24a82fe681581cc130f342363c47c0969a (patch) | |
tree | 0d494f7e1a38b95c92426f58fe6eaa877303a86c /library/core/src/iter | |
parent | Releasing progress-linux version 1.74.1+dfsg1-1~progress7.99u1. (diff) | |
download | rustc-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.rs | 1 | ||||
-rw-r--r-- | library/core/src/iter/adapters/zip.rs | 90 | ||||
-rw-r--r-- | library/core/src/iter/mod.rs | 6 | ||||
-rw-r--r-- | library/core/src/iter/sources.rs | 8 | ||||
-rw-r--r-- | library/core/src/iter/sources/empty.rs | 1 | ||||
-rw-r--r-- | library/core/src/iter/sources/from_coroutine.rs | 59 | ||||
-rw-r--r-- | library/core/src/iter/sources/from_generator.rs | 58 | ||||
-rw-r--r-- | library/core/src/iter/sources/once.rs | 1 | ||||
-rw-r--r-- | library/core/src/iter/sources/once_with.rs | 2 | ||||
-rw-r--r-- | library/core/src/iter/sources/successors.rs | 2 | ||||
-rw-r--r-- | library/core/src/iter/traits/collect.rs | 1 | ||||
-rw-r--r-- | library/core/src/iter/traits/iterator.rs | 11 |
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), |