They would indeed become an obsolete pattern, but keeping the options open can still be useful: in the same vein that ()
does not make any zero-sized struct useless (even if we ignored new-type usage for traits) since they can convey richer information.
Take, for instance, the return type of ::std::iter::Iterator::next()
, and let's call it IteratorState<Item>
:
-
Currently,
IteratorState<Item>
isOption<Item>
:type IteratorState<Item> = enum Option<Item> { Some(Item), None, }
-
with generators, it could be seen as
::std::ops::GeneratorState
<Iterator::Item, ()>
,i.e.,
type IteratorState<Item> = enum GeneratorState<Item, ()> { Yielded(Item), Complete(()), }
And although the one-type-fits-them-all is elegant logical-patterns-wise, that
Complete(())
does not look nice (although quite better than the initialNone
!). With an (isomorphic) custom type, we could improve it: -
enum IteratorState<T> { Yielded(T), Exhausted, } use self::IteratorState::*; impl<T> IteratorState<T> { fn some(self) -> Option<T> { match self { Yielded(value) => Some(value), Exhausted => None, }} }
I thus think that custom never types may very well exist, either in the form
struct Never /* = */ (!);
or in the empty enum
form. Hence the need for such a trait.
As an aside, I find custom inhabited types useful for "type-level enums", since it prevents using them as values.
Those are useful for truly immutable settings that can then lead to constant propagation and dead code removal:
trait Bool { const TRUTH: bool; fn is_true () -> bool { Self::TRUTH } }
enum True {} impl Bool for True { const TRUTH: bool = true ; }
enum False {} impl Bool for False { const TRUTH: bool = false; }
/// they can be "converted back to (zero-sized) values" with `PhantomData`
use ::std::marker::PhantomData;
struct Config<Verbose : Bool> {
// ...
_phantom: PhantomData<Verbose>,
}
impl<Verbose : Bool> Config<Verbose> {
fn run (
// ...
)
{
if Verbose::is_true() { /* be verbose */ }
// do some stuff
if Verbose::is_true() { /* be verbose */ }
// do more stuff
if Verbose::is_true() { /* be verbose */ }
}
}