/******************************************************************************* * Copyright (c) 2000, 2004 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/cpl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.core.tests.compiler.regression; import junit.framework.*; import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; public class MethodVerifyTest extends AbstractComparableTest { public MethodVerifyTest(String name) { super(name); } public static Test suite() { Test suite = buildTestSuite(testClass()); TESTS_COUNTERS.put(testClass().getName(), new Integer(suite.countTestCases())); return suite; } public static Class testClass() { return MethodVerifyTest.class; } public void test001() { this.runNegativeTest( new String[] { "Y.java", "public class Y extends X { public void foo(T t) {} }\n" + "class X { public void foo(U u) {} }\n" + "class A {}\n" }, "----------\n" + "1. ERROR in Y.java (at line 1)\r\n" + " public class Y extends X { public void foo(T t) {} }\r\n" + " ^^^^^^^^\n" + "Name clash: The method foo(T) of type Y has the same erasure as foo(U) of type X but does not override it\n" + "----------\n" // name clash: foo(T) in Y and foo(U) in X have the same erasure, yet neither overrides the other ); this.runNegativeTest( new String[] { "J.java", "public class J implements I { public void foo(T t) {} }\n" + "interface I { public void foo(U u); }\n" + "class A {}\n" }, "----------\n" + "1. ERROR in J.java (at line 1)\r\n" + " public class J implements I { public void foo(T t) {} }\r\n" + " ^\n" + "The type J must implement the inherited abstract method I.foo(A)\n" + "----------\n" + "2. ERROR in J.java (at line 1)\r\n" + " public class J implements I { public void foo(T t) {} }\r\n" + " ^^^^^^^^\n" + "Name clash: The method foo(T) of type J has the same erasure as foo(U) of type I but does not override it\n" + "----------\n" // J is not abstract and does not override abstract method foo(A) in I ); this.runNegativeTest( new String[] { "YY.java", "public class YY extends X { public void foo(T t) {} }\n" + "class X { public void foo(U u) {} }\n" }, "----------\n" + "1. ERROR in YY.java (at line 1)\r\n" + " public class YY extends X { public void foo(T t) {} }\r\n" + " ^^^^^^^^\n" + "Name clash: The method foo(T) of type YY has the same erasure as foo(U) of type X but does not override it\n" + "----------\n" // name clash: foo(T) in YY and foo(U) in X have the same erasure, yet neither overrides the other ); this.runNegativeTest( new String[] { "JJ.java", "public class JJ implements I { public void foo(T t) {} }\n" + "interface I { public void foo(U u); }\n" }, "----------\n" + "1. ERROR in JJ.java (at line 1)\r\n" + " public class JJ implements I { public void foo(T t) {} }\r\n" + " ^^\n" + "The type JJ must implement the inherited abstract method I.foo(Object)\n" + "----------\n" + "2. ERROR in JJ.java (at line 1)\r\n" + " public class JJ implements I { public void foo(T t) {} }\r\n" + " ^^^^^^^^\n" + "Name clash: The method foo(T) of type JJ has the same erasure as foo(U) of type I but does not override it\n" + "----------\n" // JJ is not abstract and does not override abstract method foo(java.lang.Object) in I ); this.runConformTest( new String[] { "YYY.java", "public class YYY extends X { public void foo(T t) {} }\n" + "class X { public void foo(U u) {} }\n" }, "" ); this.runConformTest( new String[] { "JJJ.java", "public class JJJ implements I { public void foo(T t) {} }\n" + "interface I { public void foo(U u); }\n" }, "" ); } public void test002() { // separate files this.runNegativeTest( new String[] { "Y.java", "public class Y extends X { public void foo(T t) {} }\n" + "class A {}\n", "X.java", "class X { public void foo(U u) {} }\n" }, "----------\n" + "1. ERROR in Y.java (at line 1)\r\n" + " public class Y extends X { public void foo(T t) {} }\r\n" + " ^^^^^^^^\n" + "Name clash: The method foo(T) of type Y has the same erasure as foo(U) of type X but does not override it\n" + "----------\n" // name clash: foo(T) in Y and foo(U) in X have the same erasure, yet neither overrides the other ); this.runNegativeTest( new String[] { "J.java", "public class J implements I { public void foo(T t) {} }\n" + "class A {}\n", "I.java", "interface I { public void foo(U u); }\n" }, "----------\n" + "1. ERROR in J.java (at line 1)\r\n" + " public class J implements I { public void foo(T t) {} }\r\n" + " ^\n" + "The type J must implement the inherited abstract method I.foo(A)\n" + "----------\n" + "2. ERROR in J.java (at line 1)\r\n" + " public class J implements I { public void foo(T t) {} }\r\n" + " ^^^^^^^^\n" + "Name clash: The method foo(T) of type J has the same erasure as foo(U) of type I but does not override it\n" + "----------\n" // J is not abstract and does not override abstract method foo(A) in I ); this.runNegativeTest( new String[] { "YY.java", "public class YY extends X { public void foo(T t) {} }\n", "X.java", "class X { public void foo(U u) {} }\n" }, "----------\n" + "1. ERROR in YY.java (at line 1)\r\n" + " public class YY extends X { public void foo(T t) {} }\r\n" + " ^^^^^^^^\n" + "Name clash: The method foo(T) of type YY has the same erasure as foo(U) of type X but does not override it\n" + "----------\n" // name clash: foo(T) in YY and foo(U) in X have the same erasure, yet neither overrides the other ); this.runNegativeTest( new String[] { "JJ.java", "public class JJ implements I { public void foo(T t) {} }\n", "I.java", "interface I { public void foo(U u); }\n" }, "----------\n" + "1. ERROR in JJ.java (at line 1)\r\n" + " public class JJ implements I { public void foo(T t) {} }\r\n" + " ^^\n" + "The type JJ must implement the inherited abstract method I.foo(Object)\n" + "----------\n" + "2. ERROR in JJ.java (at line 1)\r\n" + " public class JJ implements I { public void foo(T t) {} }\r\n" + " ^^^^^^^^\n" + "Name clash: The method foo(T) of type JJ has the same erasure as foo(U) of type I but does not override it\n" + "----------\n" // JJ is not abstract and does not override abstract method foo(java.lang.Object) in I ); this.runConformTest( new String[] { "YYY.java", "public class YYY extends X { public void foo(T t) {} }\n", "X.java", "class X { public void foo(U u) {} }\n" }, "" ); this.runConformTest( new String[] { "JJJ.java", "public class JJJ implements I { public void foo(T t) {} }\n", "I.java", "interface I { public void foo(U u); }\n" }, "" ); } public void test003() { // pick up superTypes as binaries this.runConformTest( new String[] { "A.java", "class A {}\n", "B.java", "class B {}\n", "X.java", "class X { public void foo(U u) {} }\n", "I.java", "interface I { public void foo(U u); }\n", }, "" ); this.runNegativeTest( new String[] { "Y.java", "public class Y extends X { public void foo(T t) {} }\n" }, "----------\n" + "1. ERROR in Y.java (at line 1)\r\n" + " public class Y extends X { public void foo(T t) {} }\r\n" + " ^^^^^^^^\n" + "Name clash: The method foo(T) of type Y has the same erasure as foo(U) of type X but does not override it\n" + "----------\n", // name clash: foo(T) in Y and foo(U) in X have the same erasure, yet neither overrides the other null, false, null ); this.runNegativeTest( new String[] { "J.java", "public class J implements I { public void foo(T t) {} }\n" }, "----------\n" + "1. ERROR in J.java (at line 1)\r\n" + " public class J implements I { public void foo(T t) {} }\r\n" + " ^\n" + "The type J must implement the inherited abstract method I.foo(A)\n" + "----------\n" + "2. ERROR in J.java (at line 1)\r\n" + " public class J implements I { public void foo(T t) {} }\r\n" + " ^^^^^^^^\n" + "Name clash: The method foo(T) of type J has the same erasure as foo(U) of type I but does not override it\n" + "----------\n", // J is not abstract and does not override abstract method foo(A) in I null, false, null ); this.runNegativeTest( new String[] { "YY.java", "public class YY extends X { public void foo(T t) {} }\n" }, "----------\n" + "1. ERROR in YY.java (at line 1)\r\n" + " public class YY extends X { public void foo(T t) {} }\r\n" + " ^^^^^^^^\n" + "Name clash: The method foo(T) of type YY has the same erasure as foo(U) of type X but does not override it\n" + "----------\n", // name clash: foo(T) in YY and foo(U) in X have the same erasure, yet neither overrides the other null, false, null ); this.runNegativeTest( new String[] { "JJ.java", "public class JJ implements I { public void foo(T t) {} }\n" }, "----------\n" + "1. ERROR in JJ.java (at line 1)\r\n" + " public class JJ implements I { public void foo(T t) {} }\r\n" + " ^^\n" + "The type JJ must implement the inherited abstract method I.foo(Object)\n" + "----------\n" + "2. ERROR in JJ.java (at line 1)\r\n" + " public class JJ implements I { public void foo(T t) {} }\r\n" + " ^^^^^^^^\n" + "Name clash: The method foo(T) of type JJ has the same erasure as foo(U) of type I but does not override it\n" + "----------\n", // JJ is not abstract and does not override abstract method foo(java.lang.Object) in I null, false, null ); this.runConformTest( new String[] { "YYY.java", "public class YYY extends X { public void foo(T t) {} }\n" }, "", null, false, null ); this.runConformTest( new String[] { "JJJ.java", "public class JJJ implements I { public void foo(T t) {} }\n" }, "", null, false, null ); } public void test004() { // all together this.runNegativeTest( new String[] { "ALL.java", "class A {}\n" + "class B {}\n" + "class X { public U foo() {return null;} }\n" + "interface I { public U foo(); }\n" + "class J implements I { public T foo() {return null;} }\n" + "class K implements I { public T foo() {return null;} }\n" + "class L implements I { public T foo() {return null;} }\n" + "class Y extends X { public T foo() { return super.foo(); } }\n" + "class Z extends X { public T foo() { return super.foo(); } }\n" + "class W extends X { public T foo() { return super.foo(); } }\n", }, "----------\n" + "1. ERROR in ALL.java (at line 5)\n" + " class J implements I { public T foo() {return null;} }\n" + " ^^^^^\n" + "The return type is incompatible with I.foo()\n" + "----------\n" + "2. ERROR in ALL.java (at line 8)\n" + " class Y extends X { public T foo() { return super.foo(); } }\n" + " ^^^^^\n" + "The return type is incompatible with X.foo()\n" + "----------\n" + "3. ERROR in ALL.java (at line 8)\n" + " class Y extends X { public T foo() { return super.foo(); } }\n" + " ^^^^^^^^^^^\n" + "Type mismatch: cannot convert from A to T\n" + "----------\n" + "4. ERROR in ALL.java (at line 10)\n" + " class W extends X { public T foo() { return super.foo(); } }\n" + " ^^^^^^^^^^^\n" + "Type mismatch: cannot convert from Object to T\n" + "----------\n" /* ALL.java:5: J is not abstract and does not override abstract method foo() in I ALL.java:5: foo() in J cannot implement foo() in I; attempting to use incompatible return type ALL.java:8: foo() in Y cannot override foo() in X; attempting to use incompatible return type ALL.java:8: incompatible types found : A required: T class Y extends X { public T foo() { return super.foo(); } } ^ ALL.java:10: incompatible types found : java.lang.Object required: T class W extends X { public T foo() { return super.foo(); } } */ ); } public void test005() { // separate files this.runNegativeTest( new String[] { "A.java", "class A {}\n", "B.java", "class B {}\n", "X.java", "class X { public U foo() {return null;} }\n", "I.java", "interface I { public U foo(); }\n", "J.java", "class J implements I { public T foo() {return null;} }\n", "K.java", "class K implements I { public T foo() {return null;} }\n", "L.java", "class L implements I { public T foo() {return null;} }\n", "Y.java", "class Y extends X { public T foo() { return super.foo(); } }\n", "Z.java", "class Z extends X { public T foo() { return super.foo(); } }\n", "W.java", "class W extends X { public T foo() { return super.foo(); } }\n", }, "----------\n" + "1. ERROR in J.java (at line 1)\n" + " class J implements I { public T foo() {return null;} }\n" + " ^^^^^\n" + "The return type is incompatible with I.foo()\n" + "----------\n" + "----------\n" + "1. ERROR in Y.java (at line 1)\n" + " class Y extends X { public T foo() { return super.foo(); } }\n" + " ^^^^^\n" + "The return type is incompatible with X.foo()\n" + "----------\n" + "2. ERROR in Y.java (at line 1)\n" + " class Y extends X { public T foo() { return super.foo(); } }\n" + " ^^^^^^^^^^^\n" + "Type mismatch: cannot convert from A to T\n" + "----------\n" + "----------\n" + "1. ERROR in W.java (at line 1)\n" + " class W extends X { public T foo() { return super.foo(); } }\n" + " ^^^^^^^^^^^\n" + "Type mismatch: cannot convert from Object to T\n" + "----------\n" /* J.java:1: J is not abstract and does not override abstract method foo() in I J.java:1: foo() in J cannot implement foo() in I; attempting to use incompatible return type W.java:1: incompatible types found : java.lang.Object required: T class W extends X { public T foo() { return super.foo(); } } Y.java:1: foo() in Y cannot override foo() in X; attempting to use incompatible return type Y.java:1: incompatible types found : A required: T class Y extends X { public T foo() { return super.foo(); } } */ ); } public void test006() { // pick up superTypes as binaries this.runConformTest( new String[] { "A.java", "class A {}\n", "B.java", "class B {}\n", "X.java", "class X { public U foo() {return null;} }\n", "I.java", "interface I { public U foo(); }\n", }, "" ); this.runNegativeTest( new String[] { "J.java", "class J implements I { public T foo() {return null;} }\n", "K.java", "class K implements I { public T foo() {return null;} }\n", "L.java", "class L implements I { public T foo() {return null;} }\n", "Y.java", "class Y extends X { public T foo() { return super.foo(); } }\n", "Z.java", "class Z extends X { public T foo() { return super.foo(); } }\n", "W.java", "class W extends X { public T foo() { return super.foo(); } }\n", }, "----------\n" + "1. ERROR in J.java (at line 1)\n" + " class J implements I { public T foo() {return null;} }\n" + " ^^^^^\n" + "The return type is incompatible with I.foo()\n" + "----------\n" + "----------\n" + "1. ERROR in Y.java (at line 1)\n" + " class Y extends X { public T foo() { return super.foo(); } }\n" + " ^^^^^\n" + "The return type is incompatible with X.foo()\n" + "----------\n" + "2. ERROR in Y.java (at line 1)\n" + " class Y extends X { public T foo() { return super.foo(); } }\n" + " ^^^^^^^^^^^\n" + "Type mismatch: cannot convert from A to T\n" + "----------\n" + "----------\n" + "1. ERROR in W.java (at line 1)\n" + " class W extends X { public T foo() { return super.foo(); } }\n" + " ^^^^^^^^^^^\n" + "Type mismatch: cannot convert from Object to T\n" + "----------\n", /* J.java:1: J is not abstract and does not override abstract method foo() in I J.java:1: foo() in J cannot implement foo() in I; attempting to use incompatible return type W.java:1: incompatible types found : java.lang.Object required: T class W extends X { public T foo() { return super.foo(); } } Y.java:1: foo() in Y cannot override foo() in X; attempting to use incompatible return type Y.java:1: incompatible types found : A required: T class Y extends X { public T foo() { return super.foo(); } } */ null, false, null ); } public void test007() { // simple covariance cases this.runConformTest( new String[] { "A.java", "abstract class A implements I {}\n" + "interface I extends J { String foo(); }\n" + "interface J { Object foo(); }\n", "X.java", "abstract class X1 extends A implements J {}\n" }, "" ); this.runNegativeTest( new String[] { "A.java", "abstract class A implements I {}\n" + "interface I extends J { Object foo(); }\n" + "interface J { String foo(); }\n", "X.java", "abstract class X2 extends A implements J {}\n" }, "----------\n" + "1. ERROR in A.java (at line 1)\r\n" + " abstract class A implements I {}\r\n" + " ^\n" + "The return type is incompatible with J.foo(), I.foo()\n" + "----------\n" + "2. ERROR in A.java (at line 2)\r\n" + " interface I extends J { Object foo(); }\r\n" + " ^^^^^\n" + "The return type is incompatible with J.foo()\n" + "----------\n" + "----------\n" + "1. ERROR in X.java (at line 1)\r\n" + " abstract class X2 extends A implements J {}\r\n" + " ^^\n" + "The return type is incompatible with I.foo(), J.foo()\n" + "----------\n" ); this.runConformTest( new String[] { "A.java", "abstract class A implements I {}\n" + "interface I { String foo(); }\n", "X.java", "abstract class X3 extends A implements J {}\n" + "interface J { Object foo(); }\n" }, "" ); this.runConformTest( new String[] { "A.java", "abstract class A implements I {}\n" + "interface I { Object foo(); }\n", "X.java", "abstract class X4 extends A implements J {}\n" + "interface J { String foo(); }\n" }, "" ); this.runConformTest( new String[] { "A.java", "class A { public String foo() { return null; } }\n" + "interface I { Object foo(); }\n", "X.java", "abstract class X5 extends A implements I {}\n" }, "" ); this.runNegativeTest( new String[] { "A.java", "class A { public Object foo() { return null; } }\n" + "interface I { String foo(); }\n", "X.java", "abstract class X6 extends A implements I {}\n" }, "----------\n" + "1. ERROR in X.java (at line 1)\r\n" + " abstract class X6 extends A implements I {}\r\n" + " ^^\n" + "The return type is incompatible with I.foo(), A.foo()\n" + "----------\n" ); this.runNegativeTest( new String[] { "A.java", "class A { int get(short i, short s) { return i; } }\n" + "class B extends A { short get(short i, short s) {return i; } }\n" }, "----------\n" + "1. ERROR in A.java (at line 2)\r\n" + " class B extends A { short get(short i, short s) {return i; } }\r\n" + " ^^^^^^^^^^^^^^^^^^^^^\n" + "The return type is incompatible with A.get(short, short)\n" + "----------\n" ); } public void test008() { // covariance test this.runNegativeTest( new String[] { "ALL.java", "interface I { I foo(); }\n" + "class A implements I { public A foo() { return null; } }\n" + "class B extends A { public B foo() { return null; } }\n" + "class C extends B { public A foo() { return null; } }\n" + "class D extends B implements I {}\n", }, "----------\n" + "1. ERROR in ALL.java (at line 4)\r\n" + " class C extends B { public A foo() { return null; } }\r\n" + " ^^^^^\n" + "The return type is incompatible with B.foo()\n" + "----------\n" // foo() in C cannot override foo() in B; attempting to use incompatible return type ); } public void test009() { this.runNegativeTest( new String[] { "A.java", "class G {}\n" + "interface I { void foo(G x); }\n" + "abstract class A implements I { void foo(G x) {} }\n" }, "----------\n" + "1. ERROR in A.java (at line 3)\r\n" + " abstract class A implements I { void foo(G x) {} }\r\n" + " ^^^^^^^^^^^\n" + "Name clash: The method foo(G) of type A has the same erasure as foo(G) of type I but does not override it\n" + "----------\n" // name clash: foo(G) in A and foo(G) in I have the same erasure, yet neither overrides the other ); this.runNegativeTest( new String[] { "A.java", "class G {}\n" + "interface I { I foo(G x); }\n" + "abstract class A implements I { I foo(G x) { return null; } }\n" }, "----------\n" + "1. ERROR in A.java (at line 3)\r\n" + " abstract class A implements I { I foo(G x) { return null; } }\r\n" + " ^^^^^^^^^^^\n" + "Name clash: The method foo(G) of type A has the same erasure as foo(G) of type I but does not override it\n" + "----------\n" // name clash: foo(G) in A and foo(G) in I have the same erasure, yet neither overrides the other ); } public void test010() { // executable bridge method case this.runConformTest( new String[] { "X.java", "public class X {\n" + " public X foo() {\n" + " System.out.println(\"Did NOT add bridge method\");\n" + " return this;\n" + " }\n" + " public static void main(String[] args) throws Exception {\n" + " X x = new A();\n" + " x.foo();\n" + " System.out.print(\" + \");\n" + " I i = new A();\n" + " i.foo();\n" + " }\n" + "}\n" + "interface I {\n" + " public I foo();\n" + "}\n" + "class A extends X implements I {\n" + " public A foo() {\n" + " System.out.print(\"Added bridge method\");\n" + " return this;\n" + " }\n" + "}\n" }, "Added bridge method + Added bridge method" ); } public void test011() { // javac 1.5.0 will only issue 1 name clash per compile... doesn't matter how many source files are involved this.runNegativeTest( new String[] { "A.java", "class A { void foo(T t) {} }\n" + "interface I { void foo(T t); }\n", "X.java", "abstract class X1 extends A implements I {}\n" }, "----------\n" + "1. ERROR in X.java (at line 1)\r\n" + " abstract class X1 extends A implements I {}\r\n" + " ^^\n" + "The inherited method A.foo(T) cannot hide the public abstract method in I\n" + "----------\n" // foo(T) in A cannot implement foo(T) in I; attempting to assign weaker access privileges; was public ); this.runNegativeTest( new String[] { "A.java", "class A { void foo(T t) {} }\n" + "interface I { void foo(T t); }\n", "X.java", "abstract class X2 extends A implements I {}\n" }, "----------\n" + "1. ERROR in X.java (at line 1)\n" + " abstract class X2 extends A implements I {}\n" + " ^^\n" + "Name clash: The method foo(T) of type A has the same erasure as foo(T) of type I but does not override it\n" + "----------\n" // name clash: foo(T) in A and foo(T) in I have the same erasure, yet neither overrides the other ); this.runNegativeTest( new String[] { "A.java", "class A { void foo(T t) {} }\n" + "interface I { void foo(T t); }\n", "X.java", "abstract class X3 extends A implements I {}\n" }, "----------\n" + "1. ERROR in X.java (at line 1)\n" + " abstract class X3 extends A implements I {}\n" + " ^^\n" + "Name clash: The method foo(T) of type A has the same erasure as foo(T) of type I but does not override it\n" + "----------\n" // name clash: foo(T) in A and foo(T) in I have the same erasure, yet neither overrides the other ); } public void test012() { this.runNegativeTest( new String[] { "A.java", "class A { public void foo(T s) {} }\n" + "class Y1 extends A { void foo(Object s) {} }\n" }, "----------\n" + "1. ERROR in A.java (at line 2)\r\n" + " class Y1 extends A { void foo(Object s) {} }\r\n" + " ^^^^^^^^^^^^^\n" + "Cannot reduce the visibility of the inherited method from A\n" + "----------\n" // foo(java.lang.Object) in Y1 cannot override foo(T) in A; attempting to assign weaker access privileges; was public ); this.runNegativeTest( new String[] { "A.java", "class A { public void foo(T[] s) {} }\n" + "class Y2 extends A { void foo(Object[] s) {} }\n" }, "----------\n" + "1. ERROR in A.java (at line 2)\n" + " class Y2 extends A { void foo(Object[] s) {} }\n" + " ^^^^^^^^^^^^^^^\n" + "Cannot reduce the visibility of the inherited method from A\n" + "----------\n" // foo(java.lang.Object[]) in Y2 cannot override foo(T[]) in A; attempting to assign weaker access privileges; was public ); this.runNegativeTest( new String[] { "A.java", "class A { public void foo(Class s) {} }\n" + "class Y3 extends A { void foo(Class s) {} }\n" }, "----------\n" + "1. ERROR in A.java (at line 2)\r\n" + " class Y3 extends A { void foo(Class s) {} }\r\n" + " ^^^^^^^^^^^^^^^^^^^^\n" + "Cannot reduce the visibility of the inherited method from A\n" + "----------\n" // foo(java.lang.Class) in Y3 cannot override foo(java.lang.Class) in A; attempting to assign weaker access privileges; was public ); } public void test013() { // javac 1.5.0 will only issue 1 name clash per compile... doesn't matter how many source files are involved this.runConformTest( new String[] { "A.java", "class A { public void foo(Class s) {} }\n" + "interface I { void foo(Class s); }\n", "X.java", "abstract class X0 extends A implements I {}\n" }, "" ); this.runNegativeTest( new String[] { "A.java", "class A { void foo(Class s) {} }\n" + "interface I { void foo(Class s); }\n", "X.java", "abstract class X1 extends A implements I {}\n" }, "----------\n" + "1. ERROR in X.java (at line 1)\r\n" + " abstract class X1 extends A implements I {}\r\n" + " ^^\n" + "Name clash: The method foo(Class) of type A has the same erasure as foo(Class) of type I but does not override it\n" + "----------\n" // name clash: foo(java.lang.Class) in A and foo(java.lang.Class) in I have the same erasure, yet neither overrides the other ); this.runNegativeTest( new String[] { "A.java", "class A { void foo(Class s) {} }\n" + "interface I { void foo(Class s); }\n", "X.java", "abstract class X2 extends A implements I {}\n" }, "----------\n" + "1. ERROR in X.java (at line 1)\r\n" + " abstract class X2 extends A implements I {}\r\n" + " ^^\n" + "Name clash: The method foo(Class) of type A has the same erasure as foo(Class) of type I but does not override it\n" + "----------\n" // name clash: foo(java.lang.Class) in A and foo(java.lang.Class) in I have the same erasure, yet neither overrides the other ); this.runNegativeTest( new String[] { "A.java", "class A { S foo(Class s) { return null; } }\n" + "interface I { Object foo(Class s); }\n", "X.java", "abstract class X3 extends A implements I {}\n" }, "----------\n" + "1. ERROR in X.java (at line 1)\r\n" + " abstract class X3 extends A implements I {}\r\n" + " ^^\n" + "Name clash: The method foo(Class) of type A has the same erasure as foo(Class) of type I but does not override it\n" + "----------\n" // name clash: foo(java.lang.Class) in A and foo(java.lang.Class) in I have the same erasure, yet neither overrides the other ); this.runNegativeTest( new String[] { "A.java", "class A { Object foo(Class s) { return null; } }\n" + "interface I { S foo(Class s); }\n", "X.java", "abstract class X4 extends A implements I {}\n" }, "----------\n" + "1. ERROR in X.java (at line 1)\r\n" + " abstract class X4 extends A implements I {}\r\n" + " ^^\n" + "Name clash: The method foo(Class) of type A has the same erasure as foo(Class) of type I but does not override it\n" + "----------\n" // name clash: foo(java.lang.Class) in A and foo(java.lang.Class) in I have the same erasure, yet neither overrides the other ); this.runNegativeTest( new String[] { "A.java", "class A { public void foo(Class s) {} }\n" + "interface I { void foo(Class s); }\n", "X.java", "class X5 extends A implements I { public void foo(Class s) {} }\n" }, "----------\n" + "1. ERROR in X.java (at line 1)\r\n" + " class X5 extends A implements I { public void foo(Class s) {} }\r\n" + " ^^^^^^^^^^^^^^^\n" + "Name clash: The method foo(Class) of type X5 has the same erasure as foo(Class) of type A but does not override it\n" + "----------\n" // name clash: foo(java.lang.Class) in X5 and foo(java.lang.Class) in A have the same erasure, yet neither overrides the other ); } public void test014() { // name clash tests this.runConformTest( new String[] { "X.java", "class X { void foo(A a) {} }\n" + "class Y extends X { void foo(A a) {} }\n" + "class A {}\n" }, "" ); this.runConformTest( new String[] { "X.java", "class X { void foo(A[] a) {} }\n" + "class Y extends X { void foo(A[] a) {} }\n" + "class A {}\n" }, "" ); this.runConformTest( new String[] { "X.java", "class X { void foo(A[] a) {} }\n" + "class Y extends X { void foo(A[] a) {} }\n" + "class A {}\n" }, "" ); this.runConformTest( new String[] { "X.java", "class X { void foo(A a) {} }\n" + "class Y extends X { void foo(A a) {} }\n" + "class A {}\n" }, "" ); this.runNegativeTest( new String[] { "X.java", "class X { void foo(A a) {} }\n" + "class Y extends X { void foo(A a) {} }\n" + "class A {}\n" }, "----------\n" + "1. ERROR in X.java (at line 2)\n" + " class Y extends X { void foo(A a) {} }\n" + " ^^^^^^^^^^^^^^^^\n" + "Name clash: The method foo(A) of type Y has the same erasure as foo(A) of type X but does not override it\n" + "----------\n" // name clash: foo(A) in Y and foo(A) in X have the same erasure, yet neither overrides the other ); this.runNegativeTest( new String[] { "X.java", "class X { void foo(A[] a) {} }\n" + "class Y extends X { void foo(A[] a) {} }\n" + "class A {}\n" }, "----------\n" + "1. ERROR in X.java (at line 2)\n" + " class Y extends X { void foo(A[] a) {} }\n" + " ^^^^^^^^^^^^^^^^^^\n" + "Name clash: The method foo(A[]) of type Y has the same erasure as foo(A[]) of type X but does not override it\n" + "----------\n" // name clash: foo(A[]) in Y and foo(A[]) in X have the same erasure, yet neither overrides the other ); } public void test015() { // more name clash tests this.runConformTest( new String[] { "X.java", "abstract class X extends Y implements I { }\n" + "interface I { void foo(A a); }\n" + "class Y { public void foo(A a) {} }\n" + "class A {}\n" }, "" ); this.runConformTest( new String[] { "X.java", "abstract class X extends Y implements I { }\n" + "interface I { void foo(A[] a); }\n" + "class Y { public void foo(A[] a) {} }\n" + "class A {}\n" }, "" ); this.runConformTest( new String[] { "X.java", "abstract class X extends Y implements I { }\n" + "interface I { void foo(A[] a); }\n" + "class Y { public void foo(A[] a) {} }\n" + "class A {}\n" }, "" ); this.runConformTest( new String[] { "X.java", "abstract class X extends Y implements I { }\n" + "interface I { void foo(A a); }\n" + "class Y { public void foo(A a) {} }\n" + "class A {}\n" }, "" ); this.runNegativeTest( new String[] { "X.java", "abstract class X extends Y implements I { }\n" + "interface I { void foo(A a); }\n" + "class Y { public void foo(A a) {} }\n" + "class A {}\n" }, "----------\n" + "1. ERROR in X.java (at line 1)\r\n" + " abstract class X extends Y implements I { }\r\n" + " ^\n" + "Name clash: The method foo(A) of type Y has the same erasure as foo(A) of type I but does not override it\n" + "----------\n" // name clash: foo(A) in Y and foo(A) in I have the same erasure, yet neither overrides the other ); this.runNegativeTest( new String[] { "X.java", "abstract class X extends Y implements I { }\n" + "interface I { void foo(A[] a); }\n" + "class Y { public void foo(A[] a) {} }\n" + "class A {}\n" }, "----------\n" + "1. ERROR in X.java (at line 1)\r\n" + " abstract class X extends Y implements I { }\r\n" + " ^\n" + "Name clash: The method foo(A[]) of type Y has the same erasure as foo(A[]) of type I but does not override it\n" + "----------\n" // name clash: foo(A[]) in Y and foo(A[]) in I have the same erasure, yet neither overrides the other ); } public void test016() { // 73971 this.runConformTest( new String[] { "X.java", "public class X {\n" + " static void m(E e) { System.out.print(\"A=\"+e.getClass()); }\n" + " static void m(E e) { System.out.print(\"B=\"+e.getClass()); }\n" + " public static void main(String[] args) {\n" + " m(new A());\n" + " m(new B());\n" + " }\n" + "}\n" + "class A {}\n" + "class B extends A {}\n" }, "A=class AB=class B" ); } public void test017() { // 77785 this.runNegativeTest( new String[] { "X.java", "class X {}\n" + "class Y { void test(X a) {} }\n" + "class Z extends Y { void test(X a) {} }\n" }, "----------\n" + "1. ERROR in X.java (at line 3)\r\n" + " class Z extends Y { void test(X a) {} }\r\n" + " ^^^^^^^^^^^^^^^^^\n" + "Name clash: The method test(X) of type Z has the same erasure as test(X) of type Y but does not override it\n" + "----------\n" // name clash: test(X) in Z and test(X) in Y have the same erasure, yet neither overrides the other ); this.runNegativeTest( new String[] { "X.java", "class X {}\n" + "class Y { void test(X a) {} }\n" + "class Z extends Y { void test(X a) {} }\n" }, "----------\n" + "1. ERROR in X.java (at line 3)\n" + " class Z extends Y { void test(X a) {} }\n" + " ^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + "Name clash: The method test(X) of type Z has the same erasure as test(X) of type Y but does not override it\n" + "----------\n" // name clash: test(X) in Z and test(X) in Y have the same erasure, yet neither overrides the other ); } public void test018() { // 77861 this.runNegativeTest( new String[] { "X.java", "class X implements Comparable {\n" + " public int compareTo(Object o) { return 0; }\n" + " public int compareTo(X o) { return 1; }\n" + "}\n" }, "----------\n" + "1. ERROR in X.java (at line 2)\n" + " public int compareTo(Object o) { return 0; }\n" + " ^^^^^^^^^^^^^^^^^^^\n" + "Name clash: The method compareTo(Object) of type X has the same erasure as compareTo(T) of type Comparable but does not override it\n" + "----------\n" // name clash: compareTo(java.lang.Object) in X and compareTo(T) in java.lang.Comparable have the same erasure, yet neither overrides the other ); } public void test019() { // 78140 this.runConformTest( new String[] { "A.java", "public class A {\n" + " T get() { return null; } \n" + "}\n" + "class B extends A {\n" + " T get() { return null; } \n" + "}\n" }, "" ); } public void test020() { // 78232 this.runConformTest( new String[] { "Test.java", "public class Test {\n" + " public static void main(String[] args) {\n" + " AbstractBase ab = new AbstractBase();\n" + " Derived d = new Derived();\n" + " AbstractBase ab2 = new Derived();\n" + " Visitor v = new MyVisitor();\n" + " System.out.print(ab.accept(v, ab.getClass().getName()));\n" + " System.out.print('+');\n" + " System.out.print(d.accept(v, d.getClass().getName()));\n" + " System.out.print('+');\n" + " System.out.print(ab2.accept(v, ab2.getClass().getName()));\n" + " }\n" + " static class MyVisitor implements Visitor {\n" + " public String visitBase(AbstractBase ab, String obj) { return \"Visited base: \" + obj; }\n" + " public String visitDerived(Derived d, String obj) { return \"Visited derived: \" + obj; }\n" + " }\n" + "}\n" + "interface Visitor {\n" + " R visitBase(AbstractBase ab, T obj);\n" + " R visitDerived(Derived d, T obj);\n" + "}\n" + "interface Visitable {\n" + " R accept(Visitor v, T obj);\n" + "}\n" + "class AbstractBase implements Visitable {\n" + " public R accept(Visitor v, T obj) { return v.visitBase(this, obj); }\n" + "}\n" + "class Derived extends AbstractBase implements Visitable {\n" + " public R accept(Visitor v, T obj) { return v.visitDerived(this, obj); }\n" + "}\n" }, "Visited base: AbstractBase+Visited derived: Derived+Visited derived: Derived" ); } public void test021() { this.runNegativeTest( new String[] { "A.java", "public class A {\n" + " public void foo(java.util.Map> m) { } \n" + "}\n", "B.java", "class B extends A {\n" + " void foo(java.util.Map> m) { } \n" + "}\n" }, "----------\n" + "1. ERROR in B.java (at line 2)\r\n" + " void foo(java.util.Map> m) { } \r\n" + " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + "Cannot reduce the visibility of the inherited method from A\n" + "----------\n" ); // now save A & pick it up as a binary type this.runConformTest( new String[] { "A.java", "public class A {\n" + " public void foo(java.util.Map> m) { } \n" + "}\n" }, "" ); this.runNegativeTest( new String[] { "B.java", "class B extends A {\n" + " void foo(java.util.Map> m) { } \n" + "}\n" }, "----------\n" + "1. ERROR in B.java (at line 2)\r\n" + " void foo(java.util.Map> m) { } \r\n" + " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + "Cannot reduce the visibility of the inherited method from A\n" + "----------\n", null, false, null ); } public void test022() { // 77562 this.runConformTest( new String[] { "A.java", "import java.util.*;\n" + "class A { List getList() { return null; } }\n" + "class B extends A { List getList() { return null; } }\n" }, "" ); this.runNegativeTest( new String[] { "A.java", "import java.util.*;\n" + "class A { List getList() { return null; } }\n" + "class B extends A { List getList() { return null; } }\n" }, "----------\n" + "1. WARNING in A.java (at line 3)\n" + " class B extends A { List getList() { return null; } }\n" + " ^^^^\n" + "Type safety: The return type List for getList() from the type B needs unchecked conversion to conform to List from the type A\n" + "----------\n" // unchecked warning on B.getList() ); } public void test023() { // 80739 this.runNegativeTest( new String[] { "A.java", "class A {\n" + " void foo(T t) {}\n" + " void foo(String i) {}\n" + "}\n" + "class B extends A {}\n" }, "----------\n" + "1. ERROR in A.java (at line 5)\r\n" + " class B extends A {}\r\n" + " ^\n" + "Duplicate methods named foo with the parameters (String) and (T) are defined by the type A\n" + "----------\n" // methods foo(T) from A and foo(java.lang.String) from A are inherited with the same signature ); } public void test024() { // 80626 this.runConformTest( new String[] { "A.java", "class A {\n" + " public void m(E e) {}\n" + "}\n" + "class B extends A {\n" + " public void m(Object e) {}\n" + "}\n" }, "" // no complaint ); this.runNegativeTest( new String[] { "A.java", "class A {\n" + " public void m(Object e) {}\n" + "}\n" + "class B extends A {\n" + " public void m(E e) {}\n" + "}\n" }, "----------\n" + "1. ERROR in A.java (at line 5)\r\n" + " public void m(E e) {}\r\n" + " ^^^^^^\n" + "Name clash: The method m(E) of type B has the same erasure as m(Object) of type A but does not override it\n" + "----------\n" // name clash: m(E) in B and m(java.lang.Object) in A have the same erasure, yet neither overrides the other ); this.runNegativeTest( new String[] { "A.java", "class A {\n" + " public void m(E e) {}\n" + "}\n" + "class B extends A {\n" + " public void m(Object e) {}\n" + "}\n" + "class C extends B {\n" + " public void m(E e) {}\n" + "}\n" }, "----------\n" + "1. ERROR in A.java (at line 8)\r\n" + " public void m(E e) {}\r\n" + " ^^^^^^\n" + "Name clash: The method m(E) of type C has the same erasure as m(Object) of type B but does not override it\n" + "----------\n" // name clash: m(E) in C and m(java.lang.Object) in B have the same erasure, yet neither overrides the other ); } public void test025() { // 81618 this.runNegativeTest( new String[] { "X.java", "public class X {\n" + " public static void main(String[] args) {\n" + " new B().test();\n" + " }\n" + "}\n" + "class A {\n" + " T test() { return null; }\n" + "}\n" + "class B extends A {\n" + " Integer test() { return 1; }\n" + "}\n" }, "----------\n" + "1. WARNING in X.java (at line 10)\n" + " Integer test() { return 1; }\n" + " ^^^^^^^\n" + "Type safety: The return type Integer for test() from the type B needs unchecked conversion to conform to T from the type A\n" + "----------\n" // warning: test() in B overrides test() in A; return type requires unchecked conversion ); this.runNegativeTest( new String[] { "X.java", "public class X {\n" + " public static void main(String[] args) {\n" + " new B().test();\n" + " }\n" + "}\n" + "class A {\n" + " T[] test() { return null; }\n" + "}\n" + "class B extends A {\n" + " Integer[] test() { return new Integer[] {2}; }\n" + "}\n" }, "----------\n" + "1. WARNING in X.java (at line 10)\n" + " Integer[] test() { return new Integer[] {2}; }\n" + " ^^^^^^^^^\n" + "Type safety: The return type Integer[] for test() from the type B needs unchecked conversion to conform to T[] from the type A\n" + "----------\n" // warning: test() in B overrides test() in A; return type requires unchecked conversion ); this.runConformTest( new String[] { "X.java", "public class X {\n" + " public static void main(String[] args) {\n" + " System.out.println(new B().test(new Integer(1)));\n" + " }\n" + "}\n" + "class A {\n" + " T test(T t) { return null; }\n" + "}\n" + "class B extends A {\n" + " T test(T t) { return t; }\n" + "}\n" }, "1" ); this.runConformTest( new String[] { "X.java", "public class X {\n" + " public static void main(String[] args) {\n" + " System.out.println(new B().test(1));\n" + " }\n" + "}\n" + "class A {\n" + " T test(U u) { return null; }\n" + "}\n" + "class B extends A {\n" + " Integer test(U u) { return 1; }\n" + "}\n" }, "1" ); this.runConformTest( new String[] { "A.java", "import java.util.concurrent.Callable;\n" + "public class A {\n" + " public static void main(String[] args) throws Exception {\n" + " Callable integerCallable = new Callable() {\n" + " public Integer call() { return new Integer(1); }\n" + " };\n" + " System.out.println(integerCallable.call());\n" + " }\n" + "}\n" }, "1" ); this.runNegativeTest( new String[] { "X.java", "interface X { T x(); }\n" + "abstract class Y implements X { public abstract S x(); }\n" + "abstract class Z implements X { public abstract X x(); }\n" }, "" // no warnings ); this.runNegativeTest( new String[] { "X.java", "interface X { T[] x(); }\n" + "abstract class Y implements X { public abstract S[] x(); }\n" + "abstract class Z implements X { public abstract X[] x(); }\n" }, "" // no warnings ); } public void test026() { this.runConformTest( new String[] { "X.java", "public class X {\n" + " public static void main(String[] args) {\n" + " System.out.print(\n" + " new B().test().getClass() + \" & \"\n" + " + new C().test().getClass() + \" & \"\n" + " + new D().test().getClass());\n" + " }\n" + "}\n" + "class A {\n" + " A test() { return this; }\n" + "}\n" + "class B extends A {\n" + " A test() { return super.test(); }\n" + "}\n" + "class C extends A {\n" + " A test() { return super.test(); }\n" + "}\n" + "class D extends A {\n" + " A test() { return super.test(); }\n" + "}\n" }, "class B & class C & class D" ); this.runConformTest( new String[] { "A.java", "public abstract class A {\n" + " public abstract A test();\n" + "}\n" + "class H {\n" + " class M extends A {\n" + " public A test() { return null; }\n" + " }\n" + "}\n" }, "" ); this.runConformTest( new String[] { "X.java", "public class X extends java.util.AbstractMap {\n" + " public java.util.Set entrySet() { return null; }\n" + "}\n" }, "" ); this.runNegativeTest( new String[] { "X.java", "public class X {\n" + " public static void main(String[] args) {\n" + " System.out.print(new C().test().getClass());\n" + " }\n" + "}\n" + "class A {\n" + " A test() { return this; }\n" + "}\n" + "class C extends A {\n" + " A test() { return super.test(); }\n" + "}\n" }, "----------\n" + "1. WARNING in X.java (at line 10)\n" + " A test() { return super.test(); }\n" + " ^\n" + "Type safety: The return type A for test() from the type C needs unchecked conversion to conform to A from the type A\n" + "----------\n" // warning: test() in C overrides test() in A; return type requires unchecked conversion ); } // https://bugs.eclipse.org/bugs/show_bug.cgi?id=82102 public void test027() { this.runConformTest( new String[] { "X.java", "public class X { void test() {} }\n" + "class Y extends X { void test() {} }\n" }, "" ); this.runNegativeTest( new String[] { "X.java", "public class X { void test() {} }\n" + "class Y extends X { void test() {} }\n" }, "----------\n" + "1. ERROR in X.java (at line 2)\n" + " class Y extends X { void test() {} }\n" + " ^^^^^^\n" + "Name clash: The method test() of type Y has the same erasure as test() of type X but does not override it\n" + "----------\n" // name clash: foo() in Y and foo() in X have the same erasure, yet neither overrides the other ); this.runNegativeTest( new String[] { "X.java", "public class X { void test(T o) {} }\n" + "class Y extends X { void test(Object o) {} }\n" }, "----------\n" + "1. ERROR in X.java (at line 2)\r\n" + " class Y extends X { void test(Object o) {} }\r\n" + " ^^^^^^^^^^^^^^\n" + "Name clash: The method test(Object) of type Y has the same erasure as test(T) of type X but does not override it\n" + "----------\n" // no error unless you try to do a super send which then fails ); this.runNegativeTest( new String[] { "X.java", "public class X { void test(T o, T t) {} }\n" + "class Y extends X { void test(Object o, T t) {} }\n" }, "----------\n" + "1. ERROR in X.java (at line 2)\r\n" + " class Y extends X { void test(Object o, T t) {} }\r\n" + " ^^^^^^^^^^^^^^^^^^^\n" + "Name clash: The method test(Object, T) of type Y has the same erasure as test(T, T) of type X but does not override it\n" + "----------\n" // name clash: test(java.lang.Object,T) in Y and test(T,T) in X have the same erasure, yet neither overrides the other ); this.runNegativeTest( new String[] { "X.java", "public class X {\n" + " void test() {\n" + " Pair p = new InvertedPair();\n" + " p.setA(new Double(1.1));\n" + " }\n" + "}\n" + "class Pair {\n" + " public void setA(A a) {}\n" + "}\n" + "class InvertedPair extends Pair {\n" + " public void setA(A a) {}\n" + "}\n" }, "----------\n" + "1. ERROR in X.java (at line 11)\n" + " public void setA(A a) {}\n" + " ^^^^^^^^^\n" + "Name clash: The method setA(A) of type InvertedPair has the same erasure as setA(A) of type Pair but does not override it\n" + "----------\n" // name clash: setA(A) in InvertedPair and setA(A) in Pair have the same erasure, yet neither overrides the other ); } // https://bugs.eclipse.org/bugs/show_bug.cgi?id=81727 public void test028() { this.runConformTest( new String[] { "X.java", "public class X implements I{\n" + " public X foo() { return null; }\n" + "}\n" + "interface I { T foo(); }\n" }, "" ); } // https://bugs.eclipse.org/bugs/show_bug.cgi?id=81568 public void test029() { this.runConformTest( new String[] { "I.java", "public interface I {\n" + " public I clone();\n" + "}\n" + "interface J extends I {}\n" }, "" ); } // https://bugs.eclipse.org/bugs/show_bug.cgi?id=81535 public void test030() { java.util.Map options = super.getCompilerOptions(); options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_4); this.runConformTest( new String[] { "X.java", "import java.io.OutputStreamWriter;\n" + "import java.io.PrintWriter;\n" + "public class X extends PrintWriter implements Runnable {\n" + " public X(OutputStreamWriter out, boolean flag) { super(out, flag); }\n" + " public void run() {}\n" + "}\n" }, "", null, // use default class-path false, // do not flush previous output dir content null, // no special vm args options, null ); } // https://bugs.eclipse.org/bugs/show_bug.cgi?id=80743 public void test031() { this.runNegativeTest( new String[] { "X.java", "interface X { long hashCode(); }\n" }, "----------\n" + "1. ERROR in X.java (at line 1)\r\n" + " interface X { long hashCode(); }\r\n" + " ^^^^^^^^^^\n" + "The return type is incompatible with Object.hashCode()\n" + "----------\n" // hashCode() in X cannot override hashCode() in java.lang.Object; attempting to use incompatible return type ); } // https://bugs.eclipse.org/bugs/show_bug.cgi?id=80736 public void test032() { // NOTE: javac only reports these errors when the problem type follows the bounds // if the type X is defined first, then no errors are reported this.runNegativeTest( new String[] { "X.java", "interface I { Float foo(); }\n" + "interface J { Integer foo(); }\n" + "public class X {}\n" }, "----------\n" + "1. ERROR in X.java (at line 3)\r\n" + " public class X {}\r\n" + " ^\n" + "The return type is incompatible with J.foo(), I.foo()\n" + "----------\n" // types J and I are incompatible; both define foo(), but with unrelated return types ); this.runNegativeTest( new String[] { "X.java", "interface I { String foo(); }\n" + "class A { public Object foo() { return null; } }" + "public class X {}\n" }, "----------\n" + "1. ERROR in X.java (at line 2)\r\n" + " class A { public Object foo() { return null; } }public class X {}\r\n" + " ^\n" + "The return type is incompatible with I.foo(), A.foo()\n" + "----------\n" // foo() in A cannot implement foo() in I; attempting to use incompatible return type ); } // https://bugs.eclipse.org/bugs/show_bug.cgi?id=80745 public void test033() { this.runConformTest( new String[] { "X.java", "interface I { Number foo(); }\n" + "interface J { Integer foo(); }\n" + "public class X implements I, J {\n" + " public Integer foo() {return 1;}\n" + " public static void main(String argv[]) {\n" + " I i = null;\n" + " J j = null;\n" + " System.out.print(i instanceof J);\n" + " System.out.print('=');\n" + " System.out.print(j instanceof I);\n" + " }\n" + "}\n" }, "false=false" ); this.runConformTest( new String[] { "X.java", "interface I { Number foo(A a); }\n" + "interface J { Integer foo(A a); }\n" + "class A{}\n" + "public class X implements I, J {\n" + " public Integer foo(A a) {return 1;}\n" + " public static void main(String argv[]) {\n" + " I i = null;\n" + " J j = null;\n" + " System.out.print(i instanceof J);\n" + " System.out.print('=');\n" + " System.out.print(j instanceof I);\n" + " }\n" + "}\n" }, "false=false" ); } // https://bugs.eclipse.org/bugs/show_bug.cgi?id=81332 public void test034() { this.runConformTest( new String[] { "B.java", "interface I> { void test(E element); }\n" + "class A implements I { public void test(Integer i) {} }\n" + "public class B extends A { public void test(String i) {} }\n" }, "" ); this.runConformTest( new String[] { "B.java", "interface I { void test(E element); }\n" + "class A { public void test(Integer i) {} }\n" + "public class B extends A implements I {}\n" + "class C extends B { public void test(Object i) {} }\n" }, "" ); this.runNegativeTest( new String[] { "B.java", "interface I { void test(E element); }\n" + "class A { public void test(Integer i) {} }\n" + "public class B extends A implements I { public void test(Comparable i) {} }\n" }, "----------\n" + "1. ERROR in B.java (at line 3)\n" + " public class B extends A implements I { public void test(Comparable i) {} }\n" + " ^^^^^^^^^^^^^^^^^^\n" + "Name clash: The method test(Comparable) of type B has the same erasure as test(E) of type I but does not override it\n" + "----------\n" // name clash: test(java.lang.Comparable) in B and test(E) in I have the same erasure, yet neither overrides the other ); this.runNegativeTest( new String[] { "B.java", "interface I> { void test(E element); }\n" + "class A implements I { public void test(Integer i) {} }\n" + "public class B extends A { public void test(Comparable i) {} }\n" }, "----------\n" + "1. ERROR in B.java (at line 3)\n" + " public class B extends A { public void test(Comparable i) {} }\n" + " ^^^^^^^^^^^^^^^^^^\n" + "Name clash: The method test(Comparable) of type B has the same erasure as test(E) of type I but does not override it\n" + "----------\n" // name clash: test(java.lang.Comparable) in B and test(E) in I have the same erasure, yet neither overrides the other ); this.runNegativeTest( new String[] { "B.java", "abstract class AA { abstract void test(E element); }\n" + "class A extends AA { public void test(Integer i) {} }\n" + "public class B extends A { public void test(Comparable i) {} }\n" }, "----------\n" + "1. ERROR in B.java (at line 3)\n" + " public class B extends A { public void test(Comparable i) {} }\n" + " ^^^^^^^^^^^^^^^^^^\n" + "Name clash: The method test(Comparable) of type B has the same erasure as test(E) of type AA but does not override it\n" + "----------\n" // name clash: test(java.lang.Comparable) in B and test(E) in AA have the same erasure, yet neither overrides the other ); } // https://bugs.eclipse.org/bugs/show_bug.cgi?id=80626 public void test035() { this.runNegativeTest( new String[] { "E.java", "interface I{ int compareTo(U o); }\n" + "abstract class F> implements I{ public final int compareTo(T o) { return 0; } }\n" + "public class E extends F { public int compareTo(Object o) { return 0; } }\n" }, "----------\n" + "1. ERROR in E.java (at line 3)\n" + " public class E extends F { public int compareTo(Object o) { return 0; } }\n" + " ^^^^^^^^^^^^^^^^^^^\n" + "Name clash: The method compareTo(Object) of type E has the same erasure as compareTo(U) of type I but does not override it\n" + "----------\n" // name clash: compareTo(java.lang.Object) in E and compareTo(U) in I have the same erasure, yet neither overrides the other ); this.runNegativeTest( new String[] { "X.java", "public enum X {\n" + " ;\n" + " public int compareTo(Object o) { return 0; }\n" + "}\n" }, "----------\n" + "1. ERROR in X.java (at line 3)\n" + " public int compareTo(Object o) { return 0; }\n" + " ^^^^^^^^^^^^^^^^^^^\n" + "Name clash: The method compareTo(Object) of type X has the same erasure as compareTo(T) of type Comparable but does not override it\n" + "----------\n" // name clash: compareTo(java.lang.Object) in X and compareTo(T) in java.lang.Comparable have the same erasure, yet neither overrides the other ); } // https://bugs.eclipse.org/bugs/show_bug.cgi?id=83162 public void test036() { // 2 interface cases // no bridge methods are created in these conform cases so no name clashes can occur this.runConformTest( new String[] { "X.java", "class X implements Equivalent, EqualityComparable {\n" + " public boolean equalTo(Object other) { return true; }\n" + "}\n" + "abstract class Y implements Equivalent, EqualityComparable {}\n" + "class Z extends Y {\n" + " public boolean equalTo(Object other) { return true; }\n" + "}\n" + "interface Equivalent { boolean equalTo(T other); }\n" + "interface EqualityComparable { boolean equalTo(T other); }\n" }, "" ); this.runConformTest( new String[] { "X.java", "class X implements Equivalent, EqualityComparable {\n" + " public boolean equalTo(Comparable other) { return true; }\n" + " public boolean equalTo(Number other) { return true; }\n" + "}\n" + "abstract class Y implements Equivalent, EqualityComparable {}\n" + "class Z extends Y {\n" + " public boolean equalTo(Comparable other) { return true; }\n" + " public boolean equalTo(Number other) { return true; }\n" + "}\n" + "interface Equivalent { boolean equalTo(T other); }\n" + "interface EqualityComparable { boolean equalTo(T other); }\n" }, "" ); this.runConformTest( new String[] { "X.java", "class X implements Equivalent, EqualityComparable {\n" + " public boolean equalTo(S other) { return true; }\n" + "}\n" + "abstract class Y implements Equivalent, EqualityComparable {}\n" + "class Z extends Y {\n" + " public boolean equalTo(U other) { return true; }\n" + "}\n" + "interface Equivalent { boolean equalTo(T other); }\n" + "interface EqualityComparable { boolean equalTo(T other); }\n" }, "" ); this.runConformTest( new String[] { "X.java", "class X implements Equivalent, EqualityComparable {\n" + " public boolean equalTo(T other) { return true; }\n" + " public boolean equalTo(S other) { return true; }\n" + "}\n" + "abstract class Y implements Equivalent, EqualityComparable {}\n" + "class Z extends Y {\n" + " public boolean equalTo(U other) { return true; }\n" + " public boolean equalTo(V other) { return true; }\n" + "}\n" + "interface Equivalent { boolean equalTo(T other); }\n" + "interface EqualityComparable { boolean equalTo(S other); }\n" }, "" ); // in these cases, bridge methods are needed once abstract/concrete methods are defiined (either in the abstract class or a concrete subclass) this.runConformTest( new String[] { "Y.java", "abstract class Y implements Equivalent, EqualityComparable {\n" + " public abstract boolean equalTo(Number other);\n" + "}\n" + "interface Equivalent { boolean equalTo(T other); }\n" + "interface EqualityComparable { boolean equalTo(T other); }\n" }, "" // no bridge methods are created here since Y does not define an equalTo(?) method which equals an inherited equalTo method ); this.runNegativeTest( new String[] { "Y.java", "abstract class Y implements Equivalent, EqualityComparable {\n" + " public abstract boolean equalTo(Object other);\n" + "}\n" + "interface Equivalent { boolean equalTo(T other); }\n" + "interface EqualityComparable { boolean equalTo(T other); }\n" }, "----------\n" + "1. ERROR in Y.java (at line 2)\n" + " public abstract boolean equalTo(Object other);\n" + " ^^^^^^^^^^^^^^^^^^^^^\n" + "Name clash: The method equalTo(Object) of type Y has the same erasure as equalTo(T) of type Equivalent but does not override it\n" + "----------\n" + "2. ERROR in Y.java (at line 2)\n" + " public abstract boolean equalTo(Object other);\n" + " ^^^^^^^^^^^^^^^^^^^^^\n" + "Name clash: The method equalTo(Object) of type Y has the same erasure as equalTo(T) of type EqualityComparable but does not override it\n" + "----------\n" // name clash: equalTo(java.lang.Object) in Y and equalTo(T) in Equivalent have the same erasure, yet neither overrides the other ); // NOTE: javac has a bug, reverse the implemented interfaces & the name clash goes away // but eventually when a concrete subclass must define the remaining method, the error shows up this.runNegativeTest( new String[] { "Y.java", "abstract class Y implements Equivalent, EqualityComparable {\n" + " public abstract boolean equalTo(String other);\n" + "}\n" + "interface Equivalent { boolean equalTo(T other); }\n" + "interface EqualityComparable { boolean equalTo(T other); }\n" }, "----------\n" + "1. ERROR in Y.java (at line 1)\n" + " abstract class Y implements Equivalent, EqualityComparable {\n" + " ^\n" + "Name clash: The method equalTo(T) of type Equivalent has the same erasure as equalTo(T) of type EqualityComparable but does not override it\n" + "----------\n" // name clash: equalTo(T) in Equivalent and equalTo(T) in EqualityComparable have the same erasure, yet neither overrides the other ); this.runNegativeTest( new String[] { "Y.java", "abstract class Y implements EqualityComparable, Equivalent {\n" + " public boolean equalTo(Integer other) { return true; }\n" + "}\n" + "interface Equivalent { boolean equalTo(T other); }\n" + "interface EqualityComparable { boolean equalTo(T other); }\n" }, "----------\n" + "1. ERROR in Y.java (at line 1)\n" + " abstract class Y implements EqualityComparable, Equivalent {\n" + " ^\n" + "Name clash: The method equalTo(T) of type EqualityComparable has the same erasure as equalTo(T) of type Equivalent but does not override it\n" + "----------\n" // name clash: equalTo(T) in EqualityComparable and equalTo(T) in Equivalent have the same erasure, yet neither overrides the other ); } public void test037() { // test inheritance scenarios this.runConformTest( new String[] { "X.java", "public abstract class X implements I, J { }\n" + "abstract class Y implements J, I { }\n" + "abstract class Z implements K { }\n" + "class YYY implements J, I { public void foo(A a) {} }\n" + "class XXX implements I, J { public void foo(A a) {} }\n" + "class ZZZ implements K { public void foo(A a) {} }\n" + "interface I { void foo(A a); }\n" + "interface J { void foo(A a); }\n" + "interface K extends I { void foo(A a); }\n" + "class A {}" }, "" ); this.runNegativeTest( new String[] { "XX.java", "public abstract class XX implements I, J { public abstract void foo(A a); }\n" + "interface I { void foo(A a); }\n" + "interface J { void foo(A a); }\n" + "class A {}" }, "----------\n" + "1. ERROR in XX.java (at line 1)\r\n" + " public abstract class XX implements I, J { public abstract void foo(A a); }\r\n" + " ^^^^^^^^^^^^^^^^\n" + "Name clash: The method foo(A) of type XX has the same erasure as foo(A) of type I but does not override it\n" + "----------\n" // name clash: foo(A) in XX and foo(A) in I have the same erasure, yet neither overrides the other ); this.runNegativeTest( new String[] { "XX.java", "public class XX implements I, J { public void foo(A a) {} }\n" + "class YY implements J, I { public void foo(A a) {} }\n" + "class ZZ implements K { public void foo(A a) {} }\n" + "interface I { void foo(A a); }\n" + "interface J { void foo(A a); }\n" + "interface K extends I { void foo(A a); }\n" + "class A {}" }, "----------\n" + "1. ERROR in XX.java (at line 1)\n" + " public class XX implements I, J { public void foo(A a) {} }\n" + " ^^\n" + "The type XX must implement the inherited abstract method I.foo(A)\n" + "----------\n" + "2. ERROR in XX.java (at line 1)\n" + " public class XX implements I, J { public void foo(A a) {} }\n" + " ^^^^^^^^^^^^^^^^\n" + "Name clash: The method foo(A) of type XX has the same erasure as foo(A) of type I but does not override it\n" + "----------\n" + "3. ERROR in XX.java (at line 2)\n" + " class YY implements J, I { public void foo(A a) {} }\n" + " ^^\n" + "The type YY must implement the inherited abstract method I.foo(A)\n" + "----------\n" + "4. ERROR in XX.java (at line 2)\n" + " class YY implements J, I { public void foo(A a) {} }\n" + " ^^^^^^^^^^^^^^^^\n" + "Name clash: The method foo(A) of type YY has the same erasure as foo(A) of type I but does not override it\n" + "----------\n" + "5. ERROR in XX.java (at line 3)\n" + " class ZZ implements K { public void foo(A a) {} }\n" + " ^^\n" + "The type ZZ must implement the inherited abstract method I.foo(A)\n" + "----------\n" + "6. ERROR in XX.java (at line 3)\n" + " class ZZ implements K { public void foo(A a) {} }\n" + " ^^^^^^^^^^^^^^^^\n" + "Name clash: The method foo(A) of type ZZ has the same erasure as foo(A) of type I but does not override it\n" + "----------\n" // XX/YY/ZZ is not abstract and does not override abstract method foo(A) in I ); this.runNegativeTest( new String[] { "X.java", "public abstract class X extends Y implements I { }\n" + "interface I { void foo(A a); }\n" + "class Y { void foo(A a) {} }\n" + "class A {}" }, "----------\n" + "1. ERROR in X.java (at line 1)\r\n" + " public abstract class X extends Y implements I { }\r\n" + " ^\n" + "Name clash: The method foo(A) of type Y has the same erasure as foo(A) of type I but does not override it\n" + "----------\n" // name clash: foo(A) in Y and foo(A) in I have the same erasure, yet neither overrides the other ); this.runNegativeTest( new String[] { "X.java", "public abstract class X extends Y implements I { }\n" + "interface I { void foo(A a); }\n" + "class Y { void foo(A a) {} }\n" + "class A {}" }, "----------\n" + "1. ERROR in X.java (at line 1)\r\n" + " public abstract class X extends Y implements I { }\r\n" + " ^\n" + "The inherited method Y.foo(A) cannot hide the public abstract method in I\n" + "----------\n" // foo(A) in Y cannot implement foo(A) in I; attempting to assign weaker access privileges; was public ); this.runNegativeTest( new String[] { "X.java", "public abstract class X extends Y implements I { }\n" + "interface I { void foo(T t); }\n" + "class Y { void foo(T t) {} }\n" }, "----------\n" + "1. ERROR in X.java (at line 1)\r\n" + " public abstract class X extends Y implements I { }\r\n" + " ^\n" + "Name clash: The method foo(T) of type Y has the same erasure as foo(T) of type I but does not override it\n" + "----------\n" // name clash: foo(T) in Y and foo(T) in I have the same erasure, yet neither overrides the other ); } public void test038() { this.runConformTest( new String[] { "X.java", "public class X extends H { void foo(A a) { super.foo(a); } }\n" + "class H { void foo(A a) {} }\n" + "class A {}" }, "" ); this.runNegativeTest( new String[] { "X.java", "public class X extends H { void foo(A a) {} }\n" + "class H { void foo(A a) {} }\n" + "class A {}" }, "----------\n" + "1. ERROR in X.java (at line 1)\r\n" + " public class X extends H { void foo(A a) {} }\r\n" + " ^^^^^^^^^^^\n" + "Name clash: The method foo(A) of type X has the same erasure as foo(A) of type H but does not override it\n" + "----------\n" // name clash: foo(A) in X and foo(A) in H have the same erasure, yet neither overrides the other // with public class X extends H { void foo(A a) { super.foo(a); } } // foo(A) in H cannot be applied to (A) ); } // https://bugs.eclipse.org/bugs/show_bug.cgi?id=83573 public void test039() { this.runConformTest( new String[] { "X.java", "public class X {\n" + " public static void main(String[] args) {\n" + " Test test = new Test();\n" + " This test2 = new Test();\n" + " System.out.println(test.get());\n" + " }\n" + " interface This {\n" + " public Object get();\n" + " }\n" + " \n" + " interface That extends This {\n" + " public String get();\n" + " \n" + " }\n" + " \n" + " static class Test implements That {\n" + " \n" + " public String get() {\n" + " return \"That\";\n" + " \n" + " }\n" + " }\n" + "}\n" }, "That" ); } // https://bugs.eclipse.org/bugs/show_bug.cgi?id=83218 public void test040() { this.runNegativeTest( new String[] { "Base.java", "interface Base { Base proc(); }\n" + "abstract class Derived implements Base { public abstract Derived proc(); }\n" }, "" // no warnings ); this.runNegativeTest( new String[] { "A.java", "class A { T test() { return null; } }\n" + "class B extends A { Integer test() { return 1; } }\n" }, "----------\n" + "1. WARNING in A.java (at line 2)\n" + " class B extends A { Integer test() { return 1; } }\n" + " ^^^^^^^\n" + "Type safety: The return type Integer for test() from the type B needs unchecked conversion to conform to T from the type A\n" + "----------\n" // warning: test() in B overrides test() in A; return type requires unchecked conversion ); this.runNegativeTest( new String[] { "A.java", "import java.util.*;\n" + "class A { List getList() { return null; } }\n" + "class B extends A { List getList() { return null; } }\n" }, "----------\n" + "1. WARNING in A.java (at line 3)\n" + " class B extends A { List getList() { return null; } }\n" + " ^^^^\n" + "Type safety: The return type List for getList() from the type B needs unchecked conversion to conform to List from the type A\n" + "----------\n" // unchecked warning on B.getList() ); this.runNegativeTest( new String[] { "X.java", "interface X { X x(); }\n" + "abstract class Y implements X { public abstract X x(); }\n" + // warning: x() in Y implements x() in X; return type requires unchecked conversion "abstract class Z implements X { public abstract X x(); }\n" }, "----------\n" + "1. WARNING in X.java (at line 2)\n" + " abstract class Y implements X { public abstract X x(); }\n" + " ^\n" + "Type safety: The return type X for x() from the type Y needs unchecked conversion to conform to X from the type X\n" + "----------\n" ); this.runNegativeTest( new String[] { "X.java", "interface X { X[] x(); }\n" + "abstract class Y implements X { public abstract X[] x(); }\n" + // warning: x() in Y implements x() in X; return type requires unchecked conversion "abstract class Z implements X { public abstract X[] x(); }\n" }, "----------\n" + "1. WARNING in X.java (at line 2)\n" + " abstract class Y implements X { public abstract X[] x(); }\n" + " ^^^\n" + "Type safety: The return type X[] for x() from the type Y needs unchecked conversion to conform to X[] from the type X\n" + "----------\n" ); } // https://bugs.eclipse.org/bugs/show_bug.cgi?id=83902 public void test041() { // inherited cases for bridge methods, varargs clashes, return type conversion checks this.runNegativeTest( new String[] { "X.java", "public class X { public void foo(String... n) {} }\n" + "interface I { void foo(String[] n); }\n" + "class Y extends X implements I { }\n" }, "----------\n" + "1. WARNING in X.java (at line 3)\n" + " class Y extends X implements I { }\n" + " ^\n" + "Varargs methods should only override other varargs methods unlike X.foo(String...) and I.foo(String[])\n" + "----------\n" // warning: foo(java.lang.String...) in X cannot implement foo(java.lang.String[]) in I; overridden method has no '...' ); this.runNegativeTest( new String[] { "X.java", "public class X { public void foo(String[] n) {} }\n" + "interface I { void foo(String... n); }\n" + "class Y extends X implements I { }\n" }, "----------\n" + "1. WARNING in X.java (at line 3)\n" + " class Y extends X implements I { }\n" + " ^\n" + "Varargs methods should only override other varargs methods unlike X.foo(String[]) and I.foo(String...)\n" + "----------\n" // warning: foo(java.lang.String[]) in X cannot implement foo(java.lang.String...) in I; overriding method is missing '...' ); this.runConformTest( new String[] { "X.java", "public class X {\n" + " public Y foo() {\n" + " System.out.println(\"SUCCESS\");\n" + " return null;\n" + " }\n" + " public static void main(String[] args) {\n" + " ((I) new Y()).foo();\n" + " }\n" + "}\n" + "interface I { X foo(); }\n" + "class Y extends X implements I { }\n" }, "SUCCESS" ); this.runNegativeTest( new String[] { "X.java", "public class X { public A foo() { return null; } }\n" + "interface I { A foo(); }\n" + "class Y extends X implements I { }\n" + "class A { }\n" }, "----------\n" + "1. WARNING in X.java (at line 3)\n" + " class Y extends X implements I { }\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" // warning: foo() in X implements foo() in I; return type requires unchecked conversion ); this.runNegativeTest( new String[] { "X.java", "public class X { public Object foo() { return null; } }\n" + "interface I { T foo(); }\n" + "class Y extends X implements I { }\n" }, "----------\n" + "1. WARNING in X.java (at line 3)\n" + " class Y extends X implements I { }\n" + " ^\n" + "Type safety: The return type Object for foo() from the type X needs unchecked conversion to conform to T from the type I\n" + "----------\n" // NOTE: javac issues an error & a warning which contradict each other // if the method Object foo() is implemented in Y then only the warning is issued, so X should be allowed to implement the method // Y is not abstract and does not override abstract method foo() in I // warning: foo() in X implements foo() in I; return type requires unchecked conversion ); } // https://bugs.eclipse.org/bugs/show_bug.cgi?id=85930 public void _test042() { this.runConformTest( new String[] { "X.java", "interface Callable\n" + "{\n" + " public enum Result { GOOD, BAD };\n" + " public Result call(T arg);\n" + "}\n" + "\n" + "public class X implements Callable\n" + "{\n" + " public Result call(String arg) { return Result.GOOD; } // Warning line\n" + "}\n" }, "" ); } // https://bugs.eclipse.org/bugs/show_bug.cgi?id=72704 public void test043() { // ambiguous message sends because of substitution from 2 different type variables this.runNegativeTest( new String[] { "X.java", "public class X { void test(E e) { e.id(new Integer(1)); } }\n" + "abstract class C { public abstract void id(A x); }\n" + "interface I { void id(B x); }\n" + "abstract class E extends C implements I {}\n" }, "----------\n" + "1. ERROR in X.java (at line 4)\r\n" + " abstract class E extends C implements I {}\r\n" + " ^\n" + "Name clash: The method id(A) of type C has the same erasure as id(B) of type I but does not override it\n" + "----------\n" // javac won't report it until C.id() is made concrete or implemented in E ); this.runNegativeTest( new String[] { "X.java", "public class X { void test(E e) { e.id(new Integer(2)); } }\n" + "abstract class C { public abstract void id(A x); }\n" + "interface I { void id(B x); }\n" + "abstract class E extends C implements I {}\n" }, "----------\n" + "1. ERROR in X.java (at line 1)\r\n" + " public class X { void test(E e) { e.id(new Integer(2)); } }\r\n" + " ^^\n" + "The method id(Integer) is ambiguous for the type E\n" + "----------\n" // reference to id is ambiguous, both method id(A) in C and method id(B) in I match ); this.runNegativeTest( new String[] { "X.java", "public class X { void test(E e) { e.id(new Integer(111)); } }\n" + "abstract class C { public void id(A x) {} }\n" + "interface I { void id(B x); }\n" + "class E extends C implements I { public void id(B b) {} }\n" }, "----------\n" + "1. ERROR in X.java (at line 1)\r\n" + " public class X { void test(E e) { e.id(new Integer(111)); } }\r\n" + " ^^\n" + "The method id(Integer) is ambiguous for the type E\n" + "----------\n" // reference to id is ambiguous, both method id(A) in C and method id(B) in E match ); this.runNegativeTest( new String[] { "X.java", "public class X {\n" + " void test(E e) { e.id(new Integer(111)); }\n" + " void test(M m) {\n" + " m.id(new Integer(111));\n" + " ((E) m).id(new Integer(111));\n" + " }\n" + " void test(N n) { n.id(new Integer(111)); }\n" + "}\n" + "abstract class C { public void id(A x) {} }\n" + "interface I { void id(B x); }\n" + "abstract class E extends C implements I {}\n" + "class M extends E { public void id(B b) {} }\n" + "abstract class N extends E { public void id(T n) {} }\n" }, "----------\n" + "1. ERROR in X.java (at line 4)\r\n" + " m.id(new Integer(111));\r\n" + " ^^\n" + "The method id(Integer) is ambiguous for the type M\n" + "----------\n" // reference to id is ambiguous, both method id(A) in C and method id(B) in M match ); } }