-
Notifications
You must be signed in to change notification settings - Fork 13.8k
Description
I tried this code:
enum Never {}
#[repr(u64, C)]
#[allow(dead_code)]
enum Thing<T> {
Never(T) = 0,
Inhabited = 1,
}
fn main() {
assert_eq!(size_of::<Thing<Never>>(), 8);
let data = 0u64;
// Discriminant is 0, so we should have Thing::Never
let thing_ref = unsafe { &*(&raw const data).cast::<Thing<Never>>() };
// This is fine
concrete(thing_ref);
// This has UB
generic::<Never>(thing_ref);
}
fn concrete(x: &Thing<Never>) {
match x {
&Thing::Inhabited => {
println!("Inhabited");
}
_ => {
println!("Never");
}
};
}
fn generic<T>(x: &Thing<T>) {
match x {
&Thing::Inhabited => {
println!("Inhabited");
}
_ => {
println!("Never");
}
};
}
I expected the concrete
and generic::<Never>
calls to behave identically. Instead, Miri detects UB only for the generic::<Never>
call:
error: Undefined Behavior: read discriminant of an uninhabited enum variant
--> src/main.rs:33:11
|
33 | match x {
| ^ 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 `generic::<Never>` at src/main.rs:33:11: 33:12
note: inside `main`
--> src/main.rs:18:5
|
18 | generic::<Never>(thing_ref);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
It seems that, in generic
, T
is treated as inhabited, even if the T
is later set to Never
(which makes the type uninhabited in concrete
). Whether the Thing::Never
variant is inhabited then affects whether the enum discriminant is checked in the MIR.
Note that, when I tried executing the program (in either debug mode or release mode), it printed Inhabited
, then printed Never
. That is, the difference between the two functions can actually be observed outside of Miri.
Probably related to #142394 and #146590, which involves uninhabited types affecting MIR generation.
See also #146430, where generics can affect MIR-building.
Meta
Reproducible on the playground with rust version 1.92.0-nightly (2025-09-19 0be8e16088894483a701)
and Miri version 0.1.0 (2025-09-19 0be8e16088)