Hi all,
This post is inspired by the following ICE bug: https://github.com/rust-lang/rust/issues/36479. Currently, it is semantically possible to construct a value of type ! (or your favorite enum Void {}) unsafely, with
unsafe { mem::transmute::<(), !>(()) }
Of course, materialization of an uninhabited type usually emits a halt-and-catch-fire; in principle, however, such a transmute should be impossible, since () is an inhabited ZST, while ! is uninhabited (but also a ZST, since sizeof::<!>() == 0). I assume materializing a ! should be UB anyways, but Iāve yet to find anywhere that says so.
The RFC for the ! type briefly comments that, in analogy with sizeof::<()>() == 0 == log(1), weād expect sizeof::<!>() == -Infty == log(0). sizeof returns usize though, so we canāt have it actually do this, but the above semantic bug (and accompanying ICE) really makes me feel like we should make a stronger distinction between ZSTs and ānever-sized-typesā (NSTs, if you like).
The only practical solution I can think of is to make transmute allergic to NSTs, though I think it should be legal to transmute between NSTs, which is dead code that the linker would optimize out anyways.
Weāre kind of stuck with the current sizeof situation though, since we can neither change the signature of sizeof or define something ridiculous like sizeof::<!>() == usize::MAX, since that would be a breaking change, and while I have a bit of trouble figuring it what situations itād actually matter in, it might come across as strange that sizeof::<Option<!>>() == 0.