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