Community
Participate
Working Groups
Build ID: I20070209-1006 Steps To Reproduce: 1. compile the code, it should not compile but it does. 2. run it, a CCE is thrown public class EclipseBug2 { enum MyEnum { value; } enum AnotherValue { value2; } static abstract class A<T> { abstract <U extends T> U empty(); } static class B extends A<Enum<?>> { @Override Enum<?> empty() { return MyEnum.value; } } public static void main(String[] args) { A<Enum<?>> a=new B(); AnotherValue value2 = a.empty(); } } More information: B.empty doesn't overrides A.empty but eclipse seems doesn't care about that ??. section 8.4.2 of the JLS clearly states that if B.empty overrides A.empty, they must have the same number of parameter types.
Note that javac 1.5.0_11, 1.6.0_01 and 1.7b06 also accept it.
Oups, i have forgiven to test with javac. Do you have reported this bug in SUN database or should i do it ? Rémi
Please do so, you found the problem, and deserve credits for it.
(In reply to comment #3) > Please do so, you found the problem, and deserve credits for it. > Ok, i will post the SUN bug id here when it will be available. About the credits, are you taking about respect or due ? SUN already send me a workstation and i don't think i can have more credits :) I have just wanted to avoid duplicates. Rémi
the SUN bug id is 6526545. http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6526545 Rémi
Reading JLS 3 § 8.4.2, it seems to me that the signature of B#empty() is a subsignature of the signature of A#empty() (because the erasure erases the type parameters). If I am right, then the code must compile. Nevertheless, javac reports an unchecked conversion that should draw the user attention onto the incumbent CCE, and we don't. I will further stress an early patch I have that enables us to do that (warn about the unchecked conversion) and post progress here. Please speak up if I have missed something.
(In reply to comment #6) > Reading JLS 3 § 8.4.2, it seems to me that the signature of B#empty() is a > subsignature of the signature of A#empty() (because the erasure erases the type > parameters). A#empty() is override equivalent to B#empty() if A#empty() == erasure(B#empty()) or B#empty() == erasure(A#empty()) because A#empty() and B#empty() are both generics, they can not be override equivalent. > If I am right, then the code must compile. > Nevertheless, javac reports an unchecked conversion that should draw the user > attention onto the incumbent CCE, and we don't. I will further stress an early > patch I have that enables us to do that (warn about the unchecked conversion) > and post progress here. an error must be reported here, not an unchecked conversion. > Please speak up if I have missed something. > Rémi
(In reply to comment #7) > (In reply to comment #6) > > Reading JLS 3 § 8.4.2, it seems to me that the signature of B#empty() is a > > subsignature of the signature of A#empty() (because the erasure erases the type > > parameters). > > A#empty() is override equivalent to B#empty() > if A#empty() == erasure(B#empty()) or > B#empty() == erasure(A#empty()) Let us note the 'has same signature as' relationship as '<=>'. erasure(A#empty) <=> B#empty iff: a) they have the same name (which is true); and b) they have the same argument types, which is true if all of the following is true: b1) they have the same number of formal parameters (true: 0); b2) they have the same number of type parameters (true: 0); b3) bound check condition, which we don't care since we have no type parameter left. Hence B#empty <=> erasure(A#empty) and comment #6 should hold?
ok, forget my last comment. > Let us note the 'has same signature as' relationship as '<=>'. > erasure(A#empty) <=> B#empty iff: > a) they have the same name (which is true); > and > b) they have the same argument types, which is true if all of the following is > true: > b1) they have the same number of formal parameters (true: 0); > b2) they have the same number of type parameters (true: 0); oups, A#empty() has one type parameter (T) and B#empty() zero. > b3) bound check condition, which we don't care since we have no type > parameter left. > Hence B#empty <=> erasure(A#empty) and comment #6 should hold? > so B#empty <=> erasure(A#empty) Rémi
Changing the title to reflect the problem analysis results.
(In reply to comment #10) > Changing the title to reflect the problem analysis results. > Daniel, i agree with your analysis if the code is this one : public class OverrideGenerics { static abstract class A<T> { abstract <U extends T> U f(); } static class B extends A<Number> { @Override Number f() { return 3; } } } but in the submitted code, the return type of B#empty is not the raw type Enum but Enum<?>, so for me erasure(bridge(A#empty)) => Enum empty() and B#empty => Enum<?> so there is no overriding here.
If I am right, the return type is not considered as far as establishing the subsignature property is concerned (JLS 3 § 8.4.2).
Created attachment 60532 [details] Tentative fix This fix adds a parameter to method substitution so as to decide whether closest matches should use upper bound or erasure types when the type parameters numbers do not match. This may be a rather crude approach to the issue, but it yields results and should kick the discussion off.
Created attachment 60533 [details] Test case modifications
Kent, any thoughts?
Created attachment 61057 [details] Tentative fix + test case Patch refresh on HEAD.
Created attachment 61146 [details] Alternative patch Not sure why the previous test was separated onto 2 lines...
Not sure either, since the test for the bug that change fixed (83218) passes with your patch, which is far more elegant than mine. Will release it for M7 after running full tests.
Released for 3.3 M7.
Verified for 3.3M7 using I20070427-0010