-
Notifications
You must be signed in to change notification settings - Fork 13.8k
Add PeekableIterator
trait
#144935
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Add PeekableIterator
trait
#144935
Conversation
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
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 |
This comment has been minimized.
This comment has been minimized.
Improve documentation for `PeekableIterator` to reflect the changes in API Co-authored-by: +merlan #flirora <flirora@flirora.xyz>
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
// 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) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// 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 { |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
.
Co-authored-by: Tim (Theemathas) Chirananthavat <theemathas@gmail.com>
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this 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
/// Executes the closure on the `next()` element without advancing the iterator, or returns `None` if the iterator is exhausted. | ||
fn peek_map<T>(&mut self, func: impl for<'a> FnOnce(&'a Self::Item) -> T) -> Option<T> { | ||
self.peek_with(|x| x.map(|y| func(y))) | ||
} |
There was a problem hiding this 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 have been part of the ACP. Could you inline it into next_if
, or make it a standalone private function?
// SAFETY: See inner comments. | ||
unsafe { | ||
if T::IS_ZST { | ||
let len = end_or_len.addr(); | ||
if len == 0 { | ||
return func(None); | ||
} | ||
} else { | ||
if self.ptr == crate::intrinsics::transmute::<$ptr, NonNull<T>>(end_or_len) { | ||
return func(None); | ||
} | ||
} | ||
// SAFETY: Now that we know it wasn't empty | ||
// we can give out a reference to it. | ||
func(Some(self.ptr.$into_ref()).as_ref()) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Few requests:
- Use
mem::transmute
rather than the intrinsic directly - Use
NonNull
methods if possible. If not, add a comment about why this is - Can this
unsafe
block be broken up?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#144935 (comment) actually covers this better
|
This comment has been minimized.
This comment has been minimized.
The job Click to see the possible cause of the failure (guessed by this bot)
|
@wmstack Are you still open to working on this PR? If not, then I’m willing to take over the work on this. |
@bluebear94 Feel free to pick this up as I’m tied up with coursework at the moment. |
☔ The latest upstream changes (presumably #147353) made this pull request unmergeable. Please resolve the merge conflicts. |
Tracking issue: #132973
Implementation
Todo: Determine which structures need to implement
PeekableIterator
:slice::iter
str::Chars
vec::IntoIter
Peekable<T>
Unresolved Issues:
peek()
without mutating?