Skip to content

#[non_exhaustive] affects whether code has UB or not, according to Miri #147722

@theemathas

Description

@theemathas

bar/src/lib.rs:

#[non_exhaustive]
#[repr(u8)]
pub enum Thing {
    One(u8) = 0,
}

src/main.rs:

use std::mem::MaybeUninit;

use bar::Thing;

fn main() {
    let buffer: [MaybeUninit<u8>; 2] = [MaybeUninit::uninit(), MaybeUninit::new(0u8)];
    let ptr: *const Thing = (&raw const buffer).cast();
    unsafe {
        match *ptr {
            Thing::One(ref _val) => {}
            _ => {}
        }
    }
}

Running the above code in Miri detects UB as follows:

error: Undefined Behavior: reading memory at alloc168[0x0..0x1], but memory is uninitialized at [0x0..0x1], and this operation requires initialized memory
 --> src/main.rs:9:15
  |
9 |         match *ptr {
  |               ^^^^ Undefined Behavior occurred here
  |
  = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
  = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
  = note: BACKTRACE:
  = note: inside `main` at src/main.rs:9:15: 9:19

Uninitialized memory occurred at alloc168[0x0..0x1], in this allocation:
alloc168 (stack variable, size: 2, align: 1) {
    __ 00                                           │ ░.
}

note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

error: aborting due to 1 previous error

However, if I delete the #[non_exhaustive] line, Miri does not detect any UB.

This seems incorrect. I believe that #[non_exhaustive] is supposed to only affect whether code compiles. It should not affect how code behaves.

It seems that, without #[non_exhaustive], rust does not even read the discriminant. But with #[non_exhaustive], rust does.

Related to:

Meta

rustc --version --verbose:

rustc 1.92.0-nightly (844264add 2025-10-14)
binary: rustc
commit-hash: 844264adda6f41ca6d0d61c4bcac0f263fc5072f
commit-date: 2025-10-14
host: aarch64-apple-darwin
release: 1.92.0-nightly
LLVM version: 21.1.3

cargo miri --version:

miri 0.1.0 (844264adda 2025-10-14)

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-MIRArea: Mid-level IR (MIR) - https://blog.rust-lang.org/2016/04/19/MIR.htmlA-exhaustiveness-checkingRelating to exhaustiveness / usefulness checking of patternsA-miriArea: The miri toolA-patternsRelating to patterns and pattern matchingC-discussionCategory: Discussion or questions that doesn't represent real issues.I-lang-radarItems that are on lang's radar and will need eventual work or consideration.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.T-langRelevant to the language teamT-opsemRelevant to the opsem team

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions