Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8342397

Implement JEP 488: Primitive Types in Patterns, instanceof, and switch (Second Preview)

    • Icon: CSR CSR
    • Resolution: Approved
    • Icon: P4 P4
    • 24
    • tools
    • None
    • source
    • minimal
    • SE

      Summary

      Based on the experiences with the previous round of preview, we propose the following update:

      • make instanceof aware of the deduced type of the relational expression when the type on RHS is a primitive type.

      Problem

      Currently, and after the first preview, the following two examples work as expected (relevant discussion).

      Short s = 42;
      s instanceof int
      // correctly evaluates to true, because s has static type Short 
      // the conversion that is safeguarded is the following: Short -> short -> int
      
      Object o = s;
      o instanceof int
      // correctly evaluates to false, because o has static type Object 
      // the conversion that is safeguarded is the following: Object -> Integer -> int (s is of type Short so this fails)

      However, javac accepts the following two with different runtime behavior:

      List<Short> ls = List.of((short) 42);
      
      switch(ls.get(0)) {
         case int _ -> true;
         default -> false;
      }
      // correctly evaluates to true, 
      // since an automatically generated cast is inserted with the deduced type ((Short) ls.get(0)).
      
      ls.get(0) instanceof int
      // erroneously evaluates to false, since what is executed is ls.get(0): Object instanceof int.
      // instanceof should safeguard the Short -> short -> int conversion
      // instead, instanceof safeguards the Object -> Integer -> int conversion (and fails).

      There are two requirements here. instanceof should continue being the precondition of safe casting and safe casting is described in Section 5.5. The second is that switch and instanceof should expose the same behavior.

      While the automatically generated cast ensures safety in terms of heap pollution in the selector expression of switch by raising a CCE, instanceof never intended to raise a CCE in case of heap pollution for the evaluation of its relational expression.

      Solution

      There are two alternatives:

      1. Sharp Cast Insertion: Automatically insert a sharp cast with the deduced type to the relational expression similarly to switch.

        e.g., (Short) ls.get(0) instanceof int

        This approach would align the behavior of the new instanceof with switch.

        In that case, an automatically generated cast would ensure that heap pollution is signaled similarly with switch. However, instanceof will start raising a CCE in case of heap pollution (something instanceof has traditionally avoided).

      2. Pattern-based Translation: Instead of introducing a sharp cast, use a pattern that first checks for the deduced type and then performs the instanceof test with the original RHS of the instanceof.

        e.g., ls.get(0) instanceof Short s && s instanceof int

        That retains the unwritten philosophy of instanceof that never throws--even in the case of heap pollution--at the expense of a more complex translation.

      In the second preview we address this issue by following the second (2) option. This maintains the philosophy of instanceof not throwing exceptions, even in cases of heap pollution, while ensuring the correct behavior when testing primitive types.

      Specification

      The JLS draft showing the exact wording for the above solutions is attached as JLS-instanceof-1.pdf

            abimpoudis Angelos Bimpoudis
            abimpoudis Angelos Bimpoudis
            Jan Lahoda
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: