1 /*
   2  * Copyright (c) 2015, 2017, 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.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;
  75 import static com.sun.tools.javac.code.TypeTag.FORALL;
  76 import static com.sun.tools.javac.code.TypeTag.METHOD;
  77 import static com.sun.tools.javac.code.TypeTag.VOID;
  78 
  79 /**
  80  * This class performs attribution of method/constructor arguments when target-typing is enabled
  81  * (source >= 8); for each argument that is potentially a poly expression, this class builds
  82  * a rich representation (see {@link ArgumentType} which can then be used for performing fast overload
  83  * checks without requiring multiple attribution passes over the same code.
  84  *
  85  * The attribution strategy for a given method/constructor argument A is as follows:
  86  *
  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 atributtion 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 influences by the currrently 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     protected ArgumentAttr(Context context) {
 124         context.put(methodAttrKey, this);
 125         deferredAttr = DeferredAttr.instance(context);
 126         diags = JCDiagnostic.Factory.instance(context);
 127         attr = Attr.instance(context);
 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      */
 169     LocalCacheContext withLocalCacheContext() {
 170         return new LocalCacheContext();
 171     }
 172 
 173     /**
 174      * Local cache context; this class keeps track of the previous cache and reverts to it
 175      * when the {@link LocalCacheContext#leave()} method is called.
 176      */
 177     class LocalCacheContext {
 178         Map<UniquePos, ArgumentType<?>> prevCache;
 179 
 180         public LocalCacheContext() {
 181             this.prevCache = argumentTypeCache;
 182             argumentTypeCache = new HashMap<>();
 183         }
 184 
 185         public void leave() {
 186             argumentTypeCache = prevCache;
 187         }
 188     }
 189 
 190     /**
 191      * Main entry point for attributing an argument with given tree and attribution environment.
 192      */
 193     Type attribArg(JCTree tree, Env<AttrContext> env) {
 194         Env<AttrContext> prevEnv = this.env;
 195         try {
 196             this.env = env;
 197             tree.accept(this);
 198             return result;
 199         } finally {
 200             this.env = prevEnv;
 201         }
 202     }
 203 
 204     @Override
 205     public void visitTree(JCTree that) {
 206         //delegates to Attr
 207         that.accept(attr);
 208         result = attr.result;
 209     }
 210 
 211     /**
 212      * Process a method argument; this method takes care of performing a speculative pass over the
 213      * argument tree and calling a well-defined entry point to build the argument type associated
 214      * with such tree.
 215      */
 216     @SuppressWarnings("unchecked")
 217     <T extends JCExpression, Z extends ArgumentType<T>> void processArg(T that, Function<T, Z> argumentTypeFactory) {
 218         UniquePos pos = new UniquePos(that);
 219         processArg(that, () -> {
 220             T speculativeTree = (T)deferredAttr.attribSpeculative(that, env, attr.new MethodAttrInfo() {
 221                 @Override
 222                 protected boolean needsArgumentAttr(JCTree tree) {
 223                     return !new UniquePos(tree).equals(pos);
 224                 }
 225             });
 226             return argumentTypeFactory.apply(speculativeTree);
 227         });
 228     }
 229 
 230     /**
 231      * Process a method argument; this method allows the caller to specify a custom speculative attribution
 232      * logic (this is used e.g. for lambdas).
 233      */
 234     @SuppressWarnings("unchecked")
 235     <T extends JCExpression, Z extends ArgumentType<T>> void processArg(T that, Supplier<Z> argumentTypeFactory) {
 236         UniquePos pos = new UniquePos(that);
 237         Z cached = (Z)argumentTypeCache.get(pos);
 238         if (cached != null) {
 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 ||
 279                 (TreeInfo.isStaticSelector(exprTree, tree.name.table.names) &&
 280                 exprTree.type.isRaw() && !exprTree.type.hasTag(ARRAY))) {
 281             tree.setOverloadKind(JCMemberReference.OverloadKind.OVERLOADED);
 282         } else {
 283             tree.setOverloadKind(JCMemberReference.OverloadKind.UNOVERLOADED);
 284         }
 285         //return a plain old deferred type for this
 286         setResult(tree, deferredAttr.new DeferredType(tree, env));
 287     }
 288 
 289     @Override
 290     public void visitLambda(JCLambda that) {
 291         if (that.paramKind == ParameterKind.EXPLICIT) {
 292             //if lambda is explicit, we can save info in the corresponding argument type
 293             processArg(that, () -> {
 294                 JCLambda speculativeLambda =
 295                         deferredAttr.attribSpeculativeLambda(that, env, attr.methodAttrInfo);
 296                 return new ExplicitLambdaType(that, env, speculativeLambda);
 297             });
 298         } else {
 299             //otherwise just use a deferred type
 300             setResult(that, deferredAttr.new DeferredType(that, env));
 301         }
 302     }
 303 
 304     @Override
 305     public void visitApply(JCMethodInvocation that) {
 306         if (that.getTypeArguments().isEmpty()) {
 307             processArg(that, speculativeTree -> new ResolvedMethodType(that, env, speculativeTree));
 308         } else {
 309             //not a poly expression, just call Attr
 310             setResult(that, attr.attribTree(that, env, attr.unknownExprInfo));
 311         }
 312     }
 313 
 314     @Override
 315     public void visitNewClass(JCNewClass that) {
 316         if (TreeInfo.isDiamond(that)) {
 317             processArg(that, speculativeTree -> new ResolvedConstructorType(that, env, speculativeTree));
 318         } else {
 319             //not a poly expression, just call Attr
 320             setResult(that, attr.attribTree(that, env, attr.unknownExprInfo));
 321         }
 322     }
 323 
 324     /**
 325      * An argument type is similar to a plain deferred type; the most important difference is that
 326      * the completion logic associated with argument types allows speculative attribution to be skipped
 327      * during overload resolution - that is, an argument type always has enough information to
 328      * perform an overload check without the need of calling back to Attr. This extra information
 329      * is typically stored in the form of a speculative tree.
 330      */
 331     abstract class ArgumentType<T extends JCExpression> extends DeferredType implements DeferredTypeCompleter {
 332 
 333         /** The speculative tree carrying type information. */
 334         T speculativeTree;
 335 
 336         /** Types associated with this argument (one type per possible target result). */
 337         Map<ResultInfo, Type> speculativeTypes;
 338 
 339         public ArgumentType(JCExpression tree, Env<AttrContext> env, T speculativeTree, Map<ResultInfo, Type> speculativeTypes) {
 340             deferredAttr.super(tree, env);
 341             this.speculativeTree = speculativeTree;
 342             this.speculativeTypes = speculativeTypes;
 343         }
 344 
 345         @Override
 346         final DeferredTypeCompleter completer() {
 347             return this;
 348         }
 349 
 350         @Override
 351         final public Type complete(DeferredType dt, ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) {
 352             Assert.check(dt == this);
 353             if (deferredAttrContext.mode == AttrMode.SPECULATIVE) {
 354                 Type t = (resultInfo.pt == Type.recoveryType) ?
 355                         deferredAttr.basicCompleter.complete(dt, resultInfo, deferredAttrContext) :
 356                         overloadCheck(resultInfo, deferredAttrContext);
 357                 speculativeTypes.put(resultInfo, t);
 358                 return t;
 359             } else {
 360                 if (!env.info.isSpeculative) {
 361                     argumentTypeCache.remove(new UniquePos(dt.tree));
 362                 }
 363                 return deferredAttr.basicCompleter.complete(dt, resultInfo, deferredAttrContext);
 364             }
 365         }
 366 
 367         @Override
 368         Type speculativeType(Symbol msym, MethodResolutionPhase phase) {
 369             if (notPertinentToApplicability.contains(msym)) {
 370                 return super.speculativeType(msym, phase);
 371             } else {
 372                 for (Map.Entry<ResultInfo, Type> _entry : speculativeTypes.entrySet()) {
 373                     DeferredAttrContext deferredAttrContext = _entry.getKey().checkContext.deferredAttrContext();
 374                     if (deferredAttrContext.phase == phase && deferredAttrContext.msym == msym) {
 375                         return _entry.getValue();
 376                     }
 377                 }
 378                 return Type.noType;
 379             }
 380         }
 381 
 382         @Override
 383         JCTree speculativeTree(DeferredAttrContext deferredAttrContext) {
 384             return notPertinentToApplicability.contains(deferredAttrContext.msym) ?
 385                     super.speculativeTree(deferredAttrContext) :
 386                     speculativeTree;
 387         }
 388 
 389         /**
 390          * Performs an overload check against a given target result.
 391          */
 392         abstract Type overloadCheck(ResultInfo resultInfo, DeferredAttrContext deferredAttrContext);
 393 
 394         /**
 395          * Creates a copy of this argument type with given tree and environment.
 396          */
 397         abstract ArgumentType<T> dup(T tree, Env<AttrContext> env);
 398     }
 399 
 400     /**
 401      * Argument type for parenthesized expression.
 402      */
 403     class ParensType extends ArgumentType<JCParens> {
 404         ParensType(JCExpression tree, Env<AttrContext> env, JCParens speculativeParens) {
 405             this(tree, env, speculativeParens, new HashMap<>());
 406         }
 407 
 408         ParensType(JCExpression tree, Env<AttrContext> env, JCParens speculativeParens, Map<ResultInfo, Type> speculativeTypes) {
 409            super(tree, env, speculativeParens, speculativeTypes);
 410         }
 411 
 412         @Override
 413         Type overloadCheck(ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) {
 414             return checkSpeculative(speculativeTree.expr, resultInfo);
 415         }
 416 
 417         @Override
 418         ArgumentType<JCParens> dup(JCParens tree, Env<AttrContext> env) {
 419             return new ParensType(tree, env, speculativeTree, speculativeTypes);
 420         }
 421     }
 422 
 423     /**
 424      * Argument type for conditionals.
 425      */
 426     class ConditionalType extends ArgumentType<JCConditional> {
 427         ConditionalType(JCExpression tree, Env<AttrContext> env, JCConditional speculativeCond) {
 428             this(tree, env, speculativeCond, new HashMap<>());
 429         }
 430 
 431         ConditionalType(JCExpression tree, Env<AttrContext> env, JCConditional speculativeCond, Map<ResultInfo, Type> speculativeTypes) {
 432            super(tree, env, speculativeCond, speculativeTypes);
 433         }
 434 
 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);
 475         }
 476 
 477         /** Compute argument types (if needed). */
 478         List<Type> argtypes() {
 479             return argtypes.orElseGet(() -> {
 480                 List<Type> res = TreeInfo.types(speculativeTree.params);
 481                 argtypes = Optional.of(res);
 482                 return res;
 483             });
 484         }
 485 
 486         /** Compute return expressions (if needed). */
 487         List<JCReturn> returnExpressions() {
 488             return returnExpressions.orElseGet(() -> {
 489                 final List<JCReturn> res;
 490                 ListBuffer<JCReturn> buf = new ListBuffer<>();
 491                 new LambdaReturnScanner() {
 492                     @Override
 493                     public void visitReturn(JCReturn tree) {
 494                         buf.add(tree);
 495                     }
 496                 }.scan(speculativeTree.body);
 497                 res = buf.toList();
 498                 returnExpressions = Optional.of(res);
 499                 return res;
 500             });
 501         }
 502 
 503         @Override
 504         Type overloadCheck(ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) {
 505             try {
 506                 //compute target-type; this logic could be shared with Attr
 507                 TargetInfo targetInfo = attr.getTargetInfo(speculativeTree, resultInfo, argtypes());
 508                 Type lambdaType = targetInfo.descriptor;
 509                 Type currentTarget = targetInfo.target;
 510                 //check compatibility
 511                 checkLambdaCompatible(lambdaType, resultInfo);
 512                 return currentTarget;
 513             } catch (FunctionDescriptorLookupError ex) {
 514                 resultInfo.checkContext.report(null, ex.getDiagnostic());
 515                 return null; //cannot get here
 516             }
 517         }
 518 
 519         /** Check lambda against given target result */
 520         private void checkLambdaCompatible(Type descriptor, ResultInfo resultInfo) {
 521             CheckContext checkContext = resultInfo.checkContext;
 522             ResultInfo bodyResultInfo = attr.lambdaBodyResult(speculativeTree, descriptor, resultInfo);
 523             switch (speculativeTree.getBodyKind()) {
 524                 case EXPRESSION:
 525                     checkSpeculative(speculativeTree.body, speculativeTree.body.type, bodyResultInfo);
 526                     break;
 527                 case STATEMENT:
 528                     for (JCReturn ret : returnExpressions()) {
 529                         checkReturnInStatementLambda(ret, bodyResultInfo);
 530                     }
 531                     break;
 532             }
 533 
 534             attr.checkLambdaCompatible(speculativeTree, descriptor, checkContext);
 535         }
 536 
 537         /**
 538          * This is an inlined version of {@link Attr#visitReturn(JCReturn)}.
 539          */
 540         void checkReturnInStatementLambda(JCReturn ret, ResultInfo resultInfo) {
 541             if (resultInfo.pt.hasTag(VOID) && ret.expr != null) {
 542                 //fail - if the function type's result is void, the lambda body must be a void-compatible block.
 543                 resultInfo.checkContext.report(speculativeTree.pos(),
 544                         diags.fragment("unexpected.ret.val"));
 545             } else if (!resultInfo.pt.hasTag(VOID)) {
 546                 if (ret.expr == null) {
 547                     //fail - if the function type's result is non-void, the lambda body must be a value-compatible block.
 548                     resultInfo.checkContext.report(speculativeTree.pos(),
 549                             diags.fragment("missing.ret.val"));
 550                 }
 551                 checkSpeculative(ret.expr, ret.expr.type, resultInfo);
 552             }
 553         }
 554 
 555         /** Get the type associated with given return expression. */
 556         Type getReturnType(JCReturn ret) {
 557             if (ret.expr == null) {
 558                 return syms.voidType;
 559             } else {
 560                 return ret.expr.type;
 561             }
 562         }
 563 
 564         @Override
 565         ArgumentType<JCLambda> dup(JCLambda tree, Env<AttrContext> env) {
 566             return new ExplicitLambdaType(tree, env, speculativeTree, speculativeTypes);
 567         }
 568     }
 569 
 570     /**
 571      * Argument type for methods/constructors.
 572      */
 573     abstract class ResolvedMemberType<E extends JCExpression> extends ArgumentType<E> {
 574 
 575         public ResolvedMemberType(JCExpression tree, Env<AttrContext> env, E speculativeMethod, Map<ResultInfo, Type> speculativeTypes) {
 576             super(tree, env, speculativeMethod, speculativeTypes);
 577         }
 578 
 579         @Override
 580         Type overloadCheck(ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) {
 581             Type mtype = methodType();
 582             ResultInfo localInfo = resultInfo(resultInfo);
 583             Type t;
 584             if (mtype != null && mtype.hasTag(METHOD) && mtype.isPartial()) {
 585                 //poly invocation
 586                 t = ((PartiallyInferredMethodType)mtype).check(localInfo);
 587             } else {
 588                 //standalone invocation
 589                 t = localInfo.check(tree.pos(), speculativeTree.type);
 590             }
 591             speculativeTypes.put(localInfo, t);
 592             return t;
 593         }
 594 
 595         /**
 596          * Get the result info to be used for performing an overload check.
 597          */
 598         abstract ResultInfo resultInfo(ResultInfo resultInfo);
 599 
 600         /**
 601          * Get the method type to be used for performing an overload check.
 602          */
 603         abstract Type methodType();
 604     }
 605 
 606     /**
 607      * Argument type for methods.
 608      */
 609     class ResolvedMethodType extends ResolvedMemberType<JCMethodInvocation> {
 610 
 611         public ResolvedMethodType(JCExpression tree, Env<AttrContext> env, JCMethodInvocation speculativeTree) {
 612             this(tree, env, speculativeTree, new HashMap<>());
 613         }
 614 
 615         public ResolvedMethodType(JCExpression tree, Env<AttrContext> env, JCMethodInvocation speculativeTree, Map<ResultInfo, Type> speculativeTypes) {
 616             super(tree, env, speculativeTree, speculativeTypes);
 617         }
 618 
 619         @Override
 620         ResultInfo resultInfo(ResultInfo resultInfo) {
 621             return resultInfo;
 622         }
 623 
 624         @Override
 625         Type methodType() {
 626             return speculativeTree.meth.type;
 627         }
 628 
 629         @Override
 630         ArgumentType<JCMethodInvocation> dup(JCMethodInvocation tree, Env<AttrContext> env) {
 631             return new ResolvedMethodType(tree, env, speculativeTree, speculativeTypes);
 632         }
 633     }
 634 
 635     /**
 636      * Argument type for constructors.
 637      */
 638     class ResolvedConstructorType extends ResolvedMemberType<JCNewClass> {
 639 
 640         public ResolvedConstructorType(JCExpression tree, Env<AttrContext> env, JCNewClass speculativeTree) {
 641             this(tree, env, speculativeTree, new HashMap<>());
 642         }
 643 
 644         public ResolvedConstructorType(JCExpression tree, Env<AttrContext> env, JCNewClass speculativeTree, Map<ResultInfo, Type> speculativeTypes) {
 645             super(tree, env, speculativeTree, speculativeTypes);
 646         }
 647 
 648         @Override
 649         ResultInfo resultInfo(ResultInfo resultInfo) {
 650             return resultInfo.dup(attr.diamondContext(speculativeTree, speculativeTree.clazz.type.tsym, resultInfo.checkContext));
 651         }
 652 
 653         @Override
 654         Type methodType() {
 655             return (speculativeTree.constructorType != null) ?
 656                     speculativeTree.constructorType.baseType() : syms.errType;
 657         }
 658 
 659         @Override
 660         ArgumentType<JCNewClass> dup(JCNewClass tree, Env<AttrContext> env) {
 661             return new ResolvedConstructorType(tree, env, speculativeTree, speculativeTypes);
 662         }
 663     }
 664 
 665     /**
 666      * An instance of this class represents a unique position in a compilation unit. A unique
 667      * position is made up of (i) a unique position in a source file (char offset) and (ii)
 668      * a source file info.
 669      */
 670     class UniquePos {
 671 
 672         /** Char offset. */
 673         int pos;
 674 
 675         /** Source info. */
 676         DiagnosticSource source;
 677 
 678         UniquePos(JCTree tree) {
 679             this.pos = tree.pos;
 680             this.source = log.currentSource();
 681         }
 682 
 683         @Override
 684         public int hashCode() {
 685             return pos << 16 + source.hashCode();
 686         }
 687 
 688         @Override
 689         public boolean equals(Object obj) {
 690             if (obj instanceof UniquePos) {
 691                 UniquePos that = (UniquePos)obj;
 692                 return pos == that.pos && source == that.source;
 693             } else {
 694                 return false;
 695             }
 696         }
 697 
 698         @Override
 699         public String toString() {
 700             return source.getFile().getName() + " @ " + source.getLineNumber(pos);
 701         }
 702     }
 703 }