Fixed bug 375394: Incorrect type checking for parameterized types
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest.java
index f2968e4..ee7d81e 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest.java
@@ -2549,4 +2549,23 @@
 		"Comparable is a raw type. References to generic type Comparable<T> should be parameterized\n" + 
 		"----------\n");
 }
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=375394
+public void test375394() {
+	this.runNegativeTest(
+		new String[] {
+			"X.java",
+			"import java.util.Collection;\n" +
+			"public class X {\n" +
+			"    static <C1,C2 extends Collection<Object>> boolean foo(C1 c, C2 c2) {\n" +
+			"        return foo(c2,c); \n" +
+			"    }\n" +
+			"}\n",
+		},
+		"----------\n" + 
+		"1. ERROR in X.java (at line 4)\n" + 
+		"	return foo(c2,c); \n" + 
+		"	       ^^^\n" + 
+		"Bound mismatch: The generic method foo(C1, C2) of type X is not applicable for the arguments (C2, C1). The inferred type C1 is not a valid substitute for the bounded parameter <C2 extends Collection<Object>>\n" + 
+		"----------\n");
+}
 }
\ No newline at end of file
diff --git a/org.eclipse.jdt.core/buildnotes_jdt-core.html b/org.eclipse.jdt.core/buildnotes_jdt-core.html
index 4536208..5a05863 100644
--- a/org.eclipse.jdt.core/buildnotes_jdt-core.html
+++ b/org.eclipse.jdt.core/buildnotes_jdt-core.html
@@ -52,7 +52,9 @@
 <h2>What's new in this drop</h2>
 
 <h3>Problem Reports Fixed</h3>
-<a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=375326">375326</a>
+<a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=375394">375394</a>
+Incorrect type checking for parameterized types
+<br><a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=375326">375326</a>
 try-with-resources assignment in statement produces stack map exception
 
 <a name="v_C43"></a>
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java
index 31710c4..84595b4 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -95,7 +95,18 @@
 		for (int i = 0, length = typeVariables.length; i < length; i++) {
 		    TypeVariableBinding typeVariable = typeVariables[i];
 		    TypeBinding substitute = methodSubstitute.typeArguments[i]; // retain for diagnostics
-		    TypeBinding substituteForChecks = Scope.substitute(new LingeringTypeVariableEliminator(typeVariables, null, scope), substitute); // while using this for bounds check
+		    /* https://bugs.eclipse.org/bugs/show_bug.cgi?id=375394, To avoid spurious bounds check failures due to circularity in formal bounds, 
+		       we should eliminate only the lingering embedded type variable references after substitution, not alien type variable references
+		       that constitute the inference per se. Also short circuit this step, if the substitution has no type variables in the first place 
+		       (as it is effectively a nop.)
+		     */ 
+		    TypeBinding substituteForChecks;
+		    if (substitute instanceof TypeVariableBinding || ((substitute.tagBits & TagBits.HasTypeVariable) == 0)) {
+		    	substituteForChecks = substitute;
+		    } else {
+		    	substituteForChecks = Scope.substitute(new LingeringTypeVariableEliminator(typeVariables, null, scope), substitute); // while using this for bounds check
+		    }
+		    
 		    if (uncheckedArguments != null && uncheckedArguments[i] == null) continue; // only bound check if inferred through 15.12.2.6
 			switch (typeVariable.boundCheck(substitution, substituteForChecks)) {
 				case TypeConstants.MISMATCH :