Skip to content

Misplaced parenthesis in if let produces unhelpful error message #82827

Closed
@mcclure

Description

@mcclure

I am learning Rust. I haven't read the full manual yet, I am just bumbling through. Tonight I hit an error message that confused me. I am using Rust 1.50.0 on OS X 10.13.6, but I can reproduce the problem on Godbolt. Here's my Godbolt repro:

// Type your code here, or load an example.
pub fn main() {
  let x = Some(3);
  if (let Some(y) = x) {
    println!("{}", y)
  } else {
    println!("None")
  }
}

This is wrong because the parenthesis between if and let confuses Rust completely. If you remove the parenthesis (Godbolt link) it works fine. But I didn't know that.

The wrong version produces the following error messages:

error[E0658]: `let` expressions in this position are experimental
 --> <source>:4:7
  |
4 |   if (let Some(y) = x) {
  |       ^^^^^^^^^^^^^^^
  |
  = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information

error: expected expression, found statement (`let`)
 --> <source>:4:7
  |
4 |   if (let Some(y) = x) {
  |       ^^^^^^^^^^^^^^^
  |
  = note: variable declaration using `let` is a statement

warning: unnecessary parentheses around `if` condition
 --> <source>:4:6
  |
4 |   if (let Some(y) = x) {
  |      ^^^^^^^^^^^^^^^^^ help: remove these parentheses
  |
  = note: `#[warn(unused_parens)]` on by default

error: aborting due to 2 previous errors; 1 warning emitted

In my opinion, this is not as helpful as it could be.

The "experimental" error mislead me badly. First off, saying something is "experimental" does not mean it is wrong, it could mean "this will be legal in the next released version". Second off, the "experimental" error does not say what is experimental. Is it destructuring which is not allowed? Is it destructuring *in this position* that is not allowed? (In context-- IE not this minimal example-- I had the if embedded as an expression inside a match.) The linked github issue is over two years old and is not enlightening, in fact, it's just frankly kinda scary.

The "expected expression, found statement" error is potentially helpful, but confused me a little, because I'd used "if let" before— and I wasn't paying as much attention to it anyway, because (C habit that I shouldn't be bringing with me into Rust?) if I get two errors on the same line, I assume the first one is the "real" error and the second one is just the compiler being thrown off by the first error.

The warning is a good hint (I had a conversation on twitter about this) but first off it looks like a style recommendation, not a functional one; and also I did not see it.

My expected behavior:

  • Because putting the parenthesis in the wrong place when doing an if let is a likely new-user "gotcha" (especially for C++ programmers, where the equivalent of if (let x = ...) has been a syntax since C++03), it would be great if the compiler would detect this would have been correct syntax without the parenthesis and print a "hint: there are no parenthesis in if let, recommend remove parenthesis" there.
  • A more nebulous thought: You should present those "is experimental" errors in a very different way, if you display them at all! They're scary, they're not actionable, they could be misleading. One possibility (I assume this has been well hashed out, but) would be to treat the experimental features as like a third kind of error besides error and warning, something like "note: this would have been legal in the 0.51 beta" (and maybe they shouldn't be printed with the errors— maybe they should be sorted down with the warnings? I wouldn't have focused on the "experimental" error, when I got it, if it weren't first).

Postscript: I had some thoughts about that parenthesis warning. I thought they would be distracting in this issue, and those thoughts were more like a feature request or a question than a bug report, so as your issue form suggests I made a forum thread about that instead.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-diagnosticsArea: Messages for errors, warnings, and lintsA-parserArea: The lexing & parsing of Rust source code to an ASTC-bugCategory: This is a bug.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions