From 48c0341a7081bb74bb4635529a94298b9be4b459 Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Fri, 12 Aug 2022 18:11:01 +0900 Subject: [PATCH 1/2] suggest removing a semicolon after impl/trait items --- compiler/rustc_parse/src/parser/item.rs | 38 +++++++++++++++++-- ...ing-semicolon-after-impl-trait-items.fixed | 7 ++++ ...moving-semicolon-after-impl-trait-items.rs | 7 ++++ ...ng-semicolon-after-impl-trait-items.stderr | 18 +++++++++ 4 files changed, 66 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/parser/suggest-removing-semicolon-after-impl-trait-items.fixed create mode 100644 src/test/ui/parser/suggest-removing-semicolon-after-impl-trait-items.rs create mode 100644 src/test/ui/parser/suggest-removing-semicolon-after-impl-trait-items.stderr diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 72c23776d3399..8f4edf6ce4800 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -670,14 +670,44 @@ impl<'a> Parser<'a> { } match parse_item(self) { Ok(None) => { + let is_unnecessary_semicolon = !items.is_empty() + // When the close delim is `)` in a case like the following, `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. + // + // issue-60075.rs + // ``` + // trait T { + // fn qux() -> Option { + // let _ = if true { + // }); + // ^ this close delim + // Some(4) + // } + // ``` + && self + .span_to_snippet(self.prev_token.span) + .map_or(false, |snippet| snippet == "}") + && self.token.kind == token::Semi; + let semicolon_span = self.token.span; // We have to bail or we'll potentially never make progress. let non_item_span = self.token.span; self.consume_block(Delimiter::Brace, ConsumeClosingDelim::Yes); - self.struct_span_err(non_item_span, "non-item in item list") - .span_label(open_brace_span, "item list starts here") + let mut err = self.struct_span_err(non_item_span, "non-item in item list"); + err.span_label(open_brace_span, "item list starts here") .span_label(non_item_span, "non-item starts here") - .span_label(self.prev_token.span, "item list ends here") - .emit(); + .span_label(self.prev_token.span, "item list ends here"); + if is_unnecessary_semicolon { + err.span_suggestion_verbose( + semicolon_span, + "consider removing this semicolon", + "", + Applicability::MaybeIncorrect, + ); + } + err.emit(); break; } Ok(Some(item)) => items.extend(item), diff --git a/src/test/ui/parser/suggest-removing-semicolon-after-impl-trait-items.fixed b/src/test/ui/parser/suggest-removing-semicolon-after-impl-trait-items.fixed new file mode 100644 index 0000000000000..63704735490fa --- /dev/null +++ b/src/test/ui/parser/suggest-removing-semicolon-after-impl-trait-items.fixed @@ -0,0 +1,7 @@ +// run-rustfix + +trait Foo { + fn bar() {} //~ ERROR non-item in item list +} + +fn main() {} diff --git a/src/test/ui/parser/suggest-removing-semicolon-after-impl-trait-items.rs b/src/test/ui/parser/suggest-removing-semicolon-after-impl-trait-items.rs new file mode 100644 index 0000000000000..4650b05e20ce8 --- /dev/null +++ b/src/test/ui/parser/suggest-removing-semicolon-after-impl-trait-items.rs @@ -0,0 +1,7 @@ +// run-rustfix + +trait Foo { + fn bar() {}; //~ ERROR non-item in item list +} + +fn main() {} diff --git a/src/test/ui/parser/suggest-removing-semicolon-after-impl-trait-items.stderr b/src/test/ui/parser/suggest-removing-semicolon-after-impl-trait-items.stderr new file mode 100644 index 0000000000000..bc12bfc02208c --- /dev/null +++ b/src/test/ui/parser/suggest-removing-semicolon-after-impl-trait-items.stderr @@ -0,0 +1,18 @@ +error: non-item in item list + --> $DIR/suggest-removing-semicolon-after-impl-trait-items.rs:4:16 + | +LL | trait Foo { + | - item list starts here +LL | fn bar() {}; + | ^ non-item starts here +LL | } + | - item list ends here + | +help: consider removing this semicolon + | +LL - fn bar() {}; +LL + fn bar() {} + | + +error: aborting due to previous error + From d47df26784355eaa4006eee60f262c6035fea307 Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Sat, 13 Aug 2022 22:10:54 +0900 Subject: [PATCH 2/2] use `span_suggestion` instead of `span_suggestion_verbose` --- compiler/rustc_parse/src/parser/item.rs | 2 +- ...t-removing-semicolon-after-impl-trait-items.stderr | 11 ++++------- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 8f4edf6ce4800..8f58bce889041 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -700,7 +700,7 @@ impl<'a> Parser<'a> { .span_label(non_item_span, "non-item starts here") .span_label(self.prev_token.span, "item list ends here"); if is_unnecessary_semicolon { - err.span_suggestion_verbose( + err.span_suggestion( semicolon_span, "consider removing this semicolon", "", diff --git a/src/test/ui/parser/suggest-removing-semicolon-after-impl-trait-items.stderr b/src/test/ui/parser/suggest-removing-semicolon-after-impl-trait-items.stderr index bc12bfc02208c..396e0c130f11b 100644 --- a/src/test/ui/parser/suggest-removing-semicolon-after-impl-trait-items.stderr +++ b/src/test/ui/parser/suggest-removing-semicolon-after-impl-trait-items.stderr @@ -4,15 +4,12 @@ error: non-item in item list LL | trait Foo { | - item list starts here LL | fn bar() {}; - | ^ non-item starts here + | ^ + | | + | non-item starts here + | help: consider removing this semicolon LL | } | - item list ends here - | -help: consider removing this semicolon - | -LL - fn bar() {}; -LL + fn bar() {} - | error: aborting due to previous error