about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_parse/parser/item.rs17
-rw-r--r--src/test/ui/parser/fn-body-eq-expr-semi.rs23
-rw-r--r--src/test/ui/parser/fn-body-eq-expr-semi.stderr117
3 files changed, 156 insertions, 1 deletions
diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs
index 428c01a8344..8263bd879ad 100644
--- a/src/librustc_parse/parser/item.rs
+++ b/src/librustc_parse/parser/item.rs
@@ -1412,10 +1412,25 @@ impl<'a> Parser<'a> {
     /// or e.g. a block when the function is a provided one.
     fn parse_fn_body(&mut self, attrs: &mut Vec<Attribute>) -> PResult<'a, Option<P<Block>>> {
         let (inner_attrs, body) = if self.check(&token::Semi) {
-            self.bump();
+            self.bump(); // `;`
             (Vec::new(), None)
         } else if self.check(&token::OpenDelim(token::Brace)) || self.token.is_whole_block() {
             self.parse_inner_attrs_and_block().map(|(attrs, body)| (attrs, Some(body)))?
+        } else if self.token.kind == token::Eq {
+            // Recover `fn foo() = $expr;`.
+            self.bump(); // `=`
+            let eq_sp = self.prev_token.span;
+            let _ = self.parse_expr()?;
+            self.expect_semi()?; // `;`
+            let span = eq_sp.to(self.prev_token.span);
+            self.struct_span_err(span, "function body cannot be `= expression;`")
+                .multipart_suggestion(
+                    "surround the expression with `{` and `}` instead of `=` and `;`",
+                    vec![(eq_sp, "{".to_string()), (self.prev_token.span, " }".to_string())],
+                    Applicability::MachineApplicable,
+                )
+                .emit();
+            (Vec::new(), Some(self.mk_block_err(span)))
         } else {
             return self.expected_semi_or_open_brace();
         };
diff --git a/src/test/ui/parser/fn-body-eq-expr-semi.rs b/src/test/ui/parser/fn-body-eq-expr-semi.rs
new file mode 100644
index 00000000000..09444079365
--- /dev/null
+++ b/src/test/ui/parser/fn-body-eq-expr-semi.rs
@@ -0,0 +1,23 @@
+fn main() {}
+
+fn syntax() {
+    fn foo() = 42; //~ ERROR function body cannot be `= expression;`
+    fn bar() -> u8 = 42; //~ ERROR function body cannot be `= expression;`
+}
+
+extern {
+    fn foo() = 42; //~ ERROR function body cannot be `= expression;`
+    //~^ ERROR incorrect function inside `extern` block
+    fn bar() -> u8 = 42; //~ ERROR function body cannot be `= expression;`
+    //~^ ERROR incorrect function inside `extern` block
+}
+
+trait Foo {
+    fn foo() = 42; //~ ERROR function body cannot be `= expression;`
+    fn bar() -> u8 = 42; //~ ERROR function body cannot be `= expression;`
+}
+
+impl Foo for () {
+    fn foo() = 42; //~ ERROR function body cannot be `= expression;`
+    fn bar() -> u8 = 42; //~ ERROR function body cannot be `= expression;`
+}
diff --git a/src/test/ui/parser/fn-body-eq-expr-semi.stderr b/src/test/ui/parser/fn-body-eq-expr-semi.stderr
new file mode 100644
index 00000000000..739133e0b40
--- /dev/null
+++ b/src/test/ui/parser/fn-body-eq-expr-semi.stderr
@@ -0,0 +1,117 @@
+error: function body cannot be `= expression;`
+  --> $DIR/fn-body-eq-expr-semi.rs:4:14
+   |
+LL |     fn foo() = 42;
+   |              ^^^^^
+   |
+help: surround the expression with `{` and `}` instead of `=` and `;`
+   |
+LL |     fn foo() { 42 }
+   |              ^    ^
+
+error: function body cannot be `= expression;`
+  --> $DIR/fn-body-eq-expr-semi.rs:5:20
+   |
+LL |     fn bar() -> u8 = 42;
+   |                    ^^^^^
+   |
+help: surround the expression with `{` and `}` instead of `=` and `;`
+   |
+LL |     fn bar() -> u8 { 42 }
+   |                    ^    ^
+
+error: function body cannot be `= expression;`
+  --> $DIR/fn-body-eq-expr-semi.rs:9:14
+   |
+LL |     fn foo() = 42;
+   |              ^^^^^
+   |
+help: surround the expression with `{` and `}` instead of `=` and `;`
+   |
+LL |     fn foo() { 42 }
+   |              ^    ^
+
+error: function body cannot be `= expression;`
+  --> $DIR/fn-body-eq-expr-semi.rs:11:20
+   |
+LL |     fn bar() -> u8 = 42;
+   |                    ^^^^^
+   |
+help: surround the expression with `{` and `}` instead of `=` and `;`
+   |
+LL |     fn bar() -> u8 { 42 }
+   |                    ^    ^
+
+error: function body cannot be `= expression;`
+  --> $DIR/fn-body-eq-expr-semi.rs:16:14
+   |
+LL |     fn foo() = 42;
+   |              ^^^^^
+   |
+help: surround the expression with `{` and `}` instead of `=` and `;`
+   |
+LL |     fn foo() { 42 }
+   |              ^    ^
+
+error: function body cannot be `= expression;`
+  --> $DIR/fn-body-eq-expr-semi.rs:17:20
+   |
+LL |     fn bar() -> u8 = 42;
+   |                    ^^^^^
+   |
+help: surround the expression with `{` and `}` instead of `=` and `;`
+   |
+LL |     fn bar() -> u8 { 42 }
+   |                    ^    ^
+
+error: function body cannot be `= expression;`
+  --> $DIR/fn-body-eq-expr-semi.rs:21:14
+   |
+LL |     fn foo() = 42;
+   |              ^^^^^
+   |
+help: surround the expression with `{` and `}` instead of `=` and `;`
+   |
+LL |     fn foo() { 42 }
+   |              ^    ^
+
+error: function body cannot be `= expression;`
+  --> $DIR/fn-body-eq-expr-semi.rs:22:20
+   |
+LL |     fn bar() -> u8 = 42;
+   |                    ^^^^^
+   |
+help: surround the expression with `{` and `}` instead of `=` and `;`
+   |
+LL |     fn bar() -> u8 { 42 }
+   |                    ^    ^
+
+error: incorrect function inside `extern` block
+  --> $DIR/fn-body-eq-expr-semi.rs:9:8
+   |
+LL | extern {
+   | ------ `extern` blocks define existing foreign functions and functions inside of them cannot have a body
+LL |     fn foo() = 42;
+   |        ^^^   ----- help: remove the invalid body: `;`
+   |        |
+   |        cannot have a body
+   |
+   = help: you might have meant to write a function accessible through FFI, which can be done by writing `extern fn` outside of the `extern` block
+   = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html
+
+error: incorrect function inside `extern` block
+  --> $DIR/fn-body-eq-expr-semi.rs:11:8
+   |
+LL | extern {
+   | ------ `extern` blocks define existing foreign functions and functions inside of them cannot have a body
+...
+LL |     fn bar() -> u8 = 42;
+   |        ^^^         ----- help: remove the invalid body: `;`
+   |        |
+   |        cannot have a body
+   |
+   = help: you might have meant to write a function accessible through FFI, which can be done by writing `extern fn` outside of the `extern` block
+   = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html
+
+error: aborting due to 10 previous errors
+