@@ -389,36 +389,80 @@ fn fold_arg_<T: Folder>(a: &Arg, fld: &mut T) -> Arg {
389
389
}
390
390
}
391
391
392
- // build a new vector of tts by appling the Folder's fold_ident to
393
- // all of the identifiers in the token trees.
394
- pub fn fold_tts < T : Folder > ( tts : & [ TokenTree ] , fld : & mut T ) -> Vec < TokenTree > {
395
- tts. iter ( ) . map ( |tt| {
396
- match * tt {
397
- TTTok ( span, ref tok) =>
398
- TTTok ( span, maybe_fold_ident ( tok, fld) ) ,
399
- TTDelim ( ref tts) => TTDelim ( Rc :: new ( fold_tts ( tts. as_slice ( ) , fld) ) ) ,
400
- 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) =>
401
398
TTSeq ( span,
402
399
Rc :: new ( fold_tts ( pattern. as_slice ( ) , fld) ) ,
403
- sep. as_ref ( ) . map ( |tok|maybe_fold_ident ( tok, fld) ) ,
400
+ sep. as_ref ( ) . map ( |tok| fold_token ( tok, fld) ) ,
404
401
is_optional) ,
405
- TTNonterminal ( sp, ref ident) =>
402
+ TTNonterminal ( sp, ref ident) =>
406
403
TTNonterminal ( sp, fld. fold_ident ( * ident) )
407
- }
408
- } ) . 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 ( )
409
409
}
410
410
411
- // apply ident folder if it's an ident, otherwise leave it alone
412
- 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 {
413
414
match * t {
414
415
token:: IDENT ( id, followed_by_colons) => {
415
416
token:: IDENT ( fld. fold_ident ( id) , followed_by_colons)
416
417
}
417
418
token:: LIFETIME ( id) => token:: LIFETIME ( fld. fold_ident ( id) ) ,
419
+ token:: INTERPOLATED ( ref nt) => token:: INTERPOLATED ( fold_interpolated ( nt, fld) ) ,
418
420
_ => ( * t) . clone ( )
419
421
}
420
422
}
421
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
+
422
466
pub fn noop_fold_fn_decl < T : Folder > ( decl : & FnDecl , fld : & mut T ) -> P < FnDecl > {
423
467
P ( FnDecl {
424
468
inputs : decl. inputs . iter ( ) . map ( |x| fold_arg_ ( x, fld) ) . collect ( ) , // bad copy
@@ -672,8 +716,15 @@ pub fn noop_fold_crate<T: Folder>(c: Crate, folder: &mut T) -> Crate {
672
716
}
673
717
}
674
718
719
+ // fold one item into possibly many items
675
720
pub fn noop_fold_item < T : Folder > ( i : & Item ,
676
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 {
677
728
let id = folder. new_id ( i. id ) ; // Needs to be first, for ast_map.
678
729
let node = folder. fold_item_underscore ( & i. node ) ;
679
730
let ident = match node {
@@ -684,14 +735,14 @@ pub fn noop_fold_item<T: Folder>(i: &Item,
684
735
_ => i. ident
685
736
} ;
686
737
687
- SmallVector :: one ( box ( GC ) Item {
738
+ Item {
688
739
id : id,
689
740
ident : folder. fold_ident ( ident) ,
690
741
attrs : i. attrs . iter ( ) . map ( |e| folder. fold_attribute ( * e) ) . collect ( ) ,
691
742
node : node,
692
743
vis : i. vis ,
693
744
span : folder. new_span ( i. span )
694
- } )
745
+ }
695
746
}
696
747
697
748
pub fn noop_fold_foreign_item < T : Folder > ( ni : & ForeignItem ,
0 commit comments