Anonymous class creation and diamonds: bound 'E extends B<E>'

Srikanth srikanth.adayapalam at oracle.com
Fri Apr 24 15:03:07 UTC 2015


On Friday 24 April 2015 08:28 PM, Georgiy Rakov wrote:
> Created the issue for this:
> https://bugs.openjdk.java.net/browse/JDK-8078618

Hi Georgiy,

I am sorry, I already created a ticket for this, but didn't manage to notify
here before you ended up creating a duplicate. I'll close the new one as
the old one has a fix under consideration already.

Thanks!
Srikanth

>
> Thanks,
> Georgiy.
>
> On 22.04.2015 20:32, Maurizio Cimadamore wrote:
>> I believe you are correct - and I believe the issue is that the fresh 
>> variable generated by javac is internally a TypeVar object, rather 
>> than a CapturedType object - meaning that it will fool the denotable 
>> check (which looks for CapturedTypes).
>>
>> @Srikanth - can you look into this?
>>
>> @Georgiy - good catch! Many thanks!
>>
>> Maurizio
>>
>> On 22/04/15 17:37, Georgiy Rakov wrote:
>>> Hello,
>>>
>>> let's consider following example:
>>>
>>>     class B<V> {}
>>>
>>>     class Foo<E extends B<E>> {
>>>         public Foo<E> complexMethod(E a) { return this; }
>>>     }
>>>
>>>     public class Test65  {
>>>         public static void check() {
>>>             Foo t4 = new Foo<>() {
>>>             };
>>>         }
>>>     }
>>>
>>> This code successfully compiles on JDK9b60. However according to my 
>>> understanding the compilation should have failed as per new spec. 
>>> Could you please tell if this understanding is correct.
>>>
>>> The reasons why I think that the compilation should have failed are 
>>> presented below.
>>>
>>> E is inferred as B<Y>, where Y is a fresh type variable with the 
>>> upper bound B<Y>.  If this is correct the given code should cause 
>>> compilation failure according to following new assertions presented 
>>> in the JDK-8073593 issue comment 
>>> <https://bugs.openjdk.java.net/browse/JDK-8073593?focusedCommentId=13622110&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-13622110>:
>>>
>>>     ***It is a compile-time error if the superclass or
>>>     superinterface type of the anonymous class, T, or any
>>>     subexpression of T, has one of the following forms:
>>>     - A type variable (4.4) that was not declared as a type
>>>     parameter (such as a type variable produced by capture
>>>     conversion (5.1.10))
>>>     - An intersection type (4.9)
>>>     - A class or interface type, where the class or interface
>>>     declaration is not accessible from the class or interface in
>>>     which the expression appears.***
>>>     The term "subexpression" includes type arguments of
>>>     parameterized types (4.5), bounds of wildcards (4.5.1), and
>>>     element types of array types (10.1). It excludes bounds of type
>>>     variables.*** 
>>>
>>> The reason for this is that anonymous class super type, which is 
>>> parameterized, has a type argument (subexpression) being a /type 
>>> variable which was not declared as a type parameter.//
>>> ///
>>> The fact that E is inferred as a type variable with the upper bound 
>>> becomes more obvious if we decide to override complexMethod:
>>>          Foo t4 = new Foo<>() {
>>>              public Foo<? extends B> complexMethod(B a){ return this; }
>>>              //public Foo<B> complexMethod(B a){ return this; } ;//this causes compilation failure
>>>          };
>>>
>>> In this case providing return type as Foo<B> causes compilation 
>>> failure. Only specifying the return type as Foo<? extends B> gets 
>>> compilation to succeed.
>>>
>>> In general the reasons why I think that E is inferred here as B<Y> 
>>> are presented below (just meaningful steps are presented). Could you 
>>> please tell if they are correct.
>>>
>>> 1. Initial bounds set created from type parameter bounds contains 
>>> following items as per JLS 18.1.3:
>>>
>>>     e :< B<e> (e - is inference variable);
>>>     e :< Object (this is added because e had no proper upper bounds);
>>>
>>> 2. Then these bounds are processed by resolution process (JLS 18.4). 
>>> During resolution e :< Object causes instantiation e=Object 
>>> according to following assertion from JLS 18.4:
>>>
>>>     Otherwise, where a_i has /proper/ upper bounds U_1 , ..., U_k ,
>>>     T_i = glb(U_1 , ..., U_k )
>>>
>>> 3. Incorporating e=Object causes following new constraint to be 
>>> added Object :< B<Object> according to following assertion from JLS 
>>> 18.3.1:
>>>
>>>     a = U and S |<:| T imply ‹S|[|a:=U|]| |<:| T|[|a:=U|]|›
>>>
>>> 5. Constraint Object :< B<Object> reduces to false causing the 
>>> second resolution attempt to take effect according to following 
>>> assertion from JLS 18.4:
>>>
>>>     Otherwise, the result contains the bound /false/, so a second
>>>     attempt is made to instantiate { a_1 , ..., a_n } by performing
>>>     the step below.
>>>
>>> 4. Fresh type variable Y with upper bound B<Y> is introduced 
>>> according to assertions from JLS 18.4 presented below (Y upper bound 
>>> is glb(Object,B<e>[e:=Y]) = B<e>[e:=Y] = B<Y>):
>>>
>>>     then let Y_1 , ..., Y_n be fresh type variables whose bounds are
>>>     as follows:
>>>     * For all /i/(1 ≤ /i/≤ /n/), where a_i has upper bounds U_1 ,
>>>     ..., U_k , let the upper bound of Y_i be glb(U_1 q, ..., U_k q),
>>>     where qis the substitution |[|a_1 :=Y_1 , ..., a_n :=Y_n |]|.
>>>
>>> 5. Finally e is instantiated as a fresh type variableY with the 
>>> upper boundB<Y> according to the following assertion from JLS 18.4:
>>>
>>>     Otherwise, for all /i/ (1 ≤ /i/ ≤ /n/), all bounds of the form
>>>     G|<|..., a_i , ...|>| = capture(G|<|...|>|) are removed from the
>>>     current bound set, /_*and the bounds *_//_*a*_//_*_1 *_//_*=
>>>     *_//_*Y_1 *_//_*, ..., *_//_*a*_//_*_n *_//_*= *_//_*Y_n
>>>     *_//_*are incorporated.
>>>
>>>     *_/
>>>
>>> Thanks,
>>> Georgiy.
>>
>

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/compiler-dev/attachments/20150424/494d88e0/attachment-0001.html>


More information about the compiler-dev mailing list