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