From d7b6bd8f131a269102662ff249e916d6f7069f97 Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Tue, 27 Sep 2022 17:20:55 +0900 Subject: [PATCH] improve errors for incomplete functions in struct definitions --- compiler/rustc_parse/src/parser/item.rs | 28 +++++++++++-------- .../ui/parser/fn-field-parse-error-ice.rs | 2 +- .../ui/parser/fn-field-parse-error-ice.stderr | 10 ++++--- .../incomplete-fn-in-struct-definition.rs | 5 ++++ .../incomplete-fn-in-struct-definition.stderr | 13 +++++++++ 5 files changed, 42 insertions(+), 16 deletions(-) create mode 100644 src/test/ui/structs/incomplete-fn-in-struct-definition.rs create mode 100644 src/test/ui/structs/incomplete-fn-in-struct-definition.stderr diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 6c4cfcf6ddf..746ddfdf4b9 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, _)) => { diff --git a/src/test/ui/parser/fn-field-parse-error-ice.rs b/src/test/ui/parser/fn-field-parse-error-ice.rs index 4ea55062fc4..188257ea53a 100644 --- a/src/test/ui/parser/fn-field-parse-error-ice.rs +++ b/src/test/ui/parser/fn-field-parse-error-ice.rs @@ -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 } diff --git a/src/test/ui/parser/fn-field-parse-error-ice.stderr b/src/test/ui/parser/fn-field-parse-error-ice.stderr index e9583f55b8e..3bf68e8cc04 100644 --- a/src/test/ui/parser/fn-field-parse-error-ice.stderr +++ b/src/test/ui/parser/fn-field-parse-error-ice.stderr @@ -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 diff --git a/src/test/ui/structs/incomplete-fn-in-struct-definition.rs b/src/test/ui/structs/incomplete-fn-in-struct-definition.rs new file mode 100644 index 00000000000..b43d1d4395a --- /dev/null +++ b/src/test/ui/structs/incomplete-fn-in-struct-definition.rs @@ -0,0 +1,5 @@ +fn main() {} + +struct S { + fn //~ ERROR expected identifier, found keyword `fn` +} diff --git a/src/test/ui/structs/incomplete-fn-in-struct-definition.stderr b/src/test/ui/structs/incomplete-fn-in-struct-definition.stderr new file mode 100644 index 00000000000..2c860606710 --- /dev/null +++ b/src/test/ui/structs/incomplete-fn-in-struct-definition.stderr @@ -0,0 +1,13 @@ +error: expected identifier, found keyword `fn` + --> $DIR/incomplete-fn-in-struct-definition.rs:4:5 + | +LL | fn + | ^^ expected identifier, found keyword + | +help: escape `fn` to use it as an identifier + | +LL | r#fn + | ++ + +error: aborting due to previous error +