|
|
|
|
|
by munificent
1036 days ago
|
|
I don't know about C#, but, yes Dart has quite sophisticated exhaustiveness checking over sealed class hiearchies, including hierarchies that are DAGs and not just trees. It also handles record/tuple types and generics, nested arbitrarily deeply. And patterns that call arbitrary getters on objects. For example, if you have this class hierarchy: sealed class A {}
sealed class B1 implements A {}
sealed class B2 implements A {}
class C1 implements B1 {}
class C2 implements B1, B2 {}
class C3 implements B2 {}
// A
// / \
// B1 B2
// / \ / \
// C1 C2 C3
Then it understands that this switch statement is exhaustive: void test(A a1, A a2) {
switch ((a1, a2)) {
case (A(), C1()): print(1);
case (C2(), C2()): print(2);
case (C3(), B2()): print(3);
case (B1(), B2()): print(4);
}
}
Because they cover the Cartesian product of all possible combinations of subtypes like: a1
A
/ \
B1 B2
/ \ / \
C1 C2 C3
a2 +----+----+----+
C1| 1 |
B1< +----+----+----+
A< C2| | 2 | |
B2< + +----+ 3 +
C3| 4 | |
+----+----+----+
This can extend to arbitrary dimensions based on how many record fields there are.Figuring that all out was quite the challenge! The full design is here: https://github.com/dart-lang/language/blob/main/accepted/3.0... |
|