99use std:: iter;
1010
1111use proc_macro2:: TokenStream ;
12- use quote:: quote;
12+ use quote:: { quote, ToTokens } ;
1313use syn:: {
1414 parse:: { Parse , ParseStream } ,
1515 parse_macro_input,
1616 punctuated:: Punctuated ,
17- token:: Plus ,
18- Error , FnArg , Generics , Ident , ItemTrait , Pat , PatType , Result , ReturnType , Signature , Token ,
19- TraitBound , TraitItem , TraitItemConst , TraitItemFn , TraitItemType , Type , TypeImplTrait ,
20- TypeParamBound ,
17+ token:: { Comma , Plus } ,
18+ Error , FnArg , GenericParam , Generics , Ident , ItemTrait , Lifetime , Pat , PatType , Result ,
19+ ReturnType , Signature , Token , TraitBound , TraitItem , TraitItemConst , TraitItemFn ,
20+ TraitItemType , Type , TypeImplTrait , TypeParamBound ,
2121} ;
2222
2323struct Attrs {
@@ -162,16 +162,58 @@ fn transform_item(item: &TraitItem, bounds: &Vec<TypeParamBound>) -> TraitItem {
162162
163163fn mk_blanket_impl ( attrs : & Attrs , tr : & ItemTrait ) -> TokenStream {
164164 let orig = & tr. ident ;
165+ let generics = & tr. generics . params ;
166+ let mut generic_names = tr
167+ . generics
168+ . params
169+ . iter ( )
170+ . map ( |generic| match generic {
171+ GenericParam :: Lifetime ( lt) => GenericParamName :: Lifetime ( & lt. lifetime ) ,
172+ GenericParam :: Type ( ty) => GenericParamName :: Type ( & ty. ident ) ,
173+ GenericParam :: Const ( co) => GenericParamName :: Const ( & co. ident ) ,
174+ } )
175+ . collect :: < Punctuated < _ , Comma > > ( ) ;
176+ let trailing_comma = if !generic_names. is_empty ( ) {
177+ generic_names. push_punct ( Comma :: default ( ) ) ;
178+ quote ! { , }
179+ } else {
180+ quote ! { }
181+ } ;
165182 let variant = & attrs. variant . name ;
166- let items = tr. items . iter ( ) . map ( |item| blanket_impl_item ( item, variant) ) ;
183+ let items = tr
184+ . items
185+ . iter ( )
186+ . map ( |item| blanket_impl_item ( item, variant, & generic_names) ) ;
167187 quote ! {
168- impl <T > #orig for T where T : #variant {
188+ impl <#generics #trailing_comma T > #orig<#generic_names> for T
189+ where T : #variant<#generic_names>
190+ {
169191 #( #items) *
170192 }
171193 }
172194}
173195
174- fn blanket_impl_item ( item : & TraitItem , variant : & Ident ) -> TokenStream {
196+ enum GenericParamName < ' s > {
197+ Lifetime ( & ' s Lifetime ) ,
198+ Type ( & ' s Ident ) ,
199+ Const ( & ' s Ident ) ,
200+ }
201+
202+ impl ToTokens for GenericParamName < ' _ > {
203+ fn to_tokens ( & self , tokens : & mut TokenStream ) {
204+ match self {
205+ GenericParamName :: Lifetime ( lt) => lt. to_tokens ( tokens) ,
206+ GenericParamName :: Type ( ty) => ty. to_tokens ( tokens) ,
207+ GenericParamName :: Const ( co) => co. to_tokens ( tokens) ,
208+ }
209+ }
210+ }
211+
212+ fn blanket_impl_item (
213+ item : & TraitItem ,
214+ variant : & Ident ,
215+ generic_names : & Punctuated < GenericParamName < ' _ > , Comma > ,
216+ ) -> TokenStream {
175217 // impl<T> IntFactory for T where T: SendIntFactory {
176218 // const NAME: &'static str = <Self as SendIntFactory>::NAME;
177219 // type MyFut<'a> = <Self as SendIntFactory>::MyFut<'a> where Self: 'a;
@@ -187,7 +229,7 @@ fn blanket_impl_item(item: &TraitItem, variant: &Ident) -> TokenStream {
187229 ..
188230 } ) => {
189231 quote ! {
190- const #ident #generics: #ty = <Self as #variant>:: #ident;
232+ const #ident #generics: #ty = <Self as #variant<#generic_names> >:: #ident;
191233 }
192234 }
193235 TraitItem :: Fn ( TraitItemFn { sig, .. } ) => {
@@ -207,7 +249,7 @@ fn blanket_impl_item(item: &TraitItem, variant: &Ident) -> TokenStream {
207249 } ;
208250 quote ! {
209251 #sig {
210- <Self as #variant>:: #ident( #( #args) , * ) #maybe_await
252+ <Self as #variant<#generic_names> >:: #ident( #( #args) , * ) #maybe_await
211253 }
212254 }
213255 }
@@ -222,7 +264,7 @@ fn blanket_impl_item(item: &TraitItem, variant: &Ident) -> TokenStream {
222264 ..
223265 } ) => {
224266 quote ! {
225- type #ident<#params> = <Self as #variant>:: #ident<#params> #where_clause;
267+ type #ident<#params> = <Self as #variant<#generic_names> >:: #ident<#params> #where_clause;
226268 }
227269 }
228270 _ => Error :: new_spanned ( item, "unsupported item type" ) . into_compile_error ( ) ,
0 commit comments