rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
97.31k stars 12.58k forks source link

Incorrect "closure bodies that contain statements must be surrounded by braces" error in unrelatedly invalid code #127223

Open izik1 opened 3 months ago

izik1 commented 3 months ago

Code

fn test() {
    let value = || {};

    (value;);
}

Current output

error: closure bodies that contain statements must be surrounded by braces
 --> src/lib.rs:2:17
  |
2 |     let value = || {};
  |                 ^^
3 |
4 |     (value;);
  |            ^
  |
note: statement found outside of a block
 --> src/lib.rs:4:11
  |
2 |     let value = || {};
  |                    -- this expression is a statement because of the trailing semicolon
3 |
4 |     (value;);
  |           ^ this `;` turns the preceding closure into a statement
note: the closure body may be incorrectly delimited
 --> src/lib.rs:2:17
  |
2 |     let value = || {};
  |                 ^^^^^ this is the parsed closure...
3 |
4 |     (value;);
  |            - ...but likely you meant the closure to end here
help: try adding braces
  |
2 ~     let value = || { {};
3 |
4 ~     (value;});
  |

Desired output

error: expected one of `!`, `)`, `,`, `.`, `::`, `?`, `{`, or an operator, found `;`
 --> src/lib.rs:4:11
  |
4 |     (value;);
  |           ^ expected one of 8 possible tokens

Rationale and extra context

This error is unrelated to the closure, and indeed, applying the suggestion leaves us with:

fn test() {
    let value = || { {};

    (value; });
}

Which now has an improperly closed brace. The correct code would (most likely) be (value)

The original code I had made the suggestion even weirder since the closure was an argument to a Higher Order Function (instead of bound to a variable) and the last line was a function call with a ; after its argument (instead of a paren expression), which happened due to a typo 😅. Just in case something following that structure would make for a useful test case as well:

fn test() {
    let value = std::iter::once_with(|| ());

    std::men::drop(value;);
}

Other cases

No response

Rust Version

❯ rustc +nightly --version --verbose
rustc 1.81.0-nightly (6868c831a 2024-06-30)
binary: rustc
commit-hash: 6868c831a1eb45c5150ff623cef5e42a8b8946d0
commit-date: 2024-06-30
host: aarch64-apple-darwin
release: 1.81.0-nightly
LLVM version: 18.1.7

Anything else?

No response

eggyal commented 3 months ago

https://github.com/rust-lang/rust/blob/7d97c59438e933e86f557ed999da3b8dfc6855a7/compiler/rustc_parse/src/parser/mod.rs#L846-L859

I suppose this test should only be applied when at the same depth as the closure definition?