Skip to content

Commit be86b2d

Browse files
committed
parse: recover on fn foo() = expr;
1 parent 379f318 commit be86b2d

File tree

3 files changed

+156
-1
lines changed

3 files changed

+156
-1
lines changed

src/librustc_parse/parser/item.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1412,10 +1412,25 @@ impl<'a> Parser<'a> {
14121412
/// or e.g. a block when the function is a provided one.
14131413
fn parse_fn_body(&mut self, attrs: &mut Vec<Attribute>) -> PResult<'a, Option<P<Block>>> {
14141414
let (inner_attrs, body) = if self.check(&token::Semi) {
1415-
self.bump();
1415+
self.bump(); // `;`
14161416
(Vec::new(), None)
14171417
} else if self.check(&token::OpenDelim(token::Brace)) || self.token.is_whole_block() {
14181418
self.parse_inner_attrs_and_block().map(|(attrs, body)| (attrs, Some(body)))?
1419+
} else if self.token.kind == token::Eq {
1420+
// Recover `fn foo() = $expr;`.
1421+
self.bump(); // `=`
1422+
let eq_sp = self.prev_token.span;
1423+
let _ = self.parse_expr()?;
1424+
self.expect_semi()?; // `;`
1425+
let span = eq_sp.to(self.prev_token.span);
1426+
self.struct_span_err(span, "function body cannot be `= expression;`")
1427+
.multipart_suggestion(
1428+
"surround the expression with `{` and `}` instead of `=` and `;`",
1429+
vec![(eq_sp, "{".to_string()), (self.prev_token.span, " }".to_string())],
1430+
Applicability::MachineApplicable,
1431+
)
1432+
.emit();
1433+
(Vec::new(), Some(self.mk_block_err(span)))
14191434
} else {
14201435
return self.expected_semi_or_open_brace();
14211436
};
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
fn main() {}
2+
3+
fn syntax() {
4+
fn foo() = 42; //~ ERROR function body cannot be `= expression;`
5+
fn bar() -> u8 = 42; //~ ERROR function body cannot be `= expression;`
6+
}
7+
8+
extern {
9+
fn foo() = 42; //~ ERROR function body cannot be `= expression;`
10+
//~^ ERROR incorrect function inside `extern` block
11+
fn bar() -> u8 = 42; //~ ERROR function body cannot be `= expression;`
12+
//~^ ERROR incorrect function inside `extern` block
13+
}
14+
15+
trait Foo {
16+
fn foo() = 42; //~ ERROR function body cannot be `= expression;`
17+
fn bar() -> u8 = 42; //~ ERROR function body cannot be `= expression;`
18+
}
19+
20+
impl Foo for () {
21+
fn foo() = 42; //~ ERROR function body cannot be `= expression;`
22+
fn bar() -> u8 = 42; //~ ERROR function body cannot be `= expression;`
23+
}
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
error: function body cannot be `= expression;`
2+
--> $DIR/fn-body-eq-expr-semi.rs:4:14
3+
|
4+
LL | fn foo() = 42;
5+
| ^^^^^
6+
|
7+
help: surround the expression with `{` and `}` instead of `=` and `;`
8+
|
9+
LL | fn foo() { 42 }
10+
| ^ ^
11+
12+
error: function body cannot be `= expression;`
13+
--> $DIR/fn-body-eq-expr-semi.rs:5:20
14+
|
15+
LL | fn bar() -> u8 = 42;
16+
| ^^^^^
17+
|
18+
help: surround the expression with `{` and `}` instead of `=` and `;`
19+
|
20+
LL | fn bar() -> u8 { 42 }
21+
| ^ ^
22+
23+
error: function body cannot be `= expression;`
24+
--> $DIR/fn-body-eq-expr-semi.rs:9:14
25+
|
26+
LL | fn foo() = 42;
27+
| ^^^^^
28+
|
29+
help: surround the expression with `{` and `}` instead of `=` and `;`
30+
|
31+
LL | fn foo() { 42 }
32+
| ^ ^
33+
34+
error: function body cannot be `= expression;`
35+
--> $DIR/fn-body-eq-expr-semi.rs:11:20
36+
|
37+
LL | fn bar() -> u8 = 42;
38+
| ^^^^^
39+
|
40+
help: surround the expression with `{` and `}` instead of `=` and `;`
41+
|
42+
LL | fn bar() -> u8 { 42 }
43+
| ^ ^
44+
45+
error: function body cannot be `= expression;`
46+
--> $DIR/fn-body-eq-expr-semi.rs:16:14
47+
|
48+
LL | fn foo() = 42;
49+
| ^^^^^
50+
|
51+
help: surround the expression with `{` and `}` instead of `=` and `;`
52+
|
53+
LL | fn foo() { 42 }
54+
| ^ ^
55+
56+
error: function body cannot be `= expression;`
57+
--> $DIR/fn-body-eq-expr-semi.rs:17:20
58+
|
59+
LL | fn bar() -> u8 = 42;
60+
| ^^^^^
61+
|
62+
help: surround the expression with `{` and `}` instead of `=` and `;`
63+
|
64+
LL | fn bar() -> u8 { 42 }
65+
| ^ ^
66+
67+
error: function body cannot be `= expression;`
68+
--> $DIR/fn-body-eq-expr-semi.rs:21:14
69+
|
70+
LL | fn foo() = 42;
71+
| ^^^^^
72+
|
73+
help: surround the expression with `{` and `}` instead of `=` and `;`
74+
|
75+
LL | fn foo() { 42 }
76+
| ^ ^
77+
78+
error: function body cannot be `= expression;`
79+
--> $DIR/fn-body-eq-expr-semi.rs:22:20
80+
|
81+
LL | fn bar() -> u8 = 42;
82+
| ^^^^^
83+
|
84+
help: surround the expression with `{` and `}` instead of `=` and `;`
85+
|
86+
LL | fn bar() -> u8 { 42 }
87+
| ^ ^
88+
89+
error: incorrect function inside `extern` block
90+
--> $DIR/fn-body-eq-expr-semi.rs:9:8
91+
|
92+
LL | extern {
93+
| ------ `extern` blocks define existing foreign functions and functions inside of them cannot have a body
94+
LL | fn foo() = 42;
95+
| ^^^ ----- help: remove the invalid body: `;`
96+
| |
97+
| cannot have a body
98+
|
99+
= 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
100+
= note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html
101+
102+
error: incorrect function inside `extern` block
103+
--> $DIR/fn-body-eq-expr-semi.rs:11:8
104+
|
105+
LL | extern {
106+
| ------ `extern` blocks define existing foreign functions and functions inside of them cannot have a body
107+
...
108+
LL | fn bar() -> u8 = 42;
109+
| ^^^ ----- help: remove the invalid body: `;`
110+
| |
111+
| cannot have a body
112+
|
113+
= 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
114+
= note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html
115+
116+
error: aborting due to 10 previous errors
117+

0 commit comments

Comments
 (0)