Anonymous class creation and diamonds: bound 'E extends B<E>'
Maurizio Cimadamore
maurizio.cimadamore at oracle.com
Wed Apr 22 17:32:57 UTC 2015
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/20150422/da40ba15/attachment-0001.html>
More information about the compiler-dev
mailing list