Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 545420

Summary: [1.8][inference] Receiving The target type of this expression must be a functional interface
Product: [Eclipse Project] JDT Reporter: kanagamahendran velusamy <kvelusamy>
Component: CoreAssignee: Stephan Herrmann <stephan.herrmann>
Status: VERIFIED FIXED QA Contact:
Severity: major    
Priority: P3 CC: jarthana, kvelusamy, manoj.palat, stephan.herrmann
Version: 4.10   
Target Milestone: 4.12 M3   
Hardware: PC   
OS: Windows 10   
See Also: https://git.eclipse.org/c/jdt/eclipse.jdt.core.git/commit/?h=R4_5_maintenance&id=dba3d88819f31e52c7b1709da4ad2221836bbba2
https://bugs.eclipse.org/bugs/show_bug.cgi?id=463728
https://git.eclipse.org/r/142384
https://git.eclipse.org/c/jdt/eclipse.jdt.core.git/commit/?id=5147f38abb400d33a4aa49de5af5318835c60b88
Whiteboard:
Attachments:
Description Flags
the java class none

Description kanagamahendran velusamy CLA 2019-03-14 15:42:55 EDT
Created attachment 277867 [details]
the java class

Please see the attached java class. Java compiler is able to compile correctly where as eclipse is showing error (version 4.4 with Luna - its working fine)

public class Main {

	public static void main(String[] args) {  

		System.out.println(new Main().getDetailCellCssFactory().getReturn());
      
	}

	public FIReturnType getDetailCellCssFactory() {
		
		return 	method1(()-> {
					return  () ->{							
							return "something";
						
					};
					
			});
	}
	
	public <X> X method1(FIWithGenerics<X> init) {
		return init.init();		
	}
}

interface FIReturnType {
	String getReturn();
}

interface FIWithGenerics<X> {
	 X init();
}


---------------------------------------------
it is giving these two errors 
The target type of this expression must be a functional interface
The method method1(FIWithGenerics<X>) in the type Main is not applicable for the arguments (() -> {})
Comment 1 kanagamahendran velusamy CLA 2019-03-14 16:04:13 EDT
This error is happening in eclipse 2018-12 latest public stable eclipse version ,however this is happening in Luna version.
Comment 2 Stephan Herrmann CLA 2019-03-14 17:28:26 EDT
Thanks I can reproduce.

The program was accepted up until 4.5, the change is caused by the fix for bug 463728

The corresponding commit only ensures we are always looking into result expressions of a lambda, even if the resultType is not yet known.
At first glance this fix looks innocent. I could only vaguely imagine, that it causes some premature type information to become sticky and prevent the correct typing later.

Until we figure out if this indeed is a regression or in line with JLS (which can take a while since these are complex issues), the following workaround can be used:

         return  this.<FIReturnType>method1(()-> { ...
Comment 3 kanagamahendran velusamy CLA 2019-03-14 19:54:48 EDT
the workaround 
        return  this.<FIReturnType>method1(()-> { ...
         or
        return  (FIReturnType)method1(()-> { ... 
are working without error in eclipse 

The java compiler ,compiles for 
                       return method1(()->{... 
it is good to have same feature in eclipse as well. 

Thank you for your time!
Comment 4 kanagamahendran velusamy CLA 2019-03-14 20:04:07 EDT
I had a wrong copy paste in the above comment...

The workaround 
        return  this.<FIReturnType>method1(()-> { ...
         or
        return 	method1(()-> {
					return (FIReturnType) () ->{ ...	
are working without error in eclipse 

The java compiler ,compiles for 
                       return method1(()->{... 
it is good to have same feature in eclipse as well. 

Thank you for your time!
Comment 5 Eclipse Genie CLA 2019-05-18 17:42:40 EDT
New Gerrit change created: https://git.eclipse.org/r/142384
Comment 6 Stephan Herrmann CLA 2019-05-18 17:49:27 EDT
(In reply to Eclipse Genie from comment #5)
> New Gerrit change created: https://git.eclipse.org/r/142384

I made an interesting find:

Inference is rejecting the inner lambda because at this point its target type is an inference variable.

JLS §18.2.1. says:

"A constraint formula of the form ‹LambdaExpression → T›, where T mentions at least one inference variable, is reduced as follows:

 * If T is not a functional interface type (§9.8), the constraint reduces to false."

An interface variable is not a functional interface type, hence ecj rejecting the program looks correct per JLS.

Apparently, s.t. is missing in JLS to prevent this undesirable effect, and interestingly, a first test run doesn't complain if I invent another rule:

 * If T is an inference variable, the constraint reduces to true (delegating the details to inner inference)


Let's see what full test run says.
Comment 8 Stephan Herrmann CLA 2019-05-18 19:39:24 EDT
(In reply to Eclipse Genie from comment #7)
> Gerrit change https://git.eclipse.org/r/142384 was merged to [master].
> Commit:
> http://git.eclipse.org/c/jdt/eclipse.jdt.core.git/commit/
> ?id=5147f38abb400d33a4aa49de5af5318835c60b88

Released for 4.12 M3
Comment 9 Manoj N Palat CLA 2019-05-21 06:05:51 EDT
Verified for Eclipse Version: 2019-06 (4.12) Build id: I20190520-0600