ArgumentAttr.java revision 3031:286fc9270404
1/* 2 * Copyright (c) 2015, 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 26package com.sun.tools.javac.comp; 27 28import com.sun.source.tree.LambdaExpressionTree.BodyKind; 29import com.sun.tools.javac.code.Flags; 30import com.sun.tools.javac.code.Symbol; 31import com.sun.tools.javac.code.Symtab; 32import com.sun.tools.javac.code.Type; 33import com.sun.tools.javac.code.Types.FunctionDescriptorLookupError; 34import com.sun.tools.javac.comp.Attr.ResultInfo; 35import com.sun.tools.javac.comp.Attr.TargetInfo; 36import com.sun.tools.javac.comp.Check.CheckContext; 37import com.sun.tools.javac.comp.DeferredAttr.AttrMode; 38import com.sun.tools.javac.comp.DeferredAttr.DeferredAttrContext; 39import com.sun.tools.javac.comp.DeferredAttr.DeferredType; 40import com.sun.tools.javac.comp.DeferredAttr.DeferredTypeCompleter; 41import com.sun.tools.javac.comp.DeferredAttr.LambdaReturnScanner; 42import com.sun.tools.javac.comp.Infer.PartiallyInferredMethodType; 43import com.sun.tools.javac.comp.Resolve.MethodResolutionPhase; 44import com.sun.tools.javac.tree.JCTree; 45import com.sun.tools.javac.tree.JCTree.JCConditional; 46import com.sun.tools.javac.tree.JCTree.JCExpression; 47import com.sun.tools.javac.tree.JCTree.JCLambda; 48import com.sun.tools.javac.tree.JCTree.JCLambda.ParameterKind; 49import com.sun.tools.javac.tree.JCTree.JCMemberReference; 50import com.sun.tools.javac.tree.JCTree.JCMethodInvocation; 51import com.sun.tools.javac.tree.JCTree.JCNewClass; 52import com.sun.tools.javac.tree.JCTree.JCParens; 53import com.sun.tools.javac.tree.JCTree.JCReturn; 54import com.sun.tools.javac.tree.TreeCopier; 55import com.sun.tools.javac.tree.TreeInfo; 56import com.sun.tools.javac.util.Assert; 57import com.sun.tools.javac.util.Context; 58import com.sun.tools.javac.util.DiagnosticSource; 59import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; 60import com.sun.tools.javac.util.List; 61import com.sun.tools.javac.util.ListBuffer; 62import com.sun.tools.javac.util.Log; 63 64import java.util.HashMap; 65import java.util.LinkedHashMap; 66import java.util.Map; 67import java.util.Optional; 68import java.util.function.Function; 69import java.util.function.Supplier; 70 71import static com.sun.tools.javac.code.TypeTag.DEFERRED; 72import static com.sun.tools.javac.code.TypeTag.FORALL; 73import static com.sun.tools.javac.code.TypeTag.METHOD; 74import static com.sun.tools.javac.code.TypeTag.VOID; 75 76/** 77 * This class performs attribution of method/constructor arguments when target-typing is enabled 78 * (source >= 8); for each argument that is potentially a poly expression, this class builds 79 * a rich representation (see {@link ArgumentType} which can then be used for performing fast overload 80 * checks without requiring multiple attribution passes over the same code. 81 * 82 * The attribution strategy for a given method/constructor argument A is as follows: 83 * 84 * - if A is potentially a poly expression (i.e. diamond instance creation expression), a speculative 85 * pass over A is performed; the results of such speculative attribution are then saved in a special 86 * type, so that enclosing overload resolution can be carried by simply checking compatibility against the 87 * type determined during this speculative pass. 88 * 89 * - if A is a standalone expression, regular atributtion takes place. 90 * 91 * To minimize the speculative work, a cache is used, so that already computed argument types 92 * associated with a given unique source location are never recomputed multiple times. 93 */ 94public class ArgumentAttr extends JCTree.Visitor { 95 96 protected static final Context.Key<ArgumentAttr> methodAttrKey = new Context.Key<>(); 97 98 private final DeferredAttr deferredAttr; 99 private final Attr attr; 100 private final Symtab syms; 101 private final Log log; 102 103 /** Attribution environment to be used. */ 104 private Env<AttrContext> env; 105 106 /** Result of method attribution. */ 107 private Type result; 108 109 /** Cache for argument types; behavior is influences by the currrently selected cache policy. */ 110 Map<UniquePos, ArgumentType<?>> argumentTypeCache = new LinkedHashMap<>(); 111 112 /** Cache policy: should argument types be cached? */ 113 private CachePolicy cachePolicy = CachePolicy.CACHE; 114 115 public static ArgumentAttr instance(Context context) { 116 ArgumentAttr instance = context.get(methodAttrKey); 117 if (instance == null) 118 instance = new ArgumentAttr(context); 119 return instance; 120 } 121 122 protected ArgumentAttr(Context context) { 123 context.put(methodAttrKey, this); 124 deferredAttr = DeferredAttr.instance(context); 125 attr = Attr.instance(context); 126 syms = Symtab.instance(context); 127 log = Log.instance(context); 128 } 129 130 /** 131 * Set the results of method attribution. 132 */ 133 void setResult(JCExpression tree, Type type) { 134 result = type; 135 if (env.info.isSpeculative) { 136 //if we are in a speculative branch we can save the type in the tree itself 137 //as there's no risk of polluting the original tree. 138 tree.type = result; 139 } 140 } 141 142 /** 143 * Checks a type in the speculative tree against a given result; the type can be either a plain 144 * type or an argument type,in which case a more complex check is required. 145 */ 146 Type checkSpeculative(JCExpression expr, ResultInfo resultInfo) { 147 return checkSpeculative(expr, expr.type, resultInfo); 148 } 149 150 /** 151 * Checks a type in the speculative tree against a given result; the type can be either a plain 152 * type or an argument type,in which case a more complex check is required. 153 */ 154 Type checkSpeculative(DiagnosticPosition pos, Type t, ResultInfo resultInfo) { 155 if (t.hasTag(DEFERRED)) { 156 return ((DeferredType)t).check(resultInfo); 157 } else { 158 return resultInfo.check(pos, t); 159 } 160 } 161 162 /** 163 * Sets given ache policy and returns current policy. 164 */ 165 CachePolicy withCachePolicy(CachePolicy newPolicy) { 166 CachePolicy oldPolicy = this.cachePolicy; 167 this.cachePolicy = newPolicy; 168 return oldPolicy; 169 } 170 171 /** 172 * Main entry point for attributing an argument with given tree and attribution environment. 173 */ 174 Type attribArg(JCTree tree, Env<AttrContext> env) { 175 Env<AttrContext> prevEnv = this.env; 176 try { 177 this.env = env; 178 tree.accept(this); 179 return result; 180 } finally { 181 this.env = prevEnv; 182 } 183 } 184 185 @Override 186 public void visitTree(JCTree that) { 187 //delegates to Attr 188 that.accept(attr); 189 result = attr.result; 190 } 191 192 /** 193 * Process a method argument; this method takes care of performing a speculative pass over the 194 * argument tree and calling a well-defined entry point to build the argument type associated 195 * with such tree. 196 */ 197 @SuppressWarnings("unchecked") 198 <T extends JCExpression, Z extends ArgumentType<T>> void processArg(T that, Function<T, Z> argumentTypeFactory) { 199 UniquePos pos = new UniquePos(that); 200 processArg(that, () -> { 201 T speculativeTree = (T)deferredAttr.attribSpeculative(that, env, attr.new MethodAttrInfo() { 202 @Override 203 protected void attr(JCTree tree, Env<AttrContext> env) { 204 //avoid speculative attribution loops 205 if (!new UniquePos(tree).equals(pos)) { 206 super.attr(tree, env); 207 } else { 208 visitTree(tree); 209 } 210 } 211 }); 212 return argumentTypeFactory.apply(speculativeTree); 213 }); 214 } 215 216 /** 217 * Process a method argument; this method allows the caller to specify a custom speculative attribution 218 * logic (this is used e.g. for lambdas). 219 */ 220 @SuppressWarnings("unchecked") 221 <T extends JCExpression, Z extends ArgumentType<T>> void processArg(T that, Supplier<Z> argumentTypeFactory) { 222 UniquePos pos = new UniquePos(that); 223 Z cached = (Z)argumentTypeCache.get(pos); 224 if (cached != null) { 225 //dup existing speculative type 226 setResult(that, cached.dup(that, env)); 227 } else { 228 Z res = argumentTypeFactory.get(); 229 if (cachePolicy == CachePolicy.CACHE) { 230 argumentTypeCache.put(pos, res); 231 } 232 setResult(that, res); 233 } 234 } 235 236 @Override 237 public void visitParens(JCParens that) { 238 processArg(that, speculativeTree -> new ParensType(that, env, speculativeTree)); 239 } 240 241 @Override 242 public void visitConditional(JCConditional that) { 243 processArg(that, speculativeTree -> new ConditionalType(that, env, speculativeTree)); 244 } 245 246 @Override 247 public void visitReference(JCMemberReference tree) { 248 //perform arity-based check 249 Env<AttrContext> localEnv = env.dup(tree); 250 JCExpression exprTree = (JCExpression)deferredAttr.attribSpeculative(tree.getQualifierExpression(), localEnv, 251 attr.memberReferenceQualifierResult(tree)); 252 JCMemberReference mref2 = new TreeCopier<Void>(attr.make).copy(tree); 253 mref2.expr = exprTree; 254 Symbol res = 255 attr.rs.getMemberReference(tree, localEnv, mref2, 256 exprTree.type, tree.name); 257 if (!res.kind.isResolutionError()) { 258 tree.sym = res; 259 } 260 if (res.kind.isResolutionTargetError() || 261 res.type != null && res.type.hasTag(FORALL) || 262 (res.flags() & Flags.VARARGS) != 0 || 263 (TreeInfo.isStaticSelector(exprTree, tree.name.table.names) && 264 exprTree.type.isRaw())) { 265 tree.overloadKind = JCMemberReference.OverloadKind.OVERLOADED; 266 } else { 267 tree.overloadKind = JCMemberReference.OverloadKind.UNOVERLOADED; 268 } 269 //return a plain old deferred type for this 270 setResult(tree, deferredAttr.new DeferredType(tree, env)); 271 } 272 273 @Override 274 public void visitLambda(JCLambda that) { 275 if (that.paramKind == ParameterKind.EXPLICIT) { 276 //if lambda is explicit, we can save info in the corresponding argument type 277 processArg(that, () -> { 278 JCLambda speculativeLambda = 279 deferredAttr.attribSpeculativeLambda(that, env, attr.methodAttrInfo); 280 return new ExplicitLambdaType(that, env, speculativeLambda); 281 }); 282 } else { 283 //otherwise just use a deferred type 284 setResult(that, deferredAttr.new DeferredType(that, env)); 285 } 286 } 287 288 @Override 289 public void visitApply(JCMethodInvocation that) { 290 if (that.getTypeArguments().isEmpty()) { 291 processArg(that, speculativeTree -> new ResolvedMethodType(that, env, speculativeTree)); 292 } else { 293 //not a poly expression, just call Attr 294 setResult(that, attr.attribTree(that, env, attr.unknownExprInfo)); 295 } 296 } 297 298 @Override 299 public void visitNewClass(JCNewClass that) { 300 if (TreeInfo.isDiamond(that)) { 301 processArg(that, speculativeTree -> new ResolvedConstructorType(that, env, speculativeTree)); 302 } else { 303 //not a poly expression, just call Attr 304 setResult(that, attr.attribTree(that, env, attr.unknownExprInfo)); 305 } 306 } 307 308 /** 309 * An argument type is similar to a plain deferred type; the most important difference is that 310 * the completion logic associated with argument types allows speculative attribution to be skipped 311 * during overload resolution - that is, an argument type always has enough information to 312 * perform an overload check without the need of calling back to Attr. This extra information 313 * is typically stored in the form of a speculative tree. 314 */ 315 abstract class ArgumentType<T extends JCExpression> extends DeferredType implements DeferredTypeCompleter { 316 317 /** The speculative tree carrying type information. */ 318 T speculativeTree; 319 320 /** Types associated with this argument (one type per possible target result). */ 321 Map<ResultInfo, Type> speculativeTypes; 322 323 public ArgumentType(JCExpression tree, Env<AttrContext> env, T speculativeTree, Map<ResultInfo, Type> speculativeTypes) { 324 deferredAttr.super(tree, env); 325 this.speculativeTree = speculativeTree; 326 this.speculativeTypes = speculativeTypes; 327 } 328 329 @Override 330 final DeferredTypeCompleter completer() { 331 return this; 332 } 333 334 @Override 335 final public Type complete(DeferredType dt, ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) { 336 Assert.check(dt == this); 337 if (deferredAttrContext.mode == AttrMode.SPECULATIVE) { 338 Type t = (resultInfo.pt == Type.recoveryType) ? 339 deferredAttr.basicCompleter.complete(dt, resultInfo, deferredAttrContext) : 340 overloadCheck(resultInfo, deferredAttrContext); 341 speculativeTypes.put(resultInfo, t); 342 return t; 343 } else { 344 if (!env.info.isSpeculative && cachePolicy == CachePolicy.CACHE) { 345 argumentTypeCache.remove(new UniquePos(dt.tree)); 346 } 347 return deferredAttr.basicCompleter.complete(dt, resultInfo, deferredAttrContext); 348 } 349 } 350 351 @Override 352 Type speculativeType(Symbol msym, MethodResolutionPhase phase) { 353 for (Map.Entry<ResultInfo, Type> _entry : speculativeTypes.entrySet()) { 354 DeferredAttrContext deferredAttrContext = _entry.getKey().checkContext.deferredAttrContext(); 355 if (deferredAttrContext.phase == phase && deferredAttrContext.msym == msym) { 356 return _entry.getValue(); 357 } 358 } 359 return Type.noType; 360 } 361 362 @Override 363 JCTree speculativeTree(DeferredAttrContext deferredAttrContext) { 364 return speculativeTree; 365 } 366 367 /** 368 * Performs an overload check against a given target result. 369 */ 370 abstract Type overloadCheck(ResultInfo resultInfo, DeferredAttrContext deferredAttrContext); 371 372 /** 373 * Creates a copy of this argument type with given tree and environment. 374 */ 375 abstract ArgumentType<T> dup(T tree, Env<AttrContext> env); 376 } 377 378 /** 379 * Argument type for parenthesized expression. 380 */ 381 class ParensType extends ArgumentType<JCParens> { 382 ParensType(JCExpression tree, Env<AttrContext> env, JCParens speculativeParens) { 383 this(tree, env, speculativeParens, new HashMap<>()); 384 } 385 386 ParensType(JCExpression tree, Env<AttrContext> env, JCParens speculativeParens, Map<ResultInfo, Type> speculativeTypes) { 387 super(tree, env, speculativeParens, speculativeTypes); 388 } 389 390 @Override 391 Type overloadCheck(ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) { 392 return checkSpeculative(speculativeTree.expr, resultInfo); 393 } 394 395 @Override 396 ArgumentType<JCParens> dup(JCParens tree, Env<AttrContext> env) { 397 return new ParensType(tree, env, speculativeTree, speculativeTypes); 398 } 399 } 400 401 /** 402 * Argument type for conditionals. 403 */ 404 class ConditionalType extends ArgumentType<JCConditional> { 405 ConditionalType(JCExpression tree, Env<AttrContext> env, JCConditional speculativeCond) { 406 this(tree, env, speculativeCond, new HashMap<>()); 407 } 408 409 ConditionalType(JCExpression tree, Env<AttrContext> env, JCConditional speculativeCond, Map<ResultInfo, Type> speculativeTypes) { 410 super(tree, env, speculativeCond, speculativeTypes); 411 } 412 413 @Override 414 Type overloadCheck(ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) { 415 ResultInfo localInfo = resultInfo.dup(attr.conditionalContext(resultInfo.checkContext)); 416 if (speculativeTree.isStandalone()) { 417 return localInfo.check(speculativeTree, speculativeTree.type); 418 } else if (resultInfo.pt.hasTag(VOID)) { 419 //this means we are returning a poly conditional from void-compatible lambda expression 420 resultInfo.checkContext.report(tree, attr.diags.fragment("conditional.target.cant.be.void")); 421 return attr.types.createErrorType(resultInfo.pt); 422 } else { 423 //poly 424 checkSpeculative(speculativeTree.truepart, localInfo); 425 checkSpeculative(speculativeTree.falsepart, localInfo); 426 return localInfo.pt; 427 } 428 } 429 430 @Override 431 ArgumentType<JCConditional> dup(JCConditional tree, Env<AttrContext> env) { 432 return new ConditionalType(tree, env, speculativeTree, speculativeTypes); 433 } 434 } 435 436 /** 437 * Argument type for explicit lambdas. 438 */ 439 class ExplicitLambdaType extends ArgumentType<JCLambda> { 440 441 /** List of argument types (lazily populated). */ 442 Optional<List<Type>> argtypes = Optional.empty(); 443 444 /** List of return expressions (lazily populated). */ 445 Optional<List<JCReturn>> returnExpressions = Optional.empty(); 446 447 ExplicitLambdaType(JCLambda originalLambda, Env<AttrContext> env, JCLambda speculativeLambda) { 448 this(originalLambda, env, speculativeLambda, new HashMap<>()); 449 } 450 451 ExplicitLambdaType(JCLambda originalLambda, Env<AttrContext> env, JCLambda speculativeLambda, Map<ResultInfo, Type> speculativeTypes) { 452 super(originalLambda, env, speculativeLambda, speculativeTypes); 453 } 454 455 /** Compute argument types (if needed). */ 456 List<Type> argtypes() { 457 return argtypes.orElseGet(() -> { 458 List<Type> res = TreeInfo.types(speculativeTree.params); 459 argtypes = Optional.of(res); 460 return res; 461 }); 462 } 463 464 /** Compute return expressions (if needed). */ 465 List<JCReturn> returnExpressions() { 466 return returnExpressions.orElseGet(() -> { 467 final List<JCReturn> res; 468 if (speculativeTree.getBodyKind() == BodyKind.EXPRESSION) { 469 res = List.of(attr.make.Return((JCExpression)speculativeTree.body)); 470 } else { 471 ListBuffer<JCReturn> returnExpressions = new ListBuffer<>(); 472 new LambdaReturnScanner() { 473 @Override 474 public void visitReturn(JCReturn tree) { 475 returnExpressions.add(tree); 476 } 477 }.scan(speculativeTree.body); 478 res = returnExpressions.toList(); 479 } 480 returnExpressions = Optional.of(res); 481 return res; 482 }); 483 } 484 485 @Override 486 Type overloadCheck(ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) { 487 try { 488 //compute target-type; this logic could be shared with Attr 489 TargetInfo targetInfo = attr.getTargetInfo(speculativeTree, resultInfo, argtypes()); 490 Type lambdaType = targetInfo.descriptor; 491 Type currentTarget = targetInfo.target; 492 //check compatibility 493 checkLambdaCompatible(lambdaType, resultInfo); 494 return currentTarget; 495 } catch (FunctionDescriptorLookupError ex) { 496 resultInfo.checkContext.report(null, ex.getDiagnostic()); 497 return null; //cannot get here 498 } 499 } 500 501 /** Check lambda against given target result */ 502 private void checkLambdaCompatible(Type descriptor, ResultInfo resultInfo) { 503 CheckContext checkContext = resultInfo.checkContext; 504 ResultInfo bodyResultInfo = attr.lambdaBodyResult(speculativeTree, descriptor, resultInfo); 505 for (JCReturn ret : returnExpressions()) { 506 Type t = getReturnType(ret); 507 if (speculativeTree.getBodyKind() == BodyKind.EXPRESSION || !t.hasTag(VOID)) { 508 checkSpeculative(ret.expr, t, bodyResultInfo); 509 } 510 } 511 512 attr.checkLambdaCompatible(speculativeTree, descriptor, checkContext); 513 } 514 515 /** Get the type associated with given return expression. */ 516 Type getReturnType(JCReturn ret) { 517 if (ret.expr == null) { 518 return syms.voidType; 519 } else { 520 return ret.expr.type; 521 } 522 } 523 524 @Override 525 ArgumentType<JCLambda> dup(JCLambda tree, Env<AttrContext> env) { 526 return new ExplicitLambdaType(tree, env, speculativeTree, speculativeTypes); 527 } 528 } 529 530 /** 531 * Argument type for methods/constructors. 532 */ 533 abstract class ResolvedMemberType<E extends JCExpression> extends ArgumentType<E> { 534 535 public ResolvedMemberType(JCExpression tree, Env<AttrContext> env, E speculativeMethod, Map<ResultInfo, Type> speculativeTypes) { 536 super(tree, env, speculativeMethod, speculativeTypes); 537 } 538 539 @Override 540 Type overloadCheck(ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) { 541 Type mtype = methodType(); 542 ResultInfo localInfo = resultInfo(resultInfo); 543 if (mtype != null && mtype.hasTag(METHOD) && mtype.isPartial()) { 544 Type t = ((PartiallyInferredMethodType)mtype).check(localInfo); 545 if (!deferredAttrContext.inferenceContext.free(localInfo.pt)) { 546 speculativeTypes.put(localInfo, t); 547 return localInfo.check(tree.pos(), t); 548 } else { 549 return t; 550 } 551 } else { 552 Type t = localInfo.check(tree.pos(), speculativeTree.type); 553 speculativeTypes.put(localInfo, t); 554 return t; 555 } 556 } 557 558 /** 559 * Get the result info to be used for performing an overload check. 560 */ 561 abstract ResultInfo resultInfo(ResultInfo resultInfo); 562 563 /** 564 * Get the method type to be used for performing an overload check. 565 */ 566 abstract Type methodType(); 567 } 568 569 /** 570 * Argument type for methods. 571 */ 572 class ResolvedMethodType extends ResolvedMemberType<JCMethodInvocation> { 573 574 public ResolvedMethodType(JCExpression tree, Env<AttrContext> env, JCMethodInvocation speculativeTree) { 575 this(tree, env, speculativeTree, new HashMap<>()); 576 } 577 578 public ResolvedMethodType(JCExpression tree, Env<AttrContext> env, JCMethodInvocation speculativeTree, Map<ResultInfo, Type> speculativeTypes) { 579 super(tree, env, speculativeTree, speculativeTypes); 580 } 581 582 @Override 583 ResultInfo resultInfo(ResultInfo resultInfo) { 584 return resultInfo; 585 } 586 587 @Override 588 Type methodType() { 589 return speculativeTree.meth.type; 590 } 591 592 @Override 593 ArgumentType<JCMethodInvocation> dup(JCMethodInvocation tree, Env<AttrContext> env) { 594 return new ResolvedMethodType(tree, env, speculativeTree, speculativeTypes); 595 } 596 } 597 598 /** 599 * Argument type for constructors. 600 */ 601 class ResolvedConstructorType extends ResolvedMemberType<JCNewClass> { 602 603 public ResolvedConstructorType(JCExpression tree, Env<AttrContext> env, JCNewClass speculativeTree) { 604 this(tree, env, speculativeTree, new HashMap<>()); 605 } 606 607 public ResolvedConstructorType(JCExpression tree, Env<AttrContext> env, JCNewClass speculativeTree, Map<ResultInfo, Type> speculativeTypes) { 608 super(tree, env, speculativeTree, speculativeTypes); 609 } 610 611 @Override 612 ResultInfo resultInfo(ResultInfo resultInfo) { 613 return resultInfo.dup(attr.diamondContext(speculativeTree, speculativeTree.clazz.type.tsym, resultInfo.checkContext)); 614 } 615 616 @Override 617 Type methodType() { 618 return (speculativeTree.constructorType != null) ? 619 speculativeTree.constructorType.baseType() : syms.errType; 620 } 621 622 @Override 623 ArgumentType<JCNewClass> dup(JCNewClass tree, Env<AttrContext> env) { 624 return new ResolvedConstructorType(tree, env, speculativeTree, speculativeTypes); 625 } 626 } 627 628 /** 629 * An instance of this class represents a unique position in a compilation unit. A unique 630 * position is made up of (i) a unique position in a source file (char offset) and (ii) 631 * a source file info. 632 */ 633 class UniquePos { 634 635 /** Char offset. */ 636 int pos; 637 638 /** Source info. */ 639 DiagnosticSource source; 640 641 UniquePos(JCTree tree) { 642 this.pos = tree.pos; 643 this.source = log.currentSource(); 644 } 645 646 @Override 647 public int hashCode() { 648 return pos << 16 + source.hashCode(); 649 } 650 651 @Override 652 public boolean equals(Object obj) { 653 if (obj instanceof UniquePos) { 654 UniquePos that = (UniquePos)obj; 655 return pos == that.pos && source == that.source; 656 } else { 657 return false; 658 } 659 } 660 661 @Override 662 public String toString() { 663 return source.getFile().getName() + " @ " + source.getLineNumber(pos); 664 } 665 } 666 667 /** 668 * Argument type caching policy. 669 */ 670 enum CachePolicy { 671 /** Cache argument types. */ 672 CACHE, 673 /** 674 * Don't cache argument types. This is useful when performing speculative attribution on 675 * a tree that is known to contain erroneous info. 676 */ 677 NO_CACHE; 678 } 679} 680