diff --git a/syntex_syntax/src/ast.rs b/syntex_syntax/src/ast.rs index d220508a..cb79c609 100644 --- a/syntex_syntax/src/ast.rs +++ b/syntex_syntax/src/ast.rs @@ -10,7 +10,6 @@ // The Rust abstract syntax tree. -pub use self::Pat_::*; pub use self::StructFieldKind::*; pub use self::TyParamBound::*; pub use self::UnsafeSource::*; @@ -521,7 +520,7 @@ pub struct Block { #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash)] pub struct Pat { pub id: NodeId, - pub node: Pat_, + pub node: PatKind, pub span: Span, } @@ -552,47 +551,53 @@ pub enum BindingMode { } #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub enum Pat_ { +pub enum PatKind { /// Represents a wildcard pattern (`_`) - PatWild, + Wild, - /// A PatIdent may either be a new bound variable, - /// or a nullary enum (in which case the third field - /// is None). + /// A `PatKind::Ident` may either be a new bound variable, + /// or a unit struct/variant pattern, or a const pattern (in the last two cases + /// the third field must be `None`). /// - /// In the nullary enum case, the parser can't determine + /// In the unit or const pattern case, the parser can't determine /// which it is. The resolver determines this, and - /// records this pattern's NodeId in an auxiliary - /// set (of "PatIdents that refer to nullary enums") - PatIdent(BindingMode, SpannedIdent, Option>), + /// records this pattern's `NodeId` in an auxiliary + /// set (of "PatIdents that refer to unit patterns or constants"). + Ident(BindingMode, SpannedIdent, Option>), + /// A struct or struct variant pattern, e.g. `Variant {x, y, ..}`. + /// The `bool` is `true` in the presence of a `..`. + Struct(Path, Vec>, bool), + + /// A tuple struct/variant pattern `Variant(x, y, z)`. /// "None" means a `Variant(..)` pattern where we don't bind the fields to names. - PatEnum(Path, Option>>), + TupleStruct(Path, Option>>), + + /// A path pattern. + /// Such pattern can be resolved to a unit struct/variant or a constant. + Path(Path), /// An associated const named using the qualified path `::CONST` or /// `::CONST`. Associated consts from inherent impls can be /// referred to as simply `T::CONST`, in which case they will end up as - /// PatEnum, and the resolver will have to sort that out. - PatQPath(QSelf, Path), + /// PatKind::Enum, and the resolver will have to sort that out. + QPath(QSelf, Path), - /// Destructuring of a struct, e.g. `Foo {x, y, ..}` - /// The `bool` is `true` in the presence of a `..` - PatStruct(Path, Vec>, bool), /// A tuple pattern `(a, b)` - PatTup(Vec>), + Tup(Vec>), /// A `box` pattern - PatBox(P), + Box(P), /// A reference pattern, e.g. `&mut (a, b)` - PatRegion(P, Mutability), + Ref(P, Mutability), /// A literal - PatLit(P), + Lit(P), /// A range pattern, e.g. `1...2` - PatRange(P, P), + Range(P, P), /// `[a, b, ..i, y, z]` is represented as: - /// `PatVec(box [a, b], Some(i), box [y, z])` - PatVec(Vec>, Option>, Vec>), + /// `PatKind::Vec(box [a, b], Some(i), box [y, z])` + Vec(Vec>, Option>, Vec>), /// A macro pattern; pre-expansion - PatMac(Mac), + Mac(Mac), } #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] @@ -1609,7 +1614,7 @@ impl Arg { }), pat: P(Pat { id: DUMMY_NODE_ID, - node: PatIdent(BindingMode::ByValue(mutability), path, None), + node: PatKind::Ident(BindingMode::ByValue(mutability), path, None), span: span }), id: DUMMY_NODE_ID diff --git a/syntex_syntax/src/ast_util.rs b/syntex_syntax/src/ast_util.rs index e22cdab9..5d55b6f8 100644 --- a/syntex_syntax/src/ast_util.rs +++ b/syntex_syntax/src/ast_util.rs @@ -69,7 +69,7 @@ pub fn ident_to_pat(id: NodeId, s: Span, i: Ident) -> P { let spanned = codemap::Spanned{ span: s, node: i }; P(Pat { id: id, - node: PatIdent(BindingMode::ByValue(Mutability::Immutable), spanned, None), + node: PatKind::Ident(BindingMode::ByValue(Mutability::Immutable), spanned, None), span: s }) } @@ -348,7 +348,7 @@ pub fn compute_id_range_for_fn_body(fk: FnKind, /// and false otherwise. pub fn pat_is_ident(pat: P) -> bool { match pat.node { - ast::PatIdent(..) => true, + PatKind::Ident(..) => true, _ => false, } } diff --git a/syntex_syntax/src/ext/base.rs b/syntex_syntax/src/ext/base.rs index 1f90c687..3d183985 100644 --- a/syntex_syntax/src/ext/base.rs +++ b/syntex_syntax/src/ext/base.rs @@ -11,7 +11,7 @@ pub use self::SyntaxExtension::*; use ast; -use ast::Name; +use ast::{Name, PatKind}; use codemap; use codemap::{CodeMap, Span, ExpnId, ExpnInfo, NO_EXPANSION}; use errors::DiagnosticBuilder; @@ -307,7 +307,7 @@ impl MacResult for MacEager { return Some(P(ast::Pat { id: ast::DUMMY_NODE_ID, span: e.span, - node: ast::PatLit(e), + node: PatKind::Lit(e), })); } } @@ -359,7 +359,7 @@ impl DummyResult { pub fn raw_pat(sp: Span) -> ast::Pat { ast::Pat { id: ast::DUMMY_NODE_ID, - node: ast::PatWild, + node: PatKind::Wild, span: sp, } } diff --git a/syntex_syntax/src/ext/build.rs b/syntex_syntax/src/ext/build.rs index 38af8353..0eb42f17 100644 --- a/syntex_syntax/src/ext/build.rs +++ b/syntex_syntax/src/ext/build.rs @@ -9,7 +9,7 @@ // except according to those terms. use abi::Abi; -use ast::{self, Ident, Generics, Expr, BlockCheckMode, UnOp}; +use ast::{self, Ident, Generics, Expr, BlockCheckMode, UnOp, PatKind}; use attr; use codemap::{Span, respan, Spanned, DUMMY_SP, Pos}; use ext::base::ExtCtxt; @@ -166,7 +166,7 @@ pub trait AstBuilder { fn expr_err(&self, span: Span, expr: P) -> P; fn expr_try(&self, span: Span, head: P) -> P; - fn pat(&self, span: Span, pat: ast::Pat_) -> P; + fn pat(&self, span: Span, pat: PatKind) -> P; fn pat_wild(&self, span: Span) -> P; fn pat_lit(&self, span: Span, expr: P) -> P; fn pat_ident(&self, span: Span, ident: ast::Ident) -> P; @@ -805,14 +805,14 @@ impl<'a> AstBuilder for ExtCtxt<'a> { } - fn pat(&self, span: Span, pat: ast::Pat_) -> P { + fn pat(&self, span: Span, pat: PatKind) -> P { P(ast::Pat { id: ast::DUMMY_NODE_ID, node: pat, span: span }) } fn pat_wild(&self, span: Span) -> P { - self.pat(span, ast::PatWild) + self.pat(span, PatKind::Wild) } fn pat_lit(&self, span: Span, expr: P) -> P { - self.pat(span, ast::PatLit(expr)) + self.pat(span, PatKind::Lit(expr)) } fn pat_ident(&self, span: Span, ident: ast::Ident) -> P { let binding_mode = ast::BindingMode::ByValue(ast::Mutability::Immutable); @@ -823,20 +823,24 @@ impl<'a> AstBuilder for ExtCtxt<'a> { span: Span, ident: ast::Ident, bm: ast::BindingMode) -> P { - let pat = ast::PatIdent(bm, Spanned{span: span, node: ident}, None); + let pat = PatKind::Ident(bm, Spanned{span: span, node: ident}, None); self.pat(span, pat) } fn pat_enum(&self, span: Span, path: ast::Path, subpats: Vec>) -> P { - let pat = ast::PatEnum(path, Some(subpats)); + let pat = if subpats.is_empty() { + PatKind::Path(path) + } else { + PatKind::TupleStruct(path, Some(subpats)) + }; self.pat(span, pat) } fn pat_struct(&self, span: Span, path: ast::Path, field_pats: Vec>) -> P { - let pat = ast::PatStruct(path, field_pats, false); + let pat = PatKind::Struct(path, field_pats, false); self.pat(span, pat) } fn pat_tuple(&self, span: Span, pats: Vec>) -> P { - self.pat(span, ast::PatTup(pats)) + self.pat(span, PatKind::Tup(pats)) } fn pat_some(&self, span: Span, pat: P) -> P { diff --git a/syntex_syntax/src/ext/expand.rs b/syntex_syntax/src/ext/expand.rs index 96dc0eef..41f8c8fe 100644 --- a/syntex_syntax/src/ext/expand.rs +++ b/syntex_syntax/src/ext/expand.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use ast::{Block, Crate, DeclKind, PatMac}; +use ast::{Block, Crate, DeclKind, PatKind}; use ast::{Local, Ident, Mac_, Name}; use ast::{MacStmtStyle, Mrk, Stmt, StmtKind, ItemKind}; use ast::TokenTree; @@ -678,7 +678,7 @@ fn rename_in_scope(pats: Vec>, (f(&mut rename_fld, fld, x), rewritten_pats) } -/// A visitor that extracts the PatIdent (binding) paths +/// A visitor that extracts the PatKind::Ident (binding) paths /// from a given thingy and puts them in a mutable /// array #[derive(Clone)] @@ -689,9 +689,9 @@ struct PatIdentFinder { impl<'v> Visitor<'v> for PatIdentFinder { fn visit_pat(&mut self, pattern: &ast::Pat) { match *pattern { - ast::Pat { id: _, node: ast::PatIdent(_, ref path1, ref inner), span: _ } => { + ast::Pat { id: _, node: PatKind::Ident(_, ref path1, ref inner), span: _ } => { self.ident_accumulator.push(path1.node); - // visit optional subpattern of PatIdent: + // visit optional subpattern of PatKind::Ident: if let Some(ref subpat) = *inner { self.visit_pat(subpat) } @@ -702,14 +702,14 @@ impl<'v> Visitor<'v> for PatIdentFinder { } } -/// find the PatIdent paths in a pattern +/// find the PatKind::Ident paths in a pattern fn pattern_bindings(pat: &ast::Pat) -> Vec { let mut name_finder = PatIdentFinder{ident_accumulator:Vec::new()}; name_finder.visit_pat(pat); name_finder.ident_accumulator } -/// find the PatIdent paths in a +/// find the PatKind::Ident paths in a fn fn_decl_arg_bindings(fn_decl: &ast::FnDecl) -> Vec { let mut pat_idents = PatIdentFinder{ident_accumulator:Vec::new()}; for arg in &fn_decl.inputs { @@ -758,12 +758,12 @@ pub fn expand_block_elts(b: P, fld: &mut MacroExpander) -> P { fn expand_pat(p: P, fld: &mut MacroExpander) -> P { match p.node { - PatMac(_) => {} + PatKind::Mac(_) => {} _ => return noop_fold_pat(p, fld) } p.clone().map(|ast::Pat {node, span, ..}| { let (pth, tts) = match node { - PatMac(mac) => (mac.node.path, mac.node.tts), + PatKind::Mac(mac) => (mac.node.path, mac.node.tts), _ => unreachable!() }; if pth.segments.len() > 1 { @@ -855,7 +855,7 @@ impl<'a> Folder for IdentRenamer<'a> { } /// A tree-folder that applies every rename in its list to -/// the idents that are in PatIdent patterns. This is more narrowly +/// the idents that are in PatKind::Ident patterns. This is more narrowly /// focused than IdentRenamer, and is needed for FnDecl, /// where we want to rename the args but not the fn name or the generics etc. pub struct PatIdentRenamer<'a> { @@ -865,16 +865,16 @@ pub struct PatIdentRenamer<'a> { impl<'a> Folder for PatIdentRenamer<'a> { fn fold_pat(&mut self, pat: P) -> P { match pat.node { - ast::PatIdent(..) => {}, + PatKind::Ident(..) => {}, _ => return noop_fold_pat(pat, self) } pat.map(|ast::Pat {id, node, span}| match node { - ast::PatIdent(binding_mode, Spanned{span: sp, node: ident}, sub) => { + PatKind::Ident(binding_mode, Spanned{span: sp, node: ident}, sub) => { let new_ident = Ident::new(ident.name, mtwt::apply_renames(self.renames, ident.ctxt)); let new_node = - ast::PatIdent(binding_mode, + PatKind::Ident(binding_mode, Spanned{span: self.new_span(sp), node: new_ident}, sub.map(|p| self.fold_pat(p))); ast::Pat { diff --git a/syntex_syntax/src/feature_gate.rs b/syntex_syntax/src/feature_gate.rs index 5dfec8da..70bd85c0 100644 --- a/syntex_syntax/src/feature_gate.rs +++ b/syntex_syntax/src/feature_gate.rs @@ -27,7 +27,7 @@ use self::AttributeType::*; use self::AttributeGate::*; use abi::Abi; -use ast::NodeId; +use ast::{NodeId, PatKind}; use ast; use attr; use attr::AttrMetaMethods; @@ -1005,19 +1005,19 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> { fn visit_pat(&mut self, pattern: &ast::Pat) { match pattern.node { - ast::PatVec(_, Some(_), ref last) if !last.is_empty() => { + PatKind::Vec(_, Some(_), ref last) if !last.is_empty() => { self.gate_feature("advanced_slice_patterns", pattern.span, "multiple-element slice matches anywhere \ but at the end of a slice (e.g. \ `[0, ..xs, 0]`) are experimental") } - ast::PatVec(..) => { + PatKind::Vec(..) => { self.gate_feature("slice_patterns", pattern.span, "slice pattern syntax is experimental"); } - ast::PatBox(..) => { + PatKind::Box(..) => { self.gate_feature("box_patterns", pattern.span, "box pattern syntax is experimental"); diff --git a/syntex_syntax/src/fold.rs b/syntex_syntax/src/fold.rs index 6df31317..d75e8f79 100644 --- a/syntex_syntax/src/fold.rs +++ b/syntex_syntax/src/fold.rs @@ -1119,23 +1119,26 @@ pub fn noop_fold_pat(p: P, folder: &mut T) -> P { p.map(|Pat {id, node, span}| Pat { id: folder.new_id(id), node: match node { - PatWild => PatWild, - PatIdent(binding_mode, pth1, sub) => { - PatIdent(binding_mode, + PatKind::Wild => PatKind::Wild, + PatKind::Ident(binding_mode, pth1, sub) => { + PatKind::Ident(binding_mode, Spanned{span: folder.new_span(pth1.span), node: folder.fold_ident(pth1.node)}, sub.map(|x| folder.fold_pat(x))) } - PatLit(e) => PatLit(folder.fold_expr(e)), - PatEnum(pth, pats) => { - PatEnum(folder.fold_path(pth), + PatKind::Lit(e) => PatKind::Lit(folder.fold_expr(e)), + PatKind::TupleStruct(pth, pats) => { + PatKind::TupleStruct(folder.fold_path(pth), pats.map(|pats| pats.move_map(|x| folder.fold_pat(x)))) } - PatQPath(qself, pth) => { + PatKind::Path(pth) => { + PatKind::Path(folder.fold_path(pth)) + } + PatKind::QPath(qself, pth) => { let qself = QSelf {ty: folder.fold_ty(qself.ty), .. qself}; - PatQPath(qself, folder.fold_path(pth)) + PatKind::QPath(qself, folder.fold_path(pth)) } - PatStruct(pth, fields, etc) => { + PatKind::Struct(pth, fields, etc) => { let pth = folder.fold_path(pth); let fs = fields.move_map(|f| { Spanned { span: folder.new_span(f.span), @@ -1145,20 +1148,20 @@ pub fn noop_fold_pat(p: P, folder: &mut T) -> P { is_shorthand: f.node.is_shorthand, }} }); - PatStruct(pth, fs, etc) + PatKind::Struct(pth, fs, etc) } - PatTup(elts) => PatTup(elts.move_map(|x| folder.fold_pat(x))), - PatBox(inner) => PatBox(folder.fold_pat(inner)), - PatRegion(inner, mutbl) => PatRegion(folder.fold_pat(inner), mutbl), - PatRange(e1, e2) => { - PatRange(folder.fold_expr(e1), folder.fold_expr(e2)) + PatKind::Tup(elts) => PatKind::Tup(elts.move_map(|x| folder.fold_pat(x))), + PatKind::Box(inner) => PatKind::Box(folder.fold_pat(inner)), + PatKind::Ref(inner, mutbl) => PatKind::Ref(folder.fold_pat(inner), mutbl), + PatKind::Range(e1, e2) => { + PatKind::Range(folder.fold_expr(e1), folder.fold_expr(e2)) }, - PatVec(before, slice, after) => { - PatVec(before.move_map(|x| folder.fold_pat(x)), + PatKind::Vec(before, slice, after) => { + PatKind::Vec(before.move_map(|x| folder.fold_pat(x)), slice.map(|x| folder.fold_pat(x)), after.move_map(|x| folder.fold_pat(x))) } - PatMac(mac) => PatMac(folder.fold_mac(mac)) + PatKind::Mac(mac) => PatKind::Mac(folder.fold_mac(mac)) }, span: folder.new_span(span) }) diff --git a/syntex_syntax/src/parse/mod.rs b/syntex_syntax/src/parse/mod.rs index f35c7907..e9723798 100644 --- a/syntex_syntax/src/parse/mod.rs +++ b/syntex_syntax/src/parse/mod.rs @@ -677,7 +677,7 @@ mod tests { use super::*; use std::rc::Rc; use codemap::{Span, BytePos, Pos, Spanned, NO_EXPANSION}; - use ast::{self, TokenTree}; + use ast::{self, TokenTree, PatKind}; use abi::Abi; use attr::{first_attr_value_str_by_name, AttrMetaMethods}; use parse; @@ -898,7 +898,7 @@ mod tests { assert!(panictry!(parser.parse_pat()) == P(ast::Pat{ id: ast::DUMMY_NODE_ID, - node: ast::PatIdent(ast::BindingMode::ByValue(ast::Mutability::Immutable), + node: PatKind::Ident(ast::BindingMode::ByValue(ast::Mutability::Immutable), Spanned{ span:sp(0, 1), node: str_to_ident("b") }, @@ -933,7 +933,7 @@ mod tests { }), pat: P(ast::Pat { id: ast::DUMMY_NODE_ID, - node: ast::PatIdent( + node: PatKind::Ident( ast::BindingMode::ByValue(ast::Mutability::Immutable), Spanned{ span: sp(6,7), @@ -1022,7 +1022,7 @@ mod tests { impl<'v> ::visit::Visitor<'v> for PatIdentVisitor { fn visit_pat(&mut self, p: &'v ast::Pat) { match p.node { - ast::PatIdent(_ , ref spannedident, _) => { + PatKind::Ident(_ , ref spannedident, _) => { self.spans.push(spannedident.span.clone()); } _ => { diff --git a/syntex_syntax/src/parse/parser.rs b/syntex_syntax/src/parse/parser.rs index af745020..0403f5f7 100644 --- a/syntex_syntax/src/parse/parser.rs +++ b/syntex_syntax/src/parse/parser.rs @@ -30,8 +30,7 @@ use ast::MacStmtStyle; use ast::Mac_; use ast::{MutTy, Mutability}; use ast::NamedField; -use ast::{Pat, PatBox, PatEnum, PatIdent, PatLit, PatQPath, PatMac, PatRange}; -use ast::{PatRegion, PatStruct, PatTup, PatVec, PatWild}; +use ast::{Pat, PatKind}; use ast::{PolyTraitRef, QSelf}; use ast::{Stmt, StmtKind}; use ast::{VariantData, StructField}; @@ -73,6 +72,7 @@ bitflags! { flags Restrictions: u8 { const RESTRICTION_STMT_EXPR = 1 << 0, const RESTRICTION_NO_STRUCT_LITERAL = 1 << 1, + const NO_NONINLINE_MOD = 1 << 2, } } @@ -106,6 +106,12 @@ pub enum ParsePub { No, } +#[derive(Clone, Copy, PartialEq)] +pub enum SemiColonMode { + Break, + Ignore, +} + /// Possibly accept an `token::Interpolated` expression (a pre-parsed expression /// dropped into the token stream, which happens while parsing the result of /// macro expansion). Placement of these is not as complex as I feared it would @@ -599,7 +605,7 @@ impl<'a> Parser<'a> { /// Check if the next token is `tok`, and return `true` if so. /// - /// This method is will automatically add `tok` to `expected_tokens` if `tok` is not + /// This method will automatically add `tok` to `expected_tokens` if `tok` is not /// encountered. pub fn check(&mut self, tok: &token::Token) -> bool { let is_present = self.token == *tok; @@ -841,6 +847,15 @@ impl<'a> Parser<'a> { return Ok((v, returned)); } + /// Eat and discard tokens until one of `kets` is encountered. Respects token trees, + /// passes through any errors encountered. Used for error recovery. + pub fn eat_to_tokens(&mut self, kets: &[&token::Token]) { + self.parse_seq_to_before_tokens(kets, + seq_sep_none(), + |p| p.parse_token_tree(), + |mut e| e.cancel()); + } + /// Parse a sequence, including the closing delimiter. The function /// f must consume tokens until reaching the next separator or /// closing bracket. @@ -851,7 +866,7 @@ impl<'a> Parser<'a> { -> PResult<'a, Vec> where F: FnMut(&mut Parser<'a>) -> PResult<'a, T>, { - let val = try!(self.parse_seq_to_before_end(ket, sep, f)); + let val = self.parse_seq_to_before_end(ket, sep, f); self.bump(); Ok(val) } @@ -862,24 +877,53 @@ impl<'a> Parser<'a> { pub fn parse_seq_to_before_end(&mut self, ket: &token::Token, sep: SeqSep, - mut f: F) - -> PResult<'a, Vec> where - F: FnMut(&mut Parser<'a>) -> PResult<'a, T>, + f: F) + -> Vec + where F: FnMut(&mut Parser<'a>) -> PResult<'a, T>, + { + self.parse_seq_to_before_tokens(&[ket], sep, f, |mut e| e.emit()) + } + + // `fe` is an error handler. + fn parse_seq_to_before_tokens(&mut self, + kets: &[&token::Token], + sep: SeqSep, + mut f: F, + mut fe: Fe) + -> Vec + where F: FnMut(&mut Parser<'a>) -> PResult<'a, T>, + Fe: FnMut(DiagnosticBuilder) { let mut first: bool = true; let mut v = vec!(); - while self.token != *ket { + while !kets.contains(&&self.token) { match sep.sep { - Some(ref t) => { - if first { first = false; } - else { try!(self.expect(t)); } - } - _ => () + Some(ref t) => { + if first { + first = false; + } else { + if let Err(e) = self.expect(t) { + fe(e); + break; + } + } + } + _ => () + } + if sep.trailing_sep_allowed && kets.iter().any(|k| self.check(k)) { + break; + } + + match f(self) { + Ok(t) => v.push(t), + Err(e) => { + fe(e); + break; + } } - if sep.trailing_sep_allowed && self.check(ket) { break; } - v.push(try!(f(self))); } - return Ok(v); + + v } /// Parse a sequence, including the closing delimiter. The function @@ -894,7 +938,7 @@ impl<'a> Parser<'a> { F: FnMut(&mut Parser<'a>) -> PResult<'a, T>, { try!(self.expect(bra)); - let result = try!(self.parse_seq_to_before_end(ket, sep, f)); + let result = self.parse_seq_to_before_end(ket, sep, f); self.bump(); Ok(result) } @@ -930,7 +974,7 @@ impl<'a> Parser<'a> { { let lo = self.span.lo; try!(self.expect(bra)); - let result = try!(self.parse_seq_to_before_end(ket, sep, f)); + let result = self.parse_seq_to_before_end(ket, sep, f); let hi = self.span.hi; self.bump(); Ok(spanned(lo, hi, result)) @@ -1217,7 +1261,25 @@ impl<'a> Parser<'a> { }; (ident, TraitItemKind::Const(ty, default)) } else { - let (constness, unsafety, abi) = try!(p.parse_fn_front_matter()); + let (constness, unsafety, abi) = match p.parse_fn_front_matter() { + Ok(cua) => cua, + Err(e) => { + loop { + p.bump(); + if p.token == token::Semi { + p.bump(); + break; + } + + if p.token == token::OpenDelim(token::DelimToken::Brace) { + try!(p.parse_token_tree()); + break; + } + } + + return Err(e); + } + }; let ident = try!(p.parse_ident()); let mut generics = try!(p.parse_generics()); @@ -2290,14 +2352,37 @@ impl<'a> Parser<'a> { while self.token != token::CloseDelim(token::Brace) { if self.eat(&token::DotDot) { - base = Some(try!(self.parse_expr())); + match self.parse_expr() { + Ok(e) => { + base = Some(e); + } + Err(mut e) => { + e.emit(); + self.recover_stmt(); + } + } break; } - fields.push(try!(self.parse_field())); - try!(self.commit_expr(&fields.last().unwrap().expr, - &[token::Comma], - &[token::CloseDelim(token::Brace)])); + match self.parse_field() { + Ok(f) => fields.push(f), + Err(mut e) => { + e.emit(); + self.recover_stmt(); + break; + } + } + + match self.commit_expr(&fields.last().unwrap().expr, + &[token::Comma], + &[token::CloseDelim(token::Brace)]) { + Ok(()) => {} + Err(mut e) => { + e.emit(); + self.recover_stmt(); + break; + } + } } hi = self.span.hi; @@ -2642,45 +2727,16 @@ impl<'a> Parser<'a> { // yet. maybe_whole!(deref self, NtTT); - // this is the fall-through for the 'match' below. - // invariants: the current token is not a left-delimiter, - // not an EOF, and not the desired right-delimiter (if - // it were, parse_seq_to_before_end would have prevented - // reaching this point. - fn parse_non_delim_tt_tok<'b>(p: &mut Parser<'b>) -> PResult<'b, TokenTree> { - maybe_whole!(deref p, NtTT); - match p.token { - token::CloseDelim(_) => { - let token_str = p.this_token_to_string(); - let mut err = p.fatal( - &format!("incorrect close delimiter: `{}`", token_str)); - // This is a conservative error: only report the last unclosed delimiter. The - // previous unclosed delimiters could actually be closed! The parser just hasn't - // gotten to them yet. - if let Some(&sp) = p.open_braces.last() { - err.span_note(sp, "unclosed delimiter"); - }; - Err(err) - }, - /* we ought to allow different depths of unquotation */ - token::Dollar | token::SubstNt(..) if p.quote_depth > 0 => { - p.parse_unquoted() - } - _ => { - Ok(TokenTree::Token(p.span, p.bump_and_get())) - } - } - } - match self.token { token::Eof => { - let open_braces = self.open_braces.clone(); let mut err: DiagnosticBuilder<'a> = - self.fatal("this file contains an un-closed delimiter"); - for sp in &open_braces { + self.diagnostic().struct_span_err(self.span, + "this file contains an un-closed delimiter"); + for sp in &self.open_braces { err.span_help(*sp, "did you mean to close this delimiter?"); } - return Err(err); + + Err(err) }, token::OpenDelim(delim) => { // The span for beginning of the delimited section @@ -2692,11 +2748,9 @@ impl<'a> Parser<'a> { self.bump(); // Parse the token trees within the delimiters - let tts = try!(self.parse_seq_to_before_end( - &token::CloseDelim(delim), - seq_sep_none(), - |p| p.parse_token_tree() - )); + let tts = self.parse_seq_to_before_end(&token::CloseDelim(delim), + seq_sep_none(), + |p| p.parse_token_tree()); // Parse the close delimiter. let close_span = self.span; @@ -2713,7 +2767,35 @@ impl<'a> Parser<'a> { close_span: close_span, }))) }, - _ => parse_non_delim_tt_tok(self), + _ => { + // invariants: the current token is not a left-delimiter, + // not an EOF, and not the desired right-delimiter (if + // it were, parse_seq_to_before_end would have prevented + // reaching this point. + maybe_whole!(deref self, NtTT); + match self.token { + token::CloseDelim(_) => { + let token_str = self.this_token_to_string(); + let mut err = self.diagnostic().struct_span_err(self.span, + &format!("incorrect close delimiter: `{}`", token_str)); + // This is a conservative error: only report the last unclosed delimiter. + // The previous unclosed delimiters could actually be closed! The parser + // just hasn't gotten to them yet. + if let Some(&sp) = self.open_braces.last() { + err.span_note(sp, "unclosed delimiter"); + }; + + Err(err) + }, + /* we ought to allow different depths of unquotation */ + token::Dollar | token::SubstNt(..) if self.quote_depth > 0 => { + self.parse_unquoted() + } + _ => { + Ok(TokenTree::Token(self.span, self.bump_and_get())) + } + } + } } } @@ -3150,8 +3232,8 @@ impl<'a> Parser<'a> { fn parse_match_expr(&mut self, attrs: ThinAttributes) -> PResult<'a, P> { let match_span = self.last_span; let lo = self.last_span.lo; - let discriminant = try!(self.parse_expr_res( - RESTRICTION_NO_STRUCT_LITERAL, None)); + let discriminant = try!(self.parse_expr_res(RESTRICTION_NO_STRUCT_LITERAL, + None)); if let Err(mut e) = self.commit_expr_expecting(&discriminant, token::OpenDelim(token::Brace)) { if self.token == token::Token::Semi { @@ -3163,7 +3245,19 @@ impl<'a> Parser<'a> { try!(self.parse_inner_attributes()).into_thin_attrs()); let mut arms: Vec = Vec::new(); while self.token != token::CloseDelim(token::Brace) { - arms.push(try!(self.parse_arm())); + match self.parse_arm() { + Ok(arm) => arms.push(arm), + Err(mut e) => { + // Recover by skipping to the end of the block. + e.emit(); + self.recover_stmt(); + let hi = self.span.hi; + if self.token == token::CloseDelim(token::Brace) { + self.bump(); + } + return Ok(self.mk_expr(lo, hi, ExprKind::Match(discriminant, arms), attrs)); + } + } } let hi = self.span.hi; self.bump(); @@ -3208,8 +3302,8 @@ impl<'a> Parser<'a> { /// Evaluate the closure with restrictions in place. /// /// After the closure is evaluated, restrictions are reset. - pub fn with_res(&mut self, r: Restrictions, f: F) -> PResult<'a, P> - where F: FnOnce(&mut Self) -> PResult<'a, P> + pub fn with_res(&mut self, r: Restrictions, f: F) -> T + where F: FnOnce(&mut Self) -> T { let old = self.restrictions; self.restrictions = r; @@ -3292,7 +3386,7 @@ impl<'a> Parser<'a> { self.check(&token::CloseDelim(token::Bracket)) { slice = Some(P(ast::Pat { id: ast::DUMMY_NODE_ID, - node: PatWild, + node: PatKind::Wild, span: self.span, })); before_slice = false; @@ -3370,14 +3464,14 @@ impl<'a> Parser<'a> { let fieldpath = codemap::Spanned{span:self.last_span, node:fieldname}; let fieldpat = P(ast::Pat{ id: ast::DUMMY_NODE_ID, - node: PatIdent(bind_type, fieldpath, None), + node: PatKind::Ident(bind_type, fieldpath, None), span: mk_sp(boxed_span_lo, hi), }); let subpat = if is_box { P(ast::Pat{ id: ast::DUMMY_NODE_ID, - node: PatBox(fieldpat), + node: PatKind::Box(fieldpat), span: mk_sp(lo, hi), }) } else { @@ -3429,7 +3523,7 @@ impl<'a> Parser<'a> { token::Underscore => { // Parse _ self.bump(); - pat = PatWild; + pat = PatKind::Wild; } token::BinOp(token::And) | token::AndAnd => { // Parse &pat / &mut pat @@ -3440,21 +3534,21 @@ impl<'a> Parser<'a> { } let subpat = try!(self.parse_pat()); - pat = PatRegion(subpat, mutbl); + pat = PatKind::Ref(subpat, mutbl); } token::OpenDelim(token::Paren) => { // Parse (pat,pat,pat,...) as tuple pattern self.bump(); let fields = try!(self.parse_pat_tuple_elements()); try!(self.expect(&token::CloseDelim(token::Paren))); - pat = PatTup(fields); + pat = PatKind::Tup(fields); } token::OpenDelim(token::Bracket) => { // Parse [pat,pat,...] as slice pattern self.bump(); let (before, slice, after) = try!(self.parse_pat_vec_elements()); try!(self.expect(&token::CloseDelim(token::Bracket))); - pat = PatVec(before, slice, after); + pat = PatKind::Vec(before, slice, after); } _ => { // At this point, token != _, &, &&, (, [ @@ -3468,7 +3562,7 @@ impl<'a> Parser<'a> { } else if self.eat_keyword(keywords::Box) { // Parse box pat let subpat = try!(self.parse_pat()); - pat = PatBox(subpat); + pat = PatKind::Box(subpat); } else if self.is_path_start() { // Parse pattern starting with a path if self.token.is_plain_ident() && self.look_ahead(1, |t| *t != token::DotDotDot && @@ -3487,7 +3581,7 @@ impl<'a> Parser<'a> { let tts = try!(self.parse_seq_to_end(&token::CloseDelim(delim), seq_sep_none(), |p| p.parse_token_tree())); let mac = Mac_ { path: path, tts: tts, ctxt: EMPTY_CTXT }; - pat = PatMac(codemap::Spanned {node: mac, + pat = PatKind::Mac(codemap::Spanned {node: mac, span: mk_sp(lo, self.last_span.hi)}); } else { // Parse ident @ pat @@ -3513,7 +3607,7 @@ impl<'a> Parser<'a> { let begin = self.mk_expr(lo, hi, ExprKind::Path(qself, path), None); self.bump(); let end = try!(self.parse_pat_range_end()); - pat = PatRange(begin, end); + pat = PatKind::Range(begin, end); } token::OpenDelim(token::Brace) => { if qself.is_some() { @@ -3521,9 +3615,13 @@ impl<'a> Parser<'a> { } // Parse struct pattern self.bump(); - let (fields, etc) = try!(self.parse_pat_fields()); + let (fields, etc) = self.parse_pat_fields().unwrap_or_else(|mut e| { + e.emit(); + self.recover_stmt(); + (vec![], false) + }); self.bump(); - pat = PatStruct(path, fields, etc); + pat = PatKind::Struct(path, fields, etc); } token::OpenDelim(token::Paren) => { if qself.is_some() { @@ -3535,22 +3633,22 @@ impl<'a> Parser<'a> { self.bump(); self.bump(); try!(self.expect(&token::CloseDelim(token::Paren))); - pat = PatEnum(path, None); + pat = PatKind::TupleStruct(path, None); } else { let args = try!(self.parse_enum_variant_seq( &token::OpenDelim(token::Paren), &token::CloseDelim(token::Paren), seq_sep_trailing_allowed(token::Comma), |p| p.parse_pat())); - pat = PatEnum(path, Some(args)); + pat = PatKind::TupleStruct(path, Some(args)); } } _ => { pat = match qself { // Parse qualified path - Some(qself) => PatQPath(qself, path), + Some(qself) => PatKind::QPath(qself, path), // Parse nullary enum - None => PatEnum(path, Some(vec![])) + None => PatKind::Path(path) }; } } @@ -3560,9 +3658,9 @@ impl<'a> Parser<'a> { let begin = try!(self.parse_pat_literal_maybe_minus()); if self.eat(&token::DotDotDot) { let end = try!(self.parse_pat_range_end()); - pat = PatRange(begin, end); + pat = PatKind::Range(begin, end); } else { - pat = PatLit(begin); + pat = PatKind::Lit(begin); } } } @@ -3581,7 +3679,7 @@ impl<'a> Parser<'a> { /// error message when parsing mistakes like ref foo(a,b) fn parse_pat_ident(&mut self, binding_mode: ast::BindingMode) - -> PResult<'a, ast::Pat_> { + -> PResult<'a, PatKind> { if !self.token.is_plain_ident() { let span = self.span; let tok_str = self.this_token_to_string(); @@ -3610,7 +3708,7 @@ impl<'a> Parser<'a> { "expected identifier, found enum pattern")) } - Ok(PatIdent(binding_mode, name, sub)) + Ok(PatKind::Ident(binding_mode, name, sub)) } /// Parse a local variable declaration @@ -3675,10 +3773,72 @@ impl<'a> Parser<'a> { /// Parse a statement. may include decl. pub fn parse_stmt(&mut self) -> PResult<'a, Option> { - Ok(try!(self.parse_stmt_())) + Ok(self.parse_stmt_()) + } + + // Eat tokens until we can be relatively sure we reached the end of the + // statement. This is something of a best-effort heuristic. + // + // We terminate when we find an unmatched `}` (without consuming it). + fn recover_stmt(&mut self) { + self.recover_stmt_(SemiColonMode::Ignore) + } + // If `break_on_semi` is `Break`, then we will stop consuming tokens after + // finding (and consuming) a `;` outside of `{}` or `[]` (note that this is + // approximate - it can mean we break too early due to macros, but that + // shoud only lead to sub-optimal recovery, not inaccurate parsing). + fn recover_stmt_(&mut self, break_on_semi: SemiColonMode) { + let mut brace_depth = 0; + let mut bracket_depth = 0; + loop { + match self.token { + token::OpenDelim(token::DelimToken::Brace) => { + brace_depth += 1; + self.bump(); + } + token::OpenDelim(token::DelimToken::Bracket) => { + bracket_depth += 1; + self.bump(); + } + token::CloseDelim(token::DelimToken::Brace) => { + if brace_depth == 0 { + return; + } + brace_depth -= 1; + self.bump(); + } + token::CloseDelim(token::DelimToken::Bracket) => { + bracket_depth -= 1; + if bracket_depth < 0 { + bracket_depth = 0; + } + self.bump(); + } + token::Eof => return, + token::Semi => { + self.bump(); + if break_on_semi == SemiColonMode::Break && + brace_depth == 0 && + bracket_depth == 0 { + return; + } + } + _ => { + self.bump() + } + } + } } - fn parse_stmt_(&mut self) -> PResult<'a, Option> { + fn parse_stmt_(&mut self) -> Option { + self.parse_stmt_without_recovery().unwrap_or_else(|mut e| { + e.emit(); + self.recover_stmt_(SemiColonMode::Break); + None + }) + } + + fn parse_stmt_without_recovery(&mut self) -> PResult<'a, Option> { maybe_whole!(Some deref self, NtStmt); let attrs = try!(self.parse_outer_attributes()); @@ -3767,7 +3927,9 @@ impl<'a> Parser<'a> { } } else { // FIXME: Bad copy of attrs - match try!(self.parse_item_(attrs.clone(), false, true)) { + let restrictions = self.restrictions | NO_NONINLINE_MOD; + match try!(self.with_res(restrictions, + |this| this.parse_item_(attrs.clone(), false, true))) { Some(i) => { let hi = i.span.hi; let decl = P(spanned(lo, hi, DeclKind::Item(i))); @@ -3834,7 +3996,7 @@ impl<'a> Parser<'a> { let lo = self.span.lo; try!(self.expect(&token::OpenDelim(token::Brace))); Ok((try!(self.parse_inner_attributes()), - try!(self.parse_block_tail(lo, BlockCheckMode::Default)))) + try!(self.parse_block_tail(lo, BlockCheckMode::Default)))) } /// Parse the rest of a block expression or function body @@ -3844,7 +4006,7 @@ impl<'a> Parser<'a> { let mut expr = None; while !self.eat(&token::CloseDelim(token::Brace)) { - let Spanned {node, span} = if let Some(s) = try!(self.parse_stmt_()) { + let Spanned {node, span} = if let Some(s) = self.parse_stmt_() { s } else { // Found only `;` or `}`. @@ -3929,17 +4091,21 @@ impl<'a> Parser<'a> { })) } - fn handle_expression_like_statement( - &mut self, - e: P, - span: Span, - stmts: &mut Vec, - last_block_expr: &mut Option>) -> PResult<'a, ()> { + fn handle_expression_like_statement(&mut self, + e: P, + span: Span, + stmts: &mut Vec, + last_block_expr: &mut Option>) + -> PResult<'a, ()> { // expression without semicolon if classify::expr_requires_semi_to_be_stmt(&e) { // Just check for errors and recover; do not eat semicolon yet. - try!(self.commit_stmt(&[], - &[token::Semi, token::CloseDelim(token::Brace)])); + if let Err(mut e) = + self.commit_stmt(&[], &[token::Semi, token::CloseDelim(token::Brace)]) + { + e.emit(); + self.recover_stmt(); + } } match self.token { @@ -4172,8 +4338,8 @@ impl<'a> Parser<'a> { fn forbid_lifetime(&mut self) -> PResult<'a, ()> { if self.token.is_lifetime() { let span = self.span; - return Err(self.span_fatal(span, "lifetime parameters must be declared \ - prior to type parameters")) + return Err(self.diagnostic().struct_span_err(span, "lifetime parameters must be \ + declared prior to type parameters")) } Ok(()) } @@ -4301,7 +4467,8 @@ impl<'a> Parser<'a> { fn parse_fn_args(&mut self, named_args: bool, allow_variadic: bool) -> PResult<'a, (Vec , bool)> { let sp = self.span; - let mut args: Vec> = + let mut variadic = false; + let args: Vec> = try!(self.parse_unspanned_seq( &token::OpenDelim(token::Paren), &token::CloseDelim(token::Paren), @@ -4312,38 +4479,36 @@ impl<'a> Parser<'a> { if allow_variadic { if p.token != token::CloseDelim(token::Paren) { let span = p.span; - return Err(p.span_fatal(span, - "`...` must be last in argument list for variadic function")) + p.span_err(span, + "`...` must be last in argument list for variadic function"); } } else { let span = p.span; - return Err(p.span_fatal(span, - "only foreign functions are allowed to be variadic")) + p.span_err(span, + "only foreign functions are allowed to be variadic"); } + variadic = true; Ok(None) } else { - Ok(Some(try!(p.parse_arg_general(named_args)))) + match p.parse_arg_general(named_args) { + Ok(arg) => Ok(Some(arg)), + Err(mut e) => { + e.emit(); + p.eat_to_tokens(&[&token::Comma, &token::CloseDelim(token::Paren)]); + Ok(None) + } + } } } )); - let variadic = match args.pop() { - Some(None) => true, - Some(x) => { - // Need to put back that last arg - args.push(x); - false - } - None => false - }; + let args: Vec<_> = args.into_iter().filter_map(|x| x).collect(); if variadic && args.is_empty() { self.span_err(sp, "variadic function must be declared with at least one named argument"); } - let args = args.into_iter().map(|x| x.unwrap()).collect(); - Ok((args, variadic)) } @@ -4520,11 +4685,11 @@ impl<'a> Parser<'a> { token::Comma => { self.bump(); let sep = seq_sep_trailing_allowed(token::Comma); - let mut fn_inputs = try!(self.parse_seq_to_before_end( + let mut fn_inputs = self.parse_seq_to_before_end( &token::CloseDelim(token::Paren), sep, parse_arg_fn - )); + ); fn_inputs.insert(0, Arg::new_self(explicit_self_sp, mutbl_self, $self_id)); fn_inputs } @@ -4543,8 +4708,7 @@ impl<'a> Parser<'a> { let fn_inputs = match explicit_self { SelfKind::Static => { let sep = seq_sep_trailing_allowed(token::Comma); - try!(self.parse_seq_to_before_end(&token::CloseDelim(token::Paren), - sep, parse_arg_fn)) + self.parse_seq_to_before_end(&token::CloseDelim(token::Paren), sep, parse_arg_fn) } SelfKind::Value(id) => parse_remaining_arguments!(id), SelfKind::Region(_,_,id) => parse_remaining_arguments!(id), @@ -4575,11 +4739,11 @@ impl<'a> Parser<'a> { } else { try!(self.expect(&token::BinOp(token::Or))); try!(self.parse_obsolete_closure_kind()); - let args = try!(self.parse_seq_to_before_end( + let args = self.parse_seq_to_before_end( &token::BinOp(token::Or), seq_sep_trailing_allowed(token::Comma), |p| p.parse_fn_block_arg() - )); + ); self.bump(); args } @@ -4741,8 +4905,8 @@ impl<'a> Parser<'a> { // eat a matched-delimiter token tree: let delim = try!(self.expect_open_delim()); let tts = try!(self.parse_seq_to_end(&token::CloseDelim(delim), - seq_sep_none(), - |p| p.parse_token_tree())); + seq_sep_none(), + |p| p.parse_token_tree())); let m_ = Mac_ { path: pth, tts: tts, ctxt: EMPTY_CTXT }; let m: ast::Mac = codemap::Spanned { node: m_, span: mk_sp(lo, @@ -5096,11 +5260,8 @@ impl<'a> Parser<'a> { self.push_mod_path(id, outer_attrs); try!(self.expect(&token::OpenDelim(token::Brace))); let mod_inner_lo = self.span.lo; - let old_owns_directory = self.owns_directory; - self.owns_directory = true; let attrs = try!(self.parse_inner_attributes()); let m = try!(self.parse_mod_items(&token::CloseDelim(token::Brace), mod_inner_lo)); - self.owns_directory = old_owns_directory; self.pop_mod_path(); Ok((id, ItemKind::Mod(m), Some(attrs))) } @@ -5177,7 +5338,17 @@ impl<'a> Parser<'a> { let paths = Parser::default_submod_path(id, &dir_path, self.sess.codemap()); - if !self.owns_directory { + if self.restrictions.contains(NO_NONINLINE_MOD) { + let msg = + "Cannot declare a non-inline module inside a block unless it has a path attribute"; + let mut err = self.diagnostic().struct_span_err(id_sp, msg); + if paths.path_exists { + let msg = format!("Maybe `use` the module `{}` instead of redeclaring it", + paths.name); + err.span_note(id_sp, &msg); + } + return Err(err); + } else if !self.owns_directory { let mut err = self.diagnostic().struct_span_err(id_sp, "cannot declare a new module at this location"); let this_module = match self.mod_path_stack.last() { @@ -5801,8 +5972,8 @@ impl<'a> Parser<'a> { // eat a matched-delimiter token tree: let delim = try!(self.expect_open_delim()); let tts = try!(self.parse_seq_to_end(&token::CloseDelim(delim), - seq_sep_none(), - |p| p.parse_token_tree())); + seq_sep_none(), + |p| p.parse_token_tree())); // single-variant-enum... : let m = Mac_ { path: pth, tts: tts, ctxt: EMPTY_CTXT }; let m: ast::Mac = codemap::Spanned { node: m, diff --git a/syntex_syntax/src/print/pprust.rs b/syntex_syntax/src/print/pprust.rs index 393baac6..602aef8d 100644 --- a/syntex_syntax/src/print/pprust.rs +++ b/syntex_syntax/src/print/pprust.rs @@ -11,7 +11,7 @@ pub use self::AnnNode::*; use abi::{self, Abi}; -use ast::{self, TokenTree, BlockCheckMode}; +use ast::{self, TokenTree, BlockCheckMode, PatKind}; use ast::{RegionTyParamBound, TraitTyParamBound, TraitBoundModifier}; use ast::Attribute; use attr::ThinAttributesExt; @@ -2463,8 +2463,8 @@ impl<'a> State<'a> { /* Pat isn't normalized, but the beauty of it is that it doesn't matter */ match pat.node { - ast::PatWild => try!(word(&mut self.s, "_")), - ast::PatIdent(binding_mode, ref path1, ref sub) => { + PatKind::Wild => try!(word(&mut self.s, "_")), + PatKind::Ident(binding_mode, ref path1, ref sub) => { match binding_mode { ast::BindingMode::ByRef(mutbl) => { try!(self.word_nbsp("ref")); @@ -2484,24 +2484,25 @@ impl<'a> State<'a> { None => () } } - ast::PatEnum(ref path, ref args_) => { + PatKind::TupleStruct(ref path, ref args_) => { try!(self.print_path(path, true, 0)); match *args_ { None => try!(word(&mut self.s, "(..)")), Some(ref args) => { - if !args.is_empty() { - try!(self.popen()); - try!(self.commasep(Inconsistent, &args[..], - |s, p| s.print_pat(&p))); - try!(self.pclose()); - } + try!(self.popen()); + try!(self.commasep(Inconsistent, &args[..], + |s, p| s.print_pat(&p))); + try!(self.pclose()); } } } - ast::PatQPath(ref qself, ref path) => { + PatKind::Path(ref path) => { + try!(self.print_path(path, true, 0)); + } + PatKind::QPath(ref qself, ref path) => { try!(self.print_qpath(path, qself, false)); } - ast::PatStruct(ref path, ref fields, etc) => { + PatKind::Struct(ref path, ref fields, etc) => { try!(self.print_path(path, true, 0)); try!(self.nbsp()); try!(self.word_space("{")); @@ -2524,7 +2525,7 @@ impl<'a> State<'a> { try!(space(&mut self.s)); try!(word(&mut self.s, "}")); } - ast::PatTup(ref elts) => { + PatKind::Tup(ref elts) => { try!(self.popen()); try!(self.commasep(Inconsistent, &elts[..], @@ -2534,32 +2535,32 @@ impl<'a> State<'a> { } try!(self.pclose()); } - ast::PatBox(ref inner) => { + PatKind::Box(ref inner) => { try!(word(&mut self.s, "box ")); try!(self.print_pat(&inner)); } - ast::PatRegion(ref inner, mutbl) => { + PatKind::Ref(ref inner, mutbl) => { try!(word(&mut self.s, "&")); if mutbl == ast::Mutability::Mutable { try!(word(&mut self.s, "mut ")); } try!(self.print_pat(&inner)); } - ast::PatLit(ref e) => try!(self.print_expr(&e)), - ast::PatRange(ref begin, ref end) => { + PatKind::Lit(ref e) => try!(self.print_expr(&**e)), + PatKind::Range(ref begin, ref end) => { try!(self.print_expr(&begin)); try!(space(&mut self.s)); try!(word(&mut self.s, "...")); try!(self.print_expr(&end)); } - ast::PatVec(ref before, ref slice, ref after) => { + PatKind::Vec(ref before, ref slice, ref after) => { try!(word(&mut self.s, "[")); try!(self.commasep(Inconsistent, &before[..], |s, p| s.print_pat(&p))); if let Some(ref p) = *slice { if !before.is_empty() { try!(self.word_space(",")); } - if p.node != ast::PatWild { + if p.node != PatKind::Wild { try!(self.print_pat(&p)); } try!(word(&mut self.s, "..")); @@ -2570,7 +2571,7 @@ impl<'a> State<'a> { |s, p| s.print_pat(&p))); try!(word(&mut self.s, "]")); } - ast::PatMac(ref m) => try!(self.print_mac(m, token::Paren)), + PatKind::Mac(ref m) => try!(self.print_mac(m, token::Paren)), } self.ann.post(self, NodePat(pat)) } @@ -2677,7 +2678,7 @@ impl<'a> State<'a> { let m = match *explicit_self { ast::SelfKind::Static => ast::Mutability::Immutable, _ => match decl.inputs[0].pat.node { - ast::PatIdent(ast::BindingMode::ByValue(m), _, _) => m, + PatKind::Ident(ast::BindingMode::ByValue(m), _, _) => m, _ => ast::Mutability::Immutable } }; @@ -2968,7 +2969,7 @@ impl<'a> State<'a> { ast::TyKind::Infer if is_closure => try!(self.print_pat(&input.pat)), _ => { match input.pat.node { - ast::PatIdent(_, ref path1, _) if + PatKind::Ident(_, ref path1, _) if path1.node.name == parse::token::special_idents::invalid.name => { // Do nothing. diff --git a/syntex_syntax/src/visit.rs b/syntex_syntax/src/visit.rs index ca9e4cc7..4c18b063 100644 --- a/syntex_syntax/src/visit.rs +++ b/syntex_syntax/src/visit.rs @@ -427,46 +427,49 @@ pub fn walk_assoc_type_binding<'v, V: Visitor<'v>>(visitor: &mut V, pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat) { match pattern.node { - PatEnum(ref path, ref opt_children) => { + PatKind::TupleStruct(ref path, ref opt_children) => { visitor.visit_path(path, pattern.id); if let Some(ref children) = *opt_children { walk_list!(visitor, visit_pat, children); } } - PatQPath(ref qself, ref path) => { + PatKind::Path(ref path) => { + visitor.visit_path(path, pattern.id); + } + PatKind::QPath(ref qself, ref path) => { visitor.visit_ty(&qself.ty); visitor.visit_path(path, pattern.id) } - PatStruct(ref path, ref fields, _) => { + PatKind::Struct(ref path, ref fields, _) => { visitor.visit_path(path, pattern.id); for field in fields { visitor.visit_ident(field.span, field.node.ident); visitor.visit_pat(&field.node.pat) } } - PatTup(ref tuple_elements) => { + PatKind::Tup(ref tuple_elements) => { walk_list!(visitor, visit_pat, tuple_elements); } - PatBox(ref subpattern) | - PatRegion(ref subpattern, _) => { + PatKind::Box(ref subpattern) | + PatKind::Ref(ref subpattern, _) => { visitor.visit_pat(subpattern) } - PatIdent(_, ref pth1, ref optional_subpattern) => { + PatKind::Ident(_, ref pth1, ref optional_subpattern) => { visitor.visit_ident(pth1.span, pth1.node); walk_opt!(visitor, visit_pat, optional_subpattern); } - PatLit(ref expression) => visitor.visit_expr(expression), - PatRange(ref lower_bound, ref upper_bound) => { + PatKind::Lit(ref expression) => visitor.visit_expr(expression), + PatKind::Range(ref lower_bound, ref upper_bound) => { visitor.visit_expr(lower_bound); visitor.visit_expr(upper_bound) } - PatWild => (), - PatVec(ref prepatterns, ref slice_pattern, ref postpatterns) => { + PatKind::Wild => (), + PatKind::Vec(ref prepatterns, ref slice_pattern, ref postpatterns) => { walk_list!(visitor, visit_pat, prepatterns); walk_opt!(visitor, visit_pat, slice_pattern); walk_list!(visitor, visit_pat, postpatterns); } - PatMac(ref mac) => visitor.visit_mac(mac), + PatKind::Mac(ref mac) => visitor.visit_mac(mac), } }