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

Bug 528069

Summary: [1.8] type inference fails with lambda and nested generics
Product: [Eclipse Project] JDT Reporter: Till Brychcy <register.eclipse>
Component: CoreAssignee: JDT-Core-Inbox <jdt-core-inbox>
Status: CLOSED WONTFIX QA Contact: Stephan Herrmann <stephan.herrmann>
Severity: normal    
Priority: P3 CC: mat.gessel+eclipse
Version: 4.8   
Target Milestone: ---   
Hardware: PC   
OS: Mac OS X   
Whiteboard:

Description Till Brychcy CLA 2017-12-03 11:18:13 EST
The following code is compiled by javac, but not by eclipse:

package test3;

interface Function<A, B> {
	B apply(A b);
}

interface Option<C> {
}

interface Product<L, R> {
}

abstract public class Test {
	abstract <P> Option<P> optional(P p);

	abstract <X> Product<X, X> product(X x);

	abstract <S1, S2> S2 unwrap(S1 s, Function<S1, Option<Product<S1, S2>>> function);

	public String test(String value) {
		return unwrap(value, s -> optional(product(s)));
	}
}

The reported errors are:
----------
1. ERROR in test3\Test.java (at line 21)
	return unwrap(value, s -> optional(product(s)));
	       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Type mismatch: cannot convert from Object to String
----------\n
2. ERROR in test3\Test.java (at line 21)
	return unwrap(value, s -> optional(product(s)));
	                          ^^^^^^^^^^^^^^^^^^^^
Type mismatch: cannot convert from Option<Product<String,String>> to Option<Product<String,Object>>
----------

Running javac with javac --debug:verboseResolution=all shows that javac also has an intermediate step where Product<String,Object> is involved,
but javac later seems to improve the solution.

I've stepped through the code a bit and noted that Product<String,String> does appear in eclipse too and it smelled to me as somewhere an
expectedType that is already set to Product<String,Object> would have to be updated, but I still don't understand that part of the code well enough.
Comment 1 Till Brychcy CLA 2017-12-03 11:21:39 EST
@Stephan, I guess this one that only you can solve.
Comment 2 Stephan Herrmann CLA 2017-12-06 18:54:27 EST
BTW:

(In reply to Till Brychcy from comment #0)
> Running javac with javac --debug:verboseResolution=all shows that javac also

I've been hunting for such an option for ages, and never found it documented anywhere on the net. Where did you find it?
Comment 3 Till Brychcy CLA 2017-12-08 18:03:55 EST
(In reply to Stephan Herrmann from comment #2)
> BTW:
> 
> (In reply to Till Brychcy from comment #0)
> > Running javac with javac --debug:verboseResolution=all shows that javac also
> 
> I've been hunting for such an option for ages, and never found it documented
> anywhere on the net. Where did you find it?

This is the equivalent for -XDverboseResolution=all in java 8 (which i originally found on stackoverflow)

I can't really remember where I found out about the new syntax, I think in was mentioned in a java 9 targeted bug in https://bugs.openjdk.java.net
Comment 4 Stephan Herrmann CLA 2018-02-22 08:03:40 EST
For the records: behavior changed due to the fix for bug 528069 which was aligned with javac via email with Oracle.

I have to pass this one, since I have no idea how to proceed.
Comment 5 Till Brychcy CLA 2018-02-22 08:07:06 EST
(In reply to Stephan Herrmann from comment #4)
> For the records: behavior changed due to the fix for bug 528069 which was

bug 528069 is this bug :-)
Comment 6 Stephan Herrmann CLA 2018-02-22 08:14:03 EST
(In reply to Till Brychcy from comment #5)
> (In reply to Stephan Herrmann from comment #4)
> > For the records: behavior changed due to the fix for bug 528069 which was
> 
> bug 528069 is this bug :-)

oops, try again: bug 511252
Comment 7 Mat Gessel CLA 2019-11-04 20:19:38 EST
Still happens in 2019-09 R (4.13.0) • JDT 3.18.100.v20190916-1045 • tried ecj 1.8, 12.

Works in javac 8-13.

Workaround: write lambda with arg type:

  unwrap(value, (String s) -> optional(product(s)));


Does ECJ try to solve for type parameters iteratively? I.e. walk the AST, infer that S1 is String, walk the AST again, infer that S2 is String based on use of S1.