-
Notifications
You must be signed in to change notification settings - Fork 13.9k
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)