Closed RalfJung closed 6 years ago
How is this dangerous?
with x: &Empty
, match *x {}
could well be (no final decision has been bade yet) insta-UB if ever executed.
Actually, just passing a &Empty
to another function is not really different from passing aliasing &mut u32
-- the promise made by the type is violated. It is not unlikely for the unsafe code guidelines process to decide that doing either of these is UB.
&Empty
is not okay, but you're working with *mut Empty
and *const Empty
in FFI.
&Empty
is not okay,
Glad we agree on that. :)
you're working with mut Empty and const Empty in FFI.
While these types are fine, I am worried that people will quickly move to variables or function arguments of type &Empty
in the wrappers they build around their FFI code.
This happened e.g. in https://github.com/briansmith/ring/, where BIGNUM
used to be an empty enum, and you can indeed find &BIGNUM
in the code.
I’ve opened https://github.com/rust-lang-nursery/nomicon/pull/44 to recommend zero-size structs with a private field, instead.
https://github.com/rust-lang/rust/pull/45225#issuecomment-346493804 is another case of Bad Things happening with empty enums used in types that are not "impossible".
The FFI section of the Nomicon currently suggests to use an empty type for "opaque pointer types". That seems pretty dangerous. This came up in the discussion at https://github.com/rust-lang/rfcs/pull/1861, and also in https://internals.rust-lang.org/t/recent-change-to-make-exhaustiveness-and-uninhabited-types-play-nicer-together/4602 many were not happy with using the empty type here.
Until we have proper opaque types, the safer suggestion seems to be do use a ZST with a private field, rather than an empty type. Then at least the type is not actively lying.