JDK-8042738 : Implicitly-typed lambdas are incorrectly potentially applicable
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 8
  • Priority: P4
  • Status: Resolved
  • Resolution: Duplicate
  • OS: linux
  • CPU: x86
  • Submitted: 2014-05-07
  • Updated: 2014-05-08
  • Resolved: 2014-05-08
Related Reports
Duplicate :  
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.