Skip to content

Unreliable warnings about unreachable code downstream of uninhabited expression #107179

Open
@graydon

Description

@graydon

Code

use core::convert::Infallible;
use core::hint::unreachable_unchecked;

fn make_infallible() -> Infallible { 
    // Infallible implements From<!>
    loop { }
}

extern {
    fn side_effects();
}

pub fn has_unit_type() {
    let _a : Infallible = make_infallible();

    // This gets no unreachable-code warning
    println!("I cannot execute");

    // This gets no unreachable-code warning
    unsafe { side_effects() }

    // This gets an unreachable-code warning
    if false { }
}

pub fn has_never_type_no_warning() -> ! {
    let _ : Infallible = make_infallible();

    // This gets no unreachable-code warning (probably correctly?)
    unsafe { unreachable_unchecked() }
}

pub fn has_never_type_has_warning() -> ! {
    let _ : Infallible = make_infallible();
    // This has the same never-type, but does get a warning
    loop {}
}

Current output

warning: unreachable expression
  --> src/lib.rs:23:5
   |
14 |     let _a : Infallible = make_infallible();
   |                           ----------------- any code following this expression is unreachable
...
23 |     if false { }
   |     ^^^^^^^^^^^^ unreachable expression
   |
note: this expression has type `Infallible`, which is uninhabited
  --> src/lib.rs:14:27
   |
14 |     let _a : Infallible = make_infallible();
   |                           ^^^^^^^^^^^^^^^^^
   = note: `#[warn(unreachable_code)]` on by default

warning: unreachable expression
  --> src/lib.rs:36:5
   |
34 |     let _ : Infallible = make_infallible();
   |                          ----------------- any code following this expression is unreachable
35 |     // This has the same never-type, but does get a warning
36 |     loop {}
   |     ^^^^^^^ unreachable expression
   |
note: this expression has type `Infallible`, which is uninhabited
  --> src/lib.rs:34:26
   |
34 |     let _ : Infallible = make_infallible();
   |                          ^^^^^^^^^^^^^^^^^

Rationale and extra context

It should warn on the first (and every) unreachable expression, not just the seemingly random set of expressions it fires on here. Note that if you change any of the make_infallible() calls to panic!() it will warn at the correct spots. So I think this is specifically related to the treatment of empty types.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-diagnosticsArea: Messages for errors, warnings, and lintsT-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