Bug 206930 - [1.5][compiler] Mismatch between javac and Eclipse compiler
Summary: [1.5][compiler] Mismatch between javac and Eclipse compiler
Status: VERIFIED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 3.4   Edit
Hardware: PC Windows XP
: P3 normal (vote)
Target Milestone: 3.5 M6   Edit
Assignee: Kent Johnson CLA
QA Contact:
URL:
Whiteboard:
Keywords:
: 166355 282101 (view as bug list)
Depends on:
Blocks:
 
Reported: 2007-10-19 13:56 EDT by Olivier Thomann CLA
Modified: 2014-02-08 01:29 EST (History)
3 users (show)

See Also:


Attachments
Proposed patch and testcase (14.45 KB, patch)
2009-02-20 15:15 EST, Kent Johnson CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Olivier Thomann CLA 2007-10-19 13:56:28 EDT
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.
Comment 1 Philipe Mulet CLA 2007-10-19 17:47:22 EDT
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> {}
Comment 2 Kent Johnson CLA 2008-03-27 16:33:46 EDT
Similar to bug 214558 but is not fixed with the same patch
Comment 3 Kent Johnson CLA 2008-03-28 11:40:03 EDT
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) {}
}
Comment 4 Kent Johnson CLA 2008-03-28 11:50:45 EDT
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.
Comment 5 Kent Johnson CLA 2008-03-28 12:01:54 EDT
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) {}
}
Comment 6 Kent Johnson CLA 2009-02-20 14:50:20 EST
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());
    }
}
Comment 7 Kent Johnson CLA 2009-02-20 14:53:12 EST
*** Bug 166355 has been marked as a duplicate of this bug. ***
Comment 8 Kent Johnson CLA 2009-02-20 15:15:40 EST
Created attachment 126344 [details]
Proposed patch and testcase
Comment 9 Kent Johnson CLA 2009-02-20 16:27:22 EST
Fix and test released for 3.5M6
Comment 10 Frederic Fusier CLA 2009-03-09 12:41:38 EDT
Verified for 3.5M6 using I20090309-0100.
Comment 11 Kent Johnson CLA 2009-07-07 13:33:40 EDT
*** Bug 282101 has been marked as a duplicate of this bug. ***