Rollup merge of #108388 - ohno418:better-suggestion-on-malformed-closure, r=davidtwco
parser: provide better suggestions and errors on closures with braces missing We currently provide wrong suggestions and unhelpful errors on closure bodies with braces missing. For example, given the following code: ```rust fn main() { let _x = Box::new(|x|x+1;); } ``` the current output is: ``` error: expected expression, found `)` --> ./main.rs:2:30 | 2 | let _x = Box::new(|x|x+1;); | ^ expected expression error: closure bodies that contain statements must be surrounded by braces --> ./main.rs:2:25 | 2 | let _x = Box::new(|x|x+1;); | ^ 3 | } | ^ | note: statement found outside of a block --> ./main.rs:2:29 | 2 | let _x = Box::new(|x|x+1;); | ---^ this `;` turns the preceding closure into a statement | | | this expression is a statement because of the trailing semicolon note: the closure body may be incorrectly delimited --> ./main.rs:2:23 | 2 | let _x = Box::new(|x|x+1;); | ^^^^^^ this is the parsed closure... 3 | } | - ...but likely you meant the closure to end here help: try adding braces | 2 ~ let _x = Box::new(|x| {x+1;); 3 ~ }} | error: expected `;`, found `}` --> ./main.rs:2:32 | 2 | let _x = Box::new(|x|x+1;); | ^ help: add `;` here 3 | } | - unexpected token error: aborting due to 3 previous errors ``` We got 3 errors, but all but the second are unnecessary or just wrong. This commit allows outputting correct suggestions and errors. The above code would output like this: ``` error: closure bodies that contain statements must be surrounded by braces --> ./main.rs:2:25 | 2 | let _x = Box::new(|x|x+1;); | ^ ^ | note: statement found outside of a block --> ./main.rs:2:29 | 2 | let _x = Box::new(|x|x+1;); | ---^ this `;` turns the preceding closure into a statement | | | this expression is a statement because of the trailing semicolon note: the closure body may be incorrectly delimited --> ./main.rs:2:23 | 2 | let _x = Box::new(|x|x+1;); | ^^^^^^ - ...but likely you meant the closure to end here | | | this is the parsed closure... help: try adding braces | 2 | let _x = Box::new(|x| {x+1;}); | + + error: aborting due to previous error ``` Fixes https://github.com/rust-lang/rust/issues/107959. r? diagnostics
This commit is contained in:
commit
8acbfe27d6
@ -982,7 +982,11 @@ fn recover_missing_braces_around_closure_body(
|
||||
let initial_semicolon = self.token.span;
|
||||
|
||||
while self.eat(&TokenKind::Semi) {
|
||||
let _ = self.parse_stmt(ForceCollect::Yes)?;
|
||||
let _ =
|
||||
self.parse_stmt_without_recovery(false, ForceCollect::Yes).unwrap_or_else(|e| {
|
||||
e.cancel();
|
||||
None
|
||||
});
|
||||
}
|
||||
|
||||
expect_err.set_primary_message(
|
||||
|
@ -4,16 +4,23 @@
|
||||
// If this recovery happens, then plenty of errors are emitted. Here, we expect
|
||||
// only one error.
|
||||
//
|
||||
// This is part of issue #88065:
|
||||
// This is part of the following issues:
|
||||
// https://github.com/rust-lang/rust/issues/88065
|
||||
// https://github.com/rust-lang/rust/issues/107959
|
||||
|
||||
// run-rustfix
|
||||
|
||||
fn main() {
|
||||
// Closure with multiple expressions delimited by semicolon.
|
||||
let num = 5;
|
||||
(1..num).reduce(|a, b| {
|
||||
//~^ ERROR: closure bodies that contain statements must be surrounded by braces
|
||||
println!("{}", a);
|
||||
a * b
|
||||
}).unwrap();
|
||||
|
||||
// Closure with a single expression ended by a semicolon.
|
||||
let mut v = vec![1, 2, 3];
|
||||
v.iter_mut().for_each(|x| {*x = *x+1;});
|
||||
//~^ ERROR: closure bodies that contain statements must be surrounded by braces
|
||||
}
|
||||
|
@ -4,16 +4,23 @@
|
||||
// If this recovery happens, then plenty of errors are emitted. Here, we expect
|
||||
// only one error.
|
||||
//
|
||||
// This is part of issue #88065:
|
||||
// This is part of the following issues:
|
||||
// https://github.com/rust-lang/rust/issues/88065
|
||||
// https://github.com/rust-lang/rust/issues/107959
|
||||
|
||||
// run-rustfix
|
||||
|
||||
fn main() {
|
||||
// Closure with multiple expressions delimited by semicolon.
|
||||
let num = 5;
|
||||
(1..num).reduce(|a, b|
|
||||
//~^ ERROR: closure bodies that contain statements must be surrounded by braces
|
||||
println!("{}", a);
|
||||
a * b
|
||||
).unwrap();
|
||||
|
||||
// Closure with a single expression ended by a semicolon.
|
||||
let mut v = vec![1, 2, 3];
|
||||
v.iter_mut().for_each(|x|*x = *x+1;);
|
||||
//~^ ERROR: closure bodies that contain statements must be surrounded by braces
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: closure bodies that contain statements must be surrounded by braces
|
||||
--> $DIR/missing_braces_around_block.rs:14:26
|
||||
--> $DIR/missing_braces_around_block.rs:16:26
|
||||
|
|
||||
LL | (1..num).reduce(|a, b|
|
||||
| ^
|
||||
@ -8,14 +8,14 @@ LL | ).unwrap();
|
||||
| ^
|
||||
|
|
||||
note: statement found outside of a block
|
||||
--> $DIR/missing_braces_around_block.rs:16:26
|
||||
--> $DIR/missing_braces_around_block.rs:18:26
|
||||
|
|
||||
LL | println!("{}", a);
|
||||
| -----------------^ this `;` turns the preceding closure into a statement
|
||||
| |
|
||||
| this expression is a statement because of the trailing semicolon
|
||||
note: the closure body may be incorrectly delimited
|
||||
--> $DIR/missing_braces_around_block.rs:14:21
|
||||
--> $DIR/missing_braces_around_block.rs:16:21
|
||||
|
|
||||
LL | (1..num).reduce(|a, b|
|
||||
| _____________________^
|
||||
@ -34,5 +34,30 @@ LL | a * b
|
||||
LL ~ }).unwrap();
|
||||
|
|
||||
|
||||
error: aborting due to previous error
|
||||
error: closure bodies that contain statements must be surrounded by braces
|
||||
--> $DIR/missing_braces_around_block.rs:24:29
|
||||
|
|
||||
LL | v.iter_mut().for_each(|x|*x = *x+1;);
|
||||
| ^ ^
|
||||
|
|
||||
note: statement found outside of a block
|
||||
--> $DIR/missing_braces_around_block.rs:24:39
|
||||
|
|
||||
LL | v.iter_mut().for_each(|x|*x = *x+1;);
|
||||
| ---------^ this `;` turns the preceding closure into a statement
|
||||
| |
|
||||
| this expression is a statement because of the trailing semicolon
|
||||
note: the closure body may be incorrectly delimited
|
||||
--> $DIR/missing_braces_around_block.rs:24:27
|
||||
|
|
||||
LL | v.iter_mut().for_each(|x|*x = *x+1;);
|
||||
| ^^^^^^^^^^^^ - ...but likely you meant the closure to end here
|
||||
| |
|
||||
| this is the parsed closure...
|
||||
help: try adding braces
|
||||
|
|
||||
LL | v.iter_mut().for_each(|x| {*x = *x+1;});
|
||||
| + +
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user