Skip to content

match on uninhabited type does not trigger UB in Miri #142394

Open
@theemathas

Description

@theemathas

I tried this code:

#![allow(deref_nullptr)]

enum Never {}

fn main() {
    unsafe {
        match *std::ptr::null::<Result<Never, Never>>() {
            Ok(_) => {
                lol();
            }
            Err(_) => {
                wut();
            }
        }
    }
}

fn lol() {
    println!("lol");
}

fn wut() {
    println!("wut");
}

I expected to see this happen: Running this with Miri detects undefined behavior.

Instead, this happened: Running this with Miri outputs "lol", and program exits successfully.

It seems like rustc is discarding the second match arm entirely in the MIR?

MIR
// WARNING: This output format is intended for human consumers only
// and is subject to change without notice. Knock yourself out.
// HINT: See also -Z dump-mir for MIR at specific points during compilation.
fn main() -> () {
    let mut _0: ();
    let mut _1: *const std::result::Result<Never, Never>;
    let _2: ();

    bb0: {
        _1 = null::<Result<Never, Never>>() -> [return: bb1, unwind continue];
    }

    bb1: {
        _2 = lol() -> [return: bb2, unwind continue];
    }

    bb2: {
        return;
    }
}

// MIR for lol() and wut() omitted for brevity

Meta

Reproducible on the playground with 1.89.0-nightly (2025-06-10 1677d46cb128cc8f285d)

@rustbot labels +A-patterns

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-MIRArea: Mid-level IR (MIR) - https://blog.rust-lang.org/2016/04/19/MIR.htmlA-miriArea: The miri toolA-patternsRelating to patterns and pattern matchingC-bugCategory: This is a bug.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