RFR: 8366968: Exhaustive switch expression rejected by for not covering all possible values [v2]

Jan Lahoda jlahoda at openjdk.org
Thu Oct 2 09:10:08 UTC 2025


> Consider case like (from the bug):
> 
> class Demo {
> 
>     sealed interface Base permits Special, Value {}
> 
>     non-sealed interface Value extends Base {}
> 
>     sealed interface Special extends Base permits SpecialValue {}
> 
>     non-sealed interface SpecialValue extends Value, Special {}
> 
>     static int demo(final Base base) {
>         return switch (base) {
>             case final Value value -> 0;
>             // Uncommenting the following line will make javac accept this program
>             //case final Special value -> throw new AssertionError();
>         };
> 
>     }
> 
> }
> 
> 
> This fails to compile:
> 
> /tmp/Demo.java:12: error: the switch expression does not cover all possible input values
>         return switch (base) {
>                ^
> 1 error
> 
> 
> Note there is no instance of `Special` that would not be an instance of `Value` as well. I.e. covering `Value` will catch all input.
> 
> Also, note that if `case Value` is replaced with `case SpecialValue`, javac also compile the code:
> 
>             case final Value value -> 0;
> =>
>             case final SpecialValue value -> 0;
> 
> $ ~/tools/jdk/jdk-25/bin/javac /tmp/Demo.java
> $
> 
> 
> Which shows the problem: replacing a type with a super type should not cause the switch to stop to be exhaustive (i.e. the switch is exhaustive for `SpecialValue`, but replacing it with its super type `Value`, the switch is no longer exhaustive for javac).
> 
> javac contains a piece of code that searches through subtypes to handle diamond class hierarchies like the one above. But, when it searches for subtypes, it does a search through permitted subtypes of the type. And since `Value` is not sealed, this search will not find `SpecialValue`, and javac won't see the switch to be exhaustive.
> 
> The proposal herein is to broaden the search, and consider all transitive permitted subtypes of the selector type, and filter subtypes of the current type from this set (if the current type is abstract, if it is not abstract, we can't do the subtype search at all). This should, I think, include all relevant subtypes.

Jan Lahoda has updated the pull request incrementally with two additional commits since the last revision:

 - Removing trailing whitespace.
 - There are no relevant permitted subtypes of a non-abstract class, not even the class itself.

-------------

Changes:
  - all: https://git.openjdk.org/jdk/pull/27547/files
  - new: https://git.openjdk.org/jdk/pull/27547/files/4cf49874..64df6f43

Webrevs:
 - full: https://webrevs.openjdk.org/?repo=jdk&pr=27547&range=01
 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27547&range=00-01

  Stats: 27 lines in 2 files changed: 25 ins; 0 del; 2 mod
  Patch: https://git.openjdk.org/jdk/pull/27547.diff
  Fetch: git fetch https://git.openjdk.org/jdk.git pull/27547/head:pull/27547

PR: https://git.openjdk.org/jdk/pull/27547


More information about the compiler-dev mailing list