diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index a8d35783c6f..59e79200568 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -105,6 +105,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 @@ -598,7 +604,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; @@ -840,6 +846,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. @@ -850,7 +865,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) } @@ -861,24 +876,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 @@ -893,7 +937,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) } @@ -929,7 +973,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)) @@ -1216,7 +1260,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()); @@ -2289,14 +2351,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; @@ -2641,45 +2726,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 @@ -2691,11 +2747,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; @@ -2712,7 +2766,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())) + } + } + } } } @@ -3149,8 +3231,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( - Restrictions::RESTRICTION_NO_STRUCT_LITERAL, None)); + let discriminant = try!(self.parse_expr_res(Restrictions::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 { @@ -3162,7 +3244,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(); @@ -3520,7 +3614,11 @@ 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 = PatKind::Struct(path, fields, etc); } @@ -3674,10 +3772,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_()) } - fn parse_stmt_(&mut self) -> PResult<'a, Option> { + // 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) -> 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()); @@ -3833,7 +3993,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 @@ -3843,7 +4003,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 `}`. @@ -3928,17 +4088,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 { @@ -4171,8 +4335,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(()) } @@ -4300,7 +4464,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), @@ -4311,38 +4476,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)) } @@ -4519,11 +4682,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 } @@ -4542,8 +4705,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), @@ -4574,11 +4736,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 } @@ -4740,8 +4902,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, @@ -5800,8 +5962,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/src/test/compile-fail/issue-30715.rs b/src/test/compile-fail/issue-30715.rs index 7ad43954010..67f619b4de4 100644 --- a/src/test/compile-fail/issue-30715.rs +++ b/src/test/compile-fail/issue-30715.rs @@ -25,7 +25,7 @@ macro_rules! parallel { fn main() { parallel! { for i in 0..n { - x += i; //~ ERROR no rules expected the token `+=` - } + x += i; //~ ERROR expected `:`, found `+=` + } //~ ERROR unexpected end of macro invocation } } diff --git a/src/test/compile-fail/macro-incomplete-parse.rs b/src/test/compile-fail/macro-incomplete-parse.rs index 32770d90189..364a7e9cf6d 100644 --- a/src/test/compile-fail/macro-incomplete-parse.rs +++ b/src/test/compile-fail/macro-incomplete-parse.rs @@ -18,7 +18,7 @@ macro_rules! ignored_item { macro_rules! ignored_expr { () => ( 1, //~ ERROR unexpected token: `,` - 2 ) //~ ERROR macro expansion ignores token `2` + 2 ) } macro_rules! ignored_pat { @@ -28,7 +28,7 @@ macro_rules! ignored_pat { ignored_item!(); //~ NOTE caused by the macro expansion here fn main() { - ignored_expr!(); //~ NOTE caused by the macro expansion here + ignored_expr!(); match 1 { ignored_pat!() => (), //~ NOTE caused by the macro expansion here _ => (), diff --git a/src/test/compile-fail/parser-recovery-1.rs b/src/test/compile-fail/parser-recovery-1.rs new file mode 100644 index 00000000000..674418dcca6 --- /dev/null +++ b/src/test/compile-fail/parser-recovery-1.rs @@ -0,0 +1,22 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that we can recover from missing braces in the parser. + +trait Foo { + fn bar() { + let x = foo(); //~ ERROR unresolved name `foo` + +} + +fn main() { + let x = y.; //~ ERROR unexpected token + //~^ ERROR unresolved name `y` +} //~ ERROR this file contains an un-closed delimiter diff --git a/src/test/parse-fail/variadic-ffi-1.rs b/src/test/compile-fail/parser-recovery-2.rs similarity index 52% rename from src/test/parse-fail/variadic-ffi-1.rs rename to src/test/compile-fail/parser-recovery-2.rs index 63a36e98439..f1eb696f6ff 100644 --- a/src/test/parse-fail/variadic-ffi-1.rs +++ b/src/test/compile-fail/parser-recovery-2.rs @@ -1,4 +1,4 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -8,11 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Z parse-only +// Test that we can recover from mismatched braces in the parser. -extern { - fn printf(...); //~ ERROR: variadic function must be declared with at least one named argument - fn printf(..., foo: isize); //~ ERROR: `...` must be last in argument list for variadic function +trait Foo { + fn bar() { + let x = foo(); //~ ERROR unresolved name `foo` + ) //~ ERROR incorrect close delimiter: `)` } -fn main() {} +fn main() { + let x = y.; //~ ERROR unexpected token + //~^ ERROR unresolved name `y` +} diff --git a/src/test/parse-fail/brace-after-qualified-path-in-match.rs b/src/test/parse-fail/brace-after-qualified-path-in-match.rs index 66f462df05a..ff434d87e1f 100644 --- a/src/test/parse-fail/brace-after-qualified-path-in-match.rs +++ b/src/test/parse-fail/brace-after-qualified-path-in-match.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// compile-flags: -Z parse-only + fn foo() { match x { ::Type{key: value} => (), diff --git a/src/test/parse-fail/issue-10636-2.rs b/src/test/parse-fail/issue-10636-2.rs index f57abf8929e..41a3b06e655 100644 --- a/src/test/parse-fail/issue-10636-2.rs +++ b/src/test/parse-fail/issue-10636-2.rs @@ -8,8 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// FIXME(31528) we emit a bunch of silly errors here due to continuing past the +// first one. This would be easy-ish to address by better recovery in tokenisation. + // compile-flags: -Z parse-only -pub fn trace_option(option: Option) { +pub fn trace_option(option: Option) { //~ HELP did you mean to close this delimiter? option.map(|some| 42; //~ NOTE: unclosed delimiter + //~^ ERROR: expected one of } //~ ERROR: incorrect close delimiter +//~^ ERROR: expected one of +//~ ERROR: this file contains an un-closed delimiter diff --git a/src/test/parse-fail/issue-14303-path.rs b/src/test/parse-fail/issue-14303-path.rs index f0d1feffec8..7c30b5f2629 100644 --- a/src/test/parse-fail/issue-14303-path.rs +++ b/src/test/parse-fail/issue-14303-path.rs @@ -12,3 +12,4 @@ fn bar<'a, T>(x: mymodule::X<'a, T, 'b, 'c>) {} //~^ ERROR lifetime parameters must be declared prior to type parameters +//~^^ ERROR unexpected token diff --git a/src/test/parse-fail/issue-2354.rs b/src/test/parse-fail/issue-2354.rs index 0b380d6ae88..2e799a72c81 100644 --- a/src/test/parse-fail/issue-2354.rs +++ b/src/test/parse-fail/issue-2354.rs @@ -12,8 +12,8 @@ fn foo() { //~ HELP did you mean to close this delimiter? match Some(x) { - Some(y) { panic!(); } - None { panic!(); } + Some(y) => { panic!(); } + None => { panic!(); } } fn bar() { diff --git a/src/test/parse-fail/match-refactor-to-expr.rs b/src/test/parse-fail/match-refactor-to-expr.rs index e85fb3c9dd5..b99d0493ff7 100644 --- a/src/test/parse-fail/match-refactor-to-expr.rs +++ b/src/test/parse-fail/match-refactor-to-expr.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// compile-flags: -Z parse-only + fn main() { let foo = match //~ NOTE did you mean to remove this `match` keyword? diff --git a/src/test/parse-fail/paren-after-qualified-path-in-match.rs b/src/test/parse-fail/paren-after-qualified-path-in-match.rs index d06fd2bb4e7..d3aa4b72b78 100644 --- a/src/test/parse-fail/paren-after-qualified-path-in-match.rs +++ b/src/test/parse-fail/paren-after-qualified-path-in-match.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// compile-flags: -Z parse-only + fn foo() { match x { ::Type(2) => (), diff --git a/src/test/parse-fail/pat-lt-bracket-4.rs b/src/test/parse-fail/pat-lt-bracket-4.rs index 3d9b492307a..a163b38b492 100644 --- a/src/test/parse-fail/pat-lt-bracket-4.rs +++ b/src/test/parse-fail/pat-lt-bracket-4.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// compile-flags: -Z parse-only + enum BtNode { Node(u32,Box,Box), Leaf(u32), diff --git a/src/test/parse-fail/pat-lt-bracket-6.rs b/src/test/parse-fail/pat-lt-bracket-6.rs index 72fdae82260..bc27aedb627 100644 --- a/src/test/parse-fail/pat-lt-bracket-6.rs +++ b/src/test/parse-fail/pat-lt-bracket-6.rs @@ -10,4 +10,5 @@ fn main() { let Test(&desc[..]) = x; //~ error: expected one of `,` or `@`, found `[` + //~^ ERROR expected one of `:`, `;`, or `=`, found `..` } diff --git a/src/test/parse-fail/pat-lt-bracket-7.rs b/src/test/parse-fail/pat-lt-bracket-7.rs index c7731d156ad..3e9478da44d 100644 --- a/src/test/parse-fail/pat-lt-bracket-7.rs +++ b/src/test/parse-fail/pat-lt-bracket-7.rs @@ -9,5 +9,6 @@ // except according to those terms. fn main() { - for thing(x[]) {} //~ error: expected one of `,` or `@`, found `[` + for thing(x[]) in foo {} //~ error: expected one of `,` or `@`, found `[` + //~^ ERROR: expected `in`, found `]` } diff --git a/src/test/parse-fail/struct-literal-in-for.rs b/src/test/parse-fail/struct-literal-in-for.rs index 107b836d160..e57298f7280 100644 --- a/src/test/parse-fail/struct-literal-in-for.rs +++ b/src/test/parse-fail/struct-literal-in-for.rs @@ -23,7 +23,7 @@ impl Foo { fn main() { for x in Foo { x: 3 //~ ERROR expected type, found `3` - }.hi() { + }.hi() { //~ ERROR expected one of `.`, `;`, `}`, or an operator, found `{` println!("yo"); } } diff --git a/src/test/parse-fail/struct-literal-in-if.rs b/src/test/parse-fail/struct-literal-in-if.rs index b1cccc51d7b..6bf41b7a450 100644 --- a/src/test/parse-fail/struct-literal-in-if.rs +++ b/src/test/parse-fail/struct-literal-in-if.rs @@ -23,7 +23,7 @@ impl Foo { fn main() { if Foo { x: 3 //~ ERROR expected type, found `3` - }.hi() { + }.hi() { //~ ERROR expected one of `.`, `;`, `}`, or an operator, found `{` println!("yo"); } } diff --git a/src/test/parse-fail/struct-literal-in-match-discriminant.rs b/src/test/parse-fail/struct-literal-in-match-discriminant.rs index 42b3e75bcf6..679f4542824 100644 --- a/src/test/parse-fail/struct-literal-in-match-discriminant.rs +++ b/src/test/parse-fail/struct-literal-in-match-discriminant.rs @@ -20,6 +20,6 @@ fn main() { } { Foo { x: x - } => {} + } => {} //~ ERROR expected one of `.`, `;`, `}`, or an operator, found `=>` } } diff --git a/src/test/parse-fail/struct-literal-in-while.rs b/src/test/parse-fail/struct-literal-in-while.rs index 1c52dc48ccd..b388aac2c54 100644 --- a/src/test/parse-fail/struct-literal-in-while.rs +++ b/src/test/parse-fail/struct-literal-in-while.rs @@ -23,7 +23,7 @@ impl Foo { fn main() { while Foo { x: 3 //~ ERROR expected type, found `3` - }.hi() { + }.hi() { //~ ERROR expected one of `.`, `;`, `}`, or an operator, found `{` println!("yo"); } }