Bug 435767 - [1.8][inference] Problem in inferrence of type : The method
in the type is not applicable for the arguments (Object)
- negative regression test
- some optimizations found during debugging
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest_1_8.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest_1_8.java
index 2666314..3f59b14 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest_1_8.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest_1_8.java
@@ -3335,4 +3335,59 @@
 		"The method collect(Collector<? super Object,A,R>) in the type Stream<Object> is not applicable for the arguments (Collector<Map.Entry<String,String>,capture#1-of ?,Map<String,List<String>>>)\n" + 
 		"----------\n");
 }
+public void testBug435767() {
+	runNegativeTest(
+		new String[] {
+			"DummyClass.java",
+			"import java.util.*;\n" +
+			"import java.util.function.*;\n" +
+			"import java.util.stream.*;\n" +
+			"public class DummyClass {\n" + 
+			"\n" + 
+			"	public void method() {\n" + 
+			"\n" + 
+			"		// Cases where there is no error\n" + 
+			"		final Supplier<Set<String>> suppliers = this.memoize(() -> new HashSet<>());\n" + 
+			"\n" + 
+			"		final Supplier<Map<Object, Object>> noMemoize = () -> suppliers.get().stream()\n" + 
+			"				.filter(path -> path.startsWith(\"\"))\n" + 
+			"				.collect(Collectors.toMap(path -> this.getKey(path), path -> this.getValue(path)));\n" + 
+			"\n" + 
+			"		// Case where there is errors.\n" + 
+			"		final Supplier<Map<Object, Object>> memoize = this.memoize(() -> suppliers.get().stream()\n" + 
+			"				.filter(path -> path.startsWith(\"\"))\n" + 
+			"				.collect(Collectors.toMap(path -> this.getKey(path), path -> this.getValue(path))));\n" + 
+			"\n" + 
+			"		// Error message are : Description\n" + 
+			"		// Resource	Path	Location	Type\n" + 
+			"		// The method getKey(String) in the type DummyClass is not applicable for the arguments (Object)	DummyClass.java line 23	Java Problem\n" + 
+			"		// The method getValue(String) in the type DummyClass is not applicable for the arguments (Object)	DummyClass.java line 23	Java Problem\n" + 
+			"\n" + 
+			"	}\n" + 
+			"\n" + 
+			"	private <T> Supplier<T> memoize(final Supplier<T> delegate) {\n" + 
+			"		return delegate;\n" + 
+			"	}\n" + 
+			"\n" + 
+			"	private Object getKey(final String path) {\n" + 
+			"		return path;\n" + 
+			"	}\n" + 
+			"\n" + 
+			"	private Object getValue(final String path) {\n" + 
+			"		return path;\n" + 
+			"	}\n" + 
+			"}\n"
+		},
+		"----------\n" + 
+		"1. ERROR in DummyClass.java (at line 18)\n" + 
+		"	.collect(Collectors.toMap(path -> this.getKey(path), path -> this.getValue(path))));\n" + 
+		"	                                       ^^^^^^\n" + 
+		"The method getKey(String) in the type DummyClass is not applicable for the arguments (Object)\n" + 
+		"----------\n" + 
+		"2. ERROR in DummyClass.java (at line 18)\n" + 
+		"	.collect(Collectors.toMap(path -> this.getKey(path), path -> this.getValue(path))));\n" + 
+		"	                                                                  ^^^^^^^^\n" + 
+		"The method getValue(String) in the type DummyClass is not applicable for the arguments (Object)\n" + 
+		"----------\n");
+}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceContext18.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceContext18.java
index 0171a8a..b39e57b 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceContext18.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceContext18.java
@@ -330,22 +330,26 @@
 	public InferenceVariable[] addTypeVariableSubstitutions(TypeBinding[] typeVariables) {
 		int len2 = typeVariables.length;
 		InferenceVariable[] newVariables = new InferenceVariable[len2];
+		InferenceVariable[] toAdd = new InferenceVariable[len2];
+		int numToAdd = 0;
 		for (int i = 0; i < typeVariables.length; i++) {
 			if (typeVariables[i] instanceof InferenceVariable)
 				newVariables[i] = (InferenceVariable) typeVariables[i]; // prevent double substitution of an already-substituted inferenceVariable
 			else
-				newVariables[i] = new InferenceVariable(typeVariables[i], this.variableCount++, this.currentInvocation, this.environment, this.object);
+				toAdd[numToAdd++] =
+					newVariables[i] = new InferenceVariable(typeVariables[i], this.variableCount++, this.currentInvocation, this.environment, this.object);
 		}
-
-		int start = 0;
-		if (this.inferenceVariables != null) {
-			int len1 = this.inferenceVariables.length;
-			System.arraycopy(this.inferenceVariables, 0, this.inferenceVariables = new InferenceVariable[len1+len2], 0, len1);
-			start = len1;
-		} else {
-			this.inferenceVariables = new InferenceVariable[len2];
+		if (numToAdd > 0) {
+			int start = 0;
+			if (this.inferenceVariables != null) {
+				int len1 = this.inferenceVariables.length;
+				System.arraycopy(this.inferenceVariables, 0, this.inferenceVariables = new InferenceVariable[len1+numToAdd], 0, len1);
+				start = len1;
+			} else {
+				this.inferenceVariables = new InferenceVariable[numToAdd];
+			}
+			System.arraycopy(toAdd, 0, this.inferenceVariables, start, numToAdd);
 		}
-		System.arraycopy(newVariables, 0, this.inferenceVariables, start, len2);
 		return newVariables;
 	}
 
@@ -413,7 +417,8 @@
 				}
 				InferenceVariable[] variablesArray = allInputs.toArray(new InferenceVariable[allInputs.size()]);
 				//   ... is resolved
-				this.currentBounds.incorporate(this);
+				if (!this.currentBounds.incorporate(this))
+					return null;
 				BoundSet solution = resolve(variablesArray);
 				// in rare cases resolving just one set of variables doesn't suffice,
 				// don't bother with finding the necessary superset, just resolve all: