Java Solaris Communities Sun Store Join SDN My Profile Why Join?
 
Bug Database
Bug Detail
Quick Lists
Top 25 Bugs
Top 25 RFE's
Recently Closed Bugs
Printable Page Printable Page


Bug Database
Bug ID: 6677785
Votes 0
Synopsis REGRESSION: StackOverFlowError with Cyclic Class level Type Parameters when used in constructors
Category java:compiler
Reported Against
Release Fixed 7(b29)
State 10-Fix Delivered, bug
Priority: 3-Medium
Related Bugs 6660289
Submit Date 20-MAR-2008
Description
Description:
Compiler crashes with StackOverFlowError for the following code. This is a *REGRESSION*. Compiler throws  "cyclic inheritance involving S" in JDK 7 b24 error as it should be, but goes into infinite loop with PIT b26. Strangely, if i comment the second constructor it compiles fine.

<code>
bash-3.00$ cat CyclicTypeParameters.java
class CyclicTypeParameters<S extends T, T extends S>{
        CyclicTypeParameters(S s){
        }
        CyclicTypeParameters(){// Works fine on commenting this
        }
}
</code>
Compilation result is :
<output>
The system is out of resources.
Consult the following stack trace for details.
java.lang.StackOverflowError
        at com.sun.tools.javac.code.Type$TypeVar.accept(Type.java:952)
        at com.sun.tools.javac.code.Types$UnaryVisitor.visit(Types.java:3240)
        at com.sun.tools.javac.code.Types.erasure(Types.java:1502)
        at com.sun.tools.javac.code.Types$16.visitTypeVar(Types.java:1525)
        at com.sun.tools.javac.code.Types$16.visitTypeVar(Types.java:1505)
        at com.sun.tools.javac.code.Type$TypeVar.accept(Type.java:952)
        at com.sun.tools.javac.code.Types$UnaryVisitor.visit(Types.java:3240)
        at com.sun.tools.javac.code.Types.erasure(Types.java:1502)
        at com.sun.tools.javac.code.Types$16.visitTypeVar(Types.java:1525)
        at com.sun.tools.javac.code.Types$16.visitTypeVar(Types.java:1505)
        at com.sun.tools.javac.code.Type$TypeVar.accept(Type.java:952)
        at com.sun.tools.javac.code.Types$UnaryVisitor.visit(Types.java:3240)
        at com.sun.tools.javac.code.Types.erasure(Types.java:1502)
        at com.sun.tools.javac.code.Types$16.visitTypeVar(Types.java:1525)
        at com.sun.tools.javac.code.Types$16.visitTypeVar(Types.java:1505)
        at com.sun.tools.javac.code.Type$TypeVar.accept(Type.java:952)
        at com.sun.tools.javac.code.Types$UnaryVisitor.visit(Types.java:3240)
        at com.sun.tools.javac.code.Types.erasure(Types.java:1502)
</output>
<version>
bash-3.2$ /net/bonsai.sfbay/w/builds/jdk/7/pit/b26/solaris-i586/jdk1.7.0/bin/java -version
java version "1.7.0-internal"
Java(TM) SE Runtime Environment (build 1.7.0-internal-jprtadm_18_Mar_2008_12_26-b00)
Java HotSpot(TM) Server VM (build 12.0-b01, mixed mode)
</version>
bash-3.2$ uname -a
SunOS bonsai 5.11 snv_77 i86pc i386 i86pc
Posted Date : 2008-03-20 07:54:24.0
Work Around
N/A
Evaluation
The problem is due to the fact that detection of cycles in type variable declaration has been moved from phase 1 of symbol completion to the attribution phase of a given class. The reason of this choice is CR 660289, where we have the following code:

class Outer<T extends Inner<?>> {
    class Inner<S extends T> {}
}  

In this example the attribution of the type-variable bound of Outer.T (namely Inner<?>) triggers the completion of the class symbol Inner (because of multiple calls to the method flags() of ClassSymbol). When javac tries to complete Inner, it tries to attribute the type variables of Inner, namely S. Unfortunately, since S's bound is T (whose attribution is waiting for S's attribution), a NPE is thrown when detecting possible cycles in the bound declaration of S. In fact we have that bound(S) = T, bound(T) == null.

In order to solve this problem I decided to postpone the circularity check involving type variables so that a given class symbol C is completed first, then any cycle is detected at a later point when C is being attributed. This sounded good at first, but this CR points out that executing the check during attribution it's too late; in fact there is a slot of time in which the class symbol has been completed but not yet attributed. Any call to either Types.erasure(tv) or Types.getUpperBound(tv) where tv is a type variable whose bound is cyclic lead javac to crash, since we have that (e.g. referring to the example above):

erasure(S) === Types.getUpperBound(S)
Types.getUpperBound(S) === Types.getUpperBound(bound(S)) === Types.getUpperBound(T)
Types.getUpperBound(T) === Types.getUpperBound(bound(T)) === Types.getUpperBound(S)

this means that we cannot compute the erasure of a type-variable whose bound is cyclic. In this example the erasure operation is executed while finishing the class symbol C. In fact, MemberEnter completes class symbols in two steps:

1) supertype, interfaces, annotation types are attributed
2) all members of the class are entered into the scope of the class

Step 1 does not depend on type-variable types and bounds, but step 2 does. As an example, consider that, in the example given above, when the symbol CyclicTypeParameters(S s) is entered into the scope of the class, javac checks that no other method exists with the same name and the same signature. This is done by invoking isOverrideEquivalent that, in turn, calls types.erasure(). Since the erasure of S cannot be computed (the bound of S is cyclic) javac then crashes, as shown above.
Posted Date : 2008-05-29 11:03:13.0
Comments
  
  Include a link with my name & email   


PLEASE NOTE: JDK6 is formerly known as Project Mustang