rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
97.85k stars 12.66k forks source link

`((), !)` and `((), ())` are considered incompatible types #112856

Open GrigorenkoPV opened 1 year ago

GrigorenkoPV commented 1 year ago

Playground

I tried this code:

fn main() {
    let a = if true {
        ((), todo!())
    } else {
        ((), ())
    };
}

I expected to see this happen:

Code compiles, runs, and panics. a has type ((), ()).

Instead, this happened:

   Compiling example v0.1.0 (/tmp/exmaple)
warning: unreachable expression
 --> src/main.rs:3:9
  |
3 |         ((), todo!())
  |         ^^^^^-------^
  |         |    |
  |         |    any code following this expression is unreachable
  |         unreachable expression
  |
  = note: `#[warn(unreachable_code)]` on by default

error[E0308]: `if` and `else` have incompatible types
 --> src/main.rs:5:9
  |
2 |       let a = if true {
  |  _____________-
3 | |         ((), todo!())
  | |         ------------- expected because of this
4 | |     } else {
5 | |         ((), ())
  | |         ^^^^^^^^ expected `((), !)`, found `((), ())`
6 | |     };
  | |_____- `if` and `else` have incompatible types
  |
  = note: expected tuple `((), !)`
             found tuple `((), ())`

For more information about this error, try `rustc --explain E0308`.
warning: `example` (bin "example") generated 1 warning
error: could not compile `example` (bin "example") due to previous error; 1 warning emitted

The following changes have no effect:

The following changes make the error go away.

*

let x = todo!();
((), x)

*

fn foo() -> () { todo!() }
((), foo())

*

let foo = || todo!();
((), foo())

*

((), (||todo!())())

Meta

rustc --version --verbose:

binary: rustc
commit-hash: 90c541806f23a127002de5b4038be731ba1458ca
commit-date: 2023-05-31
host: x86_64-unknown-linux-gnu
release: 1.70.0
LLVM version: 16.0.2

Same on nightly and beta.

Must be related to #35121.

Jules-Bertholet commented 1 year ago

Strangely,

pub fn main() {
    let a = if true {
        ((), panic!()) // not `loop {}`, `todo!()`, or anything else
    } else {
        ((), ())
    };
}

compiles on edition <= 2018. Also, this issue is not present on Rust 1.17 (Godbolt).

@rustbot label regression-from-stable-to-stable

apiraino commented 1 year ago

WG-prioritization assigning priority (Zulip discussion).

@rustbot label -I-prioritize +P-low +T-compiler

GrigorenkoPV commented 1 year ago

@rustbot label +F-never_type