javapattern-matchingrecordjava-19

Java 19 compiler issues when trying record patterns in switch expressions


I downloaded the release candidate of JDK19 from here https://jdk.java.net/19/ to play a little bit with the new record patterns that were implemented there, but I'm encountering some issues. In my tests, I wrote a version of Optional based on sealed interface plus records, in the following way:

package tests.patterns;

import java.util.Objects;

public class TestRecordPatter
{
    public static void main(final String[] args)
    {
        final Opt<String> opt1 = computeAnswer(23);
        final String answer1 = switch (opt1) {
            case Opt.Some<String>(String ans) -> ans;
            case Opt.None __ -> "no answer";
            default -> throw new IllegalStateException("This should not happen"); // A
        };
        System.out.println(answer1);

        final Opt<String> opt2 = computeAnswer(35);
        final Object answer2 = switch (opt2) { // B
            case Opt.Some<String>(var ans) -> ans; // C
            case Opt.None __ -> "no answer";
            default -> throw new IllegalStateException("This should not happen"); // A-2
        };
        System.out.println(answer2);

        final Opt<String> opt3 = computeAnswer(84);
        final String answer3 = switch (opt3) { // D
            case Opt.Some<String> s -> s.value();
            case Opt.None __ -> "no answer";
        };
        System.out.println(answer3);
    }

    private static Opt<String> computeAnswer(final int question)
    {
        if (question % 2 == 0) {
            return Opt.some(String.valueOf(question / 2));
        } else {
            return Opt.none();
        }
    }

    private sealed interface Opt<T> permits Opt.Some, Opt.None
    {

        static <T> Opt<T> of(final T value)
        {
            return value == null ? none() : some(value);
        }

        static <T> Opt<T> some(final T value)
        {
            return new Opt.Some<>(value);
        }

        @SuppressWarnings("unchecked")
        static <T> Opt<T> none()
        {
            return Opt.None.NONE;
        }

        record Some<T>(T value) implements Opt<T>
        {

            public Some
            {
                Objects.requireNonNull(value, "Value must not be null");
            }
        }

        @SuppressWarnings({ "rawtypes" })
        enum None implements Opt
        {
            NONE;
        }
    }
}

The first switch expression is using record deconstruction to get the value out of the Some variant using an explicit type for the ans variable but in this case the java compiler requires the default branch (line marked with A) otherwise it fails with the following error:

TestRecordPatter.java:[10,40] the switch expression does not cover all possible input values

In the second switch, the issue is that using var instead of explicit type for ans binds the returned type of the switch to Object and not to String. (line marked with B). Moreover, but this is not a java compiler issue, IntelliJ complains on line marked as C, highlighting the var ans part and saying something like "Type T is required but null is provided".

Finally, the third switch works fine, but that's the "old" (java 17 is old, right?) way of doing it.

Can someone help me? Am I doing something wrong?

EDIT: I just downloaded the Oracle JDK-19 GA version and it has the same issue.

EDIT 2: the second switch, the one with var has the same behaviour as the first one, so it needs a default case, as pointed by Holger


Solution

  • I just tried the code with the compiler of JDK 20 and the issue have been fixed