Thu, 22 Aug 2013 13:12:43 +0100
8023112: javac should not use lazy constant evaluation approach for method references
Reviewed-by: jjg, mcimadamore
1.1 --- a/src/share/classes/com/sun/tools/javac/comp/Attr.java Thu Aug 22 10:22:44 2013 +0100 1.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Attr.java Thu Aug 22 13:12:43 2013 +0100 1.3 @@ -1063,9 +1063,7 @@ 1.4 1.5 if (tree.init != null) { 1.6 if ((v.flags_field & FINAL) != 0 && 1.7 - !tree.init.hasTag(NEWCLASS) && 1.8 - !tree.init.hasTag(LAMBDA) && 1.9 - !tree.init.hasTag(REFERENCE)) { 1.10 + memberEnter.needsLazyConstValue(tree.init)) { 1.11 // In this case, `v' is final. Ensure that it's initializer is 1.12 // evaluated. 1.13 v.getConstValue(); // ensure initializer is evaluated
2.1 --- a/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java Thu Aug 22 10:22:44 2013 +0100 2.2 +++ b/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java Thu Aug 22 13:12:43 2013 +0100 2.3 @@ -677,8 +677,7 @@ 2.4 if (tree.init != null) { 2.5 v.flags_field |= HASINIT; 2.6 if ((v.flags_field & FINAL) != 0 && 2.7 - !tree.init.hasTag(NEWCLASS) && 2.8 - !tree.init.hasTag(LAMBDA)) { 2.9 + needsLazyConstValue(tree.init)) { 2.10 Env<AttrContext> initEnv = getInitEnv(tree, env); 2.11 initEnv.info.enclVar = v; 2.12 v.setLazyConstValue(initEnv(tree, initEnv), attr, tree.init); 2.13 @@ -700,6 +699,59 @@ 2.14 } 2.15 } 2.16 2.17 + public boolean needsLazyConstValue(JCTree tree) { 2.18 + InitTreeVisitor initTreeVisitor = new InitTreeVisitor(); 2.19 + tree.accept(initTreeVisitor); 2.20 + return initTreeVisitor.result; 2.21 + } 2.22 + 2.23 + /** Visitor class for expressions which might be constant expressions. 2.24 + */ 2.25 + static class InitTreeVisitor extends JCTree.Visitor { 2.26 + 2.27 + private boolean result = true; 2.28 + 2.29 + @Override 2.30 + public void visitTree(JCTree tree) {} 2.31 + 2.32 + @Override 2.33 + public void visitNewClass(JCNewClass that) { 2.34 + result = false; 2.35 + } 2.36 + 2.37 + @Override 2.38 + public void visitLambda(JCLambda that) { 2.39 + result = false; 2.40 + } 2.41 + 2.42 + @Override 2.43 + public void visitReference(JCMemberReference that) { 2.44 + result = false; 2.45 + } 2.46 + 2.47 + @Override 2.48 + public void visitSelect(JCFieldAccess tree) { 2.49 + tree.selected.accept(this); 2.50 + } 2.51 + 2.52 + @Override 2.53 + public void visitConditional(JCConditional tree) { 2.54 + tree.cond.accept(this); 2.55 + tree.truepart.accept(this); 2.56 + tree.falsepart.accept(this); 2.57 + } 2.58 + 2.59 + @Override 2.60 + public void visitParens(JCParens tree) { 2.61 + tree.expr.accept(this); 2.62 + } 2.63 + 2.64 + @Override 2.65 + public void visitTypeCast(JCTypeCast tree) { 2.66 + tree.expr.accept(this); 2.67 + } 2.68 + } 2.69 + 2.70 /** Create a fresh environment for a variable's initializer. 2.71 * If the variable is a field, the owner of the environment's scope 2.72 * is be the variable itself, otherwise the owner is the method
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/test/tools/javac/T8023112/SkipLazyConstantCreationForMethodRefTest.java Thu Aug 22 13:12:43 2013 +0100 3.3 @@ -0,0 +1,58 @@ 3.4 +/* 3.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 3.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3.7 + * 3.8 + * This code is free software; you can redistribute it and/or modify it 3.9 + * under the terms of the GNU General Public License version 2 only, as 3.10 + * published by the Free Software Foundation. Oracle designates this 3.11 + * particular file as subject to the "Classpath" exception as provided 3.12 + * by Oracle in the LICENSE file that accompanied this code. 3.13 + * 3.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 3.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 3.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 3.17 + * version 2 for more details (a copy is included in the LICENSE file that 3.18 + * accompanied this code). 3.19 + * 3.20 + * You should have received a copy of the GNU General Public License version 3.21 + * 2 along with this work; if not, write to the Free Software Foundation, 3.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 3.23 + * 3.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 3.25 + * or visit www.oracle.com if you need additional information or have any 3.26 + * questions. 3.27 + */ 3.28 + 3.29 +/* 3.30 + * @test 3.31 + * @bug 8023112 3.32 + * @summary Mixing up the method type argument with the class type for method 3.33 + * reference ClassType<Q>::<T>new 3.34 + * @compile SkipLazyConstantCreationForMethodRefTest.java 3.35 + */ 3.36 + 3.37 +public class SkipLazyConstantCreationForMethodRefTest<T> { 3.38 + SkipLazyConstantCreationForMethodRefTest(int a, boolean b) {} 3.39 + SkipLazyConstantCreationForMethodRefTest() {} 3.40 +} 3.41 + 3.42 +class SubClass<T> extends SkipLazyConstantCreationForMethodRefTest { 3.43 + SubClass(int a, boolean b) {} 3.44 +} 3.45 + 3.46 +interface SAM { 3.47 + SubClass<SkipLazyConstantCreationForMethodRefTest> m(int a, boolean b); 3.48 +} 3.49 + 3.50 +interface Tester1 { 3.51 + SAM s11 = SubClass<SkipLazyConstantCreationForMethodRefTest>::<Object>new; 3.52 + SAM s12 = (SubClass<SkipLazyConstantCreationForMethodRefTest>::<Object>new); 3.53 + SAM s13 = (SAM)SubClass<SkipLazyConstantCreationForMethodRefTest>::<Object>new; 3.54 + SAM s14 = true ? s11 : s12; 3.55 + SAM s15 = true ? s11 : (SAM)SubClass<SkipLazyConstantCreationForMethodRefTest>::<Object>new; 3.56 + SAM s16 = true ? (SAM)SubClass<SkipLazyConstantCreationForMethodRefTest>::<Object>new : s12; 3.57 +} 3.58 + 3.59 +interface Tester2 { 3.60 + SAM s21 = Tester1.s11; 3.61 +}