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

Compiler infinite recursion when using transitive, recursive generics

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Duplicate
    • Icon: P3 P3
    • None
    • 7u21, 7u45, 8
    • tools
    • linux

      FULL PRODUCT VERSION :
      java version "1.7.0_21"
      Java(TM) SE Runtime Environment (build 1.7.0_21-b11)
      Java HotSpot(TM) 64-Bit Server VM (build 23.21-b01, mixed mode)

      (bug is reproduced in recent 7u45 as well)

      ADDITIONAL OS VERSION INFORMATION :
      Linux nvz 3.8.0-25-generic #37-Ubuntu SMP Thu Jun 6 20:47:07 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux


      A DESCRIPTION OF THE PROBLEM :
      Compiler goes to endless recursion when doing unchecked ("??ovariant") typecast with types (type variables) that a transitively and recursively co-dependent;

        Bug was reproduced on Linux 64 bit (jdk7u21), OS X (jdk7u45)

      Please consult the code below;




      ADDITIONAL REGRESSION INFORMATION:
      java version "1.7.0_21"

      Most recent javac (**_45) version doesn't work as well

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :

        To reproduce the bug just compile the code below;
      javac JavacBug.java;

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      should just compile the code
      ACTUAL -
      compiler's endless recursion, which results in java.lang.StackOverflowError

      ERROR MESSAGES/STACK TRACES THAT OCCUR :
      The system is out of resources.
      Consult the following stack trace for details.
      java.lang.StackOverflowError
      at com.sun.tools.javac.code.Type.contains(Type.java:357)
      at com.sun.tools.javac.code.Types$Rewriter.visitTypeVar(Types.java:3593)
      at com.sun.tools.javac.code.Types$Rewriter.visitTypeVar(Types.java:3549)
      at com.sun.tools.javac.code.Type$TypeVar.accept(Type.java:1030)
      at com.sun.tools.javac.code.Types$UnaryVisitor.visit(Types.java:3792)
      at com.sun.tools.javac.code.Types$Rewriter.visitClassType(Types.java:3564)
      at com.sun.tools.javac.code.Types$Rewriter.visitClassType(Types.java:3549)
      at com.sun.tools.javac.code.Type$ClassType.accept(Type.java:583)
      at com.sun.tools.javac.code.Types$UnaryVisitor.visit(Types.java:3792)
      at com.sun.tools.javac.code.Types$Rewriter.visitTypeVar(Types.java:3593)
      at com.sun.tools.javac.code.Types$Rewriter.visitTypeVar(Types.java:3549)
      at com.sun.tools.javac.code.Type$TypeVar.accept(Type.java:1030)
      at com.sun.tools.javac.code.Types$UnaryVisitor.visit(Types.java:3792)
      at com.sun.tools.javac.code.Types$Rewriter.visitTypeVar(Types.java:3593)
      at com.sun.tools.javac.code.Types$Rewriter.visitTypeVar(Types.java:3549)
      at com.sun.tools.javac.code.Type$TypeVar.accept(Type.java:1030)
      at com.sun.tools.javac.code.Types$UnaryVisitor.visit(Types.java:3792)
      at com.sun.tools.javac.code.Types$Rewriter.visitClassType(Types.java:3564)
      at com.sun.tools.javac.code.Types$Rewriter.visitClassType(Types.java:3549)
      at com.sun.tools.javac.code.Type$ClassType.accept(Type.java:583)
      at com.sun.tools.javac.code.Types$UnaryVisitor.visit(Types.java:3792)
      at com.sun.tools.javac.code.Types$Rewriter.visitTypeVar(Types.java:3593)
      at com.sun.tools.javac.code.Types$Rewriter.visitTypeVar(Types.java:3549)
      at com.sun.tools.javac.code.Type$TypeVar.accept(Type.java:1030)
      at com.sun.tools.javac.code.Types$UnaryVisitor.visit(Types.java:3792)
      at com.sun.tools.javac.code.Types$Rewriter.visitTypeVar(Types.java:3593)
      at com.sun.tools.javac.code.Types$Rewriter.visitTypeVar(Types.java:3549)
      at com.sun.tools.javac.code.Type$TypeVar.accept(Type.java:1030)
      at com.sun.tools.javac.code.Types$UnaryVisitor.visit(Types.java:3792)
      at com.sun.tools.javac.code.Types$Rewriter.visitClassType(Types.java:3564)
      at com.sun.tools.javac.code.Types$Rewriter.visitClassType(Types.java:3549)
      at com.sun.tools.javac.code.Type$ClassType.accept(Type.java:583)
      at com.sun.tools.javac.code.Types$UnaryVisitor.visit(Types.java:3792)
      at com.sun.tools.javac.code.Types$Rewriter.visitTypeVar(Types.java:3593)
      at com.sun.tools.javac.code.Types$Rewriter.visitTypeVar(Types.java:3549)
      at com.sun.tools.javac.code.Type$TypeVar.accept(Type.java:1030)
      at com.sun.tools.javac.code.Types$UnaryVisitor.visit(Types.java:3792)
      at com.sun.tools.javac.code.Types$Rewriter.visitTypeVar(Types.java:3593)
      at com.sun.tools.javac.code.Types$Rewriter.visitTypeVar(Types.java:3549)
      at com.sun.tools.javac.code.Type$TypeVar.accept(Type.java:1030)
      at com.sun.tools.javac.code.Types$UnaryVisitor.visit(Types.java:3792)
      at com.sun.tools.javac.code.Types$Rewriter.visitClassType(Types.java:3564)
      at com.sun.tools.javac.code.Types$Rewriter.visitClassType(Types.java:3549)
      at com.sun.tools.javac.code.Type$ClassType.accept(Type.java:583)


      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      public class JavacBug {
          
          interface HolderA<T> {
              
          }

          interface HolderB<T> {
              
          }
          
          // type with "transitive, recursive" generics;
          public static class Demo<T extends T1, T1 extends HolderB<T>> {
              @SuppressWarnings("unchecked") public HolderA<T1> m3(T x) {
                  HolderA<T> f = null;
                  // this unchecked cast leads to java.lang.StackOverflowError in javac (endless recursion)
                  return (HolderA<T1>)f;
              }
          };
        
      }
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      No workaround. I could only change type bounds which makes it different from what is semantically intended:
          public static class Demo1<T extends HolderB<T>, T1 extends HolderB<T>> {
              @SuppressWarnings("unchecked") public HolderA<T1> m3(T x) {
                  HolderA<T> f = null;
                  // this unchecked cast leads to java.lang.StackOverflowError in javac (endless recursion)
                  return (HolderA<T1>)f;
              }
          };

            vromero Vicente Arturo Romero Zaldivar
            dmeetry Dmeetry Degrave (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated:
              Resolved: