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