From a8421cacfec5798f600549508545b85003c2143c Mon Sep 17 00:00:00 2001 From: Fabian Wolff Date: Fri, 10 Sep 2021 22:33:44 +0200 Subject: [PATCH] Fix error recovery in format macro parsing --- compiler/rustc_builtin_macros/src/format.rs | 31 +++++---- .../rustc_parse/src/parser/diagnostics.rs | 4 +- src/test/ui/parser/issue-88770.rs | 11 ++++ src/test/ui/parser/issue-88770.stderr | 66 +++++++++++++++++++ 4 files changed, 94 insertions(+), 18 deletions(-) create mode 100644 src/test/ui/parser/issue-88770.rs create mode 100644 src/test/ui/parser/issue-88770.stderr diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs index 8508b3b7ae6ed..cbed1bb850c42 100644 --- a/compiler/rustc_builtin_macros/src/format.rs +++ b/compiler/rustc_builtin_macros/src/format.rs @@ -164,23 +164,22 @@ fn parse_args<'a>( p.clear_expected_tokens(); } - // `Parser::expect` tries to recover using the - // `Parser::unexpected_try_recover` function. This function is able - // to recover if the expected token is a closing delimiter. - // - // As `,` is not a closing delimiter, it will always return an `Err` - // variant. - let mut err = p.expect(&token::Comma).unwrap_err(); - - match token::TokenKind::Comma.similar_tokens() { - Some(tks) if tks.contains(&p.token.kind) => { - // If a similar token is found, then it may be a typo. We - // consider it as a comma, and continue parsing. - err.emit(); - p.bump(); + match p.expect(&token::Comma) { + Err(mut err) => { + match token::TokenKind::Comma.similar_tokens() { + Some(tks) if tks.contains(&p.token.kind) => { + // If a similar token is found, then it may be a typo. We + // consider it as a comma, and continue parsing. + err.emit(); + p.bump(); + } + // Otherwise stop the parsing and return the error. + _ => return Err(err), + } + } + Ok(recovered) => { + assert!(recovered); } - // Otherwise stop the parsing and return the error. - _ => return Err(err), } } first = false; diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 94ca70d3f9578..c2db5a027054c 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -277,7 +277,7 @@ impl<'a> Parser<'a> { self.struct_span_err(sp, &msg) .span_suggestion_short(sp, "change this to `;`", ";".to_string(), appl) .emit(); - return Ok(false); + return Ok(true); } else if self.look_ahead(0, |t| { t == &token::CloseDelim(token::Brace) || ( @@ -295,7 +295,7 @@ impl<'a> Parser<'a> { .span_label(self.token.span, "unexpected token") .span_suggestion_short(sp, "add `;` here", ";".to_string(), appl) .emit(); - return Ok(false); + return Ok(true); } } diff --git a/src/test/ui/parser/issue-88770.rs b/src/test/ui/parser/issue-88770.rs new file mode 100644 index 0000000000000..bf89033f560e9 --- /dev/null +++ b/src/test/ui/parser/issue-88770.rs @@ -0,0 +1,11 @@ +// Regression test for the ICE described in #88770. + +// error-pattern:this file contains an unclosed delimiter +// error-pattern:expected one of +// error-pattern:missing `in` in `for` loop +// error-pattern:expected `;`, found `e` + +fn m(){print!("",(c for&g +u +e +e diff --git a/src/test/ui/parser/issue-88770.stderr b/src/test/ui/parser/issue-88770.stderr new file mode 100644 index 0000000000000..c7e24155d1692 --- /dev/null +++ b/src/test/ui/parser/issue-88770.stderr @@ -0,0 +1,66 @@ +error: this file contains an unclosed delimiter + --> $DIR/issue-88770.rs:11:3 + | +LL | fn m(){print!("",(c for&g + | - - - unclosed delimiter + | | | + | | unclosed delimiter + | unclosed delimiter +... +LL | e + | ^ + +error: this file contains an unclosed delimiter + --> $DIR/issue-88770.rs:11:3 + | +LL | fn m(){print!("",(c for&g + | - - - unclosed delimiter + | | | + | | unclosed delimiter + | unclosed delimiter +... +LL | e + | ^ + +error: this file contains an unclosed delimiter + --> $DIR/issue-88770.rs:11:3 + | +LL | fn m(){print!("",(c for&g + | - - - unclosed delimiter + | | | + | | unclosed delimiter + | unclosed delimiter +... +LL | e + | ^ + +error: missing `in` in `for` loop + --> $DIR/issue-88770.rs:8:26 + | +LL | fn m(){print!("",(c for&g + | __________________________^ +LL | | u + | |_ help: try adding `in` here + +error: expected one of `!`, `)`, `,`, `.`, `::`, `?`, `{`, or an operator, found keyword `for` + --> $DIR/issue-88770.rs:8:21 + | +LL | fn m(){print!("",(c for&g + | ^^^ expected one of 8 possible tokens + +error: expected `;`, found `e` + --> $DIR/issue-88770.rs:10:2 + | +LL | e + | ^ help: add `;` here +LL | e + | - unexpected token + +error: expected one of `!`, `,`, `.`, `::`, `?`, `{`, or an operator, found `)` + --> $DIR/issue-88770.rs:11:3 + | +LL | e + | ^ expected one of 7 possible tokens + +error: aborting due to 7 previous errors +