### Eclipse Workspace Patch 1.0 #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 23 Apr 2007 06:50:08 -0000 @@ -769,6 +769,17 @@ return copy; } boolean reportIncompatibleReturnTypeError(MethodBinding currentMethod, MethodBinding inheritedMethod) { + // JLS 3 §8.4.5: more are accepted, with an unchecked conversion + if (currentMethod.returnType == inheritedMethod.returnType.erasure()) { + TypeBinding[] currentParams = currentMethod.parameters; + TypeBinding[] inheritedParams = inheritedMethod.parameters; + for (int i = 0, l = currentParams.length; i < l; i++) { + if (!areTypesEqual(currentParams[i], inheritedParams[i])) { + problemReporter(currentMethod).unsafeReturnTypeOverride(currentMethod, inheritedMethod, this.type); + return false; + } + } + } if (currentMethod.typeVariables == Binding.NO_TYPE_VARIABLES && inheritedMethod.original().typeVariables != Binding.NO_TYPE_VARIABLES && currentMethod.returnType.erasure().findSuperTypeWithSameErasure(inheritedMethod.returnType.erasure()) != null) { 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 23 Apr 2007 06:50:08 -0000 @@ -627,6 +627,16 @@ SimpleSet findSuperinterfaceCollisions(ReferenceBinding superclass, ReferenceBinding[] superInterfaces) { return null; // noop in 1.4 } +/** + * Return true and report an incompatibleReturnType error if currentMethod's + * return type is strictly incompatible with inheritedMethod's, else return + * false and report an unchecked conversion warning. Do not call when + * areReturnTypesCompatible(currentMethod, inheritedMethod) returns true. + * @param currentMethod the (potentially) inheriting method + * @param inheritedMethod the inherited method + * @return true if currentMethod's return type is strictly incompatible with + * inheritedMethod's + */ boolean reportIncompatibleReturnTypeError(MethodBinding currentMethod, MethodBinding inheritedMethod) { problemReporter(currentMethod).incompatibleReturnType(currentMethod, inheritedMethod); return true; #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 23 Apr 2007 06:50:19 -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.612 diff -u -r1.612 GenericTypeTest.java --- src/org/eclipse/jdt/core/tests/compiler/regression/GenericTypeTest.java 20 Apr 2007 23:30:56 -0000 1.612 +++ src/org/eclipse/jdt/core/tests/compiler/regression/GenericTypeTest.java 23 Apr 2007 06:50:17 -0000 @@ -11175,7 +11175,7 @@ ^ */ } - public void test0384() { + public void test0384a() { this.runConformTest( new String[] { "X.java", @@ -11191,6 +11191,8 @@ "}\n" }, ""); + } + public void test0384b() { this.runNegativeTest( new String[] { "X.java", @@ -11215,7 +11217,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(