Compiler doesn't respect #[non_exhaustive] for bool-like enum

Rust:

#[repr(u8)]
#[derive(Clone, Copy)]
#[non_exhaustive]
pub enum Bool {
    False = 0, True = 1
}

pub fn create(x: u8) -> Bool {
    // Can this cause UB?
    // Conceptually I thought #[non_exhaustive] meant all bit patterns are valid.
    unsafe {
        ::std::mem::transmute(x)
    }
}

Assembly:

example::create:
        and     dil, 1
        mov     eax, edi
        ret

Code on rust.godbolt.org

I realize the code is not very useful, but I do find it somewhat surprising that create(3) as u8 != 3. Of course this only happens with enums that have two variants, one represented with 0 and the other with 1.

It has nothing to do with that. To quote the RFC:

It is purely to block exhaustive matches, hence the name.

As for whether that is UB: almost certainly. You should never, ever rely on optimisation to avoid UB. That’s just begging for something to explode.

So if I understand correctly, #[non_exhaustive] means users of the enum should not exhaustively match on it, not because other values are possible but to protect themselves from variants being added in a later version?

That is a very important distinction indeed!

It doesn’t. And you can tell that, since the create that defined the enum is still allowed to have arms only for the defined variants in a match – thereby not defining what will happen for other bit patterns.

That code is definitely unsound.