The following set of switch cases is exhaustive, but javac reports it as not exhaustive:
```
$ cat /tmp/ExhaustivenessError.java
public class ExhaustivenessError {
private int test(Root r) {
return switch (r) {
case Root(R1 _, _, _) -> 0;
case Root(R2 _, R1 _, _) -> 0;
case Root(R2 _, R2 _, R1 _) -> 0;
case Root(R2 _, R2(R1 _, R1 _), R2(R1 _, R1 _)) -> 0;
case Root(R2 _, R2(R1 _, R1 _), R2(R1 _, R2 _)) -> 0;
case Root(R2 _, R2(R1 _, R1 _), R2(R2 _, R1 _)) -> 0;
case Root(R2 _, R2(R1 _, R1 _), R2(R2 _, R2 _)) -> 0;
case Root(R2 _, R2(R1 _, R2 _), R2(R1 _, R1 _)) -> 0;
case Root(R2 _, R2(R1 _, R2 _), R2(R1 _, R2 _)) -> 0;
case Root(R2 _, R2(R1 _, R2 _), R2(R2 _, R1 _)) -> 0;
case Root(R2 _, R2(R1 _, R2 _), R2(R2 _, R2 _)) -> 0;
case Root(R2 _, R2(R2 _, R1 _), R2(R1 _, R1 _)) -> 0;
case Root(R2 _, R2(R2 _, R1 _), R2(R1 _, R2 _)) -> 0;
case Root(R2 _, R2(R2 _, R1 _), R2(R2 _, R1 _)) -> 0;
case Root(R2 _, R2(R2 _, R1 _), R2(R2 _, R2 _)) -> 0;
case Root(R2 _, R2(R2 _, R2 _), R2(R1 _, R1 _)) -> 0;
case Root(R2 _, R2(R2 _, R2 _), R2(R1 _, R2 _)) -> 0;
case Root(R2 _, R2(R2 _, R2 _), R2(R2 _, R1 _)) -> 0;
case Root(R2 _, R2(R2 _, R2 _), R2 _) -> 0;
//the above is functionally equivalent to:
// case Root(R2 _, R2(R2 _, R2 _), R2(R2 _, R2 _)) -> 0;
};
}
sealed interface Base {}
record R1() implements Base {}
record R2(Base b1, Base b2) implements Base {}
record Root(Base b1, Base b2, Base b3) {}
}
$ javac /tmp/ExhaustivenessError.java
/tmp/ExhaustivenessError.java:3: error: the switch expression does not cover all possible input values
return switch (r) {
^
1 error
```
Note that if the commented-out case is used instead of the last not-commented-out case, javac will consider the switch to be exhaustive, despite these two cases being (on this spot) functionally equivalent.
```
$ cat /tmp/ExhaustivenessError.java
public class ExhaustivenessError {
private int test(Root r) {
return switch (r) {
case Root(R1 _, _, _) -> 0;
case Root(R2 _, R1 _, _) -> 0;
case Root(R2 _, R2 _, R1 _) -> 0;
case Root(R2 _, R2(R1 _, R1 _), R2(R1 _, R1 _)) -> 0;
case Root(R2 _, R2(R1 _, R1 _), R2(R1 _, R2 _)) -> 0;
case Root(R2 _, R2(R1 _, R1 _), R2(R2 _, R1 _)) -> 0;
case Root(R2 _, R2(R1 _, R1 _), R2(R2 _, R2 _)) -> 0;
case Root(R2 _, R2(R1 _, R2 _), R2(R1 _, R1 _)) -> 0;
case Root(R2 _, R2(R1 _, R2 _), R2(R1 _, R2 _)) -> 0;
case Root(R2 _, R2(R1 _, R2 _), R2(R2 _, R1 _)) -> 0;
case Root(R2 _, R2(R1 _, R2 _), R2(R2 _, R2 _)) -> 0;
case Root(R2 _, R2(R2 _, R1 _), R2(R1 _, R1 _)) -> 0;
case Root(R2 _, R2(R2 _, R1 _), R2(R1 _, R2 _)) -> 0;
case Root(R2 _, R2(R2 _, R1 _), R2(R2 _, R1 _)) -> 0;
case Root(R2 _, R2(R2 _, R1 _), R2(R2 _, R2 _)) -> 0;
case Root(R2 _, R2(R2 _, R2 _), R2(R1 _, R1 _)) -> 0;
case Root(R2 _, R2(R2 _, R2 _), R2(R1 _, R2 _)) -> 0;
case Root(R2 _, R2(R2 _, R2 _), R2(R2 _, R1 _)) -> 0;
case Root(R2 _, R2(R2 _, R2 _), R2 _) -> 0;
//the above is functionally equivalent to:
// case Root(R2 _, R2(R2 _, R2 _), R2(R2 _, R2 _)) -> 0;
};
}
sealed interface Base {}
record R1() implements Base {}
record R2(Base b1, Base b2) implements Base {}
record Root(Base b1, Base b2, Base b3) {}
}
$ javac /tmp/ExhaustivenessError.java
/tmp/ExhaustivenessError.java:3: error: the switch expression does not cover all possible input values
return switch (r) {
^
1 error
```
Note that if the commented-out case is used instead of the last not-commented-out case, javac will consider the switch to be exhaustive, despite these two cases being (on this spot) functionally equivalent.