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 :