src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java

Fri, 02 May 2014 01:25:26 +0100

author
vromero
date
Fri, 02 May 2014 01:25:26 +0100
changeset 2382
14979dd5e034
parent 2370
acd64168cf8b
child 2410
e64bb2f5f0cf
permissions
-rw-r--r--

8030741: Inference: implement eager resolution of return types, consistent with JDK-8028800
Reviewed-by: dlsmith, jjg

     1 /*
     2  * Copyright (c) 2012, 2014, 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  */
    26 package com.sun.tools.javac.comp;
    28 import com.sun.source.tree.LambdaExpressionTree.BodyKind;
    29 import com.sun.tools.javac.code.*;
    30 import com.sun.tools.javac.tree.*;
    31 import com.sun.tools.javac.util.*;
    32 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
    33 import com.sun.tools.javac.code.Symbol.*;
    34 import com.sun.tools.javac.code.Type.*;
    35 import com.sun.tools.javac.comp.Attr.ResultInfo;
    36 import com.sun.tools.javac.comp.Infer.InferenceContext;
    37 import com.sun.tools.javac.comp.Resolve.MethodResolutionPhase;
    38 import com.sun.tools.javac.tree.JCTree.*;
    40 import java.util.ArrayList;
    41 import java.util.Collections;
    42 import java.util.EnumSet;
    43 import java.util.LinkedHashMap;
    44 import java.util.LinkedHashSet;
    45 import java.util.Map;
    46 import java.util.Set;
    47 import java.util.WeakHashMap;
    49 import static com.sun.tools.javac.code.Kinds.VAL;
    50 import static com.sun.tools.javac.code.TypeTag.*;
    51 import static com.sun.tools.javac.tree.JCTree.Tag.*;
    53 /**
    54  * This is an helper class that is used to perform deferred type-analysis.
    55  * Each time a poly expression occurs in argument position, javac attributes it
    56  * with a temporary 'deferred type' that is checked (possibly multiple times)
    57  * against an expected formal type.
    58  *
    59  *  <p><b>This is NOT part of any supported API.
    60  *  If you write code that depends on this, you do so at your own risk.
    61  *  This code and its internal interfaces are subject to change or
    62  *  deletion without notice.</b>
    63  */
    64 public class DeferredAttr extends JCTree.Visitor {
    65     protected static final Context.Key<DeferredAttr> deferredAttrKey =
    66         new Context.Key<DeferredAttr>();
    68     final Attr attr;
    69     final Check chk;
    70     final JCDiagnostic.Factory diags;
    71     final Enter enter;
    72     final Infer infer;
    73     final Resolve rs;
    74     final Log log;
    75     final Symtab syms;
    76     final TreeMaker make;
    77     final Types types;
    78     final Flow flow;
    79     final Names names;
    81     public static DeferredAttr instance(Context context) {
    82         DeferredAttr instance = context.get(deferredAttrKey);
    83         if (instance == null)
    84             instance = new DeferredAttr(context);
    85         return instance;
    86     }
    88     protected DeferredAttr(Context context) {
    89         context.put(deferredAttrKey, this);
    90         attr = Attr.instance(context);
    91         chk = Check.instance(context);
    92         diags = JCDiagnostic.Factory.instance(context);
    93         enter = Enter.instance(context);
    94         infer = Infer.instance(context);
    95         rs = Resolve.instance(context);
    96         log = Log.instance(context);
    97         syms = Symtab.instance(context);
    98         make = TreeMaker.instance(context);
    99         types = Types.instance(context);
   100         flow = Flow.instance(context);
   101         names = Names.instance(context);
   102         stuckTree = make.Ident(names.empty).setType(Type.stuckType);
   103         emptyDeferredAttrContext =
   104             new DeferredAttrContext(AttrMode.CHECK, null, MethodResolutionPhase.BOX, infer.emptyContext, null, null) {
   105                 @Override
   106                 void addDeferredAttrNode(DeferredType dt, ResultInfo ri, DeferredStuckPolicy deferredStuckPolicy) {
   107                     Assert.error("Empty deferred context!");
   108                 }
   109                 @Override
   110                 void complete() {
   111                     Assert.error("Empty deferred context!");
   112                 }
   114                 @Override
   115                 public String toString() {
   116                     return "Empty deferred context!";
   117                 }
   118             };
   119     }
   121     /** shared tree for stuck expressions */
   122     final JCTree stuckTree;
   124     /**
   125      * This type represents a deferred type. A deferred type starts off with
   126      * no information on the underlying expression type. Such info needs to be
   127      * discovered through type-checking the deferred type against a target-type.
   128      * Every deferred type keeps a pointer to the AST node from which it originated.
   129      */
   130     public class DeferredType extends Type {
   132         public JCExpression tree;
   133         Env<AttrContext> env;
   134         AttrMode mode;
   135         SpeculativeCache speculativeCache;
   137         DeferredType(JCExpression tree, Env<AttrContext> env) {
   138             super(null);
   139             this.tree = tree;
   140             this.env = attr.copyEnv(env);
   141             this.speculativeCache = new SpeculativeCache();
   142         }
   144         @Override
   145         public TypeTag getTag() {
   146             return DEFERRED;
   147         }
   149         @Override
   150         public String toString() {
   151             return "DeferredType";
   152         }
   154         /**
   155          * A speculative cache is used to keep track of all overload resolution rounds
   156          * that triggered speculative attribution on a given deferred type. Each entry
   157          * stores a pointer to the speculative tree and the resolution phase in which the entry
   158          * has been added.
   159          */
   160         class SpeculativeCache {
   162             private Map<Symbol, List<Entry>> cache =
   163                     new WeakHashMap<Symbol, List<Entry>>();
   165             class Entry {
   166                 JCTree speculativeTree;
   167                 ResultInfo resultInfo;
   169                 public Entry(JCTree speculativeTree, ResultInfo resultInfo) {
   170                     this.speculativeTree = speculativeTree;
   171                     this.resultInfo = resultInfo;
   172                 }
   174                 boolean matches(MethodResolutionPhase phase) {
   175                     return resultInfo.checkContext.deferredAttrContext().phase == phase;
   176                 }
   177             }
   179             /**
   180              * Retrieve a speculative cache entry corresponding to given symbol
   181              * and resolution phase
   182              */
   183             Entry get(Symbol msym, MethodResolutionPhase phase) {
   184                 List<Entry> entries = cache.get(msym);
   185                 if (entries == null) return null;
   186                 for (Entry e : entries) {
   187                     if (e.matches(phase)) return e;
   188                 }
   189                 return null;
   190             }
   192             /**
   193              * Stores a speculative cache entry corresponding to given symbol
   194              * and resolution phase
   195              */
   196             void put(JCTree speculativeTree, ResultInfo resultInfo) {
   197                 Symbol msym = resultInfo.checkContext.deferredAttrContext().msym;
   198                 List<Entry> entries = cache.get(msym);
   199                 if (entries == null) {
   200                     entries = List.nil();
   201                 }
   202                 cache.put(msym, entries.prepend(new Entry(speculativeTree, resultInfo)));
   203             }
   204         }
   206         /**
   207          * Get the type that has been computed during a speculative attribution round
   208          */
   209         Type speculativeType(Symbol msym, MethodResolutionPhase phase) {
   210             SpeculativeCache.Entry e = speculativeCache.get(msym, phase);
   211             return e != null ? e.speculativeTree.type : Type.noType;
   212         }
   214         /**
   215          * Check a deferred type against a potential target-type. Depending on
   216          * the current attribution mode, a normal vs. speculative attribution
   217          * round is performed on the underlying AST node. There can be only one
   218          * speculative round for a given target method symbol; moreover, a normal
   219          * attribution round must follow one or more speculative rounds.
   220          */
   221         Type check(ResultInfo resultInfo) {
   222             DeferredStuckPolicy deferredStuckPolicy;
   223             if (resultInfo.pt.hasTag(NONE) || resultInfo.pt.isErroneous()) {
   224                 deferredStuckPolicy = dummyStuckPolicy;
   225             } else if (resultInfo.checkContext.deferredAttrContext().mode == AttrMode.SPECULATIVE) {
   226                 deferredStuckPolicy = new OverloadStuckPolicy(resultInfo, this);
   227             } else {
   228                 deferredStuckPolicy = new CheckStuckPolicy(resultInfo, this);
   229             }
   230             return check(resultInfo, deferredStuckPolicy, basicCompleter);
   231         }
   233         private Type check(ResultInfo resultInfo, DeferredStuckPolicy deferredStuckPolicy,
   234                 DeferredTypeCompleter deferredTypeCompleter) {
   235             DeferredAttrContext deferredAttrContext =
   236                     resultInfo.checkContext.deferredAttrContext();
   237             Assert.check(deferredAttrContext != emptyDeferredAttrContext);
   238             if (deferredStuckPolicy.isStuck()) {
   239                 deferredAttrContext.addDeferredAttrNode(this, resultInfo, deferredStuckPolicy);
   240                 return Type.noType;
   241             } else {
   242                 try {
   243                     return deferredTypeCompleter.complete(this, resultInfo, deferredAttrContext);
   244                 } finally {
   245                     mode = deferredAttrContext.mode;
   246                 }
   247             }
   248         }
   249     }
   251     /**
   252      * A completer for deferred types. Defines an entry point for type-checking
   253      * a deferred type.
   254      */
   255     interface DeferredTypeCompleter {
   256         /**
   257          * Entry point for type-checking a deferred type. Depending on the
   258          * circumstances, type-checking could amount to full attribution
   259          * or partial structural check (aka potential applicability).
   260          */
   261         Type complete(DeferredType dt, ResultInfo resultInfo, DeferredAttrContext deferredAttrContext);
   262     }
   265     /**
   266      * A basic completer for deferred types. This completer type-checks a deferred type
   267      * using attribution; depending on the attribution mode, this could be either standard
   268      * or speculative attribution.
   269      */
   270     DeferredTypeCompleter basicCompleter = new DeferredTypeCompleter() {
   271         public Type complete(DeferredType dt, ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) {
   272             switch (deferredAttrContext.mode) {
   273                 case SPECULATIVE:
   274                     //Note: if a symbol is imported twice we might do two identical
   275                     //speculative rounds...
   276                     Assert.check(dt.mode == null || dt.mode == AttrMode.SPECULATIVE);
   277                     JCTree speculativeTree = attribSpeculative(dt.tree, dt.env, resultInfo);
   278                     dt.speculativeCache.put(speculativeTree, resultInfo);
   279                     return speculativeTree.type;
   280                 case CHECK:
   281                     Assert.check(dt.mode != null);
   282                     return attr.attribTree(dt.tree, dt.env, resultInfo);
   283             }
   284             Assert.error();
   285             return null;
   286         }
   287     };
   289     DeferredTypeCompleter dummyCompleter = new DeferredTypeCompleter() {
   290         public Type complete(DeferredType dt, ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) {
   291             Assert.check(deferredAttrContext.mode == AttrMode.CHECK);
   292             return dt.tree.type = Type.stuckType;
   293         }
   294     };
   296     /**
   297      * Policy for detecting stuck expressions. Different criteria might cause
   298      * an expression to be judged as stuck, depending on whether the check
   299      * is performed during overload resolution or after most specific.
   300      */
   301     interface DeferredStuckPolicy {
   302         /**
   303          * Has the policy detected that a given expression should be considered stuck?
   304          */
   305         boolean isStuck();
   306         /**
   307          * Get the set of inference variables a given expression depends upon.
   308          */
   309         Set<Type> stuckVars();
   310         /**
   311          * Get the set of inference variables which might get new constraints
   312          * if a given expression is being type-checked.
   313          */
   314         Set<Type> depVars();
   315     }
   317     /**
   318      * Basic stuck policy; an expression is never considered to be stuck.
   319      */
   320     DeferredStuckPolicy dummyStuckPolicy = new DeferredStuckPolicy() {
   321         @Override
   322         public boolean isStuck() {
   323             return false;
   324         }
   325         @Override
   326         public Set<Type> stuckVars() {
   327             return Collections.emptySet();
   328         }
   329         @Override
   330         public Set<Type> depVars() {
   331             return Collections.emptySet();
   332         }
   333     };
   335     /**
   336      * The 'mode' in which the deferred type is to be type-checked
   337      */
   338     public enum AttrMode {
   339         /**
   340          * A speculative type-checking round is used during overload resolution
   341          * mainly to generate constraints on inference variables. Side-effects
   342          * arising from type-checking the expression associated with the deferred
   343          * type are reversed after the speculative round finishes. This means the
   344          * expression tree will be left in a blank state.
   345          */
   346         SPECULATIVE,
   347         /**
   348          * This is the plain type-checking mode. Produces side-effects on the underlying AST node
   349          */
   350         CHECK;
   351     }
   353     /**
   354      * Routine that performs speculative type-checking; the input AST node is
   355      * cloned (to avoid side-effects cause by Attr) and compiler state is
   356      * restored after type-checking. All diagnostics (but critical ones) are
   357      * disabled during speculative type-checking.
   358      */
   359     JCTree attribSpeculative(JCTree tree, Env<AttrContext> env, ResultInfo resultInfo) {
   360         final JCTree newTree = new TreeCopier<Object>(make).copy(tree);
   361         Env<AttrContext> speculativeEnv = env.dup(newTree, env.info.dup(env.info.scope.dupUnshared()));
   362         speculativeEnv.info.scope.owner = env.info.scope.owner;
   363         Log.DeferredDiagnosticHandler deferredDiagnosticHandler =
   364                 new Log.DeferredDiagnosticHandler(log, new Filter<JCDiagnostic>() {
   365             public boolean accepts(final JCDiagnostic d) {
   366                 class PosScanner extends TreeScanner {
   367                     boolean found = false;
   369                     @Override
   370                     public void scan(JCTree tree) {
   371                         if (tree != null &&
   372                                 tree.pos() == d.getDiagnosticPosition()) {
   373                             found = true;
   374                         }
   375                         super.scan(tree);
   376                     }
   377                 };
   378                 PosScanner posScanner = new PosScanner();
   379                 posScanner.scan(newTree);
   380                 return posScanner.found;
   381             }
   382         });
   383         try {
   384             attr.attribTree(newTree, speculativeEnv, resultInfo);
   385             unenterScanner.scan(newTree);
   386             return newTree;
   387         } finally {
   388             unenterScanner.scan(newTree);
   389             log.popDiagnosticHandler(deferredDiagnosticHandler);
   390         }
   391     }
   392     //where
   393         protected UnenterScanner unenterScanner = new UnenterScanner();
   395         class UnenterScanner extends TreeScanner {
   396             @Override
   397             public void visitClassDef(JCClassDecl tree) {
   398                 ClassSymbol csym = tree.sym;
   399                 //if something went wrong during method applicability check
   400                 //it is possible that nested expressions inside argument expression
   401                 //are left unchecked - in such cases there's nothing to clean up.
   402                 if (csym == null) return;
   403                 enter.typeEnvs.remove(csym);
   404                 chk.compiled.remove(csym.flatname);
   405                 syms.classes.remove(csym.flatname);
   406                 super.visitClassDef(tree);
   407             }
   408         }
   410     /**
   411      * A deferred context is created on each method check. A deferred context is
   412      * used to keep track of information associated with the method check, such as
   413      * the symbol of the method being checked, the overload resolution phase,
   414      * the kind of attribution mode to be applied to deferred types and so forth.
   415      * As deferred types are processed (by the method check routine) stuck AST nodes
   416      * are added (as new deferred attribution nodes) to this context. The complete()
   417      * routine makes sure that all pending nodes are properly processed, by
   418      * progressively instantiating all inference variables on which one or more
   419      * deferred attribution node is stuck.
   420      */
   421     class DeferredAttrContext {
   423         /** attribution mode */
   424         final AttrMode mode;
   426         /** symbol of the method being checked */
   427         final Symbol msym;
   429         /** method resolution step */
   430         final Resolve.MethodResolutionPhase phase;
   432         /** inference context */
   433         final InferenceContext inferenceContext;
   435         /** parent deferred context */
   436         final DeferredAttrContext parent;
   438         /** Warner object to report warnings */
   439         final Warner warn;
   441         /** list of deferred attribution nodes to be processed */
   442         ArrayList<DeferredAttrNode> deferredAttrNodes = new ArrayList<DeferredAttrNode>();
   444         DeferredAttrContext(AttrMode mode, Symbol msym, MethodResolutionPhase phase,
   445                 InferenceContext inferenceContext, DeferredAttrContext parent, Warner warn) {
   446             this.mode = mode;
   447             this.msym = msym;
   448             this.phase = phase;
   449             this.parent = parent;
   450             this.warn = warn;
   451             this.inferenceContext = inferenceContext;
   452         }
   454         /**
   455          * Adds a node to the list of deferred attribution nodes - used by Resolve.rawCheckArgumentsApplicable
   456          * Nodes added this way act as 'roots' for the out-of-order method checking process.
   457          */
   458         void addDeferredAttrNode(final DeferredType dt, ResultInfo resultInfo,
   459                 DeferredStuckPolicy deferredStuckPolicy) {
   460             deferredAttrNodes.add(new DeferredAttrNode(dt, resultInfo, deferredStuckPolicy));
   461         }
   463         /**
   464          * Incrementally process all nodes, by skipping 'stuck' nodes and attributing
   465          * 'unstuck' ones. If at any point no progress can be made (no 'unstuck' nodes)
   466          * some inference variable might get eagerly instantiated so that all nodes
   467          * can be type-checked.
   468          */
   469         void complete() {
   470             while (!deferredAttrNodes.isEmpty()) {
   471                 Map<Type, Set<Type>> depVarsMap = new LinkedHashMap<Type, Set<Type>>();
   472                 List<Type> stuckVars = List.nil();
   473                 boolean progress = false;
   474                 //scan a defensive copy of the node list - this is because a deferred
   475                 //attribution round can add new nodes to the list
   476                 for (DeferredAttrNode deferredAttrNode : List.from(deferredAttrNodes)) {
   477                     if (!deferredAttrNode.process(this)) {
   478                         List<Type> restStuckVars =
   479                                 List.from(deferredAttrNode.deferredStuckPolicy.stuckVars())
   480                                 .intersect(inferenceContext.restvars());
   481                         stuckVars = stuckVars.prependList(restStuckVars);
   482                         //update dependency map
   483                         for (Type t : List.from(deferredAttrNode.deferredStuckPolicy.depVars())
   484                                 .intersect(inferenceContext.restvars())) {
   485                             Set<Type> prevDeps = depVarsMap.get(t);
   486                             if (prevDeps == null) {
   487                                 prevDeps = new LinkedHashSet<Type>();
   488                                 depVarsMap.put(t, prevDeps);
   489                             }
   490                             prevDeps.addAll(restStuckVars);
   491                         }
   492                     } else {
   493                         deferredAttrNodes.remove(deferredAttrNode);
   494                         progress = true;
   495                     }
   496                 }
   497                 if (!progress) {
   498                     DeferredAttrContext dac = this;
   499                     while (dac != emptyDeferredAttrContext) {
   500                         if (dac.mode == AttrMode.SPECULATIVE) {
   501                             //unsticking does not take place during overload
   502                             break;
   503                         }
   504                         dac = dac.parent;
   505                     }
   506                     //remove all variables that have already been instantiated
   507                     //from the list of stuck variables
   508                     try {
   509                         inferenceContext.solveAny(stuckVars, depVarsMap, warn);
   510                         inferenceContext.notifyChange();
   511                     } catch (Infer.GraphStrategy.NodeNotFoundException ex) {
   512                         //this means that we are in speculative mode and the
   513                         //set of contraints are too tight for progess to be made.
   514                         //Just leave the remaining expressions as stuck.
   515                         break;
   516                     }
   517                 }
   518             }
   519         }
   520     }
   522     /**
   523      * Class representing a deferred attribution node. It keeps track of
   524      * a deferred type, along with the expected target type information.
   525      */
   526     class DeferredAttrNode {
   528         /** underlying deferred type */
   529         DeferredType dt;
   531         /** underlying target type information */
   532         ResultInfo resultInfo;
   534         /** stuck policy associated with this node */
   535         DeferredStuckPolicy deferredStuckPolicy;
   537         DeferredAttrNode(DeferredType dt, ResultInfo resultInfo, DeferredStuckPolicy deferredStuckPolicy) {
   538             this.dt = dt;
   539             this.resultInfo = resultInfo;
   540             this.deferredStuckPolicy = deferredStuckPolicy;
   541         }
   543         /**
   544          * Process a deferred attribution node.
   545          * Invariant: a stuck node cannot be processed.
   546          */
   547         @SuppressWarnings("fallthrough")
   548         boolean process(final DeferredAttrContext deferredAttrContext) {
   549             switch (deferredAttrContext.mode) {
   550                 case SPECULATIVE:
   551                     if (deferredStuckPolicy.isStuck()) {
   552                         dt.check(resultInfo, dummyStuckPolicy, new StructuralStuckChecker());
   553                         return true;
   554                     } else {
   555                         Assert.error("Cannot get here");
   556                     }
   557                 case CHECK:
   558                     if (deferredStuckPolicy.isStuck()) {
   559                         //stuck expression - see if we can propagate
   560                         if (deferredAttrContext.parent != emptyDeferredAttrContext &&
   561                                 Type.containsAny(deferredAttrContext.parent.inferenceContext.inferencevars,
   562                                         List.from(deferredStuckPolicy.stuckVars()))) {
   563                             deferredAttrContext.parent.addDeferredAttrNode(dt,
   564                                     resultInfo.dup(new Check.NestedCheckContext(resultInfo.checkContext) {
   565                                 @Override
   566                                 public InferenceContext inferenceContext() {
   567                                     return deferredAttrContext.parent.inferenceContext;
   568                                 }
   569                                 @Override
   570                                 public DeferredAttrContext deferredAttrContext() {
   571                                     return deferredAttrContext.parent;
   572                                 }
   573                             }), deferredStuckPolicy);
   574                             dt.tree.type = Type.stuckType;
   575                             return true;
   576                         } else {
   577                             return false;
   578                         }
   579                     } else {
   580                         ResultInfo instResultInfo =
   581                                 resultInfo.dup(deferredAttrContext.inferenceContext.asInstType(resultInfo.pt));
   582                         dt.check(instResultInfo, dummyStuckPolicy, basicCompleter);
   583                         return true;
   584                     }
   585                 default:
   586                     throw new AssertionError("Bad mode");
   587             }
   588         }
   590         /**
   591          * Structural checker for stuck expressions
   592          */
   593         class StructuralStuckChecker extends TreeScanner implements DeferredTypeCompleter {
   595             ResultInfo resultInfo;
   596             InferenceContext inferenceContext;
   597             Env<AttrContext> env;
   599             public Type complete(DeferredType dt, ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) {
   600                 this.resultInfo = resultInfo;
   601                 this.inferenceContext = deferredAttrContext.inferenceContext;
   602                 this.env = dt.env;
   603                 dt.tree.accept(this);
   604                 dt.speculativeCache.put(stuckTree, resultInfo);
   605                 return Type.noType;
   606             }
   608             @Override
   609             public void visitLambda(JCLambda tree) {
   610                 Check.CheckContext checkContext = resultInfo.checkContext;
   611                 Type pt = resultInfo.pt;
   612                 if (!inferenceContext.inferencevars.contains(pt)) {
   613                     //must be a functional descriptor
   614                     Type descriptorType = null;
   615                     try {
   616                         descriptorType = types.findDescriptorType(pt);
   617                     } catch (Types.FunctionDescriptorLookupError ex) {
   618                         checkContext.report(null, ex.getDiagnostic());
   619                     }
   621                     if (descriptorType.getParameterTypes().length() != tree.params.length()) {
   622                         checkContext.report(tree,
   623                                 diags.fragment("incompatible.arg.types.in.lambda"));
   624                     }
   626                     Type currentReturnType = descriptorType.getReturnType();
   627                     boolean returnTypeIsVoid = currentReturnType.hasTag(VOID);
   628                     if (tree.getBodyKind() == BodyKind.EXPRESSION) {
   629                         boolean isExpressionCompatible = !returnTypeIsVoid ||
   630                             TreeInfo.isExpressionStatement((JCExpression)tree.getBody());
   631                         if (!isExpressionCompatible) {
   632                             resultInfo.checkContext.report(tree.pos(),
   633                                 diags.fragment("incompatible.ret.type.in.lambda",
   634                                     diags.fragment("missing.ret.val", currentReturnType)));
   635                         }
   636                     } else {
   637                         LambdaBodyStructChecker lambdaBodyChecker =
   638                                 new LambdaBodyStructChecker();
   640                         tree.body.accept(lambdaBodyChecker);
   641                         boolean isVoidCompatible = lambdaBodyChecker.isVoidCompatible;
   643                         if (returnTypeIsVoid) {
   644                             if (!isVoidCompatible) {
   645                                 resultInfo.checkContext.report(tree.pos(),
   646                                     diags.fragment("unexpected.ret.val"));
   647                             }
   648                         } else {
   649                             boolean isValueCompatible = lambdaBodyChecker.isPotentiallyValueCompatible
   650                                 && !canLambdaBodyCompleteNormally(tree);
   651                             if (!isValueCompatible && !isVoidCompatible) {
   652                                 log.error(tree.body.pos(),
   653                                     "lambda.body.neither.value.nor.void.compatible");
   654                             }
   656                             if (!isValueCompatible) {
   657                                 resultInfo.checkContext.report(tree.pos(),
   658                                     diags.fragment("incompatible.ret.type.in.lambda",
   659                                         diags.fragment("missing.ret.val", currentReturnType)));
   660                             }
   661                         }
   662                     }
   663                 }
   664             }
   666             boolean canLambdaBodyCompleteNormally(JCLambda tree) {
   667                 JCLambda newTree = new TreeCopier<>(make).copy(tree);
   668                 /* attr.lambdaEnv will create a meaningful env for the
   669                  * lambda expression. This is specially useful when the
   670                  * lambda is used as the init of a field. But we need to
   671                  * remove any added symbol.
   672                  */
   673                 Env<AttrContext> localEnv = attr.lambdaEnv(newTree, env);
   674                 try {
   675                     List<JCVariableDecl> tmpParams = newTree.params;
   676                     while (tmpParams.nonEmpty()) {
   677                         tmpParams.head.vartype = make.at(tmpParams.head).Type(syms.errType);
   678                         tmpParams = tmpParams.tail;
   679                     }
   681                     attr.attribStats(newTree.params, localEnv);
   683                     /* set pt to Type.noType to avoid generating any bound
   684                      * which may happen if lambda's return type is an
   685                      * inference variable
   686                      */
   687                     Attr.ResultInfo bodyResultInfo = attr.new ResultInfo(VAL, Type.noType);
   688                     localEnv.info.returnResult = bodyResultInfo;
   690                     // discard any log output
   691                     Log.DiagnosticHandler diagHandler = new Log.DiscardDiagnosticHandler(log);
   692                     try {
   693                         JCBlock body = (JCBlock)newTree.body;
   694                         /* we need to attribute the lambda body before
   695                          * doing the aliveness analysis. This is because
   696                          * constant folding occurs during attribution
   697                          * and the reachability of some statements depends
   698                          * on constant values, for example:
   699                          *
   700                          *     while (true) {...}
   701                          */
   702                         attr.attribStats(body.stats, localEnv);
   704                         attr.preFlow(newTree);
   705                         /* make an aliveness / reachability analysis of the lambda
   706                          * to determine if it can complete normally
   707                          */
   708                         flow.analyzeLambda(localEnv, newTree, make, true);
   709                     } finally {
   710                         log.popDiagnosticHandler(diagHandler);
   711                     }
   712                     return newTree.canCompleteNormally;
   713                 } finally {
   714                     JCBlock body = (JCBlock)newTree.body;
   715                     unenterScanner.scan(body.stats);
   716                     localEnv.info.scope.leave();
   717                 }
   718             }
   720             @Override
   721             public void visitNewClass(JCNewClass tree) {
   722                 //do nothing
   723             }
   725             @Override
   726             public void visitApply(JCMethodInvocation tree) {
   727                 //do nothing
   728             }
   730             @Override
   731             public void visitReference(JCMemberReference tree) {
   732                 Check.CheckContext checkContext = resultInfo.checkContext;
   733                 Type pt = resultInfo.pt;
   734                 if (!inferenceContext.inferencevars.contains(pt)) {
   735                     try {
   736                         types.findDescriptorType(pt);
   737                     } catch (Types.FunctionDescriptorLookupError ex) {
   738                         checkContext.report(null, ex.getDiagnostic());
   739                     }
   740                     Env<AttrContext> localEnv = env.dup(tree);
   741                     JCExpression exprTree = (JCExpression)attribSpeculative(tree.getQualifierExpression(), localEnv,
   742                             attr.memberReferenceQualifierResult(tree));
   743                     ListBuffer<Type> argtypes = new ListBuffer<>();
   744                     for (Type t : types.findDescriptorType(pt).getParameterTypes()) {
   745                         argtypes.append(Type.noType);
   746                     }
   747                     JCMemberReference mref2 = new TreeCopier<Void>(make).copy(tree);
   748                     mref2.expr = exprTree;
   749                     Symbol lookupSym =
   750                             rs.resolveMemberReferenceByArity(localEnv, mref2, exprTree.type,
   751                                 tree.name, argtypes.toList(), inferenceContext);
   752                     switch (lookupSym.kind) {
   753                         //note: as argtypes are erroneous types, type-errors must
   754                         //have been caused by arity mismatch
   755                         case Kinds.ABSENT_MTH:
   756                         case Kinds.WRONG_MTH:
   757                         case Kinds.WRONG_MTHS:
   758                         case Kinds.WRONG_STATICNESS:
   759                            checkContext.report(tree, diags.fragment("incompatible.arg.types.in.mref"));
   760                     }
   761                 }
   762             }
   763         }
   765         /* This visitor looks for return statements, its analysis will determine if
   766          * a lambda body is void or value compatible. We must analyze return
   767          * statements contained in the lambda body only, thus any return statement
   768          * contained in an inner class or inner lambda body, should be ignored.
   769          */
   770         class LambdaBodyStructChecker extends TreeScanner {
   771             boolean isVoidCompatible = true;
   772             boolean isPotentiallyValueCompatible = true;
   774             @Override
   775             public void visitClassDef(JCClassDecl tree) {
   776                 // do nothing
   777             }
   779             @Override
   780             public void visitLambda(JCLambda tree) {
   781                 // do nothing
   782             }
   784             @Override
   785             public void visitNewClass(JCNewClass tree) {
   786                 // do nothing
   787             }
   789             @Override
   790             public void visitReturn(JCReturn tree) {
   791                 if (tree.expr != null) {
   792                     isVoidCompatible = false;
   793                 } else {
   794                     isPotentiallyValueCompatible = false;
   795                 }
   796             }
   797         }
   798     }
   800     /** an empty deferred attribution context - all methods throw exceptions */
   801     final DeferredAttrContext emptyDeferredAttrContext;
   803     /**
   804      * Map a list of types possibly containing one or more deferred types
   805      * into a list of ordinary types. Each deferred type D is mapped into a type T,
   806      * where T is computed by retrieving the type that has already been
   807      * computed for D during a previous deferred attribution round of the given kind.
   808      */
   809     class DeferredTypeMap extends Type.Mapping {
   811         DeferredAttrContext deferredAttrContext;
   813         protected DeferredTypeMap(AttrMode mode, Symbol msym, MethodResolutionPhase phase) {
   814             super(String.format("deferredTypeMap[%s]", mode));
   815             this.deferredAttrContext = new DeferredAttrContext(mode, msym, phase,
   816                     infer.emptyContext, emptyDeferredAttrContext, types.noWarnings);
   817         }
   819         @Override
   820         public Type apply(Type t) {
   821             if (!t.hasTag(DEFERRED)) {
   822                 return t.map(this);
   823             } else {
   824                 DeferredType dt = (DeferredType)t;
   825                 return typeOf(dt);
   826             }
   827         }
   829         protected Type typeOf(DeferredType dt) {
   830             switch (deferredAttrContext.mode) {
   831                 case CHECK:
   832                     return dt.tree.type == null ? Type.noType : dt.tree.type;
   833                 case SPECULATIVE:
   834                     return dt.speculativeType(deferredAttrContext.msym, deferredAttrContext.phase);
   835             }
   836             Assert.error();
   837             return null;
   838         }
   839     }
   841     /**
   842      * Specialized recovery deferred mapping.
   843      * Each deferred type D is mapped into a type T, where T is computed either by
   844      * (i) retrieving the type that has already been computed for D during a previous
   845      * attribution round (as before), or (ii) by synthesizing a new type R for D
   846      * (the latter step is useful in a recovery scenario).
   847      */
   848     public class RecoveryDeferredTypeMap extends DeferredTypeMap {
   850         public RecoveryDeferredTypeMap(AttrMode mode, Symbol msym, MethodResolutionPhase phase) {
   851             super(mode, msym, phase != null ? phase : MethodResolutionPhase.BOX);
   852         }
   854         @Override
   855         protected Type typeOf(DeferredType dt) {
   856             Type owntype = super.typeOf(dt);
   857             return owntype == Type.noType ?
   858                         recover(dt) : owntype;
   859         }
   861         /**
   862          * Synthesize a type for a deferred type that hasn't been previously
   863          * reduced to an ordinary type. Functional deferred types and conditionals
   864          * are mapped to themselves, in order to have a richer diagnostic
   865          * representation. Remaining deferred types are attributed using
   866          * a default expected type (j.l.Object).
   867          */
   868         private Type recover(DeferredType dt) {
   869             dt.check(attr.new RecoveryInfo(deferredAttrContext) {
   870                 @Override
   871                 protected Type check(DiagnosticPosition pos, Type found) {
   872                     return chk.checkNonVoid(pos, super.check(pos, found));
   873                 }
   874             });
   875             return super.apply(dt);
   876         }
   877     }
   879     /**
   880      * A special tree scanner that would only visit portions of a given tree.
   881      * The set of nodes visited by the scanner can be customized at construction-time.
   882      */
   883     abstract static class FilterScanner extends TreeScanner {
   885         final Filter<JCTree> treeFilter;
   887         FilterScanner(final Set<JCTree.Tag> validTags) {
   888             this.treeFilter = new Filter<JCTree>() {
   889                 public boolean accepts(JCTree t) {
   890                     return validTags.contains(t.getTag());
   891                 }
   892             };
   893         }
   895         @Override
   896         public void scan(JCTree tree) {
   897             if (tree != null) {
   898                 if (treeFilter.accepts(tree)) {
   899                     super.scan(tree);
   900                 } else {
   901                     skip(tree);
   902                 }
   903             }
   904         }
   906         /**
   907          * handler that is executed when a node has been discarded
   908          */
   909         void skip(JCTree tree) {}
   910     }
   912     /**
   913      * A tree scanner suitable for visiting the target-type dependent nodes of
   914      * a given argument expression.
   915      */
   916     static class PolyScanner extends FilterScanner {
   918         PolyScanner() {
   919             super(EnumSet.of(CONDEXPR, PARENS, LAMBDA, REFERENCE));
   920         }
   921     }
   923     /**
   924      * A tree scanner suitable for visiting the target-type dependent nodes nested
   925      * within a lambda expression body.
   926      */
   927     static class LambdaReturnScanner extends FilterScanner {
   929         LambdaReturnScanner() {
   930             super(EnumSet.of(BLOCK, CASE, CATCH, DOLOOP, FOREACHLOOP,
   931                     FORLOOP, RETURN, SYNCHRONIZED, SWITCH, TRY, WHILELOOP));
   932         }
   933     }
   935     /**
   936      * This visitor is used to check that structural expressions conform
   937      * to their target - this step is required as inference could end up
   938      * inferring types that make some of the nested expressions incompatible
   939      * with their corresponding instantiated target
   940      */
   941     class CheckStuckPolicy extends PolyScanner implements DeferredStuckPolicy, Infer.FreeTypeListener {
   943         Type pt;
   944         Infer.InferenceContext inferenceContext;
   945         Set<Type> stuckVars = new LinkedHashSet<Type>();
   946         Set<Type> depVars = new LinkedHashSet<Type>();
   948         @Override
   949         public boolean isStuck() {
   950             return !stuckVars.isEmpty();
   951         }
   953         @Override
   954         public Set<Type> stuckVars() {
   955             return stuckVars;
   956         }
   958         @Override
   959         public Set<Type> depVars() {
   960             return depVars;
   961         }
   963         public CheckStuckPolicy(ResultInfo resultInfo, DeferredType dt) {
   964             this.pt = resultInfo.pt;
   965             this.inferenceContext = resultInfo.checkContext.inferenceContext();
   966             scan(dt.tree);
   967             if (!stuckVars.isEmpty()) {
   968                 resultInfo.checkContext.inferenceContext()
   969                         .addFreeTypeListener(List.from(stuckVars), this);
   970             }
   971         }
   973         @Override
   974         public void typesInferred(InferenceContext inferenceContext) {
   975             stuckVars.clear();
   976         }
   978         @Override
   979         public void visitLambda(JCLambda tree) {
   980             if (inferenceContext.inferenceVars().contains(pt)) {
   981                 stuckVars.add(pt);
   982             }
   983             if (!types.isFunctionalInterface(pt)) {
   984                 return;
   985             }
   986             Type descType = types.findDescriptorType(pt);
   987             List<Type> freeArgVars = inferenceContext.freeVarsIn(descType.getParameterTypes());
   988             if (tree.paramKind == JCLambda.ParameterKind.IMPLICIT &&
   989                     freeArgVars.nonEmpty()) {
   990                 stuckVars.addAll(freeArgVars);
   991                 depVars.addAll(inferenceContext.freeVarsIn(descType.getReturnType()));
   992             }
   993             scanLambdaBody(tree, descType.getReturnType());
   994         }
   996         @Override
   997         public void visitReference(JCMemberReference tree) {
   998             scan(tree.expr);
   999             if (inferenceContext.inferenceVars().contains(pt)) {
  1000                 stuckVars.add(pt);
  1001                 return;
  1003             if (!types.isFunctionalInterface(pt)) {
  1004                 return;
  1007             Type descType = types.findDescriptorType(pt);
  1008             List<Type> freeArgVars = inferenceContext.freeVarsIn(descType.getParameterTypes());
  1009             if (freeArgVars.nonEmpty() &&
  1010                     tree.overloadKind == JCMemberReference.OverloadKind.OVERLOADED) {
  1011                 stuckVars.addAll(freeArgVars);
  1012                 depVars.addAll(inferenceContext.freeVarsIn(descType.getReturnType()));
  1016         void scanLambdaBody(JCLambda lambda, final Type pt) {
  1017             if (lambda.getBodyKind() == JCTree.JCLambda.BodyKind.EXPRESSION) {
  1018                 Type prevPt = this.pt;
  1019                 try {
  1020                     this.pt = pt;
  1021                     scan(lambda.body);
  1022                 } finally {
  1023                     this.pt = prevPt;
  1025             } else {
  1026                 LambdaReturnScanner lambdaScanner = new LambdaReturnScanner() {
  1027                     @Override
  1028                     public void visitReturn(JCReturn tree) {
  1029                         if (tree.expr != null) {
  1030                             Type prevPt = CheckStuckPolicy.this.pt;
  1031                             try {
  1032                                 CheckStuckPolicy.this.pt = pt;
  1033                                 CheckStuckPolicy.this.scan(tree.expr);
  1034                             } finally {
  1035                                 CheckStuckPolicy.this.pt = prevPt;
  1039                 };
  1040                 lambdaScanner.scan(lambda.body);
  1045     /**
  1046      * This visitor is used to check that structural expressions conform
  1047      * to their target - this step is required as inference could end up
  1048      * inferring types that make some of the nested expressions incompatible
  1049      * with their corresponding instantiated target
  1050      */
  1051     class OverloadStuckPolicy extends CheckStuckPolicy implements DeferredStuckPolicy {
  1053         boolean stuck;
  1055         @Override
  1056         public boolean isStuck() {
  1057             return super.isStuck() || stuck;
  1060         public OverloadStuckPolicy(ResultInfo resultInfo, DeferredType dt) {
  1061             super(resultInfo, dt);
  1064         @Override
  1065         public void visitLambda(JCLambda tree) {
  1066             super.visitLambda(tree);
  1067             if (tree.paramKind == JCLambda.ParameterKind.IMPLICIT) {
  1068                 stuck = true;
  1072         @Override
  1073         public void visitReference(JCMemberReference tree) {
  1074             super.visitReference(tree);
  1075             if (tree.overloadKind == JCMemberReference.OverloadKind.OVERLOADED) {
  1076                 stuck = true;
  1081     /**
  1082      * Does the argument expression {@code expr} need speculative type-checking?
  1083      */
  1084     boolean isDeferred(Env<AttrContext> env, JCExpression expr) {
  1085         DeferredChecker dc = new DeferredChecker(env);
  1086         dc.scan(expr);
  1087         return dc.result.isPoly();
  1090     /**
  1091      * The kind of an argument expression. This is used by the analysis that
  1092      * determines as to whether speculative attribution is necessary.
  1093      */
  1094     enum ArgumentExpressionKind {
  1096         /** kind that denotes poly argument expression */
  1097         POLY,
  1098         /** kind that denotes a standalone expression */
  1099         NO_POLY,
  1100         /** kind that denotes a primitive/boxed standalone expression */
  1101         PRIMITIVE;
  1103         /**
  1104          * Does this kind denote a poly argument expression
  1105          */
  1106         public final boolean isPoly() {
  1107             return this == POLY;
  1110         /**
  1111          * Does this kind denote a primitive standalone expression
  1112          */
  1113         public final boolean isPrimitive() {
  1114             return this == PRIMITIVE;
  1117         /**
  1118          * Compute the kind of a standalone expression of a given type
  1119          */
  1120         static ArgumentExpressionKind standaloneKind(Type type, Types types) {
  1121             return types.unboxedTypeOrType(type).isPrimitive() ?
  1122                     ArgumentExpressionKind.PRIMITIVE :
  1123                     ArgumentExpressionKind.NO_POLY;
  1126         /**
  1127          * Compute the kind of a method argument expression given its symbol
  1128          */
  1129         static ArgumentExpressionKind methodKind(Symbol sym, Types types) {
  1130             Type restype = sym.type.getReturnType();
  1131             if (sym.type.hasTag(FORALL) &&
  1132                     restype.containsAny(((ForAll)sym.type).tvars)) {
  1133                 return ArgumentExpressionKind.POLY;
  1134             } else {
  1135                 return ArgumentExpressionKind.standaloneKind(restype, types);
  1140     /**
  1141      * Tree scanner used for checking as to whether an argument expression
  1142      * requires speculative attribution
  1143      */
  1144     final class DeferredChecker extends FilterScanner {
  1146         Env<AttrContext> env;
  1147         ArgumentExpressionKind result;
  1149         public DeferredChecker(Env<AttrContext> env) {
  1150             super(deferredCheckerTags);
  1151             this.env = env;
  1154         @Override
  1155         public void visitLambda(JCLambda tree) {
  1156             //a lambda is always a poly expression
  1157             result = ArgumentExpressionKind.POLY;
  1160         @Override
  1161         public void visitReference(JCMemberReference tree) {
  1162             //perform arity-based check
  1163             Env<AttrContext> localEnv = env.dup(tree);
  1164             JCExpression exprTree = (JCExpression)attribSpeculative(tree.getQualifierExpression(), localEnv,
  1165                     attr.memberReferenceQualifierResult(tree));
  1166             JCMemberReference mref2 = new TreeCopier<Void>(make).copy(tree);
  1167             mref2.expr = exprTree;
  1168             Symbol res =
  1169                     rs.getMemberReference(tree, localEnv, mref2,
  1170                         exprTree.type, tree.name);
  1171             tree.sym = res;
  1172             if (res.kind >= Kinds.ERRONEOUS ||
  1173                     res.type.hasTag(FORALL) ||
  1174                     (res.flags() & Flags.VARARGS) != 0 ||
  1175                     (TreeInfo.isStaticSelector(exprTree, tree.name.table.names) &&
  1176                     exprTree.type.isRaw())) {
  1177                 tree.overloadKind = JCMemberReference.OverloadKind.OVERLOADED;
  1178             } else {
  1179                 tree.overloadKind = JCMemberReference.OverloadKind.UNOVERLOADED;
  1181             //a method reference is always a poly expression
  1182             result = ArgumentExpressionKind.POLY;
  1185         @Override
  1186         public void visitTypeCast(JCTypeCast tree) {
  1187             //a cast is always a standalone expression
  1188             result = ArgumentExpressionKind.NO_POLY;
  1191         @Override
  1192         public void visitConditional(JCConditional tree) {
  1193             scan(tree.truepart);
  1194             if (!result.isPrimitive()) {
  1195                 result = ArgumentExpressionKind.POLY;
  1196                 return;
  1198             scan(tree.falsepart);
  1199             result = reduce(ArgumentExpressionKind.PRIMITIVE);
  1202         @Override
  1203         public void visitNewClass(JCNewClass tree) {
  1204             result = (TreeInfo.isDiamond(tree) || attr.findDiamonds) ?
  1205                     ArgumentExpressionKind.POLY : ArgumentExpressionKind.NO_POLY;
  1208         @Override
  1209         public void visitApply(JCMethodInvocation tree) {
  1210             Name name = TreeInfo.name(tree.meth);
  1212             //fast path
  1213             if (tree.typeargs.nonEmpty() ||
  1214                     name == name.table.names._this ||
  1215                     name == name.table.names._super) {
  1216                 result = ArgumentExpressionKind.NO_POLY;
  1217                 return;
  1220             //slow path
  1221             final JCExpression rec = tree.meth.hasTag(SELECT) ?
  1222                     ((JCFieldAccess)tree.meth).selected :
  1223                     null;
  1225             if (rec != null && !isSimpleReceiver(rec)) {
  1226                 //give up if receiver is too complex (to cut down analysis time)
  1227                 result = ArgumentExpressionKind.POLY;
  1228                 return;
  1231             Type site = rec != null ?
  1232                     attribSpeculative(rec, env, attr.unknownTypeExprInfo).type :
  1233                     env.enclClass.sym.type;
  1235             while (site.hasTag(TYPEVAR)) {
  1236                 site = site.getUpperBound();
  1239             List<Type> args = rs.dummyArgs(tree.args.length());
  1241             Resolve.LookupHelper lh = rs.new LookupHelper(name, site, args, List.<Type>nil(), MethodResolutionPhase.VARARITY) {
  1242                 @Override
  1243                 Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) {
  1244                     return rec == null ?
  1245                         rs.findFun(env, name, argtypes, typeargtypes, phase.isBoxingRequired(), phase.isVarargsRequired()) :
  1246                         rs.findMethod(env, site, name, argtypes, typeargtypes, phase.isBoxingRequired(), phase.isVarargsRequired(), false);
  1248                 @Override
  1249                 Symbol access(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, Symbol sym) {
  1250                     return sym;
  1252             };
  1254             Symbol sym = rs.lookupMethod(env, tree, site.tsym, rs.arityMethodCheck, lh);
  1256             if (sym.kind == Kinds.AMBIGUOUS) {
  1257                 Resolve.AmbiguityError err = (Resolve.AmbiguityError)sym.baseSymbol();
  1258                 result = ArgumentExpressionKind.PRIMITIVE;
  1259                 for (Symbol s : err.ambiguousSyms) {
  1260                     if (result.isPoly()) break;
  1261                     if (s.kind == Kinds.MTH) {
  1262                         result = reduce(ArgumentExpressionKind.methodKind(s, types));
  1265             } else {
  1266                 result = (sym.kind == Kinds.MTH) ?
  1267                     ArgumentExpressionKind.methodKind(sym, types) :
  1268                     ArgumentExpressionKind.NO_POLY;
  1271         //where
  1272             private boolean isSimpleReceiver(JCTree rec) {
  1273                 switch (rec.getTag()) {
  1274                     case IDENT:
  1275                         return true;
  1276                     case SELECT:
  1277                         return isSimpleReceiver(((JCFieldAccess)rec).selected);
  1278                     case TYPEAPPLY:
  1279                     case TYPEARRAY:
  1280                         return true;
  1281                     case ANNOTATED_TYPE:
  1282                         return isSimpleReceiver(((JCAnnotatedType)rec).underlyingType);
  1283                     default:
  1284                         return false;
  1287             private ArgumentExpressionKind reduce(ArgumentExpressionKind kind) {
  1288                 switch (result) {
  1289                     case PRIMITIVE: return kind;
  1290                     case NO_POLY: return kind.isPoly() ? kind : result;
  1291                     case POLY: return result;
  1292                     default:
  1293                         Assert.error();
  1294                         return null;
  1298         @Override
  1299         public void visitLiteral(JCLiteral tree) {
  1300             Type litType = attr.litType(tree.typetag);
  1301             result = ArgumentExpressionKind.standaloneKind(litType, types);
  1304         @Override
  1305         void skip(JCTree tree) {
  1306             result = ArgumentExpressionKind.NO_POLY;
  1309     //where
  1310     private EnumSet<JCTree.Tag> deferredCheckerTags =
  1311             EnumSet.of(LAMBDA, REFERENCE, PARENS, TYPECAST,
  1312                     CONDEXPR, NEWCLASS, APPLY, LITERAL);

mercurial