Skip to content

Commit c7ecabd

Browse files
committed
Add suggestions for possible missing fn, struct, or enum keywords
1 parent 51917e2 commit c7ecabd

16 files changed

+177
-0
lines changed

compiler/rustc_parse/src/parser/diagnostics.rs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -620,6 +620,55 @@ impl<'a> Parser<'a> {
620620
);
621621
}
622622

623+
// Possible missing `struct` or `enum` keyword
624+
if let TokenKind::Ident(symbol, _) = &self.prev_token.kind
625+
&& let TokenKind::OpenDelim(Delimiter::Brace) = self.token.kind
626+
&& let [TokenType::Token(token::Not), TokenType::Token(token::PathSep)] = expected[..]
627+
{
628+
let mut lookahead = self.clone();
629+
for position in 1..1000 {
630+
lookahead.bump();
631+
if lookahead.token == token::CloseDelim(Delimiter::Brace)
632+
|| lookahead.token == token::Colon
633+
{
634+
let (article, kw) = if lookahead.token == token::Colon || position == 1 {
635+
("a", "struct")
636+
} else {
637+
("an", "enum")
638+
};
639+
err.span_suggestion(
640+
self.prev_token.span,
641+
format!("if this is {article} {kw} definition, use the `{kw}` keyword"),
642+
format!("{kw} {symbol}"),
643+
Applicability::MaybeIncorrect,
644+
);
645+
break;
646+
}
647+
}
648+
}
649+
650+
// Possible missing `fn` keyword
651+
if let TokenKind::Ident(symbol, _) = &self.prev_token.kind
652+
&& let TokenKind::OpenDelim(Delimiter::Parenthesis) = self.token.kind
653+
{
654+
let mut lookahead = self.clone();
655+
for _ in 1..100 {
656+
lookahead.bump();
657+
if lookahead.token == token::Semi {
658+
break;
659+
}
660+
if lookahead.token == token::OpenDelim(Delimiter::Brace) {
661+
err.span_suggestion(
662+
self.prev_token.span,
663+
"if this is a function definition, use the `fn` keyword",
664+
format!("fn {symbol}"),
665+
Applicability::MaybeIncorrect,
666+
);
667+
break;
668+
}
669+
}
670+
}
671+
623672
if let TokenKind::Ident(symbol, _) = &self.prev_token.kind {
624673
if ["def", "fun", "func", "function"].contains(&symbol.as_str()) {
625674
err.span_suggestion_short(

tests/ui/did_you_mean/issue-40006.stderr

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ LL | X() {}
2121
...
2222
LL | }
2323
| - the item list ends here
24+
|
25+
help: if this is a function definition, use the `fn` keyword
26+
|
27+
LL | fn X() {}
28+
| ~~~~
2429

2530
error: expected one of `!` or `::`, found `(`
2631
--> $DIR/issue-40006.rs:16:6
@@ -31,6 +36,11 @@ LL | X() {}
3136
| ^ expected one of `!` or `::`
3237
LL | }
3338
| - the item list ends here
39+
|
40+
help: if this is a function definition, use the `fn` keyword
41+
|
42+
LL | fn X() {}
43+
| ~~~~
3444

3545
error: expected one of `!` or `[`, found `#`
3646
--> $DIR/issue-40006.rs:19:17
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Whoops {
2+
//~^ ERROR expected one of `!` or `::`, found `{`
3+
OptionA,
4+
OptionB,
5+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
error: expected one of `!` or `::`, found `{`
2+
--> $DIR/missing-enum-issue-125446.rs:1:8
3+
|
4+
LL | Whoops {
5+
| ^ expected one of `!` or `::`
6+
|
7+
help: if this is an enum definition, use the `enum` keyword
8+
|
9+
LL | enum Whoops {
10+
| ~~~~~~~~~~~
11+
12+
error: aborting due to 1 previous error
13+
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
whoops() {}
2+
//~^ ERROR expected one of `!` or `::`, found `(`
3+
4+
fn main() {
5+
whoops();
6+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
error: expected one of `!` or `::`, found `(`
2+
--> $DIR/missing-fn-issue-125446.rs:1:7
3+
|
4+
LL | whoops() {}
5+
| ^ expected one of `!` or `::`
6+
|
7+
help: if this is a function definition, use the `fn` keyword
8+
|
9+
LL | fn whoops() {}
10+
| ~~~~~~~~~
11+
12+
error: aborting due to 1 previous error
13+
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
main() {
2+
//~^ ERROR expected one of `!` or `::`, found `(`
3+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
error: expected one of `!` or `::`, found `(`
2+
--> $DIR/missing-fn-issue-65381-1.rs:1:5
3+
|
4+
LL | main() {
5+
| ^ expected one of `!` or `::`
6+
|
7+
help: if this is a function definition, use the `fn` keyword
8+
|
9+
LL | fn main() {
10+
| ~~~~~~~
11+
12+
error: aborting due to 1 previous error
13+
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
main();
2+
//~^ ERROR expected one of `!` or `::`, found `(`
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
error: expected one of `!` or `::`, found `(`
2+
--> $DIR/missing-fn-issue-65381-2.rs:1:5
3+
|
4+
LL | main();
5+
| ^ expected one of `!` or `::`
6+
7+
error: aborting due to 1 previous error
8+

0 commit comments

Comments
 (0)