8
8
9
9
use std:: iter;
10
10
11
- use proc_macro2:: TokenStream ;
11
+ use proc_macro2:: { Span , TokenStream } ;
12
12
use quote:: { quote, ToTokens } ;
13
13
use syn:: {
14
14
parse:: { Parse , ParseStream } ,
15
- parse_macro_input,
15
+ parse_macro_input, parse_quote ,
16
16
punctuated:: Punctuated ,
17
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 ,
18
+ Error , FnArg , GenericParam , Generics , Ident , ItemTrait , Lifetime , Pat , PatType , Receiver ,
19
+ Result , ReturnType , Signature , Token , TraitBound , TraitItem , TraitItemConst , TraitItemFn ,
20
+ TraitItemType , Type , TypeImplTrait , TypeParamBound , TypeReference , WhereClause ,
21
21
} ;
22
22
23
23
struct Attrs {
@@ -119,10 +119,10 @@ fn transform_item(item: &TraitItem, bounds: &Vec<TypeParamBound>) -> TraitItem {
119
119
// fn stream(&self) -> impl Iterator<Item = i32> + Send;
120
120
// fn call(&self) -> u32;
121
121
// }
122
- let TraitItem :: Fn ( fn_item @ TraitItemFn { sig, .. } ) = item else {
122
+ let TraitItem :: Fn ( fn_item @ TraitItemFn { sig, default , .. } ) = item else {
123
123
return item. clone ( ) ;
124
124
} ;
125
- let ( arrow , output ) = if sig. asyncness . is_some ( ) {
125
+ let ( sig , default ) = if sig. asyncness . is_some ( ) {
126
126
let orig = match & sig. output {
127
127
ReturnType :: Default => quote ! { ( ) } ,
128
128
ReturnType :: Type ( _, ty) => quote ! { #ty } ,
@@ -134,7 +134,22 @@ fn transform_item(item: &TraitItem, bounds: &Vec<TypeParamBound>) -> TraitItem {
134
134
. chain ( bounds. iter ( ) . cloned ( ) )
135
135
. collect ( ) ,
136
136
} ) ;
137
- ( syn:: parse2 ( quote ! { -> } ) . unwrap ( ) , ty)
137
+ let mut sig = sig. clone ( ) ;
138
+ if default. is_some ( ) {
139
+ add_receiver_bounds ( & mut sig) ;
140
+ }
141
+
142
+ (
143
+ Signature {
144
+ asyncness : None ,
145
+ output : ReturnType :: Type ( syn:: parse2 ( quote ! { -> } ) . unwrap ( ) , Box :: new ( ty) ) ,
146
+ ..sig. clone ( )
147
+ } ,
148
+ fn_item
149
+ . default
150
+ . as_ref ( )
151
+ . map ( |b| syn:: parse2 ( quote ! { { async move #b } } ) . unwrap ( ) ) ,
152
+ )
138
153
} else {
139
154
match & sig. output {
140
155
ReturnType :: Type ( arrow, ty) => match & * * ty {
@@ -143,19 +158,22 @@ fn transform_item(item: &TraitItem, bounds: &Vec<TypeParamBound>) -> TraitItem {
143
158
impl_token : it. impl_token ,
144
159
bounds : it. bounds . iter ( ) . chain ( bounds) . cloned ( ) . collect ( ) ,
145
160
} ) ;
146
- ( * arrow, ty)
161
+ (
162
+ Signature {
163
+ output : ReturnType :: Type ( * arrow, Box :: new ( ty) ) ,
164
+ ..sig. clone ( )
165
+ } ,
166
+ fn_item. default . clone ( ) ,
167
+ )
147
168
}
148
169
_ => return item. clone ( ) ,
149
170
} ,
150
171
ReturnType :: Default => return item. clone ( ) ,
151
172
}
152
173
} ;
153
174
TraitItem :: Fn ( TraitItemFn {
154
- sig : Signature {
155
- asyncness : None ,
156
- output : ReturnType :: Type ( arrow, Box :: new ( output) ) ,
157
- ..sig. clone ( )
158
- } ,
175
+ sig,
176
+ default,
159
177
..fn_item. clone ( )
160
178
} )
161
179
}
@@ -184,7 +202,26 @@ fn mk_blanket_impl(attrs: &Attrs, tr: &ItemTrait) -> TokenStream {
184
202
. items
185
203
. iter ( )
186
204
. map ( |item| blanket_impl_item ( item, variant, & generic_names) ) ;
187
- let where_clauses = tr. generics . where_clause . as_ref ( ) . map ( |wh| & wh. predicates ) ;
205
+ let mut where_clauses = tr
206
+ . generics
207
+ . where_clause
208
+ . as_ref ( )
209
+ . map ( |wh| wh. predicates . clone ( ) )
210
+ . unwrap_or_default ( ) ;
211
+ let self_is_sync = tr. items . iter ( ) . any ( |item| {
212
+ matches ! (
213
+ item,
214
+ TraitItem :: Fn ( TraitItemFn {
215
+ default : Some ( _) ,
216
+ ..
217
+ } )
218
+ )
219
+ } ) ;
220
+
221
+ if self_is_sync {
222
+ where_clauses. push ( parse_quote ! { for <' s> & ' s Self : Send } ) ;
223
+ }
224
+
188
225
quote ! {
189
226
impl <#generics #trailing_comma TraitVariantBlanketType > #orig<#generic_names>
190
227
for TraitVariantBlanketType
@@ -249,6 +286,7 @@ fn blanket_impl_item(
249
286
} else {
250
287
quote ! { }
251
288
} ;
289
+
252
290
quote ! {
253
291
#sig {
254
292
<Self as #variant<#generic_names>>:: #ident( #( #args) , * ) #maybe_await
@@ -272,3 +310,47 @@ fn blanket_impl_item(
272
310
_ => Error :: new_spanned ( item, "unsupported item type" ) . into_compile_error ( ) ,
273
311
}
274
312
}
313
+
314
+ fn add_receiver_bounds ( sig : & mut Signature ) {
315
+ let Some ( FnArg :: Receiver ( Receiver { ty, reference, .. } ) ) = sig. inputs . first_mut ( ) else {
316
+ return ;
317
+ } ;
318
+ let Type :: Reference (
319
+ recv_ty @ TypeReference {
320
+ mutability : None , ..
321
+ } ,
322
+ ) = & mut * * ty
323
+ else {
324
+ return ;
325
+ } ;
326
+ let Some ( ( _and, lt) ) = reference else {
327
+ return ;
328
+ } ;
329
+
330
+ let lifetime = syn:: Lifetime {
331
+ apostrophe : Span :: mixed_site ( ) ,
332
+ ident : Ident :: new ( "the_self_lt" , Span :: mixed_site ( ) ) ,
333
+ } ;
334
+ sig. generics . params . insert (
335
+ 0 ,
336
+ syn:: GenericParam :: Lifetime ( syn:: LifetimeParam {
337
+ lifetime : lifetime. clone ( ) ,
338
+ colon_token : None ,
339
+ bounds : Default :: default ( ) ,
340
+ attrs : Default :: default ( ) ,
341
+ } ) ,
342
+ ) ;
343
+ recv_ty. lifetime = Some ( lifetime. clone ( ) ) ;
344
+ * lt = Some ( lifetime) ;
345
+ let predicate = parse_quote ! { #recv_ty: Send } ;
346
+
347
+ if let Some ( wh) = & mut sig. generics . where_clause {
348
+ wh. predicates . push ( predicate) ;
349
+ } else {
350
+ let where_clause = WhereClause {
351
+ where_token : Token ! [ where ] ( Span :: mixed_site ( ) ) ,
352
+ predicates : Punctuated :: from_iter ( [ predicate] ) ,
353
+ } ;
354
+ sig. generics . where_clause = Some ( where_clause) ;
355
+ }
356
+ }
0 commit comments