9
9
use std:: iter;
10
10
11
11
use proc_macro2:: TokenStream ;
12
- use quote:: { quote, ToTokens } ;
12
+ use quote:: quote;
13
13
use syn:: {
14
14
parse:: { Parse , ParseStream } ,
15
- parse_macro_input,
15
+ parse_macro_input, parse_quote ,
16
16
punctuated:: Punctuated ,
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 ,
17
+ token:: Plus ,
18
+ Error , FnArg , GenericParam , Ident , ItemTrait , Pat , PatType , Result , ReturnType , Signature ,
19
+ Token , TraitBound , TraitItem , TraitItemConst , TraitItemFn , TraitItemType , Type , TypeGenerics ,
20
+ TypeImplTrait , TypeParam , TypeParamBound ,
21
21
} ;
22
22
23
23
struct Attrs {
@@ -162,59 +162,32 @@ fn transform_item(item: &TraitItem, bounds: &Vec<TypeParamBound>) -> TraitItem {
162
162
163
163
fn mk_blanket_impl ( attrs : & Attrs , tr : & ItemTrait ) -> TokenStream {
164
164
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
- } ;
182
165
let variant = & attrs. variant . name ;
166
+ let ( _impl, orig_ty_generics, _where) = & tr. generics . split_for_impl ( ) ;
183
167
let items = tr
184
168
. items
185
169
. iter ( )
186
- . map ( |item| blanket_impl_item ( item, variant, & generic_names) ) ;
187
- let where_clauses = tr. generics . where_clause . as_ref ( ) . map ( |wh| & wh. predicates ) ;
170
+ . map ( |item| blanket_impl_item ( item, variant, orig_ty_generics) ) ;
171
+ let blanket_bound: TypeParam =
172
+ parse_quote ! ( TraitVariantBlanketType : #variant #orig_ty_generics) ;
173
+ let blanket = & blanket_bound. ident . clone ( ) ;
174
+ let mut blanket_generics = tr. generics . clone ( ) ;
175
+ blanket_generics
176
+ . params
177
+ . push ( GenericParam :: Type ( blanket_bound) ) ;
178
+ let ( blanket_impl_generics, _ty, blanket_where_clause) = & blanket_generics. split_for_impl ( ) ;
188
179
quote ! {
189
- impl <#generics #trailing_comma TraitVariantBlanketType > #orig<#generic_names>
190
- for TraitVariantBlanketType
191
- where TraitVariantBlanketType : #variant<#generic_names>, #where_clauses
180
+ impl #blanket_impl_generics #orig #orig_ty_generics for #blanket #blanket_where_clause
192
181
{
193
182
#( #items) *
194
183
}
195
184
}
196
185
}
197
186
198
- enum GenericParamName < ' s > {
199
- Lifetime ( & ' s Lifetime ) ,
200
- Type ( & ' s Ident ) ,
201
- Const ( & ' s Ident ) ,
202
- }
203
-
204
- impl ToTokens for GenericParamName < ' _ > {
205
- fn to_tokens ( & self , tokens : & mut TokenStream ) {
206
- match self {
207
- GenericParamName :: Lifetime ( lt) => lt. to_tokens ( tokens) ,
208
- GenericParamName :: Type ( ty) => ty. to_tokens ( tokens) ,
209
- GenericParamName :: Const ( co) => co. to_tokens ( tokens) ,
210
- }
211
- }
212
- }
213
-
214
187
fn blanket_impl_item (
215
188
item : & TraitItem ,
216
189
variant : & Ident ,
217
- generic_names : & Punctuated < GenericParamName < ' _ > , Comma > ,
190
+ trait_ty_generics : & TypeGenerics < ' _ > ,
218
191
) -> TokenStream {
219
192
// impl<T> IntFactory for T where T: SendIntFactory {
220
193
// const NAME: &'static str = <Self as SendIntFactory>::NAME;
@@ -231,7 +204,7 @@ fn blanket_impl_item(
231
204
..
232
205
} ) => {
233
206
quote ! {
234
- const #ident #generics: #ty = <Self as #variant<#generic_names> >:: #ident;
207
+ const #ident #generics: #ty = <Self as #variant #trait_ty_generics >:: #ident;
235
208
}
236
209
}
237
210
TraitItem :: Fn ( TraitItemFn { sig, .. } ) => {
@@ -251,22 +224,16 @@ fn blanket_impl_item(
251
224
} ;
252
225
quote ! {
253
226
#sig {
254
- <Self as #variant<#generic_names> >:: #ident( #( #args) , * ) #maybe_await
227
+ <Self as #variant #trait_ty_generics >:: #ident( #( #args) , * ) #maybe_await
255
228
}
256
229
}
257
230
}
258
231
TraitItem :: Type ( TraitItemType {
259
- ident,
260
- generics :
261
- Generics {
262
- params,
263
- where_clause,
264
- ..
265
- } ,
266
- ..
232
+ ident, generics, ..
267
233
} ) => {
234
+ let ( impl_generics, ty_generics, where_clause) = generics. split_for_impl ( ) ;
268
235
quote ! {
269
- type #ident<#params> = <Self as #variant<#generic_names>> :: #ident<#params> #where_clause;
236
+ type #ident #impl_generics = <Self as #variant #trait_ty_generics> :: #ident #ty_generics #where_clause;
270
237
}
271
238
}
272
239
_ => Error :: new_spanned ( item, "unsupported item type" ) . into_compile_error ( ) ,
0 commit comments