@@ -389,36 +389,80 @@ fn fold_arg_<T: Folder>(a: &Arg, fld: &mut T) -> Arg {
389389 }
390390}
391391
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) =>
401398 TTSeq ( span,
402399 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) ) ,
404401 is_optional) ,
405- TTNonterminal ( sp, ref ident) =>
402+ TTNonterminal ( sp, ref ident) =>
406403 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 ( )
409409}
410410
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 {
413414 match * t {
414415 token:: IDENT ( id, followed_by_colons) => {
415416 token:: IDENT ( fld. fold_ident ( id) , followed_by_colons)
416417 }
417418 token:: LIFETIME ( id) => token:: LIFETIME ( fld. fold_ident ( id) ) ,
419+ token:: INTERPOLATED ( ref nt) => token:: INTERPOLATED ( fold_interpolated ( nt, fld) ) ,
418420 _ => ( * t) . clone ( )
419421 }
420422}
421423
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+
422466pub fn noop_fold_fn_decl < T : Folder > ( decl : & FnDecl , fld : & mut T ) -> P < FnDecl > {
423467 P ( FnDecl {
424468 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 {
672716 }
673717}
674718
719+ // fold one item into possibly many items
675720pub fn noop_fold_item < T : Folder > ( i : & Item ,
676721 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 {
677728 let id = folder. new_id ( i. id ) ; // Needs to be first, for ast_map.
678729 let node = folder. fold_item_underscore ( & i. node ) ;
679730 let ident = match node {
@@ -684,14 +735,14 @@ pub fn noop_fold_item<T: Folder>(i: &Item,
684735 _ => i. ident
685736 } ;
686737
687- SmallVector :: one ( box ( GC ) Item {
738+ Item {
688739 id : id,
689740 ident : folder. fold_ident ( ident) ,
690741 attrs : i. attrs . iter ( ) . map ( |e| folder. fold_attribute ( * e) ) . collect ( ) ,
691742 node : node,
692743 vis : i. vis ,
693744 span : folder. new_span ( i. span )
694- } )
745+ }
695746}
696747
697748pub fn noop_fold_foreign_item < T : Folder > ( ni : & ForeignItem ,
0 commit comments