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

Type inference failure leads to incorrect "match arm with an incompatible type" message #57206

Closed
mqudsi opened this issue Dec 29, 2018 · 1 comment · Fixed by #58267
Closed
Assignees
Labels
A-diagnostics Area: Messages for errors, warnings, and lints A-inference Area: Type inference

Comments

@mqudsi
Copy link
Contributor

mqudsi commented Dec 29, 2018

In the code sample below, there are two ultimately identical functions with the same problem, but while the compiler correctly reports the incorrect match block in the first function (test_func1()), it fails to do so in the second (test_func2()):

fn main() {
    let _ = test_func1(1);
    let _ = test_func2(1);
}

fn test_func1(n: i32) -> i32 {
    match n {
        12 => 'b',
        _ => 42,
    }
}

fn test_func2(n: i32) -> i32 {
    let x = match n {
        12 => 'b',
        _ => 42,
    };

    x
}

which produces the following correct error for the first function:

error[E0308]: match arms have incompatible types
  --> ./test.rs:7:5
   |
7  | /     match n {
8  | |         12 => 'b',
   | |               --- match arm with an incompatible type
9  | |         _ => 42,
10 | |     }
   | |_____^ expected i32, found char

but an incorrect error for the second message:

error[E0308]: match arms have incompatible types
  --> ./test.rs:14:13
   |
14 |       let x = match n {
   |  _____________^
15 | |         12 => 'b',
16 | |         _ => 42,
   | |              -- match arm with an incompatible type
17 | |     };
   | |_____^ expected char, found integral variable
   |
   = note: expected type `char`
              found type `{integer}`

When test_func2() is extended with an explicit type hint (that should not be necessary as it can be derived from the existing code), the resulting error message is correct once again:

fn test_func3(n: i32) -> i32 {
    let x: i32 = match n {
        12 => 'b',
        _ => 42,
    };

    x
}

producing

error[E0308]: match arms have incompatible types
  --> ./test.rs:23:18
   |
23 |       let x: i32 = match n {
   |  __________________^
24 | |         12 => 'b',
   | |               --- match arm with an incompatible type
25 | |         _ => 42,
26 | |     };
   | |_____^ expected i32, found char
@Centril Centril added A-inference Area: Type inference A-diagnostics Area: Messages for errors, warnings, and lints labels Dec 30, 2018
@estebank
Copy link
Contributor

This is because the compiler is trying to unify a type for the entire match block before it gets to unifying x and the return type i32. Because of this, it attempts to unify every single arm going in order. In this case, that means it takes char first and assumes that the rest of the match arms will have to be char too. It will be hard to avoid these errors without delaying the emission of them until after the entire block has unified...

Centril added a commit to Centril/rust that referenced this issue Feb 14, 2019
Tweak "incompatible match arms" error

- Point at the body expression of the match arm with the type error.
- Point at the prior match arms explicitly stating the evaluated type.
- Point at the entire match expr in a secondary span, instead of primary.
- For type errors in the first match arm, the cause is outside of the
  match, treat as implicit block error to give a more appropriate error.

Fix rust-lang#46776, fix rust-lang#57206.
CC rust-lang#24157, rust-lang#38234.
Centril added a commit to Centril/rust that referenced this issue Feb 14, 2019
Tweak "incompatible match arms" error

- Point at the body expression of the match arm with the type error.
- Point at the prior match arms explicitly stating the evaluated type.
- Point at the entire match expr in a secondary span, instead of primary.
- For type errors in the first match arm, the cause is outside of the
  match, treat as implicit block error to give a more appropriate error.

Fix rust-lang#46776, fix rust-lang#57206.
CC rust-lang#24157, rust-lang#38234.
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 A-inference Area: Type inference
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants