Skip to content

Commit

Permalink
Auto merge of #88835 - FabianWolff:issue-88770, r=petrochenkov
Browse files Browse the repository at this point in the history
Fix error recovery in format macro parsing

Fixes #88770. Basically, the assumption in the following comment is incorrect:
https://github.com/rust-lang/rust/blob/b69fe57261086e70aea9d5b58819a1794bf7c121/compiler/rustc_builtin_macros/src/format.rs#L167-L172

This is only true in the first iteration of the loop, when [`p.clear_expected_tokens()`](https://github.com/rust-lang/rust/blob/b69fe57261086e70aea9d5b58819a1794bf7c121/compiler/rustc_builtin_macros/src/format.rs#L164) is called. In subsequent iterations, `p.expected_tokens` won't be empty, so `p.expect()` won't actually call `unexpected_try_recover()`:
https://github.com/rust-lang/rust/blob/b69fe57261086e70aea9d5b58819a1794bf7c121/compiler/rustc_parse/src/parser/mod.rs#L487-L498

Instead, it will call `expect_one_of()`, which _can_ recover and return `Ok()`. This PR handles this case to fix the ICE in #88770.
  • Loading branch information
bors committed Sep 24, 2021
2 parents 91d8da1 + a8421ca commit a0648ea
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 18 deletions.
31 changes: 15 additions & 16 deletions compiler/rustc_builtin_macros/src/format.rs
Expand Up @@ -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;
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_parse/src/parser/diagnostics.rs
Expand Up @@ -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)
|| (
Expand All @@ -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);
}
}

Expand Down
11 changes: 11 additions & 0 deletions 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
66 changes: 66 additions & 0 deletions 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

0 comments on commit a0648ea

Please sign in to comment.