JDK-8028682 : javac fails to compile cast class to class >
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 7u9,8
  • Priority: P4
  • Status: Open
  • Resolution: Unresolved
  • OS: windows_xp
  • Submitted: 2013-03-20
  • Updated: 2015-12-11
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
tbd_majorUnresolved
Related Reports
Blocks :  
Description
FULL PRODUCT VERSION :
C:\Program Files\Far>java -version
java version  " 1.7.0_09 " 
Java(TM) SE Runtime Environment (build 1.7.0_09-b05)
Java HotSpot(TM) Client VM (build 23.5-b02, mixed mode, sharing)

ADDITIONAL OS VERSION INFORMATION :
windows xp

A DESCRIPTION OF THE PROBLEM :
Javac forbids cast Class<Generic> be cast to Class <? extends Generic<?>>

In turn, is Class<Generic> probably distinct from Class<? extends Generic<?>>  (given that their erasures are the same)  ?

In turn, is 'Generic' probably distinct from '? extends Generic<?>>'  ?

No, because |Generic| <: |Generic<?>|.

(JLS3 was not clear on this point. If both type arguments were ground types, JLS3 could prove them distinct and stop the cast, e.g. Class<String> can never be cast to Class<Integer> because Class<String> is distinct from Class<Integer> because String is distinct from Integer. However, JLS3 could not handle one or two wildcard type arguments. JLS7 takes the upper bound of a wildcard type argument - Generic<?> - and considers it against the ground type argument - Generic - to conclude that the type arguments are basically related.)

Therefore, there is no need for a compile-time error.

Since Class<Generic> is not a subtype of Class<? extends Generic<?>>, the cast is unchecked, and a compile-time unchecked warning is due.

Alex




STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
compile provided sample code

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
no errors
ACTUAL -
errors

ERROR MESSAGES/STACK TRACES THAT OCCUR :
javac:
Casting.java:4: error: inconvertible types
                  Class<? extends Generic<?>> generic = (Class<? extends
Generic<?>>) Generic.class;

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
class Generic<T> {}
public class Casting {
     void test() {
         Class<? extends Generic<?>> generic = (Class<? extends Generic<?>>) Generic.class;
      }
}


---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
compile code with Eclipse Juno
Comments
The JLS definition of castability is lacking; JDK-8078084 is needed to sort this out and decide what correct behavior should be in this case.
11-12-2015

To flesh out the implications of the existing JLS rule, things like the following are allowed: List<Class> cast to List<? extends Class<?>> // the reported use case List<Object> cast to List<? extends String> List<Class<String>> cast to List<? extends Class<Integer>> I don't know what the underlying design principle is behind the current rules in 4.5.1, but the result is quite permissive.
08-09-2014

Evaluation from JLS: An error in a cast from one parameterization of a class to another occurs if the two types are "provably distinct". In this case, that means: "One type argument is a type variable or wildcard, with an upper bound (from capture conversion, if necessary) of S; and the other type argument T is not a type variable or wildcard; and neither |S| <: |T| nor |T| <: |S|." (JLS 4.5.1) As pointed out in the description, this is not true, because |Generic| <: |Generic<?>|. In contrast, a cast from Class<Generic> to Class<Generic<?>> should prompt a compile-time error, because the two type arguments _are_ provably distinct: "Neither argument is a type variable or wildcard, and the two arguments are not the same type." (JLS 4.5.1) That said, a Class<Generic> really is not a Class<? extends Generic<?>>. So if it turns out that javac is doing something reasonable to detect a problem here, we might want to consider pushing that back into the language spec.
05-02-2014

I have to defer this webug reported issue to Dev team. Please close if not an issue.
19-11-2013