Skip to content

Commit 6906e64

Browse files
authored
Rollup merge of #102350 - TaKO8Ki:incomplete-fn-in-struct-definition, r=fee1-dead
Improve errors for incomplete functions in struct definitions Given the following code: ```rust fn main() {} struct Foo { fn } ``` [playground](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=29139f870511f6918324be5ddc26c345) The current output is: ``` Compiling playground v0.0.1 (/playground) error: functions are not allowed in struct definitions --> src/main.rs:4:5 | 4 | fn | ^^ | = help: unlike in C++, Java, and C#, functions are declared in `impl` blocks = help: see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information error: could not compile `playground` due to previous error ``` In this case, rustc should suggest escaping `fn` to use it as an identifier.
2 parents 25017f8 + e665d20 commit 6906e64

File tree

5 files changed

+44
-16
lines changed

5 files changed

+44
-16
lines changed

compiler/rustc_parse/src/parser/item.rs

+17-11
Original file line numberDiff line numberDiff line change
@@ -1753,18 +1753,24 @@ impl<'a> Parser<'a> {
17531753
};
17541754
// We use `parse_fn` to get a span for the function
17551755
let fn_parse_mode = FnParseMode { req_name: |_| true, req_body: true };
1756-
if let Err(mut db) =
1757-
self.parse_fn(&mut AttrVec::new(), fn_parse_mode, lo, &inherited_vis)
1758-
{
1759-
db.delay_as_bug();
1756+
match self.parse_fn(&mut AttrVec::new(), fn_parse_mode, lo, &inherited_vis) {
1757+
Ok(_) => {
1758+
let mut err = self.struct_span_err(
1759+
lo.to(self.prev_token.span),
1760+
&format!("functions are not allowed in {adt_ty} definitions"),
1761+
);
1762+
err.help(
1763+
"unlike in C++, Java, and C#, functions are declared in `impl` blocks",
1764+
);
1765+
err.help("see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information");
1766+
err
1767+
}
1768+
Err(err) => {
1769+
err.cancel();
1770+
self.restore_snapshot(snapshot);
1771+
self.expected_ident_found()
1772+
}
17601773
}
1761-
let mut err = self.struct_span_err(
1762-
lo.to(self.prev_token.span),
1763-
&format!("functions are not allowed in {adt_ty} definitions"),
1764-
);
1765-
err.help("unlike in C++, Java, and C#, functions are declared in `impl` blocks");
1766-
err.help("see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information");
1767-
err
17681774
} else if self.eat_keyword(kw::Struct) {
17691775
match self.parse_item_struct() {
17701776
Ok((ident, _)) => {

src/test/ui/parser/fn-field-parse-error-ice.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
struct Baz {
44
inner : dyn fn ()
55
//~^ ERROR expected `,`, or `}`, found keyword `fn`
6-
//~| ERROR functions are not allowed in struct definitions
6+
//~| ERROR expected identifier, found keyword `fn`
77
//~| ERROR cannot find type `dyn` in this scope
88
}
99

src/test/ui/parser/fn-field-parse-error-ice.stderr

+6-4
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,18 @@ error: expected `,`, or `}`, found keyword `fn`
44
LL | inner : dyn fn ()
55
| ^ help: try adding a comma: `,`
66

7-
error: functions are not allowed in struct definitions
7+
error: expected identifier, found keyword `fn`
88
--> $DIR/fn-field-parse-error-ice.rs:4:17
99
|
1010
LL | struct Baz {
1111
| --- while parsing this struct
1212
LL | inner : dyn fn ()
13-
| ^^
13+
| ^^ expected identifier, found keyword
1414
|
15-
= help: unlike in C++, Java, and C#, functions are declared in `impl` blocks
16-
= help: see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information
15+
help: escape `fn` to use it as an identifier
16+
|
17+
LL | inner : dyn r#fn ()
18+
| ++
1719

1820
error[E0412]: cannot find type `dyn` in this scope
1921
--> $DIR/fn-field-parse-error-ice.rs:4:13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
fn main() {}
2+
3+
struct S {
4+
fn: u8 //~ ERROR expected identifier, found keyword `fn`
5+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error: expected identifier, found keyword `fn`
2+
--> $DIR/incomplete-fn-in-struct-definition.rs:4:5
3+
|
4+
LL | struct S {
5+
| - while parsing this struct
6+
LL | fn: u8
7+
| ^^ expected identifier, found keyword
8+
|
9+
help: escape `fn` to use it as an identifier
10+
|
11+
LL | r#fn: u8
12+
| ++
13+
14+
error: aborting due to previous error
15+

0 commit comments

Comments
 (0)