From 39d612b7ac08aa97fb78b1791c47584cbdc46d8f Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Sat, 26 Mar 2016 00:13:54 +0200 Subject: [PATCH 1/5] syntax: Prevent bumping the parser EOF to stop infinite loops. --- src/libsyntax/parse/parser.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index b5d29a0d6dbaf..ccb9654aed411 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -261,6 +261,7 @@ pub struct Parser<'a> { /// the previous token or None (only stashed sometimes). pub last_token: Option>, last_token_interpolated: bool, + last_token_eof: bool, pub buffer: [TokenAndSpan; 4], pub buffer_start: isize, pub buffer_end: isize, @@ -369,6 +370,7 @@ impl<'a> Parser<'a> { last_span: span, last_token: None, last_token_interpolated: false, + last_token_eof: false, buffer: [ placeholder.clone(), placeholder.clone(), @@ -982,6 +984,15 @@ impl<'a> Parser<'a> { /// Advance the parser by one token pub fn bump(&mut self) { + if self.last_token_eof { + // Bumping after EOF is a bad sign, usually an infinite loop. + self.bug("attempted to bump the parser past EOF (may be stuck in a loop)"); + } + + if self.token == token::Eof { + self.last_token_eof = true; + } + self.last_span = self.span; // Stash token for error recovery (sometimes; clone is not necessarily cheap). self.last_token = if self.token.is_ident() || From c0167543dbaaf0dff10b8296955b7aa824e6973d Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Sat, 26 Mar 2016 21:37:53 +0200 Subject: [PATCH 2/5] syntax: Stop the bump loop for trait items at } and EOF. backport of 221d0fbad0b201ef9264d3c9a30cd8c143ed51b2 to beta with hand-resolution of conflicts and reverting to `try!` syntax. --- src/libsyntax/parse/parser.rs | 26 ++++++++++++++++--------- src/test/parse-fail/issue-10636-2.rs | 3 +-- src/test/parse-fail/issue-32446.rs | 16 +++++++++++++++ src/test/parse-fail/pat-lt-bracket-6.rs | 2 +- src/test/parse-fail/pat-lt-bracket-7.rs | 2 +- 5 files changed, 36 insertions(+), 13 deletions(-) create mode 100644 src/test/parse-fail/issue-32446.rs diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index ccb9654aed411..64dd60feb4e0a 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -941,7 +941,9 @@ impl<'a> Parser<'a> { { try!(self.expect(bra)); let result = self.parse_seq_to_before_end(ket, sep, f); - self.bump(); + if self.token == *ket { + self.bump(); + } Ok(result) } @@ -1276,15 +1278,21 @@ impl<'a> Parser<'a> { Ok(cua) => cua, Err(e) => { loop { - p.bump(); - if p.token == token::Semi { - p.bump(); - break; - } + match p.token { + token::Eof => break, + + token::CloseDelim(token::Brace) | + token::Semi => { + p.bump(); + break; + } + + token::OpenDelim(token::Brace) => { + try!(p.parse_token_tree()); + break; + } - if p.token == token::OpenDelim(token::DelimToken::Brace) { - try!(p.parse_token_tree()); - break; + _ => p.bump() } } diff --git a/src/test/parse-fail/issue-10636-2.rs b/src/test/parse-fail/issue-10636-2.rs index 41a3b06e6556e..1361f3d31acb9 100644 --- a/src/test/parse-fail/issue-10636-2.rs +++ b/src/test/parse-fail/issue-10636-2.rs @@ -17,5 +17,4 @@ pub fn trace_option(option: Option) { //~ HELP did you mean to close this 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 +//~^ ERROR: unexpected token diff --git a/src/test/parse-fail/issue-32446.rs b/src/test/parse-fail/issue-32446.rs new file mode 100644 index 0000000000000..90b9a4aae8b5b --- /dev/null +++ b/src/test/parse-fail/issue-32446.rs @@ -0,0 +1,16 @@ +// 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. + +// compile-flags: -Z parse-only + +fn main() {} + +// This used to end up in an infite loop trying to bump past EOF. +trait T { ... } //~ ERROR diff --git a/src/test/parse-fail/pat-lt-bracket-6.rs b/src/test/parse-fail/pat-lt-bracket-6.rs index bc27aedb627ee..5ed8f6dee8cd8 100644 --- a/src/test/parse-fail/pat-lt-bracket-6.rs +++ b/src/test/parse-fail/pat-lt-bracket-6.rs @@ -10,5 +10,5 @@ fn main() { let Test(&desc[..]) = x; //~ error: expected one of `,` or `@`, found `[` - //~^ 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 3e9478da44de5..00681e6149785 100644 --- a/src/test/parse-fail/pat-lt-bracket-7.rs +++ b/src/test/parse-fail/pat-lt-bracket-7.rs @@ -10,5 +10,5 @@ fn main() { for thing(x[]) in foo {} //~ error: expected one of `,` or `@`, found `[` - //~^ ERROR: expected `in`, found `]` + //~^ ERROR expected one of `@` or `in`, found `[` } From e175000af1c703deaa2441c33863c00f306bdfd4 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Fri, 25 Mar 2016 18:17:04 +0100 Subject: [PATCH 3/5] Put in `-Z continue-parse-after-error` This works by adding a boolean flag, `continue_after_error`, to `syntax::errors::Handler` that can be imperatively set to `true` or `false` via a new `fn set_continue_after_error`. The flag starts off true (since we generally try to recover from compiler errors, and `Handler` is shared across all phases). Then, during the `phase_1_parse_input`, we consult the setting of the `-Z continue-parse-after-error` debug flag to determine whether we should leave the flag set to `true` or should change it to `false`. ---- (We might consider adding a debugflag to do such aborts in other places where we are currently attempting recovery, such as resolve, but I think the parser is the really important case to handle in the face of #31994 and the parser bugs of varying degrees that were injected by parse error recovery.) --- src/librustc/session/config.rs | 6 ++++++ src/librustc_driver/driver.rs | 4 ++++ src/libsyntax/errors/mod.rs | 9 +++++++++ 3 files changed, 19 insertions(+) diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index ea08bf021fbba..6421629cc7ab8 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -138,6 +138,7 @@ pub struct Options { pub no_trans: bool, pub error_format: ErrorOutputType, pub treat_err_as_bug: bool, + pub continue_parse_after_error: bool, pub mir_opt_level: usize, /// if true, build up the dep-graph @@ -255,6 +256,7 @@ pub fn basic_options() -> Options { parse_only: false, no_trans: false, treat_err_as_bug: false, + continue_parse_after_error: false, mir_opt_level: 1, build_dep_graph: false, dump_dep_graph: false, @@ -629,6 +631,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "run all passes except translation; no output"), treat_err_as_bug: bool = (false, parse_bool, "treat all errors that occur as bugs"), + continue_parse_after_error: bool = (false, parse_bool, + "attempt to recover from parse errors (experimental)"), incr_comp: bool = (false, parse_bool, "enable incremental compilation (experimental)"), dump_dep_graph: bool = (false, parse_bool, @@ -1039,6 +1043,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { let parse_only = debugging_opts.parse_only; let no_trans = debugging_opts.no_trans; let treat_err_as_bug = debugging_opts.treat_err_as_bug; + let continue_parse_after_error = debugging_opts.continue_parse_after_error; let mir_opt_level = debugging_opts.mir_opt_level.unwrap_or(1); let incremental_compilation = debugging_opts.incr_comp; let dump_dep_graph = debugging_opts.dump_dep_graph; @@ -1218,6 +1223,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { parse_only: parse_only, no_trans: no_trans, treat_err_as_bug: treat_err_as_bug, + continue_parse_after_error: continue_parse_after_error, mir_opt_level: mir_opt_level, build_dep_graph: incremental_compilation || dump_dep_graph, dump_dep_graph: dump_dep_graph, diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index b446dec96fbfb..5c7b04ccedacb 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -421,6 +421,8 @@ pub fn phase_1_parse_input(sess: &Session, cfg: ast::CrateConfig, input: &Input) // memory, but they do not restore the initial state. syntax::ext::mtwt::reset_tables(); token::reset_ident_interner(); + let continue_after_error = sess.opts.continue_parse_after_error; + sess.diagnostic().set_continue_after_error(continue_after_error); let krate = time(sess.time_passes(), "parsing", || { match *input { @@ -436,6 +438,8 @@ pub fn phase_1_parse_input(sess: &Session, cfg: ast::CrateConfig, input: &Input) } }); + sess.diagnostic().set_continue_after_error(true); + if sess.opts.debugging_opts.ast_json_noexpand { println!("{}", json::as_json(&krate)); } diff --git a/src/libsyntax/errors/mod.rs b/src/libsyntax/errors/mod.rs index 9e1cb60f54f67..c8c12d5a88334 100644 --- a/src/libsyntax/errors/mod.rs +++ b/src/libsyntax/errors/mod.rs @@ -370,6 +370,7 @@ pub struct Handler { emit: RefCell>, pub can_emit_warnings: bool, treat_err_as_bug: bool, + continue_after_error: Cell, delayed_span_bug: RefCell>, } @@ -392,10 +393,15 @@ impl Handler { emit: RefCell::new(e), can_emit_warnings: can_emit_warnings, treat_err_as_bug: treat_err_as_bug, + continue_after_error: Cell::new(true), delayed_span_bug: RefCell::new(None), } } + pub fn set_continue_after_error(&self, continue_after_error: bool) { + self.continue_after_error.set(continue_after_error); + } + pub fn struct_dummy<'a>(&'a self) -> DiagnosticBuilder<'a> { DiagnosticBuilder::new(&self.emit, Level::Cancelled, "") } @@ -612,6 +618,7 @@ impl Handler { lvl: Level) { if lvl == Warning && !self.can_emit_warnings { return } self.emit.borrow_mut().emit(msp, msg, None, lvl); + if !self.continue_after_error.get() { self.abort_if_errors(); } } pub fn emit_with_code(&self, msp: Option<&MultiSpan>, @@ -620,10 +627,12 @@ impl Handler { lvl: Level) { if lvl == Warning && !self.can_emit_warnings { return } self.emit.borrow_mut().emit(msp, msg, Some(code), lvl); + if !self.continue_after_error.get() { self.abort_if_errors(); } } pub fn custom_emit(&self, rsp: RenderSpan, msg: &str, lvl: Level) { if lvl == Warning && !self.can_emit_warnings { return } self.emit.borrow_mut().custom_emit(&rsp, msg, lvl); + if !self.continue_after_error.get() { self.abort_if_errors(); } } } From 625bba3947b5fca1075d5876c4e9f85c56f50d45 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Sat, 26 Mar 2016 01:36:03 +0100 Subject: [PATCH 4/5] fix compile-fail and parse-fail tests by blindly opting back into parser recovery (so that expected errors match up) I'm opting into parser recovery in all these cases out of expediency, not because the error messages you get with recovery enabled are actually all that usable in all cases listed. --- src/test/compile-fail/issue-12560-2.rs | 2 ++ src/test/compile-fail/issue-28433.rs | 2 ++ src/test/compile-fail/issue-30715.rs | 2 ++ src/test/compile-fail/macro-incomplete-parse.rs | 2 ++ src/test/compile-fail/parse-error-correct.rs | 2 ++ src/test/compile-fail/parser-recovery-1.rs | 2 ++ src/test/compile-fail/parser-recovery-2.rs | 2 ++ src/test/compile-fail/self_type_keyword.rs | 2 ++ src/test/parse-fail/ascii-only-character-escape.rs | 2 +- src/test/parse-fail/bad-char-literals.rs | 2 +- src/test/parse-fail/bad-lit-suffixes.rs | 2 +- src/test/parse-fail/byte-literals.rs | 2 +- src/test/parse-fail/byte-string-literals.rs | 2 +- src/test/parse-fail/issue-10412.rs | 2 +- src/test/parse-fail/issue-23620-invalid-escapes.rs | 2 ++ src/test/parse-fail/lex-bad-binary-literal.rs | 2 ++ src/test/parse-fail/lex-bad-char-literals-1.rs | 2 +- src/test/parse-fail/lex-bad-numeric-literals.rs | 2 +- src/test/parse-fail/lex-bare-cr-string-literal-doc-comment.rs | 2 +- src/test/parse-fail/new-unicode-escapes-4.rs | 2 +- src/test/parse-fail/no-unsafe-self.rs | 2 +- 21 files changed, 31 insertions(+), 11 deletions(-) diff --git a/src/test/compile-fail/issue-12560-2.rs b/src/test/compile-fail/issue-12560-2.rs index 13829d73aadaa..9cbe2ebffe694 100644 --- a/src/test/compile-fail/issue-12560-2.rs +++ b/src/test/compile-fail/issue-12560-2.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// compile-flags: -Z continue-parse-after-error + // For style and consistency reasons, non-parametrized enum variants must // be used simply as `ident` instead of `ident ()`. // This test-case covers enum matching. diff --git a/src/test/compile-fail/issue-28433.rs b/src/test/compile-fail/issue-28433.rs index 3ca2213087d1f..018a40e28ef32 100644 --- a/src/test/compile-fail/issue-28433.rs +++ b/src/test/compile-fail/issue-28433.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// compile-flags: -Z continue-parse-after-error + enum bird { pub duck, //~^ ERROR: expected identifier, found keyword `pub` diff --git a/src/test/compile-fail/issue-30715.rs b/src/test/compile-fail/issue-30715.rs index 67f619b4de4f4..5cacf8f53c62e 100644 --- a/src/test/compile-fail/issue-30715.rs +++ b/src/test/compile-fail/issue-30715.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// compile-flags: -Z continue-parse-after-error + macro_rules! parallel { ( // If future has `pred`/`moelarry` fragments (where "pred" is diff --git a/src/test/compile-fail/macro-incomplete-parse.rs b/src/test/compile-fail/macro-incomplete-parse.rs index 364a7e9cf6d75..0d5f9079649c4 100644 --- a/src/test/compile-fail/macro-incomplete-parse.rs +++ b/src/test/compile-fail/macro-incomplete-parse.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// compile-flags: -Z continue-parse-after-error + macro_rules! ignored_item { () => { fn foo() {} diff --git a/src/test/compile-fail/parse-error-correct.rs b/src/test/compile-fail/parse-error-correct.rs index 7715ed41841cf..17b58a9f7c298 100644 --- a/src/test/compile-fail/parse-error-correct.rs +++ b/src/test/compile-fail/parse-error-correct.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// compile-flags: -Z continue-parse-after-error + // Test that the parser is error correcting missing idents. Despite a parsing // error (or two), we still run type checking (and don't get extra errors there). diff --git a/src/test/compile-fail/parser-recovery-1.rs b/src/test/compile-fail/parser-recovery-1.rs index 674418dcca6ad..85b6246123833 100644 --- a/src/test/compile-fail/parser-recovery-1.rs +++ b/src/test/compile-fail/parser-recovery-1.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// compile-flags: -Z continue-parse-after-error + // Test that we can recover from missing braces in the parser. trait Foo { diff --git a/src/test/compile-fail/parser-recovery-2.rs b/src/test/compile-fail/parser-recovery-2.rs index f1eb696f6ff84..109da6251e37d 100644 --- a/src/test/compile-fail/parser-recovery-2.rs +++ b/src/test/compile-fail/parser-recovery-2.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// compile-flags: -Z continue-parse-after-error + // Test that we can recover from mismatched braces in the parser. trait Foo { diff --git a/src/test/compile-fail/self_type_keyword.rs b/src/test/compile-fail/self_type_keyword.rs index e28197e81faf9..6296673787407 100644 --- a/src/test/compile-fail/self_type_keyword.rs +++ b/src/test/compile-fail/self_type_keyword.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// compile-flags: -Z continue-parse-after-error + struct Self; //~^ ERROR expected identifier, found keyword `Self` diff --git a/src/test/parse-fail/ascii-only-character-escape.rs b/src/test/parse-fail/ascii-only-character-escape.rs index 2094b63ab3688..a8c40225c3021 100644 --- a/src/test/parse-fail/ascii-only-character-escape.rs +++ b/src/test/parse-fail/ascii-only-character-escape.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Z parse-only +// compile-flags: -Z parse-only -Z continue-parse-after-error fn main() { let x = "\x80"; //~ ERROR may only be used diff --git a/src/test/parse-fail/bad-char-literals.rs b/src/test/parse-fail/bad-char-literals.rs index fe8ed8bb9a52f..96311d6de176c 100644 --- a/src/test/parse-fail/bad-char-literals.rs +++ b/src/test/parse-fail/bad-char-literals.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Z parse-only +// compile-flags: -Z parse-only -Z continue-parse-after-error // ignore-tidy-cr // ignore-tidy-tab diff --git a/src/test/parse-fail/bad-lit-suffixes.rs b/src/test/parse-fail/bad-lit-suffixes.rs index d5985fcebeb26..0811a6470247e 100644 --- a/src/test/parse-fail/bad-lit-suffixes.rs +++ b/src/test/parse-fail/bad-lit-suffixes.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Z parse-only +// compile-flags: -Z parse-only -Z continue-parse-after-error extern diff --git a/src/test/parse-fail/byte-literals.rs b/src/test/parse-fail/byte-literals.rs index 3321f2450c188..3ecd7780afd84 100644 --- a/src/test/parse-fail/byte-literals.rs +++ b/src/test/parse-fail/byte-literals.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Z parse-only +// compile-flags: -Z parse-only -Z continue-parse-after-error // ignore-tidy-tab diff --git a/src/test/parse-fail/byte-string-literals.rs b/src/test/parse-fail/byte-string-literals.rs index 22f123416f26e..4eba9e91ca5f4 100644 --- a/src/test/parse-fail/byte-string-literals.rs +++ b/src/test/parse-fail/byte-string-literals.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Z parse-only +// compile-flags: -Z parse-only -Z continue-parse-after-error // ignore-tidy-tab diff --git a/src/test/parse-fail/issue-10412.rs b/src/test/parse-fail/issue-10412.rs index 0b9456bc080d9..b75e7b12bbdc9 100644 --- a/src/test/parse-fail/issue-10412.rs +++ b/src/test/parse-fail/issue-10412.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Z parse-only +// compile-flags: -Z parse-only -Z continue-parse-after-error trait Serializable<'self, T> { //~ ERROR no longer a special lifetime diff --git a/src/test/parse-fail/issue-23620-invalid-escapes.rs b/src/test/parse-fail/issue-23620-invalid-escapes.rs index d2f78ef897b35..821149d1d0087 100644 --- a/src/test/parse-fail/issue-23620-invalid-escapes.rs +++ b/src/test/parse-fail/issue-23620-invalid-escapes.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 -Z continue-parse-after-error + fn main() { let _ = b"\u{a66e}"; //~^ ERROR unicode escape sequences cannot be used as a byte or in a byte string diff --git a/src/test/parse-fail/lex-bad-binary-literal.rs b/src/test/parse-fail/lex-bad-binary-literal.rs index e92000c54ba34..caacb12d0082d 100644 --- a/src/test/parse-fail/lex-bad-binary-literal.rs +++ b/src/test/parse-fail/lex-bad-binary-literal.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 -Z continue-parse-after-error + fn main() { 0b121; //~ ERROR invalid digit for a base 2 literal 0b10_10301; //~ ERROR invalid digit for a base 2 literal diff --git a/src/test/parse-fail/lex-bad-char-literals-1.rs b/src/test/parse-fail/lex-bad-char-literals-1.rs index 7e22a11ca970d..006e3e68d8f2d 100644 --- a/src/test/parse-fail/lex-bad-char-literals-1.rs +++ b/src/test/parse-fail/lex-bad-char-literals-1.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Z parse-only +// compile-flags: -Z parse-only -Z continue-parse-after-error static c3: char = '\x1' //~ ERROR: numeric character escape is too short ; diff --git a/src/test/parse-fail/lex-bad-numeric-literals.rs b/src/test/parse-fail/lex-bad-numeric-literals.rs index cf171b694c377..bb97b037a0028 100644 --- a/src/test/parse-fail/lex-bad-numeric-literals.rs +++ b/src/test/parse-fail/lex-bad-numeric-literals.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Z parse-only +// compile-flags: -Z parse-only -Z continue-parse-after-error fn main() { 0o1.0; //~ ERROR: octal float literal is not supported diff --git a/src/test/parse-fail/lex-bare-cr-string-literal-doc-comment.rs b/src/test/parse-fail/lex-bare-cr-string-literal-doc-comment.rs index aa48144650fed..f894305754319 100644 --- a/src/test/parse-fail/lex-bare-cr-string-literal-doc-comment.rs +++ b/src/test/parse-fail/lex-bare-cr-string-literal-doc-comment.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Z parse-only +// compile-flags: -Z parse-only -Z continue-parse-after-error // ignore-tidy-cr diff --git a/src/test/parse-fail/new-unicode-escapes-4.rs b/src/test/parse-fail/new-unicode-escapes-4.rs index fe125da1755bd..5615ac8df017d 100644 --- a/src/test/parse-fail/new-unicode-escapes-4.rs +++ b/src/test/parse-fail/new-unicode-escapes-4.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Z parse-only +// compile-flags: -Z parse-only -Z continue-parse-after-error pub fn main() { let s = "\u{lol}"; diff --git a/src/test/parse-fail/no-unsafe-self.rs b/src/test/parse-fail/no-unsafe-self.rs index 1cc0e62f5b2d5..cbdf50a7521ac 100644 --- a/src/test/parse-fail/no-unsafe-self.rs +++ b/src/test/parse-fail/no-unsafe-self.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Z parse-only +// compile-flags: -Z parse-only -Z continue-parse-after-error trait A { fn foo(*mut self); //~ ERROR cannot pass self by raw pointer From 9a32f6a284d6814bfa2fceef7dfd5b27472bfc1b Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 18 Mar 2016 15:49:12 +1300 Subject: [PATCH 5/5] Don't loop forever on error recovery with EOF closes #31804 --- src/libsyntax/parse/parser.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 64dd60feb4e0a..f11c12a059a6a 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -3809,7 +3809,9 @@ impl<'a> Parser<'a> { fn recover_stmt_(&mut self, break_on_semi: SemiColonMode) { let mut brace_depth = 0; let mut bracket_depth = 0; + debug!("recover_stmt_ enter loop"); loop { + debug!("recover_stmt_ loop {:?}", self.token); match self.token { token::OpenDelim(token::DelimToken::Brace) => { brace_depth += 1; @@ -3821,6 +3823,7 @@ impl<'a> Parser<'a> { } token::CloseDelim(token::DelimToken::Brace) => { if brace_depth == 0 { + debug!("recover_stmt_ return - close delim {:?}", self.token); return; } brace_depth -= 1; @@ -3833,12 +3836,16 @@ impl<'a> Parser<'a> { } self.bump(); } - token::Eof => return, + token::Eof => { + debug!("recover_stmt_ return - Eof"); + return; + } token::Semi => { self.bump(); if break_on_semi == SemiColonMode::Break && brace_depth == 0 && bracket_depth == 0 { + debug!("recover_stmt_ return - Semi"); return; } } @@ -4027,6 +4034,8 @@ impl<'a> Parser<'a> { while !self.eat(&token::CloseDelim(token::Brace)) { let Spanned {node, span} = if let Some(s) = self.parse_stmt_() { s + } else if self.token == token::Eof { + break; } else { // Found only `;` or `}`. continue;