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

Type inference problem (ambiguous method reference) with lambdas and generics.

XMLWordPrintable

    • generic
    • generic

      FULL PRODUCT VERSION :
      java version "1.8.0_121"
      Java(TM) SE Runtime Environment (build 1.8.0_121-b13)
      Java HotSpot(TM) 64-Bit Server VM (build 25.121-b13, mixed mode)

      ADDITIONAL OS VERSION INFORMATION :
      Linux 4.8.15-1-MANJARO #1 SMP PREEMPT Thu Dec 15 22:22:45 UTC 2016 x86_64 GNU/Linux

      A DESCRIPTION OF THE PROBLEM :
      A method is called by passing a lambda expression as single argument. That method is overloaded. The first method takes a java.util.function.Supplier<?> as single argument, the second one expects <T extends java.lang.Number>.

      The compiler fails saying that also the second method matches the method reference.

      Interestingly, the code does compile when changing <T extends java.lang.Number> to java.lang.Number.

      This is probably related to the problem already reported in JDK-8164611, but I wasn't sure if it's exactly the same issue.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Try to compile the code via "javac AmbiguousReferenceTest.java".

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      I'd expected the code to compile and print "success" when run via "java AmbiguousReferenceTest".
      ACTUAL -
      The code didn't compile (ambiguous reference).

      It does compile on Eclipse though and the test prints "success" (as expected).

      Eclipse IDE for Java Developers
      Version: Neon.2 Release (4.6.2)
      Build id: 20161208-0600

      ERROR MESSAGES/STACK TRACES THAT OCCUR :
      AmbiguousReferenceTest.java:5: error: reference to test is ambiguous
                      test(() -> true);
                      ^
        both method test(Supplier<Boolean>) in AmbiguousReferenceTest and method <T>test(T) in AmbiguousReferenceTest match
        where T is a type-variable:
          T extends Number declared in method <T>test(T)
      1 error

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      public class AmbiguousReferenceTest {

      public static void main(String[] args) {
      test((java.util.function.Supplier<?>) (() -> true));
      test(() -> true);
      System.out.println("success");
      }

      static void test(java.util.function.Supplier<?> obj) {
      // fine
      }

      // with this method the class compiles
      // static void test(java.lang.Number obj) {
      // throw new AssertionError("shouldn't be called");
      // }

      // with this method the class doesn't compile
      static <T extends java.lang.Number> void test(T obj) {
      throw new AssertionError("shouldn't be called");
      }
      }
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      Workaround 1: don't use generics in the second method (i.e. the one that shouldn't be called). See commented out lines 14-16.
      Workaround 2: cast the argument when calling the method. See line 4.

            Unassigned Unassigned
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: