upvote
Note that Rust's ! isn't stabilized, however you can (in stable Rust, today) make your own empty/ uninhabited types, yours just isn't "the" canonical empty type for the language, and so the type arithmetic won't necessarily see that it's the same thing in some cases if that matters.

Rust's core::convert::Infallible is such a type, representing in that case the error type for conversions which have no errors. For example, we can try to convert most numeric types into a 16-bit unsigned type, and obviously most of them can fail because your value was too big or negative or whatever. u16 however obviously never fails, the conversion is a no-op, nevertheless it would be stupid if we can't write generic code to convert it - so of course we can, and if we wrote generic error handling code, that code is dead for the u16 case, we can't fail, the use of empty types here justifies the compiler saying OK, that code is dead, don't emit it. Likewise converting u8 to u16 can't fail - although it's slightly more than a no-op in some sense - and so again the error handling is dead code.

reply
I see. I can not give more insightful answer here then. From personal experience, I've noticed with 0.16 with the std.Io async stuff that you cannot do:

   io.concurrent(foo, .{});
where foo's return type is `error{foobar}!noreturn`, because the compiler crashes when it tries to use that type as a std.Io.Future(T)'s struct field. Might be related or not.
reply