diff --git a/crates/bevy_utils/macros/src/lib.rs b/crates/bevy_utils/macros/src/lib.rs index 5362f5c32020d..f46c869beb6a2 100644 --- a/crates/bevy_utils/macros/src/lib.rs +++ b/crates/bevy_utils/macros/src/lib.rs @@ -35,12 +35,79 @@ impl Parse for AllTuples { } } +/// Helper macro to generate tuple pyramids. Useful to generate scaffolding to work around Rust +/// lacking variadics. Invoking `all_tuples!(impl_foo, start, end, P, Q, ..)` +/// invokes `impl_foo` providing ident tuples through arity `start..=end`. +/// # Examples +/// A single parameter. +/// ``` +/// use std::marker::PhantomData; +/// use bevy_utils_proc_macros::all_tuples; +/// +/// struct Foo { +/// // .. +/// _phantom: PhantomData +/// } +/// +/// trait WrappedInFoo { +/// type Tup; +/// } +/// +/// macro_rules! impl_wrapped_in_foo { +/// ($($T:ident),*) => { +/// impl<$($T),*> WrappedInFoo for ($($T,)*) { +/// type Tup = ($(Foo<$T>,)*); +/// } +/// }; +/// } +/// +/// all_tuples!(impl_wrapped_in_foo, 0, 15, T); +/// // impl_wrapp_in_foo!(); +/// // impl_wrapp_in_foo!(P0); +/// // impl_wrapp_in_foo!(P0, P1); +/// // .. +/// // impl_wrapp_in_foo!(P0 .. P14); +/// ``` +/// Multiple parameters. +/// ``` +/// use bevy_utils_proc_macros::all_tuples; +/// +/// trait Append { +/// type Out; +/// fn append(tup: Self, item: Item) -> Self::Out; +/// } +/// +/// impl Append for () { +/// type Out = (Item,); +/// fn append(_: Self, item: Item) -> Self::Out { +/// (item,) +/// } +/// } +/// +/// macro_rules! impl_append { +/// ($(($P:ident, $p:ident)),*) => { +/// impl<$($P),*> Append for ($($P,)*) { +/// type Out = ($($P),*, Item); +/// fn append(($($p,)*): Self, item: Item) -> Self::Out { +/// ($($p),*, item) +/// } +/// } +/// } +/// } +/// +/// all_tuples!(impl_append, 1, 15, P, p); +/// // impl_append!((P0, p0)); +/// // impl_append!((P0, p0), (P1, p1)); +/// // impl_append!((P0, p0), (P1, p1), (P2, p2)); +/// // .. +/// // impl_append!((P0, p0) .. (P14, p14)); +/// ```` #[proc_macro] pub fn all_tuples(input: TokenStream) -> TokenStream { let input = parse_macro_input!(input as AllTuples); - let len = input.end - input.start; + let len = 1 + input.end - input.start; let mut ident_tuples = Vec::with_capacity(len); - for i in input.start..=input.end { + for i in 0..=len { let idents = input .idents .iter()