Skip to content

Commit

Permalink
Rollup merge of #102350 - TaKO8Ki:incomplete-fn-in-struct-definition,…
Browse files Browse the repository at this point in the history
… 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.
  • Loading branch information
matthiaskrgr authored Sep 30, 2022
2 parents 25017f8 + e665d20 commit 6906e64
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 16 deletions.
28 changes: 17 additions & 11 deletions compiler/rustc_parse/src/parser/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1753,18 +1753,24 @@ impl<'a> Parser<'a> {
};
// We use `parse_fn` to get a span for the function
let fn_parse_mode = FnParseMode { req_name: |_| true, req_body: true };
if let Err(mut db) =
self.parse_fn(&mut AttrVec::new(), fn_parse_mode, lo, &inherited_vis)
{
db.delay_as_bug();
match self.parse_fn(&mut AttrVec::new(), fn_parse_mode, lo, &inherited_vis) {
Ok(_) => {
let mut err = self.struct_span_err(
lo.to(self.prev_token.span),
&format!("functions are not allowed in {adt_ty} definitions"),
);
err.help(
"unlike in C++, Java, and C#, functions are declared in `impl` blocks",
);
err.help("see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information");
err
}
Err(err) => {
err.cancel();
self.restore_snapshot(snapshot);
self.expected_ident_found()
}
}
let mut err = self.struct_span_err(
lo.to(self.prev_token.span),
&format!("functions are not allowed in {adt_ty} definitions"),
);
err.help("unlike in C++, Java, and C#, functions are declared in `impl` blocks");
err.help("see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information");
err
} else if self.eat_keyword(kw::Struct) {
match self.parse_item_struct() {
Ok((ident, _)) => {
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/parser/fn-field-parse-error-ice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
struct Baz {
inner : dyn fn ()
//~^ ERROR expected `,`, or `}`, found keyword `fn`
//~| ERROR functions are not allowed in struct definitions
//~| ERROR expected identifier, found keyword `fn`
//~| ERROR cannot find type `dyn` in this scope
}

Expand Down
10 changes: 6 additions & 4 deletions src/test/ui/parser/fn-field-parse-error-ice.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,18 @@ error: expected `,`, or `}`, found keyword `fn`
LL | inner : dyn fn ()
| ^ help: try adding a comma: `,`

error: functions are not allowed in struct definitions
error: expected identifier, found keyword `fn`
--> $DIR/fn-field-parse-error-ice.rs:4:17
|
LL | struct Baz {
| --- while parsing this struct
LL | inner : dyn fn ()
| ^^
| ^^ expected identifier, found keyword
|
= 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
help: escape `fn` to use it as an identifier
|
LL | inner : dyn r#fn ()
| ++

error[E0412]: cannot find type `dyn` in this scope
--> $DIR/fn-field-parse-error-ice.rs:4:13
Expand Down
5 changes: 5 additions & 0 deletions src/test/ui/structs/incomplete-fn-in-struct-definition.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
fn main() {}

struct S {
fn: u8 //~ ERROR expected identifier, found keyword `fn`
}
15 changes: 15 additions & 0 deletions src/test/ui/structs/incomplete-fn-in-struct-definition.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
error: expected identifier, found keyword `fn`
--> $DIR/incomplete-fn-in-struct-definition.rs:4:5
|
LL | struct S {
| - while parsing this struct
LL | fn: u8
| ^^ expected identifier, found keyword
|
help: escape `fn` to use it as an identifier
|
LL | r#fn: u8
| ++

error: aborting due to previous error

0 comments on commit 6906e64

Please sign in to comment.