RFR: JDK-8203338: Unboxing in return from lambda miscompiled to throw ClassCastException

B. Blaser bsrbnd at gmail.com
Sat Jun 16 22:20:21 UTC 2018


Hi,

As noted in the JBS issue, the following example fails at run-time with a CCE:

    List.of('x', 'y').stream().max((a, b) -> { return List.of(a).get(0); });

The interesting point here is that removing 'return' makes it run successfully:

    List.of('x', 'y').stream().max((a, b) -> List.of(a).get(0));

The problem seems to be in 'TransType.visitReturn()'. The lambda
method doesn't yet exist ('currentMethod == null', see
'TransType.visitLambda()') causing the return expression type to be
set to the erasure of 'List.get()' (= Object) which further causes the
type conversion problem (see
'LambdaToMethod.makeLambdaStatementBody()').

The suggested fix (here under) is to keep the original erased
expression type (= Character) if 'currentMethod == null'.

Tier1 is OK.

Any feedback is welcome,
Bernard

diff -r ed8de3d0cd28
src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java
   Sat Jun 16 10:10:54 2018 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java
   Sat Jun 16 21:16:33 2018 +0200
@@ -601,7 +601,8 @@
     }

     public void visitReturn(JCReturn tree) {
-        tree.expr = translate(tree.expr, currentMethod != null ?
types.erasure(currentMethod.type).getReturnType() : null);
+        tree.expr = translate(tree.expr, currentMethod != null ?
types.erasure(currentMethod.type).getReturnType() :
+                tree.expr != null ? types.erasure(tree.expr.type) : null);
         result = tree;
     }


More information about the compiler-dev mailing list