< prev index next >

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

Print this page
rev 51104 : imported patch switch


   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.source.tree.LambdaExpressionTree.BodyKind;
  29 import com.sun.tools.javac.code.Flags;
  30 import com.sun.tools.javac.code.Symbol;
  31 import com.sun.tools.javac.code.Symtab;
  32 import com.sun.tools.javac.code.Type;
  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.DeferredTypeCompleter;
  41 import com.sun.tools.javac.comp.DeferredAttr.LambdaReturnScanner;

  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;
  53 import com.sun.tools.javac.tree.JCTree.JCParens;
  54 import com.sun.tools.javac.tree.JCTree.JCReturn;

  55 import com.sun.tools.javac.tree.TreeCopier;
  56 import com.sun.tools.javac.tree.TreeInfo;
  57 import com.sun.tools.javac.util.Assert;
  58 import com.sun.tools.javac.util.Context;
  59 import com.sun.tools.javac.util.DiagnosticSource;
  60 import com.sun.tools.javac.util.JCDiagnostic;
  61 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
  62 import com.sun.tools.javac.util.List;
  63 import com.sun.tools.javac.util.ListBuffer;
  64 import com.sun.tools.javac.util.Log;
  65 
  66 import java.util.HashMap;
  67 import java.util.LinkedHashMap;
  68 import java.util.Map;
  69 import java.util.Optional;
  70 import java.util.function.Function;
  71 import java.util.function.Supplier;
  72 
  73 import static com.sun.tools.javac.code.TypeTag.ARRAY;
  74 import static com.sun.tools.javac.code.TypeTag.DEFERRED;


 128         syms = Symtab.instance(context);
 129         log = Log.instance(context);
 130     }
 131 
 132     /**
 133      * Set the results of method attribution.
 134      */
 135     void setResult(JCExpression tree, Type type) {
 136         result = type;
 137         if (env.info.isSpeculative) {
 138             //if we are in a speculative branch we can save the type in the tree itself
 139             //as there's no risk of polluting the original tree.
 140             tree.type = result;
 141         }
 142     }
 143 
 144     /**
 145      * Checks a type in the speculative tree against a given result; the type can be either a plain
 146      * type or an argument type,in which case a more complex check is required.
 147      */
 148     Type checkSpeculative(JCExpression expr, ResultInfo resultInfo) {
 149         return checkSpeculative(expr, expr.type, resultInfo);
 150     }
 151 
 152     /**
 153      * Checks a type in the speculative tree against a given result; the type can be either a plain
 154      * type or an argument type,in which case a more complex check is required.
 155      */
 156     Type checkSpeculative(DiagnosticPosition pos, Type t, ResultInfo resultInfo) {
 157         if (t.hasTag(DEFERRED)) {
 158             return ((DeferredType)t).check(resultInfo);
 159         } else {
 160             return resultInfo.check(pos, t);
 161         }
 162     }
 163 
 164     /**
 165      * Returns a local caching context in which argument types can safely be cached without
 166      * the risk of polluting enclosing contexts. This is useful when attempting speculative
 167      * attribution of potentially erroneous expressions, which could end up polluting the cache.
 168      */


 239             //dup existing speculative type
 240             setResult(that, cached.dup(that, env));
 241         } else {
 242             Z res = argumentTypeFactory.get();
 243             argumentTypeCache.put(pos, res);
 244             setResult(that, res);
 245         }
 246     }
 247 
 248     @Override
 249     public void visitParens(JCParens that) {
 250         processArg(that, speculativeTree -> new ParensType(that, env, speculativeTree));
 251     }
 252 
 253     @Override
 254     public void visitConditional(JCConditional that) {
 255         processArg(that, speculativeTree -> new ConditionalType(that, env, speculativeTree));
 256     }
 257 
 258     @Override





 259     public void visitReference(JCMemberReference tree) {
 260         //perform arity-based check
 261         Env<AttrContext> localEnv = env.dup(tree);
 262         JCExpression exprTree;
 263         exprTree = (JCExpression)deferredAttr.attribSpeculative(tree.getQualifierExpression(), localEnv,
 264                 attr.memberReferenceQualifierResult(tree),
 265                 withLocalCacheContext());
 266         JCMemberReference mref2 = new TreeCopier<Void>(attr.make).copy(tree);
 267         mref2.expr = exprTree;
 268         Symbol lhsSym = TreeInfo.symbol(exprTree);
 269         localEnv.info.selectSuper = lhsSym != null && lhsSym.name == lhsSym.name.table.names._super;
 270         Symbol res =
 271                 attr.rs.getMemberReference(tree, localEnv, mref2,
 272                         exprTree.type, tree.name);
 273         if (!res.kind.isResolutionError()) {
 274             tree.sym = res;
 275         }
 276         if (res.kind.isResolutionTargetError() ||
 277                 res.type != null && res.type.hasTag(FORALL) ||
 278                 (res.flags() & Flags.VARARGS) != 0 ||


 435         @Override
 436         Type overloadCheck(ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) {
 437             ResultInfo localInfo = resultInfo.dup(attr.conditionalContext(resultInfo.checkContext));
 438             if (speculativeTree.isStandalone()) {
 439                 return localInfo.check(speculativeTree, speculativeTree.type);
 440             } else if (resultInfo.pt.hasTag(VOID)) {
 441                 //this means we are returning a poly conditional from void-compatible lambda expression
 442                 resultInfo.checkContext.report(tree, attr.diags.fragment(Fragments.ConditionalTargetCantBeVoid));
 443                 return attr.types.createErrorType(resultInfo.pt);
 444             } else {
 445                 //poly
 446                 checkSpeculative(speculativeTree.truepart, localInfo);
 447                 checkSpeculative(speculativeTree.falsepart, localInfo);
 448                 return localInfo.pt;
 449             }
 450         }
 451 
 452         @Override
 453         ArgumentType<JCConditional> dup(JCConditional tree, Env<AttrContext> env) {
 454             return new ConditionalType(tree, env, speculativeTree, speculativeTypes);

























































 455         }
 456     }
 457 
 458     /**
 459      * Argument type for explicit lambdas.
 460      */
 461     class ExplicitLambdaType extends ArgumentType<JCLambda> {
 462 
 463         /** List of argument types (lazily populated). */
 464         Optional<List<Type>> argtypes = Optional.empty();
 465 
 466         /** List of return expressions (lazily populated). */
 467         Optional<List<JCReturn>> returnExpressions = Optional.empty();
 468 
 469         ExplicitLambdaType(JCLambda originalLambda, Env<AttrContext> env, JCLambda speculativeLambda) {
 470             this(originalLambda, env, speculativeLambda, new HashMap<>());
 471         }
 472 
 473         ExplicitLambdaType(JCLambda originalLambda, Env<AttrContext> env, JCLambda speculativeLambda, Map<ResultInfo, Type> speculativeTypes) {
 474             super(originalLambda, env, speculativeLambda, speculativeTypes);




   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.DeferredTypeCompleter;
  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.JCBreak;
  47 import com.sun.tools.javac.tree.JCTree.JCConditional;
  48 import com.sun.tools.javac.tree.JCTree.JCExpression;
  49 import com.sun.tools.javac.tree.JCTree.JCLambda;
  50 import com.sun.tools.javac.tree.JCTree.JCLambda.ParameterKind;
  51 import com.sun.tools.javac.tree.JCTree.JCMemberReference;
  52 import com.sun.tools.javac.tree.JCTree.JCMethodInvocation;
  53 import com.sun.tools.javac.tree.JCTree.JCNewClass;
  54 import com.sun.tools.javac.tree.JCTree.JCParens;
  55 import com.sun.tools.javac.tree.JCTree.JCReturn;
  56 import com.sun.tools.javac.tree.JCTree.JCSwitchExpression;
  57 import com.sun.tools.javac.tree.TreeCopier;
  58 import com.sun.tools.javac.tree.TreeInfo;
  59 import com.sun.tools.javac.util.Assert;
  60 import com.sun.tools.javac.util.Context;
  61 import com.sun.tools.javac.util.DiagnosticSource;
  62 import com.sun.tools.javac.util.JCDiagnostic;
  63 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
  64 import com.sun.tools.javac.util.List;
  65 import com.sun.tools.javac.util.ListBuffer;
  66 import com.sun.tools.javac.util.Log;
  67 
  68 import java.util.HashMap;
  69 import java.util.LinkedHashMap;
  70 import java.util.Map;
  71 import java.util.Optional;
  72 import java.util.function.Function;
  73 import java.util.function.Supplier;
  74 
  75 import static com.sun.tools.javac.code.TypeTag.ARRAY;
  76 import static com.sun.tools.javac.code.TypeTag.DEFERRED;


 130         syms = Symtab.instance(context);
 131         log = Log.instance(context);
 132     }
 133 
 134     /**
 135      * Set the results of method attribution.
 136      */
 137     void setResult(JCExpression tree, Type type) {
 138         result = type;
 139         if (env.info.isSpeculative) {
 140             //if we are in a speculative branch we can save the type in the tree itself
 141             //as there's no risk of polluting the original tree.
 142             tree.type = result;
 143         }
 144     }
 145 
 146     /**
 147      * Checks a type in the speculative tree against a given result; the type can be either a plain
 148      * type or an argument type,in which case a more complex check is required.
 149      */
 150     Type checkSpeculative(JCTree expr, ResultInfo resultInfo) {
 151         return checkSpeculative(expr, expr.type, resultInfo);
 152     }
 153 
 154     /**
 155      * Checks a type in the speculative tree against a given result; the type can be either a plain
 156      * type or an argument type,in which case a more complex check is required.
 157      */
 158     Type checkSpeculative(DiagnosticPosition pos, Type t, ResultInfo resultInfo) {
 159         if (t.hasTag(DEFERRED)) {
 160             return ((DeferredType)t).check(resultInfo);
 161         } else {
 162             return resultInfo.check(pos, t);
 163         }
 164     }
 165 
 166     /**
 167      * Returns a local caching context in which argument types can safely be cached without
 168      * the risk of polluting enclosing contexts. This is useful when attempting speculative
 169      * attribution of potentially erroneous expressions, which could end up polluting the cache.
 170      */


 241             //dup existing speculative type
 242             setResult(that, cached.dup(that, env));
 243         } else {
 244             Z res = argumentTypeFactory.get();
 245             argumentTypeCache.put(pos, res);
 246             setResult(that, res);
 247         }
 248     }
 249 
 250     @Override
 251     public void visitParens(JCParens that) {
 252         processArg(that, speculativeTree -> new ParensType(that, env, speculativeTree));
 253     }
 254 
 255     @Override
 256     public void visitConditional(JCConditional that) {
 257         processArg(that, speculativeTree -> new ConditionalType(that, env, speculativeTree));
 258     }
 259 
 260     @Override
 261     public void visitSwitchExpression(JCSwitchExpression that) {
 262         processArg(that, speculativeTree -> new SwitchExpressionType(that, env, speculativeTree));
 263     }
 264 
 265     @Override
 266     public void visitReference(JCMemberReference tree) {
 267         //perform arity-based check
 268         Env<AttrContext> localEnv = env.dup(tree);
 269         JCExpression exprTree;
 270         exprTree = (JCExpression)deferredAttr.attribSpeculative(tree.getQualifierExpression(), localEnv,
 271                 attr.memberReferenceQualifierResult(tree),
 272                 withLocalCacheContext());
 273         JCMemberReference mref2 = new TreeCopier<Void>(attr.make).copy(tree);
 274         mref2.expr = exprTree;
 275         Symbol lhsSym = TreeInfo.symbol(exprTree);
 276         localEnv.info.selectSuper = lhsSym != null && lhsSym.name == lhsSym.name.table.names._super;
 277         Symbol res =
 278                 attr.rs.getMemberReference(tree, localEnv, mref2,
 279                         exprTree.type, tree.name);
 280         if (!res.kind.isResolutionError()) {
 281             tree.sym = res;
 282         }
 283         if (res.kind.isResolutionTargetError() ||
 284                 res.type != null && res.type.hasTag(FORALL) ||
 285                 (res.flags() & Flags.VARARGS) != 0 ||


 442         @Override
 443         Type overloadCheck(ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) {
 444             ResultInfo localInfo = resultInfo.dup(attr.conditionalContext(resultInfo.checkContext));
 445             if (speculativeTree.isStandalone()) {
 446                 return localInfo.check(speculativeTree, speculativeTree.type);
 447             } else if (resultInfo.pt.hasTag(VOID)) {
 448                 //this means we are returning a poly conditional from void-compatible lambda expression
 449                 resultInfo.checkContext.report(tree, attr.diags.fragment(Fragments.ConditionalTargetCantBeVoid));
 450                 return attr.types.createErrorType(resultInfo.pt);
 451             } else {
 452                 //poly
 453                 checkSpeculative(speculativeTree.truepart, localInfo);
 454                 checkSpeculative(speculativeTree.falsepart, localInfo);
 455                 return localInfo.pt;
 456             }
 457         }
 458 
 459         @Override
 460         ArgumentType<JCConditional> dup(JCConditional tree, Env<AttrContext> env) {
 461             return new ConditionalType(tree, env, speculativeTree, speculativeTypes);
 462         }
 463     }
 464 
 465     /**
 466      * Argument type for switch expressions.
 467      */
 468     class SwitchExpressionType extends ArgumentType<JCSwitchExpression> {
 469         /** List of break expressions (lazily populated). */
 470         Optional<List<JCBreak>> breakExpressions = Optional.empty();
 471 
 472         SwitchExpressionType(JCExpression tree, Env<AttrContext> env, JCSwitchExpression speculativeCond) {
 473             this(tree, env, speculativeCond, new HashMap<>());
 474         }
 475 
 476         SwitchExpressionType(JCExpression tree, Env<AttrContext> env, JCSwitchExpression speculativeCond, Map<ResultInfo, Type> speculativeTypes) {
 477            super(tree, env, speculativeCond, speculativeTypes);
 478         }
 479 
 480         @Override
 481         Type overloadCheck(ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) {
 482             ResultInfo localInfo = resultInfo.dup(attr.conditionalContext(resultInfo.checkContext));
 483             if (speculativeTree.isStandalone()) {
 484                 return localInfo.check(speculativeTree, speculativeTree.type);
 485             } else if (resultInfo.pt.hasTag(VOID)) {
 486                 //this means we are returning a poly switch expression from void-compatible lambda expression
 487                 resultInfo.checkContext.report(tree, attr.diags.fragment(Fragments.SwitchExpressionTargetCantBeVoid));
 488                 return attr.types.createErrorType(resultInfo.pt);
 489             } else {
 490                 //poly
 491                 for (JCBreak brk : breakExpressions()) {
 492                     checkSpeculative(brk.value, brk.value.type, resultInfo);
 493                 }
 494                 return localInfo.pt;
 495             }
 496         }
 497 
 498         /** Compute return expressions (if needed). */
 499         List<JCBreak> breakExpressions() {
 500             return breakExpressions.orElseGet(() -> {
 501                 final List<JCBreak> res;
 502                 ListBuffer<JCBreak> buf = new ListBuffer<>();
 503                 new SwitchExpressionScanner() {
 504                     @Override
 505                     public void visitBreak(JCBreak tree) {
 506                         if (tree.target == speculativeTree)
 507                             buf.add(tree);
 508                     }
 509                 }.scan(speculativeTree.cases);
 510                 res = buf.toList();
 511                 breakExpressions = Optional.of(res);
 512                 return res;
 513             });
 514         }
 515 
 516         @Override
 517         ArgumentType<JCSwitchExpression> dup(JCSwitchExpression tree, Env<AttrContext> env) {
 518             return new SwitchExpressionType(tree, env, speculativeTree, speculativeTypes);
 519         }
 520     }
 521 
 522     /**
 523      * Argument type for explicit lambdas.
 524      */
 525     class ExplicitLambdaType extends ArgumentType<JCLambda> {
 526 
 527         /** List of argument types (lazily populated). */
 528         Optional<List<Type>> argtypes = Optional.empty();
 529 
 530         /** List of return expressions (lazily populated). */
 531         Optional<List<JCReturn>> returnExpressions = Optional.empty();
 532 
 533         ExplicitLambdaType(JCLambda originalLambda, Env<AttrContext> env, JCLambda speculativeLambda) {
 534             this(originalLambda, env, speculativeLambda, new HashMap<>());
 535         }
 536 
 537         ExplicitLambdaType(JCLambda originalLambda, Env<AttrContext> env, JCLambda speculativeLambda, Map<ResultInfo, Type> speculativeTypes) {
 538             super(originalLambda, env, speculativeLambda, speculativeTypes);


< prev index next >