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

Exhaustiveness checking tries to enforce cases which should not be possible #4152

Open
vnmiso opened this issue Nov 5, 2024 · 1 comment
Labels
patterns Issues related to pattern matching. request Requests to resolve a particular developer problem type-inference Type inference, issues or improvements

Comments

@vnmiso
Copy link

vnmiso commented Nov 5, 2024

Consider the following example:

enum MyEnum {
  a, b, c, d;
}

void doSomething(MyEnum value) {
  if (value == MyEnum.b) {
    fooB();
    return;
  }

  final text = switch (value) {
    MyEnum.a => 'a',
    MyEnum.c => 'c',
    MyEnum.d => 'd',
  };
  fooOthers(text);
}

This is a compile error (The type 'MyEnum' is not exhaustively matched by the switch cases since it doesn't match 'MyEnum.b'), even though after the if statement value cannot be MyEnum.b. Is there a deeper underlying reason that exhaustiveness checking can't handle cases like this?

Sometimes code like this can be refactored to avoid this issue (putting everything into one switch statement/expression, for example), but the code could become a lot clunkier.

@mateusfccp
Copy link
Contributor

mateusfccp commented Nov 5, 2024

This is expected. Dart doesn't keep a track of the possible values/types a variable may assume to do static analysis with them.

It's not impossible, but it's not just an adjustment to what we have now, it's a much more complex request. We would have (1) to adjust the flow analysis to consider values (currently it only considers types, except for null, which can promote to a non-nullable type) and (2) to have a concept of "not this value"/"not this type", so when the flow analysis gets to your switch, the value is promoted to "valueMyEnum, value ≠ MyEnum.b".

For your specific case, I would use a simple switch, and I think it is even clearer.

enum MyEnum {
  a, b, c, d;
}

void doSomething(MyEnum value) {
  final String text;

  switch (value) {
    case MyEnum.a:
      text = 'a';
    case MyEnum.b:
      fooB();
      return;
    case MyEnum.c:
      text = 'c';
    case MyEnum.d:
      text = 'd';
  }

  fooOthers(text);
}

@lrhn lrhn added request Requests to resolve a particular developer problem patterns Issues related to pattern matching. type-inference Type inference, issues or improvements labels Nov 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
patterns Issues related to pattern matching. request Requests to resolve a particular developer problem type-inference Type inference, issues or improvements
Projects
None yet
Development

No branches or pull requests

3 participants