-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
Add ExactSizeIterator
impl for iter::Chain
#66531
Add ExactSizeIterator
impl for iter::Chain
#66531
Conversation
bb0e383
to
1b548ae
Compare
This feels quite reasonable; cc also @scottmcm |
This affects far more than just what's mentioned here. There are a bunch of implementations that rely on DEI+ESI to be able to correctly propagate DEI (because of things like Also, this PR doesn't maintain the requirement from the ESI docs that
So I'm skeptical. It sounds like the actual proposed change here is essentially to change ESI's requirements to those of TrustedLen, just without the I feel like there's a big difference between methods that can panic because they need to iterate (because anything can be |
Good point, I missed that. In the issue I linked
I did not knowingly propose that. But yes, it seems like with the current definitions of the traits, it's indeed impossible to add this impl. But that would be a shame! I think this impl for I don't know if/how much we could change
But that's technically not a backwards-compatible change as we relax some conditions. So what code would this break? I think the change that Regarding "correct So I think the only real breakage is in code that uses |
I’m sorry, I don’t have bandwidth at the moment look into and make a judgment about the consequences of this proposal. Reassigning to someone else in T-libs at random: r? @sfackler |
r? @KodrAus |
1b548ae
to
722bba0
Compare
☔ The latest upstream changes (presumably #67596) made this pull request unmergeable. Please resolve the merge conflicts. |
/// An overflow in those methods leads to a wrong result or a panic. If | ||
/// debug assertions are enabled, a panic is guaranteed. |
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.
Is it possible that we could guarantee a panic whether or not debug assertions are enabled? Reserving the right to give a wrong result doesn't seem helpful here.
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.
Reserving this right is "helpful" in the sense that it means we don't have any performance overhead from overflow checks in release builds.
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.
It seems wrong that len()
could return something smaller than size_hint().0
on an iterator that implements TrustedLen. What sort of overhead are we talking about in practice?
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.
I was referring to all methods listed in that doc comment, not just len
. Iterator::count
currently does not check for overflow in release builds because it simply adds 1 repeatedly. In the case of len
, I agree that it should probably panic rather than return an incorrect value, if we were to land this change.
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.
len
guarantees a panic on overflow. I changed this in response to this comment.
This sentence here is a bit vague, yes. It's still technically correct for len
, but maybe I should add something like "ExactIterator::len
even guarantees a panic in release mode"? On the other hand, this behavior is already documented on that method (see above).
As for the other methods: I don't think it's in the scope of this PR to change them. And currently they only have debug checks.
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.
Sounds good. In that case I am on board with this change. Want to propose FCP?
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.
@dtolnay I'm not quite sure if you want me to add another sentence to this part of the documentation or not. (Will rebase either way soon.)
Regarding FCP: the main concern is this one. I replied to that comment, but no one else did, so I don't think it has been resolved yet. But maybe FCP is a way to get the others to look at this?
I think I like this change, but I think it would be better to change Infinite iterators are kind of an edge case anyway, I think panicking or returning weird results is acceptable. This shouldn't cause libraries that didn't have UB to suddenly have UB because the trait was safe, so libraries that did depend on that trait to be correct were incorrect to begin with. |
|
If you take the iterator: (0..usize::max_value()).chain(0..10).skip(usize::max_value()) It returns exactly 10 items and has a |
Any updates @LukasKalbertodt |
Yes, this particular iterator is an edge case because calling its It would be more practical to make this change if |
Thinking about it again, I might agree that this change is too tricky to land. The conditions for when Also, I got another idea how one could easily work around limitations like this (i.e. |
Closing now, as explained in the previous comment. |
I wonder if we can come back to this in the next edition. For example, by no longer implementing |
Editions don't allow for different trait implementations, there is only one "core Rust", see https://rust-lang.github.io/rfcs/2052-epochs.html. |
My gut reaction is that It's possible though to let people opt in to this strict behaviour, if we provide an additional method (for instance,
@xfix, which iterator is this about? |
In the issue about this impl (#34433), people concluded that it was impossible to add due to
usize
overflowing: if we create an iterator withChain
that contains more thanusize::MAX
items, thenExactSizeIterator::len
would not be able to return the correct value. This is true, but I don't think that's a reason not to add the impl:usize::MAX
elements without usingChain
.Range<u128>
,iter::repeat
,flat_map
, just to name a few.usize
that state they would panic on overflow:Iterator::count
,Iterator::enumerate
,Iterator::position
.So the "long iterator
usize
overflow" problem is already a thing and more importantly: it is already well documented how affected methods behave. So I don't think it's a problem to add this impl if it is properly documented (which hopefully this PR does). After that issue was closed, two people mentioned how useful that impl would be and that a panic in the overflow case would be certainly fine. I agree with that.r? @SimonSapin
CC @oli-obk @RalfJung @bluss (some people involved in the original issue)