dart-lang / dart-lang/language

Non exhaustive switch with generics (Recoverable Errors)

Open
#2,963 17 comments 1 reaction 0 assignees View on GitHub
exhaustiveness request
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.