Community
Participate
Working Groups
javac reports an error for the following test case where the Eclipse compiler simply reports a warning that is not related to the error reported by javac. interface A<T> { } class B { void foo(A<?> x) { } } class D implements A { } public class X extends B { void bar() { foo(new D()); } void foo(D d) { } } The Eclipse compiler from HEAD reports: ---------- 1. WARNING in D:\tests_sources\X.java (at line 9) class D implements A { ^ A is a raw type. References to generic type A<T> should be parameterized ---------- where javac 1.5, 1.6 and 1.7 report: X.java:13: reference to foo is ambiguous, both method foo(A<?>) in B and method foo(D) in X match foo(new D()); ^ 1 error D can also be defined as a static member of the class X with the same error.
It seems that the presence of the raw type A (as superclass of D) is causing grief... Smells like a bug in javac... No error for: class C extends B { void test() { remove(new D()); } void remove(D x) {} private static final class D implements A {} } class B { void remove(A x) {} } interface A {} No error for: class C extends B { void test() { remove(new D()); } void remove(D x) {} private static final class D implements A<Object> {} } class B { void remove(A<?> x) {} } interface A<T> {}
Similar to bug 214558 but is not fixed with the same patch
Philippe - for these 2 types : interface A<T> {} class D implements A {} Any idea how we can see a reference to D as a raw type or at least as a 'backwards compatible' or 'has raw hierarchy ref' type? New tag bit? Cause until D is converted to a generic type, it appears we need to skip an exact match. But I'm not totally convinced since in this example when A & B are updated, D should still compile until its updated (old code was not supposed to be broken by adding generics): interface A<T> {} class B { void foo(A<?> x) {} } class D extends B implements A { void bar() { foo(new D()); } void foo(D d) {} }
Now I'm even less convinced that we should change. interface A<T> {} class B<T> { void foo1(A x) {} void foo2(A<?> x) {} <T> void foo3(A<T> x) {} void foo4(A<T> x) {} } class D extends B implements A { void bar() { foo1(new D()); foo2(new D()); foo3(new D()); foo4(new D()); } void foo1(D d) {} void foo2(D d) {} void foo3(D d) {} void foo4(D d) {} } None of these 4 method invocations reports an error. But if B is not a generic type, then foo2 & foo3 are ambiguous errors.
So here is an easier way to look at it - WHY the difference: interface A<T> {} class B { void foo(A<?> x) {} } class B2<T> { void foo(A<?> x) {} } class D extends B implements A { void bar() { foo(new D()); // ambiguous foo(A<?>) in B and foo(D) in D match } void foo(D d) {} } class D2 extends B2 implements A { void bar() { foo(new D()); // not ambiguous } void foo(D d) {} }
We do not report these 4 ambiguous calls that javac does: interface I<T> {} class A { void a(I x) {} void b(I<?> x) {} <U> void c(I<?> x) {} } class B extends A {} class C extends B implements I { void a(C c) {} void b(C c) {} void c(C c) {} } class D extends C { void test() { a(new C()); a(new D()); b(new C()); // ambiguous b(I<?>) in A and b(C) in C match b(new D()); // ambiguous b(I<?>) in A and b(C) in C match c(new C()); // ambiguous <U>c(I<?>) in A and c(C) in C match c(new D()); // ambiguous <U>c(I<?>) in A and c(C) in C match } } class A2<T> { void a(I x) {} void b(I<?> x) {} <U> void c(I<?> x) {} void d(I<T> x) {} } class B2 extends A2 {} class C2 extends B2 implements I { void a(C2 c) {} void b(C2 c) {} void c(C2 c) {} void d(C2 c) {} } class D2 extends C2 { void test() { a(new C2()); a(new D2()); b(new C2()); b(new D2()); c(new C2()); c(new D2()); d(new C2()); d(new D2()); } }
*** Bug 166355 has been marked as a duplicate of this bug. ***
Created attachment 126344 [details] Proposed patch and testcase
Fix and test released for 3.5M6
Verified for 3.5M6 using I20090309-0100.
*** Bug 282101 has been marked as a duplicate of this bug. ***