@@ -386,6 +386,19 @@ fn expand_item_modifiers(mut it: Gc<ast::Item>, fld: &mut MacroExpander)
386
386
expand_item_modifiers ( it, fld)
387
387
}
388
388
389
+ /// Expand item_underscore
390
+ fn expand_item_underscore ( item : & ast:: Item_ , fld : & mut MacroExpander ) -> ast:: Item_ {
391
+ match * item {
392
+ ast:: ItemFn ( decl, fn_style, abi, ref generics, body) => {
393
+ let ( rewritten_fn_decl, rewritten_body)
394
+ = expand_and_rename_fn_decl_and_block ( decl, body, fld) ;
395
+ let expanded_generics = fold:: fold_generics ( generics, fld) ;
396
+ ast:: ItemFn ( rewritten_fn_decl, fn_style, abi, expanded_generics, rewritten_body)
397
+ }
398
+ _ => noop_fold_item_underscore ( & * item, fld)
399
+ }
400
+ }
401
+
389
402
// does this attribute list contain "macro_escape" ?
390
403
fn contains_macro_escape ( attrs : & [ ast:: Attribute ] ) -> bool {
391
404
attr:: contains_name ( attrs, "macro_escape" )
@@ -656,6 +669,7 @@ fn expand_non_macro_stmt(s: &Stmt, fld: &mut MacroExpander)
656
669
}
657
670
}
658
671
672
+ // expand the arm of a 'match', renaming for macro hygiene
659
673
fn expand_arm ( arm : & ast:: Arm , fld : & mut MacroExpander ) -> ast:: Arm {
660
674
// expand pats... they might contain macro uses:
661
675
let expanded_pats : Vec < Gc < ast:: Pat > > = arm. pats . iter ( ) . map ( |pat| fld. fold_pat ( * pat) ) . collect ( ) ;
@@ -665,17 +679,15 @@ fn expand_arm(arm: &ast::Arm, fld: &mut MacroExpander) -> ast::Arm {
665
679
// all of the pats must have the same set of bindings, so use the
666
680
// first one to extract them and generate new names:
667
681
let first_pat = expanded_pats. get ( 0 ) ;
668
- // code duplicated from 'let', above. Perhaps this can be lifted
669
- // into a separate function:
670
682
let idents = pattern_bindings ( * first_pat) ;
671
- let new_pending_renames =
683
+ let new_renames =
672
684
idents. iter ( ) . map ( |id| ( * id, fresh_name ( id) ) ) . collect ( ) ;
673
685
// apply the renaming, but only to the PatIdents:
674
- let mut rename_pats_fld = PatIdentRenamer { renames : & new_pending_renames } ;
686
+ let mut rename_pats_fld = PatIdentRenamer { renames : & new_renames } ;
675
687
let rewritten_pats =
676
688
expanded_pats. iter ( ) . map ( |pat| rename_pats_fld. fold_pat ( * pat) ) . collect ( ) ;
677
689
// apply renaming and then expansion to the guard and the body:
678
- let mut rename_fld = IdentRenamer { renames : & new_pending_renames } ;
690
+ let mut rename_fld = IdentRenamer { renames : & new_renames } ;
679
691
let rewritten_guard =
680
692
arm. guard . map ( |g| fld. fold_expr ( rename_fld. fold_expr ( g) ) ) ;
681
693
let rewritten_body = fld. fold_expr ( rename_fld. fold_expr ( arm. body ) ) ;
@@ -687,8 +699,6 @@ fn expand_arm(arm: &ast::Arm, fld: &mut MacroExpander) -> ast::Arm {
687
699
}
688
700
}
689
701
690
-
691
-
692
702
/// A visitor that extracts the PatIdent (binding) paths
693
703
/// from a given thingy and puts them in a mutable
694
704
/// array
@@ -721,6 +731,15 @@ fn pattern_bindings(pat : &ast::Pat) -> Vec<ast::Ident> {
721
731
name_finder. ident_accumulator
722
732
}
723
733
734
+ /// find the PatIdent paths in a
735
+ fn fn_decl_arg_bindings ( fn_decl : & ast:: FnDecl ) -> Vec < ast:: Ident > {
736
+ let mut pat_idents = PatIdentFinder { ident_accumulator : Vec :: new ( ) } ;
737
+ for arg in fn_decl. inputs . iter ( ) {
738
+ pat_idents. visit_pat ( arg. pat , ( ) ) ;
739
+ }
740
+ pat_idents. ident_accumulator
741
+ }
742
+
724
743
// expand a block. pushes a new exts_frame, then calls expand_block_elts
725
744
fn expand_block ( blk : & Block , fld : & mut MacroExpander ) -> P < Block > {
726
745
// see note below about treatment of exts table
@@ -882,6 +901,25 @@ impl<'a> Folder for PatIdentRenamer<'a> {
882
901
}
883
902
}
884
903
904
+ /// Given a fn_decl and a block and a MacroExpander, expand the fn_decl, then use the
905
+ /// PatIdents in its arguments to perform renaming in the FnDecl and
906
+ /// the block, returning both the new FnDecl and the new Block.
907
+ fn expand_and_rename_fn_decl_and_block ( fn_decl : & ast:: FnDecl , block : Gc < ast:: Block > ,
908
+ fld : & mut MacroExpander )
909
+ -> ( Gc < ast:: FnDecl > , Gc < ast:: Block > ) {
910
+ let expanded_decl = fld. fold_fn_decl ( fn_decl) ;
911
+ let idents = fn_decl_arg_bindings ( expanded_decl) ;
912
+ let renames =
913
+ idents. iter ( ) . map ( |id : & ast:: Ident | ( * id, fresh_name ( id) ) ) . collect ( ) ;
914
+ // first, a renamer for the PatIdents, for the fn_decl:
915
+ let mut rename_pat_fld = PatIdentRenamer { renames : & renames} ;
916
+ let rewritten_fn_decl = rename_pat_fld. fold_fn_decl ( expanded_decl) ;
917
+ // now, a renamer for *all* idents, for the body:
918
+ let mut rename_fld = IdentRenamer { renames : & renames} ;
919
+ let rewritten_body = fld. fold_block ( rename_fld. fold_block ( block) ) ;
920
+ ( rewritten_fn_decl, rewritten_body)
921
+ }
922
+
885
923
/// A tree-folder that performs macro expansion
886
924
pub struct MacroExpander < ' a , ' b > {
887
925
pub extsbox : SyntaxEnv ,
@@ -901,6 +939,10 @@ impl<'a, 'b> Folder for MacroExpander<'a, 'b> {
901
939
expand_item ( item, self )
902
940
}
903
941
942
+ fn fold_item_underscore ( & mut self , item : & ast:: Item_ ) -> ast:: Item_ {
943
+ expand_item_underscore ( item, self )
944
+ }
945
+
904
946
fn fold_stmt ( & mut self , stmt : & ast:: Stmt ) -> SmallVector < Gc < ast:: Stmt > > {
905
947
expand_stmt ( stmt, self )
906
948
}
0 commit comments