Possible regression involving inferred generic types
Vicente-Arturo Romero-Zaldivar
vicente.romero at oracle.com
Wed Nov 6 02:47:53 PST 2013
Hi Alex,
Thanks for the links, I have updated JDK-7115044 as you suggested,
Vicente
On 04/11/13 18:53, Alex Buckley wrote:
> Hi Vicente,
>
> Thanks for identifying the JBS issue which describes the change.
>
> If javac in JDK7 compiled this illegal code, and javac in JDK8 rejects
> this illegal code, then the JBS issue should be documented as a source
> compatibility issue in the JDK8 Release Notes. As examples, see the
> "Tools" items in the JDK7 Release Notes at [1]. This is exactly the
> place to identify changes in javac made for solid conformance reasons
> which will nevertheless confuse legions of programmers.
>
> So, please take over JDK-7115044, add the label "release-note=yes",
> and add a comment showing ReproOne.java with a brief description.
>
> Alex
>
> [1]
> http://www.oracle.com/technetwork/java/javase/compatibility-417013.html#jdk7
>
> On 11/4/2013 7:10 AM, Vicente-Arturo Romero-Zaldivar wrote:
>> Hi Liam,
>>
>> I have been investigating the issue you reported. The fix that changed
>> javac's behavior is deep in current javac 8 repo, see [1], the original
>> bug entry can be seen at [2].
>>
>> From my understanding of the spec and also based on Alex's answer at
>> [3], I think that the fact that the code compiles in 7 is a bug and thus
>> 8 can be considered correct. For this reason I don't think that there is
>> a compatibility issue here.
>>
>> I have modified the code of ReproOne.java to:
>>
>> --------------------------------------------------------------------------------
>>
>>
>> import java.util.List;
>>
>> class ReproOne {
>>
>> static class Baz<T> {
>> public static List<Baz<Object>> getElements(Baz<Object>
>> transcoder) {
>> return null;
>> }
>> }
>>
>> private static void bar(Baz arg) {
>> Baz element = Baz.getElements(arg).get(0);
>> }
>> }
>> -----------------------------------------------------------------------------------
>>
>>
>>
>> Which probably shows more clearly the fact that after erasing the return
>> value of getElements() to "java.util.List" the type of get(0) is Object
>> and thus not assignable to a variable of type Baz.
>>
>> Thanks,
>> Vicente.
>>
>> [1] http://hg.openjdk.java.net/jdk8/tl/langtools/rev/48ee63caaa93
>> [2] https://bugs.openjdk.java.net/browse/JDK-7144506
>> [3]
>> http://mail.openjdk.java.net/pipermail/compiler-dev/2013-October/007726.html
>>
>>
>>
>> On 17/10/13 01:48, cushon wrote:
>>> Forwarded from compiler-dev at Alex Buckley's suggestion. Original
>>> thread:
>>> http://mail.openjdk.java.net/pipermail/compiler-dev/2013-October/007726.html
>>>
>>>
>>>
>>>
>>> I found some cases where javac 8 behaviour diverges from javac 7,
>>> and I'm
>>> interested in knowing whether this is a bug or an intentional change.
>>>
>>> The following programs do not compile with the jdk8 javac. (I tried
>>> b111 and
>>> 954dd199d6ff). All of the programs compile with the jdk7 javac.
>>>
>>> -------------------------------------------------------------------------------
>>>
>>>
>>> import java.util.List;
>>>
>>> class ReproOne {
>>>
>>> static class Baz<T> {
>>> public static List<Baz<Object>> getElements(Baz<Object>
>>> transcoder) {
>>> return null;
>>> }
>>> }
>>>
>>> private static void bar(Baz arg) {
>>> for (Baz element : Baz.getElements(arg)) {}
>>> }
>>> }
>>> -------------------------------------------------------------------------------
>>>
>>>
>>> abstract class ReproTwo<T> {
>>>
>>> class Bar<E> {}
>>>
>>> T get(Bar<? extends T> arg1, Bar arg2) {
>>> return circularGet(arg2, arg2);
>>> }
>>>
>>> abstract T circularGet(final Bar<? extends T> arg1, final Bar<?>
>>> arg2);
>>> }
>>> -------------------------------------------------------------------------------
>>>
>>>
>>> abstract class ReproThree<T, V> {
>>>
>>> class Binding<E> {}
>>> class ProviderBinding<E> extends Binding<E> {}
>>>
>>> abstract V visitOther(Binding<? extends T> binding);
>>>
>>> public V visitTwo(ProviderBinding<? extends T> providerBinding) {
>>> return visitOther((Binding) providerBinding);
>>> }
>>> }
>>> -------------------------------------------------------------------------------
>>>
>>>
>>>
>>> javac output:
>>>
>>> ReproOne.java:12: error: incompatible types: Object cannot be
>>> converted to
>>> Baz
>>> for (Baz element : Baz.getElements(arg)) {}
>>> ^
>>>
>>> ReproTwo.java:6: error: incompatible types: Object cannot be converted
>>> to T
>>> return circularGet(arg2, arg2);
>>> ^
>>> where T is a type-variable:
>>> T extends Object declared in class ReproTwo
>>>
>>> ReproThree.java:10: error: incompatible types: Object cannot be
>>> converted
>>> to V
>>> return visitOther((Binding) providerBinding);
>>> ^
>>> where V is a type-variable:
>>> V extends Object declared in class ReproThree
>>>
>>
More information about the compiler-dev
mailing list