-
Notifications
You must be signed in to change notification settings - Fork 13.4k
Subtle breaking change with match patterns on uninhabited types #38889
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
@seanmonstar I am opening a thread to discuss some of these changes, but I do want to point out that you could probably fix your original pattern by making the uninhabitedness a private detail of the type. In particular, changing to something like this should work: enum VoidEnum { } // NOT public
pub struct Void(VoidEnum); If you set it up this way, it is not publicly visible that I agree this is a regression of some kind, but I think that it's not the usual kind of regression. Whenever code relies on limitations of the existing type-checker to make guarantees, there is the danger that if the type-checker becomes more intelligent, it will endanger that code. I'm not sure the best way to solve that challenge, other than being careful. (In retrospect, I think it's safe to say that at minimum I think we should have investigated a way to phase in some warnings or something that might have alerted you to this, though I'm not sure just how that would work, or if it would have been possible.) |
@nikomatsakis thanks for starting the discussion, and also for the alternative suggestion. I'll give it a try and see how it works. I didn't mean to say that this is "a breaking change how dare you" sort of thing, which I think you understood, but instead just wanted to point out (as you summed up) that this is a behavior change, that would cause already existing code to behave differently, and wanted to make sure the repercussions were considered. So thanks! |
In any case, @seanmonstar, we are going to temporarily back out this change while we evaluate our long-term plan. But I would advise you to try the privacy thing anyhow, as that is likely to be the model we take in any case. The uncertainty is really around corner cases in unsafe code, not simple cases like this one. I will close the issue for now I think. Feel free to re-open. |
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 theError
enum could grow more variants. People should instead use a_
pattern. This is the best one can do to imitatestd::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 instd::error::Error
and other such impls.With rustc 1.14, this is correct:
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 amatch 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.
The text was updated successfully, but these errors were encountered: