Possible regression involving inferred generic types
Jeremy Manson
jeremymanson at google.com
Mon Nov 4 13:18:51 PST 2013
Thanks, guys. I think there is a lot of value in documenting this sort of
thing. Since it was the very first incompatibility we encountered in our
source base when trying to compile with JDK8, I would expect that there is
rather a lot of it in the wild.
Jeremy
On Mon, Nov 4, 2013 at 10:53 AM, Alex Buckley <alex.buckley at oracle.com>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
>>>
>>>
>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.openjdk.java.net/pipermail/compiler-dev/attachments/20131104/211fa3f1/attachment.html
More information about the compiler-dev
mailing list