< prev index next >

src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ArgumentAttr.java

Print this page

  1 /*
  2  * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.  Oracle designates this
  8  * particular file as subject to the "Classpath" exception as provided
  9  * by Oracle in the LICENSE file that accompanied this code.
 10  *
 11  * This code is distributed in the hope that it will be useful, but WITHOUT
 12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  * version 2 for more details (a copy is included in the LICENSE file that
 15  * accompanied this code).
 16  *
 17  * You should have received a copy of the GNU General Public License version
 18  * 2 along with this work; if not, write to the Free Software Foundation,
 19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  * or visit www.oracle.com if you need additional information or have any
 23  * questions.
 24  */
 25 
 26 package com.sun.tools.javac.comp;
 27 
 28 import com.sun.tools.javac.code.Flags;
 29 import com.sun.tools.javac.code.Symbol;
 30 import com.sun.tools.javac.code.Symtab;
 31 import com.sun.tools.javac.code.Type;

 32 import com.sun.tools.javac.code.Types.FunctionDescriptorLookupError;
 33 import com.sun.tools.javac.comp.Attr.ResultInfo;
 34 import com.sun.tools.javac.comp.Attr.TargetInfo;
 35 import com.sun.tools.javac.comp.Check.CheckContext;
 36 import com.sun.tools.javac.comp.DeferredAttr.AttrMode;
 37 import com.sun.tools.javac.comp.DeferredAttr.DeferredAttrContext;
 38 import com.sun.tools.javac.comp.DeferredAttr.DeferredType;
 39 import com.sun.tools.javac.comp.DeferredAttr.LambdaReturnScanner;
 40 import com.sun.tools.javac.comp.DeferredAttr.SwitchExpressionScanner;
 41 import com.sun.tools.javac.comp.Infer.PartiallyInferredMethodType;
 42 import com.sun.tools.javac.comp.Resolve.MethodResolutionPhase;
 43 import com.sun.tools.javac.resources.CompilerProperties.Fragments;
 44 import com.sun.tools.javac.tree.JCTree;
 45 import com.sun.tools.javac.tree.JCTree.JCConditional;
 46 import com.sun.tools.javac.tree.JCTree.JCExpression;
 47 import com.sun.tools.javac.tree.JCTree.JCLambda;
 48 import com.sun.tools.javac.tree.JCTree.JCLambda.ParameterKind;
 49 import com.sun.tools.javac.tree.JCTree.JCMemberReference;
 50 import com.sun.tools.javac.tree.JCTree.JCMethodInvocation;
 51 import com.sun.tools.javac.tree.JCTree.JCNewClass;

 87  * - if A is potentially a poly expression (i.e. diamond instance creation expression), a speculative
 88  * pass over A is performed; the results of such speculative attribution are then saved in a special
 89  * type, so that enclosing overload resolution can be carried by simply checking compatibility against the
 90  * type determined during this speculative pass.
 91  *
 92  * - if A is a standalone expression, regular attribution takes place.
 93  *
 94  * To minimize the speculative work, a cache is used, so that already computed argument types
 95  * associated with a given unique source location are never recomputed multiple times.
 96  */
 97 public class ArgumentAttr extends JCTree.Visitor {
 98 
 99     protected static final Context.Key<ArgumentAttr> methodAttrKey = new Context.Key<>();
100 
101     private final DeferredAttr deferredAttr;
102     private final JCDiagnostic.Factory diags;
103     private final Attr attr;
104     private final Symtab syms;
105     private final Log log;
106 


107     /** Attribution environment to be used. */
108     private Env<AttrContext> env;
109 
110     /** Result of method attribution. */
111     Type result;
112 
113     /** Cache for argument types; behavior is influenced by the currently selected cache policy. */
114     Map<UniquePos, ArgumentType<?>> argumentTypeCache = new LinkedHashMap<>();
115 
116     public static ArgumentAttr instance(Context context) {
117         ArgumentAttr instance = context.get(methodAttrKey);
118         if (instance == null)
119             instance = new ArgumentAttr(context);
120         return instance;
121     }
122 
123     @SuppressWarnings("this-escape")
124     protected ArgumentAttr(Context context) {
125         context.put(methodAttrKey, this);
126         deferredAttr = DeferredAttr.instance(context);
127         diags = JCDiagnostic.Factory.instance(context);
128         attr = Attr.instance(context);
129         syms = Symtab.instance(context);
130         log = Log.instance(context);

131     }
132 
133     /**
134      * Set the results of method attribution.
135      */
136     void setResult(JCExpression tree, Type type) {
137         result = type;
138         if (env.info.attributionMode == DeferredAttr.AttributionMode.SPECULATIVE) {
139             //if we are in a speculative branch we can save the type in the tree itself
140             //as there's no risk of polluting the original tree.
141             tree.type = result;
142         }
143     }
144 
145     /**
146      * Checks a type in the speculative tree against a given result; the type can be either a plain
147      * type or an argument type, in which case a more complex check is required.
148      */
149     Type checkSpeculative(JCTree expr, ResultInfo resultInfo) {
150         return checkSpeculative(expr, expr.type, resultInfo);

542 
543         /** Compute return expressions (if needed). */
544         List<JCReturn> returnExpressions() {
545             return returnExpressions.orElseGet(() -> {
546                 final List<JCReturn> res;
547                 ListBuffer<JCReturn> buf = new ListBuffer<>();
548                 new LambdaReturnScanner() {
549                     @Override
550                     public void visitReturn(JCReturn tree) {
551                         buf.add(tree);
552                     }
553                 }.scan(speculativeTree.body);
554                 res = buf.toList();
555                 returnExpressions = Optional.of(res);
556                 return res;
557             });
558         }
559 
560         @Override
561         Type overloadCheck(ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) {
562             try {
563                 //compute target-type; this logic could be shared with Attr
564                 TargetInfo targetInfo = attr.getTargetInfo(speculativeTree, resultInfo, argtypes());
565                 Type lambdaType = targetInfo.descriptor;
566                 Type currentTarget = targetInfo.target;
567                 //check compatibility
568                 checkLambdaCompatible(lambdaType, resultInfo);
569                 return currentTarget;
570             } catch (FunctionDescriptorLookupError ex) {
571                 resultInfo.checkContext.report(null, ex.getDiagnostic());
572                 return null; //cannot get here





573             }
574         }
575 
576         /** Check lambda against given target result */
577         private void checkLambdaCompatible(Type descriptor, ResultInfo resultInfo) {
578             CheckContext checkContext = resultInfo.checkContext;
579             ResultInfo bodyResultInfo = attr.lambdaBodyResult(speculativeTree, descriptor, resultInfo);
580             switch (speculativeTree.getBodyKind()) {
581                 case EXPRESSION:
582                     checkSpeculative(speculativeTree.body, speculativeTree.body.type, bodyResultInfo);
583                     break;
584                 case STATEMENT:
585                     for (JCReturn ret : returnExpressions()) {
586                         checkReturnInStatementLambda(ret, bodyResultInfo);
587                     }
588                     break;
589             }
590 
591             attr.checkLambdaCompatible(speculativeTree, descriptor, checkContext);
592         }

  1 /*
  2  * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.  Oracle designates this
  8  * particular file as subject to the "Classpath" exception as provided
  9  * by Oracle in the LICENSE file that accompanied this code.
 10  *
 11  * This code is distributed in the hope that it will be useful, but WITHOUT
 12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  * version 2 for more details (a copy is included in the LICENSE file that
 15  * accompanied this code).
 16  *
 17  * You should have received a copy of the GNU General Public License version
 18  * 2 along with this work; if not, write to the Free Software Foundation,
 19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  * or visit www.oracle.com if you need additional information or have any
 23  * questions.
 24  */
 25 
 26 package com.sun.tools.javac.comp;
 27 
 28 import com.sun.tools.javac.code.Flags;
 29 import com.sun.tools.javac.code.Symbol;
 30 import com.sun.tools.javac.code.Symtab;
 31 import com.sun.tools.javac.code.Type;
 32 import com.sun.tools.javac.code.Types;
 33 import com.sun.tools.javac.code.Types.FunctionDescriptorLookupError;
 34 import com.sun.tools.javac.comp.Attr.ResultInfo;
 35 import com.sun.tools.javac.comp.Attr.TargetInfo;
 36 import com.sun.tools.javac.comp.Check.CheckContext;
 37 import com.sun.tools.javac.comp.DeferredAttr.AttrMode;
 38 import com.sun.tools.javac.comp.DeferredAttr.DeferredAttrContext;
 39 import com.sun.tools.javac.comp.DeferredAttr.DeferredType;
 40 import com.sun.tools.javac.comp.DeferredAttr.LambdaReturnScanner;
 41 import com.sun.tools.javac.comp.DeferredAttr.SwitchExpressionScanner;
 42 import com.sun.tools.javac.comp.Infer.PartiallyInferredMethodType;
 43 import com.sun.tools.javac.comp.Resolve.MethodResolutionPhase;
 44 import com.sun.tools.javac.resources.CompilerProperties.Fragments;
 45 import com.sun.tools.javac.tree.JCTree;
 46 import com.sun.tools.javac.tree.JCTree.JCConditional;
 47 import com.sun.tools.javac.tree.JCTree.JCExpression;
 48 import com.sun.tools.javac.tree.JCTree.JCLambda;
 49 import com.sun.tools.javac.tree.JCTree.JCLambda.ParameterKind;
 50 import com.sun.tools.javac.tree.JCTree.JCMemberReference;
 51 import com.sun.tools.javac.tree.JCTree.JCMethodInvocation;
 52 import com.sun.tools.javac.tree.JCTree.JCNewClass;

 88  * - if A is potentially a poly expression (i.e. diamond instance creation expression), a speculative
 89  * pass over A is performed; the results of such speculative attribution are then saved in a special
 90  * type, so that enclosing overload resolution can be carried by simply checking compatibility against the
 91  * type determined during this speculative pass.
 92  *
 93  * - if A is a standalone expression, regular attribution takes place.
 94  *
 95  * To minimize the speculative work, a cache is used, so that already computed argument types
 96  * associated with a given unique source location are never recomputed multiple times.
 97  */
 98 public class ArgumentAttr extends JCTree.Visitor {
 99 
100     protected static final Context.Key<ArgumentAttr> methodAttrKey = new Context.Key<>();
101 
102     private final DeferredAttr deferredAttr;
103     private final JCDiagnostic.Factory diags;
104     private final Attr attr;
105     private final Symtab syms;
106     private final Log log;
107 
108     private final Types types;
109 
110     /** Attribution environment to be used. */
111     private Env<AttrContext> env;
112 
113     /** Result of method attribution. */
114     Type result;
115 
116     /** Cache for argument types; behavior is influenced by the currently selected cache policy. */
117     Map<UniquePos, ArgumentType<?>> argumentTypeCache = new LinkedHashMap<>();
118 
119     public static ArgumentAttr instance(Context context) {
120         ArgumentAttr instance = context.get(methodAttrKey);
121         if (instance == null)
122             instance = new ArgumentAttr(context);
123         return instance;
124     }
125 
126     @SuppressWarnings("this-escape")
127     protected ArgumentAttr(Context context) {
128         context.put(methodAttrKey, this);
129         deferredAttr = DeferredAttr.instance(context);
130         diags = JCDiagnostic.Factory.instance(context);
131         attr = Attr.instance(context);
132         syms = Symtab.instance(context);
133         log = Log.instance(context);
134         types = Types.instance(context);
135     }
136 
137     /**
138      * Set the results of method attribution.
139      */
140     void setResult(JCExpression tree, Type type) {
141         result = type;
142         if (env.info.attributionMode == DeferredAttr.AttributionMode.SPECULATIVE) {
143             //if we are in a speculative branch we can save the type in the tree itself
144             //as there's no risk of polluting the original tree.
145             tree.type = result;
146         }
147     }
148 
149     /**
150      * Checks a type in the speculative tree against a given result; the type can be either a plain
151      * type or an argument type, in which case a more complex check is required.
152      */
153     Type checkSpeculative(JCTree expr, ResultInfo resultInfo) {
154         return checkSpeculative(expr, expr.type, resultInfo);

546 
547         /** Compute return expressions (if needed). */
548         List<JCReturn> returnExpressions() {
549             return returnExpressions.orElseGet(() -> {
550                 final List<JCReturn> res;
551                 ListBuffer<JCReturn> buf = new ListBuffer<>();
552                 new LambdaReturnScanner() {
553                     @Override
554                     public void visitReturn(JCReturn tree) {
555                         buf.add(tree);
556                     }
557                 }.scan(speculativeTree.body);
558                 res = buf.toList();
559                 returnExpressions = Optional.of(res);
560                 return res;
561             });
562         }
563 
564         @Override
565         Type overloadCheck(ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) {
566             if (types.isQuoted(resultInfo.pt)) {
567                 // quoted lambda - always correct
568                 return resultInfo.pt;
569             } else {
570                 try {
571                     //compute target-type; this logic could be shared with Attr
572                     TargetInfo targetInfo = attr.getTargetInfo(speculativeTree, resultInfo, argtypes());
573                     Type lambdaType = targetInfo.descriptor;
574                     Type currentTarget = targetInfo.target;
575                     //check compatibility
576                     checkLambdaCompatible(lambdaType, resultInfo);
577                     return currentTarget;
578                 } catch (FunctionDescriptorLookupError ex) {
579                     resultInfo.checkContext.report(null, ex.getDiagnostic());
580                     return null; //cannot get here
581                 }
582             }
583         }
584 
585         /** Check lambda against given target result */
586         private void checkLambdaCompatible(Type descriptor, ResultInfo resultInfo) {
587             CheckContext checkContext = resultInfo.checkContext;
588             ResultInfo bodyResultInfo = attr.lambdaBodyResult(speculativeTree, descriptor, resultInfo);
589             switch (speculativeTree.getBodyKind()) {
590                 case EXPRESSION:
591                     checkSpeculative(speculativeTree.body, speculativeTree.body.type, bodyResultInfo);
592                     break;
593                 case STATEMENT:
594                     for (JCReturn ret : returnExpressions()) {
595                         checkReturnInStatementLambda(ret, bodyResultInfo);
596                     }
597                     break;
598             }
599 
600             attr.checkLambdaCompatible(speculativeTree, descriptor, checkContext);
601         }
< prev index next >