about summary refs log tree commit diff
path: root/compiler/rustc_parse/src/parser
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2022-09-30 10:22:37 +0200
committerGitHub <noreply@github.com>2022-09-30 10:22:37 +0200
commit6906e64c30ca464c1bafed5b806283665d9e8f58 (patch)
tree98bfdfd7189ad56f8d50b6c9e5e888c101418050 /compiler/rustc_parse/src/parser
parent25017f8bcece0f57cc1acd3b64394f30cbda11f4 (diff)
parente665d20c020724fa356fef0214e14b4066563a29 (diff)
downloadrust-6906e64c30ca464c1bafed5b806283665d9e8f58.tar.gz
rust-6906e64c30ca464c1bafed5b806283665d9e8f58.zip
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.
Diffstat (limited to 'compiler/rustc_parse/src/parser')
-rw-r--r--compiler/rustc_parse/src/parser/item.rs28
1 files changed, 17 insertions, 11 deletions
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index c8a8e00b1fa..25425fbb2c6 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -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, _)) => {