1
- use std:: mem;
1
+ use std:: { iter :: FromIterator , mem} ;
2
2
3
3
use proc_macro2:: { Group , TokenStream , TokenTree } ;
4
4
use quote:: { format_ident, quote_spanned} ;
@@ -191,7 +191,7 @@ impl<'a> ParseBufferExt<'a> for ParseBuffer<'a> {
191
191
// visitors
192
192
193
193
// Replace `self`/`Self` with `__self`/`self_ty`.
194
- // Based on https://github.com/dtolnay/async-trait/blob/0.1.22 /src/receiver.rs
194
+ // Based on https://github.com/dtolnay/async-trait/blob/0.1.30 /src/receiver.rs
195
195
196
196
pub ( crate ) struct ReplaceReceiver < ' a > {
197
197
self_ty : & ' a Type ,
@@ -202,7 +202,7 @@ impl<'a> ReplaceReceiver<'a> {
202
202
Self { self_ty }
203
203
}
204
204
205
- fn self_to_qself ( & mut self , qself : & mut Option < QSelf > , path : & mut Path ) {
205
+ fn self_to_qself ( & self , qself : & mut Option < QSelf > , path : & mut Path ) {
206
206
if path. leading_colon . is_some ( ) {
207
207
return ;
208
208
}
@@ -235,15 +235,28 @@ impl<'a> ReplaceReceiver<'a> {
235
235
}
236
236
237
237
fn self_to_expr_path ( & self , path : & mut Path ) {
238
+ if path. leading_colon . is_some ( ) {
239
+ return ;
240
+ }
241
+
242
+ let first = & path. segments [ 0 ] ;
243
+ if first. ident != "Self" || !first. arguments . is_empty ( ) {
244
+ return ;
245
+ }
246
+
238
247
if let Type :: Path ( self_ty) = & self . self_ty {
239
- * path = self_ty. path . clone ( ) ;
248
+ let variant = mem :: replace ( path , self_ty. path . clone ( ) ) ;
240
249
for segment in & mut path. segments {
241
250
if let PathArguments :: AngleBracketed ( bracketed) = & mut segment. arguments {
242
251
if bracketed. colon2_token . is_none ( ) && !bracketed. args . is_empty ( ) {
243
252
bracketed. colon2_token = Some ( token:: Colon2 :: default ( ) ) ;
244
253
}
245
254
}
246
255
}
256
+ if variant. segments . len ( ) > 1 {
257
+ path. segments . push_punct ( token:: Colon2 :: default ( ) ) ;
258
+ path. segments . extend ( variant. segments . into_pairs ( ) . skip ( 1 ) ) ;
259
+ }
247
260
} else {
248
261
let span = path. segments [ 0 ] . ident . span ( ) ;
249
262
let msg = "Self type of this impl is unsupported in expression position" ;
@@ -285,26 +298,48 @@ impl VisitMut for ReplaceReceiver<'_> {
285
298
}
286
299
287
300
fn visit_expr_struct_mut ( & mut self , expr : & mut ExprStruct ) {
288
- if expr. path . is_ident ( "Self" ) {
289
- self . self_to_expr_path ( & mut expr. path ) ;
290
- }
301
+ self . self_to_expr_path ( & mut expr. path ) ;
291
302
visit_mut:: visit_expr_struct_mut ( self , expr) ;
292
303
}
293
304
305
+ fn visit_pat_path_mut ( & mut self , pat : & mut PatPath ) {
306
+ if pat. qself . is_none ( ) {
307
+ self . self_to_qself ( & mut pat. qself , & mut pat. path ) ;
308
+ }
309
+ visit_mut:: visit_pat_path_mut ( self , pat) ;
310
+ }
311
+
312
+ fn visit_pat_struct_mut ( & mut self , pat : & mut PatStruct ) {
313
+ self . self_to_expr_path ( & mut pat. path ) ;
314
+ visit_mut:: visit_pat_struct_mut ( self , pat) ;
315
+ }
316
+
317
+ fn visit_pat_tuple_struct_mut ( & mut self , pat : & mut PatTupleStruct ) {
318
+ self . self_to_expr_path ( & mut pat. path ) ;
319
+ visit_mut:: visit_pat_tuple_struct_mut ( self , pat) ;
320
+ }
321
+
322
+ fn visit_item_mut ( & mut self , node : & mut Item ) {
323
+ match node {
324
+ // Visit `macro_rules!` because locally defined macros can refer to `self`.
325
+ Item :: Macro ( node) if node. mac . path . is_ident ( "macro_rules" ) => {
326
+ self . visit_macro_mut ( & mut node. mac )
327
+ }
328
+ // Otherwise, do not recurse into nested items.
329
+ _ => { }
330
+ }
331
+ }
332
+
294
333
fn visit_macro_mut ( & mut self , node : & mut Macro ) {
295
334
// We can't tell in general whether `self` inside a macro invocation
296
335
// refers to the self in the argument list or a different self
297
336
// introduced within the macro. Heuristic: if the macro input contains
298
337
// `fn`, then `self` is more likely to refer to something other than the
299
338
// outer function's self argument.
300
339
if !contains_fn ( node. tokens . clone ( ) ) {
301
- node . tokens = fold_token_stream ( node. tokens . clone ( ) ) ;
340
+ visit_token_stream ( & mut node. tokens ) ;
302
341
}
303
342
}
304
-
305
- fn visit_item_mut ( & mut self , _: & mut Item ) {
306
- // Do not recurse into nested items.
307
- }
308
343
}
309
344
310
345
fn contains_fn ( tokens : TokenStream ) -> bool {
@@ -315,25 +350,35 @@ fn contains_fn(tokens: TokenStream) -> bool {
315
350
} )
316
351
}
317
352
318
- fn fold_token_stream ( tokens : TokenStream ) -> TokenStream {
319
- tokens
320
- . into_iter ( )
321
- . map ( |tt| match tt {
353
+ fn visit_token_stream ( tokens : & mut TokenStream ) -> bool {
354
+ let mut out = Vec :: new ( ) ;
355
+ let mut modified = false ;
356
+ for tt in tokens. clone ( ) {
357
+ match tt {
322
358
TokenTree :: Ident ( mut ident) => {
323
- prepend_underscore_to_self ( & mut ident) ;
324
- TokenTree :: Ident ( ident)
359
+ modified |= prepend_underscore_to_self ( & mut ident) ;
360
+ out . push ( TokenTree :: Ident ( ident) ) ;
325
361
}
326
362
TokenTree :: Group ( group) => {
327
- let content = fold_token_stream ( group. stream ( ) ) ;
328
- TokenTree :: Group ( Group :: new ( group. delimiter ( ) , content) )
363
+ let mut content = group. stream ( ) ;
364
+ modified |= visit_token_stream ( & mut content) ;
365
+ let mut new = Group :: new ( group. delimiter ( ) , content) ;
366
+ new. set_span ( group. span ( ) ) ;
367
+ out. push ( TokenTree :: Group ( new) ) ;
329
368
}
330
- other => other,
331
- } )
332
- . collect ( )
369
+ other => out. push ( other) ,
370
+ }
371
+ }
372
+ if modified {
373
+ * tokens = TokenStream :: from_iter ( out) ;
374
+ }
375
+ modified
333
376
}
334
377
335
- pub ( crate ) fn prepend_underscore_to_self ( ident : & mut Ident ) {
336
- if ident == "self" {
378
+ pub ( crate ) fn prepend_underscore_to_self ( ident : & mut Ident ) -> bool {
379
+ let modified = ident == "self" ;
380
+ if modified {
337
381
* ident = Ident :: new ( "__self" , ident. span ( ) ) ;
338
382
}
383
+ modified
339
384
}
0 commit comments