-
Notifications
You must be signed in to change notification settings - Fork 205
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
Switch expression is not exhaustive on integers #3083
Comments
Relatedly, this also does not work for the following case: bool bothTheSame(bool? a, bool? b) => switch ((a, b)) {
(bool? b1, bool? b2) when b1 == b2 => true,
(bool? b1, bool? b2) when b1 != b2 => false,
// The type '(bool?, bool?)' is not exhaustively matched by the switch cases since it doesn't match '(_, _)'.
}; If exhaustiveness cant be guaranteed for non sealed / enum types, maybe the error message should be clearer |
The first switch is not exhaustive because there is no specified way to exhaust integers. The second example doesn't work because a case with a It's not because bool bothTheSame(bool? a, bool? b) => switch ((a, b)) {
(true, true) => true,
(true, false) => false,
(true, null) => false,
(false, false) => true,
(false, true) => false,
(false, null) => false,
(null, null) => true,
(null, true) => false,
(null, false) => false,
}; (But that's just doing |
Or more succinctly (though not as succinct as bool bothTheSame(bool? a, bool? b) => switch ((a, b)) {
(true, true) => true,
(false, false) => true,
(null, null) => true,
(_, _) => false
}; |
We definitely could do exhaustiveness checking over integer ranges with relational patterns. It's something some other languages do and is something I'd like to do for Dart. We just didn't have time to get it in to 3.0. |
@munificent could that also be possible for double? |
No, you cannot exhaust doubles using So, here's a proposal: Number exhaustionAllow the type
I have no idea if the algorithm's use of spaces allows for such a dynamically defined "space set". It might have to be special-cased. Allow exhausting
Same caveats about exhaustiveness algorithm and how it implements spaces applies. The next question is whether this algorithm should be implemented by inference/reachability analysis. switch (someInt) {
case <0: sign = -1;
case ==0: sign = 0;
case >0: sign = 1;
default: throw "unreachable";
} now cannot reach the Doing range exhaustion in the reacahbility analysis does mean doing it twice, if it's also done in the exhaustiveness checking. It's not necessary if the switch is already must-exhaust (because it's an expression, or because it switches over a sealed type, which could look something like: switch (Scale) { // A sealed type with two subtypes
case Linear(magnitude: < 0): timyScale(...);
case Linear(magnitude: >= 0 && < 10): smallScale(...);
case Linear(magnitude: > 10): bigScale(...);
case Logarithmic(): logScale();
} Here the switch must be exhaustive, which means the inference doesn't need to check, it can leave that to the exhaustiveness algorithm. I'd go with no letting inference do The other side of that coin is whether All in all: Only a change to the exhaustiveness algorithm, not anything else. Only affects switches that must be exhaustive for other reasons (like switch expressions). |
Generally not a huge deal, but when this bites you, it bites you hard because it's very confusing to figure out why this is happening. If you don't know that the exhaustiveness checker doesn't handle integers like this, you'll be scratching your head. |
The analyzer claims that the following code snippet isn't exhaustive when it is. It emits the following message:
The type 'int' is not exhaustively matched by the switch cases since it doesn't match 'int()'
.The text was updated successfully, but these errors were encountered: