@@ -82,8 +82,18 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
8282 ast:: ExprWhileLet ( pat, expr, body, opt_ident) => {
8383 let pat = fld. fold_pat ( pat) ;
8484 let expr = fld. fold_expr ( expr) ;
85- let ( body, opt_ident) = expand_loop_block ( body, opt_ident, fld) ;
86- fld. cx . expr ( span, ast:: ExprWhileLet ( pat, expr, body, opt_ident) )
85+
86+ // Hygienic renaming of the body.
87+ let ( ( body, opt_ident) , mut rewritten_pats) =
88+ rename_in_scope ( vec ! [ pat] ,
89+ fld,
90+ ( body, opt_ident) ,
91+ |rename_fld, fld, ( body, opt_ident) | {
92+ expand_loop_block ( rename_fld. fold_block ( body) , opt_ident, fld)
93+ } ) ;
94+ assert ! ( rewritten_pats. len( ) == 1 ) ;
95+
96+ fld. cx . expr ( span, ast:: ExprWhileLet ( rewritten_pats. remove ( 0 ) , expr, body, opt_ident) )
8797 }
8898
8999 ast:: ExprLoop ( loop_block, opt_ident) => {
@@ -93,9 +103,37 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
93103
94104 ast:: ExprForLoop ( pat, head, body, opt_ident) => {
95105 let pat = fld. fold_pat ( pat) ;
106+
107+ // Hygienic renaming of the for loop body (for loop binds its pattern).
108+ let ( ( body, opt_ident) , mut rewritten_pats) =
109+ rename_in_scope ( vec ! [ pat] ,
110+ fld,
111+ ( body, opt_ident) ,
112+ |rename_fld, fld, ( body, opt_ident) | {
113+ expand_loop_block ( rename_fld. fold_block ( body) , opt_ident, fld)
114+ } ) ;
115+ assert ! ( rewritten_pats. len( ) == 1 ) ;
116+
96117 let head = fld. fold_expr ( head) ;
97- let ( body, opt_ident) = expand_loop_block ( body, opt_ident, fld) ;
98- fld. cx . expr ( span, ast:: ExprForLoop ( pat, head, body, opt_ident) )
118+ fld. cx . expr ( span, ast:: ExprForLoop ( rewritten_pats. remove ( 0 ) , head, body, opt_ident) )
119+ }
120+
121+ ast:: ExprIfLet ( pat, sub_expr, body, else_opt) => {
122+ let pat = fld. fold_pat ( pat) ;
123+
124+ // Hygienic renaming of the body.
125+ let ( body, mut rewritten_pats) =
126+ rename_in_scope ( vec ! [ pat] ,
127+ fld,
128+ body,
129+ |rename_fld, fld, body| {
130+ fld. fold_block ( rename_fld. fold_block ( body) )
131+ } ) ;
132+ assert ! ( rewritten_pats. len( ) == 1 ) ;
133+
134+ let else_opt = else_opt. map ( |else_opt| fld. fold_expr ( else_opt) ) ;
135+ let sub_expr = fld. fold_expr ( sub_expr) ;
136+ fld. cx . expr ( span, ast:: ExprIfLet ( rewritten_pats. remove ( 0 ) , sub_expr, body, else_opt) )
99137 }
100138
101139 ast:: ExprClosure ( capture_clause, fn_decl, block) => {
@@ -569,18 +607,18 @@ fn expand_arm(arm: ast::Arm, fld: &mut MacroExpander) -> ast::Arm {
569607 if expanded_pats. is_empty ( ) {
570608 panic ! ( "encountered match arm with 0 patterns" ) ;
571609 }
572- // all of the pats must have the same set of bindings, so use the
573- // first one to extract them and generate new names:
574- let idents = pattern_bindings ( & * expanded_pats[ 0 ] ) ;
575- let new_renames = idents. into_iter ( ) . map ( |id| ( id, fresh_name ( id) ) ) . collect ( ) ;
576- // apply the renaming, but only to the PatIdents:
577- let mut rename_pats_fld = PatIdentRenamer { renames : & new_renames} ;
578- let rewritten_pats = expanded_pats. move_map ( |pat| rename_pats_fld. fold_pat ( pat) ) ;
610+
579611 // apply renaming and then expansion to the guard and the body:
580- let mut rename_fld = IdentRenamer { renames : & new_renames} ;
581- let rewritten_guard =
582- arm. guard . map ( |g| fld. fold_expr ( rename_fld. fold_expr ( g) ) ) ;
583- let rewritten_body = fld. fold_expr ( rename_fld. fold_expr ( arm. body ) ) ;
612+ let ( ( rewritten_guard, rewritten_body) , rewritten_pats) =
613+ rename_in_scope ( expanded_pats,
614+ fld,
615+ ( arm. guard , arm. body ) ,
616+ |rename_fld, fld, ( ag, ab) |{
617+ let rewritten_guard = ag. map ( |g| fld. fold_expr ( rename_fld. fold_expr ( g) ) ) ;
618+ let rewritten_body = fld. fold_expr ( rename_fld. fold_expr ( ab) ) ;
619+ ( rewritten_guard, rewritten_body)
620+ } ) ;
621+
584622 ast:: Arm {
585623 attrs : fold:: fold_attrs ( arm. attrs , fld) ,
586624 pats : rewritten_pats,
@@ -589,6 +627,25 @@ fn expand_arm(arm: ast::Arm, fld: &mut MacroExpander) -> ast::Arm {
589627 }
590628}
591629
630+ fn rename_in_scope < X , F > ( pats : Vec < P < ast:: Pat > > ,
631+ fld : & mut MacroExpander ,
632+ x : X ,
633+ f : F )
634+ -> ( X , Vec < P < ast:: Pat > > )
635+ where F : Fn ( & mut IdentRenamer , & mut MacroExpander , X ) -> X
636+ {
637+ // all of the pats must have the same set of bindings, so use the
638+ // first one to extract them and generate new names:
639+ let idents = pattern_bindings ( & * pats[ 0 ] ) ;
640+ let new_renames = idents. into_iter ( ) . map ( |id| ( id, fresh_name ( id) ) ) . collect ( ) ;
641+ // apply the renaming, but only to the PatIdents:
642+ let mut rename_pats_fld = PatIdentRenamer { renames : & new_renames} ;
643+ let rewritten_pats = pats. move_map ( |pat| rename_pats_fld. fold_pat ( pat) ) ;
644+
645+ let mut rename_fld = IdentRenamer { renames : & new_renames } ;
646+ ( f ( & mut rename_fld, fld, x) , rewritten_pats)
647+ }
648+
592649/// A visitor that extracts the PatIdent (binding) paths
593650/// from a given thingy and puts them in a mutable
594651/// array
0 commit comments