JDK-7018313 : 5.1.9: Unchecked conversion during assignment/method invocation is too lax
  • Type: Bug
  • Component: specification
  • Sub-Component: language
  • Affected Version: 5.0,7,8
  • Priority: P4
  • Status: Open
  • Resolution: Unresolved
  • Submitted: 2011-02-09
  • Updated: 2024-04-12
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.
Other
tbdUnresolved
Related Reports
Relates :  
Relates :  
Relates :  
Description
The assignment conversion (5.2) and method invocation conversion (5.3) sections contain this paragraph, which describes how unchecked conversions can occur in these contexts:

"If, after the conversions listed above have been applied, the resulting type is a raw type (§4.8), unchecked conversion (§5.1.9) may then be applied. It is a compile time error if the chain of conversions contains two parameterized types that are not not in the subtype relation."

This is problematic for a few reasons.

First, it's unclear whether the "it is a compile time error" clause is restricting the set of allowed conversions, or if it is independently describing an error that occurs despite the conversion being allowed.  This is important because overload resolution is defined based on the argument types representing an allowed conversion. (15.12.2.3)

Second, it is not strict enough to prevent conversions like this, where StringList extends List<String> (StringList is not a parameterized type, nor is it raw):

StringList -> List -> List<Integer>

Similarly, for StringPair<T> extends Pair<String,T> (StringPair is a raw type):

StringPair -> Pair -> Pair<Integer,Integer>

It seems that the approach used in 15.12.2.2 to define "applicable by subtyping" is the right way to go: _first_ do the unchecked conversion (commit to particular type arguments for a raw type), _then_ allow widening.

Comments
Here's a valid use case that would become illegal by performing unchecked conversion before widening: class MyList implements List { ... } // legacy API List<String> ls = new MyList(); MyList is not raw, so the unchecked conversion must wait until MyList is widened to List. I can see this sort of thing happening frequently in real code. Makes me wonder if my proposal is a bad idea after all... Might be better to simply tighten up the idea of "the chain of conversions contains two parameterized types".
25-10-2013

EVALUATION Both javac and Eclipse prohibit the first conversion (StringList->List<Integer>) and allow the second (StringPair->Pair<Integer,Integer>). Both treat the prohibition of StringList->List<Integer> as part of the definition of "applicable", not as a separate check. Both treat StringPair->Pair<Integer,Integer> as "applicable by subtyping", although this is clearly not the case in 15.12.2.2. public class UncheckedAssignment { static class C<T> {} static class D extends C<String> {} static class E<S,T> {} static class F<T> extends E<String,T> {} // C<Integer> i = new D(); // illegal E<Integer,Integer> j = new F(); public static void main(String... args) { m(new D()); // prints c m(new F()); // prints b } static void m(C<Integer> arg) { System.out.println("a"); } static void m(E<Integer,Integer> arg) { System.out.println("b"); } static void m(Object arg) { System.out.println("c"); } }
09-02-2011