Skip to content

Commit 4b46c70

Browse files
committed
hygiene for match-bound vars now implemented
Closes #9384
1 parent 7bad96e commit 4b46c70

File tree

1 file changed

+33
-24
lines changed

1 file changed

+33
-24
lines changed

src/libsyntax/ext/expand.rs

Lines changed: 33 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -608,7 +608,7 @@ fn expand_non_macro_stmt(s: &Stmt, fld: &mut MacroExpander)
608608
span: span,
609609
source: source,
610610
} = **local;
611-
// expand the pat (it might contain exprs... #:(o)>
611+
// expand the pat (it might contain macro uses):
612612
let expanded_pat = fld.fold_pat(pat);
613613
// find the pat_idents in the pattern:
614614
// oh dear heaven... this is going to include the enum
@@ -618,11 +618,11 @@ fn expand_non_macro_stmt(s: &Stmt, fld: &mut MacroExpander)
618618
let idents = pattern_bindings(expanded_pat);
619619
let mut new_pending_renames =
620620
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):
621623
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};
626626
rename_fld.fold_pat(expanded_pat)
627627
};
628628
// add them to the existing pending renames:
@@ -655,31 +655,38 @@ fn expand_non_macro_stmt(s: &Stmt, fld: &mut MacroExpander)
655655
}
656656

657657
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 {
659661
fail!("encountered match arm with 0 patterns");
660662
}
661663
// all of the pats must have the same set of bindings, so use the
662664
// 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);
664666
// code duplicated from 'let', above. Perhaps this can be lifted
665667
// 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));
678685
ast::Arm {
679686
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,
683690
}
684691
}
685692

@@ -851,6 +858,8 @@ fn expand_pat(p: Gc<ast::Pat>, fld: &mut MacroExpander) -> Gc<ast::Pat> {
851858
}
852859

853860
// 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)
854863
pub struct IdentRenamer<'a> {
855864
renames: &'a mut RenameList,
856865
}
@@ -1335,8 +1344,8 @@ mod test {
13351344
invalid_name);
13361345
if !(varref_name==binding_name) {
13371346
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));
13401349
mtwt::with_sctable(|x| mtwt::display_sctable(x));
13411350
}
13421351
assert_eq!(varref_name,binding_name);

0 commit comments

Comments
 (0)