### Eclipse Workspace Patch 1.0 #P org.eclipse.jdt.core.tests.compiler Index: src/org/eclipse/jdt/core/tests/compiler/regression/MethodVerifyTest.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/MethodVerifyTest.java,v retrieving revision 1.121 diff -u -r1.121 MethodVerifyTest.java --- src/org/eclipse/jdt/core/tests/compiler/regression/MethodVerifyTest.java 28 Mar 2007 04:52:16 -0000 1.121 +++ src/org/eclipse/jdt/core/tests/compiler/regression/MethodVerifyTest.java 20 Apr 2007 11:18:24 -0000 @@ -5302,18 +5302,16 @@ // warning: create() in HashOrder overrides create() in DoubleHash; return type requires unchecked conversion ); } - //https://bugs.eclipse.org/bugs/show_bug.cgi?id=125956 - public void test081() { + // https://bugs.eclipse.org/bugs/show_bug.cgi?id=125956 + public void test081a() { this.runNegativeTest( new String[] { "X.java", "public abstract class X implements I {\n" + " public A foo() { return null; }\n" + - " public A bar() { return null; }\n" + "}\n" + "interface I {\n" + " A foo();\n" + - " A bar();\n" + "}\n" + "class A {}" }, @@ -5322,14 +5320,28 @@ " public A foo() { return null; }\r\n" + " ^\n" + "Type safety: The return type A for foo() from the type X needs unchecked conversion to conform to A from the type I\n" + + "----------\n" + ); + } + // https://bugs.eclipse.org/bugs/show_bug.cgi?id=125956 + public void test081b() { + this.runNegativeTest( + new String[] { + "X.java", + "public abstract class X implements I {\n" + + " public A bar() { return null; }\n" + + "}\n" + + "interface I {\n" + + " A bar();\n" + + "}\n" + + "class A {}" + }, "----------\n" + - "2. ERROR in X.java (at line 3)\r\n" + + "1. ERROR in X.java (at line 2)\r\n" + " public A bar() { return null; }\r\n" + " ^^^^\n" + "The return type is incompatible with I.bar()\n" + "----------\n" - // bar() in X cannot implement bar() in I; attempting to use incompatible return type - // warning: foo() in X implements foo() in I; return type requires unchecked conversion ); } //https://bugs.eclipse.org/bugs/show_bug.cgi?id=105339 @@ -7544,4 +7556,368 @@ "Type safety: The return type Enum for foo() from the type X.B needs unchecked conversion to conform to U from the type X.A\n" + "----------\n"); } +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=180789 +public void test128() { + this.runNegativeTest( + new String[] { + "X.java", + "interface I {\n" + + " U foo(Object o, V v);\n" + + "}\n" + + "public class X implements I {\n" + + " public Object foo(Object o, Object v) {\n" + + " return null;\n" + + " }\n" + + "}\n" + }, + "----------\n" + + "1. WARNING in X.java (at line 5)\n" + + " public Object foo(Object o, Object v) {\n" + + " ^^^^^^\n" + + "Type safety: The return type Object for foo(Object, Object) from the type X needs unchecked conversion to conform to U from the type I\n" + + "----------\n"); +} +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=180789 +// variant - Object is not a subtype of Z +public void test129() { + this.runNegativeTest( + new String[] { + "X.java", + "interface I {\n" + + " U foo(Object o, V v);\n" + + "}\n" + + "public class X implements I {\n" + + " public Object foo(Object o, Object v) {\n" + + " return null;\n" + + " }\n" + + "}\n" + + "class Z {\n" + + "}\n" + }, + "----------\n" + + "1. ERROR in X.java (at line 5)\n" + + " public Object foo(Object o, Object v) {\n" + + " ^^^^^^\n" + + "The return type is incompatible with I.foo(Object, V)\n" + + "----------\n"); +} +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=180789 +// ** variant - Z is not a subtype of Z, and |Z| = Z, not Z +public void test130() { + this.runNegativeTest( + new String[] { + "X.java", + "interface I {\n" + + " Z foo(Object o, V v);\n" + + "}\n" + + "public class X implements I {\n" + + " public Z foo(Object o, Object v) {\n" + + " return null;\n" + + " }\n" + + "}\n" + + "class Z {\n" + + "}" + }, + "----------\n" + + "1. ERROR in X.java (at line 5)\n" + + " public Z foo(Object o, Object v) {\n" + + " ^^^^^^^^^\n" + + "The return type is incompatible with I.foo(Object, V)\n" + + "----------\n"); +} +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=180789 +// variant - two interfaces +public void test131() { + this.runNegativeTest( + new String[] { + "X.java", + "interface I {\n" + + " U foo(Object o, V v);\n" + + "}\n" + + "interface X extends I {\n" + + " Object foo(Object o, Object v);\n" + + "}\n" + }, + "----------\n" + + "1. WARNING in X.java (at line 5)\n" + + " Object foo(Object o, Object v);\n" + + " ^^^^^^\n" + + "Type safety: The return type Object for foo(Object, Object) from the type X needs unchecked conversion to conform to U from the type I\n" + + "----------\n"); +} +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=180789 +// variant - simpler test case +public void test132() { + this.runNegativeTest( + new String[] { + "X.java", + "interface I {\n" + + " U foo();\n" + + "}\n" + + "public class X implements I {\n" + + " public Object foo() {\n" + + " return null;\n" + + " }\n" + + "}\n" + }, + "----------\n" + + "1. ERROR in X.java (at line 5)\n" + + " public Object foo() {\n" + + " ^^^^^^\n" + + "The return type is incompatible with I.foo()\n" + + "----------\n"); +} +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=180789 +// variant +public void test133() { + this.runNegativeTest( + new String[] { + "X.java", + "public class X {\n" + + " U foo() {\n" + + " return null;\n" + + " }\n" + + "}\n" + + "class Y extends X {\n" + + " public Z foo() {\n" + + " return null;\n" + + " }\n" + + "}\n" + + "class Z {\n" + + "}" + }, + "----------\n" + + "1. ERROR in X.java (at line 7)\n" + + " public Z foo() {\n" + + " ^\n" + + "The return type is incompatible with X.foo()\n" + + "----------\n" + + "2. WARNING in X.java (at line 7)\n" + + " public Z foo() {\n" + + " ^^^^^\n" + + "The method foo() of type Y should be tagged with @Override since it actually overrides a superclass method\n" + + "----------\n"); +} +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=180789 +// variant - unchecked conversion of ZC to ZC that is a subtype of Z +public void test134() { + this.runNegativeTest( + new String[] { + "X.java", + "public class X {\n" + + " Z foo() {\n" + + " return null;\n" + + " }\n" + + "}\n" + + "class Y extends X {\n" + + " public ZC foo() {\n" + + " return null;\n" + + " }\n" + + "}\n" + + "class Z {\n" + + "}\n" + + "class ZC extends Z {\n" + + "}" + }, + "----------\n" + + "1. WARNING in X.java (at line 7)\n" + + " public ZC foo() {\n" + + " ^^\n" + + "ZC is a raw type. References to generic type ZC should be parameterized\n" + + "----------\n" + + "2. WARNING in X.java (at line 7)\n" + + " public ZC foo() {\n" + + " ^^\n" + + "Type safety: The return type ZC for foo() from the type Y needs unchecked conversion to conform to Z from the type X\n" + + "----------\n" + + "3. WARNING in X.java (at line 7)\n" + + " public ZC foo() {\n" + + " ^^^^^\n" + + "The method foo() of type Y should be tagged with @Override since it actually overrides a superclass method\n" + + "----------\n"); +} +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=180789 +// variant - cast is not appropriate +public void test135() { + this.runNegativeTest( + new String[] { + "X.java", + "interface I {\n" + + " U foo(Object o, V v);\n" + + "}\n" + + "interface J extends I {\n" + + " Object foo(Object o, V v);\n" + + "}\n" + + "class X {\n" + + " J m1;\n" + + " I m2 = (I) m1;\n" + + "}" + }, + "----------\n" + + "1. ERROR in X.java (at line 5)\n" + + " Object foo(Object o, V v);\n" + + " ^^^^^^\n" + + "The return type is incompatible with I.foo(Object, V)\n" + + "----------\n" + + "2. WARNING in X.java (at line 9)\n" + + " I m2 = (I) m1;\n" + + " ^^^^^^^^^^^^^^^^^^^^^^^^\n" + + "Unnecessary cast from J to I\n" + + "----------\n"); +} +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=180789 +// variant - type identity vs type equivalence +public void test136() { + this.runNegativeTest( + new String[] { + "X.java", + "interface I {\n" + + " U foo(I p);\n" + + "}\n" + + "public class X implements I {\n" + + " public Object foo(I p) {\n" + + " return null;\n" + + " }\n" + + "}\n" + }, + "----------\n" + + "1. ERROR in X.java (at line 5)\n" + + " public Object foo(I p) {\n" + + " ^^^^^^\n" + + "The return type is incompatible with I.foo(I)\n" + + "----------\n"); +} +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=180789 +// variant - type identity vs type equivalence +public void test137() { + this.runNegativeTest( + new String[] { + "X.java", + "interface I {\n" + + " U foo(I p);\n" + + "}\n" + + "public class X implements I {\n" + + " public Object foo(I p) {\n" + + " return null;\n" + + " }\n" + + "}\n" + }, + "----------\n" + + "1. ERROR in X.java (at line 5)\n" + + " public Object foo(I p) {\n" + + " ^^^^^^\n" + + "The return type is incompatible with I.foo(I)\n" + + "----------\n"); +} +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=180789 +// variant - @Override annotation +public void test138() { + this.runNegativeTest( + new String[] { + "X.java", + "public class X {\n" + + " U foo() { return null; }\n" + + "}\n" + + "class Y extends X {\n" + + " @Override // does not override error\n" + + " Object foo() { return null; } // cannot override foo(), incompatible return type error\n" + + "}" + }, + "----------\n" + + "1. ERROR in X.java (at line 6)\n" + + " Object foo() { return null; } // cannot override foo(), incompatible return type error\n" + + " ^^^^^^\n" + + "The return type is incompatible with X.foo()\n" + + "----------\n"); +}// https://bugs.eclipse.org/bugs/show_bug.cgi?id=180789 +// variant - @Override annotation +public void test139() { + this.runNegativeTest( + new String[] { + "X.java", + "public class X {\n" + + " U foo(U one) { return null; }\n" + + "}\n" + + "class Y extends X {\n" + + " @Override\n" + + " Object foo(Object one) { return null; } // unchecked conversion warning\n" + + "}" + }, + "----------\n" + + "1. WARNING in X.java (at line 6)\n" + + " Object foo(Object one) { return null; } // unchecked conversion warning\n" + + " ^^^^^^\n" + + "Type safety: The return type Object for foo(Object) from the type Y needs unchecked conversion to conform to U from the type X\n" + + "----------\n"); +} +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=180789 +// variant - @Override annotation +public void test140() { + this.runNegativeTest( + new String[] { + "X.java", + "public class X {\n" + + " U foo(U one, U two) { return null; }\n" + + "}\n" + + "class Y extends X {\n" + + " @Override // does not override error\n" + + " Object foo(Object one, U two) { return null; }\n" + + "}" + }, + "----------\n" + + "1. ERROR in X.java (at line 6)\n" + + " Object foo(Object one, U two) { return null; }\n" + + " ^^^^^^^^^^^^^^^^^^^^^^\n" + + "Name clash: The method foo(Object, U) of type Y has the same erasure as foo(U, U) of type X but does not override it\n" + + "----------\n" + + "2. ERROR in X.java (at line 6)\n" + + " Object foo(Object one, U two) { return null; }\n" + + " ^^^^^^^^^^^^^^^^^^^^^^\n" + + (complianceLevel.compareTo(COMPLIANCE_1_5) <= 0 ? + "The method foo(Object, U) of type Y must override a superclass method\n" : + "The method foo(Object, U) of type Y must override or implement a supertype method\n") + + "----------\n"); +} +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=180789 +// variant - @Override annotation +public void test141() { + this.runNegativeTest( + new String[] { + "X.java", + "public class X {\n" + + " U foo(U one) { return null; }\n" + + "}\n" + + "class Y extends X {\n" + + " @Override // does not override error\n" + + " Object foo(U one) { return null; } // cannot override foo(U), incompatible return type error\n" + + "}" + }, + "----------\n" + + "1. ERROR in X.java (at line 6)\n" + + " Object foo(U one) { return null; } // cannot override foo(U), incompatible return type error\n" + + " ^^^^^^\n" + + "The return type is incompatible with X.foo(U)\n" + + "----------\n"); +} +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=180789 +// variant - @Override annotation +public void test142() { + this.runNegativeTest( + new String[] { + "X.java", + "public class X {\n" + + " U foo(U one, U two) { return null; }\n" + + "}\n" + + "class Y extends X {\n" + + " @Override // does not override error\n" + + " Object foo(U one, U two) { return null; } // cannot override foo(U,U), incompatible return type error\n" + + "}" + }, + "----------\n" + + "1. ERROR in X.java (at line 6)\n" + + " Object foo(U one, U two) { return null; } // cannot override foo(U,U), incompatible return type error\n" + + " ^^^^^^\n" + + "The return type is incompatible with X.foo(U, U)\n" + + "----------\n"); +} } Index: src/org/eclipse/jdt/core/tests/compiler/regression/GenericTypeTest.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericTypeTest.java,v retrieving revision 1.611 diff -u -r1.611 GenericTypeTest.java --- src/org/eclipse/jdt/core/tests/compiler/regression/GenericTypeTest.java 13 Apr 2007 14:55:45 -0000 1.611 +++ src/org/eclipse/jdt/core/tests/compiler/regression/GenericTypeTest.java 20 Apr 2007 11:18:07 -0000 @@ -11170,7 +11170,7 @@ ^ */ } - public void test0384() { + public void test0384a() { this.runConformTest( new String[] { "X.java", @@ -11186,6 +11186,8 @@ "}\n" }, ""); + } + public void test0384b() { this.runNegativeTest( new String[] { "X.java", @@ -11210,7 +11212,6 @@ "The return type is incompatible with Y.foo2()\n" + "----------\n"); } - // https://bugs.eclipse.org/bugs/show_bug.cgi?id=77496 public void test0385() { this.runNegativeTest( #P org.eclipse.jdt.core Index: compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier15.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier15.java,v retrieving revision 1.74 diff -u -r1.74 MethodVerifier15.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier15.java 17 Apr 2007 14:34:08 -0000 1.74 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier15.java 20 Apr 2007 11:18:35 -0000 @@ -475,6 +475,27 @@ } } } +boolean checkReturnTypesCompatible(MethodBinding one, MethodBinding two) { + if (areReturnTypesCompatible(one, two)) { + return true; + } + // JLS 3 §8.4.5: more are accepted, with an unchecked conversion + // this case is handled by areReturnTypesCompatible0 + // if (one.returnType.isRawType() && one.returnType.findSuperTypeWithSameErasure(two.returnType) != null) { + // problemReporter(one).unsafeReturnTypeOverride(one, two, this.type); + // return true; + // } + if (one.returnType == two.returnType.erasure()) { + int parametersCount = one.parameters.length; + for (int i = 0; i < parametersCount; i++) { + if (! areTypesEqual(one.parameters[i], two.parameters[i])) { + problemReporter(one).unsafeReturnTypeOverride(one, two, this.type); + return true; + } + } + } + return false; +} void checkTypeVariableMethods(TypeParameter typeParameter) { char[][] methodSelectors = this.inheritedMethods.keyTable; nextSelector : for (int s = methodSelectors.length; --s >= 0;) { Index: compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier.java,v retrieving revision 1.83 diff -u -r1.83 MethodVerifier.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier.java 17 Apr 2007 14:34:09 -0000 1.83 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier.java 20 Apr 2007 11:18:32 -0000 @@ -163,7 +163,7 @@ currentMethod.modifiers |= ExtraCompilerModifiers.AccOverriding; } - if (!areReturnTypesCompatible(currentMethod, inheritedMethod)) + if (!checkReturnTypesCompatible(currentMethod, inheritedMethod)) if (reportIncompatibleReturnTypeError(currentMethod, inheritedMethod)) continue nextMethod; @@ -392,6 +392,9 @@ // non visible abstract methods cannot be overridden so the type must be defined abstract problemReporter().abstractMethodCannotBeOverridden(this.type, abstractMethod); } +boolean checkReturnTypesCompatible(MethodBinding one, MethodBinding two) { + return areReturnTypesCompatible(one, two); +} void computeInheritedMethods() { ReferenceBinding superclass = this.type.isInterface() ? this.type.scope.getJavaLangObject() // check interface methods against Object