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

Bug 433823

Summary: [1.8][quick assist] Conversion from lambda to anonymous class results in compile error
Product: [Eclipse Project] JDT Reporter: Noopur Gupta <noopur_gupta>
Component: UIAssignee: JDT-UI-Inbox <jdt-ui-inbox>
Status: CLOSED DUPLICATE QA Contact:
Severity: normal    
Priority: P3 CC: rdtorres
Version: 4.4   
Target Milestone: ---   
Hardware: All   
OS: All   
Whiteboard:

Description Noopur Gupta CLA 2014-04-30 05:19:51 EDT
Example taken from bug 428856 comment #0:

----------------------------------------------------------------------
package p;

public interface Change<T, R, E extends Exception> {

	R apply(T t) throws E;

	default <V> Change<V, R, E> from(Change<? super V, ? extends T, E> before) {
		return (V v) -> apply(before.apply(v));
	}
}
----------------------------------------------------------------------

Convert the lambda to anonymous class using the quick assist.
We get the following result with a compile error:

----------------------------------------------------------------------
package p;

public interface Change<T, R, E extends Exception> {

	R apply(T t) throws E;

	default <V> Change<V, R, E> from(Change<? super V, ? extends T, E> before) {
		return new Change<V, R, E>() {
			@Override
			public R apply(V v) throws E {
				return apply(before.apply(v));
                                       ^^^^^ 
			}
		};
	}
}
----------------------------------------------------------------------

Error: The method apply(V) in the type is not applicable for the arguments (capture#2-of ? extends T)
Comment 1 Rafael Torres CLA 2015-04-16 14:14:05 EDT
I faced this issue as well. 

This is a patch to fix it: 

--- StubUtility2.java
+++ StubUtility2.java
@@ -52,6 +52,7 @@
 import org.eclipse.jdt.core.dom.Modifier;
 import org.eclipse.jdt.core.dom.Name;
 import org.eclipse.jdt.core.dom.NodeFinder;
+import org.eclipse.jdt.core.dom.ParameterizedType;
 import org.eclipse.jdt.core.dom.PrimitiveType;
 import org.eclipse.jdt.core.dom.ReturnStatement;
 import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
@@ -342,7 +343,33 @@
 			bindingReturnType= bindingReturnType.getErasure();
 		}
 		
+    if (bindingReturnType.isParameterizedType() && bindingReturnType.getTypeArguments().length > 0){
+      
+      
+      Type baseType=ast.newSimpleType(ast.newSimpleName(bindingReturnType.getErasure().getName()));
+      ParameterizedType newInstantiatedType=ast.newParameterizedType(baseType);
+      
+      List<Type> newInstTypeArgs=newInstantiatedType.typeArguments();
+      
+      ITypeBinding[] types = bindingReturnType.getTypeArguments();
+      for(ITypeBinding bindingT : types){
+        if (bindingT.isWildcardType()) {
+          ITypeBinding bound= bindingT.getBound();
+          bindingT = (bound != null) ? bound : bindingT.getErasure();
+        }
+        Type typeArg=ASTNodeFactory.newType(ast,bindingT.getName());
+        newInstTypeArgs.add(typeArg);
+      }
+        
+      decl.setReturnType2(newInstantiatedType);
+      
+      
+    } else {
+    
+      
+            
 		decl.setReturnType2(imports.addImport(bindingReturnType, ast, context));
+    }
 
 		List<SingleVariableDeclaration> parameters= createParameters(javaProject, imports, context, ast, binding, parameterNames, decl);
Comment 2 Noopur Gupta CLA 2015-04-17 04:50:07 EDT
(In reply to Rafael Torres from comment #1)
> I faced this issue as well. 
> 
> This is a patch to fix it: 

You patch does not fix the issue mentioned in comment #0.

This bug is a duplicate of bug 439637 and works if "this" is added to the method invocation in lambda body:

return (V v) -> this.apply(before.apply(v));

Please check if you have the same issue and if not, create a new bug report and provide the patch based on:
https://wiki.eclipse.org/JDT_UI/How_to_Contribute#Contributing_a_change

*** This bug has been marked as a duplicate of bug 439637 ***