8023112: javac should not use lazy constant evaluation approach for method references

Thu, 22 Aug 2013 13:12:43 +0100

author
vromero
date
Thu, 22 Aug 2013 13:12:43 +0100
changeset 1974
25aaff78d754
parent 1973
7a4717f3ea7b
child 1975
1ab22e60a738

8023112: javac should not use lazy constant evaluation approach for method references
Reviewed-by: jjg, mcimadamore

src/share/classes/com/sun/tools/javac/comp/Attr.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/comp/MemberEnter.java file | annotate | diff | comparison | revisions
test/tools/javac/T8023112/SkipLazyConstantCreationForMethodRefTest.java file | annotate | diff | comparison | revisions
     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 +}

mercurial