-
Notifications
You must be signed in to change notification settings - Fork 13.2k
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Add is_empty()
to Iterator
#90676
Add is_empty()
to Iterator
#90676
Conversation
r? @yaahc (rust-highfive has picked a reviewer for you, use r? to override) |
The job Click to see the possible cause of the failure (guessed by this bot)
|
#[inline] | ||
#[unstable(feaure = "iter_is_empty", reason = "recently added", issue = "0")] | ||
fn is_empty(&self) -> bool { | ||
(0, Some(0)) == self.size_hint() |
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.
There's no requirement that the size_hint
be this precise (unless it's ExactSizeIterator
or TrustedLen
), so I don't think this implementation is ok. For example, this won't work with from_fn
: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=0fce510cb4a02171b289d6d3bd0e8808
This would either need to be -> Option<bool>
(so it can return None
if the size_hint is inconclusive), or be on a different trait (as you mention).
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.
from_fn
obviously doesn't work, but I don't see why this is bad. This method is not always correct when it returns false
(return value of false
does not mean the iterator has items), but it should be correct when it returns true
.
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.
That's not what I'd expect it to do, at least. I'd expect it, since Rust has all the type system machinery it needs to do this, to only compile when it works -- same as .len()
isn't "well, here's what it might be".
Someone who wants unreliable checks can always just do .size_hint().0 > 0
or .size_hint().1 == Some(0)
, depending on which direction they want; I don't think convenience methods for that are appropriate.
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.
ESI is a safe trait, and to me len()
is also "here's what it might be" since we can't say not reporting accurate size is UB. is_empty
doesn't have to reside in another trait to me, but we could add a trait for users to require iterators to produce accurate is_empty
results, like FusedIterator
.
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.
ESI is a safe trait, and to me len() is also "here's what it might be" since we can't say not reporting accurate size is UB.
UB is not the only kind of forbidden behavior. Safe traits can also make promises where breaking these promises is a bug that can cascade into further downstream misbehavior such as infinite loops, panics, leaks and other API contracts being broken which easily can result in data loss or miscomputations. Sure, it's not a buffer overflow or double-free but that's little consolation when your blob storage containing petabytes of critical data suddenly become inaccessible, your account balance gets miscomputed or an airliner has an intersection event with a mountain.
So from the perspective of safe code ExactSizeIterator::len
is guaranteed to be correct and it is free to operate on that assumption for all T
. B is correct if A is correct.
is_empty
here does not meet this level of conditional correctness and would have to be weakened to the level of uselessness because it would have to explicitly mention something like
For some iterator types this function may always return
false
even when they are empty.
Which renders it useless as a trait method, because then people would have to reason about concrete types rather than the trait.
The size hint is not sufficient since returning |
This is a draft PR as an alternative to #35428.
The original feature was blocked because we felt that it shouldn't be specific to
ExactSizeIterator
, as some iterators can know whether they are empty or not but do not have an exact size e.g.Filter
.I didn't see any proposal looking exactly like this. @scottmcm created an experiment that separated it to its own trait, but the implementation seemed too restrictive to me, and adding another trait might not be worth it for a single method: functions using
Iterator
s should not require the iterator to know whether it is empty or not, it should already be able to tell using the size hint.cc @SimonSapin
EDIT: Let's discuss this change before me fixing errors. I could also just remove
ExactSizeIterator::is_empty()
in this PR.