JDK-6790039 : overhaul cast-conversion (umbrella)
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 7
  • Priority: P3
  • Status: Closed
  • Resolution: Cannot Reproduce
  • OS: generic
  • CPU: unknown
  • Submitted: 2009-01-05
  • Updated: 2010-11-04
  • Resolved: 2010-11-04
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
7Resolved
Related Reports
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Description
Cast-conversion impl has several problems when it comes to generic types; most of them have to do with the fact that javac tries to be smarter than the JLS, in order to detect an illegal generic cast at compile-time rather than at runtime. Though this is desirable, the underlying impl is not reliable, meaning that a lot of valid cast are rejected by the compiler because of some failures in the 'provable distinct' test. Note also, that javac implements a stricter version of such a test than the JLS does - this is because we want to be able to detect more illegal cast than the JLS does.

Here's an example:

List<? extends Number> ln = ...
Object o = (List<String>)ln; //error: inconvertible types

The JLS require an unchecked warning here - because ? extends Number and String are not provably distinct; on the other hand, javac exploits the type info regarding the wildcard upper bound in order to reject that cast as illegal.

Problem arise when either the target or the source type is

*) a type variable with a recursive bound (fbound) - T extends Comparable<T>
*) a captured type variable whose upper bound is recursive

In such a setting, the enhanced type-disjointness test fails, that is, it is possible for javac to consider that two such types are distinct when they are not - the result is an unwanted complilation error where the user would have expected an unchecked warning.

Comments
EVALUATION Javac implements the type-disjointness algorithm in two steps: *) Bound Rewriting *) Type-disjointness test The first step is the most crucial, as it is responsible for rewriting non-wildcard types as if they were wildcard types - e.g. the type List<#0> where #0 is a captured type variable whose upper bound is String gets rewritten as List<? extends String>. This step is crucial in order to simplify the input of the type-disjointness test. Any failure to rewrite the type as described above will likely result in an unwanted error being raised by javac. The second step recursively visits the bounds of the two types for which disjointness is to be proven. If there exist some relatioships between the two types (e.g. the bound of the first type is convertible to the second type) then the two types are assumed not to be provably distinct. With fbounds the typical scenario is that the first step leaves some captured type variables after the rewriting step; because of this, the second step, which is designed to operate on wildcard types, fails.
05-01-2009