Community
Participate
Working Groups
The following code used to compile with javac 5, stopped compiling with javac6 and started compiling again with javac7. Eclipse HEAD and BETA_JAVA7 refuse to compile it: public class X { class A<T extends B<?>> { } class B<T extends A<?>> { D<? extends B<T>> x; } class D<T extends B<?>> {} <E extends B<?>> X(E x, D<B<A<?>>> d) { if (x.x == d) { return; } } } This behavior difference needs to be understood. If I change the line with the if to if (x.x == 1) javac7 spits out this message: X.java:10: error: incomparable types: X.D<CAP#1> and int if (x.x == 1) { ^ where CAP#1,CAP#2 are fresh type-variables: CAP#1 extends X.B<CAP#2> from capture of ? extends X.B<CAP#2> CAP#2 extends X.A<?> from capture of ? 1 error which offers some clue as to what javac thinks the type x.x should be. Eclipse thinks the type of x.x. is X.D<capture#2-of ? extends X.B<capture#1-of ?>> Notice the fact that the type A is missing in eclipse assessment of the type.
I'll investigate this.
Released disabled junit test org.eclipse.jdt.core.tests.compiler.regression.GenericsRegressionTest._test347426() into BETA_JAVA7 stream. I am investigating this.
Reduced test case: public class X<T> { class A<T extends X<?>> { B<? extends A<T>> x; } class B<T extends A<?>> {} boolean b = ((A<?>)null).x == ((B<A<X<?>>>)null); } How can there be a A<?> that is also not "? extends X<?>" ? It does look like a bug in eclipse. javac7 compiles this fine. Note however that javac fails on this case while it compiles the comment#0 case alright.
(In reply to comment #3) > Note however that javac fails on this case while it compiles > the comment#0 case alright. I meant to say javac5. javac6 fails on both.
See http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6450290 for some interesting discussion on a somewhat similar javac bug.
Created attachment 196772 [details] Early version of a fix.
Created attachment 196780 [details] Improved patch - under test
Created attachment 196795 [details] Proposed patch - under test. Closer to final version - under test.
The latest patch fails to handle this variation which is compiled alright by javac7: public class X<T> { class A<T extends X<? extends String>> { B<? extends A<T>> x; } class B<T extends A<?>> {} boolean b = ((A<? extends X<?>>)null).x == ((B<A<X<? extends String>>>)null); }
Created attachment 196817 [details] Final patch Augmented to handle the scenario in comment# 9
Released in BETA_JAVA7 branch. Olivier, please take a look and let me know if some cases are still broken - TIA. Basically, given class A<T extends B<?>>, A<?> cannot be the universe of all possible parameterizations, but only that subset that conforms to ? extends B<?> and the compiler was not making allowance for this constraint during type equivalence checks.
Looks good to me.
Verified using Eclipse Java 7 Support(Beta) feature patch v20110623-0900.