Skip to content

E0308 could've been more helpful in blocks #142551

Open
@ada4a

Description

@ada4a

Code

pub fn main() {
    let a = 'b: {
        if true {
            break 'b;
        }
        3
    };
}

Current output

error[E0308]: mismatched types
 --> src/lib.rs:6:9
  |
6 |         3
  |         ^ expected `()`, found integer

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

Desired output

error[E0308]: mismatched types
 --> src/lib.rs:6:15
  |
4 |             break 'b;
  |             -------- expected because of this `break`
5 |         }
6 |         3
  |         ^ expected `()`, found integer

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

Rationale and extra context

For many other kinds of expressions, the error includes the reason for the expected type, e.g. this beauty for ifs:

error[E0308]: `if` and `else` have incompatible types
 --> src/lib.rs:8:32
  |
8 |     let a = if true { 3 } else {};
  |                       -        ^^ expected integer, found `()`
  |                       |
  |                       expected because of this

and a similar thing for matches.

I initially wanted to suggest something similar to that for blocks, but the latter don't have such nice distinct parts that the error message can name and point to. For example, a type mismatch can occur between two early-returns, but also between an early-return and the final expression.

Because of that, I looked at the instances of this error for other kinds of expressions, and I found 2 good candidates that could be adapted to blocks:

Closures

If I adjust the example block just enough to turn it into one:

pub fn main() {
    let a = || {
        if true {
            return;
        }
        3
    };
}

I get this, reasonably helpful, error message:

error[E0308]: mismatched types
 --> src/lib.rs:6:9
  |
6 |         3
  |         ^ expected `()`, found integer
  |
note: return type inferred to be `()` here
 --> src/lib.rs:4:13
  |
4 |             return;
  |             ^^^^^^

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

But the "return type inferred to be" thing is not exactly applicable to blocks.

Then I found something that looks even better imo:

loops

Again, after adapting the block into a loop:

pub fn main() {
    let a = loop {
        if true {
            break;
        }
        break 3;
    };
}

I get the following error message:

error[E0308]: mismatched types
 --> src/lib.rs:6:15
  |
4 |             break;
  |             ----- expected because of this `break`
5 |         }
6 |         break 3;
  |               ^ expected `()`, found integer

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

So I adapted it to get the desired output for blocks

Other cases

Rust Version

rustc 1.86.0 (05f9846f8 2025-03-31) (built from a source tarball)
binary: rustc
commit-hash: 05f9846f893b09a1be1fc8560e33fc3c815cfecb
commit-date: 2025-03-31
host: x86_64-unknown-linux-gnu
release: 1.86.0
LLVM version: 19.1.7

Anything else?

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-control-flowArea: Control flowA-diagnosticsArea: Messages for errors, warnings, and lintsD-terseDiagnostics: An error or lint that doesn't give enough information about the problem at hand.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