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

Capture conversion using javax.lang.model.util.Types produces error type <any>

    Details

    • Subcomponent:
    • CPU:
      x86_64
    • OS:
      windows_7

      Description

      FULL PRODUCT VERSION :
      java version "1.8.0_25"
      Java(TM) SE Runtime Environment (build 1.8.0_25-b18)
      Java HotSpot(TM) Client VM (build 25.25-b02, mixed mode, sharing)

      javac 1.8.0_25

      ADDITIONAL OS VERSION INFORMATION :
      Microsoft Windows [Version 6.1.7601]

      A DESCRIPTION OF THE PROBLEM :
      The example shows a generic type that contains a method that returns another generic type, the latter also containing a method that returns a generic type. The return type of the methods invokes the next generic type using a wildcard bound by the present type's own parameter. The last generic type adds a bound in its declaration. I expected it to produce an intersection type but it produced an error type instead (TypeKind.ERROR). From 5.1.10 it seems that the result should be a fresh type variable bound by the intersection of the previous type variable and the additional type parameter bound. Indeed, this happens if Base1 is introduced earlier in the chain (e.g., as Iy<Y extends Base1>).

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Compile the attached source, then use it as an annotation processor:

      javac Demo.java
      javac -processor Demo Demo.java

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Iz<? extends Base2>
      DECLARED Iz<capture#527 of ? extends Base2>
        TYPEVAR capture#527 of ? extends Base2
          bound: DECLARED Base2
      Iy<? extends capture#527 of ? extends Base2>
      DECLARED Iy<capture#740 of ? extends capture#527 of ? extends Base2>
        TYPEVAR capture#740 of ? extends capture#527 of ? extends Base2
          bound: TYPEVAR capture#527 of ? extends Base2
      Ix<? extends capture#740 of ? extends capture#527 of ? extends Base2>
      DECLARED Ix<capture#767 of ? extends capture#740 of ? extends capture#527 of ? extends Base2>
        TYPEVAR capture#767 of ? extends capture#740 of ? extends capture#527 of ? extends Base2
          bound: INTERSECTION capture#740 of ? extends capture#527 of ? extends Base2&Base1
      ACTUAL -
      Iz<? extends Base2>
      DECLARED Iz<capture#527 of ? extends Base2>
        TYPEVAR capture#527 of ? extends Base2
          bound: DECLARED Base2
      Iy<? extends capture#527 of ? extends Base2>
      DECLARED Iy<capture#740 of ? extends capture#527 of ? extends Base2>
        TYPEVAR capture#740 of ? extends capture#527 of ? extends Base2
          bound: TYPEVAR capture#527 of ? extends Base2
      Ix<? extends capture#740 of ? extends capture#527 of ? extends Base2>
      DECLARED Ix<capture#767 of ? extends capture#740 of ? extends capture#527 of ? extends Base2>
        TYPEVAR capture#767 of ? extends capture#740 of ? extends capture#527 of ? extends Base2
          bound: ERROR <any>

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      import java.util.Set;
      import javax.annotation.processing.*;
      import javax.lang.model.SourceVersion;
      import javax.lang.model.element.*;
      import javax.lang.model.type.*;
      import javax.lang.model.util.*;

      interface Base1 {}
      interface Base2 {}
      interface Ix<X extends Base1> {}
      interface Iy<Y> {
      Ix<? extends Y> getInY();
      }
      interface Iz<Z> {
      Iy<? extends Z> getInZ();
      }

      @SupportedSourceVersion(SourceVersion.RELEASE_8)
      @SupportedAnnotationTypes("*")
      public class Demo extends AbstractProcessor {
      public Iz<? extends Base2> rl() { return null; }

      // Attempt to determine the type of rl().getInZ().getInY()
      void test() {
      Elements eu = processingEnv.getElementUtils();
      Types tu = processingEnv.getTypeUtils();

      // Find return type of rl() and perform capture
      ExecutableElement rlel = (ExecutableElement) find(eu.getTypeElement("Demo"), "rl");
      DeclaredType izWildExtendsBase2Tm = (DeclaredType) rlel.getReturnType();
      System.out.println(izWildExtendsBase2Tm);
      DeclaredType capIzWildExtendsBase2Tm = (DeclaredType) tu.capture(izWildExtendsBase2Tm);
      print(capIzWildExtendsBase2Tm);

      // Find return type of getInZ() when viewed as member of previous method's return; capture
      Element getInZ = find(eu.getTypeElement("Iz"), "getInZ");
      ExecutableType getInZTm = (ExecutableType) tu.asMemberOf(capIzWildExtendsBase2Tm, getInZ);
      DeclaredType iyWildExtendsZ = (DeclaredType) getInZTm.getReturnType();
      System.out.println(iyWildExtendsZ);
      DeclaredType capIyWildExtendsZ = (DeclaredType) tu.capture(iyWildExtendsZ);
      print(capIyWildExtendsZ);

      // Find return type of getInY() when viewed as member of previous method's return; capture
      Element getInY = find(eu.getTypeElement("Iy"), "getInY");
      ExecutableType getInYTm = (ExecutableType) tu.asMemberOf(capIyWildExtendsZ, getInY);
      DeclaredType ixWildExtendsY = (DeclaredType) getInYTm.getReturnType();
      System.out.println(ixWildExtendsY);
      DeclaredType capIxWildExtendsY = (DeclaredType) tu.capture(ixWildExtendsY);
      print(capIxWildExtendsY);
      }

      // Print a type, its first type argument, and the bound thereof
      void print(DeclaredType dt) {
      System.out.println(dt.getKind() + " " + dt);
      TypeMirror arg0 = dt.getTypeArguments().get(0);
      System.out.println(" " + arg0.getKind() + ' ' + arg0);
      TypeMirror bound = ((TypeVariable) arg0).getUpperBound();
      System.out.println(" bound: " + bound.getKind() + ' ' + bound);
      }

      private static Element find(Element containing, String name) {
      for (Element el : containing.getEnclosedElements()) {
      if (el.getSimpleName().toString().equals(name)) return el;
      }
      return null;
      }

      @Override
      public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
      if (roundEnv.processingOver()) test();
      return false;
      }
      }
      ---------- END SOURCE ----------

        Attachments

          Issue Links

            Activity

              People

              • Assignee:
                mcimadamore Maurizio Cimadamore
                Reporter:
                webbuggrp Webbug Group
              • Votes:
                0 Vote for this issue
                Watchers:
                4 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved: