-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
iter::Zip is now invariant #35727
Comments
(also a regression from stable to beta) |
If this is a beta regression that means it is going to hit stable thursday. |
If somebody fixed and landed this right now and we started a stable build tonight we might be able to manage getting this into a Thursday release. |
... or we could just end up flubbing and missing our date. |
I don't think this is a serious enough regression to halt the release. @Stebalien this was just manufactured, right? There's no code that actually hit this? |
@brson. The fix is to either revert the zip specializations (simplest) or put the extra fields needed by specialization into the main @alexcrichton Not my code. |
Ah this is troublesome, indeed it's the associated types/struct field specialization that causes this, not just the regular "behavioral" specialization isn't it. I can't think of a workaround, we could back out the whole optimization, or just the associated type part? |
Discussed at @rust-lang/libs triage today, we concluded that we're likely to revert but we're not sure. @aturon wasn't present unfortunately and he'll likely also have opinions on this as well. We'll discuss again soon. Our other conclusion was that this wasn't super urgent because it's already hit stable. |
cc @nikomatsakis This is a pretty interesting tradeoff -- using specialization on representation destroys any variance. |
That is an interesting dilemma! I don't see an obvious solution though except maybe for explicit variance annotations on traits (that could then be checked by its implementors). i.e., you could say "all values of |
@nikomatsakis That pretty much echos my thoughts as well. |
@aturon there is a general desire for being able to prevent variance regressions (as expressed by e.g. @brson). I had thought about solving this in various ways (including as part of a more general semver checker), but this may tilt the balance in favor of adding some way to declare variance (even if it is optional). |
Decision at the libs team triage today was that we should revert the specialization of the structure of |
Sure. What do you mean by the Fuse strategy? Just no specialization of the data, only the methods? |
Ah yeah sorry I mean to just specialize the methods, not the struct representation (which we believe fixes this bug) |
…ition, r=alexcrichton Remove data structure specialization for .zip() iterator Go back on half the specialization, the part that changed the Zip struct's fields themselves depending on the types of the iterators. Previous PR: rust-lang#33090 This means that the Zip iterator will always carry two usize fields, which are sometimes unused. If a whole for loop using a .zip() iterator is inlined, these are simply removed and have no effect. The same improvement for Zip of for example slice iterators remain, and they still optimize well. However, like when the specialization of zip was merged, the compiler is still very sensistive to the exact context. For example this code only autovectorizes if the function is used, not if the code in zip_sum_i32 is inserted inline where it was called: ```rust fn zip_sum_i32(xs: &[i32], ys: &[i32]) -> i32 { let mut s = 0; for (&x, &y) in xs.iter().zip(ys) { s += x * y; } s } fn zipdot_i32_default_zip(b: &mut test::Bencher) { let xs = vec![1; 1024]; let ys = vec![1; 1024]; b.iter(|| { zip_sum_i32(&xs, &ys) }) } ``` Include a test that checks that `Zip<T, U>` is covariant w.r.t. T and U. Fixes rust-lang#35727
…excrichton Remove data structure specialization for .zip() iterator Go back on half the specialization, the part that changed the Zip struct's fields themselves depending on the types of the iterators. Previous PR: #33090 This means that the Zip iterator will always carry two usize fields, which are sometimes unused. If a whole for loop using a .zip() iterator is inlined, these are simply removed and have no effect. The same improvement for Zip of for example slice iterators remain, and they still optimize well. However, like when the specialization of zip was merged, the compiler is still very sensistive to the exact context. For example this code only autovectorizes if the function is used, not if the code in zip_sum_i32 is inserted inline where it was called: ```rust fn zip_sum_i32(xs: &[i32], ys: &[i32]) -> i32 { let mut s = 0; for (&x, &y) in xs.iter().zip(ys) { s += x * y; } s } fn zipdot_i32_default_zip(b: &mut test::Bencher) { let xs = vec![1; 1024]; let ys = vec![1; 1024]; b.iter(|| { zip_sum_i32(&xs, &ys) }) } ``` Include a test that checks that `Zip<T, U>` is covariant w.r.t. T and U. Fixes #35727
The following compiles on stable but not beta:
The text was updated successfully, but these errors were encountered: