Search code examples
javapattern-matchinginstanceofjava-record

Pattern Matching for instanceof throwing a confusing error: expression type Triple is a subtype of pattern type Triple


I have Java 19, and I am attempting to do some simple pattern-matching on a record that I created. However, Java is giving me a very confusing compilation error. Here is the simplest example I could make that causes the error.

public class ExpressionTypeIsASubsetOfPatternType
{

   public record Triple(int a, int b, int c) {}

   public static void main(String[] args)
   {

      System.out.println("Java Version = " + System.getProperty("java.version"));

      final Triple input = new Triple(1, 2, 3);

      if (input instanceof Triple t)
      {

         System.out.println("Made it here");

      }

   }

}

And here is the error that it gives me when I try to run/compile.

$ java ExpressionTypeIsASubsetOfPatternType.java
ExpressionTypeIsASubsetOfPatternType.java:15: error: expression type Triple is a subtype of pattern type Triple
      if (input instanceof Triple t)
                ^
1 error
error: compilation failed

Surprisingly enough, googling this error showed up nothing useful. I am so used to punching in an error and immediately seeing the problem. I imagine that it is because this feature is so new.

Anyways, the closest thing I could find is a bug that is related, but definitely not the same issue that I am dealing with.

Finally, here is the relevant info about my java version.

$ java --version
openjdk 19 2022-09-20
OpenJDK Runtime Environment (build 19+36-2238)
OpenJDK 64-Bit Server VM (build 19+36-2238, mixed mode, sharing)
$ javac --version
javac 19

Solution

  • Java is just being "nice": it recognizes that the test will always succeed (because input is known to be a Triple, which is already a subtype of the test type Triple), so it produces an error telling you that you're doing something useless (with a roundabout message).

    This is the same idea that makes

    void foo() {
      return;
      return; // error: unreachable statement
    }
    

    an error: there is a useless piece of code that might indicate (serious) programmer error, so the compiler forces you to rethink the code.

    The relevant section of the JLS is 15.20.2, which says

    InstanceofExpression:

    • ...
    • RelationalExpression instanceof Pattern

    ...

    The following rules apply when instanceof is the pattern match operator:

    • ...
    • If the type of the RelationalExpression is a subtype of the type of the Pattern, then a compile-time error occurs.

    I.e. this is indeed an intended part of the language and not just a compiler bug or something.