ArgumentAttr.java revision 4102:b873436b362b
1214501Srpaulo/* 2214501Srpaulo * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. 3252726Srpaulo * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4214501Srpaulo * 5252726Srpaulo * This code is free software; you can redistribute it and/or modify it 6252726Srpaulo * under the terms of the GNU General Public License version 2 only, as 7214501Srpaulo * published by the Free Software Foundation. Oracle designates this 8214501Srpaulo * particular file as subject to the "Classpath" exception as provided 9214501Srpaulo * by Oracle in the LICENSE file that accompanied this code. 10214501Srpaulo * 11214501Srpaulo * This code is distributed in the hope that it will be useful, but WITHOUT 12214501Srpaulo * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13214501Srpaulo * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14214501Srpaulo * version 2 for more details (a copy is included in the LICENSE file that 15214501Srpaulo * accompanied this code). 16214501Srpaulo * 17214501Srpaulo * You should have received a copy of the GNU General Public License version 18214501Srpaulo * 2 along with this work; if not, write to the Free Software Foundation, 19214501Srpaulo * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20214501Srpaulo * 21214501Srpaulo * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22214501Srpaulo * or visit www.oracle.com if you need additional information or have any 23214501Srpaulo * questions. 24214501Srpaulo */ 25214501Srpaulo 26214501Srpaulopackage com.sun.tools.javac.comp; 27214501Srpaulo 28214501Srpauloimport com.sun.source.tree.LambdaExpressionTree.BodyKind; 29214501Srpauloimport com.sun.tools.javac.code.Flags; 30214501Srpauloimport com.sun.tools.javac.code.Symbol; 31214501Srpauloimport com.sun.tools.javac.code.Symtab; 32214501Srpauloimport com.sun.tools.javac.code.Type; 33214501Srpauloimport com.sun.tools.javac.code.Types.FunctionDescriptorLookupError; 34214501Srpauloimport com.sun.tools.javac.comp.Attr.ResultInfo; 35214501Srpauloimport com.sun.tools.javac.comp.Attr.TargetInfo; 36214501Srpauloimport com.sun.tools.javac.comp.Check.CheckContext; 37214501Srpauloimport com.sun.tools.javac.comp.DeferredAttr.AttrMode; 38214501Srpauloimport com.sun.tools.javac.comp.DeferredAttr.DeferredAttrContext; 39214501Srpauloimport com.sun.tools.javac.comp.DeferredAttr.DeferredType; 40214501Srpauloimport com.sun.tools.javac.comp.DeferredAttr.DeferredTypeCompleter; 41214501Srpauloimport com.sun.tools.javac.comp.DeferredAttr.LambdaReturnScanner; 42214501Srpauloimport com.sun.tools.javac.comp.Infer.PartiallyInferredMethodType; 43214501Srpauloimport com.sun.tools.javac.comp.Resolve.MethodResolutionPhase; 44214501Srpauloimport com.sun.tools.javac.tree.JCTree; 45214501Srpauloimport com.sun.tools.javac.tree.JCTree.JCConditional; 46214501Srpauloimport com.sun.tools.javac.tree.JCTree.JCExpression; 47214501Srpauloimport com.sun.tools.javac.tree.JCTree.JCLambda; 48214501Srpauloimport com.sun.tools.javac.tree.JCTree.JCLambda.ParameterKind; 49214501Srpauloimport com.sun.tools.javac.tree.JCTree.JCMemberReference; 50214501Srpauloimport com.sun.tools.javac.tree.JCTree.JCMethodInvocation; 51214501Srpauloimport com.sun.tools.javac.tree.JCTree.JCNewClass; 52214501Srpauloimport com.sun.tools.javac.tree.JCTree.JCParens; 53214501Srpauloimport com.sun.tools.javac.tree.JCTree.JCReturn; 54214501Srpauloimport com.sun.tools.javac.tree.TreeCopier; 55214501Srpauloimport com.sun.tools.javac.tree.TreeInfo; 56214501Srpauloimport com.sun.tools.javac.util.Assert; 57214501Srpauloimport com.sun.tools.javac.util.Context; 58214501Srpauloimport com.sun.tools.javac.util.DiagnosticSource; 59214501Srpauloimport com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; 60214501Srpauloimport com.sun.tools.javac.util.List; 61214501Srpauloimport com.sun.tools.javac.util.ListBuffer; 62214501Srpauloimport com.sun.tools.javac.util.Log; 63214501Srpaulo 64214501Srpauloimport java.util.HashMap; 65214501Srpauloimport java.util.LinkedHashMap; 66214501Srpauloimport java.util.Map; 67214501Srpauloimport java.util.Optional; 68214501Srpauloimport java.util.function.Function; 69214501Srpauloimport java.util.function.Supplier; 70214501Srpaulo 71252726Srpauloimport static com.sun.tools.javac.code.TypeTag.ARRAY; 72252726Srpauloimport static com.sun.tools.javac.code.TypeTag.DEFERRED; 73214501Srpauloimport static com.sun.tools.javac.code.TypeTag.FORALL; 74214501Srpauloimport static com.sun.tools.javac.code.TypeTag.METHOD; 75214501Srpauloimport static com.sun.tools.javac.code.TypeTag.VOID; 76214501Srpaulo 77214501Srpaulo/** 78214501Srpaulo * This class performs attribution of method/constructor arguments when target-typing is enabled 79214501Srpaulo * (source >= 8); for each argument that is potentially a poly expression, this class builds 80214501Srpaulo * a rich representation (see {@link ArgumentType} which can then be used for performing fast overload 81214501Srpaulo * checks without requiring multiple attribution passes over the same code. 82214501Srpaulo * 83252726Srpaulo * The attribution strategy for a given method/constructor argument A is as follows: 84252726Srpaulo * 85252726Srpaulo * - if A is potentially a poly expression (i.e. diamond instance creation expression), a speculative 86252726Srpaulo * pass over A is performed; the results of such speculative attribution are then saved in a special 87252726Srpaulo * type, so that enclosing overload resolution can be carried by simply checking compatibility against the 88252726Srpaulo * type determined during this speculative pass. 89252726Srpaulo * 90252726Srpaulo * - if A is a standalone expression, regular atributtion takes place. 91252726Srpaulo * 92214501Srpaulo * To minimize the speculative work, a cache is used, so that already computed argument types 93214501Srpaulo * associated with a given unique source location are never recomputed multiple times. 94214501Srpaulo */ 95214501Srpaulopublic class ArgumentAttr extends JCTree.Visitor { 96214501Srpaulo 97252726Srpaulo protected static final Context.Key<ArgumentAttr> methodAttrKey = new Context.Key<>(); 98252726Srpaulo 99214501Srpaulo private final DeferredAttr deferredAttr; 100214501Srpaulo private final Attr attr; 101214501Srpaulo private final Symtab syms; 102214501Srpaulo private final Log log; 103214501Srpaulo 104214501Srpaulo /** Attribution environment to be used. */ 105214501Srpaulo private Env<AttrContext> env; 106214501Srpaulo 107252726Srpaulo /** Result of method attribution. */ 108214501Srpaulo Type result; 109252726Srpaulo 110252726Srpaulo /** Cache for argument types; behavior is influences by the currrently selected cache policy. */ 111252726Srpaulo Map<UniquePos, ArgumentType<?>> argumentTypeCache = new LinkedHashMap<>(); 112252726Srpaulo 113252726Srpaulo public static ArgumentAttr instance(Context context) { 114252726Srpaulo ArgumentAttr instance = context.get(methodAttrKey); 115252726Srpaulo if (instance == null) 116252726Srpaulo instance = new ArgumentAttr(context); 117252726Srpaulo return instance; 118252726Srpaulo } 119214501Srpaulo 120252726Srpaulo protected ArgumentAttr(Context context) { 121252726Srpaulo context.put(methodAttrKey, this); 122214501Srpaulo deferredAttr = DeferredAttr.instance(context); 123214501Srpaulo attr = Attr.instance(context); 124214501Srpaulo syms = Symtab.instance(context); 125214501Srpaulo log = Log.instance(context); 126214501Srpaulo } 127214501Srpaulo 128214501Srpaulo /** 129214501Srpaulo * Set the results of method attribution. 130214501Srpaulo */ 131214501Srpaulo void setResult(JCExpression tree, Type type) { 132214501Srpaulo result = type; 133214501Srpaulo if (env.info.isSpeculative) { 134214501Srpaulo //if we are in a speculative branch we can save the type in the tree itself 135214501Srpaulo //as there's no risk of polluting the original tree. 136214501Srpaulo tree.type = result; 137214501Srpaulo } 138214501Srpaulo } 139214501Srpaulo 140214501Srpaulo /** 141214501Srpaulo * Checks a type in the speculative tree against a given result; the type can be either a plain 142214501Srpaulo * type or an argument type,in which case a more complex check is required. 143214501Srpaulo */ 144214501Srpaulo Type checkSpeculative(JCExpression expr, ResultInfo resultInfo) { 145214501Srpaulo return checkSpeculative(expr, expr.type, resultInfo); 146214501Srpaulo } 147214501Srpaulo 148214501Srpaulo /** 149214501Srpaulo * Checks a type in the speculative tree against a given result; the type can be either a plain 150214501Srpaulo * type or an argument type,in which case a more complex check is required. 151214501Srpaulo */ 152214501Srpaulo Type checkSpeculative(DiagnosticPosition pos, Type t, ResultInfo resultInfo) { 153214501Srpaulo if (t.hasTag(DEFERRED)) { 154252726Srpaulo return ((DeferredType)t).check(resultInfo); 155252726Srpaulo } else { 156252726Srpaulo return resultInfo.check(pos, t); 157252726Srpaulo } 158252726Srpaulo } 159214501Srpaulo 160214501Srpaulo /** 161252726Srpaulo * Returns a local caching context in which argument types can safely be cached without 162252726Srpaulo * the risk of polluting enclosing contexts. This is useful when attempting speculative 163252726Srpaulo * attribution of potentially erroneous expressions, which could end up polluting the cache. 164214501Srpaulo */ 165214501Srpaulo LocalCacheContext withLocalCacheContext() { 166214501Srpaulo return new LocalCacheContext(); 167214501Srpaulo } 168214501Srpaulo 169214501Srpaulo /** 170214501Srpaulo * Local cache context; this class keeps track of the previous cache and reverts to it 171214501Srpaulo * when the {@link LocalCacheContext#leave()} method is called. 172214501Srpaulo */ 173214501Srpaulo class LocalCacheContext { 174214501Srpaulo Map<UniquePos, ArgumentType<?>> prevCache; 175214501Srpaulo 176214501Srpaulo public LocalCacheContext() { 177214501Srpaulo this.prevCache = argumentTypeCache; 178214501Srpaulo argumentTypeCache = new HashMap<>(); 179214501Srpaulo } 180214501Srpaulo 181214501Srpaulo public void leave() { 182214501Srpaulo argumentTypeCache = prevCache; 183214501Srpaulo } 184214501Srpaulo } 185214501Srpaulo 186214501Srpaulo /** 187214501Srpaulo * Main entry point for attributing an argument with given tree and attribution environment. 188214501Srpaulo */ 189214501Srpaulo Type attribArg(JCTree tree, Env<AttrContext> env) { 190214501Srpaulo Env<AttrContext> prevEnv = this.env; 191214501Srpaulo try { 192214501Srpaulo this.env = env; 193214501Srpaulo tree.accept(this); 194214501Srpaulo return result; 195214501Srpaulo } finally { 196214501Srpaulo this.env = prevEnv; 197214501Srpaulo } 198214501Srpaulo } 199214501Srpaulo 200214501Srpaulo @Override 201214501Srpaulo public void visitTree(JCTree that) { 202214501Srpaulo //delegates to Attr 203214501Srpaulo that.accept(attr); 204214501Srpaulo result = attr.result; 205214501Srpaulo } 206214501Srpaulo 207214501Srpaulo /** 208214501Srpaulo * Process a method argument; this method takes care of performing a speculative pass over the 209214501Srpaulo * argument tree and calling a well-defined entry point to build the argument type associated 210214501Srpaulo * with such tree. 211214501Srpaulo */ 212214501Srpaulo @SuppressWarnings("unchecked") 213214501Srpaulo <T extends JCExpression, Z extends ArgumentType<T>> void processArg(T that, Function<T, Z> argumentTypeFactory) { 214214501Srpaulo UniquePos pos = new UniquePos(that); 215214501Srpaulo processArg(that, () -> { 216214501Srpaulo T speculativeTree = (T)deferredAttr.attribSpeculative(that, env, attr.new MethodAttrInfo() { 217214501Srpaulo @Override 218214501Srpaulo protected boolean needsArgumentAttr(JCTree tree) { 219214501Srpaulo return !new UniquePos(tree).equals(pos); 220214501Srpaulo } 221214501Srpaulo }); 222214501Srpaulo return argumentTypeFactory.apply(speculativeTree); 223214501Srpaulo }); 224214501Srpaulo } 225214501Srpaulo 226214501Srpaulo /** 227214501Srpaulo * Process a method argument; this method allows the caller to specify a custom speculative attribution 228214501Srpaulo * logic (this is used e.g. for lambdas). 229214501Srpaulo */ 230214501Srpaulo @SuppressWarnings("unchecked") 231214501Srpaulo <T extends JCExpression, Z extends ArgumentType<T>> void processArg(T that, Supplier<Z> argumentTypeFactory) { 232214501Srpaulo UniquePos pos = new UniquePos(that); 233214501Srpaulo Z cached = (Z)argumentTypeCache.get(pos); 234214501Srpaulo if (cached != null) { 235214501Srpaulo //dup existing speculative type 236214501Srpaulo setResult(that, cached.dup(that, env)); 237214501Srpaulo } else { 238214501Srpaulo Z res = argumentTypeFactory.get(); 239214501Srpaulo argumentTypeCache.put(pos, res); 240214501Srpaulo setResult(that, res); 241214501Srpaulo } 242214501Srpaulo } 243214501Srpaulo 244214501Srpaulo @Override 245214501Srpaulo public void visitParens(JCParens that) { 246214501Srpaulo processArg(that, speculativeTree -> new ParensType(that, env, speculativeTree)); 247214501Srpaulo } 248214501Srpaulo 249214501Srpaulo @Override 250214501Srpaulo public void visitConditional(JCConditional that) { 251214501Srpaulo processArg(that, speculativeTree -> new ConditionalType(that, env, speculativeTree)); 252214501Srpaulo } 253214501Srpaulo 254214501Srpaulo @Override 255214501Srpaulo public void visitReference(JCMemberReference tree) { 256214501Srpaulo //perform arity-based check 257214501Srpaulo Env<AttrContext> localEnv = env.dup(tree); 258214501Srpaulo JCExpression exprTree; 259214501Srpaulo exprTree = (JCExpression)deferredAttr.attribSpeculative(tree.getQualifierExpression(), localEnv, 260214501Srpaulo attr.memberReferenceQualifierResult(tree), 261214501Srpaulo withLocalCacheContext()); 262214501Srpaulo JCMemberReference mref2 = new TreeCopier<Void>(attr.make).copy(tree); 263214501Srpaulo mref2.expr = exprTree; 264214501Srpaulo Symbol lhsSym = TreeInfo.symbol(exprTree); 265214501Srpaulo localEnv.info.selectSuper = lhsSym != null && lhsSym.name == lhsSym.name.table.names._super; 266214501Srpaulo Symbol res = 267214501Srpaulo attr.rs.getMemberReference(tree, localEnv, mref2, 268214501Srpaulo exprTree.type, tree.name); 269214501Srpaulo if (!res.kind.isResolutionError()) { 270214501Srpaulo tree.sym = res; 271214501Srpaulo } 272214501Srpaulo if (res.kind.isResolutionTargetError() || 273214501Srpaulo res.type != null && res.type.hasTag(FORALL) || 274214501Srpaulo (res.flags() & Flags.VARARGS) != 0 || 275214501Srpaulo (TreeInfo.isStaticSelector(exprTree, tree.name.table.names) && 276214501Srpaulo exprTree.type.isRaw() && !exprTree.type.hasTag(ARRAY))) { 277214501Srpaulo tree.setOverloadKind(JCMemberReference.OverloadKind.OVERLOADED); 278214501Srpaulo } else { 279214501Srpaulo tree.setOverloadKind(JCMemberReference.OverloadKind.UNOVERLOADED); 280214501Srpaulo } 281214501Srpaulo //return a plain old deferred type for this 282214501Srpaulo setResult(tree, deferredAttr.new DeferredType(tree, env)); 283214501Srpaulo } 284214501Srpaulo 285214501Srpaulo @Override 286214501Srpaulo public void visitLambda(JCLambda that) { 287214501Srpaulo if (that.paramKind == ParameterKind.EXPLICIT) { 288214501Srpaulo //if lambda is explicit, we can save info in the corresponding argument type 289214501Srpaulo processArg(that, () -> { 290214501Srpaulo JCLambda speculativeLambda = 291214501Srpaulo deferredAttr.attribSpeculativeLambda(that, env, attr.methodAttrInfo); 292214501Srpaulo return new ExplicitLambdaType(that, env, speculativeLambda); 293214501Srpaulo }); 294214501Srpaulo } else { 295214501Srpaulo //otherwise just use a deferred type 296214501Srpaulo setResult(that, deferredAttr.new DeferredType(that, env)); 297214501Srpaulo } 298214501Srpaulo } 299214501Srpaulo 300214501Srpaulo @Override 301214501Srpaulo public void visitApply(JCMethodInvocation that) { 302214501Srpaulo if (that.getTypeArguments().isEmpty()) { 303214501Srpaulo processArg(that, speculativeTree -> new ResolvedMethodType(that, env, speculativeTree)); 304214501Srpaulo } else { 305214501Srpaulo //not a poly expression, just call Attr 306214501Srpaulo setResult(that, attr.attribTree(that, env, attr.unknownExprInfo)); 307214501Srpaulo } 308214501Srpaulo } 309214501Srpaulo 310214501Srpaulo @Override 311214501Srpaulo public void visitNewClass(JCNewClass that) { 312214501Srpaulo if (TreeInfo.isDiamond(that)) { 313214501Srpaulo processArg(that, speculativeTree -> new ResolvedConstructorType(that, env, speculativeTree)); 314214501Srpaulo } else { 315214501Srpaulo //not a poly expression, just call Attr 316214501Srpaulo setResult(that, attr.attribTree(that, env, attr.unknownExprInfo)); 317214501Srpaulo } 318214501Srpaulo } 319214501Srpaulo 320214501Srpaulo /** 321214501Srpaulo * An argument type is similar to a plain deferred type; the most important difference is that 322214501Srpaulo * the completion logic associated with argument types allows speculative attribution to be skipped 323214501Srpaulo * during overload resolution - that is, an argument type always has enough information to 324214501Srpaulo * perform an overload check without the need of calling back to Attr. This extra information 325214501Srpaulo * is typically stored in the form of a speculative tree. 326214501Srpaulo */ 327214501Srpaulo abstract class ArgumentType<T extends JCExpression> extends DeferredType implements DeferredTypeCompleter { 328214501Srpaulo 329214501Srpaulo /** The speculative tree carrying type information. */ 330214501Srpaulo T speculativeTree; 331214501Srpaulo 332214501Srpaulo /** Types associated with this argument (one type per possible target result). */ 333214501Srpaulo Map<ResultInfo, Type> speculativeTypes; 334214501Srpaulo 335214501Srpaulo public ArgumentType(JCExpression tree, Env<AttrContext> env, T speculativeTree, Map<ResultInfo, Type> speculativeTypes) { 336214501Srpaulo deferredAttr.super(tree, env); 337214501Srpaulo this.speculativeTree = speculativeTree; 338214501Srpaulo this.speculativeTypes = speculativeTypes; 339214501Srpaulo } 340214501Srpaulo 341214501Srpaulo @Override 342214501Srpaulo final DeferredTypeCompleter completer() { 343214501Srpaulo return this; 344252726Srpaulo } 345252726Srpaulo 346252726Srpaulo @Override 347252726Srpaulo final public Type complete(DeferredType dt, ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) { 348252726Srpaulo Assert.check(dt == this); 349252726Srpaulo if (deferredAttrContext.mode == AttrMode.SPECULATIVE) { 350252726Srpaulo Type t = (resultInfo.pt == Type.recoveryType) ? 351252726Srpaulo deferredAttr.basicCompleter.complete(dt, resultInfo, deferredAttrContext) : 352252726Srpaulo overloadCheck(resultInfo, deferredAttrContext); 353252726Srpaulo speculativeTypes.put(resultInfo, t); 354252726Srpaulo return t; 355252726Srpaulo } else { 356252726Srpaulo if (!env.info.isSpeculative) { 357252726Srpaulo argumentTypeCache.remove(new UniquePos(dt.tree)); 358252726Srpaulo } 359252726Srpaulo return deferredAttr.basicCompleter.complete(dt, resultInfo, deferredAttrContext); 360252726Srpaulo } 361252726Srpaulo } 362252726Srpaulo 363252726Srpaulo @Override 364252726Srpaulo Type speculativeType(Symbol msym, MethodResolutionPhase phase) { 365252726Srpaulo if (pertinentToApplicability) { 366252726Srpaulo for (Map.Entry<ResultInfo, Type> _entry : speculativeTypes.entrySet()) { 367252726Srpaulo DeferredAttrContext deferredAttrContext = _entry.getKey().checkContext.deferredAttrContext(); 368214501Srpaulo if (deferredAttrContext.phase == phase && deferredAttrContext.msym == msym) { 369214501Srpaulo return _entry.getValue(); 370214501Srpaulo } 371214501Srpaulo } 372214501Srpaulo return Type.noType; 373214501Srpaulo } else { 374214501Srpaulo return super.speculativeType(msym, phase); 375214501Srpaulo } 376214501Srpaulo } 377214501Srpaulo 378214501Srpaulo @Override 379214501Srpaulo JCTree speculativeTree(DeferredAttrContext deferredAttrContext) { 380214501Srpaulo return pertinentToApplicability ? speculativeTree : super.speculativeTree(deferredAttrContext); 381214501Srpaulo } 382214501Srpaulo 383214501Srpaulo /** 384214501Srpaulo * Performs an overload check against a given target result. 385214501Srpaulo */ 386214501Srpaulo abstract Type overloadCheck(ResultInfo resultInfo, DeferredAttrContext deferredAttrContext); 387214501Srpaulo 388214501Srpaulo /** 389214501Srpaulo * Creates a copy of this argument type with given tree and environment. 390214501Srpaulo */ 391214501Srpaulo abstract ArgumentType<T> dup(T tree, Env<AttrContext> env); 392214501Srpaulo } 393214501Srpaulo 394214501Srpaulo /** 395214501Srpaulo * Argument type for parenthesized expression. 396214501Srpaulo */ 397214501Srpaulo class ParensType extends ArgumentType<JCParens> { 398214501Srpaulo ParensType(JCExpression tree, Env<AttrContext> env, JCParens speculativeParens) { 399214501Srpaulo this(tree, env, speculativeParens, new HashMap<>()); 400214501Srpaulo } 401214501Srpaulo 402214501Srpaulo ParensType(JCExpression tree, Env<AttrContext> env, JCParens speculativeParens, Map<ResultInfo, Type> speculativeTypes) { 403214501Srpaulo super(tree, env, speculativeParens, speculativeTypes); 404214501Srpaulo } 405214501Srpaulo 406214501Srpaulo @Override 407214501Srpaulo Type overloadCheck(ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) { 408214501Srpaulo return checkSpeculative(speculativeTree.expr, resultInfo); 409214501Srpaulo } 410214501Srpaulo 411214501Srpaulo @Override 412214501Srpaulo ArgumentType<JCParens> dup(JCParens tree, Env<AttrContext> env) { 413214501Srpaulo return new ParensType(tree, env, speculativeTree, speculativeTypes); 414252726Srpaulo } 415214501Srpaulo } 416214501Srpaulo 417214501Srpaulo /** 418214501Srpaulo * Argument type for conditionals. 419214501Srpaulo */ 420214501Srpaulo class ConditionalType extends ArgumentType<JCConditional> { 421214501Srpaulo ConditionalType(JCExpression tree, Env<AttrContext> env, JCConditional speculativeCond) { 422214501Srpaulo this(tree, env, speculativeCond, new HashMap<>()); 423214501Srpaulo } 424214501Srpaulo 425252726Srpaulo ConditionalType(JCExpression tree, Env<AttrContext> env, JCConditional speculativeCond, Map<ResultInfo, Type> speculativeTypes) { 426252726Srpaulo super(tree, env, speculativeCond, speculativeTypes); 427214501Srpaulo } 428214501Srpaulo 429214501Srpaulo @Override 430214501Srpaulo Type overloadCheck(ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) { 431214501Srpaulo ResultInfo localInfo = resultInfo.dup(attr.conditionalContext(resultInfo.checkContext)); 432214501Srpaulo if (speculativeTree.isStandalone()) { 433214501Srpaulo return localInfo.check(speculativeTree, speculativeTree.type); 434214501Srpaulo } else if (resultInfo.pt.hasTag(VOID)) { 435214501Srpaulo //this means we are returning a poly conditional from void-compatible lambda expression 436214501Srpaulo resultInfo.checkContext.report(tree, attr.diags.fragment("conditional.target.cant.be.void")); 437214501Srpaulo return attr.types.createErrorType(resultInfo.pt); 438214501Srpaulo } else { 439214501Srpaulo //poly 440214501Srpaulo checkSpeculative(speculativeTree.truepart, localInfo); 441252726Srpaulo checkSpeculative(speculativeTree.falsepart, localInfo); 442214501Srpaulo return localInfo.pt; 443214501Srpaulo } 444214501Srpaulo } 445214501Srpaulo 446214501Srpaulo @Override 447214501Srpaulo ArgumentType<JCConditional> dup(JCConditional tree, Env<AttrContext> env) { 448214501Srpaulo return new ConditionalType(tree, env, speculativeTree, speculativeTypes); 449214501Srpaulo } 450214501Srpaulo } 451214501Srpaulo 452214501Srpaulo /** 453214501Srpaulo * Argument type for explicit lambdas. 454214501Srpaulo */ 455214501Srpaulo class ExplicitLambdaType extends ArgumentType<JCLambda> { 456252726Srpaulo 457252726Srpaulo /** List of argument types (lazily populated). */ 458214501Srpaulo Optional<List<Type>> argtypes = Optional.empty(); 459214501Srpaulo 460214501Srpaulo /** List of return expressions (lazily populated). */ 461214501Srpaulo Optional<List<JCReturn>> returnExpressions = Optional.empty(); 462214501Srpaulo 463214501Srpaulo ExplicitLambdaType(JCLambda originalLambda, Env<AttrContext> env, JCLambda speculativeLambda) { 464214501Srpaulo this(originalLambda, env, speculativeLambda, new HashMap<>()); 465214501Srpaulo } 466214501Srpaulo 467214501Srpaulo ExplicitLambdaType(JCLambda originalLambda, Env<AttrContext> env, JCLambda speculativeLambda, Map<ResultInfo, Type> speculativeTypes) { 468214501Srpaulo super(originalLambda, env, speculativeLambda, speculativeTypes); 469214501Srpaulo } 470214501Srpaulo 471214501Srpaulo /** Compute argument types (if needed). */ 472214501Srpaulo List<Type> argtypes() { 473214501Srpaulo return argtypes.orElseGet(() -> { 474214501Srpaulo List<Type> res = TreeInfo.types(speculativeTree.params); 475214501Srpaulo argtypes = Optional.of(res); 476214501Srpaulo return res; 477214501Srpaulo }); 478214501Srpaulo } 479214501Srpaulo 480214501Srpaulo /** Compute return expressions (if needed). */ 481214501Srpaulo List<JCReturn> returnExpressions() { 482214501Srpaulo return returnExpressions.orElseGet(() -> { 483214501Srpaulo final List<JCReturn> res; 484214501Srpaulo if (speculativeTree.getBodyKind() == BodyKind.EXPRESSION) { 485214501Srpaulo res = List.of(attr.make.Return((JCExpression)speculativeTree.body)); 486214501Srpaulo } else { 487214501Srpaulo ListBuffer<JCReturn> returnExpressions = new ListBuffer<>(); 488214501Srpaulo new LambdaReturnScanner() { 489214501Srpaulo @Override 490214501Srpaulo public void visitReturn(JCReturn tree) { 491214501Srpaulo returnExpressions.add(tree); 492214501Srpaulo } 493214501Srpaulo }.scan(speculativeTree.body); 494214501Srpaulo res = returnExpressions.toList(); 495214501Srpaulo } 496214501Srpaulo returnExpressions = Optional.of(res); 497214501Srpaulo return res; 498252726Srpaulo }); 499252726Srpaulo } 500252726Srpaulo 501214501Srpaulo @Override 502252726Srpaulo Type overloadCheck(ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) { 503252726Srpaulo try { 504252726Srpaulo //compute target-type; this logic could be shared with Attr 505252726Srpaulo TargetInfo targetInfo = attr.getTargetInfo(speculativeTree, resultInfo, argtypes()); 506252726Srpaulo Type lambdaType = targetInfo.descriptor; 507252726Srpaulo Type currentTarget = targetInfo.target; 508252726Srpaulo //check compatibility 509252726Srpaulo checkLambdaCompatible(lambdaType, resultInfo); 510252726Srpaulo return currentTarget; 511252726Srpaulo } catch (FunctionDescriptorLookupError ex) { 512252726Srpaulo resultInfo.checkContext.report(null, ex.getDiagnostic()); 513252726Srpaulo return null; //cannot get here 514252726Srpaulo } 515252726Srpaulo } 516252726Srpaulo 517252726Srpaulo /** Check lambda against given target result */ 518252726Srpaulo private void checkLambdaCompatible(Type descriptor, ResultInfo resultInfo) { 519252726Srpaulo CheckContext checkContext = resultInfo.checkContext; 520252726Srpaulo ResultInfo bodyResultInfo = attr.lambdaBodyResult(speculativeTree, descriptor, resultInfo); 521252726Srpaulo for (JCReturn ret : returnExpressions()) { 522214501Srpaulo Type t = getReturnType(ret); 523214501Srpaulo if (speculativeTree.getBodyKind() == BodyKind.EXPRESSION || !t.hasTag(VOID)) { 524214501Srpaulo checkSpeculative(ret.expr, t, bodyResultInfo); 525214501Srpaulo } 526214501Srpaulo } 527214501Srpaulo 528214501Srpaulo attr.checkLambdaCompatible(speculativeTree, descriptor, checkContext); 529214501Srpaulo } 530214501Srpaulo 531214501Srpaulo /** Get the type associated with given return expression. */ 532214501Srpaulo Type getReturnType(JCReturn ret) { 533214501Srpaulo if (ret.expr == null) { 534214501Srpaulo return syms.voidType; 535214501Srpaulo } else { 536214501Srpaulo return ret.expr.type; 537214501Srpaulo } 538214501Srpaulo } 539214501Srpaulo 540214501Srpaulo @Override 541214501Srpaulo ArgumentType<JCLambda> dup(JCLambda tree, Env<AttrContext> env) { 542214501Srpaulo return new ExplicitLambdaType(tree, env, speculativeTree, speculativeTypes); 543214501Srpaulo } 544214501Srpaulo } 545214501Srpaulo 546214501Srpaulo /** 547214501Srpaulo * Argument type for methods/constructors. 548214501Srpaulo */ 549214501Srpaulo abstract class ResolvedMemberType<E extends JCExpression> extends ArgumentType<E> { 550214501Srpaulo 551214501Srpaulo public ResolvedMemberType(JCExpression tree, Env<AttrContext> env, E speculativeMethod, Map<ResultInfo, Type> speculativeTypes) { 552214501Srpaulo super(tree, env, speculativeMethod, speculativeTypes); 553214501Srpaulo } 554214501Srpaulo 555214501Srpaulo @Override 556214501Srpaulo Type overloadCheck(ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) { 557214501Srpaulo Type mtype = methodType(); 558214501Srpaulo ResultInfo localInfo = resultInfo(resultInfo); 559214501Srpaulo if (mtype != null && mtype.hasTag(METHOD) && mtype.isPartial()) { 560214501Srpaulo Type t = ((PartiallyInferredMethodType)mtype).check(localInfo); 561214501Srpaulo if (!deferredAttrContext.inferenceContext.free(localInfo.pt)) { 562214501Srpaulo speculativeTypes.put(localInfo, t); 563214501Srpaulo return localInfo.check(tree.pos(), t); 564214501Srpaulo } else { 565214501Srpaulo return t; 566214501Srpaulo } 567214501Srpaulo } else { 568214501Srpaulo Type t = localInfo.check(tree.pos(), speculativeTree.type); 569214501Srpaulo speculativeTypes.put(localInfo, t); 570214501Srpaulo return t; 571214501Srpaulo } 572214501Srpaulo } 573214501Srpaulo 574214501Srpaulo /** 575214501Srpaulo * Get the result info to be used for performing an overload check. 576214501Srpaulo */ 577214501Srpaulo abstract ResultInfo resultInfo(ResultInfo resultInfo); 578214501Srpaulo 579214501Srpaulo /** 580214501Srpaulo * Get the method type to be used for performing an overload check. 581214501Srpaulo */ 582214501Srpaulo abstract Type methodType(); 583214501Srpaulo } 584214501Srpaulo 585214501Srpaulo /** 586214501Srpaulo * Argument type for methods. 587214501Srpaulo */ 588214501Srpaulo class ResolvedMethodType extends ResolvedMemberType<JCMethodInvocation> { 589214501Srpaulo 590214501Srpaulo public ResolvedMethodType(JCExpression tree, Env<AttrContext> env, JCMethodInvocation speculativeTree) { 591214501Srpaulo this(tree, env, speculativeTree, new HashMap<>()); 592214501Srpaulo } 593214501Srpaulo 594214501Srpaulo public ResolvedMethodType(JCExpression tree, Env<AttrContext> env, JCMethodInvocation speculativeTree, Map<ResultInfo, Type> speculativeTypes) { 595214501Srpaulo super(tree, env, speculativeTree, speculativeTypes); 596214501Srpaulo } 597214501Srpaulo 598214501Srpaulo @Override 599214501Srpaulo ResultInfo resultInfo(ResultInfo resultInfo) { 600214501Srpaulo return resultInfo; 601214501Srpaulo } 602214501Srpaulo 603214501Srpaulo @Override 604214501Srpaulo Type methodType() { 605214501Srpaulo return speculativeTree.meth.type; 606214501Srpaulo } 607214501Srpaulo 608214501Srpaulo @Override 609214501Srpaulo ArgumentType<JCMethodInvocation> dup(JCMethodInvocation tree, Env<AttrContext> env) { 610214501Srpaulo return new ResolvedMethodType(tree, env, speculativeTree, speculativeTypes); 611214501Srpaulo } 612214501Srpaulo } 613214501Srpaulo 614214501Srpaulo /** 615214501Srpaulo * Argument type for constructors. 616214501Srpaulo */ 617214501Srpaulo class ResolvedConstructorType extends ResolvedMemberType<JCNewClass> { 618214501Srpaulo 619214501Srpaulo public ResolvedConstructorType(JCExpression tree, Env<AttrContext> env, JCNewClass speculativeTree) { 620214501Srpaulo this(tree, env, speculativeTree, new HashMap<>()); 621214501Srpaulo } 622214501Srpaulo 623214501Srpaulo public ResolvedConstructorType(JCExpression tree, Env<AttrContext> env, JCNewClass speculativeTree, Map<ResultInfo, Type> speculativeTypes) { 624214501Srpaulo super(tree, env, speculativeTree, speculativeTypes); 625214501Srpaulo } 626 627 @Override 628 ResultInfo resultInfo(ResultInfo resultInfo) { 629 return resultInfo.dup(attr.diamondContext(speculativeTree, speculativeTree.clazz.type.tsym, resultInfo.checkContext)); 630 } 631 632 @Override 633 Type methodType() { 634 return (speculativeTree.constructorType != null) ? 635 speculativeTree.constructorType.baseType() : syms.errType; 636 } 637 638 @Override 639 ArgumentType<JCNewClass> dup(JCNewClass tree, Env<AttrContext> env) { 640 return new ResolvedConstructorType(tree, env, speculativeTree, speculativeTypes); 641 } 642 } 643 644 /** 645 * An instance of this class represents a unique position in a compilation unit. A unique 646 * position is made up of (i) a unique position in a source file (char offset) and (ii) 647 * a source file info. 648 */ 649 class UniquePos { 650 651 /** Char offset. */ 652 int pos; 653 654 /** Source info. */ 655 DiagnosticSource source; 656 657 UniquePos(JCTree tree) { 658 this.pos = tree.pos; 659 this.source = log.currentSource(); 660 } 661 662 @Override 663 public int hashCode() { 664 return pos << 16 + source.hashCode(); 665 } 666 667 @Override 668 public boolean equals(Object obj) { 669 if (obj instanceof UniquePos) { 670 UniquePos that = (UniquePos)obj; 671 return pos == that.pos && source == that.source; 672 } else { 673 return false; 674 } 675 } 676 677 @Override 678 public String toString() { 679 return source.getFile().getName() + " @ " + source.getLineNumber(pos); 680 } 681 } 682} 683