Bug 540520 - Problem compiling annonymous inner class

Change-Id: Iba83100204a6ad6225dffb5f65dae889e8aecddf
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/LambdaExpressionsTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/LambdaExpressionsTest.java
index 2ac9f09..2ab5c9e 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/LambdaExpressionsTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/LambdaExpressionsTest.java
@@ -39,7 +39,7 @@
 public class LambdaExpressionsTest extends AbstractRegressionTest {
 
 static {
-	TESTS_NAMES = new String[] { "test449063"};
+//	TESTS_NAMES = new String[] { "testBug540520"};
 //	TESTS_NUMBERS = new int[] { 50 };
 //	TESTS_RANGE = new int[] { 11, -1 };
 }
@@ -6997,6 +6997,76 @@
 		""
 	);
 }
+public void testBug540520() {
+	Runner runner = new Runner();
+	runner.testFiles = new String[] {
+			"Run.java",
+			"import java.util.ArrayList;\n" + 
+			"import java.util.HashMap;\n" + 
+			"import java.util.List;\n" + 
+			"import java.util.Map;\n" + 
+			"import java.util.stream.Collectors;\n" + 
+			"\n" + 
+			"public class Run {\n" + 
+			"\n" + 
+			"	public static void main(String[] args) {\n" + 
+			"		\n" + 
+			"		List<TypeDeptCount> list = new ArrayList<>();\n" + 
+			"		for(int i=0;i<10;i++) {\n" + 
+			"			TypeDeptCount ty = new TypeDeptCount();\n" + 
+			"			ty.setCykbbm(\"10\"+i);\n" + 
+			"			ty.setCount(i);\n" + 
+			"		}\n" + 
+			"        List<Map<String, Object>> datas = list.stream().collect(Collectors.groupingBy(TypeDeptCount::getType))\n" + 
+			"                .entrySet().stream().map(item -> item.getValue().stream().reduce(new HashMap<String, Object>() {\n" + 
+			"                    private static final long serialVersionUID = 1L;\n" + 
+			"                    {\n" + 
+			"                        put(\"count\", 0);\n" + 
+			"                        put(\"type\", item.getKey());\n" + 
+			"                    }\n" + 
+			"                }, (data1, val) -> {\n" + 
+			"                    data1.put(val.getCykbbm(), val.getCount());\n" + 
+			"                    data1.put(\"count\", (Integer) data1.get(\"count\") + val.getCount());\n" + 
+			"                    return data1;\n" + 
+			"                }, (data1, data2) -> {\n" + 
+			"                    data2.put(\"count\", (Integer) data1.get(\"count\") + (Integer) data2.get(\"count\"));\n" + 
+			"                    data1.putAll(data2);\n" + 
+			"                    return data1;\n" + 
+			"                })).sorted((item1, item2) -> (Integer) item2.get(\"count\") - (Integer) item1.get(\"count\"))\n" + 
+			"                .collect(Collectors.toList());\n" + 
+			"        System.out.println(datas);\n" + 
+			"	}\n" + 
+			"}\n",
+			"TypeDeptCount.java",
+			"public class TypeDeptCount {\n" + 
+			"\n" + 
+			"    private String type;\n" + 
+			"    private String cykbbm;\n" + 
+			"    private Integer count;\n" + 
+			"    \n" + 
+			"	public String getType() {\n" + 
+			"		return type;\n" + 
+			"	}\n" + 
+			"	public void setType(String type) {\n" + 
+			"		this.type = type;\n" + 
+			"	}\n" + 
+			"	public String getCykbbm() {\n" + 
+			"		return cykbbm;\n" + 
+			"	}\n" + 
+			"	public void setCykbbm(String cykbbm) {\n" + 
+			"		this.cykbbm = cykbbm;\n" + 
+			"	}\n" + 
+			"	public Integer getCount() {\n" + 
+			"		return count;\n" + 
+			"	}\n" + 
+			"	public void setCount(Integer count) {\n" + 
+			"		this.count = count;\n" + 
+			"	}\n" + 
+			"}\n"
+		};
+	runner.runConformTest();
+	
+}
 public static Class testClass() {
 	return LambdaExpressionsTest.class;
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LambdaExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LambdaExpression.java
index 4d6b5d5..3494069 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LambdaExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LambdaExpression.java
@@ -1475,7 +1475,7 @@
 					if (((LambdaExpression) lambdaScope2.referenceContext).sourceStart == LambdaExpression.this.sourceStart) {
 						// local type within this lambda needs replacement: 
 						TypeBinding substType = this.localTypes2.get(orgLocal.sourceStart);
-						if (substType != null) {
+						if (substType != null && substType != orgLocal) { //$IDENTITY-COMPARISON$
 							orgLocal.transferConstantPoolNameTo(substType);
 							return substType;
 						}
@@ -1501,10 +1501,11 @@
 	/**
 	 * Perform substitution with a {@link LocalTypeSubstitutor} on all types mentioned in the given method binding.
 	 */
-	void updateLocalTypesInMethod(MethodBinding method) {
+	boolean updateLocalTypesInMethod(MethodBinding method) {
 		if (this.localTypes == null)
-			return;
+			return false;
 		updateLocalTypesInMethod(method, new LocalTypeSubstitutor(this.localTypes), new NullSubstitution(this.scope.environment()));
+		return true;
 	}
 
 	private void updateLocalTypesInMethod(MethodBinding method, Substitutor substor, Substitution subst) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java
index 78f4eea..d5b9f6f 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java
@@ -358,6 +358,11 @@
 	if (methodType == null)
 		return;
 
+	if (methodType.isProperType(true) && lambda != null) {
+		// ensure that type conversions don't leak a preliminary local type:
+		if (lambda.updateLocalTypesInMethod(lambda.descriptor))
+			methodType = lambda.expectedResultType();
+	}
 	if (TypeBinding.notEquals(methodType, expressionType)) // must call before computeConversion() and typeMismatchError()
 		scope.compilationUnitScope().recordTypeConversion(methodType, expressionType);
 	if (this.expression.isConstantValueOfTypeAssignableToType(expressionType, methodType)