Sun JDK 6 javac vs OpenJDK 6 javac
Maurizio Cimadamore
Maurizio.Cimadamore at Sun.COM
Mon Nov 30 01:31:05 PST 2009
Hi Mark,
the behavior you are experiencing is the result of the work we have been
doing in order to bring the compiler's type inference algorithm more in
sync with the version specified by the JLS. This has advantages, as the
implementation is now much more predictable and few disadvantages -
namely some programs that used to compile will fail to compile. JDK7
contains several type-inference improvements that are targeted at
reducing as much as possible the number of such programs - so that the
user won't be significantly affected by it. However in some corner cases
it could be possible that the open jdk 6 compiler/JDK 7 compiler will
reject programs that were (erroneously) accepted by the SUN JDK 6 compiler.
Speaking about your example, you have that the compiler is able to infer
A1 == A2 == String after the first round of type inference described in
JLS 15.12.2.7. At the end of this stage we have two more constraints of
the kind A1 <: R and A2 <: R but the compiler didn't take them into
account in order to infer the above result. Type variable R remains
uninferred after 15.12.2.7 so the compiler must infer it
through15.12.2.8; this stage only takes into account constraints of the
kind R <: X - unfortunately in this case there's no such constraint and
javac has no other choice than inferring Object for R (which is a legal
choice for the above unused constraints, as A1 <: Object and A2 <: Object).
JDK 6 compiler used to accept this example as it did consider the now
unused constraints of the kind A1 <: R - this however used to lead to
several bugs, as there are many situations in which this scheme ends up
inferring types that are too specific w.r.t. to the expected return type
thus leading to inference failures. The 'right' way to accept your
example would be to apply inference in argument position, so that the
additional constraint of the kind R <: String (String is the ofrmal
parameter of foo()) could be added when performing 15.12.2.8.
I hope this helps.
Maurizio
Mark Mahieu wrote:
> Repost from the right email address this time (I hope!)...
>
> I wrote:
>
>
>> should I expect to see
>> the same result from javac in Sun JDK 6 compared to OpenJDK 6
>>
>
>
> Tim Bell kindly bounced with:
>
>> Well - probably 'yes'. What did you do... what was the unexpected
>> result? What was the expected result? Do you have a small test
>> program to demonstrate the issue? What was surprising or unexpected
>> about it?
>>
>
>
> I stumbled across the following, which compiles without errors using Sun JDK 6 (various builds from b10 through b16), but is rejected by OpenJDK 6's javac (at least build b10 through to now) and OpenJDK 7 (clone of jdk7/tl/langtools):
>
> class SunJDKvsOpenJDK {
>
> public static void main(String[] args) {
> foo(bar("a", "b"));
> }
>
> static void foo(String s) {}
>
> static <R, A1 extends R, A2 extends R> R bar(A1 a1, A2 a2) {
> return null;
> }
> }
>
>
> Output from a recent OpenJDK 6 build:
>
> SunJDKvsOpenJDK.java:4: foo(java.lang.String) in SunJDKvsOpenJDK cannot be applied to (java.lang.Object)
> foo(bar("a", "b"));
> ^
> 1 error
>
>
> However, the main reason I'm asking out loud on this list is because I've been naively grabbing Sun JDK 6 and OpenJDK 6 builds of a similar vintage pretty much at random, to use as a base-line for regression testing some experiments I'm making in OpenJDK 7's javac, and given the above, I'm now wondering if I should try to stick to one or the other.
>
>
> Mark
>
>
More information about the compiler-dev
mailing list