Skip to content
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

Deleting enum variant unexpectedly changes behavior in match statement #84078

Open
jmikkola opened this issue Apr 11, 2021 · 3 comments
Open
Labels
A-lint Area: Lints (warnings about flaws in source code) such as unused_mut. A-patterns Relating to patterns and pattern matching C-enhancement Category: An issue proposing an enhancement or a PR with one. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@jmikkola
Copy link

jmikkola commented Apr 11, 2021

This came up when I was deleting some variants of a rather large enum. The variants were never used (indeed, the compiler warned me that they were unused), so deleting them should be safe. Much to my surprise, this caused test failures.

Upon closer inspection, it turned out that although my code never created those enum values, it did match them in a match statement (which I had not cleaned up). This caused the reference to that variant in the pattern to turn into a variable, which matched everything.

Here's a simplified example where B represents the enum variant[s] deleted.

I tried this code:

playground

enum MyEnum {
    A,
    // B, // the assertion below works if B is uncommented
    C,
}

fn to_int(my_enum: MyEnum) -> i32 {
    use MyEnum::*;
    match my_enum {
        A => 1,
        B => 2,
        C => 3,
    }
}

fn main() {
    assert_eq!(3, to_int(MyEnum::C));
}

I expected to see this happen:

When removing the variant B of the enum, I expected the match statement to fail to compile because it still referenced B.

Instead, this happened:

It compiled with a warning that the C variant is unreachable because B matches any pattern.


This feels like Rust behaving correctly according to the indented behavior, but the intended behavior is confusing.

I'm not sure if there is anything useful that could be done about this (perhaps disallow capitalized variables in patterns? or replace the warning with an error?).

@jmikkola jmikkola added the C-bug Category: This is a bug. label Apr 11, 2021
@workingjubilee
Copy link
Contributor

workingjubilee commented Apr 11, 2021

The following version of this example does not compile:

enum MyEnum {
    A,
    // B,
    C,
}

fn to_int(my_enum: MyEnum) -> i32 {
    use MyEnum::{A, B, C};  //~ error[E0432]: unresolved import `MyEnum::B`
    match my_enum {
        A => 1,
        B => 2,
        C => 3,
    }
}

Probably something like "globbing enum variants, specifically" should be linted against.

@leonardo-m
Copy link

leonardo-m commented Apr 11, 2021

It compiled with a warning that the C variant is unreachable because B matches any pattern.

In Rust (and other languages) warnings should be taken seriously.

Perhaps the solution is to turn the "unreachable pattern" warning into an error?

@workingjubilee
Copy link
Contributor

workingjubilee commented Apr 13, 2021

Hm. What standard must be met to make a lint deny-by-default? I am hesitant to say "hard error", because it may be that some people #![allow(unreachable_patterns)] in otherwise sound code. Unused variables, for instance, are very rarely desired, and it would be reasonable to say you should never have them in "production" code, but people are only warned, not denied or errored, on them. And I think that disallowing unreachable patterns by default risks making it too hard to refactor match code.

@ChrisDenton ChrisDenton added the needs-triage-legacy Old issue that were never triaged. Remove this label once the issue has been sufficiently triaged. label Jul 16, 2023
@fmease fmease added A-lint Area: Lints (warnings about flaws in source code) such as unused_mut. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. A-patterns Relating to patterns and pattern matching C-enhancement Category: An issue proposing an enhancement or a PR with one. and removed needs-triage-legacy Old issue that were never triaged. Remove this label once the issue has been sufficiently triaged. C-bug Category: This is a bug. labels Jan 23, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-lint Area: Lints (warnings about flaws in source code) such as unused_mut. A-patterns Relating to patterns and pattern matching C-enhancement Category: An issue proposing an enhancement or a PR with one. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

5 participants