Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8078618

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

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Duplicate
    • Icon: P3 P3
    • None
    • 9
    • tools
    • b59
    • 9

      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.

      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:

          ***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 believe that E is inferred here as B<Y> are presented below (just meaningful steps are presented).

      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 ai has proper upper bounds U1, ..., Uk, Ti = glb(U1, ..., Uk)

      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 { a1, ..., an } 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 Y1, ..., Yn be fresh type variables whose bounds are as follows:
          * For all i (1 ≤ i ≤ n), where ai has upper bounds U1, ..., Uk, let the upper bound of Yi be glb(U1 q, ..., Uk q), where q is the substitution [a1:=Y1, ..., an:=Yn].

      5. Finally e is instantiated as a fresh type variable Y with the upper bound B<Y> according to the following assertion from JLS 18.4:

          Otherwise, for all i (1 ≤ i ≤ n), all bounds of the form G<..., ai, ...> = capture(G<...>) are removed from the current bound set, and the bounds a1 = Y1, ..., an = Yn are incorporated.

            sadayapalam Srikanth Adayapalam (Inactive)
            grakov Georgiy Rakov (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: