Skip to content

Commit 86e1d1e

Browse files
Rollup merge of #100446 - TaKO8Ki:suggest-removing-semicolon-after-impl-trait-items, r=compiler-errors
Suggest removing a semicolon after impl/trait items fixes #99822
2 parents d46451c + d47df26 commit 86e1d1e

4 files changed

+63
-4
lines changed

compiler/rustc_parse/src/parser/item.rs

+34-4
Original file line numberDiff line numberDiff line change
@@ -675,14 +675,44 @@ impl<'a> Parser<'a> {
675675
}
676676
match parse_item(self) {
677677
Ok(None) => {
678+
let is_unnecessary_semicolon = !items.is_empty()
679+
// When the close delim is `)` in a case like the following, `token.kind` is expected to be `token::CloseDelim(Delimiter::Parenthesis)`,
680+
// but the actual `token.kind` is `token::CloseDelim(Delimiter::Bracket)`.
681+
// This is because the `token.kind` of the close delim is treated as the same as
682+
// that of the open delim in `TokenTreesReader::parse_token_tree`, even if the delimiters of them are different.
683+
// Therefore, `token.kind` should not be compared here.
684+
//
685+
// issue-60075.rs
686+
// ```
687+
// trait T {
688+
// fn qux() -> Option<usize> {
689+
// let _ = if true {
690+
// });
691+
// ^ this close delim
692+
// Some(4)
693+
// }
694+
// ```
695+
&& self
696+
.span_to_snippet(self.prev_token.span)
697+
.map_or(false, |snippet| snippet == "}")
698+
&& self.token.kind == token::Semi;
699+
let semicolon_span = self.token.span;
678700
// We have to bail or we'll potentially never make progress.
679701
let non_item_span = self.token.span;
680702
self.consume_block(Delimiter::Brace, ConsumeClosingDelim::Yes);
681-
self.struct_span_err(non_item_span, "non-item in item list")
682-
.span_label(open_brace_span, "item list starts here")
703+
let mut err = self.struct_span_err(non_item_span, "non-item in item list");
704+
err.span_label(open_brace_span, "item list starts here")
683705
.span_label(non_item_span, "non-item starts here")
684-
.span_label(self.prev_token.span, "item list ends here")
685-
.emit();
706+
.span_label(self.prev_token.span, "item list ends here");
707+
if is_unnecessary_semicolon {
708+
err.span_suggestion(
709+
semicolon_span,
710+
"consider removing this semicolon",
711+
"",
712+
Applicability::MaybeIncorrect,
713+
);
714+
}
715+
err.emit();
686716
break;
687717
}
688718
Ok(Some(item)) => items.extend(item),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// run-rustfix
2+
3+
trait Foo {
4+
fn bar() {} //~ ERROR non-item in item list
5+
}
6+
7+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// run-rustfix
2+
3+
trait Foo {
4+
fn bar() {}; //~ ERROR non-item in item list
5+
}
6+
7+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error: non-item in item list
2+
--> $DIR/suggest-removing-semicolon-after-impl-trait-items.rs:4:16
3+
|
4+
LL | trait Foo {
5+
| - item list starts here
6+
LL | fn bar() {};
7+
| ^
8+
| |
9+
| non-item starts here
10+
| help: consider removing this semicolon
11+
LL | }
12+
| - item list ends here
13+
14+
error: aborting due to previous error
15+

0 commit comments

Comments
 (0)