@@ -86,7 +86,7 @@ pub trait Folder {
86
86
kind : sf. node . kind ,
87
87
id : id,
88
88
ty : self . fold_ty ( sf. node . ty ) ,
89
- attrs : sf. node . attrs . iter ( ) . map ( |e| fold_attribute_ ( * e, self ) ) . collect ( )
89
+ attrs : sf. node . attrs . iter ( ) . map ( |e| self . fold_attribute ( * e) ) . collect ( )
90
90
} ,
91
91
span : self . new_span ( sf. span )
92
92
}
@@ -118,7 +118,7 @@ pub trait Folder {
118
118
119
119
fn fold_arm ( & mut self , a : & Arm ) -> Arm {
120
120
Arm {
121
- attrs : a. attrs . iter ( ) . map ( |x| fold_attribute_ ( * x, self ) ) . collect ( ) ,
121
+ attrs : a. attrs . iter ( ) . map ( |x| self . fold_attribute ( * x) ) . collect ( ) ,
122
122
pats : a. pats . iter ( ) . map ( |x| self . fold_pat ( * x) ) . collect ( ) ,
123
123
guard : a. guard . map ( |x| self . fold_expr ( x) ) ,
124
124
body : self . fold_expr ( a. body ) ,
@@ -251,7 +251,7 @@ pub trait Folder {
251
251
}
252
252
}
253
253
254
- let attrs = v. node . attrs . iter ( ) . map ( |x| fold_attribute_ ( * x, self ) ) . collect ( ) ;
254
+ let attrs = v. node . attrs . iter ( ) . map ( |x| self . fold_attribute ( * x) ) . collect ( ) ;
255
255
256
256
let de = match v. node . disr_expr {
257
257
Some ( e) => Some ( self . fold_expr ( e) ) ,
@@ -344,6 +344,21 @@ pub trait Folder {
344
344
fn fold_lifetime ( & mut self , l : & Lifetime ) -> Lifetime {
345
345
noop_fold_lifetime ( l, self )
346
346
}
347
+
348
+ //used in noop_fold_item and noop_fold_crate
349
+ fn fold_attribute ( & mut self , at : Attribute ) -> Attribute {
350
+ Spanned {
351
+ span : self . new_span ( at. span ) ,
352
+ node : ast:: Attribute_ {
353
+ id : at. node . id ,
354
+ style : at. node . style ,
355
+ value : fold_meta_item_ ( at. node . value , self ) ,
356
+ is_sugared_doc : at. node . is_sugared_doc
357
+ }
358
+ }
359
+ }
360
+
361
+
347
362
}
348
363
349
364
/* some little folds that probably aren't useful to have in Folder itself*/
@@ -364,19 +379,6 @@ fn fold_meta_item_<T: Folder>(mi: Gc<MetaItem>, fld: &mut T) -> Gc<MetaItem> {
364
379
span : fld. new_span ( mi. span ) }
365
380
}
366
381
367
- //used in noop_fold_item and noop_fold_crate
368
- fn fold_attribute_ < T : Folder > ( at : Attribute , fld : & mut T ) -> Attribute {
369
- Spanned {
370
- span : fld. new_span ( at. span ) ,
371
- node : ast:: Attribute_ {
372
- id : at. node . id ,
373
- style : at. node . style ,
374
- value : fold_meta_item_ ( at. node . value , fld) ,
375
- is_sugared_doc : at. node . is_sugared_doc
376
- }
377
- }
378
- }
379
-
380
382
//used in noop_fold_foreign_item and noop_fold_fn_decl
381
383
fn fold_arg_ < T : Folder > ( a : & Arg , fld : & mut T ) -> Arg {
382
384
let id = fld. new_id ( a. id ) ; // Needs to be first, for ast_map.
@@ -387,53 +389,80 @@ fn fold_arg_<T: Folder>(a: &Arg, fld: &mut T) -> Arg {
387
389
}
388
390
}
389
391
390
- // build a new vector of tts by appling the Folder's fold_ident to
391
- // all of the identifiers in the token trees.
392
- //
393
- // This is part of hygiene magic. As far as hygiene is concerned, there
394
- // are three types of let pattern bindings or loop labels:
395
- // - those defined and used in non-macro part of the program
396
- // - those used as part of macro invocation arguments
397
- // - those defined and used inside macro definitions
398
- // Lexically, type 1 and 2 are in one group and type 3 the other. If they
399
- // clash, in order for let and loop label to work hygienically, one group
400
- // or the other needs to be renamed. The problem is that type 2 and 3 are
401
- // parsed together (inside the macro expand function). After being parsed and
402
- // AST being constructed, they can no longer be distinguished from each other.
403
- //
404
- // For that reason, type 2 let bindings and loop labels are actually renamed
405
- // in the form of tokens instead of AST nodes, here. There are wasted effort
406
- // since many token::IDENT are not necessary part of let bindings and most
407
- // token::LIFETIME are certainly not loop labels. But we can't tell in their
408
- // token form. So this is less ideal and hacky but it works.
409
- pub fn fold_tts < T : Folder > ( tts : & [ TokenTree ] , fld : & mut T ) -> Vec < TokenTree > {
410
- tts. iter ( ) . map ( |tt| {
411
- match * tt {
412
- TTTok ( span, ref tok) =>
413
- TTTok ( span, maybe_fold_ident ( tok, fld) ) ,
414
- TTDelim ( ref tts) => TTDelim ( Rc :: new ( fold_tts ( tts. as_slice ( ) , fld) ) ) ,
415
- TTSeq ( span, ref pattern, ref sep, is_optional) =>
392
+ pub fn fold_tt < T : Folder > ( tt : & TokenTree , fld : & mut T ) -> TokenTree {
393
+ match * tt {
394
+ TTTok ( span, ref tok) =>
395
+ TTTok ( span, fold_token ( tok, fld) ) ,
396
+ TTDelim ( ref tts) => TTDelim ( Rc :: new ( fold_tts ( tts. as_slice ( ) , fld) ) ) ,
397
+ TTSeq ( span, ref pattern, ref sep, is_optional) =>
416
398
TTSeq ( span,
417
399
Rc :: new ( fold_tts ( pattern. as_slice ( ) , fld) ) ,
418
- sep. as_ref ( ) . map ( |tok|maybe_fold_ident ( tok, fld) ) ,
400
+ sep. as_ref ( ) . map ( |tok| fold_token ( tok, fld) ) ,
419
401
is_optional) ,
420
- TTNonterminal ( sp, ref ident) =>
402
+ TTNonterminal ( sp, ref ident) =>
421
403
TTNonterminal ( sp, fld. fold_ident ( * ident) )
422
- }
423
- } ) . collect ( )
404
+ }
405
+ }
406
+
407
+ pub fn fold_tts < T : Folder > ( tts : & [ TokenTree ] , fld : & mut T ) -> Vec < TokenTree > {
408
+ tts. iter ( ) . map ( |tt| fold_tt ( tt, fld) ) . collect ( )
424
409
}
425
410
426
- // apply ident folder if it's an ident, otherwise leave it alone
427
- fn maybe_fold_ident < T : Folder > ( t : & token:: Token , fld : & mut T ) -> token:: Token {
411
+
412
+ // apply ident folder if it's an ident, apply other folds to interpolated nodes
413
+ fn fold_token < T : Folder > ( t : & token:: Token , fld : & mut T ) -> token:: Token {
428
414
match * t {
429
415
token:: IDENT ( id, followed_by_colons) => {
430
416
token:: IDENT ( fld. fold_ident ( id) , followed_by_colons)
431
417
}
432
418
token:: LIFETIME ( id) => token:: LIFETIME ( fld. fold_ident ( id) ) ,
419
+ token:: INTERPOLATED ( ref nt) => token:: INTERPOLATED ( fold_interpolated ( nt, fld) ) ,
433
420
_ => ( * t) . clone ( )
434
421
}
435
422
}
436
423
424
+ // apply folder to elements of interpolated nodes
425
+ //
426
+ // NB: this can occur only when applying a fold to partially expanded code, where
427
+ // parsed pieces have gotten implanted ito *other* macro invocations. This is relevant
428
+ // for macro hygiene, but possibly not elsewhere.
429
+ //
430
+ // One problem here occurs because the types for fold_item, fold_stmt, etc. allow the
431
+ // folder to return *multiple* items; this is a problem for the nodes here, because
432
+ // they insist on having exactly one piece. One solution would be to mangle the fold
433
+ // trait to include one-to-many and one-to-one versions of these entry points, but that
434
+ // would probably confuse a lot of people and help very few. Instead, I'm just going
435
+ // to put in dynamic checks. I think the performance impact of this will be pretty much
436
+ // nonexistent. The danger is that someone will apply a fold to a partially expanded
437
+ // node, and will be confused by the fact that their "fold_item" or "fold_stmt" isn't
438
+ // getting called on NtItem or NtStmt nodes. Hopefully they'll wind up reading this
439
+ // comment, and doing something appropriate.
440
+ //
441
+ // BTW, design choice: I considered just changing the type of, e.g., NtItem to contain
442
+ // multiple items, but decided against it when I looked at parse_item_or_view_item and
443
+ // tried to figure out what I would do with multiple items there....
444
+ fn fold_interpolated < T : Folder > ( nt : & token:: Nonterminal , fld : & mut T ) -> token:: Nonterminal {
445
+ match * nt {
446
+ token:: NtItem ( item) =>
447
+ token:: NtItem ( fld. fold_item ( item)
448
+ . expect_one ( "expected fold to produce exactly one item" ) ) ,
449
+ token:: NtBlock ( block) => token:: NtBlock ( fld. fold_block ( block) ) ,
450
+ token:: NtStmt ( stmt) =>
451
+ token:: NtStmt ( fld. fold_stmt ( stmt)
452
+ . expect_one ( "expected fold to produce exactly one statement" ) ) ,
453
+ token:: NtPat ( pat) => token:: NtPat ( fld. fold_pat ( pat) ) ,
454
+ token:: NtExpr ( expr) => token:: NtExpr ( fld. fold_expr ( expr) ) ,
455
+ token:: NtTy ( ty) => token:: NtTy ( fld. fold_ty ( ty) ) ,
456
+ token:: NtIdent ( ref id, is_mod_name) =>
457
+ token:: NtIdent ( box fld. fold_ident ( * * id) , is_mod_name) ,
458
+ token:: NtMeta ( meta_item) => token:: NtMeta ( fold_meta_item_ ( meta_item, fld) ) ,
459
+ token:: NtPath ( ref path) => token:: NtPath ( box fld. fold_path ( * path) ) ,
460
+ token:: NtTT ( tt) => token:: NtTT ( box ( GC ) fold_tt( tt, fld) ) ,
461
+ // it looks to me like we can leave out the matchers: token::NtMatchers(matchers)
462
+ _ => ( * nt) . clone ( )
463
+ }
464
+ }
465
+
437
466
pub fn noop_fold_fn_decl < T : Folder > ( decl : & FnDecl , fld : & mut T ) -> P < FnDecl > {
438
467
P ( FnDecl {
439
468
inputs : decl. inputs . iter ( ) . map ( |x| fold_arg_ ( x, fld) ) . collect ( ) , // bad copy
@@ -526,7 +555,7 @@ fn fold_struct_field<T: Folder>(f: &StructField, fld: &mut T) -> StructField {
526
555
kind : f. node . kind ,
527
556
id : id,
528
557
ty : fld. fold_ty ( f. node . ty ) ,
529
- attrs : f. node . attrs . iter ( ) . map ( |a| fold_attribute_ ( * a, fld ) ) . collect ( ) ,
558
+ attrs : f. node . attrs . iter ( ) . map ( |a| fld . fold_attribute ( * a) ) . collect ( ) ,
530
559
} ,
531
560
span : fld. new_span ( f. span ) ,
532
561
}
@@ -578,7 +607,7 @@ pub fn noop_fold_view_item<T: Folder>(vi: &ViewItem, folder: &mut T)
578
607
} ;
579
608
ViewItem {
580
609
node : inner_view_item,
581
- attrs : vi. attrs . iter ( ) . map ( |a| fold_attribute_ ( * a, folder ) ) . collect ( ) ,
610
+ attrs : vi. attrs . iter ( ) . map ( |a| folder . fold_attribute ( * a) ) . collect ( ) ,
582
611
vis : vi. vis ,
583
612
span : folder. new_span ( vi. span ) ,
584
613
}
@@ -658,7 +687,7 @@ pub fn noop_fold_type_method<T: Folder>(m: &TypeMethod, fld: &mut T) -> TypeMeth
658
687
TypeMethod {
659
688
id : id,
660
689
ident : fld. fold_ident ( m. ident ) ,
661
- attrs : m. attrs . iter ( ) . map ( |a| fold_attribute_ ( * a, fld ) ) . collect ( ) ,
690
+ attrs : m. attrs . iter ( ) . map ( |a| fld . fold_attribute ( * a) ) . collect ( ) ,
662
691
fn_style : m. fn_style ,
663
692
decl : fld. fold_fn_decl ( & * m. decl ) ,
664
693
generics : fold_generics ( & m. generics , fld) ,
@@ -681,14 +710,21 @@ pub fn noop_fold_mod<T: Folder>(m: &Mod, folder: &mut T) -> Mod {
681
710
pub fn noop_fold_crate < T : Folder > ( c : Crate , folder : & mut T ) -> Crate {
682
711
Crate {
683
712
module : folder. fold_mod ( & c. module ) ,
684
- attrs : c. attrs . iter ( ) . map ( |x| fold_attribute_ ( * x, folder ) ) . collect ( ) ,
713
+ attrs : c. attrs . iter ( ) . map ( |x| folder . fold_attribute ( * x) ) . collect ( ) ,
685
714
config : c. config . iter ( ) . map ( |x| fold_meta_item_ ( * x, folder) ) . collect ( ) ,
686
715
span : folder. new_span ( c. span ) ,
687
716
}
688
717
}
689
718
719
+ // fold one item into possibly many items
690
720
pub fn noop_fold_item < T : Folder > ( i : & Item ,
691
721
folder : & mut T ) -> SmallVector < Gc < Item > > {
722
+ SmallVector :: one ( box ( GC ) noop_fold_item_ ( i, folder) )
723
+ }
724
+
725
+
726
+ // fold one item into exactly one item
727
+ pub fn noop_fold_item_ < T : Folder > ( i : & Item , folder : & mut T ) -> Item {
692
728
let id = folder. new_id ( i. id ) ; // Needs to be first, for ast_map.
693
729
let node = folder. fold_item_underscore ( & i. node ) ;
694
730
let ident = match node {
@@ -699,14 +735,14 @@ pub fn noop_fold_item<T: Folder>(i: &Item,
699
735
_ => i. ident
700
736
} ;
701
737
702
- SmallVector :: one ( box ( GC ) Item {
738
+ Item {
703
739
id : id,
704
740
ident : folder. fold_ident ( ident) ,
705
- attrs : i. attrs . iter ( ) . map ( |e| fold_attribute_ ( * e, folder ) ) . collect ( ) ,
741
+ attrs : i. attrs . iter ( ) . map ( |e| folder . fold_attribute ( * e) ) . collect ( ) ,
706
742
node : node,
707
743
vis : i. vis ,
708
744
span : folder. new_span ( i. span )
709
- } )
745
+ }
710
746
}
711
747
712
748
pub fn noop_fold_foreign_item < T : Folder > ( ni : & ForeignItem ,
@@ -715,7 +751,7 @@ pub fn noop_fold_foreign_item<T: Folder>(ni: &ForeignItem,
715
751
box ( GC ) ForeignItem {
716
752
id : id,
717
753
ident : folder. fold_ident ( ni. ident ) ,
718
- attrs : ni. attrs . iter ( ) . map ( |x| fold_attribute_ ( * x, folder ) ) . collect ( ) ,
754
+ attrs : ni. attrs . iter ( ) . map ( |x| folder . fold_attribute ( * x) ) . collect ( ) ,
719
755
node : match ni. node {
720
756
ForeignItemFn ( ref fdec, ref generics) => {
721
757
ForeignItemFn ( P ( FnDecl {
@@ -739,7 +775,7 @@ pub fn noop_fold_method<T: Folder>(m: &Method, folder: &mut T) -> Gc<Method> {
739
775
box ( GC ) Method {
740
776
id : id,
741
777
ident : folder. fold_ident ( m. ident ) ,
742
- attrs : m. attrs . iter ( ) . map ( |a| fold_attribute_ ( * a, folder ) ) . collect ( ) ,
778
+ attrs : m. attrs . iter ( ) . map ( |a| folder . fold_attribute ( * a) ) . collect ( ) ,
743
779
generics : fold_generics ( & m. generics , folder) ,
744
780
explicit_self : folder. fold_explicit_self ( & m. explicit_self ) ,
745
781
fn_style : m. fn_style ,
0 commit comments