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