Skip to content

Commit 48c0341

Browse files
committed
suggest removing a semicolon after impl/trait items
1 parent 93ab13b commit 48c0341

4 files changed

+66
-4
lines changed

compiler/rustc_parse/src/parser/item.rs

+34-4
Original file line numberDiff line numberDiff line change
@@ -670,14 +670,44 @@ impl<'a> Parser<'a> {
670670
}
671671
match parse_item(self) {
672672
Ok(None) => {
673+
let is_unnecessary_semicolon = !items.is_empty()
674+
// When the close delim is `)` in a case like the following, `token.kind` is expected to be `token::CloseDelim(Delimiter::Parenthesis)`,
675+
// but the actual `token.kind` is `token::CloseDelim(Delimiter::Bracket)`.
676+
// This is because the `token.kind` of the close delim is treated as the same as
677+
// that of the open delim in `TokenTreesReader::parse_token_tree`, even if the delimiters of them are different.
678+
// Therefore, `token.kind` should not be compared here.
679+
//
680+
// issue-60075.rs
681+
// ```
682+
// trait T {
683+
// fn qux() -> Option<usize> {
684+
// let _ = if true {
685+
// });
686+
// ^ this close delim
687+
// Some(4)
688+
// }
689+
// ```
690+
&& self
691+
.span_to_snippet(self.prev_token.span)
692+
.map_or(false, |snippet| snippet == "}")
693+
&& self.token.kind == token::Semi;
694+
let semicolon_span = self.token.span;
673695
// We have to bail or we'll potentially never make progress.
674696
let non_item_span = self.token.span;
675697
self.consume_block(Delimiter::Brace, ConsumeClosingDelim::Yes);
676-
self.struct_span_err(non_item_span, "non-item in item list")
677-
.span_label(open_brace_span, "item list starts here")
698+
let mut err = self.struct_span_err(non_item_span, "non-item in item list");
699+
err.span_label(open_brace_span, "item list starts here")
678700
.span_label(non_item_span, "non-item starts here")
679-
.span_label(self.prev_token.span, "item list ends here")
680-
.emit();
701+
.span_label(self.prev_token.span, "item list ends here");
702+
if is_unnecessary_semicolon {
703+
err.span_suggestion_verbose(
704+
semicolon_span,
705+
"consider removing this semicolon",
706+
"",
707+
Applicability::MaybeIncorrect,
708+
);
709+
}
710+
err.emit();
681711
break;
682712
}
683713
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,18 @@
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+
| ^ non-item starts here
8+
LL | }
9+
| - item list ends here
10+
|
11+
help: consider removing this semicolon
12+
|
13+
LL - fn bar() {};
14+
LL + fn bar() {}
15+
|
16+
17+
error: aborting due to previous error
18+

0 commit comments

Comments
 (0)