JDK-6611449 : Internal Error thrown during generic method/constructor invocation
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 7
  • Priority: P4
  • Status: Closed
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2007-10-01
  • Updated: 2011-05-17
  • Resolved: 2011-05-17
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 7
7 b25Fixed
Related Reports
Relates :  
Description
Description:
   
The following code fails during compilation with  "internal error".
<code>

public class TypeInferenceTest<S>{

    public  TypeInferenceTest() {

    this(1,1); //Throws internal error; cannot instanatiate ...
    //<Number>this(1,1); //Cannot find symbol
    //  <Integer>this(1); //Cannot find symbol
    // this(1); //Cannot find symbol
    }
    public <T extends S> TypeInferenceTest(T a, T b) {
        //.....
    }
    public <T extends S> TypeInferenceTest(T a) {
       //....
    }

    <T extends S> void met1(T a,T b){
       met2 (1,1);//Throws internal error; cannot instanatiate ...
       new TypeInferenceTest<Number> ().met2 (1,1); //Compiles fine -- Type Inference works
//       met2(1); // Cannot find symbol
    }
    <T extends S> void met2(T a,T b){
        //..
    }

    <T extends S> void met2(T a){
       //...
    }

}



</code>

Compilation result is :
<output>

TypeInferenceTest.java:5: internal error; cannot instantiate <T>TypeInferenceTest(T,T) at TypeInferenceTest<S> to ()
    this(1,1); //Throws internal error; cannot instanatiate ...
        ^
TypeInferenceTest.java:18: internal error; cannot instantiate <T>met2(T,T) at TypeInferenceTest<S> to (int,int)
       Integer i = met2 (1,1);//Throws internal error; cannot instanatiate ...
                        ^
2 errors


</output>

Tried in :
<version>
java version "1.7.0-internal"
Java(TM) SE Runtime Environment (build 1.7.0-internal-jprtadm_26_Sep_2007_03_43-b00)
Java HotSpot(TM) Server VM (build 11.0-b06, mixed mode)

uname -a
SunOS bonsai 5.11 snv_49 i86pc i386 i86pc

Comments
EVALUATION The internal error is due to the fact that javac selects a method/constructor that is not applicable because of the declared bound of the type variable T extending S. Unfortunatelly, this incompatibility is detected only at a later point during the resolution process so that javac is forced to trigger an internal error (because it realizes that something wrong happened during resolution). In particular, the interplay between boxing and type inference makes the resolution process to select an inapplicable method. Given a method declaration M1 and a list of actual argument types A1, A2 ... An, the resolution process is internally composed into two main steps: 1) An instantiation of M1 is found so that the formal parameters of M1 match against A1, A2 ... An. 2) If 1) fails repeat step 1) by substituting each primitive type (if any) in A1, A2 ... An with their corresponding boxed types. As an example, suppose that M1 = <T extends String> void m(T t1,T t2) and that A1,A2 = {int,int}. Step 1) should fail, since no instance of T exists so that T==int. On the other hand, step 2 fails too, since T is inferred to be Integer which is not compliant wrt the declared bound of T (Integer <: String does NOT hold). The actual behavior of javac differs from the one described above since javac makes step 1 succeed by basically inferring T itself for the type variable T. Such an inferred type is good for javac as it satisfies the declared bound of T (T <: T!), but then, at a later point, when javac checks that the selected method is effectively applicable (this is done by basically repeating step 2 - so enabling autoboxing), it suddenly realizes that the selected method is not compliant wrt the declared bound S of T. The solution to this problem is to fix javac so that step 1) fails as expected - this is equivalent to say that any type inference constraint referring a primitive type should be rewritten so that the primitive type is substituted by its boxing type, as described in JLS 15.12.2.7 " ... Otherwise, if the constraint has the form A <<F * If A is a primitive type, then A is converted to a reference type U via boxing conversion and this algorithm is applied recursively to the constraint U << F. ... "
31-01-2008

SUGGESTED FIX http://sa.sfbay.sun.com/projects/langtools_data/7/6611449/
31-01-2008

EVALUATION The use of "throws internal error" is mildly confusing; it "reports" an internal error. Either way, internal errors are not good. gzilla[6611449]% /w/local/jdk/1.7.0/bin/javac TypeInferenceTest.java TypeInferenceTest.java:6: internal error; cannot instantiate <T>TypeInferenceTest(T,T) at TypeInferenceTest<S> to () this(1,1); //Throws internal error; cannot instanatiate ... ^ TypeInferenceTest.java:19: internal error; cannot instantiate <T>met2(T,T) at TypeInferenceTest<S> to (int,int) met2 (1,1);//Throws internal error; cannot instanatiate ... ^ 2 errors gzilla[6611449]%
30-01-2008