diff options
| author | bors <bors@rust-lang.org> | 2020-09-02 19:29:27 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2020-09-02 19:29:27 +0000 |
| commit | 80fc9b0ecb29050d45b17c64af004200afd3cfc2 (patch) | |
| tree | 3d0269d8f9ecb027bd59a942462003ed9e01e4ea /compiler | |
| parent | a167485e279be8a11c9c09d0dddaf1d7c5724f1c (diff) | |
| parent | 3524c3ef4371d0bf4dd03568a004039f18c154f7 (diff) | |
| download | rust-80fc9b0ecb29050d45b17c64af004200afd3cfc2.tar.gz rust-80fc9b0ecb29050d45b17c64af004200afd3cfc2.zip | |
Auto merge of #76160 - scileo:format-recovery, r=petrochenkov
Improve recovery on malformed format call The token following a format expression should be a comma. However, when it is replaced with a similar token (such as a dot), then the corresponding error is emitted, but the token is treated as a comma, and the parsing step continues. r? @petrochenkov
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_builtin_macros/src/format.rs | 28 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/mod.rs | 4 |
2 files changed, 24 insertions, 8 deletions
diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs index 48506148ed9..5d6f791f137 100644 --- a/compiler/rustc_builtin_macros/src/format.rs +++ b/compiler/rustc_builtin_macros/src/format.rs @@ -161,14 +161,26 @@ fn parse_args<'a>( while p.token != token::Eof { if !p.eat(&token::Comma) { if first { - // After `format!(""` we always expect *only* a comma... - let mut err = ecx.struct_span_err(p.token.span, "expected token: `,`"); - err.span_label(p.token.span, "expected `,`"); - p.maybe_annotate_with_ascription(&mut err, false); - return Err(err); - } else { - // ...after that delegate to `expect` to also include the other expected tokens. - let _ = p.expect(&token::Comma)?; + 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(); + } + // Otherwise stop the parsing and return the error. + _ => return Err(err), } } first = false; diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index d90a61cd34a..84edfecad19 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -1234,6 +1234,10 @@ impl<'a> Parser<'a> { *t == token::OpenDelim(token::Brace) || *t == token::BinOp(token::Star) }) } + + pub fn clear_expected_tokens(&mut self) { + self.expected_tokens.clear(); + } } crate fn make_unclosed_delims_error( |
