JDK-6679509 : The compiler generates non-erased code when translating enhanced for loops
  • Type: Bug
  • Status: Closed
  • Resolution: Duplicate
  • Component: tools
  • Sub-Component: javac
  • Priority: P2
  • Affected Version: 7
  • OS: linux
  • CPU: x86
  • Submit Date: 2008-03-25
  • Updated Date: 2011-05-13
  • Resolved Date: 2008-04-18
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 Availabitlity Release.

To download the current JDK release, click here.
JDK 7
7Resolved
Related Reports
Duplicate :  
Description
An AssertionError occurs while compiling the following code using "javac -target 1.5 Main.java":
--------------------------------------------------------------------------
import java.util.List;

public class Main {

    public static void main(String[] args) {
        try {
        } finally {
            List<List<?>> l = null;
            for (List<?> textRegion : l) {
            }
        }
    }

}
--------------------------------------------------------------------------

Please note that "-target 1.5" is required on JDK6 and JDK7, can be omitted on JDK5.

I can reproduce on:
$ java -version
java version "1.5.0_12"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_12-b04)
Java HotSpot(TM) Server VM (build 1.5.0_12-b04, mixed mode)

$ java -version
java version "1.7.0-ea"
Java(TM) SE Runtime Environment (build 1.7.0-ea-b22)
Java HotSpot(TM) Server VM (build 11.0-b08, mixed mode)

$ java -version
java version "1.6.0_10-ea"
Java(TM) SE Runtime Environment (build 1.6.0_10-ea-b12)
Java HotSpot(TM) Server VM (build 11.0-b11, mixed mode)

Stack trace (from 1.7.0-ea-b22):
An exception has occurred in the compiler (1.7.0-ea). Please file a bug at the Java Developer Connection (http://java.sun.com/webapps/bugreport)  after checking the Bug Parade for duplicates. Include your program and the following diagnostic in your report.  Thank you.
java.lang.AssertionError: com.sun.tools.javac.jvm.Gen$1ComplexityScanner
        at com.sun.tools.javac.jvm.Gen$1ComplexityScanner.visitWildcard(Gen.java:1587)
        at com.sun.tools.javac.tree.JCTree$JCWildcard.accept(JCTree.java:1896)
        at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49)
        at com.sun.tools.javac.jvm.Gen$1ComplexityScanner.scan(Gen.java:1517)
        at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:57)
        at com.sun.tools.javac.tree.TreeScanner.visitTypeApply(TreeScanner.java:268)
        at com.sun.tools.javac.tree.JCTree$JCTypeApply.accept(JCTree.java:1840)
        at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49)
        at com.sun.tools.javac.jvm.Gen$1ComplexityScanner.scan(Gen.java:1517)
        at com.sun.tools.javac.tree.TreeScanner.visitVarDef(TreeScanner.java:94)
        at com.sun.tools.javac.tree.JCTree$JCVariableDecl.accept(JCTree.java:709)
        at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49)
        at com.sun.tools.javac.jvm.Gen$1ComplexityScanner.scan(Gen.java:1517)
        at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:57)
        at com.sun.tools.javac.tree.TreeScanner.visitBlock(TreeScanner.java:102)
        at com.sun.tools.javac.tree.JCTree$JCBlock.accept(JCTree.java:765)
        at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49)
        at com.sun.tools.javac.jvm.Gen$1ComplexityScanner.scan(Gen.java:1517)
        at com.sun.tools.javac.tree.TreeScanner.visitForLoop(TreeScanner.java:119)
        at com.sun.tools.javac.jvm.Gen$1ComplexityScanner.visitForLoop(Gen.java:1525)
        at com.sun.tools.javac.tree.JCTree$JCForLoop.accept(JCTree.java:856)
        at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49)
        at com.sun.tools.javac.jvm.Gen$1ComplexityScanner.scan(Gen.java:1517)
        at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:57)
        at com.sun.tools.javac.tree.TreeScanner.visitBlock(TreeScanner.java:102)
        at com.sun.tools.javac.tree.JCTree$JCBlock.accept(JCTree.java:765)
        at com.sun.tools.javac.jvm.Gen.estimateCodeComplexity(Gen.java:1591)
        at com.sun.tools.javac.jvm.Gen.visitTry(Gen.java:1311)
        at com.sun.tools.javac.tree.JCTree$JCTry.accept(JCTree.java:1023)
        at com.sun.tools.javac.jvm.Gen.genDef(Gen.java:679)
        at com.sun.tools.javac.jvm.Gen.genStat(Gen.java:714)
        at com.sun.tools.javac.jvm.Gen.genStat(Gen.java:700)
        at com.sun.tools.javac.jvm.Gen.genStats(Gen.java:751)
        at com.sun.tools.javac.jvm.Gen.visitBlock(Gen.java:1027)
        at com.sun.tools.javac.tree.JCTree$JCBlock.accept(JCTree.java:765)
        at com.sun.tools.javac.jvm.Gen.genDef(Gen.java:679)
        at com.sun.tools.javac.jvm.Gen.genStat(Gen.java:714)
        at com.sun.tools.javac.jvm.Gen.genMethod(Gen.java:907)
        at com.sun.tools.javac.jvm.Gen.visitMethodDef(Gen.java:880)
        at com.sun.tools.javac.tree.JCTree$JCMethodDecl.accept(JCTree.java:653)
        at com.sun.tools.javac.jvm.Gen.genDef(Gen.java:679)
        at com.sun.tools.javac.jvm.Gen.genClass(Gen.java:2219)
        at com.sun.tools.javac.main.JavaCompiler.genCode(JavaCompiler.java:631)
        at com.sun.tools.javac.main.JavaCompiler.generate(JavaCompiler.java:1303)
        at com.sun.tools.javac.main.JavaCompiler.generate(JavaCompiler.java:1273)
        at com.sun.tools.javac.main.JavaCompiler.compile2(JavaCompiler.java:779)
        at com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:744)
        at com.sun.tools.javac.main.Main.compile(Main.java:386)
        at com.sun.tools.javac.main.Main.compile(Main.java:312)
        at com.sun.tools.javac.main.Main.compile(Main.java:303)
        at com.sun.tools.javac.Main.compile(Main.java:82)
        at com.sun.tools.javac.Main.main(Main.java:67)

