Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorrect parser error when match statement is missing its ; #40799

Closed
timthelion opened this issue Mar 24, 2017 · 4 comments · Fixed by #64825
Closed

Incorrect parser error when match statement is missing its ; #40799

timthelion opened this issue Mar 24, 2017 · 4 comments · Fixed by #64825
Labels
A-diagnostics Area: Messages for errors, warnings, and lints C-bug Category: This is a bug.

Comments

@timthelion
Copy link

I found an analog of bug #40006 (Forty thousand bugs, you've gotta be kidding me! :D You've put in a lot of work there!) and @sanxiyn asked me to file my own report, so here it is.

If you don't put a ; at the end of a match block then the compiler tells you very unrelated things: https://play.rust-lang.org/?gist=ab74d4c0f3dce8c095f79469bc69b072&version=nightly&backtrace=0

@sanxiyn sanxiyn added A-diagnostics Area: Messages for errors, warnings, and lints A-parser Area: The parsing of Rust source code to an AST labels Mar 24, 2017
@oli-obk
Copy link
Contributor

oli-obk commented Mar 27, 2017

I don't see a parser error. I see a type error as I expected.

For posterity: the code is

fn main() {
    match 3 {
        4 => 1,
        3 => {
            println!("Yep it maches.");
            2
        }
        _ => 2
    }
    println!("Bye!")
}

And the error is

error[E0308]: mismatched types
 --> <anon>:6:13
  |
6 |             2
  |             ^ expected (), found integral variable
  |
  = note: expected type `()`
             found type `{integer}`

error[E0308]: match arms have incompatible types
 --> <anon>:2:5
  |
2 |       match 3 {
  |  _____^ starting here...
3 | |         4 => 1,
4 | |         3 => {
5 | |             println!("Yep it maches.");
6 | |             2
7 | |         }
8 | |         _ => 2
9 | |     }
  | |_____^ ...ending here: expected integral variable, found ()
  |
  = note: expected type `{integer}`
             found type `()`
note: match arm with an incompatible type
 --> <anon>:4:14
  |
4 |           3 => {
  |  ______________^ starting here...
5 | |             println!("Yep it maches.");
6 | |             2
7 | |         }
  | |_________^ ...ending here

error: aborting due to 2 previous errors

@timthelion
Copy link
Author

I dissagree.

The pragmatic reason I dissagree, is that the error is useless. It fails to identify the location and the kind of mistake that the programmer has made.

The pendantic reason I dissagree, is that the error is wrong.

error[E0308]: match arms have incompatible types
 --> <anon>:2:5
  |
2 |       match 3 {
  |  _____^ starting here...
3 | |         4 => 1,
4 | |         3 => {
5 | |             println!("Yep it maches.");
6 | |             2
7 | |         }
8 | |         _ => 2
9 | |     }
  | |_____^ ...ending here: expected integral variable, found ()

The match arms do NOT have incompatible types. Every arm of the match evaluates, eventually, to an {integer}. This is clear from the fact that adding a ; fixes the problem. If there was an error in the match block itself, then adding a ; wouldn't do any good.

A correct type error would be:

error[E0??]: match block's type does not match context.
 --> <anon>:2:5
  |
2 |       match 3 {
  |  _____^ starting here...
3 | |         4 => 1,
4 | |         3 => {
5 | |             println!("Yep it maches.");
6 | |             2
7 | |         }
8 | |         _ => 2
9 | |     }
  | |_____^ ...ending here: match block has type {integer}, expected ()

@oli-obk
Copy link
Contributor

oli-obk commented Mar 27, 2017

The initial error message is correct:

error[E0308]: mismatched types
 --> <anon>:6:13
  |
6 |             2
  |             ^ expected (), found integral variable
  |
  = note: expected type `()`
             found type `{integer}`

Everything else continues from there. Probably just a case of passing up a real type (the tuple) instead of TyErr

@Mark-Simulacrum Mark-Simulacrum added C-bug Category: This is a bug. and removed A-parser Area: The parsing of Rust source code to an AST labels Jul 27, 2017
@estebank

This comment has been minimized.

Centril added a commit to Centril/rust that referenced this issue Sep 27, 2019
…atthewjasper

Account for tail expressions when pointing at return type

When there's a type mismatch we make an effort to check if it was
caused by a function's return type. This logic now makes sure to
only point at the return type if the error happens in a tail
expression.

Turn `walk_parent_nodes` method into an iterator.

CC rust-lang#39968, CC rust-lang#40799.
Centril added a commit to Centril/rust that referenced this issue Sep 28, 2019
…atthewjasper

Account for tail expressions when pointing at return type

When there's a type mismatch we make an effort to check if it was
caused by a function's return type. This logic now makes sure to
only point at the return type if the error happens in a tail
expression.

Turn `walk_parent_nodes` method into an iterator.

CC rust-lang#39968, CC rust-lang#40799.
Centril added a commit to Centril/rust that referenced this issue Sep 28, 2019
…atthewjasper

Account for tail expressions when pointing at return type

When there's a type mismatch we make an effort to check if it was
caused by a function's return type. This logic now makes sure to
only point at the return type if the error happens in a tail
expression.

Turn `walk_parent_nodes` method into an iterator.

CC rust-lang#39968, CC rust-lang#40799.
Centril added a commit to Centril/rust that referenced this issue Sep 29, 2019
Point at enclosing match when expecting `()` in arm

When encountering code like the following:

```rust
fn main() {
    match 3 {
        4 => 1,
        3 => {
            println!("Yep it maches.");
            2
        }
        _ => 2
    }
    println!("Bye!")
}
```

point at the enclosing `match` expression and suggest ignoring the
returned value:

```
error[E0308]: mismatched types
  --> $DIR/match-needing-semi.rs:8:13
   |
LL | /     match 3 {
LL | |         4 => 1,
LL | |         3 => {
LL | |             2
   | |             ^ expected (), found integer
LL | |         }
LL | |         _ => 2
LL | |     }
   | |     -- help: consider using a semicolon here
   | |_____|
   |       expected this to be `()`
   |
   = note: expected type `()`
              found type `{integer}
```

Fix rust-lang#40799.
Centril added a commit to Centril/rust that referenced this issue Sep 29, 2019
Point at enclosing match when expecting `()` in arm

When encountering code like the following:

```rust
fn main() {
    match 3 {
        4 => 1,
        3 => {
            println!("Yep it maches.");
            2
        }
        _ => 2
    }
    println!("Bye!")
}
```

point at the enclosing `match` expression and suggest ignoring the
returned value:

```
error[E0308]: mismatched types
  --> $DIR/match-needing-semi.rs:8:13
   |
LL | /     match 3 {
LL | |         4 => 1,
LL | |         3 => {
LL | |             2
   | |             ^ expected (), found integer
LL | |         }
LL | |         _ => 2
LL | |     }
   | |     -- help: consider using a semicolon here
   | |_____|
   |       expected this to be `()`
   |
   = note: expected type `()`
              found type `{integer}
```

Fix rust-lang#40799.
@bors bors closed this as completed in 8a167ed Sep 29, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints C-bug Category: This is a bug.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants