Skip to content

Add PeekableIterator trait#144935

Open
wmstack wants to merge 5 commits into
rust-lang:mainfrom
wmstack:PeekableIterator
Open

Add PeekableIterator trait#144935
wmstack wants to merge 5 commits into
rust-lang:mainfrom
wmstack:PeekableIterator

Conversation

@wmstack
Copy link
Copy Markdown
Contributor

@wmstack wmstack commented Aug 5, 2025

View all comments

Tracking issue: #132973

Implementation

pub trait PeekableIterator: Iterator {
  // required method
  fn peek_with<T>(&mut self, func: impl for<'a> FnOnce(Option<&'a Self::Item>) -> T) -> T

  // provided methods
  fn peek_map<T>(&mut self, func: impl for<'a> FnOnce(&'a Self::Item) -> T) -> Option<T>
  fn next_if(&mut self, func: impl FnOnce(&Self::Item) -> bool) -> Option<Self::Item>
  fn next_if_eq<T>(&mut self, expected: &T) -> Option<Self::Item>
  where
    Self::Item: PartialEq<T>,
    T: ?Sized,
}

Todo: Determine which structures need to implement PeekableIterator:

  • slice::iter
  • str::Chars
  • vec::IntoIter
  • Peekable<T>

Unresolved Issues:

  • Add another trait for iterators that can peek() without mutating?

@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented Aug 5, 2025

r? @tgross35

rustbot has assigned @tgross35.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Aug 5, 2025
@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@theemathas
Copy link
Copy Markdown
Contributor

Maybe the correct function signature is this?

fn peek<T>(&mut self, callback: impl for<'a> FnOnce(Option<&'a Self::Item>) -> T) -> T

This would mean, for example, that str::Chars would be able to implement this without having a field inside the iterator that contains a char. Instead, it would be able to create a local variable in the peek method that stores the char.

@rust-log-analyzer

This comment has been minimized.

Comment thread library/core/src/iter/traits/peekable.rs Outdated
Comment thread library/core/src/iter/traits/peekable.rs Outdated
Comment thread library/core/src/iter/traits/peekable.rs Outdated
Comment thread library/core/src/iter/traits/peekable.rs Outdated
Comment thread library/core/src/iter/traits/peekable.rs Outdated
@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

Comment thread library/core/src/array/iter/iter_inner.rs
Comment thread library/core/src/slice/iter/macros.rs Outdated
Comment on lines +485 to +488
// 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<T>>(end_or_len) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// 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<T>>(end_or_len) {
if ptr.as_ptr() == end_or_len {

Copy link
Copy Markdown
Contributor Author

@wmstack wmstack Aug 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I was not able to write it this way as Rust determines the types differ in their mutability. In general, this code was based on the next() method generic over both Iter and IterMut

Copy link
Copy Markdown
Contributor

@tgross35 tgross35 Sep 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What exactly was the error? Seems possible to resolve by adding a $as_ptr metavar that is either as_ptr or as_mut_ptr depending on which one is being implemented (like into_ref).

next is a bit magical, others should try to be simpler if possible. cloning and advancing should be fine, it's cheap.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cloning actually wouldn't work for IterMut since it doesn't implement it. But that actually brings up a good point; the safety comments need to say why it is sound to hand out a&mut T.

Comment thread library/core/src/slice/iter/macros.rs Outdated
@rust-log-analyzer

This comment has been minimized.

Copy link
Copy Markdown
Contributor

@tgross35 tgross35 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't seem to be tested at all. Please make sure that even unstable API gets helpful examples, aside from checking the implementation they serve as a very useful smoke test for whether or not the API makes sense in the first place.

Additionally, the type-specific impls need tests in library/coretests

View changes since this review

Comment thread library/core/src/iter/traits/peekable.rs Outdated
Comment thread library/core/src/slice/iter/macros.rs Outdated
@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Sep 3, 2025
@rustbot

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@bluebear94
Copy link
Copy Markdown
Contributor

@wmstack Are you still open to working on this PR? If not, then I’m willing to take over the work on this.

@wmstack
Copy link
Copy Markdown
Contributor Author

wmstack commented Oct 9, 2025

@bluebear94 Feel free to pick this up as I’m tied up with coursework at the moment.

@bors
Copy link
Copy Markdown
Collaborator

bors commented Oct 14, 2025

☔ The latest upstream changes (presumably #147353) made this pull request unmergeable. Please resolve the merge conflicts.

@rustbot

This comment has been minimized.

@rustbot

This comment has been minimized.

@rustbot rustbot added the has-merge-commits PR has merge commits, merge with caution. label Feb 15, 2026
@rust-log-analyzer

This comment has been minimized.

@rustbot

This comment has been minimized.

@rustbot

This comment has been minimized.

@rustbot rustbot added the has-merge-commits PR has merge commits, merge with caution. label May 27, 2026
@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented May 27, 2026

Some changes occurred in src/tools/cargo

cc @ehuss

@rustbot

This comment has been minimized.

@wmstack wmstack force-pushed the PeekableIterator branch from 4e18775 to af357b6 Compare May 27, 2026 01:09
@rustbot

This comment has been minimized.

@wmstack wmstack force-pushed the PeekableIterator branch from af357b6 to 22a1c0f Compare May 27, 2026 01:25
@rustbot

This comment has been minimized.

@rustbot

This comment has been minimized.

@rustbot rustbot removed has-merge-commits PR has merge commits, merge with caution. S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels May 27, 2026
wmstack added 2 commits May 27, 2026 11:34
Implement peekable for slice::iter

Implement new PeekableIterator for Iter

Replace T with U

Apply suggestions from code review

Improve documentation for `PeekableIterator` to reflect the changes in API

Co-authored-by: +merlan #flirora <flirora@flirora.xyz>

Update next_if to use the bool

Update next_if logic to handle Some(false) correctly

Implement PeekableIterator for Chars

Peek by cloning on Chars

fix input parameter in Chars

Implement PeekableIterator for IntoIter

Forget temporary in iter_inner

Implement PeekableIterator for Peekable

Remove as_ref()

Remove unneeded transmute

Co-authored-by: Tim (Theemathas) Chirananthavat <theemathas@gmail.com>

Use assume_init_ref directly from slice

fix peek_with in macros

Reduce unsafe scope with Iter/IterMut

remove peek_map, add examples

Fix trailing whitespace, punctuation

fix example chars

add 0 case

fix example syntax
@wmstack wmstack force-pushed the PeekableIterator branch from 22a1c0f to d7fff9a Compare May 27, 2026 01:39
@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented May 27, 2026

This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed.

Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.

@rust-log-analyzer

This comment has been minimized.

@wmstack
Copy link
Copy Markdown
Contributor Author

wmstack commented May 27, 2026

I have squashed and rebased to the latest main branch.

Seems to be a problem with one of the doctests. In any case the line numbers provided for which assertion failed are concerning as they point at the wrong line numbers.

RUST_BACKTRACE=full ./x test library/core --doc --test-args "iter::traits::peekable::PeekableIterator::peek_with"

I get that the 19th line has an error, and that is an empty line:
image

The correct line in this instance is line number 24. Maybe the tool omits some spaces or comments, which I don't think is helpful.

image

@rust-log-analyzer

This comment has been minimized.

@wmstack
Copy link
Copy Markdown
Contributor Author

wmstack commented May 27, 2026

@tgross35 I believe the doctests should all compile but just a few clarifications about the coretests.

  • Adding the unstable feature to the relevant file shows:
image

However the crate root at library/coretests/lib.rs is intentionally left empty. What do you think is the right approach here.

  • Should the peekable iterator coretests be in their own file? There is only four trait files and inside library/coretests/iter/traits/iterator.rs there aren't really any other traits being imported they seem to be available through the prelude or something. Is this because they are stabilised?

Edit: Even if I ignore the intentionally empty comment at the crate root, it doesn't really get detected despite being used in a few un-committed tests:
image

@workingjubilee
Copy link
Copy Markdown
Member

have you tried adding it to https://github.com/rust-lang/rust/blob/main/library/coretests/tests/lib.rs instead?

@workingjubilee
Copy link
Copy Markdown
Member

workingjubilee commented May 27, 2026

rustc UX issue: "crate root" file not identified, can be confusing in case of test files. off to file a bug! #157001

@rust-log-analyzer

This comment has been minimized.

@wmstack wmstack force-pushed the PeekableIterator branch from 7ecb703 to 8772d5c Compare May 27, 2026 06:54
@wmstack
Copy link
Copy Markdown
Contributor Author

wmstack commented May 28, 2026

@rustbot ready

@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label May 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-libs Relevant to the library team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants