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

Implement JEP 530: Primitive Types in Patterns, instanceof, and switch (Fourth Preview)

XMLWordPrintable

    • Icon: CSR CSR
    • Resolution: Unresolved
    • Icon: P4 P4
    • 26
    • tools
    • None
    • source
    • low
    • SE

      Summary

      The proposed changes enhance the definition of unconditional exactness and apply tighter dominance checks in switch. These changes enable the compiler to identify a wider range of mistakes by developers, although a small number of switch constructs that were previously legal (prior to Primitive types in patterns, instanceof, and switch) will now be rejected when --enable-preview is passed in the compiler.

      Problem

      Currently, the dominance and unconditionality properties are defined only among types and in reality they capture only unconditionally exact conversions (conversions that will never lose information at runtime). However, when the constant is known and there are cases that a conversion can be potentially lossy, the compiler could verify if for that constant the conversion can be always exact (this is similar to the assignment context allowing a narrowing primitive conversion in the case of byte b = 42). Since JEP 507 is unaware of constant values in unconditional exactness, cases like in the example below were previously allowed:

      // OK with JEP 507 since int to float is not unconditionally exact (by only examining the types)
      // but in reality 16_777_216 is always converted to float without 
      // loss of information and case float dominates it.
      int j = ...; 
      switch(j) {
          case float f    -> {} 
          case 16_777_216 -> {} 
          default         -> {}
      }

      Furthermore, the dominance check is not taking under consideration the case when a case label is preceded by an unconditional pattern. As a result, cases like the following (where there is no clear dominance relation among two patterns) were previously allowed:

      int j = ...; 
      switch(j) {
          case int _      -> {} 
          case float _    -> {}  // OK with JEP 507 (both i2f and f2i are both NP conversions)
      }
      
      int j = ...; 
      switch (j) {
          case Integer _ -> {} 
          case byte _    -> {}  // OK with JEP 507 (there is no byte to Integer conversion)
      };
      
      interface A {} 
      interface B {} 
      A a = ...; 
      switch (a) {
          case A _       -> {} 
          case B _       -> {}  // OK with JEP 507 (even if A and B are unrelated)
      }

      Note that the last case is valid code today (prior to this JEP). A user that wrote case A followed by case B is not aware that case B is never matched; case A is unconditional for the type of the selector which is A. Such a switch is rejected with --enable-preview as part of this JEP.

      Solution

      Firstly, we intend to expand the set of the existing unconditionally exact conversions (type-based unconditionally exact conversions) with value-based unconditionally exact conversions. Making unconditional exactness aware of constant expressions and passing such information to dominance, allows to implement tighter checks. Secondly, we treat switches that contain unconditional patterns that are followed by other patterns, as erroneous.

      Specification

      The JLS draft showing the exact wording for the above solutions is attached as p4-instanceof.pdf (https://cr.openjdk.org/~abimpoudis/instanceof/jepXXX-20250926/specs/primitive-types-in-patterns-instanceof-switch-jls.html)

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

              Created:
              Updated: