10
10
//! See [`serde_closure`](https://docs.rs/serde_closure) for
11
11
//! documentation.
12
12
13
- #![ doc( html_root_url = "https://docs.rs/serde_closure_derive/0.3.1 " ) ]
13
+ #![ doc( html_root_url = "https://docs.rs/serde_closure_derive/0.3.2 " ) ]
14
14
15
15
use proc_macro2:: { Span , TokenStream } ;
16
16
use quote:: { quote, ToTokens } ;
17
17
use std:: { collections:: HashSet , iter, iter:: successors, mem:: take, str} ;
18
18
use syn:: {
19
- parse2, parse_macro_input, visit_mut:: { self , VisitMut } , Arm , AttributeArgs , Block , Error , Expr , ExprArray , ExprAssign , ExprAssignOp , ExprAsync , ExprAwait , ExprBinary , ExprBlock , ExprBox , ExprBreak , ExprCall , ExprCast , ExprClosure , ExprField , ExprForLoop , ExprGroup , ExprIf , ExprIndex , ExprLet , ExprLoop , ExprMacro , ExprMatch , ExprMethodCall , ExprParen , ExprPath , ExprRange , ExprReference , ExprRepeat , ExprReturn , ExprStruct , ExprTry , ExprTryBlock , ExprTuple , ExprType , ExprUnary , ExprUnsafe , ExprWhile , ExprYield , FieldValue , Ident , Item , Lifetime , LifetimeDef , Local , Member , Pat , PatBox , PatIdent , PatReference , PatSlice , PatTuple , PatTupleStruct , PatType , Path , PathArguments , PathSegment , ReturnType , Stmt , TraitBound , Type , TypeInfer , TypeReference , TypeTuple , UnOp
19
+ parse2, parse_macro_input, visit_mut:: { self , VisitMut } , Arm , AttributeArgs , Block , Error , Expr , ExprArray , ExprAssign , ExprAssignOp , ExprAsync , ExprAwait , ExprBinary , ExprBlock , ExprBox , ExprBreak , ExprCall , ExprCast , ExprClosure , ExprField , ExprForLoop , ExprGroup , ExprIf , ExprIndex , ExprLet , ExprLoop , ExprMacro , ExprMatch , ExprMethodCall , ExprParen , ExprPath , ExprRange , ExprReference , ExprRepeat , ExprReturn , ExprStruct , ExprTry , ExprTryBlock , ExprTuple , ExprType , ExprUnary , ExprUnsafe , ExprWhile , ExprYield , FieldValue , GenericParam , Ident , ImplItem , Item , ItemImpl , Lifetime , LifetimeDef , Local , Member , Pat , PatBox , PatIdent , PatReference , PatSlice , PatTuple , PatTupleStruct , PatType , Path , PathArguments , PathSegment , ReturnType , Stmt , TraitBound , Type , TypeInfer , TypeReference , TypeTuple , UnOp
20
20
} ;
21
21
22
22
#[ proc_macro]
@@ -60,14 +60,12 @@ pub fn desugar(
60
60
61
61
struct Desugar ;
62
62
63
- impl VisitMut for Desugar {
64
- fn visit_trait_bound_mut ( & mut self , i : & mut TraitBound ) {
65
- let span = Span :: call_site ( ) ;
66
- if let PathSegment {
67
- arguments : PathArguments :: Parenthesized ( args) ,
68
- ..
69
- } = i. path . segments . last ( ) . unwrap ( )
70
- {
63
+ impl Desugar {
64
+ fn desugar_path_arg (
65
+ & mut self , arg : & mut PathArguments , return_output : bool ,
66
+ ) -> ( u64 , Option < Type > ) {
67
+ if let PathArguments :: Parenthesized ( args) = & arg {
68
+ let span = Span :: call_site ( ) ;
71
69
let mut lifetimes = 0 ;
72
70
let mut inputs = args. inputs . clone ( ) ;
73
71
for input in & mut inputs {
@@ -95,6 +93,25 @@ impl VisitMut for Desugar {
95
93
elems : Default :: default ( ) ,
96
94
} ) ,
97
95
} ;
96
+ * arg = PathArguments :: AngleBracketed ( if !return_output {
97
+ syn:: parse2 ( quote ! { <( #inputs) , Output = #output> } ) . unwrap ( )
98
+ } else {
99
+ syn:: parse2 ( quote ! { <( #inputs) > } ) . unwrap ( )
100
+ } ) ;
101
+ ( lifetimes, if return_output { Some ( output) } else { None } )
102
+ } else {
103
+ ( 0 , None )
104
+ }
105
+ }
106
+ }
107
+
108
+ impl VisitMut for Desugar {
109
+ fn visit_trait_bound_mut ( & mut self , i : & mut TraitBound ) {
110
+ let lifetimes = self
111
+ . desugar_path_arg ( & mut i. path . segments . last_mut ( ) . unwrap ( ) . arguments , false )
112
+ . 0 ;
113
+ if lifetimes > 0 {
114
+ let span = Span :: call_site ( ) ;
98
115
let empty = syn:: parse2 ( quote ! { for <>} ) . unwrap ( ) ;
99
116
i. lifetimes = Some ( i. lifetimes . clone ( ) . unwrap_or ( empty) ) ;
100
117
i. lifetimes
@@ -107,12 +124,35 @@ impl VisitMut for Desugar {
107
124
span,
108
125
) )
109
126
} ) ) ;
110
- i. path . segments . last_mut ( ) . unwrap ( ) . arguments = PathArguments :: AngleBracketed (
111
- syn:: parse2 ( quote ! { <( #inputs) , Output = #output> } ) . unwrap ( ) ,
112
- ) ;
113
127
}
114
128
visit_mut:: visit_trait_bound_mut ( self , i)
115
129
}
130
+ fn visit_item_impl_mut ( & mut self , i : & mut ItemImpl ) {
131
+ if let Some ( ( _, path, _) ) = & mut i. trait_ {
132
+ let ( lifetimes, output) =
133
+ self . desugar_path_arg ( & mut path. segments . last_mut ( ) . unwrap ( ) . arguments , true ) ;
134
+ if lifetimes > 0 {
135
+ let span = Span :: call_site ( ) ;
136
+ i. generics . lt_token = Some ( Default :: default ( ) ) ;
137
+ i. generics . gt_token = Some ( Default :: default ( ) ) ;
138
+ i. generics . params . extend ( ( 0 ..lifetimes) . map ( |i| {
139
+ GenericParam :: Lifetime ( LifetimeDef :: new ( Lifetime :: new (
140
+ & format ! ( "'__serde_closure_{}" , bijective_base( i, 26 , alpha_lower) ) ,
141
+ span,
142
+ ) ) )
143
+ } ) ) ;
144
+ }
145
+ // Yuck
146
+ if path. segments . last ( ) . unwrap ( ) . ident == "FnOnce" {
147
+ if let Some ( output) = output {
148
+ i. items . push ( ImplItem :: Type (
149
+ syn:: parse2 ( quote ! { type Output = #output; } ) . unwrap ( ) ,
150
+ ) ) ;
151
+ }
152
+ }
153
+ }
154
+ visit_mut:: visit_item_impl_mut ( self , i)
155
+ }
116
156
}
117
157
118
158
#[ derive( Copy , Clone , PartialEq , Eq ) ]
@@ -257,6 +297,7 @@ fn impl_closure(mut closure: ExprClosure, kind: Kind) -> Result<TokenStream, Err
257
297
F : ops:: FnOnce ( & #name<#( #type_params, ) * ( ) >, I ) -> O
258
298
{
259
299
type Output = O ;
300
+
260
301
#[ inline( always) ]
261
302
fn call_once( self , args: I ) -> Self :: Output {
262
303
self . f( ) ( & self . strip_f( ) , args)
@@ -287,6 +328,7 @@ fn impl_closure(mut closure: ExprClosure, kind: Kind) -> Result<TokenStream, Err
287
328
F : ops:: FnOnce ( & mut #name<#( #type_params, ) * ( ) >, I ) -> O
288
329
{
289
330
type Output = O ;
331
+
290
332
#[ inline( always) ]
291
333
fn call_once( mut self , args: I ) -> Self :: Output {
292
334
self . f( ) ( & mut self . strip_f( ) , args)
@@ -308,6 +350,7 @@ fn impl_closure(mut closure: ExprClosure, kind: Kind) -> Result<TokenStream, Err
308
350
F : ops:: FnOnce ( #name<#( #type_params, ) * ( ) >, I ) -> O
309
351
{
310
352
type Output = O ;
353
+
311
354
#[ inline( always) ]
312
355
fn call_once( self , args: I ) -> Self :: Output {
313
356
self . f( ) ( self . strip_f( ) , args)
@@ -787,11 +830,7 @@ impl<'a> State<'a> {
787
830
{
788
831
let path_segment = & path. segments . first ( ) . unwrap ( ) ;
789
832
let ident = & path_segment. ident ;
790
- let has_path_arguments = if let PathArguments :: None = path_segment. arguments {
791
- false
792
- } else {
793
- true
794
- } ;
833
+ let has_path_arguments = !matches ! ( path_segment. arguments, PathArguments :: None ) ;
795
834
if !self . variables . contains ( ident) {
796
835
// Assume it's a variable, unless:
797
836
// * It starts with an upper-case letter, e.g. `Some`, OR
0 commit comments