Tue, 22 Jan 2013 16:39:51 +0000
8006684: Compiler produces java.lang.VerifyError: Bad type on operand stack
Summary: Lambda desugaring generates spurious references to 'this' in static contexts
Reviewed-by: jjg
1.1 --- a/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java Tue Jan 22 16:23:35 2013 +0000 1.2 +++ b/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java Tue Jan 22 16:39:51 2013 +0000 1.3 @@ -859,8 +859,8 @@ 1.4 finally { 1.5 frameStack = prevStack; 1.6 } 1.7 - if (frameStack.nonEmpty() && enclosingLambda() != null) { 1.8 - // Any class defined within a lambda is an implicit 'this' reference 1.9 + if (!tree.sym.isStatic() && frameStack.nonEmpty() && enclosingLambda() != null) { 1.10 + // Any (non-static) class defined within a lambda is an implicit 'this' reference 1.11 // because its constructor will reference the enclosing class 1.12 ((LambdaTranslationContext) context()).addSymbol(tree.sym.type.getEnclosingType().tsym, CAPTURED_THIS); 1.13 } 1.14 @@ -994,6 +994,11 @@ 1.15 * (required to skip synthetic lambda symbols) 1.16 */ 1.17 private Symbol owner() { 1.18 + return owner(false); 1.19 + } 1.20 + 1.21 + @SuppressWarnings("fallthrough") 1.22 + private Symbol owner(boolean skipLambda) { 1.23 List<Frame> frameStack2 = frameStack; 1.24 while (frameStack2.nonEmpty()) { 1.25 switch (frameStack2.head.tree.getTag()) { 1.26 @@ -1012,7 +1017,8 @@ 1.27 case METHODDEF: 1.28 return ((JCMethodDecl)frameStack2.head.tree).sym; 1.29 case LAMBDA: 1.30 - return ((LambdaTranslationContext)contextMap.get(frameStack2.head.tree)).translatedSym; 1.31 + if (!skipLambda) 1.32 + return ((LambdaTranslationContext)contextMap.get(frameStack2.head.tree)).translatedSym; 1.33 default: 1.34 frameStack2 = frameStack2.tail; 1.35 } 1.36 @@ -1311,8 +1317,9 @@ 1.37 } 1.38 1.39 Type enclosingType() { 1.40 - //local inner classes defined inside a lambda are always non-static 1.41 - return owner.enclClass().type; 1.42 + return owner.isStatic() ? 1.43 + Type.noType : 1.44 + owner.enclClass().type; 1.45 } 1.46 1.47 Type generatedLambdaSig() {
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/test/tools/javac/lambda/LambdaExpr21.java Tue Jan 22 16:39:51 2013 +0000 2.3 @@ -0,0 +1,67 @@ 2.4 +/* 2.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 2.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 2.7 + * 2.8 + * This code is free software; you can redistribute it and/or modify it 2.9 + * under the terms of the GNU General Public License version 2 only, as 2.10 + * published by the Free Software Foundation. 2.11 + * 2.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 2.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 2.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 2.15 + * version 2 for more details (a copy is included in the LICENSE file that 2.16 + * accompanied this code). 2.17 + * 2.18 + * You should have received a copy of the GNU General Public License version 2.19 + * 2 along with this work; if not, write to the Free Software Foundation, 2.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2.21 + * 2.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2.23 + * or visit www.oracle.com if you need additional information or have any 2.24 + * questions. 2.25 + */ 2.26 + 2.27 +/* 2.28 + * @test 2.29 + * @bug 8006684 2.30 + * @summary Compiler produces java.lang.VerifyError: Bad type on operand stack 2.31 + * @run main LambdaExpr21 2.32 + */ 2.33 +public class LambdaExpr21 { 2.34 + 2.35 + static int assertionCount = 0; 2.36 + 2.37 + static void assertTrue(boolean cond) { 2.38 + assertionCount++; 2.39 + if (!cond) 2.40 + throw new AssertionError(); 2.41 + } 2.42 + 2.43 + interface SAM { 2.44 + void foo(); 2.45 + } 2.46 + 2.47 + static class Checker { 2.48 + Checker(boolean cond) { 2.49 + assertTrue(cond); 2.50 + } 2.51 + } 2.52 + 2.53 + static { 2.54 + SAM s = ()-> { new Checker(true) { }; }; 2.55 + s.foo(); 2.56 + } 2.57 + 2.58 + static void test(){ 2.59 + SAM s = ()-> { new Checker(true) { }; }; 2.60 + s.foo(); 2.61 + } 2.62 + 2.63 + static SAM s = ()-> { new Checker(true) { }; }; 2.64 + 2.65 + public static void main(String[] args) { 2.66 + test(); 2.67 + s.foo(); 2.68 + assertTrue(assertionCount == 3); 2.69 + } 2.70 +}