JDK-6557958 : 15.12.4.2: Specify unchecked conversion warning during variable-arity method invocation
  • Type: Bug
  • Component: specification
  • Sub-Component: language
  • Affected Version: 6
  • Priority: P5
  • Status: Closed
  • Resolution: Fixed
  • Submitted: 2007-05-16
  • Updated: 2017-02-17
  • Resolved: 2017-02-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
7Fixed
Related Reports
Relates :  
Relates :  
Relates :  
Description
From: J. Stephen Adamczyk <###@###.###>
Date: Aug 11, 2006 12:09 PM
Subject: Unchecked conversion
To: Neal Gafter < ###@###.###>
Cc: "John H. Spicer" <###@###.###>

The JLS says several times (e.g., 5.3) that when an unchecked
conversion is considered
"It is a compile-time error if the chain of conversions contains two
parameterized types that are not in the subtype relationship".  The
example of such an invalid chain given in 5.2 is

Integer, Comparable<Integer>, Comparable, Comparable<String>

I *think* that the JLS really intends is "such an invalid sequence causes the
unchecked conversion not to be allowed" rather than what it seems to say,
which is "such an invalid sequence causes an error if the unchecked conversion
is used".  Here's a test case:

public class Test {
     static void g(Comparable<String> x) {
       System.out.println( "one" );
     }
     static void g(int x) {
       System.out.println( "two" );
     }
     public static void main( String[] args ) {
       Integer i = 1;
       g(i); 
     }
}

This compiles without error and prints "two", thus suggesting that the
disallowed unchecked conversion is simply ignored, rather than selected
and then flagged as an error.

I don't think that "most specific" distinguishes between the two candidates.
If it does, then maybe I'm drawing the wrong conclusion.

Do I have this right?

Comments
EVALUATION (Summary: The following discussion is prompted by the observation that javac gives an unchecked warning at the invocation of a variable-arity method whose varargs parameter is non-reifiable, yet no JLS text appears to require this. Investigation reveals that a host of subtle JLS changes are needed to make the JLS consistent with javac's reasonable behavior. The changes include unchecked conversion.) JLS3 15.12.4.2 says that for variable-arity method invocation, the argument list is evaluated as if it were written with "new T[] { ... }" as the last actual argument (where T is the type of the varargs parameter). This is clearly wrong because it's an error to write an array creation expression where the element type is non-reifiable. Happily, there is no need to redefine array creation expressions to allow a non-reifiable element type if the expression is the last argument of a varargs call. Instead, we can tweak 15.12.4.2: "the argument list ... is evaluated as if it were written as (e_1,...,e_n-1,new ***|T|***[]{e_n,...,e_k}) ***followed by an unchecked conversion of |T| to T***." In a fascinating bit of spec chicanery, we can drop the second ***'d text by noting that method invocation conversion already allows an unchecked conversion to be applied to a raw type [of an actual argument]. We just need to upgrade "raw type" in 4.8 from "the erasure of a parameterized type" to "the erasure of a parameterized type ***or the erasure of an array type whose element type is a parameterized type***". The erasure of such an array type is already defined in 4.6 :-) and the definition of "parameterized type" is unchanged. Since the raw type undergoing unchecked conversion is |T|[], we need to expand unchecked conversion in a minor way: "There is an unchecked conversion from the raw type G to any parameterized type of the form G<T1...Tn>***, and from the raw array type G[] to any parameterized array type G<T1...Tn>[]***." Then, 15.12.4.2 can wave goodbye to the potentially non-denotable expression "new T[]": "the argument list ... is evaluated as if it were written as (e_1,...,e_n-1,new ***|T|***[]{e_n,...,e_k})." The above text means that after all these years, javac is justified in giving an unchecked warning at a variable-arity method invocation, namely for the unchecked conversion from an array type with raw element type (|T|[]) to an array type with parameterized element type (T[]). javac chooses to refine the unchecked warning text to document an "unchecked generic array creation" rather than the general "unchecked conversion".
02-12-2010

EVALUATION When performing overload resolution for g(Integer), both g(Comparable<String>) and g(int) are considered for applicability by method invocation conversion. g(Comparable<String>) is not applicable in this way, because of the invalid chain. No compile-time error should be given, and overload resolution should proceed to discover that g(int) is the sole maximally specific method. JLS 5.2 and 5.3 (the only places which care about the chain) should say: "{Assignment,method invocation} conversion does not occur if the chain of conversions contains two parameterized types that are not in the subtype relation."
17-05-2007