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 constraints are too tight for progress 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 }