@@ -13,7 +13,7 @@ enum Conversion<'a> {
13
13
}
14
14
15
15
impl < ' a > Conversion < ' a > {
16
- fn conversion_expr ( & self , i : Ident ) -> Expr {
16
+ fn conversion_expr ( & self , i : & Ident ) -> Expr {
17
17
match * self {
18
18
Conversion :: Into ( _) => parse_quote ! ( #i. into( ) ) ,
19
19
Conversion :: AsRef ( _) => parse_quote ! ( #i. as_ref( ) ) ,
@@ -23,12 +23,10 @@ impl<'a> Conversion<'a> {
23
23
}
24
24
25
25
fn parse_bounded_type ( ty : & Type ) -> Option < Ident > {
26
- if let Type :: Path ( TypePath { qself : None , ref path } ) = ty {
27
- if path. segments . len ( ) == 1 {
28
- return Some ( path. segments [ 0 ] . ident . clone ( ) ) ;
29
- }
26
+ match & ty {
27
+ Type :: Path ( TypePath { qself : None , path } ) if path. segments . len ( ) == 1 => Some ( path. segments [ 0 ] . ident . clone ( ) ) ,
28
+ _ => None ,
30
29
}
31
- None
32
30
}
33
31
34
32
fn parse_bounds ( bounds : & Punctuated < TypeParamBound , Token ! [ +] > ) -> Option < Conversion > {
@@ -60,7 +58,6 @@ fn parse_generics(decl: &Signature) -> HashMap<Ident, Conversion<'_>> {
60
58
if let GenericParam :: Type ( ref tp) = gp {
61
59
if let Some ( conversion) = parse_bounds ( & tp. bounds ) {
62
60
ty_conversions. insert ( tp. ident . clone ( ) , conversion) ;
63
- continue ;
64
61
}
65
62
}
66
63
}
@@ -70,7 +67,6 @@ fn parse_generics(decl: &Signature) -> HashMap<Ident, Conversion<'_>> {
70
67
if let Some ( ident) = parse_bounded_type ( & pt. bounded_ty ) {
71
68
if let Some ( conversion) = parse_bounds ( & pt. bounds ) {
72
69
ty_conversions. insert ( ident, conversion) ;
73
- continue ;
74
70
}
75
71
}
76
72
}
@@ -79,51 +75,76 @@ fn parse_generics(decl: &Signature) -> HashMap<Ident, Conversion<'_>> {
79
75
ty_conversions
80
76
}
81
77
82
- fn pat_to_ident ( pat : & Pat ) -> Ident {
83
- if let Pat :: Ident ( ref pat_ident) = * pat {
84
- return pat_ident. ident . clone ( ) ;
85
- }
86
- unimplemented ! ( "No non-ident patterns for now!" ) ;
87
- }
88
-
89
- fn pat_to_expr ( pat : & Pat ) -> Expr {
90
- let ident = pat_to_ident ( pat) ;
91
- parse_quote ! ( #ident)
92
- }
93
-
94
78
fn convert < ' a > (
95
79
inputs : & ' a Punctuated < FnArg , Token ! [ , ] > ,
96
80
ty_conversions : & HashMap < Ident , Conversion < ' a > > ,
97
- ) -> ( Punctuated < Expr , Token ! [ , ] > , bool ) {
81
+ ) -> ( Punctuated < FnArg , Token ! [ , ] > , Punctuated < Expr , Token ! [ , ] > , bool ) {
82
+ let mut argtypes = Punctuated :: new ( ) ;
98
83
let mut argexprs = Punctuated :: new ( ) ;
99
84
let mut has_self = false ;
100
- inputs. iter ( ) . for_each ( |input| match input {
101
- FnArg :: Receiver ( .. ) => {
85
+ inputs. iter ( ) . enumerate ( ) . for_each ( |( i , input) | match input. clone ( ) {
86
+ FnArg :: Receiver ( receiver ) => {
102
87
has_self = true ;
88
+ argtypes. push ( FnArg :: Receiver ( receiver) ) ;
103
89
}
104
- FnArg :: Typed ( PatType { ref pat, ref ty, .. } ) => match * * ty {
105
- Type :: ImplTrait ( TypeImplTrait { ref bounds, .. } ) => {
106
- if let Some ( conv) = parse_bounds ( bounds) {
107
- let ident = pat_to_ident ( pat) ;
108
- argexprs. push ( conv. conversion_expr ( ident) ) ;
109
- } else {
110
- argexprs. push ( pat_to_expr ( pat) ) ;
90
+ FnArg :: Typed ( mut pat_type) => {
91
+ let pat_ident = match & mut * pat_type. pat {
92
+ Pat :: Ident ( pat_ident) if pat_ident. by_ref . is_none ( ) && pat_ident. subpat . is_none ( ) => pat_ident,
93
+ _ => {
94
+ pat_type. pat = Box :: new ( Pat :: Ident ( PatIdent {
95
+ ident : Ident :: new ( & format ! ( "arg_{i}_gen_by_momo_" ) , proc_macro2:: Span :: call_site ( ) ) ,
96
+ attrs : Default :: default ( ) ,
97
+ by_ref : None ,
98
+ mutability : None ,
99
+ subpat : None ,
100
+ } ) ) ;
101
+
102
+ if let Pat :: Ident ( pat_ident) = & mut * pat_type. pat {
103
+ pat_ident
104
+ } else {
105
+ panic ! ( )
106
+ }
111
107
}
112
- }
113
- Type :: Path ( ..) => {
114
- if let Some ( conv) = parse_bounded_type ( ty) . and_then ( |ident| ty_conversions. get ( & ident) ) {
115
- let ident = pat_to_ident ( pat) ;
116
- argexprs. push ( conv. conversion_expr ( ident) ) ;
117
- } else {
118
- argexprs. push ( pat_to_expr ( pat) ) ;
108
+ } ;
109
+ // Outer function type argument pat does not need mut unless its
110
+ // type is `impl AsMut`.
111
+ pat_ident. mutability = None ;
112
+
113
+ let ident = & pat_ident. ident ;
114
+
115
+ let to_expr = || parse_quote ! ( #ident) ;
116
+
117
+ match * pat_type. ty {
118
+ Type :: ImplTrait ( TypeImplTrait { ref bounds, .. } ) => {
119
+ if let Some ( conv) = parse_bounds ( bounds) {
120
+ argexprs. push ( conv. conversion_expr ( ident) ) ;
121
+ if let Conversion :: AsMut ( _) = conv {
122
+ pat_ident. mutability = Some ( Default :: default ( ) ) ;
123
+ }
124
+ } else {
125
+ argexprs. push ( to_expr ( ) ) ;
126
+ }
127
+ }
128
+ Type :: Path ( ..) => {
129
+ if let Some ( conv) = parse_bounded_type ( & pat_type. ty ) . and_then ( |ident| ty_conversions. get ( & ident) ) {
130
+ argexprs. push ( conv. conversion_expr ( ident) ) ;
131
+ if let Conversion :: AsMut ( _) = conv {
132
+ pat_ident. mutability = Some ( Default :: default ( ) ) ;
133
+ }
134
+ } else {
135
+ argexprs. push ( to_expr ( ) ) ;
136
+ }
137
+ }
138
+ _ => {
139
+ argexprs. push ( to_expr ( ) ) ;
119
140
}
120
141
}
121
- _ => {
122
- argexprs . push ( pat_to_expr ( pat ) ) ;
123
- }
124
- } ,
142
+
143
+ // Now that mutability is decided, push the type into argtypes
144
+ argtypes . push ( FnArg :: Typed ( pat_type ) ) ;
145
+ }
125
146
} ) ;
126
- ( argexprs, has_self)
147
+ ( argtypes , argexprs, has_self)
127
148
}
128
149
129
150
fn contains_self_type_path ( path : & Path ) -> bool {
@@ -199,7 +220,7 @@ fn momo_inner(code: proc_macro2::TokenStream) -> proc_macro2::TokenStream {
199
220
200
221
if let Item :: Fn ( item_fn) = fn_item {
201
222
let ty_conversions = parse_generics ( & item_fn. sig ) ;
202
- let ( argexprs, has_self) = convert ( & item_fn. sig . inputs , & ty_conversions) ;
223
+ let ( argtypes , argexprs, has_self) = convert ( & item_fn. sig . inputs , & ty_conversions) ;
203
224
204
225
let uses_self = has_self
205
226
|| item_fn. sig . inputs . iter ( ) . any ( has_self_type)
@@ -211,6 +232,11 @@ fn momo_inner(code: proc_macro2::TokenStream) -> proc_macro2::TokenStream {
211
232
proc_macro2:: Span :: call_site ( ) ,
212
233
) ;
213
234
235
+ let outer_sig = Signature {
236
+ inputs : argtypes,
237
+ ..item_fn. sig . clone ( )
238
+ } ;
239
+
214
240
let new_inner_item = Item :: Fn ( ItemFn {
215
241
// Remove doc comment since they will increase compile-time and
216
242
// also generates duplicate warning/error messages for the doc,
@@ -226,7 +252,7 @@ fn momo_inner(code: proc_macro2::TokenStream) -> proc_macro2::TokenStream {
226
252
vis : Visibility :: Inherited ,
227
253
sig : Signature {
228
254
ident : inner_ident. clone ( ) ,
229
- ..item_fn. sig . clone ( )
255
+ ..item_fn. sig
230
256
} ,
231
257
block : item_fn. block ,
232
258
} ) ;
@@ -243,7 +269,7 @@ fn momo_inner(code: proc_macro2::TokenStream) -> proc_macro2::TokenStream {
243
269
let new_item = Item :: Fn ( ItemFn {
244
270
attrs : item_fn. attrs ,
245
271
vis : item_fn. vis ,
246
- sig : item_fn . sig ,
272
+ sig : outer_sig ,
247
273
block : if has_self {
248
274
parse_quote ! ( { self . #inner_ident( #argexprs) } )
249
275
} else {
@@ -258,7 +284,7 @@ fn momo_inner(code: proc_macro2::TokenStream) -> proc_macro2::TokenStream {
258
284
let new_item = Item :: Fn ( ItemFn {
259
285
attrs : item_fn. attrs ,
260
286
vis : item_fn. vis ,
261
- sig : item_fn . sig ,
287
+ sig : outer_sig ,
262
288
block : parse_quote ! ( {
263
289
#[ allow( unused_mut) ]
264
290
#new_inner_item
0 commit comments