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;
|
let initial_semicolon = self.token.span;
|
||||||
|
|
||||||
while self.eat(&TokenKind::Semi) {
|
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(
|
expect_err.set_primary_message(
|
||||||
|
@ -4,16 +4,23 @@
|
|||||||
// If this recovery happens, then plenty of errors are emitted. Here, we expect
|
// If this recovery happens, then plenty of errors are emitted. Here, we expect
|
||||||
// only one error.
|
// 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/88065
|
||||||
|
// https://github.com/rust-lang/rust/issues/107959
|
||||||
|
|
||||||
// run-rustfix
|
// run-rustfix
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
// Closure with multiple expressions delimited by semicolon.
|
||||||
let num = 5;
|
let num = 5;
|
||||||
(1..num).reduce(|a, b| {
|
(1..num).reduce(|a, b| {
|
||||||
//~^ ERROR: closure bodies that contain statements must be surrounded by braces
|
//~^ ERROR: closure bodies that contain statements must be surrounded by braces
|
||||||
println!("{}", a);
|
println!("{}", a);
|
||||||
a * b
|
a * b
|
||||||
}).unwrap();
|
}).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
|
// If this recovery happens, then plenty of errors are emitted. Here, we expect
|
||||||
// only one error.
|
// 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/88065
|
||||||
|
// https://github.com/rust-lang/rust/issues/107959
|
||||||
|
|
||||||
// run-rustfix
|
// run-rustfix
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
// Closure with multiple expressions delimited by semicolon.
|
||||||
let num = 5;
|
let num = 5;
|
||||||
(1..num).reduce(|a, b|
|
(1..num).reduce(|a, b|
|
||||||
//~^ ERROR: closure bodies that contain statements must be surrounded by braces
|
//~^ ERROR: closure bodies that contain statements must be surrounded by braces
|
||||||
println!("{}", a);
|
println!("{}", a);
|
||||||
a * b
|
a * b
|
||||||
).unwrap();
|
).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
|
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|
|
LL | (1..num).reduce(|a, b|
|
||||||
| ^
|
| ^
|
||||||
@ -8,14 +8,14 @@ LL | ).unwrap();
|
|||||||
| ^
|
| ^
|
||||||
|
|
|
|
||||||
note: statement found outside of a block
|
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);
|
LL | println!("{}", a);
|
||||||
| -----------------^ this `;` turns the preceding closure into a statement
|
| -----------------^ this `;` turns the preceding closure into a statement
|
||||||
| |
|
| |
|
||||||
| this expression is a statement because of the trailing semicolon
|
| this expression is a statement because of the trailing semicolon
|
||||||
note: the closure body may be incorrectly delimited
|
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|
|
LL | (1..num).reduce(|a, b|
|
||||||
| _____________________^
|
| _____________________^
|
||||||
@ -34,5 +34,30 @@ LL | a * b
|
|||||||
LL ~ }).unwrap();
|
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