-
-
Notifications
You must be signed in to change notification settings - Fork 14.2k
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.