@@ -86,7 +86,7 @@ pub trait Folder {
8686 kind : sf. node . kind ,
8787 id : id,
8888 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 ( )
9090 } ,
9191 span : self . new_span ( sf. span )
9292 }
@@ -118,7 +118,7 @@ pub trait Folder {
118118
119119 fn fold_arm ( & mut self , a : & Arm ) -> Arm {
120120 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 ( ) ,
122122 pats : a. pats . iter ( ) . map ( |x| self . fold_pat ( * x) ) . collect ( ) ,
123123 guard : a. guard . map ( |x| self . fold_expr ( x) ) ,
124124 body : self . fold_expr ( a. body ) ,
@@ -251,7 +251,7 @@ pub trait Folder {
251251 }
252252 }
253253
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 ( ) ;
255255
256256 let de = match v. node . disr_expr {
257257 Some ( e) => Some ( self . fold_expr ( e) ) ,
@@ -344,6 +344,21 @@ pub trait Folder {
344344 fn fold_lifetime ( & mut self , l : & Lifetime ) -> Lifetime {
345345 noop_fold_lifetime ( l, self )
346346 }
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+
347362}
348363
349364/* 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> {
364379 span : fld. new_span ( mi. span ) }
365380}
366381
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-
380382//used in noop_fold_foreign_item and noop_fold_fn_decl
381383fn fold_arg_ < T : Folder > ( a : & Arg , fld : & mut T ) -> Arg {
382384 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 {
387389 }
388390}
389391
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) =>
416398 TTSeq ( span,
417399 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) ) ,
419401 is_optional) ,
420- TTNonterminal ( sp, ref ident) =>
402+ TTNonterminal ( sp, ref ident) =>
421403 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 ( )
424409}
425410
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 {
428414 match * t {
429415 token:: IDENT ( id, followed_by_colons) => {
430416 token:: IDENT ( fld. fold_ident ( id) , followed_by_colons)
431417 }
432418 token:: LIFETIME ( id) => token:: LIFETIME ( fld. fold_ident ( id) ) ,
419+ token:: INTERPOLATED ( ref nt) => token:: INTERPOLATED ( fold_interpolated ( nt, fld) ) ,
433420 _ => ( * t) . clone ( )
434421 }
435422}
436423
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+
437466pub fn noop_fold_fn_decl < T : Folder > ( decl : & FnDecl , fld : & mut T ) -> P < FnDecl > {
438467 P ( FnDecl {
439468 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 {
526555 kind : f. node . kind ,
527556 id : id,
528557 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 ( ) ,
530559 } ,
531560 span : fld. new_span ( f. span ) ,
532561 }
@@ -578,7 +607,7 @@ pub fn noop_fold_view_item<T: Folder>(vi: &ViewItem, folder: &mut T)
578607 } ;
579608 ViewItem {
580609 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 ( ) ,
582611 vis : vi. vis ,
583612 span : folder. new_span ( vi. span ) ,
584613 }
@@ -658,7 +687,7 @@ pub fn noop_fold_type_method<T: Folder>(m: &TypeMethod, fld: &mut T) -> TypeMeth
658687 TypeMethod {
659688 id : id,
660689 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 ( ) ,
662691 fn_style : m. fn_style ,
663692 decl : fld. fold_fn_decl ( & * m. decl ) ,
664693 generics : fold_generics ( & m. generics , fld) ,
@@ -681,14 +710,21 @@ pub fn noop_fold_mod<T: Folder>(m: &Mod, folder: &mut T) -> Mod {
681710pub fn noop_fold_crate < T : Folder > ( c : Crate , folder : & mut T ) -> Crate {
682711 Crate {
683712 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 ( ) ,
685714 config : c. config . iter ( ) . map ( |x| fold_meta_item_ ( * x, folder) ) . collect ( ) ,
686715 span : folder. new_span ( c. span ) ,
687716 }
688717}
689718
719+ // fold one item into possibly many items
690720pub fn noop_fold_item < T : Folder > ( i : & Item ,
691721 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 {
692728 let id = folder. new_id ( i. id ) ; // Needs to be first, for ast_map.
693729 let node = folder. fold_item_underscore ( & i. node ) ;
694730 let ident = match node {
@@ -699,14 +735,14 @@ pub fn noop_fold_item<T: Folder>(i: &Item,
699735 _ => i. ident
700736 } ;
701737
702- SmallVector :: one ( box ( GC ) Item {
738+ Item {
703739 id : id,
704740 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 ( ) ,
706742 node : node,
707743 vis : i. vis ,
708744 span : folder. new_span ( i. span )
709- } )
745+ }
710746}
711747
712748pub fn noop_fold_foreign_item < T : Folder > ( ni : & ForeignItem ,
@@ -715,7 +751,7 @@ pub fn noop_fold_foreign_item<T: Folder>(ni: &ForeignItem,
715751 box ( GC ) ForeignItem {
716752 id : id,
717753 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 ( ) ,
719755 node : match ni. node {
720756 ForeignItemFn ( ref fdec, ref generics) => {
721757 ForeignItemFn ( P ( FnDecl {
@@ -739,7 +775,7 @@ pub fn noop_fold_method<T: Folder>(m: &Method, folder: &mut T) -> Gc<Method> {
739775 box ( GC ) Method {
740776 id : id,
741777 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 ( ) ,
743779 generics : fold_generics ( & m. generics , folder) ,
744780 explicit_self : folder. fold_explicit_self ( & m. explicit_self ) ,
745781 fn_style : m. fn_style ,
0 commit comments