95638
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericTypeTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericTypeTest.java
index 4939176..1e5bcfe 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericTypeTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericTypeTest.java
@@ -19670,19 +19670,20 @@
"class Store<F extends Key<F>> {}\n" +
"\n" +
"public class X<T> {\n" +
- " Store<? extends Key<T>> store;\n" +
+ " Store<? extends Key<T>> store1;\n" +
+ " Store<? extends Key<? extends T>> store2;\n" +
"}\n",
},
"----------\n" +
- "1. ERROR in X.java (at line 5)\n" +
- " Store<? extends Key<T>> store;\n" +
- " ^^^^^^^^^^^^^\n" +
- "Bound mismatch: The type ? extends Key<T> is not a valid substitute for the bounded parameter <F extends Key<F>> of the type Store<F>\n" +
- "----------\n" +
- "2. ERROR in X.java (at line 5)\n" +
- " Store<? extends Key<T>> store;\n" +
+ "1. ERROR in X.java (at line 5)\r\n" +
+ " Store<? extends Key<T>> store1;\r\n" +
" ^\n" +
"Bound mismatch: The type T is not a valid substitute for the bounded parameter <E extends Key<E>> of the type Key<E>\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 6)\r\n" +
+ " Store<? extends Key<? extends T>> store2;\r\n" +
+ " ^^^^^^^^^^^\n" +
+ "Bound mismatch: The type ? extends T is not a valid substitute for the bounded parameter <E extends Key<E>> of the type Key<E>\n" +
"----------\n");
}
//check fault tolerance, in spite of bound mismatch, still pass param type for further resolving message send
@@ -19769,7 +19770,7 @@
}
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=95638 - variation
public void test679() {
- this.runNegativeTest(
+ this.runConformTest(
new String[] {
"X.java",
"class Key<E, F extends Key<E, F>> {}\n" +
@@ -19779,16 +19780,11 @@
" Store<K, ? extends Key<K, ?>> store;\n" +
"}\n",
},
- "----------\n" +
- "1. ERROR in X.java (at line 5)\n" +
- " Store<K, ? extends Key<K, ?>> store;\n" +
- " ^^^^^^^^^^^^^\n" +
- "Bound mismatch: The type ? extends Key<K,?> is not a valid substitute for the bounded parameter <B extends Key<A,B>> of the type Store<A,B>\n" +
- "----------\n");
+ "");
}
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=95638 - variation
public void test680() {
- this.runNegativeTest(
+ this.runConformTest(
new String[] {
"X.java",
"import java.util.List;\n" +
@@ -19802,16 +19798,11 @@
" List<Store<K, ?, ? extends Key<K, ?, ?, ?>, ? extends State<?>>> stores;\n" +
"}\n",
},
- "----------\n" +
- "1. ERROR in X.java (at line 9)\n" +
- " List<Store<K, ?, ? extends Key<K, ?, ?, ?>, ? extends State<?>>> stores;\n" +
- " ^^^^^^^^^^^^^\n" +
- "Bound mismatch: The type ? extends Key<K,?,?,?> is not a valid substitute for the bounded parameter <C extends Key<A,B,C,D>> of the type Store<A,B,C,D>\n" +
- "----------\n");
-}
+ "");
+}
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=95638 - variation
public void test681() {
- this.runNegativeTest(
+ this.runConformTest(
new String[] {
"X.java",
"class Key<E, K extends Key<E, K>> {\n" +
@@ -19830,14 +19821,9 @@
" Y<?, ?> y;\n" +
"}\n",
},
- "----------\n" +
- "1. ERROR in X.java (at line 7)\n" +
- " Store<E, ? extends Key<E, ?>> store2;\n" +
- " ^^^^^^^^^^^^^\n" +
- "Bound mismatch: The type ? extends Key<E,?> is not a valid substitute for the bounded parameter <K extends Key<E,K>> of the type Store<E,K>\n" +
- "----------\n");
-}
-//https://bugs.eclipse.org/bugs/show_bug.cgi?id=96134
+ "");
+}
+//https://bugs.eclipse.org/bugs/show_bug.cgi?id=95963
public void test682() {
this.runNegativeTest(
new String[] {
@@ -19853,4 +19839,440 @@
"----------\n"
);
}
+//https://bugs.eclipse.org/bugs/show_bug.cgi?id=96085
+public void test683() {
+ this.runConformTest(
+ new String[] {
+ "P.java",
+ "interface P<V> {\n" +
+ " interface A {}\n" +
+ "}\n",
+ "P2.java",
+ "class P2 implements P.A {\n" +
+ " P2(P.A problem) {}\n" +
+ "}\n",
+ "P3.java",
+ "class P3 {\n" +
+ " void test() {P.A o = new P2((P.A) null);}\n" +
+ "}\n",
+ },
+ "");
+}
+public void test684() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "public class X<T> {\n" +
+ " <U> U foo(U u1, U u2) {\n" +
+ " return u1;\n" +
+ " }\n" +
+ " void bar(X<? extends Throwable> x1, X<? extends Runnable> x2) {\n" +
+ " X<String> x = foo(x1, x2);\n" +
+ " }\n" +
+ "}\n",
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 6)\n" +
+ " X<String> x = foo(x1, x2);\n" +
+ " ^\n" +
+ "Type mismatch: cannot convert from X<capture-of ? extends Object> to X<String>\n" +
+ "----------\n");
+}
+public void test685() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "public class X<T> {\n" +
+ " <U> U foo(U u1, U u2) {\n" +
+ " return u1;\n" +
+ " }\n" +
+ " void bar(X<? extends Throwable> x1, X<? extends Runnable> x2) {\n" +
+ " X<String> x = foo(x1, x2);\n" +
+ " }\n" +
+ "}\n",
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 6)\n" +
+ " X<String> x = foo(x1, x2);\n" +
+ " ^\n" +
+ "Type mismatch: cannot convert from X<capture-of ? extends Object> to X<String>\n" +
+ "----------\n");
+}
+// check wildcard bounds wrt variable boundCheck
+public void test686() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.util.List;\n" +
+ "class Other<T extends List<? extends Runnable>> {\n" +
+ "}\n" +
+ "\n" +
+ "public class X {\n" +
+ " Other<? extends List<? extends Throwable>> other1;\n" +
+ " Other<? extends List<? super String>> other2; \n" +
+ " Other<? extends List<? extends String>> other3; \n" +
+ " Other<? extends List<? extends Runnable>> other7 = other1;\n" +
+ "}\n",
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 7)\n" +
+ " Other<? extends List<? super String>> other2; \n" +
+ " ^^^^^^^^^^^^^^\n" +
+ "Bound mismatch: The type ? extends List<? super String> is not a valid substitute for the bounded parameter <T extends List<? extends Runnable>> of the type Other<T>\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 8)\n" +
+ " Other<? extends List<? extends String>> other3; \n" +
+ " ^^^^^^^^^^^^^^\n" +
+ "Bound mismatch: The type ? extends List<? extends String> is not a valid substitute for the bounded parameter <T extends List<? extends Runnable>> of the type Other<T>\n" +
+ "----------\n");
+}
+// check wildcard bounds wrt variable boundCheck
+public void test687() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.util.List;\n" +
+ "class Other<T extends List<? extends Runnable>> {\n" +
+ "}\n" +
+ "\n" +
+ "public class X {\n" +
+ " Other<? extends List<?>> other2;\n" +
+ " Other<? extends List<? super Throwable>> other3;\n" +
+ " Other<? super List<? extends Throwable>> other4;\n" +
+ " Other<? super List<?>> other5;\n" +
+ " Other<? super List<? super Throwable>> other6;\n" +
+ "}\n",
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 7)\n" +
+ " Other<? extends List<? super Throwable>> other3;\n" +
+ " ^^^^^^^^^^^^^^\n" +
+ "Bound mismatch: The type ? extends List<? super Throwable> is not a valid substitute for the bounded parameter <T extends List<? extends Runnable>> of the type Other<T>\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 8)\n" +
+ " Other<? super List<? extends Throwable>> other4;\n" +
+ " ^^^^^^^^^^^^\n" +
+ "Bound mismatch: The type ? super List<? extends Throwable> is not a valid substitute for the bounded parameter <T extends List<? extends Runnable>> of the type Other<T>\n" +
+ "----------\n" +
+ "3. ERROR in X.java (at line 9)\n" +
+ " Other<? super List<?>> other5;\n" +
+ " ^^^^^^^^^^^^\n" +
+ "Bound mismatch: The type ? super List<?> is not a valid substitute for the bounded parameter <T extends List<? extends Runnable>> of the type Other<T>\n" +
+ "----------\n" +
+ "4. ERROR in X.java (at line 10)\n" +
+ " Other<? super List<? super Throwable>> other6;\n" +
+ " ^^^^^^^^^^^^\n" +
+ "Bound mismatch: The type ? super List<? super Throwable> is not a valid substitute for the bounded parameter <T extends List<? extends Runnable>> of the type Other<T>\n" +
+ "----------\n");
+}
+// check wildcard bounds wrt variable boundCheck
+public void test688() {
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "import java.util.List;\n" +
+ "class Other<T extends List<? extends Runnable>> {\n" +
+ "}\n" +
+ "\n" +
+ "public class X {\n" +
+ " Other<? super List<? extends Runnable>> other5;\n" +
+ "}\n",
+ },
+ "");
+}
+// check wildcard bounds wrt variable boundCheck
+public void test689() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.util.List;\n" +
+ "class Other<T extends List<? extends Runnable>> {\n" +
+ "}\n" +
+ "\n" +
+ "public class X {\n" +
+ " Other<? super List<? super Runnable>> other5;\n" +
+ "}\n",
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 6)\n" +
+ " Other<? super List<? super Runnable>> other5;\n" +
+ " ^^^^^^^^^^^^\n" +
+ "Bound mismatch: The type ? super List<? super Runnable> is not a valid substitute for the bounded parameter <T extends List<? extends Runnable>> of the type Other<T>\n" +
+ "----------\n");
+}
+// check assignment rules across param types with wildcards
+public void test690() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.util.List;\n" +
+ "public class X {\n" +
+ " void foo(List<? extends Runnable> lr, List<?> la) {\n" +
+ " lr = la;\n" +
+ " la = lr;\n" +
+ " }\n" +
+ "} \n" +
+ "\n",
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 4)\n" +
+ " lr = la;\n" +
+ " ^^\n" +
+ "Type mismatch: cannot convert from List<capture-of ?> to List<? extends Runnable>\n" +
+ "----------\n");
+}
+// check that final class bound is more restrictive
+public void test691() {
+ this.runNegativeTest(
+ new String[] {
+ "XX.java",
+ "public class XX<T extends Runnable> {\n" +
+ " void foo(XX<?> lhs, XX<? extends String> rhs) {\n" +
+ " lhs = rhs;\n" +
+ " }\n" +
+ "}\n",
+ },
+ "----------\n" +
+ "1. ERROR in XX.java (at line 2)\n" +
+ " void foo(XX<?> lhs, XX<? extends String> rhs) {\n" +
+ " ^^^^^^^^^^^^^^^^\n" +
+ "Bound mismatch: The type ? extends String is not a valid substitute for the bounded parameter <T extends Runnable> of the type XX<T>\n" +
+ "----------\n");
+}
+// check wildcard bounds wrt variable boundCheck
+public void test692() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.util.List;\n" +
+ "\n" +
+ "public class X<T extends List<Object>> {\n" +
+ " \n" +
+ " void foo(X<? extends List<String>> x) {\n" +
+ " }\n" +
+ "}\n",
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 5)\n" +
+ " void foo(X<? extends List<String>> x) {\n" +
+ " ^^^^^^^^^^^^^^\n" +
+ "Bound mismatch: The type ? extends List<String> is not a valid substitute for the bounded parameter <T extends List<Object>> of the type X<T>\n" +
+ "----------\n");
+}
+// bound checks
+public void test693() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "public class X<T extends Runnable> {\n" +
+ " X<X<String>> x1;\n" +
+ " X<? extends String> x2;\n" +
+ "}\n",
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 2)\n" +
+ " X<X<String>> x1;\n" +
+ " ^\n" +
+ "Bound mismatch: The type X<String> is not a valid substitute for the bounded parameter <T extends Runnable> of the type X<T>\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 2)\n" +
+ " X<X<String>> x1;\n" +
+ " ^^^^^^\n" +
+ "Bound mismatch: The type String is not a valid substitute for the bounded parameter <T extends Runnable> of the type X<T>\n" +
+ "----------\n" +
+ "3. ERROR in X.java (at line 3)\n" +
+ " X<? extends String> x2;\n" +
+ " ^^^^^^^^^^^^^^^^\n" +
+ "Bound mismatch: The type ? extends String is not a valid substitute for the bounded parameter <T extends Runnable> of the type X<T>\n" +
+ "----------\n");
+}
+// bound checks
+public void test694() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "public class X<T extends X<T>> {\n" +
+ " X<X<X<String>>> x1;\n" +
+ " X<? extends X<? extends X<String>>> x2;\n" +
+ "}\n",
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 2)\n" +
+ " X<X<X<String>>> x1;\n" +
+ " ^\n" +
+ "Bound mismatch: The type X<X<String>> is not a valid substitute for the bounded parameter <T extends X<T>> of the type X<T>\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 2)\n" +
+ " X<X<X<String>>> x1;\n" +
+ " ^\n" +
+ "Bound mismatch: The type X<String> is not a valid substitute for the bounded parameter <T extends X<T>> of the type X<T>\n" +
+ "----------\n" +
+ "3. ERROR in X.java (at line 2)\n" +
+ " X<X<X<String>>> x1;\n" +
+ " ^^^^^^\n" +
+ "Bound mismatch: The type String is not a valid substitute for the bounded parameter <T extends X<T>> of the type X<T>\n" +
+ "----------\n" +
+ "4. ERROR in X.java (at line 3)\n" +
+ " X<? extends X<? extends X<String>>> x2;\n" +
+ " ^^^^^^^^^^^\n" +
+ "Bound mismatch: The type ? extends X<String> is not a valid substitute for the bounded parameter <T extends X<T>> of the type X<T>\n" +
+ "----------\n" +
+ "5. ERROR in X.java (at line 3)\n" +
+ " X<? extends X<? extends X<String>>> x2;\n" +
+ " ^^^^^^\n" +
+ "Bound mismatch: The type String is not a valid substitute for the bounded parameter <T extends X<T>> of the type X<T>\n" +
+ "----------\n");
+}
+// bound checks
+public void test695() {
+ this.runConformTest(
+ new String[] {
+ "I.java",
+ "interface I<T extends I<? extends T>> {\n" +
+ "}\n",
+ },
+ "");
+}
+public void test696() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "class Key<E extends Key<E>> {}\n" +
+ "class Store<F extends Key<F>> {}\n" +
+ "\n" +
+ "public class X<T> {\n" +
+ " Store<? extends Key<T>> store = new Store<Key<T>>();\n" +
+ "}\n",
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 5)\n" +
+ " Store<? extends Key<T>> store = new Store<Key<T>>();\n" +
+ " ^\n" +
+ "Bound mismatch: The type T is not a valid substitute for the bounded parameter <E extends Key<E>> of the type Key<E>\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 5)\n" +
+ " Store<? extends Key<T>> store = new Store<Key<T>>();\n" +
+ " ^^^\n" +
+ "Bound mismatch: The type Key<T> is not a valid substitute for the bounded parameter <F extends Key<F>> of the type Store<F>\n" +
+ "----------\n" +
+ "3. ERROR in X.java (at line 5)\n" +
+ " Store<? extends Key<T>> store = new Store<Key<T>>();\n" +
+ " ^\n" +
+ "Bound mismatch: The type T is not a valid substitute for the bounded parameter <E extends Key<E>> of the type Key<E>\n" +
+ "----------\n");
+}
+public void test697() {
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "import java.util.List;\n" +
+ "public class X<U, V extends List<U>> {\n" +
+ " V v;\n" +
+ " \n" +
+ " void foo(X<String, ?> x1, X<Object, ?> x2) {\n" +
+ " String s =x1.v.get(0);\n" +
+ " Object o = x2.v.get(0);\n" +
+ " \n" +
+ " }\n" +
+ "}\n",
+ },
+ "");
+}
+public void test698() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.util.List;\n" +
+ "\n" +
+ "public class X<U extends List<Object>, V extends List<String>> {\n" +
+ " \n" +
+ " X<? super Exception, ? super Exception> x;\n" +
+ "}\n",
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 5)\n" +
+ " X<? super Exception, ? super Exception> x;\n" +
+ " ^^^^^^^^^^^^^^^^^\n" +
+ "Bound mismatch: The type ? super Exception is not a valid substitute for the bounded parameter <U extends List<Object>> of the type X<U,V>\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 5)\n" +
+ " X<? super Exception, ? super Exception> x;\n" +
+ " ^^^^^^^^^^^^^^^^^\n" +
+ "Bound mismatch: The type ? super Exception is not a valid substitute for the bounded parameter <V extends List<String>> of the type X<U,V>\n" +
+ "----------\n");
+}
+public void test699() {
+ this.runNegativeTest(
+ new String[] {
+ "X2.java",
+ "import java.util.List;\n" +
+ "class Other2<T extends List< Runnable>> {\n" +
+ "}\n" +
+ "\n" +
+ "class X2 {\n" +
+ " Other2<? extends List<Throwable>> other1;\n" +
+ " Other2<? extends List<? super String>> other2; \n" +
+ " Other2<? extends List<? extends String>> other3; \n" +
+ " Other2<? extends List<? extends Runnable>> other7 = other1;\n" +
+ "}\n",
+ },
+ "----------\n" +
+ "1. ERROR in X2.java (at line 6)\n" +
+ " Other2<? extends List<Throwable>> other1;\n" +
+ " ^^^^^^^^^^^^^^\n" +
+ "Bound mismatch: The type ? extends List<Throwable> is not a valid substitute for the bounded parameter <T extends List<Runnable>> of the type Other2<T>\n" +
+ "----------\n" +
+ "2. ERROR in X2.java (at line 7)\n" +
+ " Other2<? extends List<? super String>> other2; \n" +
+ " ^^^^^^^^^^^^^^\n" +
+ "Bound mismatch: The type ? extends List<? super String> is not a valid substitute for the bounded parameter <T extends List<Runnable>> of the type Other2<T>\n" +
+ "----------\n" +
+ "3. ERROR in X2.java (at line 8)\n" +
+ " Other2<? extends List<? extends String>> other3; \n" +
+ " ^^^^^^^^^^^^^^\n" +
+ "Bound mismatch: The type ? extends List<? extends String> is not a valid substitute for the bounded parameter <T extends List<Runnable>> of the type Other2<T>\n" +
+ "----------\n");
+}
+//https://bugs.eclipse.org/bugs/show_bug.cgi?id=96646
+public void test700() {
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "abstract class BaseFactory<T> {\n" +
+ " public T create() throws Exception {\n" +
+ " return getType().newInstance();\n" +
+ " }\n" +
+ " public abstract Class<T> getType();\n" +
+ "}\n" +
+ "interface StringFactory {\n" +
+ " public String create() throws Exception;\n" +
+ "}\n" +
+ "class X extends BaseFactory<String> implements StringFactory {\n" +
+ " @Override\n" +
+ " public Class<String> getType() {\n" +
+ " return String.class;\n" +
+ " }\n" +
+ " public static void main(String[] args) throws Exception {\n" +
+ " String emptyString = new X().create();\n" +
+ " System.out.printf(\"We have \'%s\' of type %s\", emptyString, emptyString.getClass());\n" +
+ " }\n" +
+ "}\n",
+ },
+ "----------\n" +
+ "1. ERROR in X2.java (at line 6)\n" +
+ " Other2<? extends List<Throwable>> other1;\n" +
+ " ^^^^^^^^^^^^^^\n" +
+ "Bound mismatch: The type ? extends List<Throwable> is not a valid substitute for the bounded parameter <T extends List<Runnable>> of the type Other2<T>\n" +
+ "----------\n" +
+ "2. ERROR in X2.java (at line 7)\n" +
+ " Other2<? extends List<? super String>> other2; \n" +
+ " ^^^^^^^^^^^^^^\n" +
+ "Bound mismatch: The type ? extends List<? super String> is not a valid substitute for the bounded parameter <T extends List<Runnable>> of the type Other2<T>\n" +
+ "----------\n" +
+ "3. ERROR in X2.java (at line 8)\n" +
+ " Other2<? extends List<? extends String>> other3; \n" +
+ " ^^^^^^^^^^^^^^\n" +
+ "Bound mismatch: The type ? extends List<? extends String> is not a valid substitute for the bounded parameter <T extends List<Runnable>> of the type Other2<T>\n" +
+ "----------\n");
+}
}
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/messages.properties b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/messages.properties
index 802bbd0..6a7aa22 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/messages.properties
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/messages.properties
@@ -14,7 +14,7 @@
#Format: compiler.name = word1 word2 word3
compiler.name = Eclipse Java Compiler
#Format: compiler.version = 0.XXX[, other words (don't forget the comma if adding other words)]
-compiler.version = 0.558, pre-3.1.0 release candidate-1
+compiler.version = 0.559, pre-3.1.0 release candidate-1
compiler.copyright = Copyright IBM Corp 2000, 2005. All rights reserved.
### scanning
diff --git a/org.eclipse.jdt.core/buildnotes_jdt-core.html b/org.eclipse.jdt.core/buildnotes_jdt-core.html
index 4a980cf..85b1333 100644
--- a/org.eclipse.jdt.core/buildnotes_jdt-core.html
+++ b/org.eclipse.jdt.core/buildnotes_jdt-core.html
@@ -37,6 +37,23 @@
</tr>
</table>
+<a name="v_559"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes <br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.1RC1 - 26th May 2005
+<br>Project org.eclipse.jdt.core v_559
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_559">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=95638">95638</a>
+[1.5][compiler] Possibly incorrect Bounds Mismatch errors for complicated bounds
+
+
<a name="v_558"></a>
<p><hr><h1>
Eclipse Platform Build Notes <br>
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java
index 0975e58..c21d890 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java
@@ -40,7 +40,7 @@
public final static int Bit15 = 0x4000; // is unnecessary cast (expression)
public final static int Bit16 = 0x8000; // in javadoc comment (name ref, type ref, msg)
public final static int Bit17 = 0x10000; // compound assigned (reference lhs)
- public final static int Bit18 = 0x20000;
+ public final static int Bit18 = 0x20000;
public final static int Bit19 = 0x40000;
public final static int Bit20 = 0x80000;
public final static int Bit21 = 0x100000;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java
index 961ad86..ffaf552 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java
@@ -285,7 +285,7 @@
return false;
}
// recurse on array type elements
- return checkCastTypesCompatibility(scope, ((ArrayBinding) castType).elementsType(), exprElementType, expression);
+ return checkCastTypesCompatibility(scope, castElementType, exprElementType, expression);
case Binding.TYPE_PARAMETER :
// ( TYPE_PARAMETER ) ARRAY
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ParameterizedQualifiedTypeReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ParameterizedQualifiedTypeReference.java
index a2b82dc..e07835d 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ParameterizedQualifiedTypeReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ParameterizedQualifiedTypeReference.java
@@ -51,9 +51,7 @@
TypeVariableBinding[] typeVariables = currentType.typeVariables();
TypeBinding[] argTypes = parameterizedType.arguments;
if (argTypes != null && typeVariables != null) { // argTypes may be null in error cases
- for (int i = 0, argLength = typeVariables.length; i < argLength; i++)
- if (typeVariables[i].boundCheck(parameterizedType, argTypes[i]) != TypeConstants.OK)
- scope.problemReporter().typeMismatchError(argTypes[i], typeVariables[i], currentType, this.typeArguments[index][i]);
+ parameterizedType.boundCheck(scope, this.typeArguments[index]);
}
}
}
@@ -169,7 +167,6 @@
if (argHasError) {
return null;
}
-// TODO (philippe) if ((this.bits & ASTNode.IsSuperType) != 0)
if (isClassScope)
if (((ClassScope) scope).detectHierarchyCycle(currentType, this, argTypes))
return null;
@@ -204,13 +201,10 @@
ParameterizedTypeBinding parameterizedType = scope.createParameterizedType((ReferenceBinding)currentType.erasure(), argTypes, qualifiedType);
// check argument type compatibility
if (checkBounds) // otherwise will do it in Scope.connectTypeVariables() or generic method resolution
- for (int j = 0; j < argLength; j++)
- if (typeVariables[j].boundCheck(parameterizedType, argTypes[j]) != TypeConstants.OK)
- scope.problemReporter().typeMismatchError(argTypes[j], typeVariables[j], currentType, args[j]);
+ parameterizedType.boundCheck(scope, args);
qualifiedType = parameterizedType;
}
} else {
-// TODO (philippe) if ((this.bits & ASTNode.IsSuperType) != 0)
if (isClassScope)
if (((ClassScope) scope).detectHierarchyCycle(currentType, this, null))
return null;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ParameterizedSingleTypeReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ParameterizedSingleTypeReference.java
index 587c70a..9d45cc6 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ParameterizedSingleTypeReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ParameterizedSingleTypeReference.java
@@ -37,9 +37,7 @@
TypeVariableBinding[] typeVariables = currentType.typeVariables();
TypeBinding[] argTypes = parameterizedType.arguments;
if (argTypes != null && typeVariables != null) { // may be null in error cases
- for (int i = 0, argLength = typeVariables.length; i < argLength; i++)
- if (typeVariables[i].boundCheck(parameterizedType, argTypes[i]) != TypeConstants.OK)
- scope.problemReporter().typeMismatchError(argTypes[i], typeVariables[i], currentType, this.typeArguments[i]);
+ parameterizedType.boundCheck(scope, this.typeArguments);
}
}
}
@@ -140,7 +138,6 @@
}
}
if (argHasError) return null;
-// TODO (philippe) if ((this.bits & ASTNode.IsSuperType) != 0)
if (isClassScope)
if (((ClassScope) scope).detectHierarchyCycle(currentType, this, argTypes))
return null;
@@ -166,9 +163,7 @@
ParameterizedTypeBinding parameterizedType = scope.createParameterizedType((ReferenceBinding)currentType.erasure(), argTypes, enclosingType);
// check argument type compatibility
if (checkBounds) // otherwise will do it in Scope.connectTypeVariables() or generic method resolution
- for (int i = 0; i < argLength; i++)
- if (typeVariables[i].boundCheck(parameterizedType, argTypes[i]) != TypeConstants.OK)
- scope.problemReporter().typeMismatchError(argTypes[i], typeVariables[i], currentType, this.typeArguments[i]);
+ parameterizedType.boundCheck(scope, this.typeArguments);
this.resolvedType = parameterizedType;
if (isTypeUseDeprecated(this.resolvedType, scope))
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CaptureBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CaptureBinding.java
index ab59261..8e160e9 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CaptureBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CaptureBinding.java
@@ -69,7 +69,7 @@
* Initialize capture bounds using substituted supertypes
* e.g. given X<U, V extends X<U, V>>, capture(X<E,?>) = X<E,capture>, where capture extends X<E,capture>
*/
- public void initializeBounds(ParameterizedTypeBinding capturedParameterizedType) {
+ public void initializeBounds1(ParameterizedTypeBinding capturedParameterizedType) {
TypeVariableBinding wildcardVariable = wildcard.typeVariable();
ReferenceBinding originalWildcardSuperclass = wildcard.superclass();
// prevent cyclic capture: given X<T>, capture(X<? extends T> could yield a circular type
@@ -108,6 +108,59 @@
break;
}
}
+ /**
+ * Initialize capture bounds using substituted supertypes
+ * e.g. given X<U, V extends X<U, V>>, capture(X<E,?>) = X<E,capture>, where capture extends X<E,capture>
+ */
+ public void initializeBounds(ParameterizedTypeBinding capturedParameterizedType) {
+ TypeVariableBinding wildcardVariable = wildcard.typeVariable();
+ ReferenceBinding originalVariableSuperclass = wildcardVariable.superclass;
+ // prevent cyclic capture: given X<T>, capture(X<? extends T> could yield a circular type
+ ReferenceBinding substitutedVariableSuperclass = originalVariableSuperclass.isTypeVariable() ? originalVariableSuperclass : (ReferenceBinding) Scope.substitute(capturedParameterizedType, originalVariableSuperclass);
+ ReferenceBinding[] substitutedVariableInterfaces = Scope.substitute(capturedParameterizedType, wildcardVariable.superInterfaces());
+
+ switch (wildcard.boundKind) {
+ case Wildcard.EXTENDS :
+ if (wildcard.bound.isInterface()) {
+ this.superclass = substitutedVariableSuperclass;
+ // merge wildcard bound into variable superinterfaces using glb
+ if (substitutedVariableInterfaces == NoSuperInterfaces) {
+ this.superInterfaces = new ReferenceBinding[] { (ReferenceBinding) wildcard.bound };
+ } else {
+ int length = substitutedVariableInterfaces.length;
+ System.arraycopy(substitutedVariableInterfaces, 0, substitutedVariableInterfaces = new ReferenceBinding[length+1], 1, length);
+ substitutedVariableInterfaces[0] = (ReferenceBinding) wildcard.bound;
+ this.superInterfaces = Scope.greaterLowerBound(substitutedVariableInterfaces);
+ }
+ } else {
+ // per construction the wildcard bound is a subtype of variable superclass
+ this.superclass = wildcard.bound.isArrayType() ? substitutedVariableSuperclass : (ReferenceBinding)wildcard.bound;
+ this.superInterfaces = substitutedVariableInterfaces;
+ }
+ TypeBinding substitutedWildcardBound = Scope.substitute(capturedParameterizedType, wildcard.bound);
+ this.firstBound = substitutedWildcardBound;
+ if ((substitutedWildcardBound.tagBits & HasTypeVariable) == 0)
+ this.tagBits &= ~HasTypeVariable;
+ break;
+ case Wildcard.UNBOUND :
+ this.superclass = substitutedVariableSuperclass;
+ this.superInterfaces = substitutedVariableInterfaces;
+ this.tagBits &= ~HasTypeVariable;
+ break;
+ case Wildcard.SUPER :
+ this.superclass = substitutedVariableSuperclass;
+ substitutedWildcardBound = Scope.substitute(capturedParameterizedType, wildcard.bound);
+ if (wildcardVariable.firstBound == this.superclass
+ || substitutedWildcardBound == this.superclass) {
+ this.firstBound = this.superclass;
+ }
+ this.superInterfaces = substitutedVariableInterfaces;
+ this.lowerBound = substitutedWildcardBound;
+ if ((substitutedWildcardBound.tagBits & HasTypeVariable) == 0)
+ this.tagBits &= ~HasTypeVariable;
+ break;
+ }
+ }
/**
* @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#isCapture()
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java
index 937b1b9..cb65adf 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java
@@ -12,6 +12,7 @@
import java.util.Map;
import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.ast.Wildcard;
/**
@@ -47,6 +48,25 @@
}
/**
+ * Iterate type arguments, and validate them according to corresponding variable bounds.
+ */
+ public void boundCheck(Scope scope, TypeReference[] argumentReferences) {
+ if ((this.tagBits & PassedBoundCheck) == 0) {
+ boolean hasErrors = false;
+ TypeVariableBinding[] typeVariables = this.type.typeVariables();
+ if (this.arguments != null && typeVariables != null) { // arguments may be null in error cases
+ for (int i = 0, length = typeVariables.length; i < length; i++) {
+ if (typeVariables[i].boundCheck(this, this.arguments[i]) != TypeConstants.OK) {
+ hasErrors = true;
+ scope.problemReporter().typeMismatchError(this.arguments[i], typeVariables[i], this.type, argumentReferences[i]);
+ }
+ }
+ }
+ if (!hasErrors) this.tagBits |= PassedBoundCheck; // no need to recheck it in the future
+ }
+ }
+
+ /**
* @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#canBeInstantiated()
*/
public boolean canBeInstantiated() {
@@ -63,9 +83,10 @@
if ((this.tagBits & TagBits.HasDirectWildcard) == 0)
return this;
- TypeBinding[] originalArguments = arguments, capturedArguments = originalArguments;
+ TypeBinding[] originalArguments = arguments;
int length = originalArguments.length;
- capturedArguments = new TypeBinding[length];
+ TypeBinding[] capturedArguments = new TypeBinding[length];
+
for (int i = 0; i < length; i++) {
TypeBinding argument = originalArguments[i];
if (argument.kind() == Binding.WILDCARD_TYPE) {
@@ -78,17 +99,14 @@
capturedArguments[i] = argument;
}
}
- if (capturedArguments != originalArguments) {
- ParameterizedTypeBinding capturedParameterizedType = this.environment.createParameterizedType(this.type, capturedArguments, enclosingType());
- for (int i = 0; i < length; i++) {
- TypeBinding argument = capturedArguments[i];
- if (argument.isCapture()) {
- ((CaptureBinding)argument).initializeBounds(capturedParameterizedType);
- }
+ ParameterizedTypeBinding capturedParameterizedType = this.environment.createParameterizedType(this.type, capturedArguments, enclosingType());
+ for (int i = 0; i < length; i++) {
+ TypeBinding argument = capturedArguments[i];
+ if (argument.isCapture()) {
+ ((CaptureBinding)argument).initializeBounds(capturedParameterizedType);
}
- return capturedParameterizedType;
}
- return this;
+ return capturedParameterizedType;
}
/**
* Collect the substitutes into a map for certain type variables inside the receiver type
@@ -588,6 +606,48 @@
return false;
}
+ public boolean isIntersectingWith(TypeBinding otherType) {
+ if (this == otherType)
+ return true;
+ if (otherType == null)
+ return false;
+ switch(otherType.kind()) {
+
+ case Binding.PARAMETERIZED_TYPE :
+ if ((this.tagBits & HasDirectWildcard) == 0 && (otherType.tagBits & HasDirectWildcard) == 0 && (!this.isMemberType() || !otherType.isMemberType()))
+ return false; // should have been identical
+ ParameterizedTypeBinding otherParamType = (ParameterizedTypeBinding) otherType;
+ if (this.type != otherParamType.type)
+ return false;
+ if (!isStatic()) { // static member types do not compare their enclosing
+ ReferenceBinding enclosing = enclosingType();
+ if (enclosing != null) {
+ ReferenceBinding otherEnclosing = otherParamType.enclosingType();
+ if (otherEnclosing == null) return false;
+ if ((otherEnclosing.tagBits & HasDirectWildcard) == 0) {
+ if (enclosing != otherEnclosing) return false;
+ } else {
+ if (!enclosing.isEquivalentTo(otherParamType.enclosingType())) return false;
+ }
+ }
+ }
+ int length = this.arguments == null ? 0 : this.arguments.length;
+ TypeBinding[] otherArguments = otherParamType.arguments;
+ int otherLength = otherArguments == null ? 0 : otherArguments.length;
+ if (otherLength != length)
+ return false;
+ for (int i = 0; i < length; i++) {
+ if (!this.arguments[i].isTypeArgumentIntersecting(otherArguments[i]))
+ return false;
+ }
+ return true;
+
+ case Binding.RAW_TYPE :
+ return erasure() == otherType.erasure();
+ }
+ return false;
+ }
+
/**
* @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#isParameterizedType()
*/
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/RawTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/RawTypeBinding.java
index bb8dfdc..e41ac49 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/RawTypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/RawTypeBinding.java
@@ -109,6 +109,22 @@
}
return false;
}
+
+ public boolean isIntersectingWith(TypeBinding otherType) {
+ if (this == otherType)
+ return true;
+ if (otherType == null)
+ return false;
+ switch(otherType.kind()) {
+
+ case Binding.GENERIC_TYPE :
+ case Binding.PARAMETERIZED_TYPE :
+ case Binding.RAW_TYPE :
+ return erasure() == otherType.erasure();
+ }
+ return false;
+ }
+
/**
* Raw type is not treated as a standard parameterized type
* @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#isParameterizedType()
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TagBits.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TagBits.java
index d525014..16525e5 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TagBits.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TagBits.java
@@ -47,6 +47,9 @@
// test bit to identify if the type's hierarchy is inconsistent
long HierarchyHasProblems = ASTNode.Bit16;
+ // set for parameterized type with successfull bound check
+ long PassedBoundCheck = ASTNode.Bit23;
+
// set for parameterized type NOT of the form X<?,?>
long IsBoundParameterizedType = ASTNode.Bit24;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBinding.java
index 8d4fcf5..e9d7bc6 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBinding.java
@@ -191,6 +191,12 @@
public boolean isInterface() {
return false;
}
+/**
+ * Returns true if a type is intersecting with another one,
+ */
+public boolean isIntersectingWith(TypeBinding otherType) {
+ return this == otherType;
+}
public final boolean isLocalType() {
return (tagBits & IsLocalType) != 0;
}
@@ -321,11 +327,11 @@
lowerBound = null;
break;
case Wildcard. SUPER :
- upperBound = wildcard.typeVariable();
+ upperBound = wildcard;
lowerBound = wildcard.bound;
break;
case Wildcard.UNBOUND :
- upperBound = wildcard.typeVariable();
+ upperBound = wildcard;
lowerBound = null;
}
}
@@ -334,9 +340,11 @@
if (otherWildcard.otherBounds != null) return false; // not a true wildcard (intersection type)
switch(otherWildcard.boundKind) {
case Wildcard.EXTENDS:
+ if (otherWildcard.bound == this) return true; // ? extends T <= ? extends ? extends T
return upperBound != null && upperBound.isCompatibleWith(otherWildcard.bound);
case Wildcard.SUPER :
+ if (otherWildcard.bound == this) return true; // ? super T <= ? super ? super T
return lowerBound != null && otherWildcard.bound.isCompatibleWith(lowerBound);
case Wildcard.UNBOUND :
@@ -347,6 +355,101 @@
}
/**
+ * Returns false if two given types could not intersect as argument types:
+ * List<Throwable> & List<Runnable> --> false
+ * List<? extends Throwable> & List<? extends Runnable> --> true
+ * List<? extends String> & List<? extends Runnable> --> false
+ */
+public boolean isTypeArgumentIntersecting(TypeBinding otherArgument) {
+ if (this == otherArgument)
+ return true;
+ if (this.isTypeVariable() || otherArgument.isTypeVariable())
+ return true;
+ if (this.isWildcard()) {
+ if (!otherArgument.isWildcard()) {
+ WildcardBinding wildcard = (WildcardBinding) this;
+ switch(wildcard.boundKind) {
+ case Wildcard.EXTENDS :
+ return otherArgument.isCompatibleWith(wildcard.bound);
+ case Wildcard. SUPER :
+ return wildcard.bound.isCompatibleWith(otherArgument);
+ case Wildcard.UNBOUND :
+ default:
+ return true;
+ }
+ }
+ } else if (otherArgument.isWildcard()) {
+ WildcardBinding otherWildcard = (WildcardBinding) otherArgument;
+ switch(otherWildcard.boundKind) {
+ case Wildcard.EXTENDS :
+ return this.isCompatibleWith(otherWildcard.bound);
+ case Wildcard. SUPER :
+ return otherWildcard.bound.isCompatibleWith(this);
+ case Wildcard.UNBOUND :
+ default:
+ return true;
+ }
+ }
+ TypeBinding lowerBound1 = null;
+ TypeBinding upperBound1 = null;
+ WildcardBinding wildcard = (WildcardBinding) this;
+ switch(wildcard.boundKind) {
+ case Wildcard.EXTENDS :
+ upperBound1 = wildcard.bound;
+ break;
+ case Wildcard. SUPER :
+ lowerBound1 = wildcard.bound;
+ break;
+ case Wildcard.UNBOUND :
+ }
+
+ TypeBinding lowerBound2 = null;
+ TypeBinding upperBound2 = null;
+ WildcardBinding otherWildcard = (WildcardBinding) otherArgument;
+ switch(otherWildcard.boundKind) {
+ case Wildcard.EXTENDS :
+ upperBound2 = otherWildcard.bound;
+ break;
+ case Wildcard. SUPER :
+ lowerBound2 = otherWildcard.bound;
+ break;
+ case Wildcard.UNBOUND :
+ }
+ if (lowerBound1 != null) {
+ if (lowerBound2 != null) {
+ return true; // Object could always be a candidate
+
+ } else if (upperBound2 != null) {
+ return lowerBound1.isCompatibleWith(upperBound2);
+ } else {
+ return true;
+ }
+ } else if (upperBound1 != null) {
+ if (lowerBound2 != null) {
+ return lowerBound2.isCompatibleWith(upperBound1);
+
+ } else if (upperBound2 != null) {
+ if (upperBound1.isInterface()) {
+ if (upperBound2.isInterface())
+ return true;
+ if (upperBound2.isArrayType() || ((upperBound2 instanceof ReferenceBinding) && ((ReferenceBinding)upperBound2).isFinal())) {
+ return upperBound2.isCompatibleWith(upperBound1);
+ }
+ return true;
+ } else if (upperBound2.isInterface()) {
+ if (upperBound1.isArrayType() || ((upperBound1 instanceof ReferenceBinding) && ((ReferenceBinding)upperBound1).isFinal())) {
+ return upperBound1.isCompatibleWith(upperBound2);
+ }
+ }
+ return true;
+ } else {
+ return true;
+ }
+ } else {
+ return true;
+ }
+}
+/**
* Returns true if the type was declared as a type variable
*/
public boolean isTypeVariable() {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java
index 9190c16..d64fa65 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java
@@ -56,19 +56,58 @@
if (!(argumentType instanceof ReferenceBinding || argumentType.isArrayType()))
return TypeConstants.MISMATCH;
- if (argumentType.isWildcard()) {
- WildcardBinding wildcard = (WildcardBinding) argumentType;
- switch (wildcard.boundKind) {
- case Wildcard.SUPER :
-// if (boundCheck(substitution, wildcard.bound) != TypeConstants.OK) return TypeConstants.MISMATCH;
-// break;
- return boundCheck(substitution, wildcard.bound); // only check the lower bound
+ if (argumentType.isWildcard()) {
+ WildcardBinding wildcard = (WildcardBinding) argumentType;
+ switch(wildcard.boundKind) {
+ case Wildcard.EXTENDS :
+ ReferenceBinding superclassBound = (ReferenceBinding)Scope.substitute(substitution, this.superclass());
+ TypeBinding wildcardBound = wildcard.bound;
+ boolean isArrayBound = wildcardBound.isArrayType();
+ if (!wildcardBound.isInterface()) {
+ if (isArrayBound) {
+ if (!wildcardBound.isCompatibleWith(superclassBound))
+ return TypeConstants.MISMATCH;
+ } else {
+ ReferenceBinding match = ((ReferenceBinding)wildcardBound).findSuperTypeErasingTo((ReferenceBinding)superclassBound.erasure());
+ if (match != null) {
+ if (!match.isIntersectingWith(superclassBound)) {
+ return TypeConstants.MISMATCH;
+ }
+ } else {
+ return TypeConstants.MISMATCH;
+ }
+ }
+ }
+ ReferenceBinding[] superInterfaceBounds = Scope.substitute(substitution, this.superInterfaces());
+ int length = superInterfaceBounds.length;
+ boolean mustImplement = isArrayBound || ((ReferenceBinding)wildcardBound).isFinal();
+ for (int i = 0; i < length; i++) {
+ TypeBinding superInterfaceBound = superInterfaceBounds[i];
+ if (isArrayBound) {
+ if (!wildcardBound.isCompatibleWith(superInterfaceBound))
+ return TypeConstants.MISMATCH;
+ } else {
+ ReferenceBinding match = ((ReferenceBinding)wildcardBound).findSuperTypeErasingTo((ReferenceBinding)superInterfaceBound.erasure());
+ if (match != null) {
+ if (!match.isIntersectingWith(superInterfaceBound)) {
+ return TypeConstants.MISMATCH;
+ }
+ } else if (mustImplement) {
+ return TypeConstants.MISMATCH; // cannot be extended further to satisfy missing bounds
+ }
+ }
+
+ }
+ break;
+
+ case Wildcard.SUPER :
+ return boundCheck(substitution, wildcard.bound);
+
case Wildcard.UNBOUND :
- if (this == wildcard.typeVariable())
- return TypeConstants.OK;
- break;
- }
- }
+ break;
+ }
+ return TypeConstants.OK;
+ }
boolean unchecked = false;
if (this.superclass.id != T_JavaLangObject) {
TypeBinding substitutedSuperType = hasSubstitution ? Scope.substitute(substitution, this.superclass) : this.superclass;
@@ -83,7 +122,7 @@
if (match.isRawType() && (substitutedSuperType.isGenericType()||substitutedSuperType.isBoundParameterizedType()))
unchecked = true;
}
- }
+ }
}
for (int i = 0, length = this.superInterfaces.length; i < length; i++) {
TypeBinding substitutedSuperType = hasSubstitution ? Scope.substitute(substitution, this.superInterfaces[i]) : this.superInterfaces[i];
@@ -326,13 +365,7 @@
}
return false;
}
- /**
- * Returns true if the type was declared as a type variable
- */
- public boolean isTypeVariable() {
- return true;
- }
-
+
/**
* Returns true if the 2 variables are playing exact same role: they have
* the same bounds, providing one is substituted with the other: <T1 extends
@@ -375,6 +408,13 @@
return false;
return true;
}
+
+ /**
+ * Returns true if the type was declared as a type variable
+ */
+ public boolean isTypeVariable() {
+ return true;
+ }
/**
* Returns the original type variable for a given variable.
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/WildcardBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/WildcardBinding.java
index 97e0a6d..ed0d3e2 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/WildcardBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/WildcardBinding.java
@@ -80,6 +80,7 @@
// cannot be asked per construction
return false;
}
+
/**
* Collect the substitutes into a map for certain type variables inside the receiver type
* e.g. Collection<T>.collectSubstitutes(Collection<List<X>>, Map), will populate Map with: T --> List<X>
@@ -347,7 +348,7 @@
}
return false;
}
-
+
/**
* Returns true if the type is a wildcard
*/
@@ -460,7 +461,7 @@
/* (non-Javadoc)
* @see org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding#superclass()
*/
- public ReferenceBinding superclass() {
+ public ReferenceBinding superclass1() {
if (this.superclass == null) {
TypeBinding superType = null;
if (this.boundKind == Wildcard.EXTENDS && !this.bound.isInterface()) {
@@ -476,10 +477,34 @@
return this.superclass;
}
+
+ public ReferenceBinding superclass() {
+ if (this.superclass == null) {
+ TypeBinding superType = (this.boundKind == Wildcard.EXTENDS && !this.bound.isInterface())
+ ? this.bound
+ : null;
+ this.superclass = superType instanceof ReferenceBinding && !superType.isInterface()
+ ? (ReferenceBinding) superType
+ : environment.getType(JAVA_LANG_OBJECT);
+
+// TypeBinding superType = null;
+// if (this.boundKind == Wildcard.EXTENDS && !this.bound.isInterface()) {
+// superType = this.bound;
+// } else {
+// TypeVariableBinding variable = this.typeVariable();
+// if (variable != null) superType = variable.firstBound;
+// }
+// this.superclass = superType instanceof ReferenceBinding && !superType.isInterface()
+// ? (ReferenceBinding) superType
+// : environment.getType(JAVA_LANG_OBJECT);
+ }
+
+ return this.superclass;
+ }
/* (non-Javadoc)
* @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#superInterfaces()
*/
- public ReferenceBinding[] superInterfaces() {
+ public ReferenceBinding[] superInterfaces1() {
if (this.superInterfaces == null) {
if (this.typeVariable() != null) {
this.superInterfaces = this.typeVariable.superInterfaces();
@@ -507,6 +532,31 @@
return this.superInterfaces;
}
+ public ReferenceBinding[] superInterfaces() {
+ if (this.superInterfaces == null) {
+ if (this.boundKind == Wildcard.EXTENDS) {
+ if (this.bound.isInterface()) {
+ if (this.otherBounds != null) {
+ // augment super interfaces with the wildcard otherBounds (interfaces per construction)
+ int otherLength = this.otherBounds.length;
+ System.arraycopy(this.otherBounds, 0, this.superInterfaces = new ReferenceBinding[otherLength+1], 1, otherLength);
+ this.superInterfaces[0] = (ReferenceBinding) this.bound;
+ } else {
+ this.superInterfaces = new ReferenceBinding[] { (ReferenceBinding) this.bound };
+ }
+ } else if (this.otherBounds != null) {
+ int otherLength = this.otherBounds.length;
+ System.arraycopy(this.otherBounds, 0, this.superInterfaces = new ReferenceBinding[otherLength], 0, otherLength);
+ } else {
+ this.superInterfaces = NoSuperInterfaces;
+ }
+ } else {
+ this.superInterfaces = NoSuperInterfaces;
+ }
+ }
+ return this.superInterfaces;
+ }
+
public void swapUnresolved(UnresolvedReferenceBinding unresolvedType, ReferenceBinding resolvedType, LookupEnvironment env) {
boolean affected = false;
if (this.genericType == unresolvedType) {