Comments
SUGGESTED FIX diff -r a1d1f335633f src/share/classes/com/sun/tools/javac/comp/Lower.java --- a/src/share/classes/com/sun/tools/javac/comp/Lower.java Wed Apr 09 15:30:44 2008 +0100 +++ b/src/share/classes/com/sun/tools/javac/comp/Lower.java Tue Apr 15 12:43:32 2008 +0100 @@ -2863,13 +2863,15 @@ public class Lower extends TreeTranslato JCExpressionStatement step = make.Exec(makeUnary(JCTree.PREINC, make.Ident(index))); Type elemtype = types.elemtype(tree.expr.type); - JCStatement loopvarinit = make. - VarDef(tree.var.sym, - make. - Indexed(make.Ident(arraycache), make.Ident(index)). - setType(elemtype)); + JCExpression loopvarinit = make.Indexed(make.Ident(arraycache), + make.Ident(index)).setType(elemtype); + JCVariableDecl loopvardef = (JCVariableDecl)make.VarDef(tree.var.mods, + tree.var.name, + tree.var.vartype, + loopvarinit).setType(tree.var.type); + loopvardef.sym = tree.var.sym; JCBlock body = make. - Block(0, List.of(loopvarinit, tree.body)); + Block(0, List.of(loopvardef, tree.body)); result = translate(make. ForLoop(loopinit, @@ -2944,7 +2946,11 @@ public class Lower extends TreeTranslato JCExpression vardefinit = make.App(make.Select(make.Ident(itvar), next)); if (iteratorTarget != syms.objectType) vardefinit = make.TypeCast(iteratorTarget, vardefinit); - JCVariableDecl indexDef = make.VarDef(tree.var.sym, vardefinit); + JCVariableDecl indexDef = (JCVariableDecl)make.VarDef(tree.var.mods, + tree.var.name, + tree.var.vartype, + vardefinit).setType(tree.var.type); + indexDef.sym = tree.var.sym; JCBlock body = make.Block(0, List.of(indexDef, tree.body)); result = translate(make. ForLoop(List.of(init),
2008-04-15

EVALUATION When Lower generates the trees corresponding to the foreach loops (namely within the two methods Lower.visitIterableForEachLoop() and Lower.visitArrayForEachLoop()) a synthetic variable declaration is generated by the compiler with a non-erased type. In particular, the folowing enhanced for loop: for (List<?> l : new ArrayList<List<?>>) {//code} gets translated into the following ordinary for-loop: for (java.util.Iterator i$ = l.iterator(); i$.hasNext(); ) { List<?> t = (List)i$.next(); {//code} } As it can be noticed, the type of the variable i$ is List<?> instead of the erased type List. This has to do with javac exploiting a method (namely TreeMaker.VarDef) for emitting the variable declaration AST based on the info contained into the type of the symbol of the loop variable (namely tree.var.sym.type). This bit doesn't get erased during TransTypes (during that process only tree.var.type gets erased), as the full generic signature contained inside the symbol may be required for further processing during the lowering phase (that happen at a later point) - e.g. for emitting synthetic casts in case the type of the variable is a type-variable. Even if this problem exists even without the command-line option -target 1.5, this option causes the AssertionError to be thrown. The reason has to do with the fact that starting from JDK 6, the compiler does not longer emit jsr/ret instructions for try/catch/finally blocks. That is, finally block are always inlined into the method exploiting them, thus making the check in Gen.ComplexityScanner pointless. However, if the compiler is run with the -target 1.5 option, the decision of whether the finally block has to be inlined or not method depends on Gen.estimateCodeComplexity; this method fails with the reported error when it encounters non-erased code (in this case the code in the finalizer had a wildcard in it).
2008-04-15

WORK AROUND Separate the code in the "finally" block into a method.
2008-03-25