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

javac accepts invalid assignment of generic method return type to primitive int

XMLWordPrintable

    • generic
    • generic

      ADDITIONAL SYSTEM INFORMATION :
      wsl2-ubuntu 22.04
      Linux 5.15.167.4-microsoft-standard-WSL2 #1 SMP Tue Nov 5 00:21:55 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux

      javac 21.0.8



      A DESCRIPTION OF THE PROBLEM :
      javac incorrectly allows assignment of a generic method's return value — whose type is a reference type constrained by U extends IntegralConstraint<U> — to a primitive int, even though no valid unboxing or conversion path exists.

      The Eclipse Compiler for Java (ECJ) correctly rejects this code with a compilation error, while javac accepts it with only an unchecked cast warning.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Compling following code using javac in JDK21.
      ```
      javac Test.java
      ```

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      The compliation should fail and report such error message:
      ```
      1. ERROR in Test.java (at line 5)
              int result = checker.checkIntegral(42);
                           ^^^^^^^^^^^^^^^^^^^^^^^^^
      Type mismatch: cannot convert from IntegralConstraint<IntegralConstraint<U>> to int
      ```
      ACTUAL -
      The compliation is successful with 1 warnings.
      ```
      Test.java:32: warning: [unchecked] unchecked cast
              return (U) new MyInteger(value);
                         ^
        required: U
        found: MyInteger
        where U is a type-variable:
          U extends IntegralConstraint<U> declared in method <U>checkIntegral(int)
      1 warning
      ```

      ---------- BEGIN SOURCE ----------
      public class Test {

          public static void main(String[] args) {
              IntegralChecker<MyInteger> checker = new IntegralChecker<>();
              int result = checker.checkIntegral(42);
              System.out.println(result);
          }
      }

      interface IntegralConstraint<T> {

          boolean isIntegral();
      }

      class MyInteger implements IntegralConstraint<MyInteger> {

          private final int value;

          public MyInteger(int value) {
              this.value = value;
          }

          @Override
          public boolean isIntegral() {
              return true;
          }
      }


      class IntegralChecker<T extends IntegralConstraint<T>> {
          public <U extends IntegralConstraint<U>> U checkIntegral(int value) {
              return (U) new MyInteger(value);
          }
      }
      ---------- END SOURCE ----------

        1. Test.java
          0.7 kB
          Anjana Sajeev

            vromero Vicente Arturo Romero Zaldivar
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated: