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