From 2c5b50f1def1968517de8cbede3b9c0eee35d4ed Mon Sep 17 00:00:00 2001
From: Zhixing Zhang <me@neoto.xin>
Date: Sun, 25 May 2025 03:20:47 -0700
Subject: [PATCH 1/2] Support lifetime params

---
 src/lib.rs | 81 ++++++++++++++++++++++++++++++++++++++++--------------
 1 file changed, 61 insertions(+), 20 deletions(-)

diff --git a/src/lib.rs b/src/lib.rs
index 471601b..1cab237 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -6,20 +6,43 @@
 
 use proc_macro::TokenStream;
 use proc_macro2::{Literal, Span as Span2, TokenStream as TokenStream2};
-use quote::{format_ident, quote};
+use quote::{format_ident, quote, ToTokens};
 use syn::{
     parse::{Parse, ParseStream},
     parse_macro_input,
     spanned::Spanned as _,
     token::Comma,
-    Attribute, Error, Ident, LitInt, LitStr, Result,
+    Attribute, Error, Ident, Lifetime, LitInt, LitStr, Result,
 };
 struct AllTuples {
     fake_variadic: bool,
     macro_ident: Ident,
     start: usize,
     end: usize,
-    idents: Vec<Ident>,
+    idents: Vec<AllTuplesParam>,
+}
+
+#[derive(Clone)]
+enum AllTuplesParam {
+    Ident(Ident),
+    Lifetime(Lifetime),
+}
+impl Parse for AllTuplesParam {
+    fn parse(input: ParseStream) -> Result<Self> {
+        if let Ok(lifetime) = input.parse::<Lifetime>() {
+            return Ok(Self::Lifetime(lifetime));
+        } else {
+            return Ok(Self::Ident(input.parse()?));
+        }
+    }
+}
+impl ToTokens for AllTuplesParam {
+    fn to_tokens(&self, tokens: &mut TokenStream2) {
+        match self {
+            AllTuplesParam::Ident(ident) => ident.to_tokens(tokens),
+            AllTuplesParam::Lifetime(lifetime) => lifetime.to_tokens(tokens),
+        }
+    }
 }
 
 impl Parse for AllTuples {
@@ -31,9 +54,9 @@ impl Parse for AllTuples {
         input.parse::<Comma>()?;
         let end = input.parse::<LitInt>()?.base10_parse()?;
         input.parse::<Comma>()?;
-        let mut idents = vec![input.parse::<Ident>()?];
+        let mut idents = vec![input.parse::<AllTuplesParam>()?];
         while input.parse::<Comma>().is_ok() {
-            idents.push(input.parse::<Ident>()?);
+            idents.push(input.parse::<AllTuplesParam>()?);
         }
 
         if start > 1 && fake_variadic {
@@ -167,10 +190,15 @@ pub fn all_tuples(input: TokenStream) -> TokenStream {
     let len = 1 + input.end - input.start;
     let ident_tuples = (0..=len)
         .map(|i| {
-            let idents = input
-                .idents
-                .iter()
-                .map(|ident| format_ident!("{}{}", ident, i));
+            let idents = input.idents.iter().map(|ident| match ident {
+                AllTuplesParam::Ident(ident) => {
+                    AllTuplesParam::Ident(format_ident!("{}{}", ident, i))
+                }
+                AllTuplesParam::Lifetime(lifetime) => AllTuplesParam::Lifetime(Lifetime {
+                    apostrophe: lifetime.apostrophe,
+                    ident: format_ident!("{}{}", lifetime.ident, i),
+                }),
+            });
             to_ident_tuple(idents, input.idents.len())
         })
         .collect::<Vec<_>>();
@@ -242,11 +270,16 @@ pub fn all_tuples_enumerated(input: TokenStream) -> TokenStream {
     let len = 1 + input.end - input.start;
     let ident_tuples = (0..=len)
         .map(|i| {
-            let idents = input
-                .idents
-                .iter()
-                .map(|ident| format_ident!("{}{}", ident, i));
-            to_ident_tuple_enumerated(idents, input.idents.len())
+            let idents = input.idents.iter().map(|ident| match ident {
+                AllTuplesParam::Ident(ident) => {
+                    AllTuplesParam::Ident(format_ident!("{}{}", ident, i))
+                }
+                AllTuplesParam::Lifetime(lifetime) => AllTuplesParam::Lifetime(Lifetime {
+                    apostrophe: lifetime.apostrophe,
+                    ident: format_ident!("{}{}", lifetime.ident, i),
+                }),
+            });
+            to_ident_tuple_enumerated(idents, i)
         })
         .collect::<Vec<_>>();
     let macro_ident = &input.macro_ident;
@@ -384,10 +417,15 @@ pub fn all_tuples_with_size(input: TokenStream) -> TokenStream {
     let len = 1 + input.end - input.start;
     let ident_tuples = (0..=len)
         .map(|i| {
-            let idents = input
-                .idents
-                .iter()
-                .map(|ident| format_ident!("{}{}", ident, i));
+            let idents = input.idents.iter().map(|ident| match ident {
+                AllTuplesParam::Ident(ident) => {
+                    AllTuplesParam::Ident(format_ident!("{}{}", ident, i))
+                }
+                AllTuplesParam::Lifetime(lifetime) => AllTuplesParam::Lifetime(Lifetime {
+                    apostrophe: lifetime.apostrophe,
+                    ident: format_ident!("{}{}", lifetime.ident, i),
+                }),
+            });
             to_ident_tuple(idents, input.idents.len())
         })
         .collect::<Vec<_>>();
@@ -464,7 +502,7 @@ fn choose_ident_tuples_enumerated(
     }
 }
 
-fn to_ident_tuple(idents: impl Iterator<Item = Ident>, len: usize) -> TokenStream2 {
+fn to_ident_tuple(idents: impl Iterator<Item = AllTuplesParam>, len: usize) -> TokenStream2 {
     if len < 2 {
         quote! { #(#idents)* }
     } else {
@@ -473,7 +511,10 @@ fn to_ident_tuple(idents: impl Iterator<Item = Ident>, len: usize) -> TokenStrea
 }
 
 /// Like `to_ident_tuple`, but it enumerates the identifiers
-fn to_ident_tuple_enumerated(idents: impl Iterator<Item = Ident>, idx: usize) -> TokenStream2 {
+fn to_ident_tuple_enumerated(
+    idents: impl Iterator<Item = AllTuplesParam>,
+    idx: usize,
+) -> TokenStream2 {
     let idx = Literal::usize_unsuffixed(idx);
     quote! { (#idx, #(#idents),*) }
 }

From a8ad82a77bee227fea7cf3b3e70623452bae7eae Mon Sep 17 00:00:00 2001
From: Zhixing Zhang <me@neoto.xin>
Date: Sun, 25 May 2025 10:08:01 -0700
Subject: [PATCH 2/2] clippy

---
 src/lib.rs | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/lib.rs b/src/lib.rs
index 1cab237..aa33654 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -30,9 +30,9 @@ enum AllTuplesParam {
 impl Parse for AllTuplesParam {
     fn parse(input: ParseStream) -> Result<Self> {
         if let Ok(lifetime) = input.parse::<Lifetime>() {
-            return Ok(Self::Lifetime(lifetime));
+            Ok(Self::Lifetime(lifetime))
         } else {
-            return Ok(Self::Ident(input.parse()?));
+            Ok(Self::Ident(input.parse()?))
         }
     }
 }