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

javac can't infer types from method reference when it can infer the type for lambda

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Not an Issue
    • Icon: P4 P4
    • 18
    • 11.0.9.1
    • tools
    • x86
    • windows_10

      Compiling the following code produces a compilation error on the usage of the method reference D::new, but not on the usage of the seemingly equivalent lambda expression (t, u) -> new D(t, u)


      package p;

      import java.util.function.BiFunction;

      abstract class Test extends B<Y> {
          void m(E<Integer> e) {
              e.e(new C<>(this, e, D::new));
              e.e(new C<>(this, e, (t, u) -> new D(t, u)));
          }
      }

      abstract class A<R extends Y> {}
      abstract class B<R extends Y> extends A<R> {}

      class C<T, R extends Y, Q extends A<R>> implements X {
          C(Q q, E<T> i, BiFunction<Q, C<T, R, Q>, E<Z>> f) {}
      }

      class D implements E<Z> {
          D(B<?> y, C<? super Integer, ?, ?> x) {}
          @Override
          public void e(X f) {}
      }


      interface E<T> {
          void e(X f);
      }
      interface X {}
      interface Y {}
      interface Z {}


      It can be reproduced with JDK 11 or 16:

      C:\Users\lukas\jOOQ\3.15\workspace\jOOQ-pro\jOOQ\src\main\java>javac -version
      javac 11.0.9.1

      C:\Temp>javac p/Test.java
      p\Test.java:7: error: cannot infer type arguments for C<>
              e.e(new C<>(this, e, D::new));
                  ^
        reason: inference variable Q has incompatible upper bounds A<Y>,B<?>
        where Q,R are type-variables:
          Q extends A<R> declared in class C
          R extends Y declared in class C
      1 error


      C:\Temp>"c:\Program Files\Java\jdk-16\bin\javac.exe" -version
      javac 16

      C:\Users\lukas\jOOQ\3.15\workspace\jOOQ-pro\jOOQ\src\main\java>"c:\Program Files\Java\jdk-16\bin\javac.exe" p/Test.java
      p\Test.java:7: error: cannot infer type arguments for C<>
              e.e(new C<>(this, e, D::new));
                  ^
        reason: inference variable Q has incompatible upper bounds A<Y>,B<?>
        where Q,R are type-variables:
          Q extends A<R> declared in class C
          R extends Y declared in class C
      1 error


      Eclipse compiles both method reference and lambda expression just fine. IntelliJ also doesn't detect any flaw, and even suggests replacing the lambda by a method reference


      A workaround is to avoid the diamond operator and provide explicit type arguments:


      abstract class Test extends B<Y> {
          void m(E<Integer> e) {
              e.e(new C<Integer, Y, Test>(this, e, D::new));
              e.e(new C<>(this, e, (t, u) -> new D(t, u)));
          }
      }

            vromero Vicente Arturo Romero Zaldivar
            leder Lukas Eder
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated:
              Resolved: