@@ -608,7 +608,7 @@ fn expand_non_macro_stmt(s: &Stmt, fld: &mut MacroExpander)
608
608
span : span,
609
609
source : source,
610
610
} = * * local;
611
- // expand the pat (it might contain exprs... #:(o)>
611
+ // expand the pat (it might contain macro uses):
612
612
let expanded_pat = fld. fold_pat ( pat) ;
613
613
// find the pat_idents in the pattern:
614
614
// oh dear heaven... this is going to include the enum
@@ -618,11 +618,11 @@ fn expand_non_macro_stmt(s: &Stmt, fld: &mut MacroExpander)
618
618
let idents = pattern_bindings ( expanded_pat) ;
619
619
let mut new_pending_renames =
620
620
idents. iter ( ) . map ( |ident| ( * ident, fresh_name ( ident) ) ) . collect ( ) ;
621
+ // rewrite the pattern using the new names (the old
622
+ // ones have already been applied):
621
623
let rewritten_pat = {
622
- let mut rename_fld =
623
- IdentRenamer { renames : & mut new_pending_renames} ;
624
- // rewrite the pattern using the new names (the old
625
- // ones have already been applied):
624
+ // nested binding to allow borrow to expire:
625
+ let mut rename_fld = IdentRenamer { renames : & mut new_pending_renames} ;
626
626
rename_fld. fold_pat ( expanded_pat)
627
627
} ;
628
628
// add them to the existing pending renames:
@@ -655,31 +655,38 @@ fn expand_non_macro_stmt(s: &Stmt, fld: &mut MacroExpander)
655
655
}
656
656
657
657
fn expand_arm ( arm : & ast:: Arm , fld : & mut MacroExpander ) -> ast:: Arm {
658
- if arm. pats . len ( ) == 0 {
658
+ // expand pats... they might contain macro uses:
659
+ let expanded_pats : Vec < Gc < ast:: Pat > > = arm. pats . iter ( ) . map ( |pat| fld. fold_pat ( * pat) ) . collect ( ) ;
660
+ if expanded_pats. len ( ) == 0 {
659
661
fail ! ( "encountered match arm with 0 patterns" ) ;
660
662
}
661
663
// all of the pats must have the same set of bindings, so use the
662
664
// first one to extract them and generate new names:
663
- let first_pat = arm . pats . get ( 0 ) ;
665
+ let first_pat = expanded_pats . get ( 0 ) ;
664
666
// code duplicated from 'let', above. Perhaps this can be lifted
665
667
// into a separate function:
666
- let expanded_pat = fld. fold_pat ( * first_pat) ;
667
- let mut new_pending_renames = Vec :: new ( ) ;
668
- for ident in pattern_bindings ( expanded_pat) . iter ( ) {
669
- let new_name = fresh_name ( ident) ;
670
- new_pending_renames. push ( ( * ident, new_name) ) ;
671
- }
672
- let rewritten_pat = {
673
- let mut rename_fld = IdentRenamer { renames : & mut new_pending_renames} ;
674
- // rewrite the pattern using the new names (the old
675
- // ones have already been applied):
676
- rename_fld. fold_pat ( expanded_pat)
677
- } ;
668
+ let idents = pattern_bindings ( * first_pat) ;
669
+ let mut new_pending_renames =
670
+ idents. iter ( ) . map ( |id| ( * id, fresh_name ( id) ) ) . collect ( ) ;
671
+ // rewrite all of the patterns using the new names (the old
672
+ // ones have already been applied). Note that we depend here
673
+ // on the guarantee that after expansion, there can't be any
674
+ // Path expressions (a.k.a. varrefs) left in the pattern. If
675
+ // this were false, we'd need to apply this renaming only to
676
+ // the bindings, and not to the varrefs, using a more targeted
677
+ // fold-er.
678
+ let mut rename_fld = IdentRenamer { renames : & mut new_pending_renames} ;
679
+ let rewritten_pats =
680
+ expanded_pats. iter ( ) . map ( |pat| rename_fld. fold_pat ( * pat) ) . collect ( ) ;
681
+ // apply renaming and then expansion to the guard and the body:
682
+ let rewritten_guard =
683
+ arm. guard . map ( |g| fld. fold_expr ( rename_fld. fold_expr ( g) ) ) ;
684
+ let rewritten_body = fld. fold_expr ( rename_fld. fold_expr ( arm. body ) ) ;
678
685
ast:: Arm {
679
686
attrs : arm. attrs . iter ( ) . map ( |x| fld. fold_attribute ( * x) ) . collect ( ) ,
680
- pats : arm . pats . iter ( ) . map ( |x| fld . fold_pat ( * x ) ) . collect ( ) ,
681
- guard : arm . guard . map ( |x| fld . fold_expr ( x ) ) ,
682
- body : fld . fold_expr ( arm . body ) ,
687
+ pats : rewritten_pats ,
688
+ guard : rewritten_guard ,
689
+ body : rewritten_body ,
683
690
}
684
691
}
685
692
@@ -851,6 +858,8 @@ fn expand_pat(p: Gc<ast::Pat>, fld: &mut MacroExpander) -> Gc<ast::Pat> {
851
858
}
852
859
853
860
// a tree-folder that applies every rename in its (mutable) list
861
+ // to every identifier, including both bindings and varrefs
862
+ // (and lots of things that will turn out to be neither)
854
863
pub struct IdentRenamer < ' a > {
855
864
renames : & ' a mut RenameList ,
856
865
}
@@ -1335,8 +1344,8 @@ mod test {
1335
1344
invalid_name) ;
1336
1345
if !( varref_name==binding_name) {
1337
1346
println ! ( "uh oh, should match but doesn't:" ) ;
1338
- println ! ( "varref: {:?}" , varref) ;
1339
- println ! ( "binding: {:?}" , * bindings. get( binding_idx) ) ;
1347
+ println ! ( "varref #{:?}: {:?}" , idx , varref) ;
1348
+ println ! ( "binding #{:?}: {:?}" , binding_idx , * bindings. get( binding_idx) ) ;
1340
1349
mtwt:: with_sctable ( |x| mtwt:: display_sctable ( x) ) ;
1341
1350
}
1342
1351
assert_eq ! ( varref_name, binding_name) ;
0 commit comments