JDK-6690688 : Enhanced-for-loop translation as described in JLS 14.14.2 is not type-safe
  • Type: Enhancement
  • Component: specification
  • Sub-Component: language
  • Affected Version: 7
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • OS: linux_ubuntu
  • CPU: x86
  • Submitted: 2008-04-18
  • Updated: 2016-09-20
  • Resolved: 2011-07-21
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
7 rcFixed
Related Reports
Relates :  
Relates :  
Relates :  
Relates :  
Description
JLS 14.14.2 says that, given an enhanced-for-loop statement in the form:

EnhancedForStatement:
       for ( VariableModifiersopt Type Identifier: Expression) Statement

This should be translated by the compiler as follows:

for (I #i = Expression.iterator(); #i.hasNext(); ) {

        VariableModifiersopt Type Identifier = #i.next();
   Statement
}

However, because of type-erasure, the proposed translation is not type-safe. In fact, given the fact that the runtime type-signature for Iterator.next() is ()Ljava/lang/Object; javac should also emit a cast in order to preserve type-safety: the translation should thus look as follows:

for (I #i = Expression.iterator(); #i.hasNext(); ) {

        VariableModifiersopt VarType Identifier = (TargetType)#i.next();
   Statement
}

Where TargetType has to be carefully chosen among the existing possibilities:

1) The type of the enhanced-for-loop variable  (VarType)
2) The type of the parameter of the Iterable class that has to be iterated

Currently javac applies 2), but this is source of some problems as described in the related CR 6500701.

Translation for enhanced-for-loop exploiting arrays should be adjusted as well.

Comments
EVALUATION The translation is meant to be done before type erasure, in which case no cast is needed. However, for absolute clarity, it is worth making the cast mandatory. As an example of an edge case, consider: List<? extends Integer> l = ... for (float i : l) ... which should translate to: for (Iterator<Integer> #i = l.iterator(); #i.hasNext(); ) { float #i0 = (Integer)#i.next(); // Let assignment handle the unboxing-then-widening-primitive conversion The translation is thus: for (VT #i0 : Expression) ... -> for (I #i = Expression.iterator(); #i.hasNext(); ) { VT #i0 = (CT)#i.next(); where - if VT is a reference type, then CT == VT - if VT is a primitive type, then CT == Y, where I is Iterator<X> and Y is the upper bound of the capture conversion of X.
18-04-2008