JDK-6507024 : unchecked conversion between arrays fails after capture conversion
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 6
  • Priority: P2
  • Status: Closed
  • Resolution: Fixed
  • OS: linux
  • CPU: x86
  • Submitted: 2006-12-21
  • Updated: 2011-05-18
  • Resolved: 2011-05-18
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 6 JDK 7 Other
6u21Fixed 7 b29Fixed OpenJDK6Fixed
Related Reports
Relates :  
Description
FULL PRODUCT VERSION :
ecalhoun@whirl:~/$ java -version
java version "1.6.0"
Java(TM) SE Runtime Environment (build 1.6.0-b105)
Java HotSpot(TM) Client VM (build 1.6.0-b105, mixed mode, sharing)
ecalhoun@whirl:~/$ javac -version
javac 1.6.0


ADDITIONAL OS VERSION INFORMATION :
Linux, Debian 3.0
Linux whirl 2.6.12.2 #1 SMP Sun Jul 10 16:49:53 PDT 2005 i686 GNU/Linux

A DESCRIPTION OF THE PROBLEM :
When compiling a class containing the following code:

public <T> void process (Action action, Result<T> results[])
{
    // unrelated problem stuff happens
    Result<T>[] singleResult = results.getClass().cast(Array.newInstance(results.getClass().getComponentType(), 1));
    // more problem-unrelated stuff happens
}

one receives a compiler error similar to:
 [depend] Deleted 38 out of date files in 0 seconds
     [echo] Building...
    [javac] Compiling 142 source files to .../classes
    [javac] .../SomeClass.java:88: incompatible types
    [javac] found   : capture#69 of ? extends some.pacakge.Result[]
    [javac] required:  some.package.Result<T>[]
    [javac]                         results.getClass().cast(Array.newInstance(
    [javac]                                                ^
    [javac] Note: Some input files use unchecked or unsafe operations.
    [javac] Note: Recompile with -Xlint:unchecked for details.
    [javac] 1 error

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. create a function that has a generic type passed in.
2. instantiate an array using the component type of a passed-in array argument of the generic type
3. try and cast the newly-instantiated array to the generic type
4. assign the object resulting from step 3 to a reference of the generic type.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
I expected the compiler to successfully compile the code as the JDK 1.5 compiler did.
ACTUAL -
I received a compiler error similar to:
 [depend] Deleted 38 out of date files in 0 seconds
     [echo] Building...
    [javac] Compiling 142 source files to .../classes
    [javac] .../SomeClass.java:88: incompatible types
    [javac] found   : capture#69 of ? extends some.pacakge.Result[]
    [javac] required:  some.package.Result<T>[]
    [javac]                         results.getClass().cast(Array.newInstance(
    [javac]                                                ^
    [javac] Note: Some input files use unchecked or unsafe operations.
    [javac] Note: Recompile with -Xlint:unchecked for details.
    [javac] 1 error

ERROR MESSAGES/STACK TRACES THAT OCCUR :
I received a compiler error similar to:
 [depend] Deleted 38 out of date files in 0 seconds
     [echo] Building...
    [javac] Compiling 142 source files to .../classes
    [javac] .../SomeClass.java:88: incompatible types
    [javac] found   : capture#69 of ? extends some.pacakge.Result[]
    [javac] required:  some.package.Result<T>[]
    [javac]                         results.getClass().cast(Array.newInstance(
    [javac]                                                ^
    [javac] Note: Some input files use unchecked or unsafe operations.
    [javac] Note: Recompile with -Xlint:unchecked for details.
    [javac] 1 error

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
See description.
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
For now, I am going to have a 2nd generic type, passed-in as a parameter to the function which can be used as a model of what return type to expect.

Comments
SUGGESTED FIX a webrev of this fix is available at: http://sa.sfbay.sun.com/projects/langtools_data/7/6507024/
21-05-2008

EVALUATION The corresponding JLS bug has been addressed; as Alex says, there should be an unchecked conversion from C[] to C<T>[] and, as a consequence, between a captured type variable whose upper bound is C[] and C<T>[]. Javac seems capable of handling unchecked conversion between arrays already. The problem only affects captured types; this is due to the fact that the code inside Types.isUncheckedSubtype applies array subtyping ONLY if both types S and T in a subtyping test S <: T are arrays. In the submitted example S is not an array (it's a captured type variable). This causes the bug. In order to solve this problem, we should add some propagation to the algorithm in Types.isSubtypeUnchecked: if S is a type variable, then call Types.isSubtypeUnchecked recursively where T' = T and S' = upper(S).
21-05-2008

EVALUATION Unfortunately, no reproducible test case was submitted so I had to write my own: import java.lang.reflect.Array; class Test { interface Result<T> {} <T> void m(Result<T>[] results) { Result<T>[] r = results.getClass().cast(null); } } Since the argument to cast are immaterial to this problem, I have simply used null. The type of results.getClass() is Class<? extends Result[]>. Consequently the type of results.getClass().cast(null) is the capture of ? extends Result[]. So the question is: is there there an unchecked conversion from the capture of ? extends Result[] to Result<T>[]? According to the compiler there is one from Result[] to Result<T>[] which should imply that there is one from the capture of ? extends Result[]. I cannot find anything in the JLS to support any of this so it appears that there is a JLS bug as well. This is understandable as it is not recommended that arrays and generic types are mixed as in the example. I assume that this is indeed a compiler error and filed specification bug number 6508599.
29-12-2006