Description
If an enum contained an uninhabited type, it is now valid to ignore matching that variant (and in fact encouraged, since include that pattern or _
now receives a warning).
I'll take a reduced example from hyper: hyper::Error
Currently, hyper::Error
includes a __DontMatchMe
variant as part of its way of saying that the Error
enum could grow more variants. People should instead use a _
pattern. This is the best one can do to imitate std::io::ErrorKind
, but without the additional #[unstable]
attribute protecting it.
Since the __DontMatchMe
variant should never actually be created, I filled it with an uninhabited type, so allow the optimizer to remove arms using it in std::error::Error
and other such impls.
With rustc 1.14, this is correct:
enum Void {}
enum Error {
Io,
Utf8,
Parse,
__DontMatchMe(Void),
}
fn foo(x: Error) {
match x {
Error::Io => (),
Error::Utf8 => (),
Error::Parse => (),
_ => (),
}
}
With nightly after #38069 was landed, the above will warn that the user should remove the _
pattern. If they do so, then the contract that __DontMatchMe
was supposed to provide is broken. With the _
removed, it looks like every variant is handled, and so any upgrade in hyper that adds a new variant will break this code. And that code will look innocent, where as before at least someone you need to explitictly do a match e { Error::__DontMatchMe => () }
and know that it could break.
I can remove the uninhabited type in hyper, but this behavior change does feel like one of the subtlely breaking kind.