There's a huge semantic difference: a type with zero allowed values can never be constructed.
This means that a function that returns an uninhabited type is statically known to not return -- since there's no way it could construct an uninhabited value for a return expression. It also means you can coerce a value of uninhabited type into any other type, because any code which recieves a value of an uninhabited type must be unreachable.
For instance, in Rust you can write the following:
Because panic! aborts the program and doesn't return, its return type is uninhabited. Thus, a panic! can be used in a context where a string is expected.
There's a huge semantic difference: a type with zero allowed values can never be constructed.
This means that a function that returns an uninhabited type is statically known to not return -- since there's no way it could construct an uninhabited value for a return expression. It also means you can coerce a value of uninhabited type into any other type, because any code which recieves a value of an uninhabited type must be unreachable.
For instance, in Rust you can write the following:
Because panic! aborts the program and doesn't return, its return type is uninhabited. Thus, a panic! can be used in a context where a string is expected.