> Consider code like:
>
> package test;
> public class Test {
> private int test(Root r) {
> return switch (r) {
> case Root(R2(R1 _), R2(R1 _)) -> 0;
> case Root(R2(R1 _), R2(R2 _)) -> 0;
> case Root(R2(R2 _), R2(R1 _)) -> 0;
> };
> }
> sealed interface Base {}
> record R1() implements Base {}
> record R2(Base b1) implements Base {}
> record Root(R2 b2, R2 b3) {}
> }
> ```
>
> This is missing a case for `Root(R2(R2 _), R2(R2 _))`. javac will produce an
> error correctly, but the error is not very helpful:
>
> $ javac test/Test.java
> .../test/Test.java:4: error: the switch expression does not cover all
> possible input values
> return switch (r) {
> ^
> 1 error
>
>
> The goal of this PR is to improve the error, at least in some cases to
> something along these lines:
>
> $ javac test/Test.java
> .../test/Test.java:4: error: the switch expression does not cover all
> possible input values
> return switch (r) {
> ^
> missing patterns:
> Root(R2(R2 _), R2(R2 _))
> 1 error
>
>
> The (very simplified) way it works in a recursive (or induction) way:
> - start with defining the missing pattern as the binding pattern for the
> selector type. This would certainly exhaust the switch.
> - for a current missing pattern, try to enhance it:
> - if the current type is a sealed type, try to expand to its (direct)
> permitted subtypes. Remove those that are not needed.
> - if the current (binding pattern) type is a record type, expand it to a
> record type, generate all possible combinations of its component types based
> on sealed hierarchies. Remove those that are not needed.
>
> This approach relies heavily on our ability to compute exhaustiveness, which
> is evaluated repeatedly in the process.
>
> There are some cases where the algorithm does not produce ideal results (see
> the tests), but overall seems much better than what we have now.
>
> Another significant limitation is the speed of the process. Evaluating
> exhaustiveness is not a fast process, and this algorithm evaluates
> exhaustiveness repeatedly, potentially for many combinations of patterns
> (esp. for record patterns). So part of the proposal here is to have a time
> deadline for the computation. The default is 5s, and can be changed by
> `-XDexhaustivityTimeout=<timeout-in-ms>`.
>
> There's also an open possibility for select tools to delay the more detailed
> computation to some later time, although that would need to be tried and
> evaluated.
Jan Lahoda has updated the pull request incrementally with one additional
commit since the last revision:
Attempting to use the number of 'base checks' as the limit, instead of
wall-clock time.
-------------
Changes:
- all: https://git.openjdk.org/jdk/pull/27256/files
- new: https://git.openjdk.org/jdk/pull/27256/files/e41e7268..8f1ea6b9
Webrevs:
- full: https://webrevs.openjdk.org/?repo=jdk&pr=27256&range=12
- incr: https://webrevs.openjdk.org/?repo=jdk&pr=27256&range=11-12
Stats: 23 lines in 3 files changed: 0 ins; 2 del; 21 mod
Patch: https://git.openjdk.org/jdk/pull/27256.diff
Fetch: git fetch https://git.openjdk.org/jdk.git pull/27256/head:pull/27256
PR: https://git.openjdk.org/jdk/pull/27256