@@ -82,8 +82,18 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
82
82
ast:: ExprWhileLet ( pat, expr, body, opt_ident) => {
83
83
let pat = fld. fold_pat ( pat) ;
84
84
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) )
87
97
}
88
98
89
99
ast:: ExprLoop ( loop_block, opt_ident) => {
@@ -93,9 +103,37 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
93
103
94
104
ast:: ExprForLoop ( pat, head, body, opt_ident) => {
95
105
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
+
96
117
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) )
99
137
}
100
138
101
139
ast:: ExprClosure ( capture_clause, fn_decl, block) => {
@@ -569,18 +607,18 @@ fn expand_arm(arm: ast::Arm, fld: &mut MacroExpander) -> ast::Arm {
569
607
if expanded_pats. is_empty ( ) {
570
608
panic ! ( "encountered match arm with 0 patterns" ) ;
571
609
}
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
+
579
611
// 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
+
584
622
ast:: Arm {
585
623
attrs : fold:: fold_attrs ( arm. attrs , fld) ,
586
624
pats : rewritten_pats,
@@ -589,6 +627,25 @@ fn expand_arm(arm: ast::Arm, fld: &mut MacroExpander) -> ast::Arm {
589
627
}
590
628
}
591
629
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
+
592
649
/// A visitor that extracts the PatIdent (binding) paths
593
650
/// from a given thingy and puts them in a mutable
594
651
/// array
0 commit comments