Auto merge of #88835 - FabianWolff:issue-88770, r=petrochenkov
Fix error recovery in format macro parsing Fixes #88770. Basically, the assumption in the following comment is incorrect:b69fe57261/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()`](b69fe57261/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()`:b69fe57261/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.
This commit is contained in:
commit
a0648eab36
4 changed files with 94 additions and 18 deletions
|
@ -164,14 +164,8 @@ fn parse_args<'a>(
|
||||||
p.clear_expected_tokens();
|
p.clear_expected_tokens();
|
||||||
}
|
}
|
||||||
|
|
||||||
// `Parser::expect` tries to recover using the
|
match p.expect(&token::Comma) {
|
||||||
// `Parser::unexpected_try_recover` function. This function is able
|
Err(mut err) => {
|
||||||
// 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() {
|
match token::TokenKind::Comma.similar_tokens() {
|
||||||
Some(tks) if tks.contains(&p.token.kind) => {
|
Some(tks) if tks.contains(&p.token.kind) => {
|
||||||
// If a similar token is found, then it may be a typo. We
|
// If a similar token is found, then it may be a typo. We
|
||||||
|
@ -183,6 +177,11 @@ fn parse_args<'a>(
|
||||||
_ => return Err(err),
|
_ => return Err(err),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Ok(recovered) => {
|
||||||
|
assert!(recovered);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
first = false;
|
first = false;
|
||||||
if p.token == token::Eof {
|
if p.token == token::Eof {
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -277,7 +277,7 @@ impl<'a> Parser<'a> {
|
||||||
self.struct_span_err(sp, &msg)
|
self.struct_span_err(sp, &msg)
|
||||||
.span_suggestion_short(sp, "change this to `;`", ";".to_string(), appl)
|
.span_suggestion_short(sp, "change this to `;`", ";".to_string(), appl)
|
||||||
.emit();
|
.emit();
|
||||||
return Ok(false);
|
return Ok(true);
|
||||||
} else if self.look_ahead(0, |t| {
|
} else if self.look_ahead(0, |t| {
|
||||||
t == &token::CloseDelim(token::Brace)
|
t == &token::CloseDelim(token::Brace)
|
||||||
|| (
|
|| (
|
||||||
|
@ -295,7 +295,7 @@ impl<'a> Parser<'a> {
|
||||||
.span_label(self.token.span, "unexpected token")
|
.span_label(self.token.span, "unexpected token")
|
||||||
.span_suggestion_short(sp, "add `;` here", ";".to_string(), appl)
|
.span_suggestion_short(sp, "add `;` here", ";".to_string(), appl)
|
||||||
.emit();
|
.emit();
|
||||||
return Ok(false);
|
return Ok(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
11
src/test/ui/parser/issue-88770.rs
Normal file
11
src/test/ui/parser/issue-88770.rs
Normal file
|
@ -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
src/test/ui/parser/issue-88770.stderr
Normal file
66
src/test/ui/parser/issue-88770.stderr
Normal file
|
@ -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
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue