diff options
| author | bors <bors@rust-lang.org> | 2015-10-09 08:53:45 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2015-10-09 08:53:45 +0000 |
| commit | c14609035d1780d4a8a3ca7b4fdf93046299ab4a (patch) | |
| tree | e2cd7e864e6d87be5ef3f9c044d0d2a510c6c96e /src/libsyntax | |
| parent | 7cea9a714130b7b85caf91c2a1d126539f41c383 (diff) | |
| parent | a62a529eea3e00b3ce9e659daa4235add2cb8551 (diff) | |
| download | rust-c14609035d1780d4a8a3ca7b4fdf93046299ab4a.tar.gz rust-c14609035d1780d4a8a3ca7b4fdf93046299ab4a.zip | |
Auto merge of #28857 - nrc:lowering, r=nikomatsakis
r? @nikomatsakis
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/ast.rs | 18 | ||||
| -rw-r--r-- | src/libsyntax/codemap.rs | 22 | ||||
| -rw-r--r-- | src/libsyntax/config.rs | 4 | ||||
| -rw-r--r-- | src/libsyntax/diagnostic.rs | 1 | ||||
| -rw-r--r-- | src/libsyntax/ext/base.rs | 7 | ||||
| -rw-r--r-- | src/libsyntax/ext/build.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax/ext/expand.rs | 466 | ||||
| -rw-r--r-- | src/libsyntax/feature_gate.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax/fold.rs | 5 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 4 | ||||
| -rw-r--r-- | src/libsyntax/print/pprust.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax/visit.rs | 2 |
12 files changed, 91 insertions, 444 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index ce00505b0b4..34b99ab8cce 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -375,6 +375,11 @@ pub const CRATE_NODE_ID: NodeId = 0; /// small, positive ids. pub const DUMMY_NODE_ID: NodeId = !0; +pub trait NodeIdAssigner { + fn next_node_id(&self) -> NodeId; + fn peek_node_id(&self) -> NodeId; +} + /// The AST represents all type param bounds as types. /// typeck::collect::compute_bounds matches these against /// the "special" built-in traits (see middle::lang_items) and @@ -850,9 +855,8 @@ pub enum Expr_ { /// /// `'label: loop { block }` ExprLoop(P<Block>, Option<Ident>), - /// A `match` block, with a source that indicates whether or not it is - /// the result of a desugaring, and if so, which kind. - ExprMatch(P<Expr>, Vec<Arm>, MatchSource), + /// A `match` block. + ExprMatch(P<Expr>, Vec<Arm>), /// A closure (for example, `move |a, b, c| {a + b + c}`) ExprClosure(CaptureClause, P<FnDecl>, P<Block>), /// A block (`{ ... }`) @@ -932,14 +936,6 @@ pub struct QSelf { } #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] -pub enum MatchSource { - Normal, - IfLetDesugar { contains_else_clause: bool }, - WhileLetDesugar, - ForLoopDesugar, -} - -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] pub enum CaptureClause { CaptureByValue, CaptureByRef, diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index aa4dd1d53c5..a73fd4534c9 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -29,7 +29,6 @@ use std::io::{self, Read}; use serialize::{Encodable, Decodable, Encoder, Decoder}; -use parse::token::intern; use ast::Name; // _____________________________________________________________________________ @@ -269,28 +268,8 @@ pub enum ExpnFormat { MacroAttribute(Name), /// e.g. `format!()` MacroBang(Name), - /// Syntax sugar expansion performed by the compiler (libsyntax::expand). - CompilerExpansion(CompilerExpansionFormat), } -#[derive(Clone, Copy, Hash, Debug, PartialEq, Eq)] -pub enum CompilerExpansionFormat { - IfLet, - PlacementIn, - WhileLet, - ForLoop, -} - -impl CompilerExpansionFormat { - pub fn name(self) -> &'static str { - match self { - CompilerExpansionFormat::IfLet => "if let expansion", - CompilerExpansionFormat::PlacementIn => "placement-in expansion", - CompilerExpansionFormat::WhileLet => "while let expansion", - CompilerExpansionFormat::ForLoop => "for loop expansion", - } - } -} #[derive(Clone, Hash, Debug)] pub struct NameAndSpan { /// The format with which the macro was invoked. @@ -310,7 +289,6 @@ impl NameAndSpan { match self.format { ExpnFormat::MacroAttribute(s) => s, ExpnFormat::MacroBang(s) => s, - ExpnFormat::CompilerExpansion(ce) => intern(ce.name()), } } } diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs index 889a0d7e440..2d266be3242 100644 --- a/src/libsyntax/config.rs +++ b/src/libsyntax/config.rs @@ -225,10 +225,10 @@ fn fold_expr<F>(cx: &mut Context<F>, expr: P<ast::Expr>) -> P<ast::Expr> where fold::noop_fold_expr(ast::Expr { id: id, node: match node { - ast::ExprMatch(m, arms, source) => { + ast::ExprMatch(m, arms) => { ast::ExprMatch(m, arms.into_iter() .filter(|a| (cx.in_cfg)(&a.attrs)) - .collect(), source) + .collect()) } _ => node }, diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs index 6b4a5538501..2a8cdf138b0 100644 --- a/src/libsyntax/diagnostic.rs +++ b/src/libsyntax/diagnostic.rs @@ -737,7 +737,6 @@ impl EmitterWriter { let (pre, post) = match ei.callee.format { codemap::MacroAttribute(..) => ("#[", "]"), codemap::MacroBang(..) => ("", "!"), - codemap::CompilerExpansion(..) => ("", ""), }; // Don't print recursive invocations if ei.call_site != last_span { diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 7459f8b8f24..6196062b08a 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -13,7 +13,7 @@ pub use self::SyntaxExtension::*; use ast; use ast::Name; use codemap; -use codemap::{CodeMap, Span, ExpnId, ExpnInfo, NO_EXPANSION, CompilerExpansion}; +use codemap::{CodeMap, Span, ExpnId, ExpnInfo, NO_EXPANSION}; use ext; use ext::expand; use ext::tt::macro_rules; @@ -651,10 +651,7 @@ impl<'a> ExtCtxt<'a> { return None; } expn_id = i.call_site.expn_id; - match i.callee.format { - CompilerExpansion(..) => (), - _ => last_macro = Some(i.call_site), - } + last_macro = Some(i.call_site); return Some(()); }) }).is_none() { diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index a20080dcbf0..efea85f9162 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -868,7 +868,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { } fn expr_match(&self, span: Span, arg: P<ast::Expr>, arms: Vec<ast::Arm>) -> P<Expr> { - self.expr(span, ast::ExprMatch(arg, arms, ast::MatchSource::Normal)) + self.expr(span, ast::ExprMatch(arg, arms)) } fn expr_if(&self, span: Span, cond: P<ast::Expr>, diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index b15c51490a1..b1b4605d5ec 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -20,53 +20,20 @@ use attr; use attr::AttrMetaMethods; use codemap; use codemap::{Span, Spanned, ExpnInfo, NameAndSpan, MacroBang, MacroAttribute}; -use codemap::{CompilerExpansion, CompilerExpansionFormat}; use ext::base::*; use feature_gate::{self, Features, GatedCfg}; use fold; use fold::*; use parse; use parse::token::{fresh_mark, fresh_name, intern}; -use parse::token; use ptr::P; use util::small_vector::SmallVector; use visit; use visit::Visitor; use std_inject; -// Given suffix ["b","c","d"], returns path `::std::b::c::d` when -// `fld.cx.use_std`, and `::core::b::c::d` otherwise. -fn mk_core_path(fld: &mut MacroExpander, - span: Span, - suffix: &[&'static str]) -> ast::Path { - let idents = fld.cx.std_path(suffix); - fld.cx.path_global(span, idents) -} pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> { - fn push_compiler_expansion(fld: &mut MacroExpander, span: Span, - expansion_type: CompilerExpansionFormat) { - fld.cx.bt_push(ExpnInfo { - call_site: span, - callee: NameAndSpan { - format: CompilerExpansion(expansion_type), - - // This does *not* mean code generated after - // `push_compiler_expansion` is automatically exempt - // from stability lints; must also tag such code with - // an appropriate span from `fld.cx.backtrace()`. - allow_internal_unstable: true, - - span: None, - }, - }); - } - - // Sets the expn_id so that we can use unstable methods. - fn allow_unstable(fld: &mut MacroExpander, span: Span) -> Span { - Span { expn_id: fld.cx.backtrace(), ..span } - } - let expr_span = e.span; return e.and_then(|ast::Expr {id, node, span}| match node { @@ -94,265 +61,39 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> { }) } - // Desugar ExprInPlace: `in PLACE { EXPR }` ast::ExprInPlace(placer, value_expr) => { - // to: - // - // let p = PLACE; - // let mut place = Placer::make_place(p); - // let raw_place = Place::pointer(&mut place); - // push_unsafe!({ - // std::intrinsics::move_val_init(raw_place, pop_unsafe!( EXPR )); - // InPlace::finalize(place) - // }) - // Ensure feature-gate is enabled feature_gate::check_for_placement_in( fld.cx.ecfg.features, &fld.cx.parse_sess.span_diagnostic, expr_span); - push_compiler_expansion(fld, expr_span, CompilerExpansionFormat::PlacementIn); - - let value_span = value_expr.span; - let placer_span = placer.span; - - let placer_expr = fld.fold_expr(placer); + let placer = fld.fold_expr(placer); let value_expr = fld.fold_expr(value_expr); - - let placer_ident = token::gensym_ident("placer"); - let agent_ident = token::gensym_ident("place"); - let p_ptr_ident = token::gensym_ident("p_ptr"); - - let placer = fld.cx.expr_ident(span, placer_ident); - let agent = fld.cx.expr_ident(span, agent_ident); - let p_ptr = fld.cx.expr_ident(span, p_ptr_ident); - - let make_place = ["ops", "Placer", "make_place"]; - let place_pointer = ["ops", "Place", "pointer"]; - let move_val_init = ["intrinsics", "move_val_init"]; - let inplace_finalize = ["ops", "InPlace", "finalize"]; - - let make_call = |fld: &mut MacroExpander, p, args| { - // We feed in the `expr_span` because codemap's span_allows_unstable - // allows the call_site span to inherit the `allow_internal_unstable` - // setting. - let span_unstable = allow_unstable(fld, expr_span); - let path = mk_core_path(fld, span_unstable, p); - let path = fld.cx.expr_path(path); - let expr_span_unstable = allow_unstable(fld, span); - fld.cx.expr_call(expr_span_unstable, path, args) - }; - - let stmt_let = |fld: &mut MacroExpander, bind, expr| { - fld.cx.stmt_let(placer_span, false, bind, expr) - }; - let stmt_let_mut = |fld: &mut MacroExpander, bind, expr| { - fld.cx.stmt_let(placer_span, true, bind, expr) - }; - - // let placer = <placer_expr> ; - let s1 = stmt_let(fld, placer_ident, placer_expr); - - // let mut place = Placer::make_place(placer); - let s2 = { - let call = make_call(fld, &make_place, vec![placer]); - stmt_let_mut(fld, agent_ident, call) - }; - - // let p_ptr = Place::pointer(&mut place); - let s3 = { - let args = vec![fld.cx.expr_mut_addr_of(placer_span, agent.clone())]; - let call = make_call(fld, &place_pointer, args); - stmt_let(fld, p_ptr_ident, call) - }; - - // pop_unsafe!(EXPR)); - let pop_unsafe_expr = pop_unsafe_expr(fld.cx, value_expr, value_span); - - // push_unsafe!({ - // ptr::write(p_ptr, pop_unsafe!(<value_expr>)); - // InPlace::finalize(place) - // }) - let expr = { - let call_move_val_init = StmtSemi(make_call( - fld, &move_val_init, vec![p_ptr, pop_unsafe_expr]), ast::DUMMY_NODE_ID); - let call_move_val_init = codemap::respan(value_span, call_move_val_init); - - let call = make_call(fld, &inplace_finalize, vec![agent]); - Some(push_unsafe_expr(fld.cx, vec![P(call_move_val_init)], call, span)) - }; - - let block = fld.cx.block_all(span, vec![s1, s2, s3], expr); - let result = fld.cx.expr_block(block); - fld.cx.bt_pop(); - result + fld.cx.expr(span, ast::ExprInPlace(placer, value_expr)) } - // Issue #22181: - // Eventually a desugaring for `box EXPR` - // (similar to the desugaring above for `in PLACE BLOCK`) - // should go here, desugaring - // - // to: - // - // let mut place = BoxPlace::make_place(); - // let raw_place = Place::pointer(&mut place); - // let value = $value; - // unsafe { - // ::std::ptr::write(raw_place, value); - // Boxed::finalize(place) - // } - // - // But for now there are type-inference issues doing that. - ast::ExprWhile(cond, body, opt_ident) => { let cond = fld.fold_expr(cond); let (body, opt_ident) = expand_loop_block(body, opt_ident, fld); fld.cx.expr(span, ast::ExprWhile(cond, body, opt_ident)) } - // Desugar ExprWhileLet - // From: `[opt_ident]: while let <pat> = <expr> <body>` ast::ExprWhileLet(pat, expr, body, opt_ident) => { - // to: - // - // [opt_ident]: loop { - // match <expr> { - // <pat> => <body>, - // _ => break - // } - // } - - push_compiler_expansion(fld, span, CompilerExpansionFormat::WhileLet); - - // `<pat> => <body>` - let pat_arm = { - let body_expr = fld.cx.expr_block(body); - fld.cx.arm(pat.span, vec![pat], body_expr) - }; - - // `_ => break` - let break_arm = { - let pat_under = fld.cx.pat_wild(span); - let break_expr = fld.cx.expr_break(span); - fld.cx.arm(span, vec![pat_under], break_expr) - }; - - // `match <expr> { ... }` - let arms = vec![pat_arm, break_arm]; - let match_expr = fld.cx.expr(span, - ast::ExprMatch(expr, arms, ast::MatchSource::WhileLetDesugar)); - - // `[opt_ident]: loop { ... }` - let loop_block = fld.cx.block_expr(match_expr); - let (loop_block, opt_ident) = expand_loop_block(loop_block, opt_ident, fld); - let result = fld.cx.expr(span, ast::ExprLoop(loop_block, opt_ident)); - fld.cx.bt_pop(); - result - } - - // Desugar ExprIfLet - // From: `if let <pat> = <expr> <body> [<elseopt>]` - ast::ExprIfLet(pat, expr, body, mut elseopt) => { - // to: - // - // match <expr> { - // <pat> => <body>, - // [_ if <elseopt_if_cond> => <elseopt_if_body>,] - // _ => [<elseopt> | ()] - // } - - push_compiler_expansion(fld, span, CompilerExpansionFormat::IfLet); - - // `<pat> => <body>` - let pat_arm = { - let body_expr = fld.cx.expr_block(body); - fld.cx.arm(pat.span, vec![pat], body_expr) - }; - - // `[_ if <elseopt_if_cond> => <elseopt_if_body>,]` - let else_if_arms = { - let mut arms = vec![]; - loop { - let elseopt_continue = elseopt - .and_then(|els| els.and_then(|els| match els.node { - // else if - ast::ExprIf(cond, then, elseopt) => { - let pat_under = fld.cx.pat_wild(span); - arms.push(ast::Arm { - attrs: vec![], - pats: vec![pat_under], - guard: Some(cond), - body: fld.cx.expr_block(then) - }); - elseopt.map(|elseopt| (elseopt, true)) - } - _ => Some((P(els), false)) - })); - match elseopt_continue { - Some((e, true)) => { - elseopt = Some(e); - } - Some((e, false)) => { - elseopt = Some(e); - break; - } - None => { - elseopt = None; - break; - } - } - } - arms - }; - - let contains_else_clause = elseopt.is_some(); - - // `_ => [<elseopt> | ()]` - let else_arm = { - let pat_under = fld.cx.pat_wild(span); - let else_expr = elseopt.unwrap_or_else(|| fld.cx.expr_tuple(span, vec![])); - fld.cx.arm(span, vec![pat_under], else_expr) - }; - - let mut arms = Vec::with_capacity(else_if_arms.len() + 2); - arms.push(pat_arm); - arms.extend(else_if_arms); - arms.push(else_arm); - - let match_expr = fld.cx.expr(span, - ast::ExprMatch(expr, arms, - ast::MatchSource::IfLetDesugar { - contains_else_clause: contains_else_clause, - })); - let result = fld.fold_expr(match_expr); - fld.cx.bt_pop(); - result - } + let pat = fld.fold_pat(pat); + let expr = fld.fold_expr(expr); + + // Hygienic renaming of the body. + let ((body, opt_ident), mut rewritten_pats) = + rename_in_scope(vec![pat], + fld, + (body, opt_ident), + |rename_fld, fld, (body, opt_ident)| { + expand_loop_block(rename_fld.fold_block(body), opt_ident, fld) + }); + assert!(rewritten_pats.len() == 1); - // Desugar support for ExprIfLet in the ExprIf else position - ast::ExprIf(cond, blk, elseopt) => { - let elseopt = elseopt.map(|els| els.and_then(|els| match els.node { - ast::ExprIfLet(..) => { - push_compiler_expansion(fld, span, CompilerExpansionFormat::IfLet); - // wrap the if-let expr in a block - let span = els.span; - let blk = P(ast::Block { - stmts: vec![], - expr: Some(P(els)), - id: ast::DUMMY_NODE_ID, - rules: ast::DefaultBlock, - span: span - }); - let result = fld.cx.expr_block(blk); - fld.cx.bt_pop(); - result - } - _ => P(els) - })); - let if_expr = fld.cx.expr(span, ast::ExprIf(cond, blk, elseopt)); - if_expr.map(|e| noop_fold_expr(e, fld)) + fld.cx.expr(span, ast::ExprWhileLet(rewritten_pats.remove(0), expr, body, opt_ident)) } ast::ExprLoop(loop_block, opt_ident) => { @@ -360,102 +101,39 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> { fld.cx.expr(span, ast::ExprLoop(loop_block, opt_ident)) } - // Desugar ExprForLoop - // From: `[opt_ident]: for <pat> in <head> <body>` ast::ExprForLoop(pat, head, body, opt_ident) => { - // to: - // - // { - // let result = match ::std::iter::IntoIterator::into_iter(<head>) { - // mut iter => { - // [opt_ident]: loop { - // match ::std::iter::Iterator::next(&mut iter) { - // ::std::option::Option::Some(<pat>) => <body>, - // ::std::option::Option::None => break - // } - // } - // } - // }; - // result - // } - - push_compiler_expansion(fld, span, CompilerExpansionFormat::ForLoop); - - let span = fld.new_span(span); + let pat = fld.fold_pat(pat); + + // Hygienic renaming of the for loop body (for loop binds its pattern). + let ((body, opt_ident), mut rewritten_pats) = + rename_in_scope(vec![pat], + fld, + (body, opt_ident), + |rename_fld, fld, (body, opt_ident)| { + expand_loop_block(rename_fld.fold_block(body), opt_ident, fld) + }); + assert!(rewritten_pats.len() == 1); - // expand <head> let head = fld.fold_expr(head); + fld.cx.expr(span, ast::ExprForLoop(rewritten_pats.remove(0), head, body, opt_ident)) + } - let iter = token::gensym_ident("iter"); - - let pat_span = fld.new_span(pat.span); - // `::std::option::Option::Some(<pat>) => <body>` - let pat_arm = { - let body_expr = fld.cx.expr_block(body); - let pat = fld.fold_pat(pat); - let some_pat = fld.cx.pat_some(pat_span, pat); - - fld.cx.arm(pat_span, vec![some_pat], body_expr) - }; - - // `::std::option::Option::None => break` - let break_arm = { - let break_expr = fld.cx.expr_break(span); - - fld.cx.arm(span, vec![fld.cx.pat_none(span)], break_expr) - }; - - // `match ::std::iter::Iterator::next(&mut iter) { ... }` - let match_expr = { - let next_path = { - let strs = fld.cx.std_path(&["iter", "Iterator", "next"]); - - fld.cx.path_global(span, strs) - }; - let ref_mut_iter = fld.cx.expr_mut_addr_of(span, fld.cx.expr_ident(span, iter)); - let next_expr = - fld.cx.expr_call(span, fld.cx.expr_path(next_path), vec![ref_mut_iter]); - let arms = vec![pat_arm, break_arm]; - - fld.cx.expr(pat_span, - ast::ExprMatch(next_expr, arms, ast::MatchSource::ForLoopDesugar)) - }; - - // `[opt_ident]: loop { ... }` - let loop_block = fld.cx.block_expr(match_expr); - let (loop_block, opt_ident) = expand_loop_block(loop_block, opt_ident, fld); - let loop_expr = fld.cx.expr(span, ast::ExprLoop(loop_block, opt_ident)); - - // `mut iter => { ... }` - let iter_arm = { - let iter_pat = - fld.cx.pat_ident_binding_mode(span, iter, ast::BindByValue(ast::MutMutable)); - fld.cx.arm(span, vec![iter_pat], loop_expr) - }; - - // `match ::std::iter::IntoIterator::into_iter(<head>) { ... }` - let into_iter_expr = { - let into_iter_path = { - let strs = fld.cx.std_path(&["iter", "IntoIterator", - "into_iter"]); - - fld.cx.path_global(span, strs) - }; - - fld.cx.expr_call(span, fld.cx.expr_path(into_iter_path), vec![head]) - }; + ast::ExprIfLet(pat, sub_expr, body, else_opt) => { + let pat = fld.fold_pat(pat); - let match_expr = fld.cx.expr_match(span, into_iter_expr, vec![iter_arm]); + // Hygienic renaming of the body. + let (body, mut rewritten_pats) = + rename_in_scope(vec![pat], + fld, + body, + |rename_fld, fld, body| { + fld.fold_block(rename_fld.fold_block(body)) + }); + assert!(rewritten_pats.len() == 1); - // `{ let result = ...; result }` - let result_ident = token::gensym_ident("result"); - let result = fld.cx.expr_block( - fld.cx.block_all( - span, - vec![fld.cx.stmt_let(span, false, result_ident, match_expr)], - Some(fld.cx.expr_ident(span, result_ident)))); - fld.cx.bt_pop(); - result + let else_opt = else_opt.map(|else_opt| fld.fold_expr(else_opt)); + let sub_expr = fld.fold_expr(sub_expr); + fld.cx.expr(span, ast::ExprIfLet(rewritten_pats.remove(0), sub_expr, body, else_opt)) } ast::ExprClosure(capture_clause, fn_decl, block) => { @@ -475,25 +153,6 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> { }, fld)) } }); - - fn push_unsafe_expr(cx: &mut ExtCtxt, stmts: Vec<P<ast::Stmt>>, - expr: P<ast::Expr>, span: Span) - -> P<ast::Expr> { - let rules = ast::PushUnsafeBlock(ast::CompilerGenerated); - cx.expr_block(P(ast::Block { - rules: rules, span: span, id: ast::DUMMY_NODE_ID, - stmts: stmts, expr: Some(expr), - })) - } - - fn pop_unsafe_expr(cx: &mut ExtCtxt, expr: P<ast::Expr>, span: Span) - -> P<ast::Expr> { - let rules = ast::PopUnsafeBlock(ast::CompilerGenerated); - cx.expr_block(P(ast::Block { - rules: rules, span: span, id: ast::DUMMY_NODE_ID, - stmts: vec![], expr: Some(expr), - })) - } } /// Expand a (not-ident-style) macro invocation. Returns the result @@ -948,18 +607,18 @@ fn expand_arm(arm: ast::Arm, fld: &mut MacroExpander) -> ast::Arm { if expanded_pats.is_empty() { panic!("encountered match arm with 0 patterns"); } - // all of the pats must have the same set of bindings, so use the - // first one to extract them and generate new names: - let idents = pattern_bindings(&*expanded_pats[0]); - let new_renames = idents.into_iter().map(|id| (id, fresh_name(id))).collect(); - // apply the renaming, but only to the PatIdents: - let mut rename_pats_fld = PatIdentRenamer{renames:&new_renames}; - let rewritten_pats = expanded_pats.move_map(|pat| rename_pats_fld.fold_pat(pat)); + // apply renaming and then expansion to the guard and the body: - let mut rename_fld = IdentRenamer{renames:&new_renames}; - let rewritten_guard = - arm.guard.map(|g| fld.fold_expr(rename_fld.fold_expr(g))); - let rewritten_body = fld.fold_expr(rename_fld.fold_expr(arm.body)); + let ((rewritten_guard, rewritten_body), rewritten_pats) = + rename_in_scope(expanded_pats, + fld, + (arm.guard, arm.body), + |rename_fld, fld, (ag, ab)|{ + let rewritten_guard = ag.map(|g| fld.fold_expr(rename_fld.fold_expr(g))); + let rewritten_body = fld.fold_expr(rename_fld.fold_expr(ab)); + (rewritten_guard, rewritten_body) + }); + ast::Arm { attrs: fold::fold_attrs(arm.attrs, fld), pats: rewritten_pats, @@ -968,6 +627,25 @@ fn expand_arm(arm: ast::Arm, fld: &mut MacroExpander) -> ast::Arm { } } +fn rename_in_scope<X, F>(pats: Vec<P<ast::Pat>>, + fld: &mut MacroExpander, + x: X, + f: F) + -> (X, Vec<P<ast::Pat>>) + where F: Fn(&mut IdentRenamer, &mut MacroExpander, X) -> X +{ + // all of the pats must have the same set of bindings, so use the + // first one to extract them and generate new names: + let idents = pattern_bindings(&*pats[0]); + let new_renames = idents.into_iter().map(|id| (id, fresh_name(id))).collect(); + // apply the renaming, but only to the PatIdents: + let mut rename_pats_fld = PatIdentRenamer{renames:&new_renames}; + let rewritten_pats = pats.move_map(|pat| rename_pats_fld.fold_pat(pat)); + + let mut rename_fld = IdentRenamer{ renames:&new_renames }; + (f(&mut rename_fld, fld, x), rewritten_pats) +} + /// A visitor that extracts the PatIdent (binding) paths /// from a given thingy and puts them in a mutable /// array diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 6129cddfe6d..8efeaa330c0 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -726,7 +726,7 @@ impl<'a, 'v> Visitor<'v> for MacroVisitor<'a> { } struct PostExpansionVisitor<'a> { - context: &'a Context<'a> + context: &'a Context<'a>, } impl<'a> PostExpansionVisitor<'a> { diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 914b08265fe..3c1aa992a3c 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -1256,10 +1256,9 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span}: Expr, folder: &mut T) -> ExprLoop(folder.fold_block(body), opt_ident.map(|i| folder.fold_ident(i))) } - ExprMatch(expr, arms, source) => { + ExprMatch(expr, arms) => { ExprMatch(folder.fold_expr(expr), - arms.move_map(|x| folder.fold_arm(x)), - source) + arms.move_map(|x| folder.fold_arm(x))) } ExprClosure(capture_clause, decl, body) => { ExprClosure(capture_clause, diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index f47dfeb1d34..443cea696b6 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -37,7 +37,7 @@ use ast::{LifetimeDef, Lit, Lit_}; use ast::{LitBool, LitChar, LitByte, LitByteStr}; use ast::{LitStr, LitInt, Local}; use ast::{MacStmtWithBraces, MacStmtWithSemicolon, MacStmtWithoutBraces}; -use ast::{MutImmutable, MutMutable, Mac_, MatchSource}; +use ast::{MutImmutable, MutMutable, Mac_}; use ast::{MutTy, BiMul, Mutability}; use ast::{MethodImplItem, NamedField, UnNeg, NoReturn, UnNot}; use ast::{Pat, PatBox, PatEnum, PatIdent, PatLit, PatQPath, PatMac, PatRange}; @@ -2927,7 +2927,7 @@ impl<'a> Parser<'a> { } let hi = self.span.hi; try!(self.bump()); - return Ok(self.mk_expr(lo, hi, ExprMatch(discriminant, arms, MatchSource::Normal))); + return Ok(self.mk_expr(lo, hi, ExprMatch(discriminant, arms))); } pub fn parse_arm_nopanic(&mut self) -> PResult<Arm> { diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 405fd9b8cc7..f5f3907a4e6 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -2045,7 +2045,7 @@ impl<'a> State<'a> { try!(space(&mut self.s)); try!(self.print_block(&**blk)); } - ast::ExprMatch(ref expr, ref arms, _) => { + ast::ExprMatch(ref expr, ref arms) => { try!(self.cbox(indent_unit)); try!(self.ibox(4)); try!(self.word_nbsp("match")); diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 67e4927a52f..091580b9bd8 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -731,7 +731,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { visitor.visit_block(block); walk_opt_ident(visitor, expression.span, opt_ident) } - ExprMatch(ref subexpression, ref arms, _) => { + ExprMatch(ref subexpression, ref arms) => { visitor.visit_expr(subexpression); walk_list!(visitor, visit_arm, arms); } |
