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

Lint to ensure all variants of an enum are used #9255

Open
Nemo157 opened this issue Jul 28, 2022 · 2 comments
Open

Lint to ensure all variants of an enum are used #9255

Nemo157 opened this issue Jul 28, 2022 · 2 comments
Labels
A-lint Area: New lints

Comments

@Nemo157
Copy link
Member

Nemo157 commented Jul 28, 2022

What it does

Check that all variants of an enum are used inside a function.

This is similar to standard exhaustiveness checking of a match, and the non-exhaustive-omitted-patterns lint for non-exhaustive enums; but generalized to usecases that are not using match.

Lint Name

No response

Category

restriction

Advantage

Ensures that when new variants are added to an enum (whether because it's an internal enum, public enum with a major version bump, or an external non-exhaustive enum) those variants are handled.

A major usecase I see for this is things that produce values of the enum and are expected to be able to produce every variant, such as parsers.

Drawbacks

How do you determine which enum to lint on?

Example

enum Intensity { Normal, Bold, Faint }
struct Unknown;
impl FromStr for Intensity {
    type Err = Unknown;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "normal" => Ok(Intensity::Normal),
            "bold" => Ok(Intensity::Bold),
            _ => Err(Unknown),
        }
    }
}

Could be written as:

enum Intensity { Normal, Bold, Faint }
struct Unknown;
impl FromStr for Intensity {
    type Err = Unknown;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "normal" => Ok(Intensity::Normal),
            "bold" => Ok(Intensity::Bold),
            "faint" => Ok(Intensity::Faint),
            _ => Err(Unknown),
        }
    }
}
@5225225
Copy link
Contributor

5225225 commented Jul 29, 2022

I wonder if you could have an attribute like #[all_constructed(Intensity)] that goes on some block, and then all variants of that enum must be constructed inside that scope, or a warning is fired.

That would solve the "how do you know what to lint on" issue nicely. But that wouldn't quite be a lint, because it needs an argument.

And, as I understand it, all lints are always emitted, but allowed ones are just ignored. Which leads to performance issues when you have lints that would be triggered a lot, and you only care about it in a few places. I believe lints against implicit drops run into that issue, and I'm not sure if that's been fixed yet.

@kpreid
Copy link
Contributor

kpreid commented Jan 18, 2024

The discussion above mentions producing all variants within some function, but some cases use cases might want to lint for producing all variants within the crate — for example, an error enum might have its different variants constructed by many different functions. In this case, there's no need to define the scope; it could just be a lint you enable or disable as usual — on the enum, or even a single variant of the enum (if a “deprecated” variant is no longer ever produced but needs to still exist for compatibility).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-lint Area: New lints
Projects
None yet
Development

No branches or pull requests

3 participants