dart-lang / dart-lang/language
Non exhaustive switch with generics (Recoverable Errors)
- Dominant language
- TeX
- Stars
- 2.9k
- Forks
- 239
- Avg merge
- 2d 18h
- Merged PRs (30d)
- 14
Description
I am trying to implement a custom error handling in dart. I want to be able to represent a correct return (Ok) or an error union (yes, I really hate undocumented exceptions 😁, I would use exceptions only for "panic" situations, unrecoverable errors). Since unions are still not present in Dart I am trying to accomplish this with sealed classes.
I took some error handling examples from different languages and rust error handling (https://doc.rust-lang.org/book/ch09-02-recoverable-errors-with-result.html) seems to work well in many cases.
This is my implementation, however the following does not exhaustiveness checks.
```dart
sealed class Result {}
class Ok extends Result {
Ok(this.value);
final T value;
}
class Err extends Result {
Err(this.error);
final E error;
}
sealed class DivideError {}
class DivideByZero extends DivideError {}
class DivideByNegative extends DivideError {}
Result divideNonNegative(int a, int b) {
if (b == 0) return Err(DivideByZero());
if (b < 0) return Err(DivideByNegative());
return Ok(a ~/ b);
}
void main() {
final result = divideNonNegative(10, 0);
//dart (non_exhaustive_switch)
switch (result) {
case Ok(:final value):
print(value);
case Err(:final error):
switch (error) {
case DivideByZero():
print('Divide by zero');
case DivideByNegative():
print('Divide by negative');
}
// case Ok():
// print('Ok');
// case Err():
// print('Error');
}
// or...
//dart (non_exhaustive_switch)
switch (result) {
case Ok(:final value):
print(value);
case Err():
print('Divide by zero');
case Err():
print('Divide by negative');
// case Ok():
// print('Ok');
// case Err():
// print('Error');
}
}
```
First, is there a more "darty" way to represent this? Should this give an error? Since I am using sealed classes I would think that this was Ok.
Contributor guide
Research direction
The issue provides a self-contained Dart reproduction using sealed classes, a generic Result type, and nested switches. Start by running that example and tracing the exhaustiveness rules for the generic sealed hierarchy; done means the language behavior and diagnostic for both switch forms are resolved.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- dart
- Domain
- compilers
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100