From 38e446af571509451177ec370ba8e004db6b2787 Mon Sep 17 00:00:00 2001 From: Waleed Dahshan Date: Tue, 5 Aug 2025 11:55:34 +1000 Subject: [PATCH 01/14] Add peekable_iterator --- library/core/src/iter/mod.rs | 2 ++ library/core/src/iter/traits/mod.rs | 3 ++ library/core/src/iter/traits/peekable.rs | 42 ++++++++++++++++++++++++ 3 files changed, 47 insertions(+) create mode 100644 library/core/src/iter/traits/peekable.rs diff --git a/library/core/src/iter/mod.rs b/library/core/src/iter/mod.rs index 56ca1305b601b..fa1564712ed35 100644 --- a/library/core/src/iter/mod.rs +++ b/library/core/src/iter/mod.rs @@ -452,6 +452,8 @@ pub use self::traits::FusedIterator; pub use self::traits::InPlaceIterable; #[stable(feature = "rust1", since = "1.0.0")] pub use self::traits::Iterator; +#[unstable(feature = "peekable_iterator", issue = "132973")] +pub use self::traits::PeekableIterator; #[unstable(issue = "none", feature = "trusted_fused")] pub use self::traits::TrustedFused; #[unstable(feature = "trusted_len", issue = "37572")] diff --git a/library/core/src/iter/traits/mod.rs b/library/core/src/iter/traits/mod.rs index b330e9ffe21ac..116353c9a1783 100644 --- a/library/core/src/iter/traits/mod.rs +++ b/library/core/src/iter/traits/mod.rs @@ -4,6 +4,7 @@ mod double_ended; mod exact_size; mod iterator; mod marker; +mod peekable; mod unchecked_iterator; #[unstable(issue = "none", feature = "inplace_iteration")] @@ -12,6 +13,8 @@ pub use self::marker::InPlaceIterable; pub use self::marker::TrustedFused; #[unstable(feature = "trusted_step", issue = "85731")] pub use self::marker::TrustedStep; +#[unstable(feature = "peekable_iterator", issue = "132973")] +pub use self::peekable::PeekableIterator; pub(crate) use self::unchecked_iterator::UncheckedIterator; #[stable(feature = "rust1", since = "1.0.0")] pub use self::{ diff --git a/library/core/src/iter/traits/peekable.rs b/library/core/src/iter/traits/peekable.rs new file mode 100644 index 0000000000000..99aeb0c87d6f7 --- /dev/null +++ b/library/core/src/iter/traits/peekable.rs @@ -0,0 +1,42 @@ +#[unstable(feature = "peekable_iterator", issue = "132973")] +/// Iterators which inherently support `peek()` without needing to be wrapped by a `Peekable`. +pub trait PeekableIterator: Iterator { + /// returns a reference to the `next()` value without advancing the iterator. + /// Just like `next()`, if there is a value, it returns a reference to it in Some() + /// if the iteration is finished, a `None` is returned + /// + /// # Examples + /// Basic usage: + /// ``` + /// let xs = [1, 2, 3]; + /// let mut iter = xs.iter(); + /// + /// // peek() allows us to check the future value + /// assert_eq!(iter.peek(), Some(&&1)); + /// assert_eq!(iter.next(), Some(&1)); + /// + /// // peek() doesn't move the iterator forward + /// assert_eq!(iter.peek(), Some(&&2)); + /// assert_eq!(iter.peek(), Some(&&2)); + /// + /// ``` + fn peek(&mut self) -> Option<&Self::Item>; + + /// returns the `next()` element if a predicate holds true + fn next_if(&mut self, func: impl FnOnce(&Self::Item) -> bool) -> Option { + let Some(item) = self.peek() else { + return None; + }; + + if func(item) { self.next() } else { None } + } + + /// move forward and return the `next()` item if it is equal to the expected value + fn next_if_eq(&mut self, expected: &T) -> Option + where + Self::Item: PartialEq, + T: ?Sized, + { + self.next_if(|x| x == expected) + } +} From 8d2bdb05701c0c098d9870c5111c5702ae22573f Mon Sep 17 00:00:00 2001 From: Waleed Dahshan Date: Tue, 5 Aug 2025 13:45:58 +1000 Subject: [PATCH 02/14] Implement peekable for slice::iter --- library/core/src/slice/iter.rs | 3 ++- library/core/src/slice/iter/macros.rs | 28 +++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs index ae910e0525209..a4708c8602d8a 100644 --- a/library/core/src/slice/iter.rs +++ b/library/core/src/slice/iter.rs @@ -6,7 +6,8 @@ mod macros; use super::{from_raw_parts, from_raw_parts_mut}; use crate::hint::assert_unchecked; use crate::iter::{ - FusedIterator, TrustedLen, TrustedRandomAccess, TrustedRandomAccessNoCoerce, UncheckedIterator, + FusedIterator, PeekableIterator, TrustedLen, TrustedRandomAccess, TrustedRandomAccessNoCoerce, + UncheckedIterator, }; use crate::marker::PhantomData; use crate::mem::{self, SizedTypeProperties}; diff --git a/library/core/src/slice/iter/macros.rs b/library/core/src/slice/iter/macros.rs index 7c1ed3fe8a246..78202f6f1c691 100644 --- a/library/core/src/slice/iter/macros.rs +++ b/library/core/src/slice/iter/macros.rs @@ -468,6 +468,34 @@ macro_rules! iterator { } } + #[unstable(feature = "peekable_iterator", issue = "132973")] + impl<'a, T> PeekableIterator for $name<'a, T> { + fn peek(&mut self) -> Option<&$elem> { + let ptr = self.ptr; + let end_or_len = self.end_or_len; + + // SAFETY: See inner comments. + unsafe { + if T::IS_ZST { + let len = end_or_len.addr(); + if len == 0 { + return None; + } + } else { + // SAFETY: by type invariant, the `end_or_len` field is always + // non-null for a non-ZST pointee. (This transmute ensures we + // get `!nonnull` metadata on the load of the field.) + if ptr == crate::intrinsics::transmute::<$ptr, NonNull>(end_or_len) { + return None; + } + } + // SAFETY: Now that we know it wasn't empty and we've moved past + // the first one (to avoid giving a duplicate `&mut` next time), + // we can give out a reference to it. + Some(core::mem::transmute(&self.ptr)) + } + } + } #[stable(feature = "default_iters", since = "1.70.0")] impl Default for $name<'_, T> { /// Creates an empty slice iterator. From ecc7b86d7743bbcbbeda7055f5597315598f5c9b Mon Sep 17 00:00:00 2001 From: Waleed Dahshan Date: Tue, 5 Aug 2025 18:23:41 +1000 Subject: [PATCH 03/14] Implement new PeekableIterator for Iter --- library/core/src/iter/traits/peekable.rs | 33 ++++++------------------ library/core/src/slice/iter/macros.rs | 12 ++++----- 2 files changed, 14 insertions(+), 31 deletions(-) diff --git a/library/core/src/iter/traits/peekable.rs b/library/core/src/iter/traits/peekable.rs index 99aeb0c87d6f7..99562b2ca2946 100644 --- a/library/core/src/iter/traits/peekable.rs +++ b/library/core/src/iter/traits/peekable.rs @@ -1,34 +1,17 @@ #[unstable(feature = "peekable_iterator", issue = "132973")] /// Iterators which inherently support `peek()` without needing to be wrapped by a `Peekable`. pub trait PeekableIterator: Iterator { - /// returns a reference to the `next()` value without advancing the iterator. - /// Just like `next()`, if there is a value, it returns a reference to it in Some() - /// if the iteration is finished, a `None` is returned - /// - /// # Examples - /// Basic usage: - /// ``` - /// let xs = [1, 2, 3]; - /// let mut iter = xs.iter(); - /// - /// // peek() allows us to check the future value - /// assert_eq!(iter.peek(), Some(&&1)); - /// assert_eq!(iter.next(), Some(&1)); - /// - /// // peek() doesn't move the iterator forward - /// assert_eq!(iter.peek(), Some(&&2)); - /// assert_eq!(iter.peek(), Some(&&2)); - /// - /// ``` - fn peek(&mut self) -> Option<&Self::Item>; + /// executes the closure with an Option containing `None` if the iterator is exhausted or Some(&Self::Item) + fn peek_with(&mut self, func: impl for<'a> FnOnce(Option<&'a Self::Item>) -> T) -> T; + + /// executes the closure on the next element without advancing the iterator, or returns None if the iterator is exhausted. + fn peek_map(&mut self, func: impl for<'a> FnOnce(&'a Self::Item) -> T) -> Option { + self.peek_with(|x| x.map(|y| func(y))) + } /// returns the `next()` element if a predicate holds true fn next_if(&mut self, func: impl FnOnce(&Self::Item) -> bool) -> Option { - let Some(item) = self.peek() else { - return None; - }; - - if func(item) { self.next() } else { None } + self.peek_map(func).and_then(|_| self.next()) } /// move forward and return the `next()` item if it is equal to the expected value diff --git a/library/core/src/slice/iter/macros.rs b/library/core/src/slice/iter/macros.rs index 78202f6f1c691..e00f8ee3490a8 100644 --- a/library/core/src/slice/iter/macros.rs +++ b/library/core/src/slice/iter/macros.rs @@ -470,7 +470,7 @@ macro_rules! iterator { #[unstable(feature = "peekable_iterator", issue = "132973")] impl<'a, T> PeekableIterator for $name<'a, T> { - fn peek(&mut self) -> Option<&$elem> { + fn peek_with(&mut self, func: impl for<'b> FnOnce(Option<&'b Self::Item>) -> T) -> T { let ptr = self.ptr; let end_or_len = self.end_or_len; @@ -479,20 +479,20 @@ macro_rules! iterator { if T::IS_ZST { let len = end_or_len.addr(); if len == 0 { - return None; + return func(None); } } else { // SAFETY: by type invariant, the `end_or_len` field is always // non-null for a non-ZST pointee. (This transmute ensures we // get `!nonnull` metadata on the load of the field.) if ptr == crate::intrinsics::transmute::<$ptr, NonNull>(end_or_len) { - return None; + return func(None); } } - // SAFETY: Now that we know it wasn't empty and we've moved past - // the first one (to avoid giving a duplicate `&mut` next time), + // SAFETY: Now that we know it wasn't empty // we can give out a reference to it. - Some(core::mem::transmute(&self.ptr)) + let tmp = {ptr}.$into_ref(); + func(Some(&tmp)) } } } From 3dd13bca9b3603de5ded81baebe1cccdac33debd Mon Sep 17 00:00:00 2001 From: Waleed Dahshan Date: Tue, 5 Aug 2025 18:37:47 +1000 Subject: [PATCH 04/14] Replace T with U --- library/core/src/slice/iter/macros.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/slice/iter/macros.rs b/library/core/src/slice/iter/macros.rs index e00f8ee3490a8..df2c2945dd51c 100644 --- a/library/core/src/slice/iter/macros.rs +++ b/library/core/src/slice/iter/macros.rs @@ -470,7 +470,7 @@ macro_rules! iterator { #[unstable(feature = "peekable_iterator", issue = "132973")] impl<'a, T> PeekableIterator for $name<'a, T> { - fn peek_with(&mut self, func: impl for<'b> FnOnce(Option<&'b Self::Item>) -> T) -> T { + fn peek_with(&mut self, func: impl for<'b> FnOnce(Option<&'b Self::Item>) -> U) -> U { let ptr = self.ptr; let end_or_len = self.end_or_len; From bf0193cc61b24bc3a4c7bc0764f88a3128b0851b Mon Sep 17 00:00:00 2001 From: Waleed Dahshan <58462210+wmstack@users.noreply.github.com> Date: Wed, 6 Aug 2025 12:52:12 +1000 Subject: [PATCH 05/14] Apply suggestions from code review Improve documentation for `PeekableIterator` to reflect the changes in API Co-authored-by: +merlan #flirora --- library/core/src/iter/traits/peekable.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/library/core/src/iter/traits/peekable.rs b/library/core/src/iter/traits/peekable.rs index 99562b2ca2946..c9ebf88fda05d 100644 --- a/library/core/src/iter/traits/peekable.rs +++ b/library/core/src/iter/traits/peekable.rs @@ -1,20 +1,20 @@ #[unstable(feature = "peekable_iterator", issue = "132973")] -/// Iterators which inherently support `peek()` without needing to be wrapped by a `Peekable`. +/// Iterators which inherently support peeking without needing to be wrapped by a `Peekable`. pub trait PeekableIterator: Iterator { - /// executes the closure with an Option containing `None` if the iterator is exhausted or Some(&Self::Item) + /// Executes the closure with a reference to the `next()` value without advancing the iterator. fn peek_with(&mut self, func: impl for<'a> FnOnce(Option<&'a Self::Item>) -> T) -> T; - /// executes the closure on the next element without advancing the iterator, or returns None if the iterator is exhausted. + /// Executes the closure on the `next()` element without advancing the iterator, or returns `None` if the iterator is exhausted. fn peek_map(&mut self, func: impl for<'a> FnOnce(&'a Self::Item) -> T) -> Option { self.peek_with(|x| x.map(|y| func(y))) } - /// returns the `next()` element if a predicate holds true + /// Returns the `next()` element if the given predicate holds true. fn next_if(&mut self, func: impl FnOnce(&Self::Item) -> bool) -> Option { self.peek_map(func).and_then(|_| self.next()) } - /// move forward and return the `next()` item if it is equal to the expected value + /// Moves forward and return the `next()` item if it is equal to the expected value. fn next_if_eq(&mut self, expected: &T) -> Option where Self::Item: PartialEq, From dc33dd203e64e7e5633633c420f04093cac0526c Mon Sep 17 00:00:00 2001 From: Waleed Dahshan Date: Wed, 6 Aug 2025 13:04:11 +1000 Subject: [PATCH 06/14] Update next_if to use the bool --- library/core/src/iter/traits/peekable.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/iter/traits/peekable.rs b/library/core/src/iter/traits/peekable.rs index c9ebf88fda05d..00d161e497f47 100644 --- a/library/core/src/iter/traits/peekable.rs +++ b/library/core/src/iter/traits/peekable.rs @@ -11,7 +11,7 @@ pub trait PeekableIterator: Iterator { /// Returns the `next()` element if the given predicate holds true. fn next_if(&mut self, func: impl FnOnce(&Self::Item) -> bool) -> Option { - self.peek_map(func).and_then(|_| self.next()) + self.peek_with(|x| if func(x) { self.next() } else { None }) } /// Moves forward and return the `next()` item if it is equal to the expected value. From 58924634d8b6497805e49cd5c569a1068d8baa21 Mon Sep 17 00:00:00 2001 From: Waleed Dahshan Date: Wed, 6 Aug 2025 13:15:37 +1000 Subject: [PATCH 07/14] Update next_if logic to handle Some(false) correctly --- library/core/src/iter/traits/peekable.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/library/core/src/iter/traits/peekable.rs b/library/core/src/iter/traits/peekable.rs index 00d161e497f47..0de6d98122630 100644 --- a/library/core/src/iter/traits/peekable.rs +++ b/library/core/src/iter/traits/peekable.rs @@ -11,7 +11,10 @@ pub trait PeekableIterator: Iterator { /// Returns the `next()` element if the given predicate holds true. fn next_if(&mut self, func: impl FnOnce(&Self::Item) -> bool) -> Option { - self.peek_with(|x| if func(x) { self.next() } else { None }) + match self.peek_map(func) { + Some(true) => self.next(), + _ => None, + } } /// Moves forward and return the `next()` item if it is equal to the expected value. From ec565f662768ef107d9cb93470f3682d7d237e2f Mon Sep 17 00:00:00 2001 From: Waleed Dahshan Date: Wed, 6 Aug 2025 13:34:42 +1000 Subject: [PATCH 08/14] Implement PeekableIterator for Chars --- library/core/src/str/iter.rs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/library/core/src/str/iter.rs b/library/core/src/str/iter.rs index d2985d8a18669..6b65b9c9f5f51 100644 --- a/library/core/src/str/iter.rs +++ b/library/core/src/str/iter.rs @@ -8,8 +8,8 @@ use super::{ }; use crate::fmt::{self, Write}; use crate::iter::{ - Chain, Copied, Filter, FlatMap, Flatten, FusedIterator, Map, TrustedLen, TrustedRandomAccess, - TrustedRandomAccessNoCoerce, + Chain, Copied, Filter, FlatMap, Flatten, FusedIterator, Map, PeekableIterator, TrustedLen, + TrustedRandomAccess, TrustedRandomAccessNoCoerce, }; use crate::num::NonZero; use crate::ops::Try; @@ -132,6 +132,18 @@ impl<'a> DoubleEndedIterator for Chars<'a> { } } +#[unstable(feature = "peekable_iterator", issue = "132973")] +impl<'a> PeekableIterator for Chars<'a> { + fn peek_with(&mut self, func: impl for<'b> FnOnce(Option<&'b Self::Item>) -> T) -> T { + // SAFETY: `str` invariant says `self.iter` is a valid UTF-8 string and + // the resulting `ch` is a valid Unicode Scalar Value. + let tmp = unsafe { + next_code_point(&mut self.iter.clone()).map(|ch| char::from_u32_unchecked(ch)) + }; + func(&tmp) + } +} + #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for Chars<'_> {} From ff668ecf0ec0217a686e05aee2060005bac3f32d Mon Sep 17 00:00:00 2001 From: Waleed Dahshan Date: Wed, 6 Aug 2025 13:56:36 +1000 Subject: [PATCH 09/14] Peek by cloning on Chars --- library/core/src/str/iter.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/library/core/src/str/iter.rs b/library/core/src/str/iter.rs index 6b65b9c9f5f51..1baa17f644f4e 100644 --- a/library/core/src/str/iter.rs +++ b/library/core/src/str/iter.rs @@ -135,11 +135,7 @@ impl<'a> DoubleEndedIterator for Chars<'a> { #[unstable(feature = "peekable_iterator", issue = "132973")] impl<'a> PeekableIterator for Chars<'a> { fn peek_with(&mut self, func: impl for<'b> FnOnce(Option<&'b Self::Item>) -> T) -> T { - // SAFETY: `str` invariant says `self.iter` is a valid UTF-8 string and - // the resulting `ch` is a valid Unicode Scalar Value. - let tmp = unsafe { - next_code_point(&mut self.iter.clone()).map(|ch| char::from_u32_unchecked(ch)) - }; + let tmp = self.clone().next(); func(&tmp) } } From 56d74c62ad787a6f747472524c11022ac18eab80 Mon Sep 17 00:00:00 2001 From: Waleed Dahshan Date: Wed, 6 Aug 2025 14:45:37 +1000 Subject: [PATCH 10/14] fix input parameter in Chars --- library/core/src/str/iter.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/str/iter.rs b/library/core/src/str/iter.rs index 1baa17f644f4e..4bb2368eec7a2 100644 --- a/library/core/src/str/iter.rs +++ b/library/core/src/str/iter.rs @@ -136,7 +136,7 @@ impl<'a> DoubleEndedIterator for Chars<'a> { impl<'a> PeekableIterator for Chars<'a> { fn peek_with(&mut self, func: impl for<'b> FnOnce(Option<&'b Self::Item>) -> T) -> T { let tmp = self.clone().next(); - func(&tmp) + func(tmp.as_ref()) } } From c552fc81d8412eb3ee15c86155f7f1c6bd88c093 Mon Sep 17 00:00:00 2001 From: Waleed Dahshan Date: Wed, 6 Aug 2025 16:35:35 +1000 Subject: [PATCH 11/14] Implement PeekableIterator for IntoIter --- library/core/src/array/iter.rs | 9 ++++++++- library/core/src/array/iter/iter_inner.rs | 10 ++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/library/core/src/array/iter.rs b/library/core/src/array/iter.rs index fdae5c08f1e8e..f28cff9762f90 100644 --- a/library/core/src/array/iter.rs +++ b/library/core/src/array/iter.rs @@ -1,7 +1,7 @@ //! Defines the `IntoIter` owned iterator for arrays. use crate::intrinsics::transmute_unchecked; -use crate::iter::{FusedIterator, TrustedLen, TrustedRandomAccessNoCoerce}; +use crate::iter::{FusedIterator, PeekableIterator, TrustedLen, TrustedRandomAccessNoCoerce}; use crate::mem::MaybeUninit; use crate::num::NonZero; use crate::ops::{IndexRange, Range, Try}; @@ -350,6 +350,13 @@ impl FusedIterator for IntoIter {} #[stable(feature = "array_value_iter_impls", since = "1.40.0")] unsafe impl TrustedLen for IntoIter {} +#[unstable(feature = "peekable_iterator", issue = "132973")] +impl PeekableIterator for IntoIter { + fn peek_with(&mut self, func: impl for<'b> FnOnce(Option<&'b Self::Item>) -> U) -> U { + self.unsize_mut().peek_with(func) + } +} + #[doc(hidden)] #[unstable(issue = "none", feature = "std_internals")] #[rustc_unsafe_specialization_marker] diff --git a/library/core/src/array/iter/iter_inner.rs b/library/core/src/array/iter/iter_inner.rs index 3c2343591f8cf..7a623a257e300 100644 --- a/library/core/src/array/iter/iter_inner.rs +++ b/library/core/src/array/iter/iter_inner.rs @@ -175,6 +175,16 @@ impl PolymorphicIter<[MaybeUninit]> { }) } + #[inline] + pub(super) fn peek_with(&mut self, func: impl for<'b> FnOnce(Option<&'b T>) -> U) -> U { + let tmp = self.alive.clone().next().map(|idx| { + // SAFETY: `idx` is in self.alive range + unsafe { self.data.get_unchecked(idx).assume_init_read() } + }); + + func(tmp.as_ref()) + } + #[inline] pub(super) fn size_hint(&self) -> (usize, Option) { let len = self.len(); From 6fc70f2815133e9d1be4351580a70e65f4280a6b Mon Sep 17 00:00:00 2001 From: Waleed Dahshan Date: Thu, 7 Aug 2025 10:09:02 +1000 Subject: [PATCH 12/14] Forget temporary in iter_inner --- library/core/src/array/iter/iter_inner.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/library/core/src/array/iter/iter_inner.rs b/library/core/src/array/iter/iter_inner.rs index 7a623a257e300..769be779a139d 100644 --- a/library/core/src/array/iter/iter_inner.rs +++ b/library/core/src/array/iter/iter_inner.rs @@ -176,13 +176,16 @@ impl PolymorphicIter<[MaybeUninit]> { } #[inline] - pub(super) fn peek_with(&mut self, func: impl for<'b> FnOnce(Option<&'b T>) -> U) -> U { + pub(super) fn peek_with(&self, func: impl for<'b> FnOnce(Option<&'b T>) -> U) -> U { let tmp = self.alive.clone().next().map(|idx| { // SAFETY: `idx` is in self.alive range unsafe { self.data.get_unchecked(idx).assume_init_read() } }); - func(tmp.as_ref()) + let out = func(tmp.as_ref()); + // Avoid dropping before the item is consumed + crate::mem::forget(tmp); + out } #[inline] From 54ad56858a0d9a7c2468c41a954dfe9f4d60b851 Mon Sep 17 00:00:00 2001 From: Waleed Dahshan Date: Thu, 7 Aug 2025 10:09:51 +1000 Subject: [PATCH 13/14] Implement PeekableIterator for Peekable --- library/core/src/iter/adapters/peekable.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/library/core/src/iter/adapters/peekable.rs b/library/core/src/iter/adapters/peekable.rs index a6522659620a0..605a4eb48c248 100644 --- a/library/core/src/iter/adapters/peekable.rs +++ b/library/core/src/iter/adapters/peekable.rs @@ -1,5 +1,5 @@ use crate::iter::adapters::SourceIter; -use crate::iter::{FusedIterator, TrustedLen}; +use crate::iter::{FusedIterator, PeekableIterator, TrustedLen}; use crate::ops::{ControlFlow, Try}; /// An iterator with a `peek()` that returns an optional reference to the next @@ -322,6 +322,14 @@ impl Peekable { #[unstable(feature = "trusted_len", issue = "37572")] unsafe impl TrustedLen for Peekable where I: TrustedLen {} +#[unstable(feature = "peekable_iterator", issue = "132973")] +impl PeekableIterator for Peekable { + fn peek_with(&mut self, func: impl for<'a> FnOnce(Option<&'a Self::Item>) -> T) -> T { + let tmp = self.peek(); + func(tmp.as_ref()) + } +} + #[unstable(issue = "none", feature = "inplace_iteration")] unsafe impl SourceIter for Peekable where From 14a6ecdff771feacb4c67f2f4e7b48e2349c9379 Mon Sep 17 00:00:00 2001 From: Waleed Dahshan Date: Thu, 7 Aug 2025 10:14:12 +1000 Subject: [PATCH 14/14] Remove as_ref() --- library/core/src/iter/adapters/peekable.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/iter/adapters/peekable.rs b/library/core/src/iter/adapters/peekable.rs index 605a4eb48c248..5ef1e1ac1758d 100644 --- a/library/core/src/iter/adapters/peekable.rs +++ b/library/core/src/iter/adapters/peekable.rs @@ -326,7 +326,7 @@ unsafe impl TrustedLen for Peekable where I: TrustedLen {} impl PeekableIterator for Peekable { fn peek_with(&mut self, func: impl for<'a> FnOnce(Option<&'a Self::Item>) -> T) -> T { let tmp = self.peek(); - func(tmp.as_ref()) + func(tmp) } }