1 /* 2 * Copyright (c) 2012, 2019, 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.source.tree.NewClassTree; 30 import com.sun.tools.javac.code.*; 31 import com.sun.tools.javac.code.Type.ErrorType; 32 import com.sun.tools.javac.code.Type.MethodType; 33 import com.sun.tools.javac.code.Type.StructuralTypeMapping; 34 import com.sun.tools.javac.code.Types.TypeMapping; 35 import com.sun.tools.javac.comp.ArgumentAttr.LocalCacheContext; 36 import com.sun.tools.javac.comp.Infer.GraphSolver.InferenceGraph; 37 import com.sun.tools.javac.comp.Resolve.ResolveError; 38 import com.sun.tools.javac.resources.CompilerProperties.Fragments; 39 import com.sun.tools.javac.tree.*; 40 import com.sun.tools.javac.util.*; 41 import com.sun.tools.javac.util.DefinedBy.Api; 42 import com.sun.tools.javac.util.GraphUtils.DependencyKind; 43 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; 44 import com.sun.tools.javac.comp.Attr.ResultInfo; 45 import com.sun.tools.javac.comp.Resolve.MethodResolutionPhase; 46 import com.sun.tools.javac.resources.CompilerProperties.Errors; 47 import com.sun.tools.javac.tree.JCTree.*; 48 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticType; 49 import com.sun.tools.javac.util.Log.DeferredDiagnosticHandler; 50 import com.sun.tools.javac.util.Log.DiagnosticHandler; 51 52 import java.util.ArrayList; 53 import java.util.Collection; 54 import java.util.Collections; 55 import java.util.EnumSet; 56 import java.util.HashSet; 57 import java.util.LinkedHashSet; 58 import java.util.Map; 59 import java.util.Set; 60 import java.util.WeakHashMap; 61 import java.util.function.Supplier; 62 63 import com.sun.source.tree.MemberReferenceTree; 64 import com.sun.tools.javac.code.Type; 65 import com.sun.tools.javac.tree.JCTree.JCMemberReference.OverloadKind; 66 67 import static com.sun.tools.javac.code.TypeTag.*; 68 import com.sun.tools.javac.comp.Annotate.Queues; 69 import static com.sun.tools.javac.tree.JCTree.Tag.*; 70 71 /** 72 * This is an helper class that is used to perform deferred type-analysis. 73 * Each time a poly expression occurs in argument position, javac attributes it 74 * with a temporary 'deferred type' that is checked (possibly multiple times) 75 * against an expected formal type. 76 * 77 * <p><b>This is NOT part of any supported API. 78 * If you write code that depends on this, you do so at your own risk. 79 * This code and its internal interfaces are subject to change or 80 * deletion without notice.</b> 81 */ 82 public class DeferredAttr extends JCTree.Visitor { 83 protected static final Context.Key<DeferredAttr> deferredAttrKey = new Context.Key<>(); 84 85 final Annotate annotate; 86 final Attr attr; 87 final ArgumentAttr argumentAttr; 88 final Check chk; 89 final JCDiagnostic.Factory diags; 90 final Enter enter; 91 final Infer infer; 92 final Resolve rs; 93 final Log log; 94 final Symtab syms; 95 final TreeMaker make; 96 final TreeCopier<Void> treeCopier; 97 final TypeMapping<Void> deferredCopier; 98 final Types types; 99 final Flow flow; 100 final Names names; 101 final TypeEnvs typeEnvs; 102 final DeferredCompletionFailureHandler dcfh; 103 104 public static DeferredAttr instance(Context context) { 105 DeferredAttr instance = context.get(deferredAttrKey); 106 if (instance == null) 107 instance = new DeferredAttr(context); 108 return instance; 109 } 110 111 protected DeferredAttr(Context context) { 112 context.put(deferredAttrKey, this); 113 annotate = Annotate.instance(context); 114 attr = Attr.instance(context); 115 argumentAttr = ArgumentAttr.instance(context); 116 chk = Check.instance(context); 117 diags = JCDiagnostic.Factory.instance(context); 118 enter = Enter.instance(context); 119 infer = Infer.instance(context); 120 rs = Resolve.instance(context); 121 log = Log.instance(context); 122 syms = Symtab.instance(context); 123 make = TreeMaker.instance(context); 124 types = Types.instance(context); 125 flow = Flow.instance(context); 126 names = Names.instance(context); 127 stuckTree = make.Ident(names.empty).setType(Type.stuckType); 128 typeEnvs = TypeEnvs.instance(context); 129 dcfh = DeferredCompletionFailureHandler.instance(context); 130 emptyDeferredAttrContext = 131 new DeferredAttrContext(AttrMode.CHECK, null, MethodResolutionPhase.BOX, infer.emptyContext, null, null) { 132 @Override 133 void addDeferredAttrNode(DeferredType dt, ResultInfo ri, DeferredStuckPolicy deferredStuckPolicy) { 134 Assert.error("Empty deferred context!"); 135 } 136 @Override 137 void complete() { 138 Assert.error("Empty deferred context!"); 139 } 140 141 @Override 142 public String toString() { 143 return "Empty deferred context!"; 144 } 145 }; 146 147 // For speculative attribution, skip the class definition in <>. 148 treeCopier = 149 new TreeCopier<Void>(make) { 150 @Override @DefinedBy(Api.COMPILER_TREE) 151 public JCTree visitNewClass(NewClassTree node, Void p) { 152 JCNewClass t = (JCNewClass) node; 153 if (TreeInfo.isDiamond(t)) { 154 JCExpression encl = copy(t.encl, p); 155 List<JCExpression> typeargs = copy(t.typeargs, p); 156 JCExpression clazz = copy(t.clazz, p); 157 List<JCExpression> args = copy(t.args, p); 158 JCClassDecl def = null; 159 return make.at(t.pos).SpeculativeNewClass(encl, typeargs, clazz, args, def, t.def != null); 160 } else { 161 return super.visitNewClass(node, p); 162 } 163 } 164 165 @Override @DefinedBy(Api.COMPILER_TREE) 166 public JCTree visitMemberReference(MemberReferenceTree node, Void p) { 167 JCMemberReference t = (JCMemberReference) node; 168 JCExpression expr = copy(t.expr, p); 169 List<JCExpression> typeargs = copy(t.typeargs, p); 170 /** once the value for overloadKind is determined for a copy, it can be safely forwarded to 171 * the copied tree, we want to profit from that 172 */ 173 JCMemberReference result = new JCMemberReference(t.mode, t.name, expr, typeargs) { 174 @Override 175 public void setOverloadKind(OverloadKind overloadKind) { 176 OverloadKind previous = t.getOverloadKind(); 177 if (previous == null || previous == OverloadKind.ERROR) { 178 t.setOverloadKind(overloadKind); 179 } else { 180 Assert.check(previous == overloadKind || overloadKind == OverloadKind.ERROR); 181 } 182 } 183 184 @Override 185 public OverloadKind getOverloadKind() { 186 return t.getOverloadKind(); 187 } 188 }; 189 result.pos = t.pos; 190 return result; 191 } 192 }; 193 deferredCopier = new TypeMapping<Void> () { 194 @Override 195 public Type visitType(Type t, Void v) { 196 if (t.hasTag(DEFERRED)) { 197 DeferredType dt = (DeferredType) t; 198 return new DeferredType(treeCopier.copy(dt.tree), dt.env); 199 } 200 return t; 201 } 202 }; 203 } 204 205 /** shared tree for stuck expressions */ 206 final JCTree stuckTree; 207 208 /** 209 * This type represents a deferred type. A deferred type starts off with 210 * no information on the underlying expression type. Such info needs to be 211 * discovered through type-checking the deferred type against a target-type. 212 * Every deferred type keeps a pointer to the AST node from which it originated. 213 */ 214 public class DeferredType extends Type { 215 216 public JCExpression tree; 217 Env<AttrContext> env; 218 AttrMode mode; 219 Set<Symbol> notPertinentToApplicability = new HashSet<>(); 220 SpeculativeCache speculativeCache; 221 222 DeferredType(JCExpression tree, Env<AttrContext> env) { 223 super(null, TypeMetadata.EMPTY); 224 this.tree = tree; 225 this.env = attr.copyEnv(env); 226 this.speculativeCache = new SpeculativeCache(); 227 } 228 229 @Override 230 public DeferredType cloneWithMetadata(TypeMetadata md) { 231 throw new AssertionError("Cannot add metadata to a deferred type"); 232 } 233 234 @Override 235 public TypeTag getTag() { 236 return DEFERRED; 237 } 238 239 @Override @DefinedBy(Api.LANGUAGE_MODEL) 240 public String toString() { 241 return "DeferredType"; 242 } 243 244 /** 245 * A speculative cache is used to keep track of all overload resolution rounds 246 * that triggered speculative attribution on a given deferred type. Each entry 247 * stores a pointer to the speculative tree and the resolution phase in which the entry 248 * has been added. 249 */ 250 class SpeculativeCache { 251 252 private Map<Symbol, List<Entry>> cache = new WeakHashMap<>(); 253 254 class Entry { 255 JCTree speculativeTree; 256 ResultInfo resultInfo; 257 258 public Entry(JCTree speculativeTree, ResultInfo resultInfo) { 259 this.speculativeTree = speculativeTree; 260 this.resultInfo = resultInfo; 261 } 262 263 boolean matches(MethodResolutionPhase phase) { 264 return resultInfo.checkContext.deferredAttrContext().phase == phase; 265 } 266 } 267 268 /** 269 * Retrieve a speculative cache entry corresponding to given symbol 270 * and resolution phase 271 */ 272 Entry get(Symbol msym, MethodResolutionPhase phase) { 273 List<Entry> entries = cache.get(msym); 274 if (entries == null) return null; 275 for (Entry e : entries) { 276 if (e.matches(phase)) return e; 277 } 278 return null; 279 } 280 281 /** 282 * Stores a speculative cache entry corresponding to given symbol 283 * and resolution phase 284 */ 285 void put(JCTree speculativeTree, ResultInfo resultInfo) { 286 Symbol msym = resultInfo.checkContext.deferredAttrContext().msym; 287 List<Entry> entries = cache.get(msym); 288 if (entries == null) { 289 entries = List.nil(); 290 } 291 cache.put(msym, entries.prepend(new Entry(speculativeTree, resultInfo))); 292 } 293 } 294 295 /** 296 * Get the type that has been computed during a speculative attribution round 297 */ 298 Type speculativeType(Symbol msym, MethodResolutionPhase phase) { 299 SpeculativeCache.Entry e = speculativeCache.get(msym, phase); 300 return e != null ? e.speculativeTree.type : Type.noType; 301 } 302 303 JCTree speculativeTree(DeferredAttrContext deferredAttrContext) { 304 DeferredType.SpeculativeCache.Entry e = speculativeCache.get(deferredAttrContext.msym, deferredAttrContext.phase); 305 return e != null ? e.speculativeTree : stuckTree; 306 } 307 308 DeferredTypeCompleter completer() { 309 return basicCompleter; 310 } 311 312 /** 313 * Check a deferred type against a potential target-type. Depending on 314 * the current attribution mode, a normal vs. speculative attribution 315 * round is performed on the underlying AST node. There can be only one 316 * speculative round for a given target method symbol; moreover, a normal 317 * attribution round must follow one or more speculative rounds. 318 */ 319 Type check(ResultInfo resultInfo) { 320 DeferredStuckPolicy deferredStuckPolicy; 321 if (resultInfo.pt.hasTag(NONE) || resultInfo.pt.isErroneous()) { 322 deferredStuckPolicy = dummyStuckPolicy; 323 } else if (resultInfo.checkContext.deferredAttrContext().mode == AttrMode.SPECULATIVE || 324 resultInfo.checkContext.deferredAttrContext().insideOverloadPhase()) { 325 deferredStuckPolicy = new OverloadStuckPolicy(resultInfo, this); 326 } else { 327 deferredStuckPolicy = new CheckStuckPolicy(resultInfo, this); 328 } 329 return check(resultInfo, deferredStuckPolicy, completer()); 330 } 331 332 private Type check(ResultInfo resultInfo, DeferredStuckPolicy deferredStuckPolicy, 333 DeferredTypeCompleter deferredTypeCompleter) { 334 DeferredAttrContext deferredAttrContext = 335 resultInfo.checkContext.deferredAttrContext(); 336 Assert.check(deferredAttrContext != emptyDeferredAttrContext); 337 if (deferredStuckPolicy.isStuck()) { 338 notPertinentToApplicability.add(deferredAttrContext.msym); 339 deferredAttrContext.addDeferredAttrNode(this, resultInfo, deferredStuckPolicy); 340 return Type.noType; 341 } else { 342 try { 343 return deferredTypeCompleter.complete(this, resultInfo, deferredAttrContext); 344 } finally { 345 mode = deferredAttrContext.mode; 346 } 347 } 348 } 349 } 350 351 /** 352 * A completer for deferred types. Defines an entry point for type-checking 353 * a deferred type. 354 */ 355 interface DeferredTypeCompleter { 356 /** 357 * Entry point for type-checking a deferred type. Depending on the 358 * circumstances, type-checking could amount to full attribution 359 * or partial structural check (aka potential applicability). 360 */ 361 Type complete(DeferredType dt, ResultInfo resultInfo, DeferredAttrContext deferredAttrContext); 362 } 363 364 365 /** 366 * A basic completer for deferred types. This completer type-checks a deferred type 367 * using attribution; depending on the attribution mode, this could be either standard 368 * or speculative attribution. 369 */ 370 DeferredTypeCompleter basicCompleter = new DeferredTypeCompleter() { 371 public Type complete(DeferredType dt, ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) { 372 switch (deferredAttrContext.mode) { 373 case SPECULATIVE: 374 //Note: if a symbol is imported twice we might do two identical 375 //speculative rounds... 376 Assert.check(dt.mode == null || dt.mode == AttrMode.SPECULATIVE); 377 JCTree speculativeTree = attribSpeculative(dt.tree, dt.env, resultInfo); 378 dt.speculativeCache.put(speculativeTree, resultInfo); 379 return speculativeTree.type; 380 case CHECK: 381 Assert.check(dt.mode != null); 382 return attr.attribTree(dt.tree, dt.env, resultInfo); 383 } 384 Assert.error(); 385 return null; 386 } 387 }; 388 389 /** 390 * Policy for detecting stuck expressions. Different criteria might cause 391 * an expression to be judged as stuck, depending on whether the check 392 * is performed during overload resolution or after most specific. 393 */ 394 interface DeferredStuckPolicy { 395 /** 396 * Has the policy detected that a given expression should be considered stuck? 397 */ 398 boolean isStuck(); 399 /** 400 * Get the set of inference variables a given expression depends upon. 401 */ 402 Set<Type> stuckVars(); 403 /** 404 * Get the set of inference variables which might get new constraints 405 * if a given expression is being type-checked. 406 */ 407 Set<Type> depVars(); 408 } 409 410 /** 411 * Basic stuck policy; an expression is never considered to be stuck. 412 */ 413 DeferredStuckPolicy dummyStuckPolicy = new DeferredStuckPolicy() { 414 @Override 415 public boolean isStuck() { 416 return false; 417 } 418 @Override 419 public Set<Type> stuckVars() { 420 return Collections.emptySet(); 421 } 422 @Override 423 public Set<Type> depVars() { 424 return Collections.emptySet(); 425 } 426 }; 427 428 /** 429 * The 'mode' in which the deferred type is to be type-checked 430 */ 431 public enum AttrMode { 432 /** 433 * A speculative type-checking round is used during overload resolution 434 * mainly to generate constraints on inference variables. Side-effects 435 * arising from type-checking the expression associated with the deferred 436 * type are reversed after the speculative round finishes. This means the 437 * expression tree will be left in a blank state. 438 */ 439 SPECULATIVE, 440 /** 441 * This is the plain type-checking mode. Produces side-effects on the underlying AST node 442 */ 443 CHECK 444 } 445 446 /** 447 * Performs speculative attribution of a lambda body and returns the speculative lambda tree, 448 * in the absence of a target-type. Since {@link Attr#visitLambda(JCLambda)} cannot type-check 449 * lambda bodies w/o a suitable target-type, this routine 'unrolls' the lambda by turning it 450 * into a regular block, speculatively type-checks the block and then puts back the pieces. 451 */ 452 JCLambda attribSpeculativeLambda(JCLambda that, Env<AttrContext> env, ResultInfo resultInfo) { 453 ListBuffer<JCStatement> stats = new ListBuffer<>(); 454 stats.addAll(that.params); 455 if (that.getBodyKind() == JCLambda.BodyKind.EXPRESSION) { 456 stats.add(make.Return((JCExpression)that.body)); 457 } else { 458 stats.add((JCBlock)that.body); 459 } 460 JCBlock lambdaBlock = make.at(that.pos).Block(0, stats.toList()); 461 Env<AttrContext> localEnv = attr.lambdaEnv(that, env); 462 try { 463 localEnv.info.returnResult = resultInfo; 464 JCBlock speculativeTree = (JCBlock)attribSpeculative(lambdaBlock, localEnv, resultInfo); 465 List<JCVariableDecl> args = speculativeTree.getStatements().stream() 466 .filter(s -> s.hasTag(Tag.VARDEF)) 467 .map(t -> (JCVariableDecl)t) 468 .collect(List.collector()); 469 JCTree lambdaBody = speculativeTree.getStatements().last(); 470 if (lambdaBody.hasTag(Tag.RETURN)) { 471 lambdaBody = ((JCReturn)lambdaBody).expr; 472 } 473 JCLambda speculativeLambda = make.Lambda(args, lambdaBody); 474 attr.preFlow(speculativeLambda); 475 flow.analyzeLambda(env, speculativeLambda, make, false); 476 return speculativeLambda; 477 } finally { 478 localEnv.info.scope.leave(); 479 } 480 } 481 482 /** 483 * Routine that performs speculative type-checking; the input AST node is 484 * cloned (to avoid side-effects cause by Attr) and compiler state is 485 * restored after type-checking. All diagnostics (but critical ones) are 486 * disabled during speculative type-checking. 487 */ 488 JCTree attribSpeculative(JCTree tree, Env<AttrContext> env, ResultInfo resultInfo) { 489 return attribSpeculative(tree, env, resultInfo, treeCopier, 490 null, AttributionMode.SPECULATIVE, null); 491 } 492 493 JCTree attribSpeculative(JCTree tree, Env<AttrContext> env, ResultInfo resultInfo, LocalCacheContext localCache) { 494 return attribSpeculative(tree, env, resultInfo, treeCopier, 495 null, AttributionMode.SPECULATIVE, localCache); 496 } 497 498 <Z> JCTree attribSpeculative(JCTree tree, Env<AttrContext> env, ResultInfo resultInfo, TreeCopier<Z> deferredCopier, 499 Supplier<DiagnosticHandler> diagHandlerCreator, AttributionMode attributionMode, 500 LocalCacheContext localCache) { 501 final JCTree newTree = deferredCopier.copy(tree); 502 return attribSpeculative(newTree, env, resultInfo, diagHandlerCreator, attributionMode, localCache); 503 } 504 505 /** 506 * Attribute the given tree, mostly reverting side-effects applied to shared 507 * compiler state. Exceptions include the ArgumentAttr.argumentTypeCache, 508 * changes to which may be preserved if localCache is null. 509 */ 510 <Z> JCTree attribSpeculative(JCTree tree, Env<AttrContext> env, ResultInfo resultInfo, 511 Supplier<DiagnosticHandler> diagHandlerCreator, AttributionMode attributionMode, 512 LocalCacheContext localCache) { 513 Env<AttrContext> speculativeEnv = env.dup(tree, env.info.dup(env.info.scope.dupUnshared(env.info.scope.owner))); 514 speculativeEnv.info.attributionMode = attributionMode; 515 Log.DiagnosticHandler deferredDiagnosticHandler = diagHandlerCreator != null ? diagHandlerCreator.get() : new DeferredDiagnosticHandler(log); 516 DeferredCompletionFailureHandler.Handler prevCFHandler = dcfh.setHandler(dcfh.speculativeCodeHandler); 517 Queues prevQueues = annotate.setQueues(new Queues()); 518 int nwarnings = log.nwarnings; 519 log.nwarnings = 0; 520 try { 521 attr.attribTree(tree, speculativeEnv, resultInfo); 522 return tree; 523 } finally { 524 annotate.setQueues(prevQueues); 525 dcfh.setHandler(prevCFHandler); 526 log.nwarnings += nwarnings; 527 enter.unenter(env.toplevel, tree); 528 log.popDiagnosticHandler(deferredDiagnosticHandler); 529 if (localCache != null) { 530 localCache.leave(); 531 } 532 } 533 } 534 535 /** 536 * A deferred context is created on each method check. A deferred context is 537 * used to keep track of information associated with the method check, such as 538 * the symbol of the method being checked, the overload resolution phase, 539 * the kind of attribution mode to be applied to deferred types and so forth. 540 * As deferred types are processed (by the method check routine) stuck AST nodes 541 * are added (as new deferred attribution nodes) to this context. The complete() 542 * routine makes sure that all pending nodes are properly processed, by 543 * progressively instantiating all inference variables on which one or more 544 * deferred attribution node is stuck. 545 */ 546 class DeferredAttrContext { 547 548 /** attribution mode */ 549 final AttrMode mode; 550 551 /** symbol of the method being checked */ 552 final Symbol msym; 553 554 /** method resolution step */ 555 final Resolve.MethodResolutionPhase phase; 556 557 /** inference context */ 558 final InferenceContext inferenceContext; 559 560 /** parent deferred context */ 561 final DeferredAttrContext parent; 562 563 /** Warner object to report warnings */ 564 final Warner warn; 565 566 /** list of deferred attribution nodes to be processed */ 567 ArrayList<DeferredAttrNode> deferredAttrNodes = new ArrayList<>(); 568 569 DeferredAttrContext(AttrMode mode, Symbol msym, MethodResolutionPhase phase, 570 InferenceContext inferenceContext, DeferredAttrContext parent, Warner warn) { 571 this.mode = mode; 572 this.msym = msym; 573 this.phase = phase; 574 this.parent = parent; 575 this.warn = warn; 576 this.inferenceContext = inferenceContext; 577 } 578 579 /** 580 * Adds a node to the list of deferred attribution nodes - used by Resolve.rawCheckArgumentsApplicable 581 * Nodes added this way act as 'roots' for the out-of-order method checking process. 582 */ 583 void addDeferredAttrNode(final DeferredType dt, ResultInfo resultInfo, 584 DeferredStuckPolicy deferredStuckPolicy) { 585 deferredAttrNodes.add(new DeferredAttrNode(dt, resultInfo, deferredStuckPolicy)); 586 } 587 588 /** 589 * Incrementally process all nodes, by skipping 'stuck' nodes and attributing 590 * 'unstuck' ones. If at any point no progress can be made (no 'unstuck' nodes) 591 * some inference variable might get eagerly instantiated so that all nodes 592 * can be type-checked. 593 */ 594 void complete() { 595 while (!deferredAttrNodes.isEmpty()) { 596 boolean progress = false; 597 //scan a defensive copy of the node list - this is because a deferred 598 //attribution round can add new nodes to the list 599 for (DeferredAttrNode deferredAttrNode : List.from(deferredAttrNodes)) { 600 if (deferredAttrNode.process(this)) { 601 deferredAttrNodes.remove(deferredAttrNode); 602 progress = true; 603 } 604 } 605 if (!progress) { 606 if (insideOverloadPhase()) { 607 for (DeferredAttrNode deferredNode: deferredAttrNodes) { 608 deferredNode.dt.tree.type = Type.noType; 609 } 610 return; 611 } 612 //remove all variables that have already been instantiated 613 //from the list of stuck variables 614 try { 615 //find stuck expression to unstuck 616 DeferredAttrNode toUnstuck = pickDeferredNode(); 617 inferenceContext.solveAny(List.from(toUnstuck.deferredStuckPolicy.stuckVars()), warn); 618 inferenceContext.notifyChange(); 619 } catch (Infer.GraphStrategy.NodeNotFoundException ex) { 620 //this means that we are in speculative mode and the 621 //set of contraints are too tight for progess to be made. 622 //Just leave the remaining expressions as stuck. 623 break; 624 } 625 } 626 } 627 } 628 629 public boolean insideOverloadPhase() { 630 DeferredAttrContext dac = this; 631 if (dac == emptyDeferredAttrContext) { 632 return false; 633 } 634 if (dac.mode == AttrMode.SPECULATIVE) { 635 return true; 636 } 637 return dac.parent.insideOverloadPhase(); 638 } 639 640 /** 641 * Pick the deferred node to be unstuck. First, deferred nodes are organized into a graph 642 * (see {@code DeferredAttrContext.buildStuckGraph()}, where a node N1 depends on another node N2 643 * if its input variable depends (as per the inference graph) on the output variables of N2 644 * (see {@code DeferredAttrContext.canInfluence()}. 645 * 646 * Then, the chosen deferred node is the first strongly connected component containing exactly 647 * one node found in such a graph. If no such component is found, the first deferred node is chosen. 648 */ 649 DeferredAttrNode pickDeferredNode() { 650 List<StuckNode> stuckGraph = buildStuckGraph(); 651 //compute tarjan on the stuck graph 652 List<? extends StuckNode> csn = GraphUtils.tarjan(stuckGraph).get(0); 653 return csn.length() == 1 ? csn.get(0).data : deferredAttrNodes.get(0); 654 } 655 656 List<StuckNode> buildStuckGraph() { 657 //first, build inference graph 658 infer.doIncorporation(inferenceContext, warn); 659 InferenceGraph graph = infer.new GraphSolver(inferenceContext, types.noWarnings) 660 .new InferenceGraph(); 661 //then, build stuck graph 662 List<StuckNode> nodes = deferredAttrNodes.stream() 663 .map(StuckNode::new) 664 .collect(List.collector()); 665 //init stuck expression graph; a deferred node A depends on a deferred node B iff 666 //B's output variables can influence A's input variables. 667 for (StuckNode sn1 : nodes) { 668 for (StuckNode sn2 : nodes) { 669 if (sn1 != sn2 && canInfluence(graph, sn2, sn1)) { 670 sn1.deps.add(sn2); 671 } 672 } 673 } 674 return nodes; 675 } 676 677 boolean canInfluence(InferenceGraph graph, StuckNode sn1, StuckNode sn2) { 678 Set<Type> outputVars = sn1.data.deferredStuckPolicy.depVars(); 679 for (Type inputVar : sn2.data.deferredStuckPolicy.stuckVars()) { 680 InferenceGraph.Node inputNode = graph.findNode(inputVar); 681 //already solved stuck vars do not appear in the graph 682 if (inputNode != null) { 683 Set<InferenceGraph.Node> inputClosure = inputNode.closure(); 684 if (outputVars.stream() 685 .map(graph::findNode) 686 .anyMatch(inputClosure::contains)) { 687 return true; 688 } 689 } 690 } 691 return false; 692 } 693 694 class StuckNode extends GraphUtils.TarjanNode<DeferredAttrNode, StuckNode> { 695 696 Set<StuckNode> deps = new HashSet<>(); 697 698 StuckNode(DeferredAttrNode data) { 699 super(data); 700 } 701 702 @Override 703 public DependencyKind[] getSupportedDependencyKinds() { 704 return new DependencyKind[] { Infer.DependencyKind.STUCK }; 705 } 706 707 @Override 708 public Collection<? extends StuckNode> getDependenciesByKind(DependencyKind dk) { 709 if (dk == Infer.DependencyKind.STUCK) { 710 return deps; 711 } else { 712 throw new IllegalStateException(); 713 } 714 } 715 716 @Override 717 public Iterable<? extends StuckNode> getAllDependencies() { 718 return deps; 719 } 720 } 721 } 722 723 /** 724 * Class representing a deferred attribution node. It keeps track of 725 * a deferred type, along with the expected target type information. 726 */ 727 class DeferredAttrNode { 728 729 /** underlying deferred type */ 730 DeferredType dt; 731 732 /** underlying target type information */ 733 ResultInfo resultInfo; 734 735 /** stuck policy associated with this node */ 736 DeferredStuckPolicy deferredStuckPolicy; 737 738 DeferredAttrNode(DeferredType dt, ResultInfo resultInfo, DeferredStuckPolicy deferredStuckPolicy) { 739 this.dt = dt; 740 this.resultInfo = resultInfo; 741 this.deferredStuckPolicy = deferredStuckPolicy; 742 } 743 744 /** 745 * Process a deferred attribution node. 746 * Invariant: a stuck node cannot be processed. 747 */ 748 @SuppressWarnings("fallthrough") 749 boolean process(final DeferredAttrContext deferredAttrContext) { 750 switch (deferredAttrContext.mode) { 751 case SPECULATIVE: 752 if (deferredStuckPolicy.isStuck()) { 753 dt.check(resultInfo, dummyStuckPolicy, new StructuralStuckChecker()); 754 return true; 755 } else { 756 Assert.error("Cannot get here"); 757 } 758 case CHECK: 759 if (deferredStuckPolicy.isStuck()) { 760 //stuck expression - see if we can propagate 761 if (deferredAttrContext.parent != emptyDeferredAttrContext && 762 Type.containsAny(deferredAttrContext.parent.inferenceContext.inferencevars, 763 List.from(deferredStuckPolicy.stuckVars()))) { 764 deferredAttrContext.parent.addDeferredAttrNode(dt, 765 resultInfo.dup(new Check.NestedCheckContext(resultInfo.checkContext) { 766 @Override 767 public InferenceContext inferenceContext() { 768 return deferredAttrContext.parent.inferenceContext; 769 } 770 @Override 771 public DeferredAttrContext deferredAttrContext() { 772 return deferredAttrContext.parent; 773 } 774 }), deferredStuckPolicy); 775 dt.tree.type = Type.stuckType; 776 return true; 777 } else { 778 return false; 779 } 780 } else { 781 Assert.check(!deferredAttrContext.insideOverloadPhase(), 782 "attribution shouldn't be happening here"); 783 ResultInfo instResultInfo = 784 resultInfo.dup(deferredAttrContext.inferenceContext.asInstType(resultInfo.pt)); 785 dt.check(instResultInfo, dummyStuckPolicy, basicCompleter); 786 return true; 787 } 788 default: 789 throw new AssertionError("Bad mode"); 790 } 791 } 792 793 /** 794 * Structural checker for stuck expressions 795 */ 796 class StructuralStuckChecker extends TreeScanner implements DeferredTypeCompleter { 797 798 ResultInfo resultInfo; 799 InferenceContext inferenceContext; 800 Env<AttrContext> env; 801 802 public Type complete(DeferredType dt, ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) { 803 this.resultInfo = resultInfo; 804 this.inferenceContext = deferredAttrContext.inferenceContext; 805 this.env = dt.env; 806 dt.tree.accept(this); 807 dt.speculativeCache.put(stuckTree, resultInfo); 808 return Type.noType; 809 } 810 811 @Override 812 public void visitLambda(JCLambda tree) { 813 Check.CheckContext checkContext = resultInfo.checkContext; 814 Type pt = resultInfo.pt; 815 if (!inferenceContext.inferencevars.contains(pt)) { 816 //must be a functional descriptor 817 Type descriptorType = null; 818 try { 819 descriptorType = types.findDescriptorType(pt); 820 } catch (Types.FunctionDescriptorLookupError ex) { 821 checkContext.report(null, ex.getDiagnostic()); 822 } 823 824 if (descriptorType.getParameterTypes().length() != tree.params.length()) { 825 checkContext.report(tree, 826 diags.fragment(Fragments.IncompatibleArgTypesInLambda)); 827 } 828 829 Type currentReturnType = descriptorType.getReturnType(); 830 boolean returnTypeIsVoid = currentReturnType.hasTag(VOID); 831 if (tree.getBodyKind() == BodyKind.EXPRESSION) { 832 boolean isExpressionCompatible = !returnTypeIsVoid || 833 TreeInfo.isExpressionStatement((JCExpression)tree.getBody()); 834 if (!isExpressionCompatible) { 835 resultInfo.checkContext.report(tree.pos(), 836 diags.fragment(Fragments.IncompatibleRetTypeInLambda(Fragments.MissingRetVal(currentReturnType)))); 837 } 838 } else { 839 LambdaBodyStructChecker lambdaBodyChecker = 840 new LambdaBodyStructChecker(); 841 842 tree.body.accept(lambdaBodyChecker); 843 boolean isVoidCompatible = lambdaBodyChecker.isVoidCompatible; 844 845 if (returnTypeIsVoid) { 846 if (!isVoidCompatible) { 847 resultInfo.checkContext.report(tree.pos(), 848 diags.fragment(Fragments.UnexpectedRetVal)); 849 } 850 } else { 851 boolean isValueCompatible = lambdaBodyChecker.isPotentiallyValueCompatible 852 && !canLambdaBodyCompleteNormally(tree); 853 if (!isValueCompatible && !isVoidCompatible) { 854 log.error(tree.body.pos(), 855 Errors.LambdaBodyNeitherValueNorVoidCompatible); 856 } 857 858 if (!isValueCompatible) { 859 resultInfo.checkContext.report(tree.pos(), 860 diags.fragment(Fragments.IncompatibleRetTypeInLambda(Fragments.MissingRetVal(currentReturnType)))); 861 } 862 } 863 } 864 } 865 } 866 867 boolean canLambdaBodyCompleteNormally(JCLambda tree) { 868 List<JCVariableDecl> oldParams = tree.params; 869 LocalCacheContext localCacheContext = argumentAttr.withLocalCacheContext(); 870 try { 871 tree.params = tree.params.stream() 872 .map(vd -> make.VarDef(vd.mods, vd.name, make.Erroneous(), null)) 873 .collect(List.collector()); 874 return attribSpeculativeLambda(tree, env, attr.unknownExprInfo).canCompleteNormally; 875 } finally { 876 localCacheContext.leave(); 877 tree.params = oldParams; 878 } 879 } 880 881 @Override 882 public void visitNewClass(JCNewClass tree) { 883 //do nothing 884 } 885 886 @Override 887 public void visitApply(JCMethodInvocation tree) { 888 //do nothing 889 } 890 891 @Override 892 public void visitReference(JCMemberReference tree) { 893 Assert.checkNonNull(tree.getOverloadKind()); 894 Check.CheckContext checkContext = resultInfo.checkContext; 895 Type pt = resultInfo.pt; 896 if (!inferenceContext.inferencevars.contains(pt)) { 897 Type descriptor = null; 898 try { 899 descriptor = types.findDescriptorType(pt); 900 } catch (Types.FunctionDescriptorLookupError ex) { 901 checkContext.report(null, ex.getDiagnostic()); 902 } 903 Env<AttrContext> localEnv = env.dup(tree); 904 JCExpression exprTree; 905 exprTree = (JCExpression)attribSpeculative(tree.getQualifierExpression(), localEnv, 906 attr.memberReferenceQualifierResult(tree), argumentAttr.withLocalCacheContext()); 907 ListBuffer<Type> argtypes = new ListBuffer<>(); 908 for (Type t : descriptor.getParameterTypes()) { 909 argtypes.append(Type.noType); 910 } 911 JCMemberReference mref2 = new TreeCopier<Void>(make).copy(tree); 912 mref2.expr = exprTree; 913 Symbol lookupSym = 914 rs.resolveMemberReference(localEnv, mref2, exprTree.type, 915 tree.name, argtypes.toList(), List.nil(), descriptor, rs.arityMethodCheck, 916 inferenceContext, rs.structuralReferenceChooser).fst; 917 switch (lookupSym.kind) { 918 case WRONG_MTH: 919 case WRONG_MTHS: 920 //note: as argtypes are erroneous types, type-errors must 921 //have been caused by arity mismatch 922 checkContext.report(tree, diags.fragment(Fragments.IncompatibleArgTypesInMref)); 923 break; 924 case ABSENT_MTH: 925 case STATICERR: 926 //if no method found, or method found with wrong staticness, report better message 927 checkContext.report(tree, ((ResolveError)lookupSym).getDiagnostic(DiagnosticType.FRAGMENT, 928 tree, exprTree.type.tsym, exprTree.type, tree.name, argtypes.toList(), List.nil())); 929 break; 930 } 931 } 932 } 933 } 934 935 /* This visitor looks for return statements, its analysis will determine if 936 * a lambda body is void or value compatible. We must analyze return 937 * statements contained in the lambda body only, thus any return statement 938 * contained in an inner class or inner lambda body, should be ignored. 939 */ 940 class LambdaBodyStructChecker extends TreeScanner { 941 boolean isVoidCompatible = true; 942 boolean isPotentiallyValueCompatible = true; 943 944 @Override 945 public void visitClassDef(JCClassDecl tree) { 946 // do nothing 947 } 948 949 @Override 950 public void visitLambda(JCLambda tree) { 951 // do nothing 952 } 953 954 @Override 955 public void visitNewClass(JCNewClass tree) { 956 // do nothing 957 } 958 959 @Override 960 public void visitReturn(JCReturn tree) { 961 if (tree.expr != null) { 962 isVoidCompatible = false; 963 } else { 964 isPotentiallyValueCompatible = false; 965 } 966 } 967 } 968 } 969 970 /** an empty deferred attribution context - all methods throw exceptions */ 971 final DeferredAttrContext emptyDeferredAttrContext; 972 973 /** 974 * Map a list of types possibly containing one or more deferred types 975 * into a list of ordinary types. Each deferred type D is mapped into a type T, 976 * where T is computed by retrieving the type that has already been 977 * computed for D during a previous deferred attribution round of the given kind. 978 */ 979 class DeferredTypeMap<T> extends StructuralTypeMapping<T> { 980 DeferredAttrContext deferredAttrContext; 981 982 protected DeferredTypeMap(AttrMode mode, Symbol msym, MethodResolutionPhase phase) { 983 this.deferredAttrContext = new DeferredAttrContext(mode, msym, phase, 984 infer.emptyContext, emptyDeferredAttrContext, types.noWarnings); 985 } 986 987 @Override 988 public Type visitType(Type t, T p) { 989 if (!t.hasTag(DEFERRED)) { 990 return super.visitType(t, p); 991 } else { 992 DeferredType dt = (DeferredType)t; 993 return typeOf(dt, p); 994 } 995 } 996 997 protected Type typeOf(DeferredType dt, T p) { 998 switch (deferredAttrContext.mode) { 999 case CHECK: 1000 return dt.tree.type == null ? Type.noType : dt.tree.type; 1001 case SPECULATIVE: 1002 return dt.speculativeType(deferredAttrContext.msym, deferredAttrContext.phase); 1003 } 1004 Assert.error(); 1005 return null; 1006 } 1007 } 1008 1009 /** 1010 * Specialized recovery deferred mapping. 1011 * Each deferred type D is mapped into a type T, where T is computed either by 1012 * (i) retrieving the type that has already been computed for D during a previous 1013 * attribution round (as before), or (ii) by synthesizing a new type R for D 1014 * (the latter step is useful in a recovery scenario). 1015 */ 1016 public class RecoveryDeferredTypeMap extends DeferredTypeMap<Type> { 1017 1018 public RecoveryDeferredTypeMap(AttrMode mode, Symbol msym, MethodResolutionPhase phase) { 1019 super(mode, msym, phase != null ? phase : MethodResolutionPhase.BOX); 1020 } 1021 1022 @Override 1023 protected Type typeOf(DeferredType dt, Type pt) { 1024 Type owntype = super.typeOf(dt, pt); 1025 return owntype == Type.noType ? 1026 recover(dt, pt) : owntype; 1027 } 1028 1029 @Override 1030 public Type visitMethodType(Type.MethodType t, Type pt) { 1031 if (t.hasTag(METHOD) && deferredAttrContext.mode == AttrMode.CHECK) { 1032 Type mtype = deferredAttrContext.msym.type; 1033 mtype = mtype.hasTag(ERROR) ? ((ErrorType)mtype).getOriginalType() : null; 1034 if (mtype != null && mtype.hasTag(METHOD)) { 1035 List<Type> argtypes1 = map(t.getParameterTypes(), mtype.getParameterTypes()); 1036 Type restype1 = visit(t.getReturnType(), mtype.getReturnType()); 1037 List<Type> thrown1 = map(t.getThrownTypes(), mtype.getThrownTypes()); 1038 if (argtypes1 == t.getParameterTypes() && 1039 restype1 == t.getReturnType() && 1040 thrown1 == t.getThrownTypes()) return t; 1041 else return new MethodType(argtypes1, restype1, thrown1, t.tsym); 1042 } 1043 } 1044 return super.visitMethodType(t, pt); 1045 } 1046 1047 /** 1048 * Synthesize a type for a deferred type that hasn't been previously 1049 * reduced to an ordinary type. Functional deferred types and conditionals 1050 * are mapped to themselves, in order to have a richer diagnostic 1051 * representation. Remaining deferred types are attributed using 1052 * a default expected type (j.l.Object). 1053 */ 1054 private Type recover(DeferredType dt, Type pt) { 1055 dt.check(attr.new RecoveryInfo(deferredAttrContext, pt != null ? pt : Type.recoveryType) { 1056 @Override 1057 protected Type check(DiagnosticPosition pos, Type found) { 1058 return chk.checkNonVoid(pos, super.check(pos, found)); 1059 } 1060 }); 1061 return super.visit(dt); 1062 } 1063 1064 private List<Type> map(List<Type> ts, List<Type> pts) { 1065 if (ts.nonEmpty()) { 1066 List<Type> tail1 = map(ts.tail, pts != null ? pts.tail : null); 1067 Type t = visit(ts.head, pts != null && pts.nonEmpty() ? pts.head : null); 1068 if (tail1 != ts.tail || t != ts.head) 1069 return tail1.prepend(t); 1070 } 1071 return ts; 1072 } 1073 } 1074 1075 /** 1076 * A special tree scanner that would only visit portions of a given tree. 1077 * The set of nodes visited by the scanner can be customized at construction-time. 1078 */ 1079 abstract static class FilterScanner extends com.sun.tools.javac.tree.TreeScanner { 1080 1081 final Filter<JCTree> treeFilter; 1082 1083 FilterScanner(final Set<JCTree.Tag> validTags) { 1084 this.treeFilter = t -> validTags.contains(t.getTag()); 1085 } 1086 1087 @Override 1088 public void scan(JCTree tree) { 1089 if (tree != null) { 1090 if (treeFilter.accepts(tree)) { 1091 super.scan(tree); 1092 } else { 1093 skip(tree); 1094 } 1095 } 1096 } 1097 1098 /** 1099 * handler that is executed when a node has been discarded 1100 */ 1101 void skip(JCTree tree) {} 1102 } 1103 1104 /** 1105 * A tree scanner suitable for visiting the target-type dependent nodes of 1106 * a given argument expression. 1107 */ 1108 static class PolyScanner extends FilterScanner { 1109 1110 PolyScanner() { 1111 super(EnumSet.of(CONDEXPR, PARENS, LAMBDA, REFERENCE)); 1112 } 1113 } 1114 1115 /** 1116 * A tree scanner suitable for visiting the target-type dependent nodes nested 1117 * within a lambda expression body. 1118 */ 1119 static class LambdaReturnScanner extends FilterScanner { 1120 1121 LambdaReturnScanner() { 1122 super(EnumSet.of(BLOCK, CASE, CATCH, DOLOOP, FOREACHLOOP, 1123 FORLOOP, IF, RETURN, SYNCHRONIZED, SWITCH, TRY, WHILELOOP)); 1124 } 1125 } 1126 1127 /** 1128 * A tree scanner suitable for visiting the target-type dependent nodes nested 1129 * within a switch expression body. 1130 */ 1131 static class SwitchExpressionScanner extends FilterScanner { 1132 1133 SwitchExpressionScanner() { 1134 super(EnumSet.of(BLOCK, CASE, CATCH, DOLOOP, FOREACHLOOP, 1135 FORLOOP, IF, SYNCHRONIZED, SWITCH, TRY, WHILELOOP, YIELD)); 1136 } 1137 } 1138 1139 /** 1140 * This visitor is used to check that structural expressions conform 1141 * to their target - this step is required as inference could end up 1142 * inferring types that make some of the nested expressions incompatible 1143 * with their corresponding instantiated target 1144 */ 1145 class CheckStuckPolicy extends PolyScanner implements DeferredStuckPolicy, Infer.FreeTypeListener { 1146 1147 Type pt; 1148 InferenceContext inferenceContext; 1149 Set<Type> stuckVars = new LinkedHashSet<>(); 1150 Set<Type> depVars = new LinkedHashSet<>(); 1151 1152 @Override 1153 public boolean isStuck() { 1154 return !stuckVars.isEmpty(); 1155 } 1156 1157 @Override 1158 public Set<Type> stuckVars() { 1159 return stuckVars; 1160 } 1161 1162 @Override 1163 public Set<Type> depVars() { 1164 return depVars; 1165 } 1166 1167 public CheckStuckPolicy(ResultInfo resultInfo, DeferredType dt) { 1168 this.pt = resultInfo.pt; 1169 this.inferenceContext = resultInfo.checkContext.inferenceContext(); 1170 scan(dt.tree); 1171 if (!stuckVars.isEmpty()) { 1172 resultInfo.checkContext.inferenceContext() 1173 .addFreeTypeListener(List.from(stuckVars), this); 1174 } 1175 } 1176 1177 @Override 1178 public void typesInferred(InferenceContext inferenceContext) { 1179 stuckVars.clear(); 1180 } 1181 1182 @Override 1183 public void visitLambda(JCLambda tree) { 1184 if (inferenceContext.inferenceVars().contains(pt)) { 1185 stuckVars.add(pt); 1186 } 1187 if (!types.isFunctionalInterface(pt)) { 1188 return; 1189 } 1190 Type descType = types.findDescriptorType(pt); 1191 List<Type> freeArgVars = inferenceContext.freeVarsIn(descType.getParameterTypes()); 1192 if (tree.paramKind == JCLambda.ParameterKind.IMPLICIT && 1193 freeArgVars.nonEmpty()) { 1194 stuckVars.addAll(freeArgVars); 1195 depVars.addAll(inferenceContext.freeVarsIn(descType.getReturnType())); 1196 } 1197 scanLambdaBody(tree, descType.getReturnType()); 1198 } 1199 1200 @Override 1201 public void visitReference(JCMemberReference tree) { 1202 scan(tree.expr); 1203 if (inferenceContext.inferenceVars().contains(pt)) { 1204 stuckVars.add(pt); 1205 return; 1206 } 1207 if (!types.isFunctionalInterface(pt)) { 1208 return; 1209 } 1210 1211 Type descType = types.findDescriptorType(pt); 1212 List<Type> freeArgVars = inferenceContext.freeVarsIn(descType.getParameterTypes()); 1213 if (freeArgVars.nonEmpty() && 1214 tree.getOverloadKind() != JCMemberReference.OverloadKind.UNOVERLOADED) { 1215 stuckVars.addAll(freeArgVars); 1216 depVars.addAll(inferenceContext.freeVarsIn(descType.getReturnType())); 1217 } 1218 } 1219 1220 void scanLambdaBody(JCLambda lambda, final Type pt) { 1221 if (lambda.getBodyKind() == JCTree.JCLambda.BodyKind.EXPRESSION) { 1222 Type prevPt = this.pt; 1223 try { 1224 this.pt = pt; 1225 scan(lambda.body); 1226 } finally { 1227 this.pt = prevPt; 1228 } 1229 } else { 1230 LambdaReturnScanner lambdaScanner = new LambdaReturnScanner() { 1231 @Override 1232 public void visitReturn(JCReturn tree) { 1233 if (tree.expr != null) { 1234 Type prevPt = CheckStuckPolicy.this.pt; 1235 try { 1236 CheckStuckPolicy.this.pt = pt; 1237 CheckStuckPolicy.this.scan(tree.expr); 1238 } finally { 1239 CheckStuckPolicy.this.pt = prevPt; 1240 } 1241 } 1242 } 1243 }; 1244 lambdaScanner.scan(lambda.body); 1245 } 1246 } 1247 } 1248 1249 /** 1250 * This visitor is used to check that structural expressions conform 1251 * to their target - this step is required as inference could end up 1252 * inferring types that make some of the nested expressions incompatible 1253 * with their corresponding instantiated target 1254 */ 1255 class OverloadStuckPolicy extends CheckStuckPolicy implements DeferredStuckPolicy { 1256 1257 boolean stuck; 1258 1259 @Override 1260 public boolean isStuck() { 1261 return super.isStuck() || stuck; 1262 } 1263 1264 public OverloadStuckPolicy(ResultInfo resultInfo, DeferredType dt) { 1265 super(resultInfo, dt); 1266 } 1267 1268 @Override 1269 public void visitLambda(JCLambda tree) { 1270 super.visitLambda(tree); 1271 if (tree.paramKind == JCLambda.ParameterKind.IMPLICIT) { 1272 stuck = true; 1273 } 1274 } 1275 1276 @Override 1277 public void visitReference(JCMemberReference tree) { 1278 super.visitReference(tree); 1279 if (tree.getOverloadKind() != JCMemberReference.OverloadKind.UNOVERLOADED) { 1280 stuck = true; 1281 } 1282 } 1283 } 1284 1285 /** 1286 * Mode of attribution (used in AttrContext). 1287 */ 1288 enum AttributionMode { 1289 /**Normal, non-speculative, attribution.*/ 1290 FULL(false), 1291 /**Speculative attribution on behalf of an Analyzer.*/ 1292 ANALYZER(true), 1293 /**Speculative attribution.*/ 1294 SPECULATIVE(true); 1295 1296 AttributionMode(boolean isSpeculative) { 1297 this.isSpeculative = isSpeculative; 1298 } 1299 1300 boolean isSpeculative() { 1301 return isSpeculative; 1302 } 1303 1304 final boolean isSpeculative; 1305 } 1306 }