rust-lang / rust

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

Boolean OR is getting confused with closure? #116128

Open arifd opened 1 year ago

arifd commented 1 year ago

Code

fn main() {
  let _ = {
    {true} || true
  };
}

Current output

Compiling playground v0.0.1 (/playground)
warning: unnecessary braces around block return value
 --> src/main.rs:3:5
  |
3 |     {true} || true
  |     ^    ^
  |
  = note: `#[warn(unused_braces)]` on by default
help: remove these braces
  |
3 -     {true} || true
3 +     true || true
  |

error[E0308]: mismatched types
 --> src/main.rs:3:6
  |
3 |     {true} || true
  |      ^^^^ expected `()`, found `bool`

For more information about this error, try `rustc --explain E0308`.
warning: `playground` (bin "playground") generated 1 warning
error: could not compile `playground` (bin "playground") due to previous error; 1 warning emitted

Desired output

No response

Rationale and extra context

No response

Other cases

No response

Anything else?

No response

dawnofmidnight commented 1 year ago

For further context, this code after Rustfmt is the following:

fn main() {
    let _ = {
        {
            true
        }
        || true
    };
}

Thus, this code is being interpreted as a block statement, followed by a closure. This is not a parser bug, but it is not a very good error.

vincenzopalazzo commented 1 year ago

@rustbot claim

vincenzopalazzo commented 1 year ago

Thus, this code is being interpreted as a block statement, followed by a closure. This is not a parser bug, but it is not a very good error.

Mh ok I think I got the problem, but I am not able to imagine what kind of message we can add here to better understand the problem.

There are any suggestions?

arifd commented 1 year ago

As a motivating example, this is what I tried to express:

fn foo() -> bool {
    { println!("a"); false } || { println!("b"); false }
}

and encountered this error:

error[E0308]: mismatched types
 --> src/main.rs:4:22
  |
4 |     { println!("a"); false } || { println!("b"); false }
  |                      ^^^^^ expected `()`, found `bool`
  |
help: you might have meant to return this value
  |
4 |     { println!("a"); return false; } || { println!("b"); false }
  |                      ++++++      +

error[E0308]: mismatched types
 --> src/main.rs:4:30
  |
3 | fn foo() -> bool {
  |             ---- expected `bool` because of return type
4 |     { println!("a"); false } || { println!("b"); false }
  |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found closure
  |
  = note: expected type `bool`
          found closure `[closure@src/main.rs:4:30: 4:32]`
help: parentheses are required to parse this as an expression
  |
4 |     ({ println!("a"); false }) || { println!("b"); false }
  |     +                        +

For more information about this error, try `rustc --explain E0308`.
error: could not compile `playground` (bin "playground") due to 2 previous errors

Curiously, binding to a variable fixes the problem:

fn foo() -> bool {
    let result = { println!("a"); false } || { println!("b"); false };
    result
}

but clippy doesn't like it.

dawnofmidnight commented 1 year ago

Mh ok I think I got the problem, but I am not able to imagine what kind of message we can add here to better understand the problem.

If this sort of situation is detectable, it could be something like

= note: this is a block statement followed by a closure
= help: to make this a block expression, consider surrounding it in parentheses `({ ... }) || ...`

This is very tentative wording, but something along those lines would at least make it clear what it going on, and suggest a potential fix.

compiler-errors commented 1 year ago

We already have some logic to explain this on E0308, but the code to make this work in case we're not already expecting a bool will need to be written somewhat delicately, since this is very deep into the "confusing false-positive" territory of diagnostics :rofl:

https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=de948b08c3c75a1ae66a8a0e231f6ac5