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

Implicitly-typed lambdas are incorrectly potentially applicable

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Resolved
    • Priority: P4
    • Resolution: Duplicate
    • Affects Version/s: 8
    • Fix Version/s: None
    • Component/s: tools
    • Labels:
    • Subcomponent:
    • CPU:
      x86
    • OS:
      linux

      Description

      FULL PRODUCT VERSION :
      java version "1.8.0"
      Java(TM) SE Runtime Environment (build 1.8.0-b132)
      Java HotSpot(TM) Server VM (build 25.0-b70, mixed mode)

      ADDITIONAL OS VERSION INFORMATION :
      Linux linuxmint 3.2.0-32-generic #51-Ubuntu SMP Wed Sep 26 21:32:50 UTC 2012 i686 athlon i386 GNU/Linux

      A DESCRIPTION OF THE PROBLEM :
      JLS8 chapter 15.12.2.1 describes when a lambda is considered potentially applicable with a functional interface type like follows:

      "A lambda expression (§15.27) is potentially compatible with a functional interface type (§9.8) if all of the following are true:

        * The arity of the target type's function type is the same as the arity of the lambda expression.

        * If the target type's function type has a void return, then the lambda body is either a statement expression (§14.8) or a void-compatible block (§15.27.2).

        * If the target type's function type has a (non-void) return type, then the lambda body is either an expression or a value-compatible block (§15.27.2)."

      It also implies that these rules should hold for both implicitly-typed and explicitly-typed lambdas by stating this:

      "The definition of potential applicability goes beyond a basic arity check to also take into account the presence and "shape" of functional interface target types. In some cases involving type argument inference, a lambda expression appearing as a method invocation argument cannot be properly typed until after overload resolution. These rules allow the form of the lambda expression to still be taken into account, discarding obviously incorrect target types that might otherwise cause ambiguity errors. "

      However, in the test case supplied with this report the implicitly-typed lambdas are potentially applicable with functional interface types in a way that breaks the above stated rules.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Compile the provided test case.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Expected compilation to succeed.
      ACTUAL -
      Compilation fails with ambiguity error.

      ERROR MESSAGES/STACK TRACES THAT OCCUR :
      Test.java:18: error: reference to method is ambiguous
      method((a, b) -> a + b);
      ^
        both method method(A) in Test and method method(B) in Test match
      Test.java:18: error: incompatible types: bad return type in lambda expression
      method((a, b) -> a + b);
      ^
          int cannot be converted to void
      Test.java:21: error: reference to method is ambiguous
      method((a, b) -> {System.out.println("String"); });
      ^
        both method method(A) in Test and method method(B) in Test match
      Test.java:25: error: reference to method is ambiguous
      method((a, b) -> {
      ^
        both method method(A) in Test and method method(B) in Test match
      Test.java:27: error: incompatible types: bad return type in lambda expression
      return a + b;
      ^
          unexpected return value
      Note: Some messages have been simplified; recompile with -Xdiags:verbose to get full output
      5 errors


      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      import java.util.*;

      public class Test {

      interface A {
      void m(int a, int b);
      }
      interface B {
      int m(int a, int b);
      }

      public static void method(A a) { }

      public static void method(B b) { }

      public static void main(String[] args) {
      // Should only be potentially applicable with type B
      method((a, b) -> a + b);

      // Should only be potentially applicable with type A
      method((a, b) -> {System.out.println("String"); });


      // Should only be potentially applicable with type B
      method((a, b) -> {
      if(a < b)
      return a + b;
      else
      return a;
      });
          }
      }
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      Use explicitly-typed lambdas.

        Attachments

          Issue Links

            Activity

              People

              • Assignee:
                vromero Vicente Arturo Romero Zaldivar
                Reporter:
                webbuggrp Webbug Group
              • Votes:
                0 Vote for this issue
                Watchers:
                1 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved: