-
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
TrustedRandomAccess optimization for Zip containing vec::IntoIter is unsound with how specialization currently behaves around HRTB fn pointers #85873
Comments
Assigning priority as discussed in the Zulip thread of the Prioritization Working Group, issue will be discussed during T-compiler meeting |
|
Would removing the specialization from Zip be a solution or is its existence on IntoIter itself also an issue? There has been some discussion around introducing a new |
AFAIK (correct me if I’m wrong), |
It's at least used here rust/library/alloc/src/vec/source_iter_marker.rs Lines 123 to 144 in 835150e
and I also intend to use it in other places e.g. #83770 although that particular one had to be reverted since performance initially looked good but turned out mixed later. |
oh… right, I might have only grepped for |
Great. So this second use case ignores the documentation of |
And while we’re at it, |
Ah, I see you’re personally involved whith the ( The |
I'm not even sure if enumerating which methods are safe to call and in which order is enough, the constraints are more subtle than that as we discussed in #85888 (comment)
Great points. I'm not sure if those are actually safe. Calculating len usually itself uses
It's good to have an extra pair of eyeballs, thank you! This stuff is difficult and I have obviously missed several things.
Yeah, but removing TrustedRandomAccess renders it unused since it always has to come from a In my opinion the real source of grief is So we can definitely add more test cases, try to fix what is broken or rip out the optimizations that I introduced erroneously but I'd like to explore #85342 as an alternative and also get the libs team's opinion on that. It does seem easier to reason about optimizations there. We might even be able to leave |
It’s all a question of what the documentation of |
Haha, regarding those, in my mind I’m already picturing ways to fix the remaining issues around that point (e.g. #82303) by extending |
By the way, regarding side-effects, here’s a thing I just came up with: Actually, that’s not even on stable yet, so kind-of a beta regression? |
Well, I am curious about what you cook up. TRA was originally intended to allow Theoretically we could have separate Tangentially, tried adding a fixup method that could be used to bring an iterator back into a clean state after
I would call it a new way to trigger #82303 caused by #83990 Note that I lean heavily in favor of allowing the elimination of iterator side-effects one way or another where possible as long as it still produces the same final result. But yeah, I can understand if someone wants to treat this as a regression. |
Maybe a reasonable approach is, especially if #85874 happens to get merged, to have two traits, one version of |
Something like |
That wouldn't actually help since this trait needs to be propagated through iterator adapters. If we have an instance of So we would have to put an additional marker on each adapter. The marker traits seem to be proliferating. I was also thinking about separating out the |
Good points. Maybe everything can become Edit: Well, these would need to be considered and explicitly written for every adapter, too. And I just noticed that An unstable + hidden |
Right, either passing capabilities through or setting a flag unconditionally would be easy enough, but evaluating more complex conditions based on type bounds would be tricky. It could probably be done with specialization and const functions but could get verbose quickly, thus negating most conciseness wins. Having all capabilities in a single trait might still be useful in so far that the final consumers of that trait, i.e. the specializations, would only have to specialize on So we probably have to stick to separate marker traits for the time being. Maybe they can be consolidated in the future when const generics and specialization become more powerful. |
removing T-compiler as this seems more in T-libs ballpack (Zulip thread) @rustbot label -T-compiler |
Related to #85863, which now includes a high-level description covering both #85863 and #85873. [This issue is not a duplicate because both issues can be fixed independently in different ways.]
(playground)
@rustbot label T-libs-impl, T-compiler, A-specialization, A-iterators, A-typesystem, A-lifetimes, A-traits, regression-from-stable-to-stable
someone please add the unsound labelthanksExplanation
Zip
uses an optimization if both contained iterators implementTrustedRandomAccess
. There’s an implfor both
vec::IntoIter
andvec_deque::IntoIter
that depend onCopy
. This way, unsound specialization is possible. This can be turned into actual ill-behaved programs at runtime similar as in #85863, relying on covariance ofIntoIter
andZip
. This way, theZipImpl
implementation is switched out and this way theZip
iterator gets into an illegal state resulting in violation of the contract ofTrustedRandomAccess
by calling.next()
on theIterMut
iterator after the first item was already read via__iterator_get_unchecked
. The best immediate fix is probably to remove those twoTrustedRandomAccess
implementations forIntoIter
; they’re an optimization only, anyway. This distinguishes this issue clearly from #85863 because for theFusedIterator
trait, the specialization is quite directly part of the API, whereas this issue is only about a soundness regression from a performance optimization that can easily be reverted.The text was updated successfully, but these errors were encountered: