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 "match arms have incompatible types" error message #24157

Closed
offlinemark opened this issue Apr 7, 2015 · 28 comments · Fixed by #117526
Closed

Incorrect "match arms have incompatible types" error message #24157

offlinemark opened this issue Apr 7, 2015 · 28 comments · Fixed by #117526
Labels
A-diagnostics Area: Messages for errors, warnings, and lints C-enhancement Category: An issue proposing an enhancement or a PR with one. D-papercut Diagnostics: An error or lint that needs small tweaks. P-low Low priority T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@offlinemark
Copy link
Contributor

I have code that matches on a Result<usize>, with cases for Ok(usize_var) and Err(why). I get a "match arms have incompatible types" error upon compilation which I believe is incorrect.

I'm not incredibly experienced with this, but discussion in irc (https://botbot.me/mozilla/rust/2015-04-06/?msg=35985521&page=37) supports that this may be a bug.

I tried this code (available at http://is.gd/Y00aRi):

fn main() {
    let mut input: String = String::new();
    match std::io::stdin().read_line(&mut input) {
        Ok(bytes_read) => bytes_read,
        Err(why) => panic!("{}", why)
    }
    println!("{}", input);
}

I expected it to compile, however there is a "match arms have incompatible types" error even though I believe the match arms should both be of type usize.

I should note that adding a semicolon after the match causes clean compilation.

@steveklabnik steveklabnik added the A-diagnostics Area: Messages for errors, warnings, and lints label Apr 7, 2015
@ftxqxd
Copy link
Contributor

ftxqxd commented Apr 7, 2015

(@steveklabnik I don't think the A-diagnostics label is appropriate for this issue. The bug is that this gives an error at all, not that the error message is bad, so perhaps I-wrong would be better?)

@steveklabnik
Copy link
Member

I mean, it's a very bad error regardless, but yeah, maybe. I'll add it too.

@offlinemark
Copy link
Contributor Author

My rustc version, if it helps

$ rustc --verbose --version
rustc 1.0.0-beta (9854143cb 2015-04-02) (built 2015-04-02)
binary: rustc
commit-hash: 9854143cba679834bc4ef932858cd5303f015a0e
commit-date: 2015-04-02
build-date: 2015-04-02
host: x86_64-apple-darwin
release: 1.0.0-beta

@lilyball
Copy link
Contributor

lilyball commented Apr 8, 2015

Yielding an error is correct here. The error message is merely misleading.

The core issue here is your first match arm is attempting to evaluate to a usize value, but the entire match statement is not semicolon-terminated. If you replace the panic!() with, say, 42, you get a similar error:

<anon>:3:5: 6:6 error: mismatched types:
 expected `()`,
    found `usize`
(expected (),
    found usize) [E0308]
<anon>:3     match std::io::stdin().read_line(&mut input) {
<anon>:4         Ok(bytes_read) => bytes_read,
<anon>:5         Err(why) => 42
<anon>:6     }

This is also a bit misleading. The error looks like this because the match expression occurs in statement position, so either the match expression needs to resolve to the type () or it needs to be semicolon-terminated. The error here could definitely be better. In your case, the error is about the match arms having different types because Rust apparently decides to unify the panic!() with the expected () return value, instead of with the first match arm's usize value. If it resolved it with the usize then you'd see the error I listed above instead.

@lilyball lilyball removed the I-wrong label Apr 8, 2015
@lilyball
Copy link
Contributor

lilyball commented Apr 8, 2015

Given that, I'm removing I-wrong.

@ftxqxd
Copy link
Contributor

ftxqxd commented Apr 8, 2015

@kballard Huh, you're right. I always assumed that adding a semicolon to a statement-position match shouldn't ever change anything.

@lilyball
Copy link
Contributor

lilyball commented Apr 8, 2015

Funnily enough, just the other day in IRC @bstrie discovered the exact same thing :)

@ghost
Copy link

ghost commented Apr 19, 2015

Another interesting test case, by @Binero from #24568, that we should include as part of the fix:

fn main() {
    is_one(1)
}

fn is_one(a: u8) {
    match a {
        1 => true,
        _ => panic!("It's not one!"),
    }
}
<anon>:6:5: 9:6 error: match arms have incompatible types:
 expected `bool`,
    found `()`
(expected bool,
    found ()) [E0308]
<anon>:6     match a {
<anon>:7         1 => true,
<anon>:8         _ => panic!("It's not one!"),
<anon>:9     }
<anon>:8:14: 8:38 note: match arm with an incompatible type
<anon>:8         _ => panic!("It's not one!"),
                      ^~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to previous error
playpen: application terminated with error code 101
Program ended.

@rbtcollins
Copy link
Contributor

Just to note, that this is super confusing for new rust developers - I sought help in #rust after beating my head on the wall for a bit :)

@fungos
Copy link

fungos commented Nov 3, 2016

Another code that to me looks the same issue or even #35685. But it is a little different so I'm not really sure if should open a new issue:

pub trait Foo {}

struct Bar;
struct Baz;

impl Foo for Bar { }
impl Foo for Baz { }

fn not_all_paths(a: &str) -> u32 {
    match a {
        "baz" => 0,
        _ => 1,
    }; // "not all control paths return a value" due to ;
}

fn right(b: &str) -> Box<Foo> {
    match b {
        "baz" => Box::new(Baz),
        _ => Box::new(Bar),
    }
}

fn wrong(c: &str) -> Box<Foo> {
    match c {
        "baz" => Box::new(Baz),
        _ => Box::new(Bar),
    }; // "match arms have incompatible types" due to ;
}

fn main() {
}

Play here: https://is.gd/GTv1gf
Using: rustc 1.14.0-nightly (7c69b0d 2016-11-01)

@nambrot
Copy link

nambrot commented Feb 27, 2017

Could someone outline what the recommended approach is for differently typed match arms? What do I do with options where i want to just run a operation in the Some case but ignore in the None case?

@Mark-Simulacrum
Copy link
Member

So I think the fix here would involve basically throwing away individual match arms, returning () instead of their type so as to "unify" when the match is in statement position. This seems relatively fine, but cc @rust-lang/lang -- would we need an RFC for this? Is that the correct interpretation of the best option?

@Mark-Simulacrum Mark-Simulacrum added the T-lang Relevant to the language team, which will review and decide on the PR/issue. label May 24, 2017
@withoutboats
Copy link
Contributor

The current behavior seems preferable to a change to me.

In all of these cases you are doing something quite unidiomatic, and in several the programmer has almost certainly made a mistake and should receive an error. For example:

fn is_one(a: u8) {
    match a {
        1 => true,
        _ => panic!("It's not one!"),
    }
}

It seems clear to me that this function is supposed to return bool; if you change the return type, it will compile.

For the rest of them I see similar errors.

There are diagnostics issues, but I definitely think nothing should change about the semantics.

@nikomatsakis
Copy link
Contributor

I agree with @withoutboats that this is a purely diagnostic issue.

@Mark-Simulacrum Mark-Simulacrum added C-enhancement Category: An issue proposing an enhancement or a PR with one. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. and removed T-lang Relevant to the language team, which will review and decide on the PR/issue. labels Jul 22, 2017
@estebank

This comment has been minimized.

@estebank
Copy link
Contributor

Updated to Jan 2019:

For @withoutboats case, the output is the original error:

error[E0308]: match arms have incompatible types
 --> src/main.rs:6:5
  |
6 | /     match a {
7 | |         1 => true,
8 | |         _ => panic!("It's not one!"),
9 | |     }
  | |_____^ expected bool, found ()
  |
  = note: expected type `bool`
             found type `()`
note: match arm with an incompatible type
 --> src/main.rs:8:14
  |
8 |         _ => panic!("It's not one!"),
  |              ^^^^^^^^^^^^^^^^^^^^^^^
  = note: this error originates in a macro outside of the current crate

But if we "fix" the incompatible arms "problem", we get get a suggestion to change the return type:

error[E0308]: mismatched types
 --> src/main.rs:8:40
  |
5 | fn is_one(a: u8) {
  |                  - help: possibly return type missing here?: `-> bool `
...
8 |         _ => {panic!("It's not one!"); false},
  |                                        ^^^^^ expected (), found bool
  |
  = note: expected type `()`
             found type `bool`

I'm guessing that adding that suggestion to match arms have incompatible types would be worthwhile (maybe with a suggestion to add a semicolon at the end of the match as we do in some cases, but I don't think that's as worthwhile).


@fungos's code now produces a code suggestion to remove the incorrect semicolons:

error[E0308]: mismatched types
  --> src/main.rs:9:30
   |
9  | fn not_all_paths(a: &str) -> u32 {
   |    -------------             ^^^ expected u32, found ()
   |    |
   |    this function's body doesn't return
...
13 |     }; // "not all control paths return a value" due to ;
   |      - help: consider removing this semicolon
   |
   = note: expected type `u32`
              found type `()`

error[E0308]: match arms have incompatible types
  --> src/main.rs:24:5
   |
24 | /     match c {
25 | |         "baz" => Box::new(Baz),
26 | |         _ => Box::new(Bar),
   | |              ------------- match arm with an incompatible type
27 | |     }; // "match arms have incompatible types" due to ;
   | |_____^ expected struct `Baz`, found struct `Bar`
   |
   = note: expected type `std::boxed::Box<Baz>`
              found type `std::boxed::Box<Bar>`

error[E0308]: mismatched types
  --> src/main.rs:23:22
   |
23 | fn wrong(c: &str) -> Box<Foo> {
   |    -----             ^^^^^^^^ expected struct `std::boxed::Box`, found ()
   |    |
   |    this function's body doesn't return
...
27 |     }; // "match arms have incompatible types" due to ;
   |      - help: consider removing this semicolon
   |
   = note: expected type `std::boxed::Box<(dyn Foo + 'static)>`
              found type `()`

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.
@estebank
Copy link
Contributor

estebank commented Mar 7, 2019

I believe there's little room for improvement here beyond what has been done so far:

error[E0308]: match arms have incompatible types
 --> src/main.rs:5:21
  |
3 | /     match std::io::stdin().read_line(&mut input) {
4 | |         Ok(bytes_read) => bytes_read,
  | |                           ---------- this is found to be of type `usize`
5 | |         Err(why) => panic!("{}", why)
  | |                     ^^^^^^^^^^^^^^^^^ expected usize, found ()
6 | |     }
  | |_____- `match` arms have incompatible types
  |
  = note: expected type `usize`
             found type `()`
  = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
error[E0308]: match arms have incompatible types
 --> src/main.rs:8:14
  |
6 | /     match a {
7 | |         1 => true,
  | |              ---- this is found to be of type `bool`
8 | |         _ => panic!("It's not one!"),
  | |              ^^^^^^^^^^^^^^^^^^^^^^^ expected bool, found ()
9 | |     }
  | |_____- `match` arms have incompatible types
  |
  = note: expected type `bool`
             found type `()`
  = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)

estebank added a commit to estebank/rust that referenced this issue Feb 25, 2021
Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this issue Feb 26, 2021
…oli-obk

Detect match statement intended to be tail expression

CC rust-lang#24157
bors added a commit to rust-lang-ci/rust that referenced this issue Feb 26, 2021
…i-obk

Detect match statement intended to be tail expression

CC rust-lang#24157
@workingjubilee
Copy link
Member

workingjubilee commented Feb 20, 2022

Triage report: emits the correct diagnostic for Rust Edition 2021, and thus we could close this, but before we do so, I should note that I added the caveat there quite deliberately as this actually emits the wrong diagnostic still, in a very weird way, on Edition 2015 and Edition 2018:

Compiling playground v0.0.1 (/playground)
error[[E0308]](https://doc.rust-lang.org/stable/error-index.html#E0308): `match` arms have incompatible types
 [--> src/main.rs:5:21
](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018#)  |
3 | /     match std::io::stdin().read_line(&mut input) {
4 | |         Ok(bytes_read) => bytes_read,
  | |                           ---------- this is found to be of type `usize`
5 | |         Err(why) => panic!("{}", why)
  | |                     ^^^^^^^^^^^^^^^^^ expected `usize`, found `()`
6 | |     }
  | |_____- `match` arms have incompatible types
  |
  = note: this error originates in the macro `$crate::panic::panic_2015`
  (in Nightly builds, run with -Z macro-backtrace for more info)

stable/nightly doesn't seem to matter. rustc version is 1.61.0

@estebank
Copy link
Contributor

@workingjubilee, I agree that the ticket should remain open, although with a lower priority :)

Thanks for triaging!

@estebank estebank added the P-low Low priority label Feb 22, 2022
@arkivm
Copy link

arkivm commented Nov 21, 2022

Sorry for bumping on the existing issue. But the problem I encounter is very relevant to this issue.

The snippet (playground)

fn exit_wrapper() {
    std::process::exit(1)
}

fn main() {
    let mut input: String = String::new();
    match std::io::stdin().read_line(&mut input) {
        Ok(u) => u,
        Err(_e) => exit_wrapper(),
    };
}

errors with

   Compiling playground v0.0.1 (/playground)
error[[E0308]](https://doc.rust-lang.org/nightly/error-index.html#E0308): `match` arms have incompatible types
  --> src/main.rs:9:20
   |
7  | /     match std::io::stdin().read_line(&mut input) {
8  | |         Ok(u) => u,
   | |                  - this is found to be of type `usize`
9  | |         Err(_e) => exit_wrapper(),
   | |                    ^^^^^^^^^^^^^^ expected `usize`, found `()`
10 | |     };
   | |_____- `match` arms have incompatible types

For more information about this error, try `rustc --explain E0308`.
error: could not compile `playground` due to previous error

However, it compiles when I explicitly annotate the exit_wrapper with a return type -> !.
Is it unreasonable to expect the compiler to deduce the type of exit_wrapper function automatically to !?

@workingjubilee
Copy link
Member

Is it unreasonable to expect the compiler to deduce the type of exit_wrapper function automatically to !?

Basically: yes. You are asking for the deduction Rust decided to not attempt.

Function signatures are a coercion site and must remain stable despite their interior for various other stability promises to mean much, so the function signature must dominate over whatever the contents are. This is relaxed in very specific cases, but those cases are ones where a type can be inferred along the "exterior" of the function signature, and the "interior" will not have any meaningful effect on the type deduced.

@arkivm
Copy link

arkivm commented Nov 22, 2022

Thank you @workingjubilee. That clarifies my question. Also, thanks for posting an explanation on the mentioned issue.

@estebank
Copy link
Contributor

Maybe the diagnostic could attempt to perform that analysis on exit_wrapper() to see if it could return ! and suggest that code, and either way we should be pointing at line 1 stating "exit_wrapper returns ()".

@estebank
Copy link
Contributor

current output for the original report:

error[E0308]: mismatched types
 --> src/main.rs:3:5
  |
3 | /     match std::io::stdin().read_line(&mut input) {
4 | |         Ok(bytes_read) => bytes_read,
5 | |         Err(why) => panic!("{}", why)
6 | |     }
  | |     ^- help: consider using a semicolon here
  | |_____|
  |       expected `()`, found `usize`

There has been no movement in trying to probe a called function that returns () to see if it could be ! instead. I'm not sure if we will.

@majaha
Copy link
Contributor

majaha commented Oct 29, 2023

I've made an interesting minimal contrasting pair that showcases this diagnostic issue: Playground

If you build the code:

fn never() -> ! {
    loop {}
}

fn foo(a: bool) {
    match a {
        true => 1,
        false => never(),
    }
}

you get the error

error[E0308]: mismatched types
 --> src/lib.rs:7:17
  |
7 |         true => 1,
  |                 ^ expected `()`, found integer
  |
help: consider using a semicolon here
  |
9 |     };
  |      +
help: try adding a return type
  |
5 | fn foo(a: bool) -> i32 {
  |                 ++++++

which is acceptable, and has useful help: tips that guide you in the right direction. However, if you wrap the never() in a { block }, like so:

fn bar(a: bool) {
    match a {
        true => 1,
        false => {
            never()
        }
    }
}

then you get the error:

error[E0308]: `match` arms have incompatible types
  --> src/lib.rs:16:13
   |
13 | /     match a {
14 | |         true => 1,
   | |                 - this is found to be of type `{integer}`
15 | |         false => {
16 | |             never()
   | |             ^^^^^^^ expected integer, found `()`
17 | |         }
18 | |     }
   | |_____- `match` arms have incompatible types

For more information about this error, try `rustc --explain E0308`.

This error message has several issues.

  1. The addition of the brackets has baffled those useful help: tips.
  2. It feels like the compiler is lying to you about the type of never(), pointing directly at it and saying it "found ()" despite it having type !. I realise that the compiler must have already coerced the type, but it feels kinda gaslight-y.
  3. The compiler claims that the match arms have incompatible types, even though this isn't true. Rather, the compiler is coercing types across the boundary of the match statement before coercing between the different arms of the match statement, as you would intuitively expect would happen first.
  4. The line fn bar(a: bool) { doesn't appear anywhere in the error message, despite being the source of the inferred () type, and it's being a candidate for the problem line.

estebank added a commit to estebank/rust that referenced this issue Nov 2, 2023
On functions with a default return type that influences the coerced type
of `match` arms, check if the failing arm is actually of type `!`. If
so, suggest changing the return type so the coercion against the prior
arms is successful.

```
error[E0308]: `match` arms have incompatible types
  --> $DIR/match-tail-expr-never-type-error.rs:9:13
   |
LL |   fn bar(a: bool) {
   |                  - help: try adding a return type: `-> i32`
LL | /     match a {
LL | |         true => 1,
   | |                 - this is found to be of type `{integer}`
LL | |         false => {
LL | |             never()
   | |             ^^^^^^^
   | |             |
   | |             expected integer, found `()`
   | |             this expression is of type `!`, but it get's coerced to `()` due to its surrounding expression
LL | |         }
LL | |     }
   | |_____- `match` arms have incompatible types
```

Fix rust-lang#24157.
estebank added a commit to estebank/rust that referenced this issue Nov 6, 2023
On functions with a default return type that influences the coerced type
of `match` arms, check if the failing arm is actually of type `!`. If
so, suggest changing the return type so the coercion against the prior
arms is successful.

```
error[E0308]: `match` arms have incompatible types
  --> $DIR/match-tail-expr-never-type-error.rs:9:13
   |
LL |   fn bar(a: bool) {
   |                  - help: try adding a return type: `-> i32`
LL | /     match a {
LL | |         true => 1,
   | |                 - this is found to be of type `{integer}`
LL | |         false => {
LL | |             never()
   | |             ^^^^^^^
   | |             |
   | |             expected integer, found `()`
   | |             this expression is of type `!`, but it get's coerced to `()` due to its surrounding expression
LL | |         }
LL | |     }
   | |_____- `match` arms have incompatible types
```

Fix rust-lang#24157.
estebank added a commit to estebank/rust that referenced this issue Nov 18, 2023
On functions with a default return type that influences the coerced type
of `match` arms, check if the failing arm is actually of type `!`. If
so, suggest changing the return type so the coercion against the prior
arms is successful.

```
error[E0308]: `match` arms have incompatible types
  --> $DIR/match-tail-expr-never-type-error.rs:9:13
   |
LL |   fn bar(a: bool) {
   |                  - help: try adding a return type: `-> i32`
LL | /     match a {
LL | |         true => 1,
   | |                 - this is found to be of type `{integer}`
LL | |         false => {
LL | |             never()
   | |             ^^^^^^^
   | |             |
   | |             expected integer, found `()`
   | |             this expression is of type `!`, but it get's coerced to `()` due to its surrounding expression
LL | |         }
LL | |     }
   | |_____- `match` arms have incompatible types
```

Fix rust-lang#24157.
estebank added a commit to estebank/rust that referenced this issue Nov 22, 2023
On functions with a default return type that influences the coerced type
of `match` arms, check if the failing arm is actually of type `!`. If
so, suggest changing the return type so the coercion against the prior
arms is successful.

```
error[E0308]: `match` arms have incompatible types
  --> $DIR/match-tail-expr-never-type-error.rs:9:13
   |
LL |   fn bar(a: bool) {
   |                  - help: try adding a return type: `-> i32`
LL | /     match a {
LL | |         true => 1,
   | |                 - this is found to be of type `{integer}`
LL | |         false => {
LL | |             never()
   | |             ^^^^^^^
   | |             |
   | |             expected integer, found `()`
   | |             this expression is of type `!`, but it get's coerced to `()` due to its surrounding expression
LL | |         }
LL | |     }
   | |_____- `match` arms have incompatible types
```

Fix rust-lang#24157.
bors added a commit to rust-lang-ci/rust that referenced this issue Nov 27, 2023
Account for `!` arm in tail `match` expr

On functions with a default return type that influences the coerced type of `match` arms, check if the failing arm is actually of type `!`. If so, suggest changing the return type so the coercion against the prior arms is successful.

```
error[E0308]: `match` arms have incompatible types
  --> $DIR/match-tail-expr-never-type-error.rs:9:13
   |
LL |   fn bar(a: bool) {
   |                  - help: try adding a return type: `-> i32`
LL | /     match a {
LL | |         true => 1,
   | |                 - this is found to be of type `{integer}`
LL | |         false => {
LL | |             never()
   | |             ^^^^^^^
   | |             |
   | |             expected integer, found `()`
   | |             this expression is of type `!`, but it get's coerced to `()` due to its surrounding expression
LL | |         }
LL | |     }
   | |_____- `match` arms have incompatible types
```

Fix rust-lang#24157.
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Nov 27, 2023
Account for `!` arm in tail `match` expr

On functions with a default return type that influences the coerced type of `match` arms, check if the failing arm is actually of type `!`. If so, suggest changing the return type so the coercion against the prior arms is successful.

```
error[E0308]: `match` arms have incompatible types
  --> $DIR/match-tail-expr-never-type-error.rs:9:13
   |
LL |   fn bar(a: bool) {
   |                  - help: try adding a return type: `-> i32`
LL | /     match a {
LL | |         true => 1,
   | |                 - this is found to be of type `{integer}`
LL | |         false => {
LL | |             never()
   | |             ^^^^^^^
   | |             |
   | |             expected integer, found `()`
   | |             this expression is of type `!`, but it get's coerced to `()` due to its surrounding expression
LL | |         }
LL | |     }
   | |_____- `match` arms have incompatible types
```

Fix rust-lang#24157.
GuillaumeGomez added a commit to GuillaumeGomez/rust that referenced this issue Nov 27, 2023
Account for `!` arm in tail `match` expr

On functions with a default return type that influences the coerced type of `match` arms, check if the failing arm is actually of type `!`. If so, suggest changing the return type so the coercion against the prior arms is successful.

```
error[E0308]: `match` arms have incompatible types
  --> $DIR/match-tail-expr-never-type-error.rs:9:13
   |
LL |   fn bar(a: bool) {
   |                  - help: try adding a return type: `-> i32`
LL | /     match a {
LL | |         true => 1,
   | |                 - this is found to be of type `{integer}`
LL | |         false => {
LL | |             never()
   | |             ^^^^^^^
   | |             |
   | |             expected integer, found `()`
   | |             this expression is of type `!`, but it get's coerced to `()` due to its surrounding expression
LL | |         }
LL | |     }
   | |_____- `match` arms have incompatible types
```

Fix rust-lang#24157.
compiler-errors added a commit to compiler-errors/rust that referenced this issue Nov 28, 2023
Account for `!` arm in tail `match` expr

On functions with a default return type that influences the coerced type of `match` arms, check if the failing arm is actually of type `!`. If so, suggest changing the return type so the coercion against the prior arms is successful.

```
error[E0308]: `match` arms have incompatible types
  --> $DIR/match-tail-expr-never-type-error.rs:9:13
   |
LL |   fn bar(a: bool) {
   |                  - help: try adding a return type: `-> i32`
LL | /     match a {
LL | |         true => 1,
   | |                 - this is found to be of type `{integer}`
LL | |         false => {
LL | |             never()
   | |             ^^^^^^^
   | |             |
   | |             expected integer, found `()`
   | |             this expression is of type `!`, but it get's coerced to `()` due to its surrounding expression
LL | |         }
LL | |     }
   | |_____- `match` arms have incompatible types
```

Fix rust-lang#24157.
@bors bors closed this as completed in 8221f9c Nov 28, 2023
rust-timer added a commit to rust-lang-ci/rust that referenced this issue Nov 28, 2023
Rollup merge of rust-lang#117526 - estebank:issue-24157, r=b-naber

Account for `!` arm in tail `match` expr

On functions with a default return type that influences the coerced type of `match` arms, check if the failing arm is actually of type `!`. If so, suggest changing the return type so the coercion against the prior arms is successful.

```
error[E0308]: `match` arms have incompatible types
  --> $DIR/match-tail-expr-never-type-error.rs:9:13
   |
LL |   fn bar(a: bool) {
   |                  - help: try adding a return type: `-> i32`
LL | /     match a {
LL | |         true => 1,
   | |                 - this is found to be of type `{integer}`
LL | |         false => {
LL | |             never()
   | |             ^^^^^^^
   | |             |
   | |             expected integer, found `()`
   | |             this expression is of type `!`, but it get's coerced to `()` due to its surrounding expression
LL | |         }
LL | |     }
   | |_____- `match` arms have incompatible types
```

Fix rust-lang#24157.
kjetilkjeka pushed a commit to kjetilkjeka/rust that referenced this issue Nov 29, 2023
On functions with a default return type that influences the coerced type
of `match` arms, check if the failing arm is actually of type `!`. If
so, suggest changing the return type so the coercion against the prior
arms is successful.

```
error[E0308]: `match` arms have incompatible types
  --> $DIR/match-tail-expr-never-type-error.rs:9:13
   |
LL |   fn bar(a: bool) {
   |                  - help: try adding a return type: `-> i32`
LL | /     match a {
LL | |         true => 1,
   | |                 - this is found to be of type `{integer}`
LL | |         false => {
LL | |             never()
   | |             ^^^^^^^
   | |             |
   | |             expected integer, found `()`
   | |             this expression is of type `!`, but it get's coerced to `()` due to its surrounding expression
LL | |         }
LL | |     }
   | |_____- `match` arms have incompatible types
```

Fix rust-lang#24157.
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-enhancement Category: An issue proposing an enhancement or a PR with one. D-papercut Diagnostics: An error or lint that needs small tweaks. P-low Low priority T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.