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 }