DeferredAttr.java revision 2819:b93a15ac3bde
1193326Sed/*
2193326Sed * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
3193326Sed * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4193326Sed *
5193326Sed * This code is free software; you can redistribute it and/or modify it
6193326Sed * under the terms of the GNU General Public License version 2 only, as
7193326Sed * published by the Free Software Foundation.  Oracle designates this
8193326Sed * particular file as subject to the "Classpath" exception as provided
9193326Sed * by Oracle in the LICENSE file that accompanied this code.
10193326Sed *
11193326Sed * This code is distributed in the hope that it will be useful, but WITHOUT
12193326Sed * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13193326Sed * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14193326Sed * version 2 for more details (a copy is included in the LICENSE file that
15193326Sed * accompanied this code).
16249423Sdim *
17249423Sdim * You should have received a copy of the GNU General Public License version
18249423Sdim * 2 along with this work; if not, write to the Free Software Foundation,
19193326Sed * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20193326Sed *
21249423Sdim * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22226633Sdim * or visit www.oracle.com if you need additional information or have any
23249423Sdim * questions.
24193326Sed */
25193326Sed
26226633Sdimpackage com.sun.tools.javac.comp;
27226633Sdim
28226633Sdimimport com.sun.source.tree.LambdaExpressionTree.BodyKind;
29226633Sdimimport com.sun.tools.javac.code.*;
30226633Sdimimport com.sun.tools.javac.comp.Resolve.ResolveError;
31226633Sdimimport com.sun.tools.javac.resources.CompilerProperties;
32226633Sdimimport com.sun.tools.javac.resources.CompilerProperties.Fragments;
33226633Sdimimport com.sun.tools.javac.tree.*;
34226633Sdimimport com.sun.tools.javac.util.*;
35226633Sdimimport com.sun.tools.javac.util.DefinedBy.Api;
36226633Sdimimport com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
37226633Sdimimport com.sun.tools.javac.code.Symbol.*;
38226633Sdimimport com.sun.tools.javac.code.Type.*;
39226633Sdimimport com.sun.tools.javac.comp.Attr.ResultInfo;
40226633Sdimimport com.sun.tools.javac.comp.Infer.InferenceContext;
41226633Sdimimport com.sun.tools.javac.comp.Resolve.MethodResolutionPhase;
42226633Sdimimport com.sun.tools.javac.tree.JCTree.*;
43226633Sdimimport com.sun.tools.javac.util.JCDiagnostic.DiagnosticType;
44226633Sdimimport com.sun.tools.javac.util.Log.DeferredDiagnosticHandler;
45243830Sdim
46243830Sdimimport java.util.ArrayList;
47243830Sdimimport java.util.Collections;
48243830Sdimimport java.util.EnumMap;
49243830Sdimimport java.util.EnumSet;
50243830Sdimimport java.util.LinkedHashMap;
51243830Sdimimport java.util.LinkedHashSet;
52243830Sdimimport java.util.Map;
53243830Sdimimport java.util.Set;
54243830Sdimimport java.util.WeakHashMap;
55243830Sdimimport java.util.function.Function;
56243830Sdim
57243830Sdimimport static com.sun.tools.javac.code.TypeTag.*;
58243830Sdimimport static com.sun.tools.javac.tree.JCTree.Tag.*;
59243830Sdimimport static com.sun.tools.javac.code.Kinds.*;
60243830Sdimimport static com.sun.tools.javac.code.Kinds.Kind.*;
61243830Sdim
62243830Sdim/**
63243830Sdim * This is an helper class that is used to perform deferred type-analysis.
64243830Sdim * Each time a poly expression occurs in argument position, javac attributes it
65243830Sdim * with a temporary 'deferred type' that is checked (possibly multiple times)
66243830Sdim * against an expected formal type.
67243830Sdim *
68243830Sdim *  <p><b>This is NOT part of any supported API.
69243830Sdim *  If you write code that depends on this, you do so at your own risk.
70243830Sdim *  This code and its internal interfaces are subject to change or
71243830Sdim *  deletion without notice.</b>
72243830Sdim */
73243830Sdimpublic class DeferredAttr extends JCTree.Visitor {
74243830Sdim    protected static final Context.Key<DeferredAttr> deferredAttrKey = new Context.Key<>();
75193326Sed
76193326Sed    final Attr attr;
77243830Sdim    final Check chk;
78243830Sdim    final JCDiagnostic.Factory diags;
79193326Sed    final Enter enter;
80226633Sdim    final Infer infer;
81243830Sdim    final Resolve rs;
82243830Sdim    final Log log;
83243830Sdim    final Symtab syms;
84243830Sdim    final TreeMaker make;
85193326Sed    final Types types;
86193326Sed    final Flow flow;
87193326Sed    final Names names;
88193326Sed    final TypeEnvs typeEnvs;
89193326Sed
90193326Sed    public static DeferredAttr instance(Context context) {
91193326Sed        DeferredAttr instance = context.get(deferredAttrKey);
92193326Sed        if (instance == null)
93193326Sed            instance = new DeferredAttr(context);
94198092Srdivacky        return instance;
95193326Sed    }
96193326Sed
97193326Sed    protected DeferredAttr(Context context) {
98193326Sed        context.put(deferredAttrKey, this);
99193326Sed        attr = Attr.instance(context);
100193326Sed        chk = Check.instance(context);
101193326Sed        diags = JCDiagnostic.Factory.instance(context);
102193326Sed        enter = Enter.instance(context);
103193326Sed        infer = Infer.instance(context);
104218893Sdim        rs = Resolve.instance(context);
105243830Sdim        log = Log.instance(context);
106243830Sdim        syms = Symtab.instance(context);
107193326Sed        make = TreeMaker.instance(context);
108193326Sed        types = Types.instance(context);
109194179Sed        flow = Flow.instance(context);
110218893Sdim        names = Names.instance(context);
111243830Sdim        stuckTree = make.Ident(names.empty).setType(Type.stuckType);
112243830Sdim        typeEnvs = TypeEnvs.instance(context);
113194179Sed        emptyDeferredAttrContext =
114194179Sed            new DeferredAttrContext(AttrMode.CHECK, null, MethodResolutionPhase.BOX, infer.emptyContext, null, null) {
115193326Sed                @Override
116193326Sed                void addDeferredAttrNode(DeferredType dt, ResultInfo ri, DeferredStuckPolicy deferredStuckPolicy) {
117193326Sed                    Assert.error("Empty deferred context!");
118193326Sed                }
119193326Sed                @Override
120193326Sed                void complete() {
121193326Sed                    Assert.error("Empty deferred context!");
122193326Sed                }
123193326Sed
124193326Sed                @Override
125193326Sed                public String toString() {
126193326Sed                    return "Empty deferred context!";
127193326Sed                }
128193326Sed            };
129193326Sed    }
130193326Sed
131193326Sed    /** shared tree for stuck expressions */
132249423Sdim    final JCTree stuckTree;
133218893Sdim
134243830Sdim    /**
135249423Sdim     * This type represents a deferred type. A deferred type starts off with
136193326Sed     * no information on the underlying expression type. Such info needs to be
137193326Sed     * discovered through type-checking the deferred type against a target-type.
138193326Sed     * Every deferred type keeps a pointer to the AST node from which it originated.
139198092Srdivacky     */
140193326Sed    public class DeferredType extends Type {
141193326Sed
142193326Sed        public JCExpression tree;
143249423Sdim        Env<AttrContext> env;
144193326Sed        AttrMode mode;
145193326Sed        SpeculativeCache speculativeCache;
146193326Sed
147193326Sed        DeferredType(JCExpression tree, Env<AttrContext> env) {
148193326Sed            super(null, TypeMetadata.empty);
149193326Sed            this.tree = tree;
150193326Sed            this.env = attr.copyEnv(env);
151193326Sed            this.speculativeCache = new SpeculativeCache();
152193326Sed        }
153193326Sed
154193326Sed        @Override
155193326Sed        public DeferredType clone(TypeMetadata md) {
156198092Srdivacky            throw new AssertionError("Cannot add metadata to a deferred type");
157193326Sed        }
158218893Sdim
159243830Sdim        @Override
160243830Sdim        public TypeTag getTag() {
161193326Sed            return DEFERRED;
162193326Sed        }
163193326Sed
164193326Sed        @Override @DefinedBy(Api.LANGUAGE_MODEL)
165193326Sed        public String toString() {
166193326Sed            return "DeferredType";
167193326Sed        }
168193326Sed
169193326Sed        /**
170193326Sed         * A speculative cache is used to keep track of all overload resolution rounds
171193326Sed         * that triggered speculative attribution on a given deferred type. Each entry
172193326Sed         * stores a pointer to the speculative tree and the resolution phase in which the entry
173193326Sed         * has been added.
174193326Sed         */
175193326Sed        class SpeculativeCache {
176193326Sed
177193326Sed            private Map<Symbol, List<Entry>> cache = new WeakHashMap<>();
178198092Srdivacky
179193326Sed            class Entry {
180193326Sed                JCTree speculativeTree;
181218893Sdim                ResultInfo resultInfo;
182243830Sdim
183243830Sdim                public Entry(JCTree speculativeTree, ResultInfo resultInfo) {
184193326Sed                    this.speculativeTree = speculativeTree;
185193326Sed                    this.resultInfo = resultInfo;
186193326Sed                }
187193326Sed
188198092Srdivacky                boolean matches(MethodResolutionPhase phase) {
189193326Sed                    return resultInfo.checkContext.deferredAttrContext().phase == phase;
190193326Sed                }
191193326Sed            }
192218893Sdim
193243830Sdim            /**
194243830Sdim             * Retrieve a speculative cache entry corresponding to given symbol
195243830Sdim             * and resolution phase
196193326Sed             */
197193326Sed            Entry get(Symbol msym, MethodResolutionPhase phase) {
198218893Sdim                List<Entry> entries = cache.get(msym);
199208600Srdivacky                if (entries == null) return null;
200243830Sdim                for (Entry e : entries) {
201249423Sdim                    if (e.matches(phase)) return e;
202243830Sdim                }
203243830Sdim                return null;
204243830Sdim            }
205193326Sed
206243830Sdim            /**
207243830Sdim             * Stores a speculative cache entry corresponding to given symbol
208243830Sdim             * and resolution phase
209193326Sed             */
210193326Sed            void put(JCTree speculativeTree, ResultInfo resultInfo) {
211198092Srdivacky                Symbol msym = resultInfo.checkContext.deferredAttrContext().msym;
212193326Sed                List<Entry> entries = cache.get(msym);
213193326Sed                if (entries == null) {
214193326Sed                    entries = List.nil();
215193326Sed                }
216218893Sdim                cache.put(msym, entries.prepend(new Entry(speculativeTree, resultInfo)));
217234353Sdim            }
218234353Sdim        }
219218893Sdim
220226633Sdim        /**
221234353Sdim         * Get the type that has been computed during a speculative attribution round
222234353Sdim         */
223234353Sdim        Type speculativeType(Symbol msym, MethodResolutionPhase phase) {
224198092Srdivacky            SpeculativeCache.Entry e = speculativeCache.get(msym, phase);
225193326Sed            return e != null ? e.speculativeTree.type : Type.noType;
226193326Sed        }
227193326Sed
228249423Sdim        /**
229218893Sdim         * Check a deferred type against a potential target-type. Depending on
230243830Sdim         * the current attribution mode, a normal vs. speculative attribution
231249423Sdim         * round is performed on the underlying AST node. There can be only one
232218893Sdim         * speculative round for a given target method symbol; moreover, a normal
233193326Sed         * attribution round must follow one or more speculative rounds.
234218893Sdim         */
235212904Sdim        Type check(ResultInfo resultInfo) {
236218893Sdim            DeferredStuckPolicy deferredStuckPolicy;
237249423Sdim            if (resultInfo.pt.hasTag(NONE) || resultInfo.pt.isErroneous()) {
238193326Sed                deferredStuckPolicy = dummyStuckPolicy;
239193326Sed            } else if (resultInfo.checkContext.deferredAttrContext().mode == AttrMode.SPECULATIVE ||
240193326Sed                    resultInfo.checkContext.deferredAttrContext().insideOverloadPhase()) {
241193326Sed                deferredStuckPolicy = new OverloadStuckPolicy(resultInfo, this);
242193326Sed            } else {
243218893Sdim                deferredStuckPolicy = new CheckStuckPolicy(resultInfo, this);
244243830Sdim            }
245243830Sdim            return check(resultInfo, deferredStuckPolicy, basicCompleter);
246243830Sdim        }
247218893Sdim
248193326Sed        private Type check(ResultInfo resultInfo, DeferredStuckPolicy deferredStuckPolicy,
249234353Sdim                DeferredTypeCompleter deferredTypeCompleter) {
250234353Sdim            DeferredAttrContext deferredAttrContext =
251234353Sdim                    resultInfo.checkContext.deferredAttrContext();
252234353Sdim            Assert.check(deferredAttrContext != emptyDeferredAttrContext);
253218893Sdim            if (deferredStuckPolicy.isStuck()) {
254243830Sdim                deferredAttrContext.addDeferredAttrNode(this, resultInfo, deferredStuckPolicy);
255243830Sdim                return Type.noType;
256218893Sdim            } else {
257218893Sdim                try {
258234353Sdim                    return deferredTypeCompleter.complete(this, resultInfo, deferredAttrContext);
259234353Sdim                } finally {
260234353Sdim                    mode = deferredAttrContext.mode;
261234353Sdim                }
262234353Sdim            }
263249423Sdim        }
264234353Sdim    }
265234353Sdim
266234353Sdim    /**
267243830Sdim     * A completer for deferred types. Defines an entry point for type-checking
268243830Sdim     * a deferred type.
269243830Sdim     */
270243830Sdim    interface DeferredTypeCompleter {
271234353Sdim        /**
272243830Sdim         * Entry point for type-checking a deferred type. Depending on the
273243830Sdim         * circumstances, type-checking could amount to full attribution
274243830Sdim         * or partial structural check (aka potential applicability).
275234353Sdim         */
276234353Sdim        Type complete(DeferredType dt, ResultInfo resultInfo, DeferredAttrContext deferredAttrContext);
277234353Sdim    }
278234353Sdim
279234353Sdim
280243830Sdim    /**
281243830Sdim     * A basic completer for deferred types. This completer type-checks a deferred type
282249423Sdim     * using attribution; depending on the attribution mode, this could be either standard
283243830Sdim     * or speculative attribution.
284218893Sdim     */
285218893Sdim    DeferredTypeCompleter basicCompleter = new DeferredTypeCompleter() {
286218893Sdim        public Type complete(DeferredType dt, ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) {
287239462Sdim            switch (deferredAttrContext.mode) {
288239462Sdim                case SPECULATIVE:
289239462Sdim                    //Note: if a symbol is imported twice we might do two identical
290239462Sdim                    //speculative rounds...
291239462Sdim                    Assert.check(dt.mode == null || dt.mode == AttrMode.SPECULATIVE);
292239462Sdim                    JCTree speculativeTree = attribSpeculative(dt.tree, dt.env, resultInfo);
293239462Sdim                    dt.speculativeCache.put(speculativeTree, resultInfo);
294239462Sdim                    return speculativeTree.type;
295239462Sdim                case CHECK:
296239462Sdim                    Assert.check(dt.mode != null);
297239462Sdim                    return attr.attribTree(dt.tree, dt.env, resultInfo);
298239462Sdim            }
299239462Sdim            Assert.error();
300239462Sdim            return null;
301239462Sdim        }
302239462Sdim    };
303239462Sdim
304239462Sdim    DeferredTypeCompleter dummyCompleter = new DeferredTypeCompleter() {
305239462Sdim        public Type complete(DeferredType dt, ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) {
306239462Sdim            Assert.check(deferredAttrContext.mode == AttrMode.CHECK);
307239462Sdim            return dt.tree.type = Type.stuckType;
308239462Sdim        }
309239462Sdim    };
310239462Sdim
311239462Sdim    /**
312239462Sdim     * Policy for detecting stuck expressions. Different criteria might cause
313239462Sdim     * an expression to be judged as stuck, depending on whether the check
314239462Sdim     * is performed during overload resolution or after most specific.
315239462Sdim     */
316239462Sdim    interface DeferredStuckPolicy {
317239462Sdim        /**
318239462Sdim         * Has the policy detected that a given expression should be considered stuck?
319239462Sdim         */
320218893Sdim        boolean isStuck();
321218893Sdim        /**
322218893Sdim         * Get the set of inference variables a given expression depends upon.
323218893Sdim         */
324234353Sdim        Set<Type> stuckVars();
325234353Sdim        /**
326218893Sdim         * Get the set of inference variables which might get new constraints
327226633Sdim         * if a given expression is being type-checked.
328226633Sdim         */
329218893Sdim        Set<Type> depVars();
330218893Sdim    }
331218893Sdim
332218893Sdim    /**
333234353Sdim     * Basic stuck policy; an expression is never considered to be stuck.
334234353Sdim     */
335239462Sdim    DeferredStuckPolicy dummyStuckPolicy = new DeferredStuckPolicy() {
336193326Sed        @Override
337193326Sed        public boolean isStuck() {
338218893Sdim            return false;
339226633Sdim        }
340226633Sdim        @Override
341218893Sdim        public Set<Type> stuckVars() {
342226633Sdim            return Collections.emptySet();
343226633Sdim        }
344218893Sdim        @Override
345226633Sdim        public Set<Type> depVars() {
346234353Sdim            return Collections.emptySet();
347234353Sdim        }
348234353Sdim    };
349234353Sdim
350234353Sdim    /**
351226633Sdim     * The 'mode' in which the deferred type is to be type-checked
352226633Sdim     */
353226633Sdim    public enum AttrMode {
354226633Sdim        /**
355234353Sdim         * A speculative type-checking round is used during overload resolution
356234353Sdim         * mainly to generate constraints on inference variables. Side-effects
357234353Sdim         * arising from type-checking the expression associated with the deferred
358234353Sdim         * type are reversed after the speculative round finishes. This means the
359239462Sdim         * expression tree will be left in a blank state.
360234353Sdim         */
361234353Sdim        SPECULATIVE,
362218893Sdim        /**
363218893Sdim         * This is the plain type-checking mode. Produces side-effects on the underlying AST node
364218893Sdim         */
365234353Sdim        CHECK
366218893Sdim    }
367234353Sdim
368234353Sdim    /**
369234353Sdim     * Routine that performs speculative type-checking; the input AST node is
370212904Sdim     * cloned (to avoid side-effects cause by Attr) and compiler state is
371212904Sdim     * restored after type-checking. All diagnostics (but critical ones) are
372226633Sdim     * disabled during speculative type-checking.
373226633Sdim     */
374226633Sdim    JCTree attribSpeculative(JCTree tree, Env<AttrContext> env, ResultInfo resultInfo) {
375193326Sed        return attribSpeculative(tree, env, resultInfo, new TreeCopier<>(make),
376193326Sed                (newTree)->new DeferredAttrDiagHandler(log, newTree));
377193326Sed    }
378198092Srdivacky
379193326Sed    <Z> JCTree attribSpeculative(JCTree tree, Env<AttrContext> env, ResultInfo resultInfo, TreeCopier<Z> deferredCopier,
380193326Sed                                 Function<JCTree, DeferredDiagnosticHandler> diagHandlerCreator) {
381193326Sed        final JCTree newTree = deferredCopier.copy(tree);
382193326Sed        Env<AttrContext> speculativeEnv = env.dup(newTree, env.info.dup(env.info.scope.dupUnshared(env.info.scope.owner)));
383193326Sed        speculativeEnv.info.isSpeculative = true;
384193326Sed        Log.DeferredDiagnosticHandler deferredDiagnosticHandler = diagHandlerCreator.apply(newTree);
385193326Sed        try {
386193326Sed            attr.attribTree(newTree, speculativeEnv, resultInfo);
387193326Sed            unenterScanner.scan(newTree);
388193326Sed            return newTree;
389193326Sed        } finally {
390198092Srdivacky            unenterScanner.scan(newTree);
391193326Sed            log.popDiagnosticHandler(deferredDiagnosticHandler);
392193326Sed        }
393198092Srdivacky    }
394193326Sed    //where
395193326Sed        protected UnenterScanner unenterScanner = new UnenterScanner();
396198092Srdivacky
397193326Sed        class UnenterScanner extends TreeScanner {
398193326Sed            @Override
399193326Sed            public void visitClassDef(JCClassDecl tree) {
400193326Sed                ClassSymbol csym = tree.sym;
401193326Sed                //if something went wrong during method applicability check
402243830Sdim                //it is possible that nested expressions inside argument expression
403243830Sdim                //are left unchecked - in such cases there's nothing to clean up.
404243830Sdim                if (csym == null) return;
405243830Sdim                typeEnvs.remove(csym);
406193326Sed                chk.compiled.remove(csym.flatname);
407193326Sed                syms.classes.remove(csym.flatname);
408193326Sed                super.visitClassDef(tree);
409193326Sed            }
410193326Sed        }
411193326Sed
412193326Sed        static class DeferredAttrDiagHandler extends Log.DeferredDiagnosticHandler {
413193326Sed
414193326Sed            static class PosScanner extends TreeScanner {
415193326Sed                DiagnosticPosition pos;
416234353Sdim                boolean found = false;
417234353Sdim
418234353Sdim                PosScanner(DiagnosticPosition pos) {
419234353Sdim                    this.pos = pos;
420198092Srdivacky                }
421193326Sed
422193326Sed                @Override
423198092Srdivacky                public void scan(JCTree tree) {
424193326Sed                    if (tree != null &&
425193326Sed                            tree.pos() == pos) {
426198092Srdivacky                        found = true;
427193326Sed                    }
428193326Sed                    super.scan(tree);
429193326Sed                }
430193326Sed            }
431193326Sed
432193326Sed            DeferredAttrDiagHandler(Log log, JCTree newTree) {
433193326Sed                super(log, new Filter<JCDiagnostic>() {
434193326Sed                    public boolean accepts(JCDiagnostic d) {
435193326Sed                        PosScanner posScanner = new PosScanner(d.getDiagnosticPosition());
436193326Sed                        posScanner.scan(newTree);
437193326Sed                        return posScanner.found;
438193326Sed                    }
439193326Sed                });
440193326Sed            }
441193326Sed        }
442193326Sed
443193326Sed    /**
444193326Sed     * A deferred context is created on each method check. A deferred context is
445193326Sed     * used to keep track of information associated with the method check, such as
446193326Sed     * the symbol of the method being checked, the overload resolution phase,
447193326Sed     * the kind of attribution mode to be applied to deferred types and so forth.
448198092Srdivacky     * As deferred types are processed (by the method check routine) stuck AST nodes
449193326Sed     * are added (as new deferred attribution nodes) to this context. The complete()
450193326Sed     * routine makes sure that all pending nodes are properly processed, by
451193326Sed     * progressively instantiating all inference variables on which one or more
452193326Sed     * deferred attribution node is stuck.
453193326Sed     */
454243830Sdim    class DeferredAttrContext {
455243830Sdim
456243830Sdim        /** attribution mode */
457243830Sdim        final AttrMode mode;
458198092Srdivacky
459193326Sed        /** symbol of the method being checked */
460193326Sed        final Symbol msym;
461193326Sed
462193326Sed        /** method resolution step */
463249423Sdim        final Resolve.MethodResolutionPhase phase;
464198092Srdivacky
465243830Sdim        /** inference context */
466193326Sed        final InferenceContext inferenceContext;
467193326Sed
468234353Sdim        /** parent deferred context */
469193326Sed        final DeferredAttrContext parent;
470193326Sed
471193326Sed        /** Warner object to report warnings */
472193326Sed        final Warner warn;
473193326Sed
474198092Srdivacky        /** list of deferred attribution nodes to be processed */
475193326Sed        ArrayList<DeferredAttrNode> deferredAttrNodes = new ArrayList<>();
476198092Srdivacky
477193326Sed        DeferredAttrContext(AttrMode mode, Symbol msym, MethodResolutionPhase phase,
478193326Sed                InferenceContext inferenceContext, DeferredAttrContext parent, Warner warn) {
479193326Sed            this.mode = mode;
480193326Sed            this.msym = msym;
481193326Sed            this.phase = phase;
482193326Sed            this.parent = parent;
483193326Sed            this.warn = warn;
484193326Sed            this.inferenceContext = inferenceContext;
485193326Sed        }
486249423Sdim
487243830Sdim        /**
488226633Sdim         * Adds a node to the list of deferred attribution nodes - used by Resolve.rawCheckArgumentsApplicable
489193326Sed         * Nodes added this way act as 'roots' for the out-of-order method checking process.
490193326Sed         */
491193326Sed        void addDeferredAttrNode(final DeferredType dt, ResultInfo resultInfo,
492193326Sed                DeferredStuckPolicy deferredStuckPolicy) {
493193326Sed            deferredAttrNodes.add(new DeferredAttrNode(dt, resultInfo, deferredStuckPolicy));
494193326Sed        }
495198092Srdivacky
496193326Sed        /**
497193326Sed         * Incrementally process all nodes, by skipping 'stuck' nodes and attributing
498193326Sed         * 'unstuck' ones. If at any point no progress can be made (no 'unstuck' nodes)
499193326Sed         * some inference variable might get eagerly instantiated so that all nodes
500193326Sed         * can be type-checked.
501193326Sed         */
502193326Sed        void complete() {
503193326Sed            while (!deferredAttrNodes.isEmpty()) {
504193326Sed                Map<Type, Set<Type>> depVarsMap = new LinkedHashMap<>();
505243830Sdim                List<Type> stuckVars = List.nil();
506193326Sed                boolean progress = false;
507193326Sed                //scan a defensive copy of the node list - this is because a deferred
508193326Sed                //attribution round can add new nodes to the list
509193326Sed                for (DeferredAttrNode deferredAttrNode : List.from(deferredAttrNodes)) {
510193326Sed                    if (!deferredAttrNode.process(this)) {
511193326Sed                        List<Type> restStuckVars =
512193326Sed                                List.from(deferredAttrNode.deferredStuckPolicy.stuckVars())
513193326Sed                                .intersect(inferenceContext.restvars());
514198092Srdivacky                        stuckVars = stuckVars.prependList(restStuckVars);
515193326Sed                        //update dependency map
516193326Sed                        for (Type t : List.from(deferredAttrNode.deferredStuckPolicy.depVars())
517193326Sed                                .intersect(inferenceContext.restvars())) {
518198092Srdivacky                            Set<Type> prevDeps = depVarsMap.get(t);
519193326Sed                            if (prevDeps == null) {
520193326Sed                                prevDeps = new LinkedHashSet<>();
521193326Sed                                depVarsMap.put(t, prevDeps);
522193326Sed                            }
523193326Sed                            prevDeps.addAll(restStuckVars);
524193326Sed                        }
525193326Sed                    } else {
526193326Sed                        deferredAttrNodes.remove(deferredAttrNode);
527193326Sed                        progress = true;
528193326Sed                    }
529193326Sed                }
530193326Sed                if (!progress) {
531193326Sed                    if (insideOverloadPhase()) {
532193326Sed                        for (DeferredAttrNode deferredNode: deferredAttrNodes) {
533193326Sed                            deferredNode.dt.tree.type = Type.noType;
534193326Sed                        }
535193326Sed                        return;
536193326Sed                    }
537193326Sed                    //remove all variables that have already been instantiated
538193326Sed                    //from the list of stuck variables
539198092Srdivacky                    try {
540193326Sed                        inferenceContext.solveAny(stuckVars, depVarsMap, warn);
541193326Sed                        inferenceContext.notifyChange();
542193326Sed                    } catch (Infer.GraphStrategy.NodeNotFoundException ex) {
543193326Sed                        //this means that we are in speculative mode and the
544193326Sed                        //set of contraints are too tight for progess to be made.
545193326Sed                        //Just leave the remaining expressions as stuck.
546193326Sed                        break;
547193326Sed                    }
548193326Sed                }
549193326Sed            }
550218893Sdim        }
551234353Sdim
552202879Srdivacky        private boolean insideOverloadPhase() {
553199990Srdivacky            DeferredAttrContext dac = this;
554193326Sed            if (dac == emptyDeferredAttrContext) {
555198092Srdivacky                return false;
556198092Srdivacky            }
557198092Srdivacky            if (dac.mode == AttrMode.SPECULATIVE) {
558198092Srdivacky                return true;
559198092Srdivacky            }
560199990Srdivacky            return dac.parent.insideOverloadPhase();
561198092Srdivacky        }
562199990Srdivacky    }
563218893Sdim
564218893Sdim    /**
565218893Sdim     * Class representing a deferred attribution node. It keeps track of
566218893Sdim     * a deferred type, along with the expected target type information.
567199990Srdivacky     */
568199990Srdivacky    class DeferredAttrNode {
569218893Sdim
570218893Sdim        /** underlying deferred type */
571218893Sdim        DeferredType dt;
572218893Sdim
573198092Srdivacky        /** underlying target type information */
574199990Srdivacky        ResultInfo resultInfo;
575198092Srdivacky
576199990Srdivacky        /** stuck policy associated with this node */
577218893Sdim        DeferredStuckPolicy deferredStuckPolicy;
578218893Sdim
579218893Sdim        DeferredAttrNode(DeferredType dt, ResultInfo resultInfo, DeferredStuckPolicy deferredStuckPolicy) {
580218893Sdim            this.dt = dt;
581218893Sdim            this.resultInfo = resultInfo;
582199990Srdivacky            this.deferredStuckPolicy = deferredStuckPolicy;
583198092Srdivacky        }
584199990Srdivacky
585218893Sdim        /**
586218893Sdim         * Process a deferred attribution node.
587218893Sdim         * Invariant: a stuck node cannot be processed.
588218893Sdim         */
589218893Sdim        @SuppressWarnings("fallthrough")
590199990Srdivacky        boolean process(final DeferredAttrContext deferredAttrContext) {
591198092Srdivacky            switch (deferredAttrContext.mode) {
592198092Srdivacky                case SPECULATIVE:
593198092Srdivacky                    if (deferredStuckPolicy.isStuck()) {
594198092Srdivacky                        dt.check(resultInfo, dummyStuckPolicy, new StructuralStuckChecker());
595193326Sed                        return true;
596193326Sed                    } else {
597193326Sed                        Assert.error("Cannot get here");
598193326Sed                    }
599193326Sed                case CHECK:
600193326Sed                    if (deferredStuckPolicy.isStuck()) {
601243830Sdim                        //stuck expression - see if we can propagate
602193326Sed                        if (deferredAttrContext.parent != emptyDeferredAttrContext &&
603193326Sed                                Type.containsAny(deferredAttrContext.parent.inferenceContext.inferencevars,
604193326Sed                                        List.from(deferredStuckPolicy.stuckVars()))) {
605193326Sed                            deferredAttrContext.parent.addDeferredAttrNode(dt,
606234353Sdim                                    resultInfo.dup(new Check.NestedCheckContext(resultInfo.checkContext) {
607193326Sed                                @Override
608193326Sed                                public InferenceContext inferenceContext() {
609198092Srdivacky                                    return deferredAttrContext.parent.inferenceContext;
610193326Sed                                }
611249423Sdim                                @Override
612234353Sdim                                public DeferredAttrContext deferredAttrContext() {
613234353Sdim                                    return deferredAttrContext.parent;
614234353Sdim                                }
615234353Sdim                            }), deferredStuckPolicy);
616234353Sdim                            dt.tree.type = Type.stuckType;
617234353Sdim                            return true;
618234353Sdim                        } else {
619243830Sdim                            return false;
620193326Sed                        }
621193326Sed                    } else {
622226633Sdim                        Assert.check(!deferredAttrContext.insideOverloadPhase(),
623193326Sed                                "attribution shouldn't be happening here");
624193326Sed                        ResultInfo instResultInfo =
625193326Sed                                resultInfo.dup(deferredAttrContext.inferenceContext.asInstType(resultInfo.pt));
626193326Sed                        dt.check(instResultInfo, dummyStuckPolicy, basicCompleter);
627193326Sed                        return true;
628193326Sed                    }
629193326Sed                default:
630193326Sed                    throw new AssertionError("Bad mode");
631198092Srdivacky            }
632193326Sed        }
633193326Sed
634193326Sed        /**
635193326Sed         * Structural checker for stuck expressions
636198092Srdivacky         */
637193326Sed        class StructuralStuckChecker extends TreeScanner implements DeferredTypeCompleter {
638249423Sdim
639193326Sed            ResultInfo resultInfo;
640193326Sed            InferenceContext inferenceContext;
641193326Sed            Env<AttrContext> env;
642193326Sed
643234353Sdim            public Type complete(DeferredType dt, ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) {
644193326Sed                this.resultInfo = resultInfo;
645193326Sed                this.inferenceContext = deferredAttrContext.inferenceContext;
646193326Sed                this.env = dt.env;
647193326Sed                dt.tree.accept(this);
648193326Sed                dt.speculativeCache.put(stuckTree, resultInfo);
649234353Sdim                return Type.noType;
650193326Sed            }
651234353Sdim
652193326Sed            @Override
653234353Sdim            public void visitLambda(JCLambda tree) {
654234353Sdim                Check.CheckContext checkContext = resultInfo.checkContext;
655243830Sdim                Type pt = resultInfo.pt;
656234353Sdim                if (!inferenceContext.inferencevars.contains(pt)) {
657234353Sdim                    //must be a functional descriptor
658234353Sdim                    Type descriptorType = null;
659234353Sdim                    try {
660234353Sdim                        descriptorType = types.findDescriptorType(pt);
661193326Sed                    } catch (Types.FunctionDescriptorLookupError ex) {
662198092Srdivacky                        checkContext.report(null, ex.getDiagnostic());
663226633Sdim                    }
664193326Sed
665193326Sed                    if (descriptorType.getParameterTypes().length() != tree.params.length()) {
666193326Sed                        checkContext.report(tree,
667193326Sed                                diags.fragment("incompatible.arg.types.in.lambda"));
668193326Sed                    }
669193326Sed
670193326Sed                    Type currentReturnType = descriptorType.getReturnType();
671193326Sed                    boolean returnTypeIsVoid = currentReturnType.hasTag(VOID);
672193326Sed                    if (tree.getBodyKind() == BodyKind.EXPRESSION) {
673193326Sed                        boolean isExpressionCompatible = !returnTypeIsVoid ||
674193326Sed                            TreeInfo.isExpressionStatement((JCExpression)tree.getBody());
675193326Sed                        if (!isExpressionCompatible) {
676198092Srdivacky                            resultInfo.checkContext.report(tree.pos(),
677234353Sdim                                diags.fragment("incompatible.ret.type.in.lambda",
678193326Sed                                    diags.fragment("missing.ret.val", currentReturnType)));
679193326Sed                        }
680193326Sed                    } else {
681193326Sed                        LambdaBodyStructChecker lambdaBodyChecker =
682193326Sed                                new LambdaBodyStructChecker();
683193326Sed
684193326Sed                        tree.body.accept(lambdaBodyChecker);
685193326Sed                        boolean isVoidCompatible = lambdaBodyChecker.isVoidCompatible;
686198092Srdivacky
687193326Sed                        if (returnTypeIsVoid) {
688193326Sed                            if (!isVoidCompatible) {
689193326Sed                                resultInfo.checkContext.report(tree.pos(),
690193326Sed                                    diags.fragment("unexpected.ret.val"));
691193326Sed                            }
692193326Sed                        } else {
693193326Sed                            boolean isValueCompatible = lambdaBodyChecker.isPotentiallyValueCompatible
694193326Sed                                && !canLambdaBodyCompleteNormally(tree);
695193326Sed                            if (!isValueCompatible && !isVoidCompatible) {
696193326Sed                                log.error(tree.body.pos(),
697249423Sdim                                    "lambda.body.neither.value.nor.void.compatible");
698193326Sed                            }
699226633Sdim
700193326Sed                            if (!isValueCompatible) {
701193326Sed                                resultInfo.checkContext.report(tree.pos(),
702193326Sed                                    diags.fragment("incompatible.ret.type.in.lambda",
703193326Sed                                        diags.fragment("missing.ret.val", currentReturnType)));
704193326Sed                            }
705198092Srdivacky                        }
706193326Sed                    }
707193326Sed                }
708198092Srdivacky            }
709193326Sed
710193326Sed            boolean canLambdaBodyCompleteNormally(JCLambda tree) {
711193326Sed                JCLambda newTree = new TreeCopier<>(make).copy(tree);
712193326Sed                /* attr.lambdaEnv will create a meaningful env for the
713193326Sed                 * lambda expression. This is specially useful when the
714198092Srdivacky                 * lambda is used as the init of a field. But we need to
715193326Sed                 * remove any added symbol.
716193326Sed                 */
717249423Sdim                Env<AttrContext> localEnv = attr.lambdaEnv(newTree, env);
718193326Sed                try {
719193326Sed                    List<JCVariableDecl> tmpParams = newTree.params;
720193326Sed                    while (tmpParams.nonEmpty()) {
721193326Sed                        tmpParams.head.vartype = make.at(tmpParams.head).Type(syms.errType);
722193326Sed                        tmpParams = tmpParams.tail;
723193326Sed                    }
724198092Srdivacky
725193326Sed                    attr.attribStats(newTree.params, localEnv);
726193326Sed
727249423Sdim                    /* set pt to Type.noType to avoid generating any bound
728193326Sed                     * which may happen if lambda's return type is an
729226633Sdim                     * inference variable
730193326Sed                     */
731193326Sed                    Attr.ResultInfo bodyResultInfo = attr.new ResultInfo(KindSelector.VAL, Type.noType);
732193326Sed                    localEnv.info.returnResult = bodyResultInfo;
733198092Srdivacky
734193326Sed                    // discard any log output
735193326Sed                    Log.DiagnosticHandler diagHandler = new Log.DiscardDiagnosticHandler(log);
736193326Sed                    try {
737193326Sed                        JCBlock body = (JCBlock)newTree.body;
738193326Sed                        /* we need to attribute the lambda body before
739193326Sed                         * doing the aliveness analysis. This is because
740193326Sed                         * constant folding occurs during attribution
741193326Sed                         * and the reachability of some statements depends
742193326Sed                         * on constant values, for example:
743193326Sed                         *
744193326Sed                         *     while (true) {...}
745193326Sed                         */
746193326Sed                        attr.attribStats(body.stats, localEnv);
747193326Sed
748193326Sed                        attr.preFlow(newTree);
749193326Sed                        /* make an aliveness / reachability analysis of the lambda
750198092Srdivacky                         * to determine if it can complete normally
751193326Sed                         */
752193326Sed                        flow.analyzeLambda(localEnv, newTree, make, true);
753193326Sed                    } finally {
754193326Sed                        log.popDiagnosticHandler(diagHandler);
755193326Sed                    }
756193326Sed                    return newTree.canCompleteNormally;
757193326Sed                } finally {
758243830Sdim                    JCBlock body = (JCBlock)newTree.body;
759243830Sdim                    unenterScanner.scan(body.stats);
760243830Sdim                    localEnv.info.scope.leave();
761243830Sdim                }
762243830Sdim            }
763243830Sdim
764243830Sdim            @Override
765243830Sdim            public void visitNewClass(JCNewClass tree) {
766243830Sdim                //do nothing
767243830Sdim            }
768243830Sdim
769243830Sdim            @Override
770243830Sdim            public void visitApply(JCMethodInvocation tree) {
771243830Sdim                //do nothing
772193326Sed            }
773193326Sed
774193326Sed            @Override
775193326Sed            public void visitReference(JCMemberReference tree) {
776193326Sed                Check.CheckContext checkContext = resultInfo.checkContext;
777193326Sed                Type pt = resultInfo.pt;
778193326Sed                if (!inferenceContext.inferencevars.contains(pt)) {
779193326Sed                    try {
780193326Sed                        types.findDescriptorType(pt);
781193326Sed                    } catch (Types.FunctionDescriptorLookupError ex) {
782193326Sed                        checkContext.report(null, ex.getDiagnostic());
783243830Sdim                    }
784243830Sdim                    Env<AttrContext> localEnv = env.dup(tree);
785193326Sed                    JCExpression exprTree = (JCExpression)attribSpeculative(tree.getQualifierExpression(), localEnv,
786243830Sdim                            attr.memberReferenceQualifierResult(tree));
787249423Sdim                    ListBuffer<Type> argtypes = new ListBuffer<>();
788193326Sed                    for (Type t : types.findDescriptorType(pt).getParameterTypes()) {
789193326Sed                        argtypes.append(Type.noType);
790193326Sed                    }
791193326Sed                    JCMemberReference mref2 = new TreeCopier<Void>(make).copy(tree);
792193326Sed                    mref2.expr = exprTree;
793193326Sed                    Symbol lookupSym =
794193326Sed                            rs.resolveMemberReference(localEnv, mref2, exprTree.type,
795193326Sed                                    tree.name, argtypes.toList(), List.nil(), rs.arityMethodCheck,
796243830Sdim                                    inferenceContext, rs.structuralReferenceChooser).fst;
797193326Sed                    switch (lookupSym.kind) {
798193326Sed                        case WRONG_MTH:
799193326Sed                        case WRONG_MTHS:
800193326Sed                            //note: as argtypes are erroneous types, type-errors must
801198092Srdivacky                            //have been caused by arity mismatch
802193326Sed                            checkContext.report(tree, diags.fragment(Fragments.IncompatibleArgTypesInMref));
803243830Sdim                            break;
804249423Sdim                        case ABSENT_MTH:
805198092Srdivacky                        case STATICERR:
806193326Sed                            //if no method found, or method found with wrong staticness, report better message
807193326Sed                            checkContext.report(tree, ((ResolveError)lookupSym).getDiagnostic(DiagnosticType.FRAGMENT,
808198092Srdivacky                                    tree, exprTree.type.tsym, exprTree.type, tree.name, argtypes.toList(), List.nil()));
809193326Sed                            break;
810198092Srdivacky                    }
811193326Sed                }
812193326Sed            }
813193326Sed        }
814193326Sed
815193326Sed        /* This visitor looks for return statements, its analysis will determine if
816193326Sed         * a lambda body is void or value compatible. We must analyze return
817193326Sed         * statements contained in the lambda body only, thus any return statement
818193326Sed         * contained in an inner class or inner lambda body, should be ignored.
819193326Sed         */
820193326Sed        class LambdaBodyStructChecker extends TreeScanner {
821193326Sed            boolean isVoidCompatible = true;
822193326Sed            boolean isPotentiallyValueCompatible = true;
823193326Sed
824193326Sed            @Override
825193326Sed            public void visitClassDef(JCClassDecl tree) {
826193326Sed                // do nothing
827201361Srdivacky            }
828201361Srdivacky
829193326Sed            @Override
830198092Srdivacky            public void visitLambda(JCLambda tree) {
831198092Srdivacky                // do nothing
832201361Srdivacky            }
833201361Srdivacky
834193326Sed            @Override
835193326Sed            public void visitNewClass(JCNewClass tree) {
836193326Sed                // do nothing
837239462Sdim            }
838234353Sdim
839234353Sdim            @Override
840234353Sdim            public void visitReturn(JCReturn tree) {
841234353Sdim                if (tree.expr != null) {
842234353Sdim                    isVoidCompatible = false;
843226633Sdim                } else {
844226633Sdim                    isPotentiallyValueCompatible = false;
845226633Sdim                }
846226633Sdim            }
847226633Sdim        }
848226633Sdim    }
849226633Sdim
850226633Sdim    /** an empty deferred attribution context - all methods throw exceptions */
851226633Sdim    final DeferredAttrContext emptyDeferredAttrContext;
852226633Sdim
853226633Sdim    /** The AttrMode to descriptive name mapping */
854226633Sdim    private static final EnumMap<AttrMode, String> deferredTypeMapDescriptions;
855234353Sdim    static {
856226633Sdim        deferredTypeMapDescriptions = new EnumMap<>(AttrMode.class);
857226633Sdim        deferredTypeMapDescriptions.put(AttrMode.CHECK, "deferredTypeMap[CHECK]");
858226633Sdim        deferredTypeMapDescriptions.put(AttrMode.SPECULATIVE, "deferredTypeMap[SPECULATIVE]");
859226633Sdim    }
860226633Sdim
861226633Sdim    /**
862226633Sdim     * Map a list of types possibly containing one or more deferred types
863226633Sdim     * into a list of ordinary types. Each deferred type D is mapped into a type T,
864226633Sdim     * where T is computed by retrieving the type that has already been
865226633Sdim     * computed for D during a previous deferred attribution round of the given kind.
866226633Sdim     */
867226633Sdim    class DeferredTypeMap extends Type.Mapping {
868234353Sdim        DeferredAttrContext deferredAttrContext;
869226633Sdim
870226633Sdim        protected DeferredTypeMap(AttrMode mode, Symbol msym, MethodResolutionPhase phase) {
871226633Sdim            super(deferredTypeMapDescriptions.get(mode));
872226633Sdim            this.deferredAttrContext = new DeferredAttrContext(mode, msym, phase,
873239462Sdim                    infer.emptyContext, emptyDeferredAttrContext, types.noWarnings);
874226633Sdim        }
875193326Sed
876226633Sdim        @Override
877226633Sdim        public Type apply(Type t) {
878234353Sdim            if (!t.hasTag(DEFERRED)) {
879193326Sed                return t.map(this);
880198092Srdivacky            } else {
881226633Sdim                DeferredType dt = (DeferredType)t;
882198092Srdivacky                return typeOf(dt);
883234353Sdim            }
884234353Sdim        }
885234353Sdim
886234353Sdim        protected Type typeOf(DeferredType dt) {
887226633Sdim            switch (deferredAttrContext.mode) {
888226633Sdim                case CHECK:
889226633Sdim                    return dt.tree.type == null ? Type.noType : dt.tree.type;
890193326Sed                case SPECULATIVE:
891193326Sed                    return dt.speculativeType(deferredAttrContext.msym, deferredAttrContext.phase);
892193326Sed            }
893193326Sed            Assert.error();
894234353Sdim            return null;
895234353Sdim        }
896234353Sdim    }
897234353Sdim
898234353Sdim    /**
899234353Sdim     * Specialized recovery deferred mapping.
900234353Sdim     * Each deferred type D is mapped into a type T, where T is computed either by
901234353Sdim     * (i) retrieving the type that has already been computed for D during a previous
902234353Sdim     * attribution round (as before), or (ii) by synthesizing a new type R for D
903234353Sdim     * (the latter step is useful in a recovery scenario).
904234353Sdim     */
905234353Sdim    public class RecoveryDeferredTypeMap extends DeferredTypeMap {
906234353Sdim
907234353Sdim        public RecoveryDeferredTypeMap(AttrMode mode, Symbol msym, MethodResolutionPhase phase) {
908198092Srdivacky            super(mode, msym, phase != null ? phase : MethodResolutionPhase.BOX);
909221345Sdim        }
910193326Sed
911193326Sed        @Override
912193326Sed        protected Type typeOf(DeferredType dt) {
913193326Sed            Type owntype = super.typeOf(dt);
914193326Sed            return owntype == Type.noType ?
915193326Sed                        recover(dt) : owntype;
916193326Sed        }
917193326Sed
918193326Sed        /**
919234353Sdim         * Synthesize a type for a deferred type that hasn't been previously
920234353Sdim         * reduced to an ordinary type. Functional deferred types and conditionals
921234353Sdim         * are mapped to themselves, in order to have a richer diagnostic
922234353Sdim         * representation. Remaining deferred types are attributed using
923198092Srdivacky         * a default expected type (j.l.Object).
924234353Sdim         */
925234353Sdim        private Type recover(DeferredType dt) {
926234353Sdim            dt.check(attr.new RecoveryInfo(deferredAttrContext) {
927234353Sdim                @Override
928234353Sdim                protected Type check(DiagnosticPosition pos, Type found) {
929234353Sdim                    return chk.checkNonVoid(pos, super.check(pos, found));
930234353Sdim                }
931234353Sdim            });
932234353Sdim            return super.apply(dt);
933234353Sdim        }
934234353Sdim    }
935234353Sdim
936234353Sdim    /**
937218893Sdim     * A special tree scanner that would only visit portions of a given tree.
938234353Sdim     * The set of nodes visited by the scanner can be customized at construction-time.
939234353Sdim     */
940234353Sdim    abstract static class FilterScanner extends TreeScanner {
941234353Sdim
942234353Sdim        final Filter<JCTree> treeFilter;
943234353Sdim
944234353Sdim        FilterScanner(final Set<JCTree.Tag> validTags) {
945234353Sdim            this.treeFilter = new Filter<JCTree>() {
946234353Sdim                public boolean accepts(JCTree t) {
947234353Sdim                    return validTags.contains(t.getTag());
948234353Sdim                }
949234353Sdim            };
950234353Sdim        }
951234353Sdim
952234353Sdim        @Override
953234353Sdim        public void scan(JCTree tree) {
954234353Sdim            if (tree != null) {
955234353Sdim                if (treeFilter.accepts(tree)) {
956234353Sdim                    super.scan(tree);
957234353Sdim                } else {
958234353Sdim                    skip(tree);
959234353Sdim                }
960234353Sdim            }
961234353Sdim        }
962234353Sdim
963234353Sdim        /**
964234353Sdim         * handler that is executed when a node has been discarded
965234353Sdim         */
966234353Sdim        void skip(JCTree tree) {}
967234353Sdim    }
968218893Sdim
969234353Sdim    /**
970234353Sdim     * A tree scanner suitable for visiting the target-type dependent nodes of
971234353Sdim     * a given argument expression.
972234353Sdim     */
973234353Sdim    static class PolyScanner extends FilterScanner {
974234353Sdim
975226633Sdim        PolyScanner() {
976218893Sdim            super(EnumSet.of(CONDEXPR, PARENS, LAMBDA, REFERENCE));
977234353Sdim        }
978234353Sdim    }
979218893Sdim
980234353Sdim    /**
981234353Sdim     * A tree scanner suitable for visiting the target-type dependent nodes nested
982234353Sdim     * within a lambda expression body.
983234353Sdim     */
984234353Sdim    static class LambdaReturnScanner extends FilterScanner {
985234353Sdim
986234353Sdim        LambdaReturnScanner() {
987234353Sdim            super(EnumSet.of(BLOCK, CASE, CATCH, DOLOOP, FOREACHLOOP,
988234353Sdim                    FORLOOP, IF, RETURN, SYNCHRONIZED, SWITCH, TRY, WHILELOOP));
989234353Sdim        }
990234353Sdim    }
991243830Sdim
992234353Sdim    /**
993193326Sed     * This visitor is used to check that structural expressions conform
994234353Sdim     * to their target - this step is required as inference could end up
995234353Sdim     * inferring types that make some of the nested expressions incompatible
996193326Sed     * with their corresponding instantiated target
997234353Sdim     */
998234353Sdim    class CheckStuckPolicy extends PolyScanner implements DeferredStuckPolicy, Infer.FreeTypeListener {
999243830Sdim
1000243830Sdim        Type pt;
1001243830Sdim        Infer.InferenceContext inferenceContext;
1002234353Sdim        Set<Type> stuckVars = new LinkedHashSet<>();
1003193326Sed        Set<Type> depVars = new LinkedHashSet<>();
1004193326Sed
1005234353Sdim        @Override
1006234353Sdim        public boolean isStuck() {
1007193326Sed            return !stuckVars.isEmpty();
1008234353Sdim        }
1009226633Sdim
1010234353Sdim        @Override
1011234353Sdim        public Set<Type> stuckVars() {
1012234353Sdim            return stuckVars;
1013193326Sed        }
1014193326Sed
1015234353Sdim        @Override
1016193326Sed        public Set<Type> depVars() {
1017198092Srdivacky            return depVars;
1018198092Srdivacky        }
1019193326Sed
1020234353Sdim        public CheckStuckPolicy(ResultInfo resultInfo, DeferredType dt) {
1021234353Sdim            this.pt = resultInfo.pt;
1022234353Sdim            this.inferenceContext = resultInfo.checkContext.inferenceContext();
1023234353Sdim            scan(dt.tree);
1024234353Sdim            if (!stuckVars.isEmpty()) {
1025234353Sdim                resultInfo.checkContext.inferenceContext()
1026234353Sdim                        .addFreeTypeListener(List.from(stuckVars), this);
1027234353Sdim            }
1028234353Sdim        }
1029234353Sdim
1030234353Sdim        @Override
1031234353Sdim        public void typesInferred(InferenceContext inferenceContext) {
1032234353Sdim            stuckVars.clear();
1033234353Sdim        }
1034234353Sdim
1035234353Sdim        @Override
1036234353Sdim        public void visitLambda(JCLambda tree) {
1037234353Sdim            if (inferenceContext.inferenceVars().contains(pt)) {
1038234353Sdim                stuckVars.add(pt);
1039234353Sdim            }
1040234353Sdim            if (!types.isFunctionalInterface(pt)) {
1041234353Sdim                return;
1042193326Sed            }
1043193326Sed            Type descType = types.findDescriptorType(pt);
1044198092Srdivacky            List<Type> freeArgVars = inferenceContext.freeVarsIn(descType.getParameterTypes());
1045193326Sed            if (tree.paramKind == JCLambda.ParameterKind.IMPLICIT &&
1046193326Sed                    freeArgVars.nonEmpty()) {
1047193326Sed                stuckVars.addAll(freeArgVars);
1048193326Sed                depVars.addAll(inferenceContext.freeVarsIn(descType.getReturnType()));
1049226633Sdim            }
1050234353Sdim            scanLambdaBody(tree, descType.getReturnType());
1051193326Sed        }
1052193326Sed
1053193326Sed        @Override
1054239462Sdim        public void visitReference(JCMemberReference tree) {
1055226633Sdim            scan(tree.expr);
1056226633Sdim            if (inferenceContext.inferenceVars().contains(pt)) {
1057226633Sdim                stuckVars.add(pt);
1058226633Sdim                return;
1059226633Sdim            }
1060226633Sdim            if (!types.isFunctionalInterface(pt)) {
1061226633Sdim                return;
1062226633Sdim            }
1063193326Sed
1064193326Sed            Type descType = types.findDescriptorType(pt);
1065193326Sed            List<Type> freeArgVars = inferenceContext.freeVarsIn(descType.getParameterTypes());
1066193326Sed            if (freeArgVars.nonEmpty() &&
1067226633Sdim                    tree.overloadKind == JCMemberReference.OverloadKind.OVERLOADED) {
1068226633Sdim                stuckVars.addAll(freeArgVars);
1069226633Sdim                depVars.addAll(inferenceContext.freeVarsIn(descType.getReturnType()));
1070193326Sed            }
1071226633Sdim        }
1072226633Sdim
1073226633Sdim        void scanLambdaBody(JCLambda lambda, final Type pt) {
1074226633Sdim            if (lambda.getBodyKind() == JCTree.JCLambda.BodyKind.EXPRESSION) {
1075226633Sdim                Type prevPt = this.pt;
1076226633Sdim                try {
1077226633Sdim                    this.pt = pt;
1078226633Sdim                    scan(lambda.body);
1079226633Sdim                } finally {
1080226633Sdim                    this.pt = prevPt;
1081226633Sdim                }
1082226633Sdim            } else {
1083226633Sdim                LambdaReturnScanner lambdaScanner = new LambdaReturnScanner() {
1084226633Sdim                    @Override
1085226633Sdim                    public void visitReturn(JCReturn tree) {
1086226633Sdim                        if (tree.expr != null) {
1087226633Sdim                            Type prevPt = CheckStuckPolicy.this.pt;
1088226633Sdim                            try {
1089226633Sdim                                CheckStuckPolicy.this.pt = pt;
1090226633Sdim                                CheckStuckPolicy.this.scan(tree.expr);
1091226633Sdim                            } finally {
1092226633Sdim                                CheckStuckPolicy.this.pt = prevPt;
1093226633Sdim                            }
1094226633Sdim                        }
1095226633Sdim                    }
1096226633Sdim                };
1097226633Sdim                lambdaScanner.scan(lambda.body);
1098226633Sdim            }
1099226633Sdim        }
1100226633Sdim    }
1101193326Sed
1102193326Sed    /**
1103193326Sed     * This visitor is used to check that structural expressions conform
1104193326Sed     * to their target - this step is required as inference could end up
1105193326Sed     * inferring types that make some of the nested expressions incompatible
1106239462Sdim     * with their corresponding instantiated target
1107193326Sed     */
1108193326Sed    class OverloadStuckPolicy extends CheckStuckPolicy implements DeferredStuckPolicy {
1109193326Sed
1110218893Sdim        boolean stuck;
1111234353Sdim
1112223017Sdim        @Override
1113226633Sdim        public boolean isStuck() {
1114226633Sdim            return super.isStuck() || stuck;
1115218893Sdim        }
1116218893Sdim
1117218893Sdim        public OverloadStuckPolicy(ResultInfo resultInfo, DeferredType dt) {
1118218893Sdim            super(resultInfo, dt);
1119223017Sdim        }
1120223017Sdim
1121239462Sdim        @Override
1122239462Sdim        public void visitLambda(JCLambda tree) {
1123223017Sdim            super.visitLambda(tree);
1124193326Sed            if (tree.paramKind == JCLambda.ParameterKind.IMPLICIT) {
1125193326Sed                stuck = true;
1126193326Sed            }
1127193326Sed        }
1128223017Sdim
1129193326Sed        @Override
1130223017Sdim        public void visitReference(JCMemberReference tree) {
1131193326Sed            super.visitReference(tree);
1132226633Sdim            if (tree.overloadKind == JCMemberReference.OverloadKind.OVERLOADED) {
1133198092Srdivacky                stuck = true;
1134193326Sed            }
1135193326Sed        }
1136193326Sed    }
1137193326Sed
1138193326Sed    /**
1139239462Sdim     * Does the argument expression {@code expr} need speculative type-checking?
1140239462Sdim     */
1141223017Sdim    boolean isDeferred(Env<AttrContext> env, JCExpression expr) {
1142193326Sed        DeferredChecker dc = new DeferredChecker(env);
1143193326Sed        dc.scan(expr);
1144223017Sdim        return dc.result.isPoly();
1145193326Sed    }
1146198092Srdivacky
1147193326Sed    /**
1148198092Srdivacky     * The kind of an argument expression. This is used by the analysis that
1149193326Sed     * determines as to whether speculative attribution is necessary.
1150198092Srdivacky     */
1151226633Sdim    enum ArgumentExpressionKind {
1152226633Sdim
1153226633Sdim        /** kind that denotes poly argument expression */
1154226633Sdim        POLY,
1155226633Sdim        /** kind that denotes a standalone expression */
1156226633Sdim        NO_POLY,
1157226633Sdim        /** kind that denotes a primitive/boxed standalone expression */
1158243830Sdim        PRIMITIVE;
1159226633Sdim
1160226633Sdim        /**
1161226633Sdim         * Does this kind denote a poly argument expression
1162226633Sdim         */
1163193326Sed        public final boolean isPoly() {
1164193326Sed            return this == POLY;
1165193326Sed        }
1166193326Sed
1167198092Srdivacky        /**
1168193326Sed         * Does this kind denote a primitive standalone expression
1169198092Srdivacky         */
1170226633Sdim        public final boolean isPrimitive() {
1171226633Sdim            return this == PRIMITIVE;
1172226633Sdim        }
1173226633Sdim
1174198092Srdivacky        /**
1175193326Sed         * Compute the kind of a standalone expression of a given type
1176193326Sed         */
1177226633Sdim        static ArgumentExpressionKind standaloneKind(Type type, Types types) {
1178198092Srdivacky            return types.unboxedTypeOrType(type).isPrimitive() ?
1179193326Sed                    ArgumentExpressionKind.PRIMITIVE :
1180193326Sed                    ArgumentExpressionKind.NO_POLY;
1181198092Srdivacky        }
1182193326Sed
1183234353Sdim        /**
1184193326Sed         * Compute the kind of a method argument expression given its symbol
1185198092Srdivacky         */
1186193326Sed        static ArgumentExpressionKind methodKind(Symbol sym, Types types) {
1187193326Sed            Type restype = sym.type.getReturnType();
1188193326Sed            if (sym.type.hasTag(FORALL) &&
1189198092Srdivacky                    restype.containsAny(((ForAll)sym.type).tvars)) {
1190193326Sed                return ArgumentExpressionKind.POLY;
1191198092Srdivacky            } else {
1192234353Sdim                return ArgumentExpressionKind.standaloneKind(restype, types);
1193234353Sdim            }
1194193326Sed        }
1195193326Sed    }
1196193326Sed
1197193326Sed    /**
1198193326Sed     * Tree scanner used for checking as to whether an argument expression
1199205219Srdivacky     * requires speculative attribution
1200218893Sdim     */
1201218893Sdim    final class DeferredChecker extends FilterScanner {
1202218893Sdim
1203239462Sdim        Env<AttrContext> env;
1204239462Sdim        ArgumentExpressionKind result;
1205205219Srdivacky
1206234353Sdim        public DeferredChecker(Env<AttrContext> env) {
1207234353Sdim            super(deferredCheckerTags);
1208234353Sdim            this.env = env;
1209234353Sdim        }
1210234353Sdim
1211234353Sdim        @Override
1212234353Sdim        public void visitLambda(JCLambda tree) {
1213234353Sdim            //a lambda is always a poly expression
1214234353Sdim            result = ArgumentExpressionKind.POLY;
1215234353Sdim        }
1216234353Sdim
1217234353Sdim        @Override
1218234353Sdim        public void visitReference(JCMemberReference tree) {
1219234353Sdim            //perform arity-based check
1220234353Sdim            Env<AttrContext> localEnv = env.dup(tree);
1221234353Sdim            JCExpression exprTree = (JCExpression)attribSpeculative(tree.getQualifierExpression(), localEnv,
1222234353Sdim                    attr.memberReferenceQualifierResult(tree));
1223234353Sdim            JCMemberReference mref2 = new TreeCopier<Void>(make).copy(tree);
1224234353Sdim            mref2.expr = exprTree;
1225234353Sdim            Symbol res =
1226234353Sdim                    rs.getMemberReference(tree, localEnv, mref2,
1227234353Sdim                        exprTree.type, tree.name);
1228234353Sdim            tree.sym = res;
1229234353Sdim            if (res.kind.isOverloadError() ||
1230234353Sdim                    res.type.hasTag(FORALL) ||
1231234353Sdim                    (res.flags() & Flags.VARARGS) != 0 ||
1232234353Sdim                    (TreeInfo.isStaticSelector(exprTree, tree.name.table.names) &&
1233234353Sdim                    exprTree.type.isRaw())) {
1234234353Sdim                tree.overloadKind = JCMemberReference.OverloadKind.OVERLOADED;
1235234353Sdim            } else {
1236234353Sdim                tree.overloadKind = JCMemberReference.OverloadKind.UNOVERLOADED;
1237234353Sdim            }
1238234353Sdim            //a method reference is always a poly expression
1239234353Sdim            result = ArgumentExpressionKind.POLY;
1240234353Sdim        }
1241234353Sdim
1242193326Sed        @Override
1243198092Srdivacky        public void visitTypeCast(JCTypeCast tree) {
1244226633Sdim            //a cast is always a standalone expression
1245226633Sdim            result = ArgumentExpressionKind.NO_POLY;
1246193326Sed        }
1247226633Sdim
1248226633Sdim        @Override
1249226633Sdim        public void visitConditional(JCConditional tree) {
1250212904Sdim            scan(tree.truepart);
1251198092Srdivacky            if (!result.isPrimitive()) {
1252226633Sdim                result = ArgumentExpressionKind.POLY;
1253226633Sdim                return;
1254226633Sdim            }
1255198092Srdivacky            scan(tree.falsepart);
1256226633Sdim            result = reduce(ArgumentExpressionKind.PRIMITIVE).isPrimitive() ?
1257226633Sdim                    ArgumentExpressionKind.PRIMITIVE :
1258193326Sed                    ArgumentExpressionKind.POLY;
1259226633Sdim
1260198092Srdivacky        }
1261234353Sdim
1262234353Sdim        @Override
1263234353Sdim        public void visitNewClass(JCNewClass tree) {
1264226633Sdim            result = TreeInfo.isDiamond(tree) ?
1265226633Sdim                    ArgumentExpressionKind.POLY : ArgumentExpressionKind.NO_POLY;
1266243830Sdim        }
1267243830Sdim
1268243830Sdim        @Override
1269226633Sdim        public void visitApply(JCMethodInvocation tree) {
1270239462Sdim            Name name = TreeInfo.name(tree.meth);
1271239462Sdim
1272239462Sdim            //fast path
1273239462Sdim            if (tree.typeargs.nonEmpty() ||
1274239462Sdim                    name == name.table.names._this ||
1275226633Sdim                    name == name.table.names._super) {
1276226633Sdim                result = ArgumentExpressionKind.NO_POLY;
1277226633Sdim                return;
1278226633Sdim            }
1279226633Sdim
1280226633Sdim            //slow path
1281226633Sdim            Symbol sym = quicklyResolveMethod(env, tree);
1282226633Sdim
1283226633Sdim            if (sym == null) {
1284193326Sed                result = ArgumentExpressionKind.POLY;
1285226633Sdim                return;
1286226633Sdim            }
1287226633Sdim
1288226633Sdim            result = analyzeCandidateMethods(sym, ArgumentExpressionKind.PRIMITIVE,
1289198092Srdivacky                    argumentKindAnalyzer);
1290226633Sdim        }
1291226633Sdim        //where
1292226633Sdim            private boolean isSimpleReceiver(JCTree rec) {
1293226633Sdim                switch (rec.getTag()) {
1294226633Sdim                    case IDENT:
1295226633Sdim                        return true;
1296226633Sdim                    case SELECT:
1297226633Sdim                        return isSimpleReceiver(((JCFieldAccess)rec).selected);
1298226633Sdim                    case TYPEAPPLY:
1299243830Sdim                    case TYPEARRAY:
1300243830Sdim                        return true;
1301243830Sdim                    case ANNOTATED_TYPE:
1302226633Sdim                        return isSimpleReceiver(((JCAnnotatedType)rec).underlyingType);
1303193326Sed                    case APPLY:
1304226633Sdim                        return true;
1305226633Sdim                    default:
1306234353Sdim                        return false;
1307234353Sdim                }
1308234353Sdim            }
1309226633Sdim            private ArgumentExpressionKind reduce(ArgumentExpressionKind kind) {
1310226633Sdim                return argumentKindAnalyzer.reduce(result, kind);
1311226633Sdim            }
1312226633Sdim            MethodAnalyzer<ArgumentExpressionKind> argumentKindAnalyzer =
1313226633Sdim                    new MethodAnalyzer<ArgumentExpressionKind>() {
1314243830Sdim                @Override
1315226633Sdim                public ArgumentExpressionKind process(MethodSymbol ms) {
1316243830Sdim                    return ArgumentExpressionKind.methodKind(ms, types);
1317198092Srdivacky                }
1318234353Sdim                @Override
1319234353Sdim                public ArgumentExpressionKind reduce(ArgumentExpressionKind kind1,
1320234353Sdim                                                     ArgumentExpressionKind kind2) {
1321234353Sdim                    switch (kind1) {
1322234353Sdim                        case PRIMITIVE: return kind2;
1323234353Sdim                        case NO_POLY: return kind2.isPoly() ? kind2 : kind1;
1324234353Sdim                        case POLY: return kind1;
1325234353Sdim                        default:
1326234353Sdim                            Assert.error();
1327234353Sdim                            return null;
1328234353Sdim                    }
1329234353Sdim                }
1330234353Sdim                @Override
1331234353Sdim                public boolean shouldStop(ArgumentExpressionKind result) {
1332234353Sdim                    return result.isPoly();
1333234353Sdim                }
1334193326Sed            };
1335193326Sed
1336193326Sed        @Override
1337198092Srdivacky        public void visitLiteral(JCLiteral tree) {
1338193326Sed            Type litType = attr.litType(tree.typetag);
1339234353Sdim            result = ArgumentExpressionKind.standaloneKind(litType, types);
1340234353Sdim        }
1341234353Sdim
1342234353Sdim        @Override
1343234353Sdim        void skip(JCTree tree) {
1344234353Sdim            result = ArgumentExpressionKind.NO_POLY;
1345234353Sdim        }
1346234353Sdim
1347234353Sdim        private Symbol quicklyResolveMethod(Env<AttrContext> env, final JCMethodInvocation tree) {
1348234353Sdim            final JCExpression rec = tree.meth.hasTag(SELECT) ?
1349234353Sdim                    ((JCFieldAccess)tree.meth).selected :
1350234353Sdim                    null;
1351234353Sdim
1352234353Sdim            if (rec != null && !isSimpleReceiver(rec)) {
1353193326Sed                return null;
1354193326Sed            }
1355218893Sdim
1356243830Sdim            Type site;
1357243830Sdim
1358218893Sdim            if (rec != null) {
1359218893Sdim                if (rec.hasTag(APPLY)) {
1360218893Sdim                    Symbol recSym = quicklyResolveMethod(env, (JCMethodInvocation) rec);
1361226633Sdim                    if (recSym == null)
1362193326Sed                        return null;
1363193326Sed                    Symbol resolvedReturnType =
1364218893Sdim                            analyzeCandidateMethods(recSym, syms.errSymbol, returnSymbolAnalyzer);
1365212904Sdim                    if (resolvedReturnType == null)
1366218893Sdim                        return null;
1367243830Sdim                    site = resolvedReturnType.type;
1368212904Sdim                } else {
1369243830Sdim                    site = attribSpeculative(rec, env, attr.unknownTypeExprInfo).type;
1370218893Sdim                }
1371212904Sdim            } else {
1372218893Sdim                site = env.enclClass.sym.type;
1373212904Sdim            }
1374212904Sdim
1375193326Sed            while (site.hasTag(TYPEVAR)) {
1376193326Sed                site = site.getUpperBound();
1377193326Sed            }
1378243830Sdim
1379243830Sdim            site = types.capture(site);
1380243830Sdim
1381243830Sdim            List<Type> args = rs.dummyArgs(tree.args.length());
1382243830Sdim            Name name = TreeInfo.name(tree.meth);
1383243830Sdim
1384243830Sdim            Resolve.LookupHelper lh = rs.new LookupHelper(name, site, args, List.<Type>nil(), MethodResolutionPhase.VARARITY) {
1385226633Sdim                @Override
1386226633Sdim                Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) {
1387243830Sdim                    return rec == null ?
1388243830Sdim                        rs.findFun(env, name, argtypes, typeargtypes, phase.isBoxingRequired(), phase.isVarargsRequired()) :
1389243830Sdim                        rs.findMethod(env, site, name, argtypes, typeargtypes, phase.isBoxingRequired(), phase.isVarargsRequired(), false);
1390243830Sdim                }
1391243830Sdim                @Override
1392243830Sdim                Symbol access(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, Symbol sym) {
1393243830Sdim                    return sym;
1394243830Sdim                }
1395243830Sdim            };
1396243830Sdim
1397234353Sdim            return rs.lookupMethod(env, tree, site.tsym, rs.arityMethodCheck, lh);
1398234353Sdim        }
1399234353Sdim        //where:
1400234353Sdim            MethodAnalyzer<Symbol> returnSymbolAnalyzer = new MethodAnalyzer<Symbol>() {
1401243830Sdim                @Override
1402243830Sdim                public Symbol process(MethodSymbol ms) {
1403243830Sdim                    ArgumentExpressionKind kind = ArgumentExpressionKind.methodKind(ms, types);
1404243830Sdim                    if (kind == ArgumentExpressionKind.POLY || ms.getReturnType().hasTag(TYPEVAR))
1405243830Sdim                        return null;
1406243830Sdim                    return ms.getReturnType().tsym;
1407243830Sdim                }
1408243830Sdim                @Override
1409243830Sdim                public Symbol reduce(Symbol s1, Symbol s2) {
1410243830Sdim                    return s1 == syms.errSymbol ? s2 : s1 == s2 ? s1 : null;
1411243830Sdim                }
1412243830Sdim                @Override
1413243830Sdim                public boolean shouldStop(Symbol result) {
1414243830Sdim                    return result == null;
1415243830Sdim                }
1416243830Sdim            };
1417243830Sdim
1418243830Sdim        /**
1419243830Sdim         * Process the result of Resolve.lookupMethod. If sym is a method symbol, the result of
1420243830Sdim         * MethodAnalyzer.process is returned. If sym is an ambiguous symbol, all the candidate
1421243830Sdim         * methods are inspected one by one, using MethodAnalyzer.process. The outcomes are
1422243830Sdim         * reduced using MethodAnalyzer.reduce (using defaultValue as the first value over which
1423243830Sdim         * the reduction runs). MethodAnalyzer.shouldStop can be used to stop the inspection early.
1424243830Sdim         */
1425243830Sdim        <E> E analyzeCandidateMethods(Symbol sym, E defaultValue, MethodAnalyzer<E> analyzer) {
1426243830Sdim            switch (sym.kind) {
1427243830Sdim                case MTH:
1428243830Sdim                    return analyzer.process((MethodSymbol) sym);
1429243830Sdim                case AMBIGUOUS:
1430243830Sdim                    Resolve.AmbiguityError err = (Resolve.AmbiguityError)sym.baseSymbol();
1431243830Sdim                    E res = defaultValue;
1432243830Sdim                    for (Symbol s : err.ambiguousSyms) {
1433234353Sdim                        if (s.kind == MTH) {
1434234353Sdim                            res = analyzer.reduce(res, analyzer.process((MethodSymbol) s));
1435226633Sdim                            if (analyzer.shouldStop(res))
1436239462Sdim                                return res;
1437239462Sdim                        }
1438239462Sdim                    }
1439239462Sdim                    return res;
1440239462Sdim                default:
1441239462Sdim                    return defaultValue;
1442193326Sed            }
1443193326Sed        }
1444193326Sed    }
1445193326Sed
1446218893Sdim    /** Analyzer for methods - used by analyzeCandidateMethods. */
1447193326Sed    interface MethodAnalyzer<E> {
1448234353Sdim        E process(MethodSymbol ms);
1449193326Sed        E reduce(E e1, E e2);
1450198092Srdivacky        boolean shouldStop(E result);
1451205219Srdivacky    }
1452193326Sed
1453218893Sdim    //where
1454218893Sdim    private EnumSet<JCTree.Tag> deferredCheckerTags =
1455218893Sdim            EnumSet.of(LAMBDA, REFERENCE, PARENS, TYPECAST,
1456205219Srdivacky                    CONDEXPR, NEWCLASS, APPLY, LITERAL);
1457193326Sed}
1458239462Sdim