diff options
| author | bors <bors@rust-lang.org> | 2014-02-23 15:37:05 -0800 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2014-02-23 15:37:05 -0800 |
| commit | 329fcd48e508ebe41e6d2425c0f54b2210af401d (patch) | |
| tree | b5297ad96ec683968e1b5dee486710be4a7c8ab3 /src/libsyntax/ext | |
| parent | cbed3321f5bbe4375819dd82193bd4299fabafb9 (diff) | |
| parent | 386db05df8aa8349857ad6f5486db0bdcc79f3cd (diff) | |
| download | rust-329fcd48e508ebe41e6d2425c0f54b2210af401d.tar.gz rust-329fcd48e508ebe41e6d2425c0f54b2210af401d.zip | |
auto merge of #12338 : edwardw/rust/hygienic-break-continue, r=cmr
Makes labelled loops hygiene by performing renaming of the labels defined in e.g. `'x: loop { ... }` and then used in break and continue statements within loop body so that they act hygienically when used with macros.
Closes #12262.
Diffstat (limited to 'src/libsyntax/ext')
| -rw-r--r-- | src/libsyntax/ext/expand.rs | 31 | ||||
| -rw-r--r-- | src/libsyntax/ext/tt/macro_parser.rs | 5 |
2 files changed, 32 insertions, 4 deletions
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 1e0bfb0d3e9..b49f9fb3a38 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -139,6 +139,8 @@ pub fn expand_expr(e: @ast::Expr, fld: &mut MacroExpander) -> @ast::Expr { // Expand any interior macros etc. // NB: we don't fold pats yet. Curious. let src_expr = fld.fold_expr(src_expr).clone(); + // Rename label before expansion. + let (opt_ident, src_loop_block) = rename_loop_label(opt_ident, src_loop_block, fld); let src_loop_block = fld.fold_block(src_loop_block); let span = e.span; @@ -165,8 +167,7 @@ pub fn expand_expr(e: @ast::Expr, fld: &mut MacroExpander) -> @ast::Expr { // `None => break ['<ident>];` let none_arm = { - // FIXME #6993: this map goes away: - let break_expr = fld.cx.expr(span, ast::ExprBreak(opt_ident.map(|x| x.name))); + let break_expr = fld.cx.expr(span, ast::ExprBreak(opt_ident)); let none_pat = fld.cx.pat_ident(span, none_ident); fld.cx.arm(span, ~[none_pat], break_expr) }; @@ -199,10 +200,36 @@ pub fn expand_expr(e: @ast::Expr, fld: &mut MacroExpander) -> @ast::Expr { fld.cx.expr_match(span, discrim, ~[arm]) } + ast::ExprLoop(loop_block, opt_ident) => { + let (opt_ident, loop_block) = + rename_loop_label(opt_ident, loop_block, fld); + let loop_block = fld.fold_block(loop_block); + fld.cx.expr(e.span, ast::ExprLoop(loop_block, opt_ident)) + } + _ => noop_fold_expr(e, fld) } } +// Rename loop label and its all occurrences inside the loop body +fn rename_loop_label(opt_ident: Option<Ident>, + loop_block: P<Block>, + fld: &mut MacroExpander) -> (Option<Ident>, P<Block>) { + match opt_ident { + Some(label) => { + // Generate fresh label and add to the existing pending renames + let new_label = fresh_name(&label); + let rename = (label, new_label); + fld.extsbox.info().pending_renames.push(rename); + let mut pending_renames = ~[rename]; + let mut rename_fld = renames_to_fold(&mut pending_renames); + (Some(rename_fld.fold_ident(label)), + rename_fld.fold_block(loop_block)) + } + None => (None, loop_block) + } +} + // eval $e with a new exts frame: macro_rules! with_exts_frame ( ($extsboxexpr:expr,$macros_escape:expr,$e:expr) => diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index 456533de5e9..edd875a57a7 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -218,8 +218,9 @@ pub fn parse_or_else<R: Reader>(sess: @ParseSess, // perform a token equality check, ignoring syntax context (that is, an unhygienic comparison) pub fn token_name_eq(t1 : &Token, t2 : &Token) -> bool { match (t1,t2) { - (&token::IDENT(id1,_),&token::IDENT(id2,_)) => - id1.name == id2.name, + (&token::IDENT(id1,_),&token::IDENT(id2,_)) + | (&token::LIFETIME(id1),&token::LIFETIME(id2)) => + id1.name == id2.name, _ => *t1 == *t2 } } |
