-
Notifications
You must be signed in to change notification settings - Fork 13.2k
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
Adjustments to Extend<(T, …)> for (ExtendT, …)
implementations
#137400
base: master
Are you sure you want to change the base?
Conversation
…ault function for readability
hm, can this come with a test for the new behavior in terms of ordering? |
It sure can! I’m not sure what’s the best location for the test. |
ordering of side-effects to `coretest`.
5ad489e
to
9341954
Compare
I've spent half an hour staring at the code and my frustration has increased to the point where I want to just rip this whole mess out1. So even though this is a good improvement and all of these changes are completely sensible, I won't merge this PR. I really don't think maintaining the status quo – a completely unmaintainable macro hack – is a good idea. So, how do you feel about the following:
Footnotes
|
This is an alternative to rust-lang#137400. The current macro is incredibly complicated and introduces subtle bugs like calling the `extend_one` of the individual collections in backwards order. This PR drastically simplifies the macro by removing recursion and moving the specialization out of the macro. It also fixes the ordering issue described above (I've stolen the test of the new behaviour from rust-lang#137400). Additionally, the 1-tuple is now special-cased to allow taking advantage of the well-optimized `Extend` implementations of the individual collection.
I've opened #138799 as an alternative. |
This is an alternative to rust-lang#137400. The current macro is incredibly complicated and introduces subtle bugs like calling the `extend_one` of the individual collections in backwards order. This PR drastically simplifies the macro by removing recursion and moving the specialization out of the macro. It also fixes the ordering issue described above (I've stolen the test of the new behaviour from rust-lang#137400). Additionally, the 1-tuple is now special-cased to allow taking advantage of the well-optimized `Extend` implementations of the individual collection.
This PR is still containing too many intermediate commits, but I thought keeping them makes it easier to review for now.
I can certainly squash everything – I can also try to rebase into a cleaner multiple-commits result (which might especially be useful to keep e.g. the renaming steps separate, and so on).
Before putting in such works, I’d like to first hear feedback that this change is generally desired/reasonable; and also I’m waiting for feedback on whether or squashing everything to a simple single commit is alright, too.
I know that reviewing the macro madness here in-depth will be hard, so here’s a short explanation of what changed:
minor:
ty_name
/trait_name
/TraitA
style made the code hard to readA
andEA
in the docs felt weird; this is switching toT
andExtendT
, inspired on one hand by the(A, B)
(ExtendA, ExtendB)
naming before the generalization, and theT_n
-style names for otherfake_variadic
sfn extend
is callediter
now, following the parameter naming of the method in the trait itself#[allow(non_snake_case)]
are instead changed from a style ofextend_one_unchecked
-using variant)relevant behavior changes
the generalized implementation had changed the behavior of e.g.
iter::unzip
and the impls for(A, B)
pairsthis is perhaps most visible by just macro-expanding a section of the current
master
macro expansionnote how
self.1
comes beforeself.0
Here’s a test case showing this change between 1.84 and 1.85
(compiler explorer)
1.84
1.85
I’m not sure if this is much of an actual issue, because it might not break any guaranteed behavior/properties of the relevant traits and types. So I’m not sure if this deserves to become a test-case in the library and/or ui test suite…
But it still seems an unnecessary change, and the less natural order of side-effects.
This PR fixes that, and returns to the 1.84 behavior.
The change happened in the first place, because it’s harder to generate macro invocations of the form
than of the form
This PR restructures the macro to a partially tt-munching style that manages to un-reverse the list partial macro inputs. I.e. instead of invocations on trailing sublists of a reversed
(… D C B A)
-style macro input, it instead now generates invocations on leading sublists of a non-reversed(A B C D …)
input.the new implementations for
(T,)
used a loop ofextend_one
unnecessarilyI would assume that a simple approach of
is more performant, as it can make use of the normal
SpecExtend
specialization chain, incorporating e.g. preservation of capacity inVec
, and such things.But I haven’t tested (yet) if this has any performance downsides.
Not to say that
(T,)
is a particularly common use-case; it isn’t; though I do suppose there could be future users anyway that end up using thisExtend
impl by virtue of being macro-users or users of code-generators themselves.