bevy
bevy copied to clipboard
Create enumerating version of `all_tuples`
Objective
When writing macros that blanket-implement traits over tuples, it is often necessary to index into anonymous tuple struct fields. This turns out to be somewhat annoying, since it requires the indices to be passed sequentially in the macro invocation, which prevents the macro from being used with all_tuples.
The goal here is to provide support for this pattern by introducing an enumerating version of all_tuples that can be used in these circumstances.
Solution
Create all_tuples_enumerated, a procedural macro which behaves much like all_tuples but enumerates its output. Here is an example from the docs:
trait Squawk {
fn squawk(&self);
}
// If every type in a tuple is `Squawk`, the tuple can squawk by having its
// constituents squawk sequentially:
macro_rules! impl_squawk {
($(($n:tt, $T:ident)),*) => {
impl<$($T: Squawk),*> Squawk for ($($T,)*) {
fn squawk(&self) {
$(
self.$n.squawk();
)*
}
}
};
}
all_tuples_enumerated!(impl_squawk, 1, 15, T);
// impl_squawk!((0, T0));
// impl_squawk!((0, T0), (1, T1));
// ..
// impl_squawk!((0, T0) .. (14, T14));
The implementation for StableInterpolate over tuples has been changed to use this pattern instead of doing manual enumeration. It also actually uses fake_variadic now.
Testing
Tested via macro expansion and compiling.
FYI I'm merging the simple fix in #15933 now, but I do think we should move fully to this. It does make me think we should pull all_tuples out into its own crate though: I'm not a fan of bevy_math relying on bevy_utils.
I can try my hand at that again using this once this is merged and I'm feeling better.
https://github.com/bevyengine/variadics_please has been created, please open a PR in that repo for the implementation.