Skip to content

Subtle breaking change with match patterns on uninhabited types #38889

Closed
@seanmonstar

Description

@seanmonstar

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    I-needs-decisionIssue: In need of a decision.P-highHigh priorityT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.T-langRelevant to the language teamregression-from-stable-to-nightlyPerformance or correctness regression from stable to nightly.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions