From 6d85bb953521039350a915a73033a2e46e1a8665 Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Wed, 10 Aug 2022 02:29:28 +0900 Subject: [PATCH] suggest a missing semicolon before an array --- compiler/rustc_parse/src/parser/expr.rs | 42 +++++++++++++++++++ ...-suggest-suggest-semicolon-before-array.rs | 8 ++++ ...gest-suggest-semicolon-before-array.stderr | 10 +++++ ...ggest-suggest-semicolon-before-array.fixed | 11 +++++ .../suggest-suggest-semicolon-before-array.rs | 11 +++++ ...gest-suggest-semicolon-before-array.stderr | 13 ++++++ 6 files changed, 95 insertions(+) create mode 100644 src/test/ui/parser/do-not-suggest-suggest-semicolon-before-array.rs create mode 100644 src/test/ui/parser/do-not-suggest-suggest-semicolon-before-array.stderr create mode 100644 src/test/ui/parser/suggest-suggest-semicolon-before-array.fixed create mode 100644 src/test/ui/parser/suggest-suggest-semicolon-before-array.rs create mode 100644 src/test/ui/parser/suggest-suggest-semicolon-before-array.stderr diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index e473f4d30cf09..b8bd960a5b3d6 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1258,8 +1258,11 @@ impl<'a> Parser<'a> { /// Parse an indexing expression `expr[...]`. fn parse_index_expr(&mut self, lo: Span, base: P) -> PResult<'a, P> { + let prev_span = self.prev_token.span; + let open_delim_span = self.token.span; self.bump(); // `[` let index = self.parse_expr()?; + self.suggest_missing_semicolon_before_array(prev_span, open_delim_span)?; self.expect(&token::CloseDelim(Delimiter::Bracket))?; Ok(self.mk_expr(lo.to(self.prev_token.span), self.mk_index(base, index), AttrVec::new())) } @@ -2056,6 +2059,45 @@ impl<'a> Parser<'a> { } } + fn suggest_missing_semicolon_before_array( + &self, + prev_span: Span, + open_delim_span: Span, + ) -> PResult<'a, ()> { + if self.token.kind == token::Comma { + let mut snapshot = self.create_snapshot_for_diagnostic(); + snapshot.bump(); + match snapshot.parse_seq_to_before_end( + &token::CloseDelim(Delimiter::Bracket), + SeqSep::trailing_allowed(token::Comma), + |p| p.parse_expr(), + ) { + Ok(_) + // When the close delim is `)`, `token.kind` is expected to be `token::CloseDelim(Delimiter::Parenthesis)`, + // but the actual `token.kind` is `token::CloseDelim(Delimiter::Bracket)`. + // This is because the `token.kind` of the close delim is treated as the same as + // that of the open delim in `TokenTreesReader::parse_token_tree`, even if the delimiters of them are different. + // Therefore, `token.kind` should not be compared here. + if snapshot + .span_to_snippet(snapshot.token.span) + .map_or(false, |snippet| snippet == "]") => + { + let mut err = self.struct_span_err(open_delim_span, "expected `;`, found `[`"); + err.span_suggestion_verbose( + prev_span.shrink_to_hi(), + "consider adding `;` here", + ';', + Applicability::MaybeIncorrect, + ); + return Err(err); + } + Ok(_) => (), + Err(err) => err.cancel(), + } + } + Ok(()) + } + /// Parses a block or unsafe block. pub(super) fn parse_block_expr( &mut self, diff --git a/src/test/ui/parser/do-not-suggest-suggest-semicolon-before-array.rs b/src/test/ui/parser/do-not-suggest-suggest-semicolon-before-array.rs new file mode 100644 index 0000000000000..7ebf3f6b0d899 --- /dev/null +++ b/src/test/ui/parser/do-not-suggest-suggest-semicolon-before-array.rs @@ -0,0 +1,8 @@ +fn foo() {} + +fn bar() -> [u8; 2] { + foo() + [1, 3) //~ ERROR expected one of `.`, `?`, `]`, or an operator, found `,` +} + +fn main() {} diff --git a/src/test/ui/parser/do-not-suggest-suggest-semicolon-before-array.stderr b/src/test/ui/parser/do-not-suggest-suggest-semicolon-before-array.stderr new file mode 100644 index 0000000000000..d6e8db803299c --- /dev/null +++ b/src/test/ui/parser/do-not-suggest-suggest-semicolon-before-array.stderr @@ -0,0 +1,10 @@ +error: expected one of `.`, `?`, `]`, or an operator, found `,` + --> $DIR/do-not-suggest-suggest-semicolon-before-array.rs:5:5 + | +LL | [1, 3) + | ^ ^ help: `]` may belong here + | | + | unclosed delimiter + +error: aborting due to previous error + diff --git a/src/test/ui/parser/suggest-suggest-semicolon-before-array.fixed b/src/test/ui/parser/suggest-suggest-semicolon-before-array.fixed new file mode 100644 index 0000000000000..a06b58b2740fa --- /dev/null +++ b/src/test/ui/parser/suggest-suggest-semicolon-before-array.fixed @@ -0,0 +1,11 @@ +// run-rustfix +#![allow(dead_code)] + +fn foo() {} + +fn bar() -> [u8; 2] { + foo(); + [1, 3] //~ ERROR expected `;`, found `[` +} + +fn main() {} diff --git a/src/test/ui/parser/suggest-suggest-semicolon-before-array.rs b/src/test/ui/parser/suggest-suggest-semicolon-before-array.rs new file mode 100644 index 0000000000000..f601ca2aef54e --- /dev/null +++ b/src/test/ui/parser/suggest-suggest-semicolon-before-array.rs @@ -0,0 +1,11 @@ +// run-rustfix +#![allow(dead_code)] + +fn foo() {} + +fn bar() -> [u8; 2] { + foo() + [1, 3] //~ ERROR expected `;`, found `[` +} + +fn main() {} diff --git a/src/test/ui/parser/suggest-suggest-semicolon-before-array.stderr b/src/test/ui/parser/suggest-suggest-semicolon-before-array.stderr new file mode 100644 index 0000000000000..bf86b43554d1a --- /dev/null +++ b/src/test/ui/parser/suggest-suggest-semicolon-before-array.stderr @@ -0,0 +1,13 @@ +error: expected `;`, found `[` + --> $DIR/suggest-suggest-semicolon-before-array.rs:8:5 + | +LL | [1, 3] + | ^ + | +help: consider adding `;` here + | +LL | foo(); + | + + +error: aborting due to previous error +