Types.java revision 2897:524255b0bec0
1219019Sgabor/*
2219019Sgabor * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
3219019Sgabor * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4219019Sgabor *
5219019Sgabor * This code is free software; you can redistribute it and/or modify it
6219019Sgabor * under the terms of the GNU General Public License version 2 only, as
7219019Sgabor * published by the Free Software Foundation.  Oracle designates this
8219019Sgabor * particular file as subject to the "Classpath" exception as provided
9219019Sgabor * by Oracle in the LICENSE file that accompanied this code.
10219019Sgabor *
11219019Sgabor * This code is distributed in the hope that it will be useful, but WITHOUT
12219019Sgabor * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13219019Sgabor * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14219019Sgabor * version 2 for more details (a copy is included in the LICENSE file that
15219019Sgabor * accompanied this code).
16219019Sgabor *
17219019Sgabor * You should have received a copy of the GNU General Public License version
18219019Sgabor * 2 along with this work; if not, write to the Free Software Foundation,
19219019Sgabor * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20219019Sgabor *
21219019Sgabor * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22219019Sgabor * or visit www.oracle.com if you need additional information or have any
23219019Sgabor * questions.
24219019Sgabor */
25219019Sgabor
26219019Sgaborpackage com.sun.tools.javac.code;
27219019Sgabor
28219019Sgaborimport java.lang.ref.SoftReference;
29219019Sgaborimport java.util.HashSet;
30219019Sgaborimport java.util.HashMap;
31219019Sgaborimport java.util.Locale;
32219019Sgaborimport java.util.Map;
33219019Sgaborimport java.util.Set;
34219019Sgaborimport java.util.WeakHashMap;
35219019Sgaborimport java.util.function.BiPredicate;
36219019Sgaborimport java.util.stream.Collector;
37219019Sgabor
38219019Sgaborimport javax.tools.JavaFileObject;
39219019Sgabor
40219019Sgaborimport com.sun.tools.javac.code.Attribute.RetentionPolicy;
41219019Sgaborimport com.sun.tools.javac.code.Lint.LintCategory;
42219019Sgaborimport com.sun.tools.javac.code.Type.UndetVar.InferenceBound;
43219019Sgaborimport com.sun.tools.javac.code.TypeMetadata.Entry.Kind;
44219019Sgaborimport com.sun.tools.javac.comp.AttrContext;
45219019Sgaborimport com.sun.tools.javac.comp.Check;
46219019Sgaborimport com.sun.tools.javac.comp.Enter;
47219019Sgaborimport com.sun.tools.javac.comp.Env;
48219019Sgaborimport com.sun.tools.javac.util.*;
49219019Sgabor
50219019Sgaborimport static com.sun.tools.javac.code.BoundKind.*;
51219019Sgaborimport static com.sun.tools.javac.code.Flags.*;
52219019Sgaborimport static com.sun.tools.javac.code.Kinds.Kind.*;
53219019Sgaborimport static com.sun.tools.javac.code.Scope.*;
54219019Sgaborimport static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE;
55219019Sgaborimport static com.sun.tools.javac.code.Symbol.*;
56219019Sgaborimport static com.sun.tools.javac.code.Type.*;
57219019Sgaborimport static com.sun.tools.javac.code.TypeTag.*;
58219019Sgaborimport static com.sun.tools.javac.jvm.ClassFile.externalize;
59219019Sgabor
60219019Sgabor/**
61219019Sgabor * Utility class containing various operations on types.
62219019Sgabor *
63219019Sgabor * <p>Unless other names are more illustrative, the following naming
64219019Sgabor * conventions should be observed in this file:
65219019Sgabor *
66219019Sgabor * <dl>
67219019Sgabor * <dt>t</dt>
68219019Sgabor * <dd>If the first argument to an operation is a type, it should be named t.</dd>
69219019Sgabor * <dt>s</dt>
70219019Sgabor * <dd>Similarly, if the second argument to an operation is a type, it should be named s.</dd>
71219019Sgabor * <dt>ts</dt>
72219019Sgabor * <dd>If an operations takes a list of types, the first should be named ts.</dd>
73219019Sgabor * <dt>ss</dt>
74219019Sgabor * <dd>A second list of types should be named ss.</dd>
75219019Sgabor * </dl>
76219019Sgabor *
77219019Sgabor * <p><b>This is NOT part of any supported API.
78219019Sgabor * If you write code that depends on this, you do so at your own risk.
79219019Sgabor * This code and its internal interfaces are subject to change or
80219019Sgabor * deletion without notice.</b>
81219019Sgabor */
82219019Sgaborpublic class Types {
83219019Sgabor    protected static final Context.Key<Types> typesKey = new Context.Key<>();
84219019Sgabor
85219019Sgabor    final Symtab syms;
86219019Sgabor    final JavacMessages messages;
87219019Sgabor    final Names names;
88219019Sgabor    final boolean allowObjectToPrimitiveCast;
89219019Sgabor    final boolean allowDefaultMethods;
90219019Sgabor    final Check chk;
91219019Sgabor    final Enter enter;
92219019Sgabor    JCDiagnostic.Factory diags;
93219019Sgabor    List<Warner> warnStack = List.nil();
94219019Sgabor    final Name capturedName;
95219019Sgabor    private final FunctionDescriptorLookupError functionDescriptorLookupError;
96219019Sgabor
97219019Sgabor    public final Warner noWarnings;
98219019Sgabor
99219019Sgabor    // <editor-fold defaultstate="collapsed" desc="Instantiating">
100219019Sgabor    public static Types instance(Context context) {
101219019Sgabor        Types instance = context.get(typesKey);
102219019Sgabor        if (instance == null)
103219019Sgabor            instance = new Types(context);
104219019Sgabor        return instance;
105219019Sgabor    }
106219019Sgabor
107219019Sgabor    protected Types(Context context) {
108219019Sgabor        context.put(typesKey, this);
109219019Sgabor        syms = Symtab.instance(context);
110219019Sgabor        names = Names.instance(context);
111219019Sgabor        Source source = Source.instance(context);
112219019Sgabor        allowObjectToPrimitiveCast = source.allowObjectToPrimitiveCast();
113219019Sgabor        allowDefaultMethods = source.allowDefaultMethods();
114219019Sgabor        chk = Check.instance(context);
115219019Sgabor        enter = Enter.instance(context);
116219019Sgabor        capturedName = names.fromString("<captured wildcard>");
117219019Sgabor        messages = JavacMessages.instance(context);
118219019Sgabor        diags = JCDiagnostic.Factory.instance(context);
119219019Sgabor        functionDescriptorLookupError = new FunctionDescriptorLookupError();
120219019Sgabor        noWarnings = new Warner(null);
121219019Sgabor    }
122219019Sgabor    // </editor-fold>
123219019Sgabor
124219019Sgabor    // <editor-fold defaultstate="collapsed" desc="bounds">
125219019Sgabor    /**
126219019Sgabor     * Get a wildcard's upper bound, returning non-wildcards unchanged.
127219019Sgabor     * @param t a type argument, either a wildcard or a type
128219019Sgabor     */
129219019Sgabor    public Type wildUpperBound(Type t) {
130219019Sgabor        if (t.hasTag(WILDCARD)) {
131219019Sgabor            WildcardType w = (WildcardType) t;
132219019Sgabor            if (w.isSuperBound())
133219019Sgabor                return w.bound == null ? syms.objectType : w.bound.bound;
134219019Sgabor            else
135219019Sgabor                return wildUpperBound(w.type);
136219019Sgabor        }
137219019Sgabor        else return t;
138219019Sgabor    }
139219019Sgabor
140219019Sgabor    /**
141219019Sgabor     * Get a capture variable's upper bound, returning other types unchanged.
142219019Sgabor     * @param t a type
143219019Sgabor     */
144219019Sgabor    public Type cvarUpperBound(Type t) {
145219019Sgabor        if (t.hasTag(TYPEVAR)) {
146219019Sgabor            TypeVar v = (TypeVar) t;
147219019Sgabor            return v.isCaptured() ? cvarUpperBound(v.bound) : v;
148219019Sgabor        }
149219019Sgabor        else return t;
150219019Sgabor    }
151219019Sgabor
152219019Sgabor    /**
153219019Sgabor     * Get a wildcard's lower bound, returning non-wildcards unchanged.
154219019Sgabor     * @param t a type argument, either a wildcard or a type
155219019Sgabor     */
156219019Sgabor    public Type wildLowerBound(Type t) {
157219019Sgabor        if (t.hasTag(WILDCARD)) {
158219019Sgabor            WildcardType w = (WildcardType) t;
159219019Sgabor            return w.isExtendsBound() ? syms.botType : wildLowerBound(w.type);
160219019Sgabor        }
161219019Sgabor        else return t;
162219019Sgabor    }
163219019Sgabor
164219019Sgabor    /**
165219019Sgabor     * Get a capture variable's lower bound, returning other types unchanged.
166219019Sgabor     * @param t a type
167219019Sgabor     */
168219019Sgabor    public Type cvarLowerBound(Type t) {
169219019Sgabor        if (t.hasTag(TYPEVAR) && ((TypeVar) t).isCaptured()) {
170219019Sgabor            return cvarLowerBound(t.getLowerBound());
171219019Sgabor        }
172219019Sgabor        else return t;
173219019Sgabor    }
174219019Sgabor
175219019Sgabor    /**
176219019Sgabor     * Recursively skip type-variables until a class/array type is found; capture conversion is then
177219019Sgabor     * (optionally) applied to the resulting type. This is useful for i.e. computing a site that is
178219019Sgabor     * suitable for a method lookup.
179219019Sgabor     */
180219019Sgabor    public Type skipTypeVars(Type site, boolean capture) {
181219019Sgabor        while (site.hasTag(TYPEVAR)) {
182219019Sgabor            site = site.getUpperBound();
183219019Sgabor        }
184219019Sgabor        return capture ? capture(site) : site;
185219019Sgabor    }
186219019Sgabor    // </editor-fold>
187219019Sgabor
188219019Sgabor    // <editor-fold defaultstate="collapsed" desc="isUnbounded">
189219019Sgabor    /**
190219019Sgabor     * Checks that all the arguments to a class are unbounded
191219019Sgabor     * wildcards or something else that doesn't make any restrictions
192219019Sgabor     * on the arguments. If a class isUnbounded, a raw super- or
193219019Sgabor     * subclass can be cast to it without a warning.
194219019Sgabor     * @param t a type
195219019Sgabor     * @return true iff the given type is unbounded or raw
196219019Sgabor     */
197219019Sgabor    public boolean isUnbounded(Type t) {
198219019Sgabor        return isUnbounded.visit(t);
199219019Sgabor    }
200219019Sgabor    // where
201219019Sgabor        private final UnaryVisitor<Boolean> isUnbounded = new UnaryVisitor<Boolean>() {
202219019Sgabor
203219019Sgabor            public Boolean visitType(Type t, Void ignored) {
204219019Sgabor                return true;
205219019Sgabor            }
206219019Sgabor
207219019Sgabor            @Override
208219019Sgabor            public Boolean visitClassType(ClassType t, Void ignored) {
209219019Sgabor                List<Type> parms = t.tsym.type.allparams();
210219019Sgabor                List<Type> args = t.allparams();
211219019Sgabor                while (parms.nonEmpty()) {
212219019Sgabor                    WildcardType unb = new WildcardType(syms.objectType,
213219019Sgabor                                                        BoundKind.UNBOUND,
214219019Sgabor                                                        syms.boundClass,
215219019Sgabor                                                        (TypeVar)parms.head);
216219019Sgabor                    if (!containsType(args.head, unb))
217219019Sgabor                        return false;
218219019Sgabor                    parms = parms.tail;
219219019Sgabor                    args = args.tail;
220219019Sgabor                }
221219019Sgabor                return true;
222219019Sgabor            }
223219019Sgabor        };
224219019Sgabor    // </editor-fold>
225219019Sgabor
226219019Sgabor    // <editor-fold defaultstate="collapsed" desc="asSub">
227219019Sgabor    /**
228219019Sgabor     * Return the least specific subtype of t that starts with symbol
229219019Sgabor     * sym.  If none exists, return null.  The least specific subtype
230219019Sgabor     * is determined as follows:
231219019Sgabor     *
232219019Sgabor     * <p>If there is exactly one parameterized instance of sym that is a
233219019Sgabor     * subtype of t, that parameterized instance is returned.<br>
234219019Sgabor     * Otherwise, if the plain type or raw type `sym' is a subtype of
235219019Sgabor     * type t, the type `sym' itself is returned.  Otherwise, null is
236219019Sgabor     * returned.
237219019Sgabor     */
238219019Sgabor    public Type asSub(Type t, Symbol sym) {
239219019Sgabor        return asSub.visit(t, sym);
240219019Sgabor    }
241219019Sgabor    // where
242219019Sgabor        private final SimpleVisitor<Type,Symbol> asSub = new SimpleVisitor<Type,Symbol>() {
243219019Sgabor
244219019Sgabor            public Type visitType(Type t, Symbol sym) {
245219019Sgabor                return null;
246219019Sgabor            }
247219019Sgabor
248219019Sgabor            @Override
249219019Sgabor            public Type visitClassType(ClassType t, Symbol sym) {
250219019Sgabor                if (t.tsym == sym)
251219019Sgabor                    return t;
252219019Sgabor                Type base = asSuper(sym.type, t.tsym);
253219019Sgabor                if (base == null)
254219019Sgabor                    return null;
255219019Sgabor                ListBuffer<Type> from = new ListBuffer<>();
256219019Sgabor                ListBuffer<Type> to = new ListBuffer<>();
257219019Sgabor                try {
258219019Sgabor                    adapt(base, t, from, to);
259219019Sgabor                } catch (AdaptFailure ex) {
260219019Sgabor                    return null;
261219019Sgabor                }
262219019Sgabor                Type res = subst(sym.type, from.toList(), to.toList());
263219019Sgabor                if (!isSubtype(res, t))
264219019Sgabor                    return null;
265219019Sgabor                ListBuffer<Type> openVars = new ListBuffer<>();
266219019Sgabor                for (List<Type> l = sym.type.allparams();
267219019Sgabor                     l.nonEmpty(); l = l.tail)
268219019Sgabor                    if (res.contains(l.head) && !t.contains(l.head))
269219019Sgabor                        openVars.append(l.head);
270219019Sgabor                if (openVars.nonEmpty()) {
271219019Sgabor                    if (t.isRaw()) {
272219019Sgabor                        // The subtype of a raw type is raw
273219019Sgabor                        res = erasure(res);
274219019Sgabor                    } else {
275219019Sgabor                        // Unbound type arguments default to ?
276219019Sgabor                        List<Type> opens = openVars.toList();
277219019Sgabor                        ListBuffer<Type> qs = new ListBuffer<>();
278219019Sgabor                        for (List<Type> iter = opens; iter.nonEmpty(); iter = iter.tail) {
279219019Sgabor                            qs.append(new WildcardType(syms.objectType, BoundKind.UNBOUND,
280219019Sgabor                                                       syms.boundClass, (TypeVar) iter.head));
281219019Sgabor                        }
282219019Sgabor                        res = subst(res, opens, qs.toList());
283219019Sgabor                    }
284219019Sgabor                }
285219019Sgabor                return res;
286219019Sgabor            }
287219019Sgabor
288219019Sgabor            @Override
289219019Sgabor            public Type visitErrorType(ErrorType t, Symbol sym) {
290219019Sgabor                return t;
291219019Sgabor            }
292219019Sgabor        };
293219019Sgabor    // </editor-fold>
294219019Sgabor
295219019Sgabor    // <editor-fold defaultstate="collapsed" desc="isConvertible">
296219019Sgabor    /**
297219019Sgabor     * Is t a subtype of or convertible via boxing/unboxing
298219019Sgabor     * conversion to s?
299219019Sgabor     */
300219019Sgabor    public boolean isConvertible(Type t, Type s, Warner warn) {
301219019Sgabor        if (t.hasTag(ERROR)) {
302219019Sgabor            return true;
303219019Sgabor        }
304219019Sgabor        boolean tPrimitive = t.isPrimitive();
305219019Sgabor        boolean sPrimitive = s.isPrimitive();
306219019Sgabor        if (tPrimitive == sPrimitive) {
307219019Sgabor            return isSubtypeUnchecked(t, s, warn);
308219019Sgabor        }
309219019Sgabor        return tPrimitive
310219019Sgabor            ? isSubtype(boxedClass(t).type, s)
311219019Sgabor            : isSubtype(unboxedType(t), s);
312219019Sgabor    }
313219019Sgabor
314219019Sgabor    /**
315219019Sgabor     * Is t a subtype of or convertible via boxing/unboxing
316219019Sgabor     * conversions to s?
317219019Sgabor     */
318219019Sgabor    public boolean isConvertible(Type t, Type s) {
319219019Sgabor        return isConvertible(t, s, noWarnings);
320219019Sgabor    }
321219019Sgabor    // </editor-fold>
322219019Sgabor
323219019Sgabor    // <editor-fold defaultstate="collapsed" desc="findSam">
324219019Sgabor
325219019Sgabor    /**
326219019Sgabor     * Exception used to report a function descriptor lookup failure. The exception
327219019Sgabor     * wraps a diagnostic that can be used to generate more details error
328219019Sgabor     * messages.
329219019Sgabor     */
330219019Sgabor    public static class FunctionDescriptorLookupError extends RuntimeException {
331219019Sgabor        private static final long serialVersionUID = 0;
332219019Sgabor
333219019Sgabor        JCDiagnostic diagnostic;
334219019Sgabor
335219019Sgabor        FunctionDescriptorLookupError() {
336219019Sgabor            this.diagnostic = null;
337219019Sgabor        }
338219019Sgabor
339219019Sgabor        FunctionDescriptorLookupError setMessage(JCDiagnostic diag) {
340219019Sgabor            this.diagnostic = diag;
341219019Sgabor            return this;
342219019Sgabor        }
343219019Sgabor
344219019Sgabor        public JCDiagnostic getDiagnostic() {
345219019Sgabor            return diagnostic;
346219019Sgabor        }
347219019Sgabor    }
348219019Sgabor
349219019Sgabor    /**
350219019Sgabor     * A cache that keeps track of function descriptors associated with given
351219019Sgabor     * functional interfaces.
352219019Sgabor     */
353219019Sgabor    class DescriptorCache {
354219019Sgabor
355219019Sgabor        private WeakHashMap<TypeSymbol, Entry> _map = new WeakHashMap<>();
356219019Sgabor
357219019Sgabor        class FunctionDescriptor {
358219019Sgabor            Symbol descSym;
359219019Sgabor
360219019Sgabor            FunctionDescriptor(Symbol descSym) {
361219019Sgabor                this.descSym = descSym;
362219019Sgabor            }
363219019Sgabor
364219019Sgabor            public Symbol getSymbol() {
365219019Sgabor                return descSym;
366219019Sgabor            }
367219019Sgabor
368219019Sgabor            public Type getType(Type site) {
369219019Sgabor                site = removeWildcards(site);
370219019Sgabor                if (!chk.checkValidGenericType(site)) {
371219019Sgabor                    //if the inferred functional interface type is not well-formed,
372219019Sgabor                    //or if it's not a subtype of the original target, issue an error
373219019Sgabor                    throw failure(diags.fragment("no.suitable.functional.intf.inst", site));
374219019Sgabor                }
375219019Sgabor                return memberType(site, descSym);
376219019Sgabor            }
377219019Sgabor        }
378219019Sgabor
379219019Sgabor        class Entry {
380219019Sgabor            final FunctionDescriptor cachedDescRes;
381219019Sgabor            final int prevMark;
382219019Sgabor
383219019Sgabor            public Entry(FunctionDescriptor cachedDescRes,
384219019Sgabor                    int prevMark) {
385219019Sgabor                this.cachedDescRes = cachedDescRes;
386219019Sgabor                this.prevMark = prevMark;
387219019Sgabor            }
388219019Sgabor
389219019Sgabor            boolean matches(int mark) {
390219019Sgabor                return  this.prevMark == mark;
391219019Sgabor            }
392219019Sgabor        }
393219019Sgabor
394219019Sgabor        FunctionDescriptor get(TypeSymbol origin) throws FunctionDescriptorLookupError {
395219019Sgabor            Entry e = _map.get(origin);
396219019Sgabor            CompoundScope members = membersClosure(origin.type, false);
397219019Sgabor            if (e == null ||
398219019Sgabor                    !e.matches(members.getMark())) {
399219019Sgabor                FunctionDescriptor descRes = findDescriptorInternal(origin, members);
400219019Sgabor                _map.put(origin, new Entry(descRes, members.getMark()));
401219019Sgabor                return descRes;
402219019Sgabor            }
403219019Sgabor            else {
404219019Sgabor                return e.cachedDescRes;
405219019Sgabor            }
406219019Sgabor        }
407219019Sgabor
408219019Sgabor        /**
409219019Sgabor         * Compute the function descriptor associated with a given functional interface
410219019Sgabor         */
411219019Sgabor        public FunctionDescriptor findDescriptorInternal(TypeSymbol origin,
412219019Sgabor                CompoundScope membersCache) throws FunctionDescriptorLookupError {
413219019Sgabor            if (!origin.isInterface() || (origin.flags() & ANNOTATION) != 0) {
414219019Sgabor                //t must be an interface
415219019Sgabor                throw failure("not.a.functional.intf", origin);
416219019Sgabor            }
417219019Sgabor
418219019Sgabor            final ListBuffer<Symbol> abstracts = new ListBuffer<>();
419219019Sgabor            for (Symbol sym : membersCache.getSymbols(new DescriptorFilter(origin))) {
420219019Sgabor                Type mtype = memberType(origin.type, sym);
421219019Sgabor                if (abstracts.isEmpty() ||
422219019Sgabor                        (sym.name == abstracts.first().name &&
423219019Sgabor                        overrideEquivalent(mtype, memberType(origin.type, abstracts.first())))) {
424219019Sgabor                    abstracts.append(sym);
425219019Sgabor                } else {
426219019Sgabor                    //the target method(s) should be the only abstract members of t
427219019Sgabor                    throw failure("not.a.functional.intf.1",  origin,
428219019Sgabor                            diags.fragment("incompatible.abstracts", Kinds.kindName(origin), origin));
429219019Sgabor                }
430219019Sgabor            }
431219019Sgabor            if (abstracts.isEmpty()) {
432219019Sgabor                //t must define a suitable non-generic method
433219019Sgabor                throw failure("not.a.functional.intf.1", origin,
434219019Sgabor                            diags.fragment("no.abstracts", Kinds.kindName(origin), origin));
435219019Sgabor            } else if (abstracts.size() == 1) {
436219019Sgabor                return new FunctionDescriptor(abstracts.first());
437219019Sgabor            } else { // size > 1
438219019Sgabor                FunctionDescriptor descRes = mergeDescriptors(origin, abstracts.toList());
439219019Sgabor                if (descRes == null) {
440219019Sgabor                    //we can get here if the functional interface is ill-formed
441219019Sgabor                    ListBuffer<JCDiagnostic> descriptors = new ListBuffer<>();
442219019Sgabor                    for (Symbol desc : abstracts) {
443219019Sgabor                        String key = desc.type.getThrownTypes().nonEmpty() ?
444219019Sgabor                                "descriptor.throws" : "descriptor";
445219019Sgabor                        descriptors.append(diags.fragment(key, desc.name,
446219019Sgabor                                desc.type.getParameterTypes(),
447219019Sgabor                                desc.type.getReturnType(),
448219019Sgabor                                desc.type.getThrownTypes()));
449219019Sgabor                    }
450219019Sgabor                    JCDiagnostic.MultilineDiagnostic incompatibleDescriptors =
451219019Sgabor                            new JCDiagnostic.MultilineDiagnostic(diags.fragment("incompatible.descs.in.functional.intf",
452219019Sgabor                            Kinds.kindName(origin), origin), descriptors.toList());
453219019Sgabor                    throw failure(incompatibleDescriptors);
454219019Sgabor                }
455219019Sgabor                return descRes;
456219019Sgabor            }
457219019Sgabor        }
458219019Sgabor
459219019Sgabor        /**
460219019Sgabor         * Compute a synthetic type for the target descriptor given a list
461219019Sgabor         * of override-equivalent methods in the functional interface type.
462219019Sgabor         * The resulting method type is a method type that is override-equivalent
463219019Sgabor         * and return-type substitutable with each method in the original list.
464219019Sgabor         */
465219019Sgabor        private FunctionDescriptor mergeDescriptors(TypeSymbol origin, List<Symbol> methodSyms) {
466219019Sgabor            //pick argument types - simply take the signature that is a
467219019Sgabor            //subsignature of all other signatures in the list (as per JLS 8.4.2)
468219019Sgabor            List<Symbol> mostSpecific = List.nil();
469219019Sgabor            outer: for (Symbol msym1 : methodSyms) {
470219019Sgabor                Type mt1 = memberType(origin.type, msym1);
471219019Sgabor                for (Symbol msym2 : methodSyms) {
472219019Sgabor                    Type mt2 = memberType(origin.type, msym2);
473219019Sgabor                    if (!isSubSignature(mt1, mt2)) {
474219019Sgabor                        continue outer;
475219019Sgabor                    }
476219019Sgabor                }
477219019Sgabor                mostSpecific = mostSpecific.prepend(msym1);
478219019Sgabor            }
479219019Sgabor            if (mostSpecific.isEmpty()) {
480219019Sgabor                return null;
481219019Sgabor            }
482219019Sgabor
483219019Sgabor
484219019Sgabor            //pick return types - this is done in two phases: (i) first, the most
485219019Sgabor            //specific return type is chosen using strict subtyping; if this fails,
486219019Sgabor            //a second attempt is made using return type substitutability (see JLS 8.4.5)
487219019Sgabor            boolean phase2 = false;
488219019Sgabor            Symbol bestSoFar = null;
489219019Sgabor            while (bestSoFar == null) {
490219019Sgabor                outer: for (Symbol msym1 : mostSpecific) {
491219019Sgabor                    Type mt1 = memberType(origin.type, msym1);
492219019Sgabor                    for (Symbol msym2 : methodSyms) {
493219019Sgabor                        Type mt2 = memberType(origin.type, msym2);
494219019Sgabor                        if (phase2 ?
495219019Sgabor                                !returnTypeSubstitutable(mt1, mt2) :
496219019Sgabor                                !isSubtypeInternal(mt1.getReturnType(), mt2.getReturnType())) {
497219019Sgabor                            continue outer;
498219019Sgabor                        }
499219019Sgabor                    }
500219019Sgabor                    bestSoFar = msym1;
501219019Sgabor                }
502219019Sgabor                if (phase2) {
503219019Sgabor                    break;
504219019Sgabor                } else {
505219019Sgabor                    phase2 = true;
506219019Sgabor                }
507219019Sgabor            }
508219019Sgabor            if (bestSoFar == null) return null;
509219019Sgabor
510219019Sgabor            //merge thrown types - form the intersection of all the thrown types in
511219019Sgabor            //all the signatures in the list
512219019Sgabor            boolean toErase = !bestSoFar.type.hasTag(FORALL);
513219019Sgabor            List<Type> thrown = null;
514219019Sgabor            Type mt1 = memberType(origin.type, bestSoFar);
515219019Sgabor            for (Symbol msym2 : methodSyms) {
516219019Sgabor                Type mt2 = memberType(origin.type, msym2);
517219019Sgabor                List<Type> thrown_mt2 = mt2.getThrownTypes();
518219019Sgabor                if (toErase) {
519219019Sgabor                    thrown_mt2 = erasure(thrown_mt2);
520219019Sgabor                } else {
521219019Sgabor                    /* If bestSoFar is generic then all the methods are generic.
522219019Sgabor                     * The opposite is not true: a non generic method can override
523219019Sgabor                     * a generic method (raw override) so it's safe to cast mt1 and
524219019Sgabor                     * mt2 to ForAll.
525219019Sgabor                     */
526219019Sgabor                    ForAll fa1 = (ForAll)mt1;
527219019Sgabor                    ForAll fa2 = (ForAll)mt2;
528219019Sgabor                    thrown_mt2 = subst(thrown_mt2, fa2.tvars, fa1.tvars);
529219019Sgabor                }
530219019Sgabor                thrown = (thrown == null) ?
531219019Sgabor                    thrown_mt2 :
532219019Sgabor                    chk.intersect(thrown_mt2, thrown);
533219019Sgabor            }
534219019Sgabor
535219019Sgabor            final List<Type> thrown1 = thrown;
536219019Sgabor            return new FunctionDescriptor(bestSoFar) {
537219019Sgabor                @Override
538219019Sgabor                public Type getType(Type origin) {
539219019Sgabor                    Type mt = memberType(origin, getSymbol());
540219019Sgabor                    return createMethodTypeWithThrown(mt, thrown1);
541219019Sgabor                }
542219019Sgabor            };
543219019Sgabor        }
544219019Sgabor
545219019Sgabor        boolean isSubtypeInternal(Type s, Type t) {
546219019Sgabor            return (s.isPrimitive() && t.isPrimitive()) ?
547219019Sgabor                    isSameType(t, s) :
548219019Sgabor                    isSubtype(s, t);
549219019Sgabor        }
550219019Sgabor
551219019Sgabor        FunctionDescriptorLookupError failure(String msg, Object... args) {
552219019Sgabor            return failure(diags.fragment(msg, args));
553219019Sgabor        }
554219019Sgabor
555219019Sgabor        FunctionDescriptorLookupError failure(JCDiagnostic diag) {
556219019Sgabor            return functionDescriptorLookupError.setMessage(diag);
557219019Sgabor        }
558219019Sgabor    }
559219019Sgabor
560219019Sgabor    private DescriptorCache descCache = new DescriptorCache();
561219019Sgabor
562219019Sgabor    /**
563219019Sgabor     * Find the method descriptor associated to this class symbol - if the
564219019Sgabor     * symbol 'origin' is not a functional interface, an exception is thrown.
565219019Sgabor     */
566219019Sgabor    public Symbol findDescriptorSymbol(TypeSymbol origin) throws FunctionDescriptorLookupError {
567219019Sgabor        return descCache.get(origin).getSymbol();
568219019Sgabor    }
569219019Sgabor
570219019Sgabor    /**
571219019Sgabor     * Find the type of the method descriptor associated to this class symbol -
572219019Sgabor     * if the symbol 'origin' is not a functional interface, an exception is thrown.
573219019Sgabor     */
574219019Sgabor    public Type findDescriptorType(Type origin) throws FunctionDescriptorLookupError {
575219019Sgabor        return descCache.get(origin.tsym).getType(origin);
576219019Sgabor    }
577219019Sgabor
578219019Sgabor    /**
579219019Sgabor     * Is given type a functional interface?
580219019Sgabor     */
581219019Sgabor    public boolean isFunctionalInterface(TypeSymbol tsym) {
582219019Sgabor        try {
583219019Sgabor            findDescriptorSymbol(tsym);
584219019Sgabor            return true;
585219019Sgabor        } catch (FunctionDescriptorLookupError ex) {
586219019Sgabor            return false;
587219019Sgabor        }
588219019Sgabor    }
589219019Sgabor
590219019Sgabor    public boolean isFunctionalInterface(Type site) {
591219019Sgabor        try {
592219019Sgabor            findDescriptorType(site);
593219019Sgabor            return true;
594219019Sgabor        } catch (FunctionDescriptorLookupError ex) {
595219019Sgabor            return false;
596219019Sgabor        }
597219019Sgabor    }
598219019Sgabor
599219019Sgabor    public Type removeWildcards(Type site) {
600219019Sgabor        Type capturedSite = capture(site);
601219019Sgabor        if (capturedSite != site) {
602219019Sgabor            Type formalInterface = site.tsym.type;
603219019Sgabor            ListBuffer<Type> typeargs = new ListBuffer<>();
604219019Sgabor            List<Type> actualTypeargs = site.getTypeArguments();
605219019Sgabor            List<Type> capturedTypeargs = capturedSite.getTypeArguments();
606219019Sgabor            //simply replace the wildcards with its bound
607219019Sgabor            for (Type t : formalInterface.getTypeArguments()) {
608219019Sgabor                if (actualTypeargs.head.hasTag(WILDCARD)) {
609219019Sgabor                    WildcardType wt = (WildcardType)actualTypeargs.head;
610219019Sgabor                    Type bound;
611219019Sgabor                    switch (wt.kind) {
612219019Sgabor                        case EXTENDS:
613219019Sgabor                        case UNBOUND:
614219019Sgabor                            CapturedType capVar = (CapturedType)capturedTypeargs.head;
615219019Sgabor                            //use declared bound if it doesn't depend on formal type-args
616219019Sgabor                            bound = capVar.bound.containsAny(capturedSite.getTypeArguments()) ?
617219019Sgabor                                    wt.type : capVar.bound;
618219019Sgabor                            break;
619219019Sgabor                        default:
620219019Sgabor                            bound = wt.type;
621219019Sgabor                    }
622219019Sgabor                    typeargs.append(bound);
623219019Sgabor                } else {
624219019Sgabor                    typeargs.append(actualTypeargs.head);
625219019Sgabor                }
626219019Sgabor                actualTypeargs = actualTypeargs.tail;
627219019Sgabor                capturedTypeargs = capturedTypeargs.tail;
628219019Sgabor            }
629219019Sgabor            return subst(formalInterface, formalInterface.getTypeArguments(), typeargs.toList());
630219019Sgabor        } else {
631219019Sgabor            return site;
632219019Sgabor        }
633219019Sgabor    }
634219019Sgabor
635219019Sgabor    /**
636219019Sgabor     * Create a symbol for a class that implements a given functional interface
637219019Sgabor     * and overrides its functional descriptor. This routine is used for two
638219019Sgabor     * main purposes: (i) checking well-formedness of a functional interface;
639219019Sgabor     * (ii) perform functional interface bridge calculation.
640219019Sgabor     */
641219019Sgabor    public ClassSymbol makeFunctionalInterfaceClass(Env<AttrContext> env, Name name, List<Type> targets, long cflags) {
642219019Sgabor        if (targets.isEmpty()) {
643219019Sgabor            return null;
644219019Sgabor        }
645219019Sgabor        Symbol descSym = findDescriptorSymbol(targets.head.tsym);
646219019Sgabor        Type descType = findDescriptorType(targets.head);
647219019Sgabor        ClassSymbol csym = new ClassSymbol(cflags, name, env.enclClass.sym.outermostClass());
648219019Sgabor        csym.completer = Completer.NULL_COMPLETER;
649219019Sgabor        csym.members_field = WriteableScope.create(csym);
650219019Sgabor        MethodSymbol instDescSym = new MethodSymbol(descSym.flags(), descSym.name, descType, csym);
651219019Sgabor        csym.members_field.enter(instDescSym);
652219019Sgabor        Type.ClassType ctype = new Type.ClassType(Type.noType, List.<Type>nil(), csym);
653219019Sgabor        ctype.supertype_field = syms.objectType;
654219019Sgabor        ctype.interfaces_field = targets;
655219019Sgabor        csym.type = ctype;
656219019Sgabor        csym.sourcefile = ((ClassSymbol)csym.owner).sourcefile;
657219019Sgabor        return csym;
658219019Sgabor    }
659219019Sgabor
660219019Sgabor    /**
661219019Sgabor     * Find the minimal set of methods that are overridden by the functional
662219019Sgabor     * descriptor in 'origin'. All returned methods are assumed to have different
663219019Sgabor     * erased signatures.
664219019Sgabor     */
665219019Sgabor    public List<Symbol> functionalInterfaceBridges(TypeSymbol origin) {
666219019Sgabor        Assert.check(isFunctionalInterface(origin));
667219019Sgabor        Symbol descSym = findDescriptorSymbol(origin);
668219019Sgabor        CompoundScope members = membersClosure(origin.type, false);
669219019Sgabor        ListBuffer<Symbol> overridden = new ListBuffer<>();
670219019Sgabor        outer: for (Symbol m2 : members.getSymbolsByName(descSym.name, bridgeFilter)) {
671219019Sgabor            if (m2 == descSym) continue;
672219019Sgabor            else if (descSym.overrides(m2, origin, Types.this, false)) {
673219019Sgabor                for (Symbol m3 : overridden) {
674219019Sgabor                    if (isSameType(m3.erasure(Types.this), m2.erasure(Types.this)) ||
675219019Sgabor                            (m3.overrides(m2, origin, Types.this, false) &&
676219019Sgabor                            (pendingBridges((ClassSymbol)origin, m3.enclClass()) ||
677219019Sgabor                            (((MethodSymbol)m2).binaryImplementation((ClassSymbol)m3.owner, Types.this) != null)))) {
678219019Sgabor                        continue outer;
679219019Sgabor                    }
680219019Sgabor                }
681219019Sgabor                overridden.add(m2);
682219019Sgabor            }
683219019Sgabor        }
684219019Sgabor        return overridden.toList();
685219019Sgabor    }
686219019Sgabor    //where
687219019Sgabor        private Filter<Symbol> bridgeFilter = new Filter<Symbol>() {
688219019Sgabor            public boolean accepts(Symbol t) {
689219019Sgabor                return t.kind == MTH &&
690219019Sgabor                        t.name != names.init &&
691219019Sgabor                        t.name != names.clinit &&
692219019Sgabor                        (t.flags() & SYNTHETIC) == 0;
693219019Sgabor            }
694219019Sgabor        };
695219019Sgabor        private boolean pendingBridges(ClassSymbol origin, TypeSymbol s) {
696219019Sgabor            //a symbol will be completed from a classfile if (a) symbol has
697219019Sgabor            //an associated file object with CLASS kind and (b) the symbol has
698219019Sgabor            //not been entered
699219019Sgabor            if (origin.classfile != null &&
700219019Sgabor                    origin.classfile.getKind() == JavaFileObject.Kind.CLASS &&
701219019Sgabor                    enter.getEnv(origin) == null) {
702219019Sgabor                return false;
703219019Sgabor            }
704219019Sgabor            if (origin == s) {
705219019Sgabor                return true;
706219019Sgabor            }
707219019Sgabor            for (Type t : interfaces(origin.type)) {
708219019Sgabor                if (pendingBridges((ClassSymbol)t.tsym, s)) {
709219019Sgabor                    return true;
710219019Sgabor                }
711219019Sgabor            }
712219019Sgabor            return false;
713219019Sgabor        }
714219019Sgabor    // </editor-fold>
715219019Sgabor
716219019Sgabor   /**
717219019Sgabor    * Scope filter used to skip methods that should be ignored (such as methods
718219019Sgabor    * overridden by j.l.Object) during function interface conversion interface check
719219019Sgabor    */
720219019Sgabor    class DescriptorFilter implements Filter<Symbol> {
721219019Sgabor
722219019Sgabor       TypeSymbol origin;
723219019Sgabor
724219019Sgabor       DescriptorFilter(TypeSymbol origin) {
725219019Sgabor           this.origin = origin;
726219019Sgabor       }
727219019Sgabor
728219019Sgabor       @Override
729219019Sgabor       public boolean accepts(Symbol sym) {
730219019Sgabor           return sym.kind == MTH &&
731219019Sgabor                   (sym.flags() & (ABSTRACT | DEFAULT)) == ABSTRACT &&
732219019Sgabor                   !overridesObjectMethod(origin, sym) &&
733219019Sgabor                   (interfaceCandidates(origin.type, (MethodSymbol)sym).head.flags() & DEFAULT) == 0;
734219019Sgabor       }
735219019Sgabor    }
736219019Sgabor
737219019Sgabor    // <editor-fold defaultstate="collapsed" desc="isSubtype">
738219019Sgabor    /**
739219019Sgabor     * Is t an unchecked subtype of s?
740219019Sgabor     */
741219019Sgabor    public boolean isSubtypeUnchecked(Type t, Type s) {
742219019Sgabor        return isSubtypeUnchecked(t, s, noWarnings);
743219019Sgabor    }
744219019Sgabor    /**
745219019Sgabor     * Is t an unchecked subtype of s?
746219019Sgabor     */
747219019Sgabor    public boolean isSubtypeUnchecked(Type t, Type s, Warner warn) {
748219019Sgabor        boolean result = isSubtypeUncheckedInternal(t, s, warn);
749219019Sgabor        if (result) {
750219019Sgabor            checkUnsafeVarargsConversion(t, s, warn);
751219019Sgabor        }
752219019Sgabor        return result;
753219019Sgabor    }
754219019Sgabor    //where
755219019Sgabor        private boolean isSubtypeUncheckedInternal(Type t, Type s, Warner warn) {
756219019Sgabor            if (t.hasTag(ARRAY) && s.hasTag(ARRAY)) {
757219019Sgabor                if (((ArrayType)t).elemtype.isPrimitive()) {
758219019Sgabor                    return isSameType(elemtype(t), elemtype(s));
759219019Sgabor                } else {
760219019Sgabor                    return isSubtypeUnchecked(elemtype(t), elemtype(s), warn);
761219019Sgabor                }
762219019Sgabor            } else if (isSubtype(t, s)) {
763219019Sgabor                return true;
764219019Sgabor            } else if (t.hasTag(TYPEVAR)) {
765219019Sgabor                return isSubtypeUnchecked(t.getUpperBound(), s, warn);
766219019Sgabor            } else if (!s.isRaw()) {
767219019Sgabor                Type t2 = asSuper(t, s.tsym);
768219019Sgabor                if (t2 != null && t2.isRaw()) {
769219019Sgabor                    if (isReifiable(s)) {
770219019Sgabor                        warn.silentWarn(LintCategory.UNCHECKED);
771219019Sgabor                    } else {
772219019Sgabor                        warn.warn(LintCategory.UNCHECKED);
773219019Sgabor                    }
774219019Sgabor                    return true;
775219019Sgabor                }
776219019Sgabor            }
777219019Sgabor            return false;
778219019Sgabor        }
779219019Sgabor
780219019Sgabor        private void checkUnsafeVarargsConversion(Type t, Type s, Warner warn) {
781219019Sgabor            if (!t.hasTag(ARRAY) || isReifiable(t)) {
782219019Sgabor                return;
783219019Sgabor            }
784219019Sgabor            ArrayType from = (ArrayType)t;
785219019Sgabor            boolean shouldWarn = false;
786219019Sgabor            switch (s.getTag()) {
787219019Sgabor                case ARRAY:
788219019Sgabor                    ArrayType to = (ArrayType)s;
789219019Sgabor                    shouldWarn = from.isVarargs() &&
790219019Sgabor                            !to.isVarargs() &&
791219019Sgabor                            !isReifiable(from);
792219019Sgabor                    break;
793219019Sgabor                case CLASS:
794219019Sgabor                    shouldWarn = from.isVarargs();
795219019Sgabor                    break;
796219019Sgabor            }
797219019Sgabor            if (shouldWarn) {
798219019Sgabor                warn.warn(LintCategory.VARARGS);
799219019Sgabor            }
800219019Sgabor        }
801219019Sgabor
802219019Sgabor    /**
803219019Sgabor     * Is t a subtype of s?<br>
804219019Sgabor     * (not defined for Method and ForAll types)
805219019Sgabor     */
806219019Sgabor    final public boolean isSubtype(Type t, Type s) {
807219019Sgabor        return isSubtype(t, s, true);
808219019Sgabor    }
809219019Sgabor    final public boolean isSubtypeNoCapture(Type t, Type s) {
810219019Sgabor        return isSubtype(t, s, false);
811219019Sgabor    }
812219019Sgabor    public boolean isSubtype(Type t, Type s, boolean capture) {
813219019Sgabor        if (t.equalsIgnoreMetadata(s))
814219019Sgabor            return true;
815219019Sgabor        if (s.isPartial())
816219019Sgabor            return isSuperType(s, t);
817219019Sgabor
818219019Sgabor        if (s.isCompound()) {
819219019Sgabor            for (Type s2 : interfaces(s).prepend(supertype(s))) {
820219019Sgabor                if (!isSubtype(t, s2, capture))
821219019Sgabor                    return false;
822219019Sgabor            }
823219019Sgabor            return true;
824219019Sgabor        }
825219019Sgabor
826219019Sgabor        // Generally, if 's' is a lower-bounded type variable, recur on lower bound; but
827219019Sgabor        // for inference variables and intersections, we need to keep 's'
828219019Sgabor        // (see JLS 4.10.2 for intersections and 18.2.3 for inference vars)
829219019Sgabor        if (!t.hasTag(UNDETVAR) && !t.isCompound()) {
830219019Sgabor            // TODO: JDK-8039198, bounds checking sometimes passes in a wildcard as s
831219019Sgabor            Type lower = cvarLowerBound(wildLowerBound(s));
832219019Sgabor            if (s != lower && !lower.hasTag(BOT))
833219019Sgabor                return isSubtype(capture ? capture(t) : t, lower, false);
834219019Sgabor        }
835219019Sgabor
836219019Sgabor        return isSubtype.visit(capture ? capture(t) : t, s);
837219019Sgabor    }
838219019Sgabor    // where
839219019Sgabor        private TypeRelation isSubtype = new TypeRelation()
840219019Sgabor        {
841219019Sgabor            @Override
842219019Sgabor            public Boolean visitType(Type t, Type s) {
843219019Sgabor                switch (t.getTag()) {
844219019Sgabor                 case BYTE:
845219019Sgabor                     return (!s.hasTag(CHAR) && t.getTag().isSubRangeOf(s.getTag()));
846219019Sgabor                 case CHAR:
847219019Sgabor                     return (!s.hasTag(SHORT) && t.getTag().isSubRangeOf(s.getTag()));
848219019Sgabor                 case SHORT: case INT: case LONG:
849219019Sgabor                 case FLOAT: case DOUBLE:
850219019Sgabor                     return t.getTag().isSubRangeOf(s.getTag());
851219019Sgabor                 case BOOLEAN: case VOID:
852219019Sgabor                     return t.hasTag(s.getTag());
853219019Sgabor                 case TYPEVAR:
854219019Sgabor                     return isSubtypeNoCapture(t.getUpperBound(), s);
855219019Sgabor                 case BOT:
856219019Sgabor                     return
857219019Sgabor                         s.hasTag(BOT) || s.hasTag(CLASS) ||
858219019Sgabor                         s.hasTag(ARRAY) || s.hasTag(TYPEVAR);
859219019Sgabor                 case WILDCARD: //we shouldn't be here - avoids crash (see 7034495)
860219019Sgabor                 case NONE:
861219019Sgabor                     return false;
862219019Sgabor                 default:
863219019Sgabor                     throw new AssertionError("isSubtype " + t.getTag());
864219019Sgabor                 }
865219019Sgabor            }
866219019Sgabor
867219019Sgabor            private Set<TypePair> cache = new HashSet<>();
868219019Sgabor
869219019Sgabor            private boolean containsTypeRecursive(Type t, Type s) {
870219019Sgabor                TypePair pair = new TypePair(t, s);
871219019Sgabor                if (cache.add(pair)) {
872219019Sgabor                    try {
873219019Sgabor                        return containsType(t.getTypeArguments(),
874219019Sgabor                                            s.getTypeArguments());
875219019Sgabor                    } finally {
876219019Sgabor                        cache.remove(pair);
877219019Sgabor                    }
878219019Sgabor                } else {
879219019Sgabor                    return containsType(t.getTypeArguments(),
880219019Sgabor                                        rewriteSupers(s).getTypeArguments());
881219019Sgabor                }
882219019Sgabor            }
883219019Sgabor
884219019Sgabor            private Type rewriteSupers(Type t) {
885219019Sgabor                if (!t.isParameterized())
886219019Sgabor                    return t;
887219019Sgabor                ListBuffer<Type> from = new ListBuffer<>();
888219019Sgabor                ListBuffer<Type> to = new ListBuffer<>();
889219019Sgabor                adaptSelf(t, from, to);
890219019Sgabor                if (from.isEmpty())
891219019Sgabor                    return t;
892219019Sgabor                ListBuffer<Type> rewrite = new ListBuffer<>();
893219019Sgabor                boolean changed = false;
894219019Sgabor                for (Type orig : to.toList()) {
895219019Sgabor                    Type s = rewriteSupers(orig);
896219019Sgabor                    if (s.isSuperBound() && !s.isExtendsBound()) {
897219019Sgabor                        s = new WildcardType(syms.objectType,
898219019Sgabor                                             BoundKind.UNBOUND,
899219019Sgabor                                             syms.boundClass,
900219019Sgabor                                             s.getMetadata());
901219019Sgabor                        changed = true;
902219019Sgabor                    } else if (s != orig) {
903219019Sgabor                        s = new WildcardType(wildUpperBound(s),
904219019Sgabor                                             BoundKind.EXTENDS,
905219019Sgabor                                             syms.boundClass,
906219019Sgabor                                             s.getMetadata());
907219019Sgabor                        changed = true;
908219019Sgabor                    }
909219019Sgabor                    rewrite.append(s);
910219019Sgabor                }
911219019Sgabor                if (changed)
912219019Sgabor                    return subst(t.tsym.type, from.toList(), rewrite.toList());
913219019Sgabor                else
914219019Sgabor                    return t;
915219019Sgabor            }
916219019Sgabor
917219019Sgabor            @Override
918219019Sgabor            public Boolean visitClassType(ClassType t, Type s) {
919219019Sgabor                Type sup = asSuper(t, s.tsym);
920219019Sgabor                if (sup == null) return false;
921219019Sgabor                // If t is an intersection, sup might not be a class type
922219019Sgabor                if (!sup.hasTag(CLASS)) return isSubtypeNoCapture(sup, s);
923219019Sgabor                return sup.tsym == s.tsym
924219019Sgabor                     // Check type variable containment
925219019Sgabor                    && (!s.isParameterized() || containsTypeRecursive(s, sup))
926219019Sgabor                    && isSubtypeNoCapture(sup.getEnclosingType(),
927219019Sgabor                                          s.getEnclosingType());
928219019Sgabor            }
929219019Sgabor
930219019Sgabor            @Override
931219019Sgabor            public Boolean visitArrayType(ArrayType t, Type s) {
932219019Sgabor                if (s.hasTag(ARRAY)) {
933219019Sgabor                    if (t.elemtype.isPrimitive())
934219019Sgabor                        return isSameType(t.elemtype, elemtype(s));
935219019Sgabor                    else
936219019Sgabor                        return isSubtypeNoCapture(t.elemtype, elemtype(s));
937219019Sgabor                }
938219019Sgabor
939219019Sgabor                if (s.hasTag(CLASS)) {
940219019Sgabor                    Name sname = s.tsym.getQualifiedName();
941219019Sgabor                    return sname == names.java_lang_Object
942219019Sgabor                        || sname == names.java_lang_Cloneable
943219019Sgabor                        || sname == names.java_io_Serializable;
944219019Sgabor                }
945219019Sgabor
946219019Sgabor                return false;
947219019Sgabor            }
948219019Sgabor
949219019Sgabor            @Override
950219019Sgabor            public Boolean visitUndetVar(UndetVar t, Type s) {
951219019Sgabor                //todo: test against origin needed? or replace with substitution?
952219019Sgabor                if (t == s || t.qtype == s || s.hasTag(ERROR) || s.hasTag(UNKNOWN)) {
953219019Sgabor                    return true;
954219019Sgabor                } else if (s.hasTag(BOT)) {
955219019Sgabor                    //if 's' is 'null' there's no instantiated type U for which
956219019Sgabor                    //U <: s (but 'null' itself, which is not a valid type)
957219019Sgabor                    return false;
958219019Sgabor                }
959219019Sgabor
960219019Sgabor                t.addBound(InferenceBound.UPPER, s, Types.this);
961219019Sgabor                return true;
962219019Sgabor            }
963219019Sgabor
964219019Sgabor            @Override
965219019Sgabor            public Boolean visitErrorType(ErrorType t, Type s) {
966219019Sgabor                return true;
967219019Sgabor            }
968219019Sgabor        };
969219019Sgabor
970219019Sgabor    /**
971219019Sgabor     * Is t a subtype of every type in given list `ts'?<br>
972219019Sgabor     * (not defined for Method and ForAll types)<br>
973219019Sgabor     * Allows unchecked conversions.
974219019Sgabor     */
975219019Sgabor    public boolean isSubtypeUnchecked(Type t, List<Type> ts, Warner warn) {
976219019Sgabor        for (List<Type> l = ts; l.nonEmpty(); l = l.tail)
977219019Sgabor            if (!isSubtypeUnchecked(t, l.head, warn))
978219019Sgabor                return false;
979219019Sgabor        return true;
980219019Sgabor    }
981219019Sgabor
982219019Sgabor    /**
983219019Sgabor     * Are corresponding elements of ts subtypes of ss?  If lists are
984219019Sgabor     * of different length, return false.
985219019Sgabor     */
986219019Sgabor    public boolean isSubtypes(List<Type> ts, List<Type> ss) {
987219019Sgabor        while (ts.tail != null && ss.tail != null
988219019Sgabor               /*inlined: ts.nonEmpty() && ss.nonEmpty()*/ &&
989219019Sgabor               isSubtype(ts.head, ss.head)) {
990219019Sgabor            ts = ts.tail;
991219019Sgabor            ss = ss.tail;
992219019Sgabor        }
993219019Sgabor        return ts.tail == null && ss.tail == null;
994219019Sgabor        /*inlined: ts.isEmpty() && ss.isEmpty();*/
995219019Sgabor    }
996219019Sgabor
997219019Sgabor    /**
998219019Sgabor     * Are corresponding elements of ts subtypes of ss, allowing
999219019Sgabor     * unchecked conversions?  If lists are of different length,
1000219019Sgabor     * return false.
1001219019Sgabor     **/
1002219019Sgabor    public boolean isSubtypesUnchecked(List<Type> ts, List<Type> ss, Warner warn) {
1003219019Sgabor        while (ts.tail != null && ss.tail != null
1004219019Sgabor               /*inlined: ts.nonEmpty() && ss.nonEmpty()*/ &&
1005219019Sgabor               isSubtypeUnchecked(ts.head, ss.head, warn)) {
1006219019Sgabor            ts = ts.tail;
1007219019Sgabor            ss = ss.tail;
1008219019Sgabor        }
1009219019Sgabor        return ts.tail == null && ss.tail == null;
1010219019Sgabor        /*inlined: ts.isEmpty() && ss.isEmpty();*/
1011219019Sgabor    }
1012219019Sgabor    // </editor-fold>
1013219019Sgabor
1014219019Sgabor    // <editor-fold defaultstate="collapsed" desc="isSuperType">
1015219019Sgabor    /**
1016219019Sgabor     * Is t a supertype of s?
1017219019Sgabor     */
1018219019Sgabor    public boolean isSuperType(Type t, Type s) {
1019219019Sgabor        switch (t.getTag()) {
1020219019Sgabor        case ERROR:
1021219019Sgabor            return true;
1022219019Sgabor        case UNDETVAR: {
1023219019Sgabor            UndetVar undet = (UndetVar)t;
1024219019Sgabor            if (t == s ||
1025219019Sgabor                undet.qtype == s ||
1026219019Sgabor                s.hasTag(ERROR) ||
1027219019Sgabor                s.hasTag(BOT)) {
1028219019Sgabor                return true;
1029219019Sgabor            }
1030219019Sgabor            undet.addBound(InferenceBound.LOWER, s, this);
1031219019Sgabor            return true;
1032219019Sgabor        }
1033219019Sgabor        default:
1034219019Sgabor            return isSubtype(s, t);
1035219019Sgabor        }
1036219019Sgabor    }
1037219019Sgabor    // </editor-fold>
1038219019Sgabor
1039219019Sgabor    // <editor-fold defaultstate="collapsed" desc="isSameType">
1040219019Sgabor    /**
1041219019Sgabor     * Are corresponding elements of the lists the same type?  If
1042219019Sgabor     * lists are of different length, return false.
1043219019Sgabor     */
1044219019Sgabor    public boolean isSameTypes(List<Type> ts, List<Type> ss) {
1045219019Sgabor        return isSameTypes(ts, ss, false);
1046219019Sgabor    }
1047219019Sgabor    public boolean isSameTypes(List<Type> ts, List<Type> ss, boolean strict) {
1048219019Sgabor        while (ts.tail != null && ss.tail != null
1049219019Sgabor               /*inlined: ts.nonEmpty() && ss.nonEmpty()*/ &&
1050219019Sgabor               isSameType(ts.head, ss.head, strict)) {
1051219019Sgabor            ts = ts.tail;
1052219019Sgabor            ss = ss.tail;
1053219019Sgabor        }
1054219019Sgabor        return ts.tail == null && ss.tail == null;
1055219019Sgabor        /*inlined: ts.isEmpty() && ss.isEmpty();*/
1056219019Sgabor    }
1057219019Sgabor
1058219019Sgabor    /**
1059219019Sgabor    * A polymorphic signature method (JLS SE 7, 8.4.1) is a method that
1060219019Sgabor    * (i) is declared in the java.lang.invoke.MethodHandle class, (ii) takes
1061219019Sgabor    * a single variable arity parameter (iii) whose declared type is Object[],
1062219019Sgabor    * (iv) has a return type of Object and (v) is native.
1063219019Sgabor    */
1064219019Sgabor   public boolean isSignaturePolymorphic(MethodSymbol msym) {
1065219019Sgabor       List<Type> argtypes = msym.type.getParameterTypes();
1066219019Sgabor       return (msym.flags_field & NATIVE) != 0 &&
1067219019Sgabor               msym.owner == syms.methodHandleType.tsym &&
1068219019Sgabor               argtypes.tail.tail == null &&
1069219019Sgabor               argtypes.head.hasTag(TypeTag.ARRAY) &&
1070219019Sgabor               msym.type.getReturnType().tsym == syms.objectType.tsym &&
1071219019Sgabor               ((ArrayType)argtypes.head).elemtype.tsym == syms.objectType.tsym;
1072219019Sgabor   }
1073219019Sgabor
1074219019Sgabor    /**
1075219019Sgabor     * Is t the same type as s?
1076219019Sgabor     */
1077219019Sgabor    public boolean isSameType(Type t, Type s) {
1078219019Sgabor        return isSameType(t, s, false);
1079219019Sgabor    }
1080219019Sgabor    public boolean isSameType(Type t, Type s, boolean strict) {
1081219019Sgabor        return strict ?
1082219019Sgabor                isSameTypeStrict.visit(t, s) :
1083219019Sgabor                isSameTypeLoose.visit(t, s);
1084219019Sgabor    }
1085219019Sgabor    // where
1086219019Sgabor        abstract class SameTypeVisitor extends TypeRelation {
1087219019Sgabor
1088219019Sgabor            public Boolean visitType(Type t, Type s) {
1089219019Sgabor                if (t.equalsIgnoreMetadata(s))
1090219019Sgabor                    return true;
1091219019Sgabor
1092219019Sgabor                if (s.isPartial())
1093219019Sgabor                    return visit(s, t);
1094219019Sgabor
1095219019Sgabor                switch (t.getTag()) {
1096219019Sgabor                case BYTE: case CHAR: case SHORT: case INT: case LONG: case FLOAT:
1097219019Sgabor                case DOUBLE: case BOOLEAN: case VOID: case BOT: case NONE:
1098219019Sgabor                    return t.hasTag(s.getTag());
1099219019Sgabor                case TYPEVAR: {
1100219019Sgabor                    if (s.hasTag(TYPEVAR)) {
1101219019Sgabor                        //type-substitution does not preserve type-var types
1102219019Sgabor                        //check that type var symbols and bounds are indeed the same
1103219019Sgabor                        return sameTypeVars((TypeVar)t, (TypeVar)s);
1104219019Sgabor                    }
1105219019Sgabor                    else {
1106219019Sgabor                        //special case for s == ? super X, where upper(s) = u
1107219019Sgabor                        //check that u == t, where u has been set by Type.withTypeVar
1108219019Sgabor                        return s.isSuperBound() &&
1109219019Sgabor                                !s.isExtendsBound() &&
1110219019Sgabor                                visit(t, wildUpperBound(s));
1111219019Sgabor                    }
1112219019Sgabor                }
1113219019Sgabor                default:
1114219019Sgabor                    throw new AssertionError("isSameType " + t.getTag());
1115219019Sgabor                }
1116219019Sgabor            }
1117219019Sgabor
1118219019Sgabor            abstract boolean sameTypeVars(TypeVar tv1, TypeVar tv2);
1119219019Sgabor
1120219019Sgabor            @Override
1121219019Sgabor            public Boolean visitWildcardType(WildcardType t, Type s) {
1122219019Sgabor                if (s.isPartial())
1123219019Sgabor                    return visit(s, t);
1124219019Sgabor                else
1125219019Sgabor                    return false;
1126219019Sgabor            }
1127219019Sgabor
1128219019Sgabor            @Override
1129219019Sgabor            public Boolean visitClassType(ClassType t, Type s) {
1130219019Sgabor                if (t == s)
1131219019Sgabor                    return true;
1132219019Sgabor
1133219019Sgabor                if (s.isPartial())
1134219019Sgabor                    return visit(s, t);
1135219019Sgabor
1136219019Sgabor                if (s.isSuperBound() && !s.isExtendsBound())
1137219019Sgabor                    return visit(t, wildUpperBound(s)) && visit(t, wildLowerBound(s));
1138219019Sgabor
1139219019Sgabor                if (t.isCompound() && s.isCompound()) {
1140219019Sgabor                    if (!visit(supertype(t), supertype(s)))
1141219019Sgabor                        return false;
1142219019Sgabor
1143219019Sgabor                    HashSet<UniqueType> set = new HashSet<>();
1144219019Sgabor                    for (Type x : interfaces(t))
1145219019Sgabor                        set.add(new UniqueType(x, Types.this));
1146219019Sgabor                    for (Type x : interfaces(s)) {
1147219019Sgabor                        if (!set.remove(new UniqueType(x, Types.this)))
1148219019Sgabor                            return false;
1149219019Sgabor                    }
1150219019Sgabor                    return (set.isEmpty());
1151219019Sgabor                }
1152219019Sgabor                return t.tsym == s.tsym
1153219019Sgabor                    && visit(t.getEnclosingType(), s.getEnclosingType())
1154219019Sgabor                    && containsTypes(t.getTypeArguments(), s.getTypeArguments());
1155219019Sgabor            }
1156219019Sgabor
1157219019Sgabor            abstract protected boolean containsTypes(List<Type> ts1, List<Type> ts2);
1158219019Sgabor
1159219019Sgabor            @Override
1160219019Sgabor            public Boolean visitArrayType(ArrayType t, Type s) {
1161219019Sgabor                if (t == s)
1162219019Sgabor                    return true;
1163219019Sgabor
1164219019Sgabor                if (s.isPartial())
1165219019Sgabor                    return visit(s, t);
1166219019Sgabor
1167219019Sgabor                return s.hasTag(ARRAY)
1168219019Sgabor                    && containsTypeEquivalent(t.elemtype, elemtype(s));
1169219019Sgabor            }
1170219019Sgabor
1171219019Sgabor            @Override
1172219019Sgabor            public Boolean visitMethodType(MethodType t, Type s) {
1173219019Sgabor                // isSameType for methods does not take thrown
1174219019Sgabor                // exceptions into account!
1175219019Sgabor                return hasSameArgs(t, s) && visit(t.getReturnType(), s.getReturnType());
1176219019Sgabor            }
1177219019Sgabor
1178219019Sgabor            @Override
1179219019Sgabor            public Boolean visitPackageType(PackageType t, Type s) {
1180219019Sgabor                return t == s;
1181219019Sgabor            }
1182219019Sgabor
1183219019Sgabor            @Override
1184219019Sgabor            public Boolean visitForAll(ForAll t, Type s) {
1185219019Sgabor                if (!s.hasTag(FORALL)) {
1186219019Sgabor                    return false;
1187219019Sgabor                }
1188219019Sgabor
1189219019Sgabor                ForAll forAll = (ForAll)s;
1190219019Sgabor                return hasSameBounds(t, forAll)
1191219019Sgabor                    && visit(t.qtype, subst(forAll.qtype, forAll.tvars, t.tvars));
1192219019Sgabor            }
1193219019Sgabor
1194219019Sgabor            @Override
1195219019Sgabor            public Boolean visitUndetVar(UndetVar t, Type s) {
1196219019Sgabor                if (s.hasTag(WILDCARD)) {
1197219019Sgabor                    // FIXME, this might be leftovers from before capture conversion
1198219019Sgabor                    return false;
1199219019Sgabor                }
1200219019Sgabor
1201219019Sgabor                if (t == s || t.qtype == s || s.hasTag(ERROR) || s.hasTag(UNKNOWN)) {
1202219019Sgabor                    return true;
1203219019Sgabor                }
1204219019Sgabor
1205219019Sgabor                t.addBound(InferenceBound.EQ, s, Types.this);
1206219019Sgabor
1207219019Sgabor                return true;
1208219019Sgabor            }
1209219019Sgabor
1210219019Sgabor            @Override
1211219019Sgabor            public Boolean visitErrorType(ErrorType t, Type s) {
1212219019Sgabor                return true;
1213219019Sgabor            }
1214219019Sgabor        }
1215219019Sgabor
1216219019Sgabor        /**
1217219019Sgabor         * Standard type-equality relation - type variables are considered
1218219019Sgabor         * equals if they share the same type symbol.
1219219019Sgabor         */
1220219019Sgabor        TypeRelation isSameTypeLoose = new LooseSameTypeVisitor();
1221219019Sgabor
1222219019Sgabor        private class LooseSameTypeVisitor extends SameTypeVisitor {
1223219019Sgabor
1224219019Sgabor            /** cache of the type-variable pairs being (recursively) tested. */
1225219019Sgabor            private Set<TypePair> cache = new HashSet<>();
1226219019Sgabor
1227219019Sgabor            @Override
1228219019Sgabor            boolean sameTypeVars(TypeVar tv1, TypeVar tv2) {
1229219019Sgabor                return tv1.tsym == tv2.tsym && checkSameBounds(tv1, tv2);
1230219019Sgabor            }
1231219019Sgabor            @Override
1232219019Sgabor            protected boolean containsTypes(List<Type> ts1, List<Type> ts2) {
1233219019Sgabor                return containsTypeEquivalent(ts1, ts2);
1234219019Sgabor            }
1235219019Sgabor
1236219019Sgabor            /**
1237219019Sgabor             * Since type-variable bounds can be recursive, we need to protect against
1238219019Sgabor             * infinite loops - where the same bounds are checked over and over recursively.
1239219019Sgabor             */
1240219019Sgabor            private boolean checkSameBounds(TypeVar tv1, TypeVar tv2) {
1241219019Sgabor                TypePair p = new TypePair(tv1, tv2, true);
1242219019Sgabor                if (cache.add(p)) {
1243219019Sgabor                    try {
1244219019Sgabor                        return visit(tv1.getUpperBound(), tv2.getUpperBound());
1245219019Sgabor                    } finally {
1246219019Sgabor                        cache.remove(p);
1247219019Sgabor                    }
1248219019Sgabor                } else {
1249219019Sgabor                    return false;
1250219019Sgabor                }
1251219019Sgabor            }
1252219019Sgabor        };
1253219019Sgabor
1254219019Sgabor        /**
1255219019Sgabor         * Strict type-equality relation - type variables are considered
1256219019Sgabor         * equals if they share the same object identity.
1257219019Sgabor         */
1258219019Sgabor        TypeRelation isSameTypeStrict = new SameTypeVisitor() {
1259219019Sgabor            @Override
1260219019Sgabor            boolean sameTypeVars(TypeVar tv1, TypeVar tv2) {
1261219019Sgabor                return tv1 == tv2;
1262219019Sgabor            }
1263219019Sgabor            @Override
1264219019Sgabor            protected boolean containsTypes(List<Type> ts1, List<Type> ts2) {
1265219019Sgabor                return isSameTypes(ts1, ts2, true);
1266219019Sgabor            }
1267219019Sgabor
1268219019Sgabor            @Override
1269219019Sgabor            public Boolean visitWildcardType(WildcardType t, Type s) {
1270219019Sgabor                if (!s.hasTag(WILDCARD)) {
1271219019Sgabor                    return false;
1272219019Sgabor                } else {
1273219019Sgabor                    WildcardType t2 = (WildcardType)s;
1274219019Sgabor                    return t.kind == t2.kind &&
1275219019Sgabor                            isSameType(t.type, t2.type, true);
1276219019Sgabor                }
1277219019Sgabor            }
1278219019Sgabor        };
1279219019Sgabor
1280219019Sgabor    // </editor-fold>
1281219019Sgabor
1282219019Sgabor    // <editor-fold defaultstate="collapsed" desc="Contains Type">
1283219019Sgabor    public boolean containedBy(Type t, Type s) {
1284219019Sgabor        switch (t.getTag()) {
1285219019Sgabor        case UNDETVAR:
1286219019Sgabor            if (s.hasTag(WILDCARD)) {
1287219019Sgabor                UndetVar undetvar = (UndetVar)t;
1288219019Sgabor                WildcardType wt = (WildcardType)s;
1289219019Sgabor                switch(wt.kind) {
1290219019Sgabor                    case UNBOUND:
1291219019Sgabor                        break;
1292219019Sgabor                    case EXTENDS: {
1293219019Sgabor                        Type bound = wildUpperBound(s);
1294219019Sgabor                        undetvar.addBound(InferenceBound.UPPER, bound, this);
1295219019Sgabor                        break;
1296219019Sgabor                    }
1297219019Sgabor                    case SUPER: {
1298219019Sgabor                        Type bound = wildLowerBound(s);
1299219019Sgabor                        undetvar.addBound(InferenceBound.LOWER, bound, this);
1300219019Sgabor                        break;
1301219019Sgabor                    }
1302219019Sgabor                }
1303219019Sgabor                return true;
1304219019Sgabor            } else {
1305219019Sgabor                return isSameType(t, s);
1306219019Sgabor            }
1307219019Sgabor        case ERROR:
1308219019Sgabor            return true;
1309219019Sgabor        default:
1310219019Sgabor            return containsType(s, t);
1311219019Sgabor        }
1312219019Sgabor    }
1313219019Sgabor
1314219019Sgabor    boolean containsType(List<Type> ts, List<Type> ss) {
1315219019Sgabor        while (ts.nonEmpty() && ss.nonEmpty()
1316219019Sgabor               && containsType(ts.head, ss.head)) {
1317219019Sgabor            ts = ts.tail;
1318219019Sgabor            ss = ss.tail;
1319219019Sgabor        }
1320219019Sgabor        return ts.isEmpty() && ss.isEmpty();
1321219019Sgabor    }
1322219019Sgabor
1323219019Sgabor    /**
1324219019Sgabor     * Check if t contains s.
1325219019Sgabor     *
1326219019Sgabor     * <p>T contains S if:
1327219019Sgabor     *
1328219019Sgabor     * <p>{@code L(T) <: L(S) && U(S) <: U(T)}
1329219019Sgabor     *
1330219019Sgabor     * <p>This relation is only used by ClassType.isSubtype(), that
1331219019Sgabor     * is,
1332219019Sgabor     *
1333219019Sgabor     * <p>{@code C<S> <: C<T> if T contains S.}
1334219019Sgabor     *
1335219019Sgabor     * <p>Because of F-bounds, this relation can lead to infinite
1336219019Sgabor     * recursion.  Thus we must somehow break that recursion.  Notice
1337219019Sgabor     * that containsType() is only called from ClassType.isSubtype().
1338219019Sgabor     * Since the arguments have already been checked against their
1339219019Sgabor     * bounds, we know:
1340219019Sgabor     *
1341219019Sgabor     * <p>{@code U(S) <: U(T) if T is "super" bound (U(T) *is* the bound)}
1342219019Sgabor     *
1343219019Sgabor     * <p>{@code L(T) <: L(S) if T is "extends" bound (L(T) is bottom)}
1344219019Sgabor     *
1345219019Sgabor     * @param t a type
1346219019Sgabor     * @param s a type
1347219019Sgabor     */
1348219019Sgabor    public boolean containsType(Type t, Type s) {
1349219019Sgabor        return containsType.visit(t, s);
1350219019Sgabor    }
1351219019Sgabor    // where
1352219019Sgabor        private TypeRelation containsType = new TypeRelation() {
1353219019Sgabor
1354219019Sgabor            public Boolean visitType(Type t, Type s) {
1355219019Sgabor                if (s.isPartial())
1356219019Sgabor                    return containedBy(s, t);
1357219019Sgabor                else
1358219019Sgabor                    return isSameType(t, s);
1359219019Sgabor            }
1360219019Sgabor
1361219019Sgabor//            void debugContainsType(WildcardType t, Type s) {
1362219019Sgabor//                System.err.println();
1363219019Sgabor//                System.err.format(" does %s contain %s?%n", t, s);
1364219019Sgabor//                System.err.format(" %s U(%s) <: U(%s) %s = %s%n",
1365219019Sgabor//                                  wildUpperBound(s), s, t, wildUpperBound(t),
1366219019Sgabor//                                  t.isSuperBound()
1367219019Sgabor//                                  || isSubtypeNoCapture(wildUpperBound(s), wildUpperBound(t)));
1368219019Sgabor//                System.err.format(" %s L(%s) <: L(%s) %s = %s%n",
1369219019Sgabor//                                  wildLowerBound(t), t, s, wildLowerBound(s),
1370219019Sgabor//                                  t.isExtendsBound()
1371219019Sgabor//                                  || isSubtypeNoCapture(wildLowerBound(t), wildLowerBound(s)));
1372219019Sgabor//                System.err.println();
1373219019Sgabor//            }
1374219019Sgabor
1375219019Sgabor            @Override
1376219019Sgabor            public Boolean visitWildcardType(WildcardType t, Type s) {
1377219019Sgabor                if (s.isPartial())
1378219019Sgabor                    return containedBy(s, t);
1379219019Sgabor                else {
1380219019Sgabor//                    debugContainsType(t, s);
1381219019Sgabor                    return isSameWildcard(t, s)
1382219019Sgabor                        || isCaptureOf(s, t)
1383219019Sgabor                        || ((t.isExtendsBound() || isSubtypeNoCapture(wildLowerBound(t), wildLowerBound(s))) &&
1384219019Sgabor                            (t.isSuperBound() || isSubtypeNoCapture(wildUpperBound(s), wildUpperBound(t))));
1385219019Sgabor                }
1386219019Sgabor            }
1387219019Sgabor
1388219019Sgabor            @Override
1389219019Sgabor            public Boolean visitUndetVar(UndetVar t, Type s) {
1390219019Sgabor                if (!s.hasTag(WILDCARD)) {
1391219019Sgabor                    return isSameType(t, s);
1392219019Sgabor                } else {
1393219019Sgabor                    return false;
1394219019Sgabor                }
1395219019Sgabor            }
1396219019Sgabor
1397219019Sgabor            @Override
1398219019Sgabor            public Boolean visitErrorType(ErrorType t, Type s) {
1399219019Sgabor                return true;
1400219019Sgabor            }
1401219019Sgabor        };
1402219019Sgabor
1403219019Sgabor    public boolean isCaptureOf(Type s, WildcardType t) {
1404219019Sgabor        if (!s.hasTag(TYPEVAR) || !((TypeVar)s).isCaptured())
1405219019Sgabor            return false;
1406219019Sgabor        return isSameWildcard(t, ((CapturedType)s).wildcard);
1407219019Sgabor    }
1408219019Sgabor
1409219019Sgabor    public boolean isSameWildcard(WildcardType t, Type s) {
1410219019Sgabor        if (!s.hasTag(WILDCARD))
1411219019Sgabor            return false;
1412219019Sgabor        WildcardType w = (WildcardType)s;
1413219019Sgabor        return w.kind == t.kind && w.type == t.type;
1414219019Sgabor    }
1415219019Sgabor
1416219019Sgabor    public boolean containsTypeEquivalent(List<Type> ts, List<Type> ss) {
1417219019Sgabor        while (ts.nonEmpty() && ss.nonEmpty()
1418219019Sgabor               && containsTypeEquivalent(ts.head, ss.head)) {
1419219019Sgabor            ts = ts.tail;
1420219019Sgabor            ss = ss.tail;
1421219019Sgabor        }
1422219019Sgabor        return ts.isEmpty() && ss.isEmpty();
1423219019Sgabor    }
1424219019Sgabor    // </editor-fold>
1425219019Sgabor
1426219019Sgabor    // <editor-fold defaultstate="collapsed" desc="isCastable">
1427219019Sgabor    public boolean isCastable(Type t, Type s) {
1428219019Sgabor        return isCastable(t, s, noWarnings);
1429219019Sgabor    }
1430219019Sgabor
1431219019Sgabor    /**
1432219019Sgabor     * Is t is castable to s?<br>
1433219019Sgabor     * s is assumed to be an erased type.<br>
1434219019Sgabor     * (not defined for Method and ForAll types).
1435219019Sgabor     */
1436219019Sgabor    public boolean isCastable(Type t, Type s, Warner warn) {
1437219019Sgabor        if (t == s)
1438219019Sgabor            return true;
1439219019Sgabor
1440219019Sgabor        if (t.isPrimitive() != s.isPrimitive())
1441219019Sgabor            return (isConvertible(t, s, warn)
1442219019Sgabor                    || (allowObjectToPrimitiveCast &&
1443219019Sgabor                        s.isPrimitive() &&
1444219019Sgabor                        isSubtype(boxedClass(s).type, t)));
1445219019Sgabor        if (warn != warnStack.head) {
1446219019Sgabor            try {
1447219019Sgabor                warnStack = warnStack.prepend(warn);
1448219019Sgabor                checkUnsafeVarargsConversion(t, s, warn);
1449219019Sgabor                return isCastable.visit(t,s);
1450219019Sgabor            } finally {
1451219019Sgabor                warnStack = warnStack.tail;
1452219019Sgabor            }
1453219019Sgabor        } else {
1454219019Sgabor            return isCastable.visit(t,s);
1455219019Sgabor        }
1456219019Sgabor    }
1457219019Sgabor    // where
1458219019Sgabor        private TypeRelation isCastable = new TypeRelation() {
1459219019Sgabor
1460219019Sgabor            public Boolean visitType(Type t, Type s) {
1461219019Sgabor                if (s.hasTag(ERROR))
1462219019Sgabor                    return true;
1463219019Sgabor
1464219019Sgabor                switch (t.getTag()) {
1465219019Sgabor                case BYTE: case CHAR: case SHORT: case INT: case LONG: case FLOAT:
1466219019Sgabor                case DOUBLE:
1467219019Sgabor                    return s.isNumeric();
1468219019Sgabor                case BOOLEAN:
1469219019Sgabor                    return s.hasTag(BOOLEAN);
1470219019Sgabor                case VOID:
1471219019Sgabor                    return false;
1472219019Sgabor                case BOT:
1473219019Sgabor                    return isSubtype(t, s);
1474219019Sgabor                default:
1475219019Sgabor                    throw new AssertionError();
1476219019Sgabor                }
1477219019Sgabor            }
1478219019Sgabor
1479219019Sgabor            @Override
1480219019Sgabor            public Boolean visitWildcardType(WildcardType t, Type s) {
1481219019Sgabor                return isCastable(wildUpperBound(t), s, warnStack.head);
1482219019Sgabor            }
1483219019Sgabor
1484219019Sgabor            @Override
1485219019Sgabor            public Boolean visitClassType(ClassType t, Type s) {
1486219019Sgabor                if (s.hasTag(ERROR) || s.hasTag(BOT))
1487219019Sgabor                    return true;
1488219019Sgabor
1489219019Sgabor                if (s.hasTag(TYPEVAR)) {
1490219019Sgabor                    if (isCastable(t, s.getUpperBound(), noWarnings)) {
1491219019Sgabor                        warnStack.head.warn(LintCategory.UNCHECKED);
1492219019Sgabor                        return true;
1493219019Sgabor                    } else {
1494219019Sgabor                        return false;
1495219019Sgabor                    }
1496219019Sgabor                }
1497219019Sgabor
1498219019Sgabor                if (t.isIntersection() || s.isIntersection()) {
1499219019Sgabor                    return !t.isIntersection() ?
1500219019Sgabor                            visitIntersectionType((IntersectionClassType)s, t, true) :
1501219019Sgabor                            visitIntersectionType((IntersectionClassType)t, s, false);
1502219019Sgabor                }
1503219019Sgabor
1504219019Sgabor                if (s.hasTag(CLASS) || s.hasTag(ARRAY)) {
1505219019Sgabor                    boolean upcast;
1506219019Sgabor                    if ((upcast = isSubtype(erasure(t), erasure(s)))
1507219019Sgabor                        || isSubtype(erasure(s), erasure(t))) {
1508219019Sgabor                        if (!upcast && s.hasTag(ARRAY)) {
1509219019Sgabor                            if (!isReifiable(s))
1510219019Sgabor                                warnStack.head.warn(LintCategory.UNCHECKED);
1511219019Sgabor                            return true;
1512219019Sgabor                        } else if (s.isRaw()) {
1513219019Sgabor                            return true;
1514219019Sgabor                        } else if (t.isRaw()) {
1515219019Sgabor                            if (!isUnbounded(s))
1516219019Sgabor                                warnStack.head.warn(LintCategory.UNCHECKED);
1517219019Sgabor                            return true;
1518219019Sgabor                        }
1519219019Sgabor                        // Assume |a| <: |b|
1520219019Sgabor                        final Type a = upcast ? t : s;
1521219019Sgabor                        final Type b = upcast ? s : t;
1522219019Sgabor                        final boolean HIGH = true;
1523219019Sgabor                        final boolean LOW = false;
1524219019Sgabor                        final boolean DONT_REWRITE_TYPEVARS = false;
1525219019Sgabor                        Type aHigh = rewriteQuantifiers(a, HIGH, DONT_REWRITE_TYPEVARS);
1526219019Sgabor                        Type aLow  = rewriteQuantifiers(a, LOW,  DONT_REWRITE_TYPEVARS);
1527219019Sgabor                        Type bHigh = rewriteQuantifiers(b, HIGH, DONT_REWRITE_TYPEVARS);
1528219019Sgabor                        Type bLow  = rewriteQuantifiers(b, LOW,  DONT_REWRITE_TYPEVARS);
1529219019Sgabor                        Type lowSub = asSub(bLow, aLow.tsym);
1530219019Sgabor                        Type highSub = (lowSub == null) ? null : asSub(bHigh, aHigh.tsym);
1531219019Sgabor                        if (highSub == null) {
1532219019Sgabor                            final boolean REWRITE_TYPEVARS = true;
1533219019Sgabor                            aHigh = rewriteQuantifiers(a, HIGH, REWRITE_TYPEVARS);
1534219019Sgabor                            aLow  = rewriteQuantifiers(a, LOW,  REWRITE_TYPEVARS);
1535219019Sgabor                            bHigh = rewriteQuantifiers(b, HIGH, REWRITE_TYPEVARS);
1536219019Sgabor                            bLow  = rewriteQuantifiers(b, LOW,  REWRITE_TYPEVARS);
1537219019Sgabor                            lowSub = asSub(bLow, aLow.tsym);
1538219019Sgabor                            highSub = (lowSub == null) ? null : asSub(bHigh, aHigh.tsym);
1539219019Sgabor                        }
1540219019Sgabor                        if (highSub != null) {
1541219019Sgabor                            if (!(a.tsym == highSub.tsym && a.tsym == lowSub.tsym)) {
1542219019Sgabor                                Assert.error(a.tsym + " != " + highSub.tsym + " != " + lowSub.tsym);
1543219019Sgabor                            }
1544219019Sgabor                            if (!disjointTypes(aHigh.allparams(), highSub.allparams())
1545219019Sgabor                                && !disjointTypes(aHigh.allparams(), lowSub.allparams())
1546219019Sgabor                                && !disjointTypes(aLow.allparams(), highSub.allparams())
1547219019Sgabor                                && !disjointTypes(aLow.allparams(), lowSub.allparams())) {
1548219019Sgabor                                if (upcast ? giveWarning(a, b) :
1549219019Sgabor                                    giveWarning(b, a))
1550219019Sgabor                                    warnStack.head.warn(LintCategory.UNCHECKED);
1551219019Sgabor                                return true;
1552219019Sgabor                            }
1553219019Sgabor                        }
1554219019Sgabor                        if (isReifiable(s))
1555219019Sgabor                            return isSubtypeUnchecked(a, b);
1556219019Sgabor                        else
1557219019Sgabor                            return isSubtypeUnchecked(a, b, warnStack.head);
1558219019Sgabor                    }
1559219019Sgabor
1560219019Sgabor                    // Sidecast
1561219019Sgabor                    if (s.hasTag(CLASS)) {
1562219019Sgabor                        if ((s.tsym.flags() & INTERFACE) != 0) {
1563219019Sgabor                            return ((t.tsym.flags() & FINAL) == 0)
1564219019Sgabor                                ? sideCast(t, s, warnStack.head)
1565219019Sgabor                                : sideCastFinal(t, s, warnStack.head);
1566219019Sgabor                        } else if ((t.tsym.flags() & INTERFACE) != 0) {
1567219019Sgabor                            return ((s.tsym.flags() & FINAL) == 0)
1568219019Sgabor                                ? sideCast(t, s, warnStack.head)
1569219019Sgabor                                : sideCastFinal(t, s, warnStack.head);
1570219019Sgabor                        } else {
1571219019Sgabor                            // unrelated class types
1572219019Sgabor                            return false;
1573219019Sgabor                        }
1574219019Sgabor                    }
1575219019Sgabor                }
1576219019Sgabor                return false;
1577219019Sgabor            }
1578219019Sgabor
1579219019Sgabor            boolean visitIntersectionType(IntersectionClassType ict, Type s, boolean reverse) {
1580219019Sgabor                Warner warn = noWarnings;
1581219019Sgabor                for (Type c : ict.getComponents()) {
1582219019Sgabor                    warn.clear();
1583219019Sgabor                    if (reverse ? !isCastable(s, c, warn) : !isCastable(c, s, warn))
1584219019Sgabor                        return false;
1585219019Sgabor                }
1586219019Sgabor                if (warn.hasLint(LintCategory.UNCHECKED))
1587219019Sgabor                    warnStack.head.warn(LintCategory.UNCHECKED);
1588219019Sgabor                return true;
1589219019Sgabor            }
1590219019Sgabor
1591219019Sgabor            @Override
1592219019Sgabor            public Boolean visitArrayType(ArrayType t, Type s) {
1593219019Sgabor                switch (s.getTag()) {
1594219019Sgabor                case ERROR:
1595219019Sgabor                case BOT:
1596219019Sgabor                    return true;
1597219019Sgabor                case TYPEVAR:
1598219019Sgabor                    if (isCastable(s, t, noWarnings)) {
1599219019Sgabor                        warnStack.head.warn(LintCategory.UNCHECKED);
1600219019Sgabor                        return true;
1601219019Sgabor                    } else {
1602219019Sgabor                        return false;
1603219019Sgabor                    }
1604219019Sgabor                case CLASS:
1605219019Sgabor                    return isSubtype(t, s);
1606219019Sgabor                case ARRAY:
1607219019Sgabor                    if (elemtype(t).isPrimitive() || elemtype(s).isPrimitive()) {
1608219019Sgabor                        return elemtype(t).hasTag(elemtype(s).getTag());
1609219019Sgabor                    } else {
1610219019Sgabor                        return visit(elemtype(t), elemtype(s));
1611219019Sgabor                    }
1612219019Sgabor                default:
1613219019Sgabor                    return false;
1614219019Sgabor                }
1615219019Sgabor            }
1616219019Sgabor
1617219019Sgabor            @Override
1618219019Sgabor            public Boolean visitTypeVar(TypeVar t, Type s) {
1619219019Sgabor                switch (s.getTag()) {
1620219019Sgabor                case ERROR:
1621219019Sgabor                case BOT:
1622219019Sgabor                    return true;
1623219019Sgabor                case TYPEVAR:
1624219019Sgabor                    if (isSubtype(t, s)) {
1625219019Sgabor                        return true;
1626219019Sgabor                    } else if (isCastable(t.bound, s, noWarnings)) {
1627219019Sgabor                        warnStack.head.warn(LintCategory.UNCHECKED);
1628219019Sgabor                        return true;
1629219019Sgabor                    } else {
1630219019Sgabor                        return false;
1631219019Sgabor                    }
1632219019Sgabor                default:
1633219019Sgabor                    return isCastable(t.bound, s, warnStack.head);
1634219019Sgabor                }
1635219019Sgabor            }
1636219019Sgabor
1637219019Sgabor            @Override
1638219019Sgabor            public Boolean visitErrorType(ErrorType t, Type s) {
1639219019Sgabor                return true;
1640219019Sgabor            }
1641219019Sgabor        };
1642219019Sgabor    // </editor-fold>
1643219019Sgabor
1644219019Sgabor    // <editor-fold defaultstate="collapsed" desc="disjointTypes">
1645219019Sgabor    public boolean disjointTypes(List<Type> ts, List<Type> ss) {
1646219019Sgabor        while (ts.tail != null && ss.tail != null) {
1647219019Sgabor            if (disjointType(ts.head, ss.head)) return true;
1648219019Sgabor            ts = ts.tail;
1649219019Sgabor            ss = ss.tail;
1650219019Sgabor        }
1651219019Sgabor        return false;
1652219019Sgabor    }
1653219019Sgabor
1654219019Sgabor    /**
1655219019Sgabor     * Two types or wildcards are considered disjoint if it can be
1656219019Sgabor     * proven that no type can be contained in both. It is
1657219019Sgabor     * conservative in that it is allowed to say that two types are
1658219019Sgabor     * not disjoint, even though they actually are.
1659219019Sgabor     *
1660219019Sgabor     * The type {@code C<X>} is castable to {@code C<Y>} exactly if
1661219019Sgabor     * {@code X} and {@code Y} are not disjoint.
1662219019Sgabor     */
1663219019Sgabor    public boolean disjointType(Type t, Type s) {
1664219019Sgabor        return disjointType.visit(t, s);
1665219019Sgabor    }
1666219019Sgabor    // where
1667219019Sgabor        private TypeRelation disjointType = new TypeRelation() {
1668219019Sgabor
1669219019Sgabor            private Set<TypePair> cache = new HashSet<>();
1670219019Sgabor
1671219019Sgabor            @Override
1672219019Sgabor            public Boolean visitType(Type t, Type s) {
1673219019Sgabor                if (s.hasTag(WILDCARD))
1674219019Sgabor                    return visit(s, t);
1675219019Sgabor                else
1676219019Sgabor                    return notSoftSubtypeRecursive(t, s) || notSoftSubtypeRecursive(s, t);
1677219019Sgabor            }
1678219019Sgabor
1679219019Sgabor            private boolean isCastableRecursive(Type t, Type s) {
1680219019Sgabor                TypePair pair = new TypePair(t, s);
1681219019Sgabor                if (cache.add(pair)) {
1682219019Sgabor                    try {
1683219019Sgabor                        return Types.this.isCastable(t, s);
1684219019Sgabor                    } finally {
1685219019Sgabor                        cache.remove(pair);
1686219019Sgabor                    }
1687219019Sgabor                } else {
1688219019Sgabor                    return true;
1689219019Sgabor                }
1690219019Sgabor            }
1691219019Sgabor
1692219019Sgabor            private boolean notSoftSubtypeRecursive(Type t, Type s) {
1693219019Sgabor                TypePair pair = new TypePair(t, s);
1694219019Sgabor                if (cache.add(pair)) {
1695219019Sgabor                    try {
1696219019Sgabor                        return Types.this.notSoftSubtype(t, s);
1697219019Sgabor                    } finally {
1698219019Sgabor                        cache.remove(pair);
1699219019Sgabor                    }
1700219019Sgabor                } else {
1701219019Sgabor                    return false;
1702219019Sgabor                }
1703219019Sgabor            }
1704219019Sgabor
1705219019Sgabor            @Override
1706219019Sgabor            public Boolean visitWildcardType(WildcardType t, Type s) {
1707219019Sgabor                if (t.isUnbound())
1708219019Sgabor                    return false;
1709219019Sgabor
1710219019Sgabor                if (!s.hasTag(WILDCARD)) {
1711219019Sgabor                    if (t.isExtendsBound())
1712219019Sgabor                        return notSoftSubtypeRecursive(s, t.type);
1713219019Sgabor                    else
1714219019Sgabor                        return notSoftSubtypeRecursive(t.type, s);
1715219019Sgabor                }
1716219019Sgabor
1717219019Sgabor                if (s.isUnbound())
1718219019Sgabor                    return false;
1719219019Sgabor
1720219019Sgabor                if (t.isExtendsBound()) {
1721219019Sgabor                    if (s.isExtendsBound())
1722219019Sgabor                        return !isCastableRecursive(t.type, wildUpperBound(s));
1723219019Sgabor                    else if (s.isSuperBound())
1724219019Sgabor                        return notSoftSubtypeRecursive(wildLowerBound(s), t.type);
1725219019Sgabor                } else if (t.isSuperBound()) {
1726219019Sgabor                    if (s.isExtendsBound())
1727219019Sgabor                        return notSoftSubtypeRecursive(t.type, wildUpperBound(s));
1728219019Sgabor                }
1729219019Sgabor                return false;
1730219019Sgabor            }
1731219019Sgabor        };
1732219019Sgabor    // </editor-fold>
1733219019Sgabor
1734219019Sgabor    // <editor-fold defaultstate="collapsed" desc="cvarLowerBounds">
1735219019Sgabor    public List<Type> cvarLowerBounds(List<Type> ts) {
1736219019Sgabor        return ts.map(cvarLowerBoundMapping);
1737219019Sgabor    }
1738219019Sgabor        private final TypeMapping<Void> cvarLowerBoundMapping = new TypeMapping<Void>() {
1739219019Sgabor            @Override
1740219019Sgabor            public Type visitCapturedType(CapturedType t, Void _unused) {
1741219019Sgabor                return cvarLowerBound(t);
1742219019Sgabor            }
1743219019Sgabor        };
1744219019Sgabor    // </editor-fold>
1745219019Sgabor
1746219019Sgabor    // <editor-fold defaultstate="collapsed" desc="notSoftSubtype">
1747219019Sgabor    /**
1748219019Sgabor     * This relation answers the question: is impossible that
1749219019Sgabor     * something of type `t' can be a subtype of `s'? This is
1750219019Sgabor     * different from the question "is `t' not a subtype of `s'?"
1751219019Sgabor     * when type variables are involved: Integer is not a subtype of T
1752219019Sgabor     * where {@code <T extends Number>} but it is not true that Integer cannot
1753219019Sgabor     * possibly be a subtype of T.
1754219019Sgabor     */
1755219019Sgabor    public boolean notSoftSubtype(Type t, Type s) {
1756219019Sgabor        if (t == s) return false;
1757219019Sgabor        if (t.hasTag(TYPEVAR)) {
1758219019Sgabor            TypeVar tv = (TypeVar) t;
1759219019Sgabor            return !isCastable(tv.bound,
1760219019Sgabor                               relaxBound(s),
1761219019Sgabor                               noWarnings);
1762219019Sgabor        }
1763219019Sgabor        if (!s.hasTag(WILDCARD))
1764219019Sgabor            s = cvarUpperBound(s);
1765219019Sgabor
1766219019Sgabor        return !isSubtype(t, relaxBound(s));
1767219019Sgabor    }
1768219019Sgabor
1769219019Sgabor    private Type relaxBound(Type t) {
1770219019Sgabor        return (t.hasTag(TYPEVAR)) ?
1771219019Sgabor                rewriteQuantifiers(skipTypeVars(t, false), true, true) :
1772219019Sgabor                t;
1773219019Sgabor    }
1774219019Sgabor    // </editor-fold>
1775219019Sgabor
1776219019Sgabor    // <editor-fold defaultstate="collapsed" desc="isReifiable">
1777219019Sgabor    public boolean isReifiable(Type t) {
1778219019Sgabor        return isReifiable.visit(t);
1779219019Sgabor    }
1780219019Sgabor    // where
1781219019Sgabor        private UnaryVisitor<Boolean> isReifiable = new UnaryVisitor<Boolean>() {
1782219019Sgabor
1783219019Sgabor            public Boolean visitType(Type t, Void ignored) {
1784219019Sgabor                return true;
1785219019Sgabor            }
1786219019Sgabor
1787219019Sgabor            @Override
1788219019Sgabor            public Boolean visitClassType(ClassType t, Void ignored) {
1789219019Sgabor                if (t.isCompound())
1790219019Sgabor                    return false;
1791219019Sgabor                else {
1792219019Sgabor                    if (!t.isParameterized())
1793219019Sgabor                        return true;
1794219019Sgabor
1795219019Sgabor                    for (Type param : t.allparams()) {
1796219019Sgabor                        if (!param.isUnbound())
1797219019Sgabor                            return false;
1798219019Sgabor                    }
1799219019Sgabor                    return true;
1800219019Sgabor                }
1801219019Sgabor            }
1802219019Sgabor
1803219019Sgabor            @Override
1804219019Sgabor            public Boolean visitArrayType(ArrayType t, Void ignored) {
1805219019Sgabor                return visit(t.elemtype);
1806219019Sgabor            }
1807219019Sgabor
1808219019Sgabor            @Override
1809219019Sgabor            public Boolean visitTypeVar(TypeVar t, Void ignored) {
1810219019Sgabor                return false;
1811219019Sgabor            }
1812219019Sgabor        };
1813219019Sgabor    // </editor-fold>
1814219019Sgabor
1815219019Sgabor    // <editor-fold defaultstate="collapsed" desc="Array Utils">
1816219019Sgabor    public boolean isArray(Type t) {
1817219019Sgabor        while (t.hasTag(WILDCARD))
1818219019Sgabor            t = wildUpperBound(t);
1819219019Sgabor        return t.hasTag(ARRAY);
1820219019Sgabor    }
1821219019Sgabor
1822219019Sgabor    /**
1823219019Sgabor     * The element type of an array.
1824219019Sgabor     */
1825219019Sgabor    public Type elemtype(Type t) {
1826219019Sgabor        switch (t.getTag()) {
1827219019Sgabor        case WILDCARD:
1828219019Sgabor            return elemtype(wildUpperBound(t));
1829219019Sgabor        case ARRAY:
1830219019Sgabor            return ((ArrayType)t).elemtype;
1831219019Sgabor        case FORALL:
1832219019Sgabor            return elemtype(((ForAll)t).qtype);
1833219019Sgabor        case ERROR:
1834219019Sgabor            return t;
1835219019Sgabor        default:
1836219019Sgabor            return null;
1837219019Sgabor        }
1838219019Sgabor    }
1839219019Sgabor
1840219019Sgabor    public Type elemtypeOrType(Type t) {
1841219019Sgabor        Type elemtype = elemtype(t);
1842219019Sgabor        return elemtype != null ?
1843219019Sgabor            elemtype :
1844219019Sgabor            t;
1845219019Sgabor    }
1846219019Sgabor
1847219019Sgabor    /**
1848219019Sgabor     * Mapping to take element type of an arraytype
1849219019Sgabor     */
1850219019Sgabor    private TypeMapping<Void> elemTypeFun = new TypeMapping<Void>() {
1851219019Sgabor        @Override
1852219019Sgabor        public Type visitArrayType(ArrayType t, Void _unused) {
1853219019Sgabor            return t.elemtype;
1854219019Sgabor        }
1855219019Sgabor
1856219019Sgabor        @Override
1857219019Sgabor        public Type visitTypeVar(TypeVar t, Void _unused) {
1858219019Sgabor            return visit(skipTypeVars(t, false));
1859219019Sgabor        }
1860219019Sgabor    };
1861219019Sgabor
1862219019Sgabor    /**
1863219019Sgabor     * The number of dimensions of an array type.
1864219019Sgabor     */
1865219019Sgabor    public int dimensions(Type t) {
1866219019Sgabor        int result = 0;
1867219019Sgabor        while (t.hasTag(ARRAY)) {
1868219019Sgabor            result++;
1869219019Sgabor            t = elemtype(t);
1870219019Sgabor        }
1871219019Sgabor        return result;
1872219019Sgabor    }
1873219019Sgabor
1874219019Sgabor    /**
1875219019Sgabor     * Returns an ArrayType with the component type t
1876219019Sgabor     *
1877219019Sgabor     * @param t The component type of the ArrayType
1878219019Sgabor     * @return the ArrayType for the given component
1879219019Sgabor     */
1880219019Sgabor    public ArrayType makeArrayType(Type t) {
1881219019Sgabor        if (t.hasTag(VOID) || t.hasTag(PACKAGE)) {
1882219019Sgabor            Assert.error("Type t must not be a VOID or PACKAGE type, " + t.toString());
1883219019Sgabor        }
1884219019Sgabor        return new ArrayType(t, syms.arrayClass);
1885219019Sgabor    }
1886219019Sgabor    // </editor-fold>
1887219019Sgabor
1888219019Sgabor    // <editor-fold defaultstate="collapsed" desc="asSuper">
1889219019Sgabor    /**
1890219019Sgabor     * Return the (most specific) base type of t that starts with the
1891219019Sgabor     * given symbol.  If none exists, return null.
1892219019Sgabor     *
1893219019Sgabor     * Caveat Emptor: Since javac represents the class of all arrays with a singleton
1894219019Sgabor     * symbol Symtab.arrayClass, which by being a singleton cannot hold any discriminant,
1895219019Sgabor     * this method could yield surprising answers when invoked on arrays. For example when
1896219019Sgabor     * invoked with t being byte [] and sym being t.sym itself, asSuper would answer null.
1897219019Sgabor     *
1898219019Sgabor     * @param t a type
1899219019Sgabor     * @param sym a symbol
1900219019Sgabor     */
1901219019Sgabor    public Type asSuper(Type t, Symbol sym) {
1902219019Sgabor        /* Some examples:
1903219019Sgabor         *
1904219019Sgabor         * (Enum<E>, Comparable) => Comparable<E>
1905219019Sgabor         * (c.s.s.d.AttributeTree.ValueKind, Enum) => Enum<c.s.s.d.AttributeTree.ValueKind>
1906219019Sgabor         * (c.s.s.t.ExpressionTree, c.s.s.t.Tree) => c.s.s.t.Tree
1907219019Sgabor         * (j.u.List<capture#160 of ? extends c.s.s.d.DocTree>, Iterable) =>
1908219019Sgabor         *     Iterable<capture#160 of ? extends c.s.s.d.DocTree>
1909219019Sgabor         */
1910219019Sgabor        if (sym.type == syms.objectType) { //optimization
1911219019Sgabor            return syms.objectType;
1912219019Sgabor        }
1913219019Sgabor        return asSuper.visit(t, sym);
1914219019Sgabor    }
1915219019Sgabor    // where
1916219019Sgabor        private SimpleVisitor<Type,Symbol> asSuper = new SimpleVisitor<Type,Symbol>() {
1917219019Sgabor
1918219019Sgabor            public Type visitType(Type t, Symbol sym) {
1919219019Sgabor                return null;
1920219019Sgabor            }
1921219019Sgabor
1922219019Sgabor            @Override
1923219019Sgabor            public Type visitClassType(ClassType t, Symbol sym) {
1924219019Sgabor                if (t.tsym == sym)
1925219019Sgabor                    return t;
1926219019Sgabor
1927219019Sgabor                Type st = supertype(t);
1928219019Sgabor                if (st.hasTag(CLASS) || st.hasTag(TYPEVAR)) {
1929219019Sgabor                    Type x = asSuper(st, sym);
1930219019Sgabor                    if (x != null)
1931219019Sgabor                        return x;
1932219019Sgabor                }
1933219019Sgabor                if ((sym.flags() & INTERFACE) != 0) {
1934219019Sgabor                    for (List<Type> l = interfaces(t); l.nonEmpty(); l = l.tail) {
1935219019Sgabor                        if (!l.head.hasTag(ERROR)) {
1936219019Sgabor                            Type x = asSuper(l.head, sym);
1937219019Sgabor                            if (x != null)
1938219019Sgabor                                return x;
1939219019Sgabor                        }
1940219019Sgabor                    }
1941219019Sgabor                }
1942219019Sgabor                return null;
1943219019Sgabor            }
1944219019Sgabor
1945219019Sgabor            @Override
1946219019Sgabor            public Type visitArrayType(ArrayType t, Symbol sym) {
1947219019Sgabor                return isSubtype(t, sym.type) ? sym.type : null;
1948219019Sgabor            }
1949219019Sgabor
1950219019Sgabor            @Override
1951219019Sgabor            public Type visitTypeVar(TypeVar t, Symbol sym) {
1952219019Sgabor                if (t.tsym == sym)
1953219019Sgabor                    return t;
1954219019Sgabor                else
1955219019Sgabor                    return asSuper(t.bound, sym);
1956219019Sgabor            }
1957219019Sgabor
1958219019Sgabor            @Override
1959219019Sgabor            public Type visitErrorType(ErrorType t, Symbol sym) {
1960219019Sgabor                return t;
1961219019Sgabor            }
1962219019Sgabor        };
1963219019Sgabor
1964219019Sgabor    /**
1965219019Sgabor     * Return the base type of t or any of its outer types that starts
1966219019Sgabor     * with the given symbol.  If none exists, return null.
1967219019Sgabor     *
1968219019Sgabor     * @param t a type
1969219019Sgabor     * @param sym a symbol
1970219019Sgabor     */
1971219019Sgabor    public Type asOuterSuper(Type t, Symbol sym) {
1972219019Sgabor        switch (t.getTag()) {
1973219019Sgabor        case CLASS:
1974219019Sgabor            do {
1975219019Sgabor                Type s = asSuper(t, sym);
1976219019Sgabor                if (s != null) return s;
1977219019Sgabor                t = t.getEnclosingType();
1978219019Sgabor            } while (t.hasTag(CLASS));
1979219019Sgabor            return null;
1980219019Sgabor        case ARRAY:
1981219019Sgabor            return isSubtype(t, sym.type) ? sym.type : null;
1982219019Sgabor        case TYPEVAR:
1983219019Sgabor            return asSuper(t, sym);
1984219019Sgabor        case ERROR:
1985219019Sgabor            return t;
1986219019Sgabor        default:
1987219019Sgabor            return null;
1988219019Sgabor        }
1989219019Sgabor    }
1990219019Sgabor
1991219019Sgabor    /**
1992219019Sgabor     * Return the base type of t or any of its enclosing types that
1993219019Sgabor     * starts with the given symbol.  If none exists, return null.
1994219019Sgabor     *
1995219019Sgabor     * @param t a type
1996219019Sgabor     * @param sym a symbol
1997219019Sgabor     */
1998219019Sgabor    public Type asEnclosingSuper(Type t, Symbol sym) {
1999219019Sgabor        switch (t.getTag()) {
2000219019Sgabor        case CLASS:
2001219019Sgabor            do {
2002219019Sgabor                Type s = asSuper(t, sym);
2003219019Sgabor                if (s != null) return s;
2004219019Sgabor                Type outer = t.getEnclosingType();
2005219019Sgabor                t = (outer.hasTag(CLASS)) ? outer :
2006219019Sgabor                    (t.tsym.owner.enclClass() != null) ? t.tsym.owner.enclClass().type :
2007219019Sgabor                    Type.noType;
2008219019Sgabor            } while (t.hasTag(CLASS));
2009219019Sgabor            return null;
2010219019Sgabor        case ARRAY:
2011219019Sgabor            return isSubtype(t, sym.type) ? sym.type : null;
2012219019Sgabor        case TYPEVAR:
2013219019Sgabor            return asSuper(t, sym);
2014219019Sgabor        case ERROR:
2015219019Sgabor            return t;
2016219019Sgabor        default:
2017219019Sgabor            return null;
2018219019Sgabor        }
2019219019Sgabor    }
2020219019Sgabor    // </editor-fold>
2021219019Sgabor
2022219019Sgabor    // <editor-fold defaultstate="collapsed" desc="memberType">
2023219019Sgabor    /**
2024219019Sgabor     * The type of given symbol, seen as a member of t.
2025219019Sgabor     *
2026219019Sgabor     * @param t a type
2027219019Sgabor     * @param sym a symbol
2028219019Sgabor     */
2029219019Sgabor    public Type memberType(Type t, Symbol sym) {
2030219019Sgabor        return (sym.flags() & STATIC) != 0
2031219019Sgabor            ? sym.type
2032219019Sgabor            : memberType.visit(t, sym);
2033219019Sgabor        }
2034219019Sgabor    // where
2035219019Sgabor        private SimpleVisitor<Type,Symbol> memberType = new SimpleVisitor<Type,Symbol>() {
2036219019Sgabor
2037219019Sgabor            public Type visitType(Type t, Symbol sym) {
2038219019Sgabor                return sym.type;
2039219019Sgabor            }
2040219019Sgabor
2041219019Sgabor            @Override
2042219019Sgabor            public Type visitWildcardType(WildcardType t, Symbol sym) {
2043219019Sgabor                return memberType(wildUpperBound(t), sym);
2044219019Sgabor            }
2045219019Sgabor
2046219019Sgabor            @Override
2047219019Sgabor            public Type visitClassType(ClassType t, Symbol sym) {
2048219019Sgabor                Symbol owner = sym.owner;
2049219019Sgabor                long flags = sym.flags();
2050219019Sgabor                if (((flags & STATIC) == 0) && owner.type.isParameterized()) {
2051219019Sgabor                    Type base = asOuterSuper(t, owner);
2052219019Sgabor                    //if t is an intersection type T = CT & I1 & I2 ... & In
2053219019Sgabor                    //its supertypes CT, I1, ... In might contain wildcards
2054219019Sgabor                    //so we need to go through capture conversion
2055219019Sgabor                    base = t.isCompound() ? capture(base) : base;
2056219019Sgabor                    if (base != null) {
2057219019Sgabor                        List<Type> ownerParams = owner.type.allparams();
2058219019Sgabor                        List<Type> baseParams = base.allparams();
2059219019Sgabor                        if (ownerParams.nonEmpty()) {
2060219019Sgabor                            if (baseParams.isEmpty()) {
2061219019Sgabor                                // then base is a raw type
2062219019Sgabor                                return erasure(sym.type);
2063219019Sgabor                            } else {
2064219019Sgabor                                return subst(sym.type, ownerParams, baseParams);
2065219019Sgabor                            }
2066219019Sgabor                        }
2067219019Sgabor                    }
2068219019Sgabor                }
2069219019Sgabor                return sym.type;
2070219019Sgabor            }
2071219019Sgabor
2072219019Sgabor            @Override
2073219019Sgabor            public Type visitTypeVar(TypeVar t, Symbol sym) {
2074219019Sgabor                return memberType(t.bound, sym);
2075219019Sgabor            }
2076219019Sgabor
2077219019Sgabor            @Override
2078219019Sgabor            public Type visitErrorType(ErrorType t, Symbol sym) {
2079219019Sgabor                return t;
2080219019Sgabor            }
2081219019Sgabor        };
2082219019Sgabor    // </editor-fold>
2083219019Sgabor
2084219019Sgabor    // <editor-fold defaultstate="collapsed" desc="isAssignable">
2085219019Sgabor    public boolean isAssignable(Type t, Type s) {
2086219019Sgabor        return isAssignable(t, s, noWarnings);
2087219019Sgabor    }
2088219019Sgabor
2089219019Sgabor    /**
2090219019Sgabor     * Is t assignable to s?<br>
2091219019Sgabor     * Equivalent to subtype except for constant values and raw
2092219019Sgabor     * types.<br>
2093219019Sgabor     * (not defined for Method and ForAll types)
2094219019Sgabor     */
2095219019Sgabor    public boolean isAssignable(Type t, Type s, Warner warn) {
2096219019Sgabor        if (t.hasTag(ERROR))
2097219019Sgabor            return true;
2098219019Sgabor        if (t.getTag().isSubRangeOf(INT) && t.constValue() != null) {
2099219019Sgabor            int value = ((Number)t.constValue()).intValue();
2100219019Sgabor            switch (s.getTag()) {
2101219019Sgabor            case BYTE:
2102219019Sgabor                if (Byte.MIN_VALUE <= value && value <= Byte.MAX_VALUE)
2103219019Sgabor                    return true;
2104219019Sgabor                break;
2105219019Sgabor            case CHAR:
2106219019Sgabor                if (Character.MIN_VALUE <= value && value <= Character.MAX_VALUE)
2107219019Sgabor                    return true;
2108219019Sgabor                break;
2109219019Sgabor            case SHORT:
2110219019Sgabor                if (Short.MIN_VALUE <= value && value <= Short.MAX_VALUE)
2111219019Sgabor                    return true;
2112219019Sgabor                break;
2113219019Sgabor            case INT:
2114219019Sgabor                return true;
2115219019Sgabor            case CLASS:
2116219019Sgabor                switch (unboxedType(s).getTag()) {
2117219019Sgabor                case BYTE:
2118219019Sgabor                case CHAR:
2119219019Sgabor                case SHORT:
2120219019Sgabor                    return isAssignable(t, unboxedType(s), warn);
2121219019Sgabor                }
2122219019Sgabor                break;
2123219019Sgabor            }
2124219019Sgabor        }
2125219019Sgabor        return isConvertible(t, s, warn);
2126219019Sgabor    }
2127219019Sgabor    // </editor-fold>
2128219019Sgabor
2129219019Sgabor    // <editor-fold defaultstate="collapsed" desc="erasure">
2130219019Sgabor    /**
2131219019Sgabor     * The erasure of t {@code |t|} -- the type that results when all
2132219019Sgabor     * type parameters in t are deleted.
2133219019Sgabor     */
2134219019Sgabor    public Type erasure(Type t) {
2135219019Sgabor        return eraseNotNeeded(t) ? t : erasure(t, false);
2136219019Sgabor    }
2137219019Sgabor    //where
2138219019Sgabor    private boolean eraseNotNeeded(Type t) {
2139219019Sgabor        // We don't want to erase primitive types and String type as that
2140219019Sgabor        // operation is idempotent. Also, erasing these could result in loss
2141219019Sgabor        // of information such as constant values attached to such types.
2142219019Sgabor        return (t.isPrimitive()) || (syms.stringType.tsym == t.tsym);
2143219019Sgabor    }
2144219019Sgabor
2145219019Sgabor    private Type erasure(Type t, boolean recurse) {
2146219019Sgabor        if (t.isPrimitive()) {
2147219019Sgabor            return t; /* fast special case */
2148219019Sgabor        } else {
2149219019Sgabor            Type out = erasure.visit(t, recurse);
2150219019Sgabor            return out;
2151219019Sgabor        }
2152219019Sgabor        }
2153219019Sgabor    // where
2154219019Sgabor        private TypeMapping<Boolean> erasure = new TypeMapping<Boolean>() {
2155219019Sgabor            private Type combineMetadata(final Type s,
2156219019Sgabor                                         final Type t) {
2157219019Sgabor                if (t.getMetadata() != TypeMetadata.EMPTY) {
2158219019Sgabor                    switch (s.getKind()) {
2159219019Sgabor                        case OTHER:
2160219019Sgabor                        case UNION:
2161219019Sgabor                        case INTERSECTION:
2162219019Sgabor                        case PACKAGE:
2163219019Sgabor                        case EXECUTABLE:
2164219019Sgabor                        case NONE:
2165219019Sgabor                        case VOID:
2166219019Sgabor                        case ERROR:
2167219019Sgabor                            return s;
2168219019Sgabor                        default: return s.cloneWithMetadata(s.getMetadata().without(Kind.ANNOTATIONS));
2169219019Sgabor                    }
2170219019Sgabor                } else {
2171219019Sgabor                    return s;
2172219019Sgabor                }
2173219019Sgabor            }
2174219019Sgabor
2175219019Sgabor            public Type visitType(Type t, Boolean recurse) {
2176219019Sgabor                if (t.isPrimitive())
2177219019Sgabor                    return t; /*fast special case*/
2178219019Sgabor                else {
2179219019Sgabor                    //other cases already handled
2180219019Sgabor                    return combineMetadata(t, t);
2181219019Sgabor                }
2182219019Sgabor            }
2183219019Sgabor
2184219019Sgabor            @Override
2185219019Sgabor            public Type visitClassType(ClassType t, Boolean recurse) {
2186219019Sgabor                Type erased = t.tsym.erasure(Types.this);
2187219019Sgabor                if (recurse) {
2188219019Sgabor                    erased = new ErasedClassType(erased.getEnclosingType(),erased.tsym,
2189219019Sgabor                            t.getMetadata().without(Kind.ANNOTATIONS));
2190219019Sgabor                    return erased;
2191219019Sgabor                } else {
2192219019Sgabor                    return combineMetadata(erased, t);
2193219019Sgabor                }
2194219019Sgabor            }
2195219019Sgabor
2196219019Sgabor            @Override
2197219019Sgabor            public Type visitTypeVar(TypeVar t, Boolean recurse) {
2198219019Sgabor                Type erased = erasure(t.bound, recurse);
2199219019Sgabor                return combineMetadata(erased, t);
2200219019Sgabor            }
2201219019Sgabor        };
2202219019Sgabor
2203219019Sgabor    public List<Type> erasure(List<Type> ts) {
2204219019Sgabor        return erasure.visit(ts, false);
2205219019Sgabor    }
2206219019Sgabor
2207219019Sgabor    public Type erasureRecursive(Type t) {
2208219019Sgabor        return erasure(t, true);
2209219019Sgabor    }
2210219019Sgabor
2211219019Sgabor    public List<Type> erasureRecursive(List<Type> ts) {
2212219019Sgabor        return erasure.visit(ts, true);
2213219019Sgabor    }
2214219019Sgabor    // </editor-fold>
2215219019Sgabor
2216219019Sgabor    // <editor-fold defaultstate="collapsed" desc="makeIntersectionType">
2217219019Sgabor    /**
2218219019Sgabor     * Make an intersection type from non-empty list of types.  The list should be ordered according to
2219219019Sgabor     * {@link TypeSymbol#precedes(TypeSymbol, Types)}. Note that this might cause a symbol completion.
2220219019Sgabor     * Hence, this version of makeIntersectionType may not be called during a classfile read.
2221219019Sgabor     *
2222219019Sgabor     * @param bounds    the types from which the intersection type is formed
2223219019Sgabor     */
2224219019Sgabor    public IntersectionClassType makeIntersectionType(List<Type> bounds) {
2225219019Sgabor        return makeIntersectionType(bounds, bounds.head.tsym.isInterface());
2226219019Sgabor    }
2227219019Sgabor
2228219019Sgabor    /**
2229219019Sgabor     * Make an intersection type from non-empty list of types.  The list should be ordered according to
2230219019Sgabor     * {@link TypeSymbol#precedes(TypeSymbol, Types)}. This does not cause symbol completion as
2231219019Sgabor     * an extra parameter indicates as to whether all bounds are interfaces - in which case the
2232219019Sgabor     * supertype is implicitly assumed to be 'Object'.
2233219019Sgabor     *
2234219019Sgabor     * @param bounds        the types from which the intersection type is formed
2235219019Sgabor     * @param allInterfaces are all bounds interface types?
2236219019Sgabor     */
2237219019Sgabor    public IntersectionClassType makeIntersectionType(List<Type> bounds, boolean allInterfaces) {
2238219019Sgabor        Assert.check(bounds.nonEmpty());
2239219019Sgabor        Type firstExplicitBound = bounds.head;
2240219019Sgabor        if (allInterfaces) {
2241219019Sgabor            bounds = bounds.prepend(syms.objectType);
2242219019Sgabor        }
2243219019Sgabor        ClassSymbol bc =
2244219019Sgabor            new ClassSymbol(ABSTRACT|PUBLIC|SYNTHETIC|COMPOUND|ACYCLIC,
2245219019Sgabor                            Type.moreInfo
2246219019Sgabor                                ? names.fromString(bounds.toString())
2247219019Sgabor                                : names.empty,
2248219019Sgabor                            null,
2249219019Sgabor                            syms.noSymbol);
2250219019Sgabor        IntersectionClassType intersectionType = new IntersectionClassType(bounds, bc, allInterfaces);
2251219019Sgabor        bc.type = intersectionType;
2252219019Sgabor        bc.erasure_field = (bounds.head.hasTag(TYPEVAR)) ?
2253219019Sgabor                syms.objectType : // error condition, recover
2254219019Sgabor                erasure(firstExplicitBound);
2255219019Sgabor        bc.members_field = WriteableScope.create(bc);
2256219019Sgabor        return intersectionType;
2257219019Sgabor    }
2258219019Sgabor    // </editor-fold>
2259219019Sgabor
2260219019Sgabor    // <editor-fold defaultstate="collapsed" desc="supertype">
2261219019Sgabor    public Type supertype(Type t) {
2262219019Sgabor        return supertype.visit(t);
2263219019Sgabor    }
2264219019Sgabor    // where
2265219019Sgabor        private UnaryVisitor<Type> supertype = new UnaryVisitor<Type>() {
2266219019Sgabor
2267219019Sgabor            public Type visitType(Type t, Void ignored) {
2268219019Sgabor                // A note on wildcards: there is no good way to
2269219019Sgabor                // determine a supertype for a super bounded wildcard.
2270219019Sgabor                return Type.noType;
2271219019Sgabor            }
2272219019Sgabor
2273219019Sgabor            @Override
2274219019Sgabor            public Type visitClassType(ClassType t, Void ignored) {
2275219019Sgabor                if (t.supertype_field == null) {
2276219019Sgabor                    Type supertype = ((ClassSymbol)t.tsym).getSuperclass();
2277219019Sgabor                    // An interface has no superclass; its supertype is Object.
2278219019Sgabor                    if (t.isInterface())
2279219019Sgabor                        supertype = ((ClassType)t.tsym.type).supertype_field;
2280219019Sgabor                    if (t.supertype_field == null) {
2281219019Sgabor                        List<Type> actuals = classBound(t).allparams();
2282219019Sgabor                        List<Type> formals = t.tsym.type.allparams();
2283219019Sgabor                        if (t.hasErasedSupertypes()) {
2284219019Sgabor                            t.supertype_field = erasureRecursive(supertype);
2285219019Sgabor                        } else if (formals.nonEmpty()) {
2286219019Sgabor                            t.supertype_field = subst(supertype, formals, actuals);
2287219019Sgabor                        }
2288219019Sgabor                        else {
2289219019Sgabor                            t.supertype_field = supertype;
2290219019Sgabor                        }
2291219019Sgabor                    }
2292219019Sgabor                }
2293219019Sgabor                return t.supertype_field;
2294219019Sgabor            }
2295219019Sgabor
2296219019Sgabor            /**
2297219019Sgabor             * The supertype is always a class type. If the type
2298219019Sgabor             * variable's bounds start with a class type, this is also
2299219019Sgabor             * the supertype.  Otherwise, the supertype is
2300219019Sgabor             * java.lang.Object.
2301219019Sgabor             */
2302219019Sgabor            @Override
2303219019Sgabor            public Type visitTypeVar(TypeVar t, Void ignored) {
2304219019Sgabor                if (t.bound.hasTag(TYPEVAR) ||
2305219019Sgabor                    (!t.bound.isCompound() && !t.bound.isInterface())) {
2306219019Sgabor                    return t.bound;
2307219019Sgabor                } else {
2308219019Sgabor                    return supertype(t.bound);
2309219019Sgabor                }
2310219019Sgabor            }
2311219019Sgabor
2312219019Sgabor            @Override
2313219019Sgabor            public Type visitArrayType(ArrayType t, Void ignored) {
2314219019Sgabor                if (t.elemtype.isPrimitive() || isSameType(t.elemtype, syms.objectType))
2315219019Sgabor                    return arraySuperType();
2316219019Sgabor                else
2317219019Sgabor                    return new ArrayType(supertype(t.elemtype), t.tsym);
2318219019Sgabor            }
2319219019Sgabor
2320219019Sgabor            @Override
2321219019Sgabor            public Type visitErrorType(ErrorType t, Void ignored) {
2322219019Sgabor                return Type.noType;
2323219019Sgabor            }
2324219019Sgabor        };
2325219019Sgabor    // </editor-fold>
2326219019Sgabor
2327219019Sgabor    // <editor-fold defaultstate="collapsed" desc="interfaces">
2328219019Sgabor    /**
2329219019Sgabor     * Return the interfaces implemented by this class.
2330219019Sgabor     */
2331219019Sgabor    public List<Type> interfaces(Type t) {
2332219019Sgabor        return interfaces.visit(t);
2333219019Sgabor    }
2334219019Sgabor    // where
2335219019Sgabor        private UnaryVisitor<List<Type>> interfaces = new UnaryVisitor<List<Type>>() {
2336219019Sgabor
2337219019Sgabor            public List<Type> visitType(Type t, Void ignored) {
2338219019Sgabor                return List.nil();
2339219019Sgabor            }
2340219019Sgabor
2341219019Sgabor            @Override
2342219019Sgabor            public List<Type> visitClassType(ClassType t, Void ignored) {
2343219019Sgabor                if (t.interfaces_field == null) {
2344219019Sgabor                    List<Type> interfaces = ((ClassSymbol)t.tsym).getInterfaces();
2345219019Sgabor                    if (t.interfaces_field == null) {
2346219019Sgabor                        // If t.interfaces_field is null, then t must
2347219019Sgabor                        // be a parameterized type (not to be confused
2348219019Sgabor                        // with a generic type declaration).
2349219019Sgabor                        // Terminology:
2350219019Sgabor                        //    Parameterized type: List<String>
2351219019Sgabor                        //    Generic type declaration: class List<E> { ... }
2352219019Sgabor                        // So t corresponds to List<String> and
2353219019Sgabor                        // t.tsym.type corresponds to List<E>.
2354219019Sgabor                        // The reason t must be parameterized type is
2355219019Sgabor                        // that completion will happen as a side
2356219019Sgabor                        // effect of calling
2357219019Sgabor                        // ClassSymbol.getInterfaces.  Since
2358219019Sgabor                        // t.interfaces_field is null after
2359219019Sgabor                        // completion, we can assume that t is not the
2360219019Sgabor                        // type of a class/interface declaration.
2361219019Sgabor                        Assert.check(t != t.tsym.type, t);
2362219019Sgabor                        List<Type> actuals = t.allparams();
2363219019Sgabor                        List<Type> formals = t.tsym.type.allparams();
2364219019Sgabor                        if (t.hasErasedSupertypes()) {
2365219019Sgabor                            t.interfaces_field = erasureRecursive(interfaces);
2366219019Sgabor                        } else if (formals.nonEmpty()) {
2367219019Sgabor                            t.interfaces_field = subst(interfaces, formals, actuals);
2368219019Sgabor                        }
2369219019Sgabor                        else {
2370219019Sgabor                            t.interfaces_field = interfaces;
2371219019Sgabor                        }
2372219019Sgabor                    }
2373219019Sgabor                }
2374219019Sgabor                return t.interfaces_field;
2375219019Sgabor            }
2376219019Sgabor
2377219019Sgabor            @Override
2378219019Sgabor            public List<Type> visitTypeVar(TypeVar t, Void ignored) {
2379219019Sgabor                if (t.bound.isCompound())
2380219019Sgabor                    return interfaces(t.bound);
2381219019Sgabor
2382219019Sgabor                if (t.bound.isInterface())
2383219019Sgabor                    return List.of(t.bound);
2384219019Sgabor
2385219019Sgabor                return List.nil();
2386219019Sgabor            }
2387219019Sgabor        };
2388219019Sgabor
2389219019Sgabor    public List<Type> directSupertypes(Type t) {
2390219019Sgabor        return directSupertypes.visit(t);
2391219019Sgabor    }
2392219019Sgabor    // where
2393219019Sgabor        private final UnaryVisitor<List<Type>> directSupertypes = new UnaryVisitor<List<Type>>() {
2394219019Sgabor
2395219019Sgabor            public List<Type> visitType(final Type type, final Void ignored) {
2396219019Sgabor                if (!type.isIntersection()) {
2397219019Sgabor                    final Type sup = supertype(type);
2398219019Sgabor                    return (sup == Type.noType || sup == type || sup == null)
2399219019Sgabor                        ? interfaces(type)
2400219019Sgabor                        : interfaces(type).prepend(sup);
2401219019Sgabor                } else {
2402219019Sgabor                    return visitIntersectionType((IntersectionClassType) type);
2403219019Sgabor                }
2404219019Sgabor            }
2405219019Sgabor
2406219019Sgabor            private List<Type> visitIntersectionType(final IntersectionClassType it) {
2407219019Sgabor                return it.getExplicitComponents();
2408219019Sgabor            }
2409219019Sgabor
2410219019Sgabor        };
2411219019Sgabor
2412219019Sgabor    public boolean isDirectSuperInterface(TypeSymbol isym, TypeSymbol origin) {
2413219019Sgabor        for (Type i2 : interfaces(origin.type)) {
2414219019Sgabor            if (isym == i2.tsym) return true;
2415219019Sgabor        }
2416219019Sgabor        return false;
2417219019Sgabor    }
2418219019Sgabor    // </editor-fold>
2419219019Sgabor
2420219019Sgabor    // <editor-fold defaultstate="collapsed" desc="isDerivedRaw">
2421219019Sgabor    Map<Type,Boolean> isDerivedRawCache = new HashMap<>();
2422219019Sgabor
2423219019Sgabor    public boolean isDerivedRaw(Type t) {
2424219019Sgabor        Boolean result = isDerivedRawCache.get(t);
2425219019Sgabor        if (result == null) {
2426219019Sgabor            result = isDerivedRawInternal(t);
2427219019Sgabor            isDerivedRawCache.put(t, result);
2428219019Sgabor        }
2429219019Sgabor        return result;
2430219019Sgabor    }
2431219019Sgabor
2432219019Sgabor    public boolean isDerivedRawInternal(Type t) {
2433219019Sgabor        if (t.isErroneous())
2434219019Sgabor            return false;
2435219019Sgabor        return
2436219019Sgabor            t.isRaw() ||
2437219019Sgabor            supertype(t) != Type.noType && isDerivedRaw(supertype(t)) ||
2438219019Sgabor            isDerivedRaw(interfaces(t));
2439219019Sgabor    }
2440219019Sgabor
2441219019Sgabor    public boolean isDerivedRaw(List<Type> ts) {
2442219019Sgabor        List<Type> l = ts;
2443219019Sgabor        while (l.nonEmpty() && !isDerivedRaw(l.head)) l = l.tail;
2444219019Sgabor        return l.nonEmpty();
2445219019Sgabor    }
2446219019Sgabor    // </editor-fold>
2447219019Sgabor
2448219019Sgabor    // <editor-fold defaultstate="collapsed" desc="setBounds">
2449219019Sgabor    /**
2450219019Sgabor     * Same as {@link Types#setBounds(TypeVar, List, boolean)}, except that third parameter is computed directly,
2451219019Sgabor     * as follows: if all all bounds are interface types, the computed supertype is Object,otherwise
2452219019Sgabor     * the supertype is simply left null (in this case, the supertype is assumed to be the head of
2453219019Sgabor     * the bound list passed as second argument). Note that this check might cause a symbol completion.
2454219019Sgabor     * Hence, this version of setBounds may not be called during a classfile read.
2455219019Sgabor     *
2456219019Sgabor     * @param t         a type variable
2457219019Sgabor     * @param bounds    the bounds, must be nonempty
2458219019Sgabor     */
2459219019Sgabor    public void setBounds(TypeVar t, List<Type> bounds) {
2460219019Sgabor        setBounds(t, bounds, bounds.head.tsym.isInterface());
2461219019Sgabor    }
2462219019Sgabor
2463219019Sgabor    /**
2464219019Sgabor     * Set the bounds field of the given type variable to reflect a (possibly multiple) list of bounds.
2465219019Sgabor     * This does not cause symbol completion as an extra parameter indicates as to whether all bounds
2466219019Sgabor     * are interfaces - in which case the supertype is implicitly assumed to be 'Object'.
2467219019Sgabor     *
2468219019Sgabor     * @param t             a type variable
2469219019Sgabor     * @param bounds        the bounds, must be nonempty
2470219019Sgabor     * @param allInterfaces are all bounds interface types?
2471219019Sgabor     */
2472219019Sgabor    public void setBounds(TypeVar t, List<Type> bounds, boolean allInterfaces) {
2473219019Sgabor        t.bound = bounds.tail.isEmpty() ?
2474219019Sgabor                bounds.head :
2475219019Sgabor                makeIntersectionType(bounds, allInterfaces);
2476219019Sgabor        t.rank_field = -1;
2477219019Sgabor    }
2478219019Sgabor    // </editor-fold>
2479219019Sgabor
2480219019Sgabor    // <editor-fold defaultstate="collapsed" desc="getBounds">
2481219019Sgabor    /**
2482219019Sgabor     * Return list of bounds of the given type variable.
2483219019Sgabor     */
2484219019Sgabor    public List<Type> getBounds(TypeVar t) {
2485219019Sgabor        if (t.bound.hasTag(NONE))
2486219019Sgabor            return List.nil();
2487219019Sgabor        else if (t.bound.isErroneous() || !t.bound.isCompound())
2488219019Sgabor            return List.of(t.bound);
2489219019Sgabor        else if ((erasure(t).tsym.flags() & INTERFACE) == 0)
2490219019Sgabor            return interfaces(t).prepend(supertype(t));
2491219019Sgabor        else
2492219019Sgabor            // No superclass was given in bounds.
2493219019Sgabor            // In this case, supertype is Object, erasure is first interface.
2494219019Sgabor            return interfaces(t);
2495219019Sgabor    }
2496219019Sgabor    // </editor-fold>
2497219019Sgabor
2498219019Sgabor    // <editor-fold defaultstate="collapsed" desc="classBound">
2499219019Sgabor    /**
2500219019Sgabor     * If the given type is a (possibly selected) type variable,
2501219019Sgabor     * return the bounding class of this type, otherwise return the
2502219019Sgabor     * type itself.
2503219019Sgabor     */
2504219019Sgabor    public Type classBound(Type t) {
2505219019Sgabor        return classBound.visit(t);
2506219019Sgabor    }
2507219019Sgabor    // where
2508219019Sgabor        private UnaryVisitor<Type> classBound = new UnaryVisitor<Type>() {
2509219019Sgabor
2510219019Sgabor            public Type visitType(Type t, Void ignored) {
2511219019Sgabor                return t;
2512219019Sgabor            }
2513219019Sgabor
2514219019Sgabor            @Override
2515219019Sgabor            public Type visitClassType(ClassType t, Void ignored) {
2516219019Sgabor                Type outer1 = classBound(t.getEnclosingType());
2517219019Sgabor                if (outer1 != t.getEnclosingType())
2518219019Sgabor                    return new ClassType(outer1, t.getTypeArguments(), t.tsym,
2519219019Sgabor                                         t.getMetadata());
2520219019Sgabor                else
2521219019Sgabor                    return t;
2522219019Sgabor            }
2523219019Sgabor
2524219019Sgabor            @Override
2525219019Sgabor            public Type visitTypeVar(TypeVar t, Void ignored) {
2526219019Sgabor                return classBound(supertype(t));
2527219019Sgabor            }
2528219019Sgabor
2529219019Sgabor            @Override
2530219019Sgabor            public Type visitErrorType(ErrorType t, Void ignored) {
2531219019Sgabor                return t;
2532219019Sgabor            }
2533219019Sgabor        };
2534219019Sgabor    // </editor-fold>
2535219019Sgabor
2536219019Sgabor    // <editor-fold defaultstate="collapsed" desc="sub signature / override equivalence">
2537219019Sgabor    /**
2538219019Sgabor     * Returns true iff the first signature is a <em>sub
2539219019Sgabor     * signature</em> of the other.  This is <b>not</b> an equivalence
2540219019Sgabor     * relation.
2541219019Sgabor     *
2542219019Sgabor     * @jls section 8.4.2.
2543219019Sgabor     * @see #overrideEquivalent(Type t, Type s)
2544219019Sgabor     * @param t first signature (possibly raw).
2545219019Sgabor     * @param s second signature (could be subjected to erasure).
2546219019Sgabor     * @return true if t is a sub signature of s.
2547219019Sgabor     */
2548219019Sgabor    public boolean isSubSignature(Type t, Type s) {
2549219019Sgabor        return isSubSignature(t, s, true);
2550219019Sgabor    }
2551219019Sgabor
2552219019Sgabor    public boolean isSubSignature(Type t, Type s, boolean strict) {
2553219019Sgabor        return hasSameArgs(t, s, strict) || hasSameArgs(t, erasure(s), strict);
2554219019Sgabor    }
2555219019Sgabor
2556219019Sgabor    /**
2557219019Sgabor     * Returns true iff these signatures are related by <em>override
2558219019Sgabor     * equivalence</em>.  This is the natural extension of
2559219019Sgabor     * isSubSignature to an equivalence relation.
2560219019Sgabor     *
2561219019Sgabor     * @jls section 8.4.2.
2562219019Sgabor     * @see #isSubSignature(Type t, Type s)
2563219019Sgabor     * @param t a signature (possible raw, could be subjected to
2564219019Sgabor     * erasure).
2565219019Sgabor     * @param s a signature (possible raw, could be subjected to
2566219019Sgabor     * erasure).
2567219019Sgabor     * @return true if either argument is a sub signature of the other.
2568219019Sgabor     */
2569219019Sgabor    public boolean overrideEquivalent(Type t, Type s) {
2570219019Sgabor        return hasSameArgs(t, s) ||
2571219019Sgabor            hasSameArgs(t, erasure(s)) || hasSameArgs(erasure(t), s);
2572219019Sgabor    }
2573219019Sgabor
2574219019Sgabor    public boolean overridesObjectMethod(TypeSymbol origin, Symbol msym) {
2575219019Sgabor        for (Symbol sym : syms.objectType.tsym.members().getSymbolsByName(msym.name)) {
2576219019Sgabor            if (msym.overrides(sym, origin, Types.this, true)) {
2577219019Sgabor                return true;
2578219019Sgabor            }
2579219019Sgabor        }
2580219019Sgabor        return false;
2581219019Sgabor    }
2582219019Sgabor
2583219019Sgabor    // <editor-fold defaultstate="collapsed" desc="Determining method implementation in given site">
2584219019Sgabor    class ImplementationCache {
2585219019Sgabor
2586219019Sgabor        private WeakHashMap<MethodSymbol, SoftReference<Map<TypeSymbol, Entry>>> _map = new WeakHashMap<>();
2587219019Sgabor
2588219019Sgabor        class Entry {
2589219019Sgabor            final MethodSymbol cachedImpl;
2590219019Sgabor            final Filter<Symbol> implFilter;
2591219019Sgabor            final boolean checkResult;
2592219019Sgabor            final int prevMark;
2593219019Sgabor
2594219019Sgabor            public Entry(MethodSymbol cachedImpl,
2595219019Sgabor                    Filter<Symbol> scopeFilter,
2596219019Sgabor                    boolean checkResult,
2597219019Sgabor                    int prevMark) {
2598219019Sgabor                this.cachedImpl = cachedImpl;
2599219019Sgabor                this.implFilter = scopeFilter;
2600219019Sgabor                this.checkResult = checkResult;
2601219019Sgabor                this.prevMark = prevMark;
2602219019Sgabor            }
2603219019Sgabor
2604219019Sgabor            boolean matches(Filter<Symbol> scopeFilter, boolean checkResult, int mark) {
2605219019Sgabor                return this.implFilter == scopeFilter &&
2606219019Sgabor                        this.checkResult == checkResult &&
2607219019Sgabor                        this.prevMark == mark;
2608219019Sgabor            }
2609219019Sgabor        }
2610219019Sgabor
2611219019Sgabor        MethodSymbol get(MethodSymbol ms, TypeSymbol origin, boolean checkResult, Filter<Symbol> implFilter) {
2612219019Sgabor            SoftReference<Map<TypeSymbol, Entry>> ref_cache = _map.get(ms);
2613219019Sgabor            Map<TypeSymbol, Entry> cache = ref_cache != null ? ref_cache.get() : null;
2614219019Sgabor            if (cache == null) {
2615219019Sgabor                cache = new HashMap<>();
2616219019Sgabor                _map.put(ms, new SoftReference<>(cache));
2617219019Sgabor            }
2618219019Sgabor            Entry e = cache.get(origin);
2619219019Sgabor            CompoundScope members = membersClosure(origin.type, true);
2620219019Sgabor            if (e == null ||
2621219019Sgabor                    !e.matches(implFilter, checkResult, members.getMark())) {
2622219019Sgabor                MethodSymbol impl = implementationInternal(ms, origin, checkResult, implFilter);
2623219019Sgabor                cache.put(origin, new Entry(impl, implFilter, checkResult, members.getMark()));
2624219019Sgabor                return impl;
2625219019Sgabor            }
2626219019Sgabor            else {
2627219019Sgabor                return e.cachedImpl;
2628219019Sgabor            }
2629219019Sgabor        }
2630219019Sgabor
2631219019Sgabor        private MethodSymbol implementationInternal(MethodSymbol ms, TypeSymbol origin, boolean checkResult, Filter<Symbol> implFilter) {
2632219019Sgabor            for (Type t = origin.type; t.hasTag(CLASS) || t.hasTag(TYPEVAR); t = supertype(t)) {
2633219019Sgabor                t = skipTypeVars(t, false);
2634219019Sgabor                TypeSymbol c = t.tsym;
2635219019Sgabor                Symbol bestSoFar = null;
2636219019Sgabor                for (Symbol sym : c.members().getSymbolsByName(ms.name, implFilter)) {
2637219019Sgabor                    if (sym != null && sym.overrides(ms, origin, Types.this, checkResult)) {
2638219019Sgabor                        bestSoFar = sym;
2639219019Sgabor                        if ((sym.flags() & ABSTRACT) == 0) {
2640219019Sgabor                            //if concrete impl is found, exit immediately
2641219019Sgabor                            break;
2642219019Sgabor                        }
2643219019Sgabor                    }
2644219019Sgabor                }
2645219019Sgabor                if (bestSoFar != null) {
2646219019Sgabor                    //return either the (only) concrete implementation or the first abstract one
2647219019Sgabor                    return (MethodSymbol)bestSoFar;
2648219019Sgabor                }
2649219019Sgabor            }
2650219019Sgabor            return null;
2651219019Sgabor        }
2652219019Sgabor    }
2653219019Sgabor
2654219019Sgabor    private ImplementationCache implCache = new ImplementationCache();
2655219019Sgabor
2656219019Sgabor    public MethodSymbol implementation(MethodSymbol ms, TypeSymbol origin, boolean checkResult, Filter<Symbol> implFilter) {
2657219019Sgabor        return implCache.get(ms, origin, checkResult, implFilter);
2658219019Sgabor    }
2659219019Sgabor    // </editor-fold>
2660219019Sgabor
2661219019Sgabor    // <editor-fold defaultstate="collapsed" desc="compute transitive closure of all members in given site">
2662219019Sgabor    class MembersClosureCache extends SimpleVisitor<CompoundScope, Boolean> {
2663219019Sgabor
2664219019Sgabor        private WeakHashMap<TypeSymbol, Entry> _map = new WeakHashMap<>();
2665219019Sgabor
2666219019Sgabor        class Entry {
2667219019Sgabor            final boolean skipInterfaces;
2668219019Sgabor            final CompoundScope compoundScope;
2669219019Sgabor
2670219019Sgabor            public Entry(boolean skipInterfaces, CompoundScope compoundScope) {
2671219019Sgabor                this.skipInterfaces = skipInterfaces;
2672219019Sgabor                this.compoundScope = compoundScope;
2673219019Sgabor            }
2674219019Sgabor
2675219019Sgabor            boolean matches(boolean skipInterfaces) {
2676219019Sgabor                return this.skipInterfaces == skipInterfaces;
2677219019Sgabor            }
2678219019Sgabor        }
2679219019Sgabor
2680219019Sgabor        List<TypeSymbol> seenTypes = List.nil();
2681219019Sgabor
2682219019Sgabor        /** members closure visitor methods **/
2683219019Sgabor
2684219019Sgabor        public CompoundScope visitType(Type t, Boolean skipInterface) {
2685219019Sgabor            return null;
2686219019Sgabor        }
2687219019Sgabor
2688219019Sgabor        @Override
2689219019Sgabor        public CompoundScope visitClassType(ClassType t, Boolean skipInterface) {
2690219019Sgabor            if (seenTypes.contains(t.tsym)) {
2691219019Sgabor                //this is possible when an interface is implemented in multiple
2692219019Sgabor                //superclasses, or when a classs hierarchy is circular - in such
2693219019Sgabor                //cases we don't need to recurse (empty scope is returned)
2694219019Sgabor                return new CompoundScope(t.tsym);
2695219019Sgabor            }
2696219019Sgabor            try {
2697219019Sgabor                seenTypes = seenTypes.prepend(t.tsym);
2698219019Sgabor                ClassSymbol csym = (ClassSymbol)t.tsym;
2699219019Sgabor                Entry e = _map.get(csym);
2700219019Sgabor                if (e == null || !e.matches(skipInterface)) {
2701219019Sgabor                    CompoundScope membersClosure = new CompoundScope(csym);
2702219019Sgabor                    if (!skipInterface) {
2703219019Sgabor                        for (Type i : interfaces(t)) {
2704219019Sgabor                            membersClosure.prependSubScope(visit(i, skipInterface));
2705219019Sgabor                        }
2706219019Sgabor                    }
2707219019Sgabor                    membersClosure.prependSubScope(visit(supertype(t), skipInterface));
2708219019Sgabor                    membersClosure.prependSubScope(csym.members());
2709219019Sgabor                    e = new Entry(skipInterface, membersClosure);
2710219019Sgabor                    _map.put(csym, e);
2711219019Sgabor                }
2712219019Sgabor                return e.compoundScope;
2713219019Sgabor            }
2714219019Sgabor            finally {
2715219019Sgabor                seenTypes = seenTypes.tail;
2716219019Sgabor            }
2717219019Sgabor        }
2718219019Sgabor
2719219019Sgabor        @Override
2720219019Sgabor        public CompoundScope visitTypeVar(TypeVar t, Boolean skipInterface) {
2721219019Sgabor            return visit(t.getUpperBound(), skipInterface);
2722219019Sgabor        }
2723219019Sgabor    }
2724219019Sgabor
2725219019Sgabor    private MembersClosureCache membersCache = new MembersClosureCache();
2726219019Sgabor
2727219019Sgabor    public CompoundScope membersClosure(Type site, boolean skipInterface) {
2728219019Sgabor        return membersCache.visit(site, skipInterface);
2729219019Sgabor    }
2730219019Sgabor    // </editor-fold>
2731219019Sgabor
2732219019Sgabor
2733219019Sgabor    /** Return first abstract member of class `sym'.
2734219019Sgabor     */
2735219019Sgabor    public MethodSymbol firstUnimplementedAbstract(ClassSymbol sym) {
2736219019Sgabor        try {
2737219019Sgabor            return firstUnimplementedAbstractImpl(sym, sym);
2738219019Sgabor        } catch (CompletionFailure ex) {
2739219019Sgabor            chk.completionError(enter.getEnv(sym).tree.pos(), ex);
2740219019Sgabor            return null;
2741219019Sgabor        }
2742219019Sgabor    }
2743219019Sgabor        //where:
2744219019Sgabor        private MethodSymbol firstUnimplementedAbstractImpl(ClassSymbol impl, ClassSymbol c) {
2745219019Sgabor            MethodSymbol undef = null;
2746219019Sgabor            // Do not bother to search in classes that are not abstract,
2747219019Sgabor            // since they cannot have abstract members.
2748219019Sgabor            if (c == impl || (c.flags() & (ABSTRACT | INTERFACE)) != 0) {
2749219019Sgabor                Scope s = c.members();
2750219019Sgabor                for (Symbol sym : s.getSymbols(NON_RECURSIVE)) {
2751219019Sgabor                    if (sym.kind == MTH &&
2752219019Sgabor                        (sym.flags() & (ABSTRACT|IPROXY|DEFAULT)) == ABSTRACT) {
2753219019Sgabor                        MethodSymbol absmeth = (MethodSymbol)sym;
2754219019Sgabor                        MethodSymbol implmeth = absmeth.implementation(impl, this, true);
2755219019Sgabor                        if (implmeth == null || implmeth == absmeth) {
2756219019Sgabor                            //look for default implementations
2757219019Sgabor                            if (allowDefaultMethods) {
2758219019Sgabor                                MethodSymbol prov = interfaceCandidates(impl.type, absmeth).head;
2759219019Sgabor                                if (prov != null && prov.overrides(absmeth, impl, this, true)) {
2760219019Sgabor                                    implmeth = prov;
2761219019Sgabor                                }
2762219019Sgabor                            }
2763219019Sgabor                        }
2764219019Sgabor                        if (implmeth == null || implmeth == absmeth) {
2765219019Sgabor                            undef = absmeth;
2766219019Sgabor                            break;
2767219019Sgabor                        }
2768219019Sgabor                    }
2769219019Sgabor                }
2770219019Sgabor                if (undef == null) {
2771219019Sgabor                    Type st = supertype(c.type);
2772219019Sgabor                    if (st.hasTag(CLASS))
2773219019Sgabor                        undef = firstUnimplementedAbstractImpl(impl, (ClassSymbol)st.tsym);
2774219019Sgabor                }
2775219019Sgabor                for (List<Type> l = interfaces(c.type);
2776219019Sgabor                     undef == null && l.nonEmpty();
2777219019Sgabor                     l = l.tail) {
2778219019Sgabor                    undef = firstUnimplementedAbstractImpl(impl, (ClassSymbol)l.head.tsym);
2779219019Sgabor                }
2780219019Sgabor            }
2781219019Sgabor            return undef;
2782219019Sgabor        }
2783219019Sgabor
2784219019Sgabor
2785219019Sgabor    //where
2786219019Sgabor    public List<MethodSymbol> interfaceCandidates(Type site, MethodSymbol ms) {
2787219019Sgabor        Filter<Symbol> filter = new MethodFilter(ms, site);
2788219019Sgabor        List<MethodSymbol> candidates = List.nil();
2789219019Sgabor            for (Symbol s : membersClosure(site, false).getSymbols(filter)) {
2790219019Sgabor                if (!site.tsym.isInterface() && !s.owner.isInterface()) {
2791219019Sgabor                    return List.of((MethodSymbol)s);
2792219019Sgabor                } else if (!candidates.contains(s)) {
2793219019Sgabor                    candidates = candidates.prepend((MethodSymbol)s);
2794219019Sgabor                }
2795219019Sgabor            }
2796219019Sgabor            return prune(candidates);
2797219019Sgabor        }
2798219019Sgabor
2799219019Sgabor    public List<MethodSymbol> prune(List<MethodSymbol> methods) {
2800219019Sgabor        ListBuffer<MethodSymbol> methodsMin = new ListBuffer<>();
2801219019Sgabor        for (MethodSymbol m1 : methods) {
2802219019Sgabor            boolean isMin_m1 = true;
2803219019Sgabor            for (MethodSymbol m2 : methods) {
2804219019Sgabor                if (m1 == m2) continue;
2805219019Sgabor                if (m2.owner != m1.owner &&
2806219019Sgabor                        asSuper(m2.owner.type, m1.owner) != null) {
2807219019Sgabor                    isMin_m1 = false;
2808219019Sgabor                    break;
2809219019Sgabor                }
2810219019Sgabor            }
2811219019Sgabor            if (isMin_m1)
2812219019Sgabor                methodsMin.append(m1);
2813219019Sgabor        }
2814219019Sgabor        return methodsMin.toList();
2815219019Sgabor    }
2816219019Sgabor    // where
2817219019Sgabor            private class MethodFilter implements Filter<Symbol> {
2818219019Sgabor
2819219019Sgabor                Symbol msym;
2820219019Sgabor                Type site;
2821219019Sgabor
2822219019Sgabor                MethodFilter(Symbol msym, Type site) {
2823219019Sgabor                    this.msym = msym;
2824219019Sgabor                    this.site = site;
2825219019Sgabor                }
2826219019Sgabor
2827219019Sgabor                public boolean accepts(Symbol s) {
2828219019Sgabor                    return s.kind == MTH &&
2829219019Sgabor                            s.name == msym.name &&
2830219019Sgabor                            (s.flags() & SYNTHETIC) == 0 &&
2831219019Sgabor                            s.isInheritedIn(site.tsym, Types.this) &&
2832219019Sgabor                            overrideEquivalent(memberType(site, s), memberType(site, msym));
2833219019Sgabor                }
2834219019Sgabor            }
2835219019Sgabor    // </editor-fold>
2836219019Sgabor
2837219019Sgabor    /**
2838219019Sgabor     * Does t have the same arguments as s?  It is assumed that both
2839219019Sgabor     * types are (possibly polymorphic) method types.  Monomorphic
2840219019Sgabor     * method types "have the same arguments", if their argument lists
2841219019Sgabor     * are equal.  Polymorphic method types "have the same arguments",
2842219019Sgabor     * if they have the same arguments after renaming all type
2843219019Sgabor     * variables of one to corresponding type variables in the other,
2844219019Sgabor     * where correspondence is by position in the type parameter list.
2845219019Sgabor     */
2846219019Sgabor    public boolean hasSameArgs(Type t, Type s) {
2847219019Sgabor        return hasSameArgs(t, s, true);
2848219019Sgabor    }
2849219019Sgabor
2850219019Sgabor    public boolean hasSameArgs(Type t, Type s, boolean strict) {
2851219019Sgabor        return hasSameArgs(t, s, strict ? hasSameArgs_strict : hasSameArgs_nonstrict);
2852219019Sgabor    }
2853219019Sgabor
2854219019Sgabor    private boolean hasSameArgs(Type t, Type s, TypeRelation hasSameArgs) {
2855219019Sgabor        return hasSameArgs.visit(t, s);
2856219019Sgabor    }
2857219019Sgabor    // where
2858219019Sgabor        private class HasSameArgs extends TypeRelation {
2859219019Sgabor
2860219019Sgabor            boolean strict;
2861219019Sgabor
2862219019Sgabor            public HasSameArgs(boolean strict) {
2863219019Sgabor                this.strict = strict;
2864219019Sgabor            }
2865219019Sgabor
2866219019Sgabor            public Boolean visitType(Type t, Type s) {
2867219019Sgabor                throw new AssertionError();
2868219019Sgabor            }
2869219019Sgabor
2870219019Sgabor            @Override
2871219019Sgabor            public Boolean visitMethodType(MethodType t, Type s) {
2872219019Sgabor                return s.hasTag(METHOD)
2873219019Sgabor                    && containsTypeEquivalent(t.argtypes, s.getParameterTypes());
2874219019Sgabor            }
2875219019Sgabor
2876219019Sgabor            @Override
2877219019Sgabor            public Boolean visitForAll(ForAll t, Type s) {
2878219019Sgabor                if (!s.hasTag(FORALL))
2879219019Sgabor                    return strict ? false : visitMethodType(t.asMethodType(), s);
2880219019Sgabor
2881219019Sgabor                ForAll forAll = (ForAll)s;
2882219019Sgabor                return hasSameBounds(t, forAll)
2883219019Sgabor                    && visit(t.qtype, subst(forAll.qtype, forAll.tvars, t.tvars));
2884219019Sgabor            }
2885219019Sgabor
2886219019Sgabor            @Override
2887219019Sgabor            public Boolean visitErrorType(ErrorType t, Type s) {
2888219019Sgabor                return false;
2889219019Sgabor            }
2890219019Sgabor        }
2891219019Sgabor
2892219019Sgabor    TypeRelation hasSameArgs_strict = new HasSameArgs(true);
2893219019Sgabor        TypeRelation hasSameArgs_nonstrict = new HasSameArgs(false);
2894219019Sgabor
2895219019Sgabor    // </editor-fold>
2896219019Sgabor
2897219019Sgabor    // <editor-fold defaultstate="collapsed" desc="subst">
2898219019Sgabor    public List<Type> subst(List<Type> ts,
2899219019Sgabor                            List<Type> from,
2900219019Sgabor                            List<Type> to) {
2901219019Sgabor        return ts.map(new Subst(from, to));
2902219019Sgabor    }
2903219019Sgabor
2904219019Sgabor    /**
2905219019Sgabor     * Substitute all occurrences of a type in `from' with the
2906219019Sgabor     * corresponding type in `to' in 't'. Match lists `from' and `to'
2907219019Sgabor     * from the right: If lists have different length, discard leading
2908219019Sgabor     * elements of the longer list.
2909219019Sgabor     */
2910219019Sgabor    public Type subst(Type t, List<Type> from, List<Type> to) {
2911219019Sgabor        return t.map(new Subst(from, to));
2912219019Sgabor    }
2913219019Sgabor
2914219019Sgabor    private class Subst extends TypeMapping<Void> {
2915219019Sgabor        List<Type> from;
2916219019Sgabor        List<Type> to;
2917219019Sgabor
2918219019Sgabor        public Subst(List<Type> from, List<Type> to) {
2919219019Sgabor            int fromLength = from.length();
2920219019Sgabor            int toLength = to.length();
2921219019Sgabor            while (fromLength > toLength) {
2922219019Sgabor                fromLength--;
2923219019Sgabor                from = from.tail;
2924219019Sgabor            }
2925219019Sgabor            while (fromLength < toLength) {
2926219019Sgabor                toLength--;
2927219019Sgabor                to = to.tail;
2928219019Sgabor            }
2929219019Sgabor            this.from = from;
2930219019Sgabor            this.to = to;
2931219019Sgabor        }
2932219019Sgabor
2933219019Sgabor        @Override
2934219019Sgabor        public Type visitTypeVar(TypeVar t, Void ignored) {
2935219019Sgabor            for (List<Type> from = this.from, to = this.to;
2936219019Sgabor                 from.nonEmpty();
2937219019Sgabor                 from = from.tail, to = to.tail) {
2938219019Sgabor                if (t.equalsIgnoreMetadata(from.head)) {
2939219019Sgabor                    return to.head.withTypeVar(t);
2940219019Sgabor                }
2941219019Sgabor            }
2942219019Sgabor            return t;
2943219019Sgabor        }
2944219019Sgabor
2945219019Sgabor        @Override
2946219019Sgabor        public Type visitClassType(ClassType t, Void ignored) {
2947219019Sgabor            if (!t.isCompound()) {
2948219019Sgabor                return super.visitClassType(t, ignored);
2949219019Sgabor            } else {
2950219019Sgabor                Type st = visit(supertype(t));
2951219019Sgabor                List<Type> is = visit(interfaces(t), ignored);
2952219019Sgabor                if (st == supertype(t) && is == interfaces(t))
2953219019Sgabor                    return t;
2954219019Sgabor                else
2955219019Sgabor                    return makeIntersectionType(is.prepend(st));
2956219019Sgabor            }
2957219019Sgabor        }
2958219019Sgabor
2959219019Sgabor        @Override
2960219019Sgabor        public Type visitWildcardType(WildcardType t, Void ignored) {
2961219019Sgabor            WildcardType t2 = (WildcardType)super.visitWildcardType(t, ignored);
2962219019Sgabor            if (t2 != t && t.isExtendsBound() && t2.type.isExtendsBound()) {
2963219019Sgabor                t2.type = wildUpperBound(t2.type);
2964219019Sgabor            }
2965219019Sgabor            return t2;
2966219019Sgabor        }
2967219019Sgabor
2968219019Sgabor        @Override
2969219019Sgabor        public Type visitForAll(ForAll t, Void ignored) {
2970219019Sgabor            if (Type.containsAny(to, t.tvars)) {
2971219019Sgabor                //perform alpha-renaming of free-variables in 't'
2972219019Sgabor                //if 'to' types contain variables that are free in 't'
2973219019Sgabor                List<Type> freevars = newInstances(t.tvars);
2974219019Sgabor                t = new ForAll(freevars,
2975219019Sgabor                               Types.this.subst(t.qtype, t.tvars, freevars));
2976219019Sgabor            }
2977219019Sgabor            List<Type> tvars1 = substBounds(t.tvars, from, to);
2978219019Sgabor            Type qtype1 = visit(t.qtype);
2979219019Sgabor            if (tvars1 == t.tvars && qtype1 == t.qtype) {
2980219019Sgabor                return t;
2981219019Sgabor            } else if (tvars1 == t.tvars) {
2982219019Sgabor                return new ForAll(tvars1, qtype1) {
2983219019Sgabor                    @Override
2984219019Sgabor                    public boolean needsStripping() {
2985219019Sgabor                        return true;
2986219019Sgabor                    }
2987219019Sgabor                };
2988219019Sgabor            } else {
2989219019Sgabor                return new ForAll(tvars1, Types.this.subst(qtype1, t.tvars, tvars1)) {
2990219019Sgabor                    @Override
2991219019Sgabor                    public boolean needsStripping() {
2992219019Sgabor                        return true;
2993219019Sgabor                    }
2994219019Sgabor                };
2995219019Sgabor            }
2996219019Sgabor        }
2997219019Sgabor    }
2998219019Sgabor
2999219019Sgabor    public List<Type> substBounds(List<Type> tvars,
3000219019Sgabor                                  List<Type> from,
3001219019Sgabor                                  List<Type> to) {
3002219019Sgabor        if (tvars.isEmpty())
3003219019Sgabor            return tvars;
3004219019Sgabor        ListBuffer<Type> newBoundsBuf = new ListBuffer<>();
3005219019Sgabor        boolean changed = false;
3006219019Sgabor        // calculate new bounds
3007219019Sgabor        for (Type t : tvars) {
3008219019Sgabor            TypeVar tv = (TypeVar) t;
3009219019Sgabor            Type bound = subst(tv.bound, from, to);
3010219019Sgabor            if (bound != tv.bound)
3011219019Sgabor                changed = true;
3012219019Sgabor            newBoundsBuf.append(bound);
3013219019Sgabor        }
3014219019Sgabor        if (!changed)
3015219019Sgabor            return tvars;
3016219019Sgabor        ListBuffer<Type> newTvars = new ListBuffer<>();
3017219019Sgabor        // create new type variables without bounds
3018219019Sgabor        for (Type t : tvars) {
3019219019Sgabor            newTvars.append(new TypeVar(t.tsym, null, syms.botType,
3020219019Sgabor                                        t.getMetadata()));
3021219019Sgabor        }
3022219019Sgabor        // the new bounds should use the new type variables in place
3023219019Sgabor        // of the old
3024219019Sgabor        List<Type> newBounds = newBoundsBuf.toList();
3025219019Sgabor        from = tvars;
3026219019Sgabor        to = newTvars.toList();
3027219019Sgabor        for (; !newBounds.isEmpty(); newBounds = newBounds.tail) {
3028219019Sgabor            newBounds.head = subst(newBounds.head, from, to);
3029219019Sgabor        }
3030219019Sgabor        newBounds = newBoundsBuf.toList();
3031219019Sgabor        // set the bounds of new type variables to the new bounds
3032219019Sgabor        for (Type t : newTvars.toList()) {
3033219019Sgabor            TypeVar tv = (TypeVar) t;
3034219019Sgabor            tv.bound = newBounds.head;
3035219019Sgabor            newBounds = newBounds.tail;
3036219019Sgabor        }
3037219019Sgabor        return newTvars.toList();
3038219019Sgabor    }
3039219019Sgabor
3040219019Sgabor    public TypeVar substBound(TypeVar t, List<Type> from, List<Type> to) {
3041219019Sgabor        Type bound1 = subst(t.bound, from, to);
3042219019Sgabor        if (bound1 == t.bound)
3043219019Sgabor            return t;
3044219019Sgabor        else {
3045219019Sgabor            // create new type variable without bounds
3046219019Sgabor            TypeVar tv = new TypeVar(t.tsym, null, syms.botType,
3047219019Sgabor                                     t.getMetadata());
3048219019Sgabor            // the new bound should use the new type variable in place
3049219019Sgabor            // of the old
3050219019Sgabor            tv.bound = subst(bound1, List.<Type>of(t), List.<Type>of(tv));
3051219019Sgabor            return tv;
3052219019Sgabor        }
3053219019Sgabor    }
3054219019Sgabor    // </editor-fold>
3055219019Sgabor
3056219019Sgabor    // <editor-fold defaultstate="collapsed" desc="hasSameBounds">
3057219019Sgabor    /**
3058219019Sgabor     * Does t have the same bounds for quantified variables as s?
3059219019Sgabor     */
3060219019Sgabor    public boolean hasSameBounds(ForAll t, ForAll s) {
3061219019Sgabor        List<Type> l1 = t.tvars;
3062219019Sgabor        List<Type> l2 = s.tvars;
3063219019Sgabor        while (l1.nonEmpty() && l2.nonEmpty() &&
3064219019Sgabor               isSameType(l1.head.getUpperBound(),
3065219019Sgabor                          subst(l2.head.getUpperBound(),
3066219019Sgabor                                s.tvars,
3067219019Sgabor                                t.tvars))) {
3068219019Sgabor            l1 = l1.tail;
3069219019Sgabor            l2 = l2.tail;
3070219019Sgabor        }
3071219019Sgabor        return l1.isEmpty() && l2.isEmpty();
3072219019Sgabor    }
3073219019Sgabor    // </editor-fold>
3074219019Sgabor
3075219019Sgabor    // <editor-fold defaultstate="collapsed" desc="newInstances">
3076219019Sgabor    /** Create new vector of type variables from list of variables
3077219019Sgabor     *  changing all recursive bounds from old to new list.
3078219019Sgabor     */
3079219019Sgabor    public List<Type> newInstances(List<Type> tvars) {
3080219019Sgabor        List<Type> tvars1 = tvars.map(newInstanceFun);
3081219019Sgabor        for (List<Type> l = tvars1; l.nonEmpty(); l = l.tail) {
3082219019Sgabor            TypeVar tv = (TypeVar) l.head;
3083219019Sgabor            tv.bound = subst(tv.bound, tvars, tvars1);
3084219019Sgabor        }
3085219019Sgabor        return tvars1;
3086219019Sgabor    }
3087219019Sgabor        private static final TypeMapping<Void> newInstanceFun = new TypeMapping<Void>() {
3088219019Sgabor            @Override
3089219019Sgabor            public TypeVar visitTypeVar(TypeVar t, Void _unused) {
3090219019Sgabor                return new TypeVar(t.tsym, t.getUpperBound(), t.getLowerBound(), t.getMetadata());
3091219019Sgabor            }
3092219019Sgabor        };
3093219019Sgabor    // </editor-fold>
3094219019Sgabor
3095219019Sgabor    public Type createMethodTypeWithParameters(Type original, List<Type> newParams) {
3096219019Sgabor        return original.accept(methodWithParameters, newParams);
3097219019Sgabor    }
3098219019Sgabor    // where
3099219019Sgabor        private final MapVisitor<List<Type>> methodWithParameters = new MapVisitor<List<Type>>() {
3100219019Sgabor            public Type visitType(Type t, List<Type> newParams) {
3101219019Sgabor                throw new IllegalArgumentException("Not a method type: " + t);
3102219019Sgabor            }
3103219019Sgabor            public Type visitMethodType(MethodType t, List<Type> newParams) {
3104219019Sgabor                return new MethodType(newParams, t.restype, t.thrown, t.tsym);
3105219019Sgabor            }
3106219019Sgabor            public Type visitForAll(ForAll t, List<Type> newParams) {
3107219019Sgabor                return new ForAll(t.tvars, t.qtype.accept(this, newParams));
3108219019Sgabor            }
3109219019Sgabor        };
3110219019Sgabor
3111219019Sgabor    public Type createMethodTypeWithThrown(Type original, List<Type> newThrown) {
3112219019Sgabor        return original.accept(methodWithThrown, newThrown);
3113219019Sgabor    }
3114219019Sgabor    // where
3115219019Sgabor        private final MapVisitor<List<Type>> methodWithThrown = new MapVisitor<List<Type>>() {
3116219019Sgabor            public Type visitType(Type t, List<Type> newThrown) {
3117219019Sgabor                throw new IllegalArgumentException("Not a method type: " + t);
3118219019Sgabor            }
3119219019Sgabor            public Type visitMethodType(MethodType t, List<Type> newThrown) {
3120219019Sgabor                return new MethodType(t.argtypes, t.restype, newThrown, t.tsym);
3121219019Sgabor            }
3122219019Sgabor            public Type visitForAll(ForAll t, List<Type> newThrown) {
3123219019Sgabor                return new ForAll(t.tvars, t.qtype.accept(this, newThrown));
3124219019Sgabor            }
3125219019Sgabor        };
3126219019Sgabor
3127219019Sgabor    public Type createMethodTypeWithReturn(Type original, Type newReturn) {
3128219019Sgabor        return original.accept(methodWithReturn, newReturn);
3129219019Sgabor    }
3130219019Sgabor    // where
3131219019Sgabor        private final MapVisitor<Type> methodWithReturn = new MapVisitor<Type>() {
3132219019Sgabor            public Type visitType(Type t, Type newReturn) {
3133219019Sgabor                throw new IllegalArgumentException("Not a method type: " + t);
3134219019Sgabor            }
3135219019Sgabor            public Type visitMethodType(MethodType t, Type newReturn) {
3136219019Sgabor                return new MethodType(t.argtypes, newReturn, t.thrown, t.tsym);
3137219019Sgabor            }
3138219019Sgabor            public Type visitForAll(ForAll t, Type newReturn) {
3139219019Sgabor                return new ForAll(t.tvars, t.qtype.accept(this, newReturn));
3140219019Sgabor            }
3141219019Sgabor        };
3142219019Sgabor
3143219019Sgabor    // <editor-fold defaultstate="collapsed" desc="createErrorType">
3144219019Sgabor    public Type createErrorType(Type originalType) {
3145219019Sgabor        return new ErrorType(originalType, syms.errSymbol);
3146219019Sgabor    }
3147219019Sgabor
3148219019Sgabor    public Type createErrorType(ClassSymbol c, Type originalType) {
3149219019Sgabor        return new ErrorType(c, originalType);
3150219019Sgabor    }
3151219019Sgabor
3152219019Sgabor    public Type createErrorType(Name name, TypeSymbol container, Type originalType) {
3153219019Sgabor        return new ErrorType(name, container, originalType);
3154219019Sgabor    }
3155219019Sgabor    // </editor-fold>
3156219019Sgabor
3157219019Sgabor    // <editor-fold defaultstate="collapsed" desc="rank">
3158219019Sgabor    /**
3159219019Sgabor     * The rank of a class is the length of the longest path between
3160219019Sgabor     * the class and java.lang.Object in the class inheritance
3161219019Sgabor     * graph. Undefined for all but reference types.
3162219019Sgabor     */
3163219019Sgabor    public int rank(Type t) {
3164219019Sgabor        switch(t.getTag()) {
3165219019Sgabor        case CLASS: {
3166219019Sgabor            ClassType cls = (ClassType)t;
3167219019Sgabor            if (cls.rank_field < 0) {
3168219019Sgabor                Name fullname = cls.tsym.getQualifiedName();
3169219019Sgabor                if (fullname == names.java_lang_Object)
3170219019Sgabor                    cls.rank_field = 0;
3171219019Sgabor                else {
3172219019Sgabor                    int r = rank(supertype(cls));
3173219019Sgabor                    for (List<Type> l = interfaces(cls);
3174219019Sgabor                         l.nonEmpty();
3175219019Sgabor                         l = l.tail) {
3176219019Sgabor                        if (rank(l.head) > r)
3177219019Sgabor                            r = rank(l.head);
3178219019Sgabor                    }
3179219019Sgabor                    cls.rank_field = r + 1;
3180219019Sgabor                }
3181219019Sgabor            }
3182219019Sgabor            return cls.rank_field;
3183219019Sgabor        }
3184219019Sgabor        case TYPEVAR: {
3185219019Sgabor            TypeVar tvar = (TypeVar)t;
3186219019Sgabor            if (tvar.rank_field < 0) {
3187219019Sgabor                int r = rank(supertype(tvar));
3188219019Sgabor                for (List<Type> l = interfaces(tvar);
3189219019Sgabor                     l.nonEmpty();
3190219019Sgabor                     l = l.tail) {
3191219019Sgabor                    if (rank(l.head) > r) r = rank(l.head);
3192219019Sgabor                }
3193219019Sgabor                tvar.rank_field = r + 1;
3194219019Sgabor            }
3195219019Sgabor            return tvar.rank_field;
3196219019Sgabor        }
3197219019Sgabor        case ERROR:
3198219019Sgabor        case NONE:
3199219019Sgabor            return 0;
3200219019Sgabor        default:
3201219019Sgabor            throw new AssertionError();
3202219019Sgabor        }
3203219019Sgabor    }
3204219019Sgabor    // </editor-fold>
3205219019Sgabor
3206219019Sgabor    /**
3207219019Sgabor     * Helper method for generating a string representation of a given type
3208219019Sgabor     * accordingly to a given locale
3209219019Sgabor     */
3210219019Sgabor    public String toString(Type t, Locale locale) {
3211219019Sgabor        return Printer.createStandardPrinter(messages).visit(t, locale);
3212219019Sgabor    }
3213219019Sgabor
3214219019Sgabor    /**
3215219019Sgabor     * Helper method for generating a string representation of a given type
3216219019Sgabor     * accordingly to a given locale
3217219019Sgabor     */
3218219019Sgabor    public String toString(Symbol t, Locale locale) {
3219219019Sgabor        return Printer.createStandardPrinter(messages).visit(t, locale);
3220219019Sgabor    }
3221219019Sgabor
3222219019Sgabor    // <editor-fold defaultstate="collapsed" desc="toString">
3223219019Sgabor    /**
3224219019Sgabor     * This toString is slightly more descriptive than the one on Type.
3225219019Sgabor     *
3226219019Sgabor     * @deprecated Types.toString(Type t, Locale l) provides better support
3227219019Sgabor     * for localization
3228219019Sgabor     */
3229219019Sgabor    @Deprecated
3230219019Sgabor    public String toString(Type t) {
3231219019Sgabor        if (t.hasTag(FORALL)) {
3232219019Sgabor            ForAll forAll = (ForAll)t;
3233219019Sgabor            return typaramsString(forAll.tvars) + forAll.qtype;
3234219019Sgabor        }
3235219019Sgabor        return "" + t;
3236219019Sgabor    }
3237219019Sgabor    // where
3238219019Sgabor        private String typaramsString(List<Type> tvars) {
3239219019Sgabor            StringBuilder s = new StringBuilder();
3240219019Sgabor            s.append('<');
3241219019Sgabor            boolean first = true;
3242219019Sgabor            for (Type t : tvars) {
3243219019Sgabor                if (!first) s.append(", ");
3244219019Sgabor                first = false;
3245219019Sgabor                appendTyparamString(((TypeVar)t), s);
3246219019Sgabor            }
3247219019Sgabor            s.append('>');
3248219019Sgabor            return s.toString();
3249219019Sgabor        }
3250219019Sgabor        private void appendTyparamString(TypeVar t, StringBuilder buf) {
3251219019Sgabor            buf.append(t);
3252219019Sgabor            if (t.bound == null ||
3253219019Sgabor                t.bound.tsym.getQualifiedName() == names.java_lang_Object)
3254219019Sgabor                return;
3255219019Sgabor            buf.append(" extends "); // Java syntax; no need for i18n
3256219019Sgabor            Type bound = t.bound;
3257219019Sgabor            if (!bound.isCompound()) {
3258219019Sgabor                buf.append(bound);
3259219019Sgabor            } else if ((erasure(t).tsym.flags() & INTERFACE) == 0) {
3260219019Sgabor                buf.append(supertype(t));
3261219019Sgabor                for (Type intf : interfaces(t)) {
3262219019Sgabor                    buf.append('&');
3263219019Sgabor                    buf.append(intf);
3264219019Sgabor                }
3265219019Sgabor            } else {
3266219019Sgabor                // No superclass was given in bounds.
3267219019Sgabor                // In this case, supertype is Object, erasure is first interface.
3268219019Sgabor                boolean first = true;
3269219019Sgabor                for (Type intf : interfaces(t)) {
3270219019Sgabor                    if (!first) buf.append('&');
3271219019Sgabor                    first = false;
3272219019Sgabor                    buf.append(intf);
3273219019Sgabor                }
3274219019Sgabor            }
3275219019Sgabor        }
3276219019Sgabor    // </editor-fold>
3277219019Sgabor
3278219019Sgabor    // <editor-fold defaultstate="collapsed" desc="Determining least upper bounds of types">
3279219019Sgabor    /**
3280219019Sgabor     * A cache for closures.
3281219019Sgabor     *
3282219019Sgabor     * <p>A closure is a list of all the supertypes and interfaces of
3283219019Sgabor     * a class or interface type, ordered by ClassSymbol.precedes
3284219019Sgabor     * (that is, subclasses come first, arbitrary but fixed
3285219019Sgabor     * otherwise).
3286219019Sgabor     */
3287219019Sgabor    private Map<Type,List<Type>> closureCache = new HashMap<>();
3288219019Sgabor
3289219019Sgabor    /**
3290219019Sgabor     * Returns the closure of a class or interface type.
3291219019Sgabor     */
3292219019Sgabor    public List<Type> closure(Type t) {
3293219019Sgabor        List<Type> cl = closureCache.get(t);
3294219019Sgabor        if (cl == null) {
3295219019Sgabor            Type st = supertype(t);
3296219019Sgabor            if (!t.isCompound()) {
3297219019Sgabor                if (st.hasTag(CLASS)) {
3298219019Sgabor                    cl = insert(closure(st), t);
3299219019Sgabor                } else if (st.hasTag(TYPEVAR)) {
3300219019Sgabor                    cl = closure(st).prepend(t);
3301219019Sgabor                } else {
3302219019Sgabor                    cl = List.of(t);
3303219019Sgabor                }
3304219019Sgabor            } else {
3305219019Sgabor                cl = closure(supertype(t));
3306219019Sgabor            }
3307219019Sgabor            for (List<Type> l = interfaces(t); l.nonEmpty(); l = l.tail)
3308219019Sgabor                cl = union(cl, closure(l.head));
3309219019Sgabor            closureCache.put(t, cl);
3310219019Sgabor        }
3311219019Sgabor        return cl;
3312219019Sgabor    }
3313219019Sgabor
3314219019Sgabor    /**
3315219019Sgabor     * Collect types into a new closure (using a @code{ClosureHolder})
3316219019Sgabor     */
3317219019Sgabor    public Collector<Type, ClosureHolder, List<Type>> closureCollector(boolean minClosure, BiPredicate<Type, Type> shouldSkip) {
3318219019Sgabor        return Collector.of(() -> new ClosureHolder(minClosure, shouldSkip),
3319219019Sgabor                ClosureHolder::add,
3320219019Sgabor                ClosureHolder::merge,
3321219019Sgabor                ClosureHolder::closure);
3322219019Sgabor    }
3323219019Sgabor    //where
3324219019Sgabor        class ClosureHolder {
3325219019Sgabor            List<Type> closure;
3326219019Sgabor            final boolean minClosure;
3327219019Sgabor            final BiPredicate<Type, Type> shouldSkip;
3328219019Sgabor
3329219019Sgabor            ClosureHolder(boolean minClosure, BiPredicate<Type, Type> shouldSkip) {
3330219019Sgabor                this.closure = List.nil();
3331219019Sgabor                this.minClosure = minClosure;
3332219019Sgabor                this.shouldSkip = shouldSkip;
3333219019Sgabor            }
3334219019Sgabor
3335219019Sgabor            void add(Type type) {
3336219019Sgabor                closure = insert(closure, type, shouldSkip);
3337219019Sgabor            }
3338219019Sgabor
3339219019Sgabor            ClosureHolder merge(ClosureHolder other) {
3340219019Sgabor                closure = union(closure, other.closure, shouldSkip);
3341219019Sgabor                return this;
3342219019Sgabor            }
3343219019Sgabor
3344219019Sgabor            List<Type> closure() {
3345219019Sgabor                return minClosure ? closureMin(closure) : closure;
3346219019Sgabor            }
3347219019Sgabor        }
3348219019Sgabor
3349219019Sgabor    BiPredicate<Type, Type> basicClosureSkip = (t1, t2) -> t1.tsym == t2.tsym;
3350219019Sgabor
3351219019Sgabor    /**
3352219019Sgabor     * Insert a type in a closure
3353219019Sgabor     */
3354219019Sgabor    public List<Type> insert(List<Type> cl, Type t, BiPredicate<Type, Type> shouldSkip) {
3355219019Sgabor        if (cl.isEmpty()) {
3356219019Sgabor            return cl.prepend(t);
3357219019Sgabor        } else if (shouldSkip.test(t, cl.head)) {
3358219019Sgabor            return cl;
3359219019Sgabor        } else if (t.tsym.precedes(cl.head.tsym, this)) {
3360219019Sgabor            return cl.prepend(t);
3361219019Sgabor        } else {
3362219019Sgabor            // t comes after head, or the two are unrelated
3363219019Sgabor            return insert(cl.tail, t, shouldSkip).prepend(cl.head);
3364219019Sgabor        }
3365219019Sgabor    }
3366219019Sgabor
3367219019Sgabor    public List<Type> insert(List<Type> cl, Type t) {
3368219019Sgabor        return insert(cl, t, basicClosureSkip);
3369219019Sgabor    }
3370219019Sgabor
3371219019Sgabor    /**
3372219019Sgabor     * Form the union of two closures
3373219019Sgabor     */
3374219019Sgabor    public List<Type> union(List<Type> cl1, List<Type> cl2, BiPredicate<Type, Type> shouldSkip) {
3375219019Sgabor        if (cl1.isEmpty()) {
3376219019Sgabor            return cl2;
3377219019Sgabor        } else if (cl2.isEmpty()) {
3378219019Sgabor            return cl1;
3379219019Sgabor        } else if (shouldSkip.test(cl1.head, cl2.head)) {
3380219019Sgabor            return union(cl1.tail, cl2.tail, shouldSkip).prepend(cl1.head);
3381219019Sgabor        } else if (cl1.head.tsym.precedes(cl2.head.tsym, this)) {
3382219019Sgabor            return union(cl1.tail, cl2, shouldSkip).prepend(cl1.head);
3383219019Sgabor        } else if (cl2.head.tsym.precedes(cl1.head.tsym, this)) {
3384219019Sgabor            return union(cl1, cl2.tail, shouldSkip).prepend(cl2.head);
3385219019Sgabor        } else {
3386219019Sgabor            // unrelated types
3387219019Sgabor            return union(cl1.tail, cl2, shouldSkip).prepend(cl1.head);
3388219019Sgabor        }
3389219019Sgabor    }
3390219019Sgabor
3391219019Sgabor    public List<Type> union(List<Type> cl1, List<Type> cl2) {
3392219019Sgabor        return union(cl1, cl2, basicClosureSkip);
3393219019Sgabor    }
3394219019Sgabor
3395219019Sgabor    /**
3396219019Sgabor     * Intersect two closures
3397219019Sgabor     */
3398219019Sgabor    public List<Type> intersect(List<Type> cl1, List<Type> cl2) {
3399219019Sgabor        if (cl1 == cl2)
3400219019Sgabor            return cl1;
3401219019Sgabor        if (cl1.isEmpty() || cl2.isEmpty())
3402219019Sgabor            return List.nil();
3403219019Sgabor        if (cl1.head.tsym.precedes(cl2.head.tsym, this))
3404219019Sgabor            return intersect(cl1.tail, cl2);
3405219019Sgabor        if (cl2.head.tsym.precedes(cl1.head.tsym, this))
3406219019Sgabor            return intersect(cl1, cl2.tail);
3407219019Sgabor        if (isSameType(cl1.head, cl2.head))
3408219019Sgabor            return intersect(cl1.tail, cl2.tail).prepend(cl1.head);
3409219019Sgabor        if (cl1.head.tsym == cl2.head.tsym &&
3410219019Sgabor            cl1.head.hasTag(CLASS) && cl2.head.hasTag(CLASS)) {
3411219019Sgabor            if (cl1.head.isParameterized() && cl2.head.isParameterized()) {
3412219019Sgabor                Type merge = merge(cl1.head,cl2.head);
3413219019Sgabor                return intersect(cl1.tail, cl2.tail).prepend(merge);
3414219019Sgabor            }
3415219019Sgabor            if (cl1.head.isRaw() || cl2.head.isRaw())
3416219019Sgabor                return intersect(cl1.tail, cl2.tail).prepend(erasure(cl1.head));
3417219019Sgabor        }
3418219019Sgabor        return intersect(cl1.tail, cl2.tail);
3419219019Sgabor    }
3420219019Sgabor    // where
3421219019Sgabor        class TypePair {
3422219019Sgabor            final Type t1;
3423219019Sgabor            final Type t2;
3424219019Sgabor            boolean strict;
3425219019Sgabor
3426219019Sgabor            TypePair(Type t1, Type t2) {
3427219019Sgabor                this(t1, t2, false);
3428219019Sgabor            }
3429219019Sgabor
3430219019Sgabor            TypePair(Type t1, Type t2, boolean strict) {
3431219019Sgabor                this.t1 = t1;
3432219019Sgabor                this.t2 = t2;
3433219019Sgabor                this.strict = strict;
3434219019Sgabor            }
3435219019Sgabor            @Override
3436219019Sgabor            public int hashCode() {
3437219019Sgabor                return 127 * Types.this.hashCode(t1) + Types.this.hashCode(t2);
3438219019Sgabor            }
3439219019Sgabor            @Override
3440219019Sgabor            public boolean equals(Object obj) {
3441219019Sgabor                if (!(obj instanceof TypePair))
3442219019Sgabor                    return false;
3443219019Sgabor                TypePair typePair = (TypePair)obj;
3444219019Sgabor                return isSameType(t1, typePair.t1, strict)
3445219019Sgabor                    && isSameType(t2, typePair.t2, strict);
3446219019Sgabor            }
3447219019Sgabor        }
3448219019Sgabor        Set<TypePair> mergeCache = new HashSet<>();
3449219019Sgabor        private Type merge(Type c1, Type c2) {
3450219019Sgabor            ClassType class1 = (ClassType) c1;
3451219019Sgabor            List<Type> act1 = class1.getTypeArguments();
3452219019Sgabor            ClassType class2 = (ClassType) c2;
3453219019Sgabor            List<Type> act2 = class2.getTypeArguments();
3454219019Sgabor            ListBuffer<Type> merged = new ListBuffer<>();
3455219019Sgabor            List<Type> typarams = class1.tsym.type.getTypeArguments();
3456219019Sgabor
3457219019Sgabor            while (act1.nonEmpty() && act2.nonEmpty() && typarams.nonEmpty()) {
3458219019Sgabor                if (containsType(act1.head, act2.head)) {
3459219019Sgabor                    merged.append(act1.head);
3460219019Sgabor                } else if (containsType(act2.head, act1.head)) {
3461219019Sgabor                    merged.append(act2.head);
3462219019Sgabor                } else {
3463219019Sgabor                    TypePair pair = new TypePair(c1, c2);
3464219019Sgabor                    Type m;
3465219019Sgabor                    if (mergeCache.add(pair)) {
3466219019Sgabor                        m = new WildcardType(lub(wildUpperBound(act1.head),
3467219019Sgabor                                                 wildUpperBound(act2.head)),
3468219019Sgabor                                             BoundKind.EXTENDS,
3469219019Sgabor                                             syms.boundClass);
3470219019Sgabor                        mergeCache.remove(pair);
3471219019Sgabor                    } else {
3472219019Sgabor                        m = new WildcardType(syms.objectType,
3473219019Sgabor                                             BoundKind.UNBOUND,
3474219019Sgabor                                             syms.boundClass);
3475219019Sgabor                    }
3476219019Sgabor                    merged.append(m.withTypeVar(typarams.head));
3477219019Sgabor                }
3478219019Sgabor                act1 = act1.tail;
3479219019Sgabor                act2 = act2.tail;
3480219019Sgabor                typarams = typarams.tail;
3481219019Sgabor            }
3482219019Sgabor            Assert.check(act1.isEmpty() && act2.isEmpty() && typarams.isEmpty());
3483219019Sgabor            // There is no spec detailing how type annotations are to
3484219019Sgabor            // be inherited.  So set it to noAnnotations for now
3485219019Sgabor            return new ClassType(class1.getEnclosingType(), merged.toList(),
3486219019Sgabor                                 class1.tsym);
3487219019Sgabor        }
3488219019Sgabor
3489219019Sgabor    /**
3490219019Sgabor     * Return the minimum type of a closure, a compound type if no
3491219019Sgabor     * unique minimum exists.
3492219019Sgabor     */
3493219019Sgabor    private Type compoundMin(List<Type> cl) {
3494219019Sgabor        if (cl.isEmpty()) return syms.objectType;
3495219019Sgabor        List<Type> compound = closureMin(cl);
3496219019Sgabor        if (compound.isEmpty())
3497219019Sgabor            return null;
3498219019Sgabor        else if (compound.tail.isEmpty())
3499219019Sgabor            return compound.head;
3500219019Sgabor        else
3501219019Sgabor            return makeIntersectionType(compound);
3502219019Sgabor    }
3503219019Sgabor
3504219019Sgabor    /**
3505219019Sgabor     * Return the minimum types of a closure, suitable for computing
3506219019Sgabor     * compoundMin or glb.
3507219019Sgabor     */
3508219019Sgabor    private List<Type> closureMin(List<Type> cl) {
3509219019Sgabor        ListBuffer<Type> classes = new ListBuffer<>();
3510219019Sgabor        ListBuffer<Type> interfaces = new ListBuffer<>();
3511219019Sgabor        Set<Type> toSkip = new HashSet<>();
3512219019Sgabor        while (!cl.isEmpty()) {
3513219019Sgabor            Type current = cl.head;
3514219019Sgabor            boolean keep = !toSkip.contains(current);
3515219019Sgabor            if (keep && current.hasTag(TYPEVAR)) {
3516219019Sgabor                // skip lower-bounded variables with a subtype in cl.tail
3517219019Sgabor                for (Type t : cl.tail) {
3518219019Sgabor                    if (isSubtypeNoCapture(t, current)) {
3519219019Sgabor                        keep = false;
3520219019Sgabor                        break;
3521219019Sgabor                    }
3522219019Sgabor                }
3523219019Sgabor            }
3524219019Sgabor            if (keep) {
3525219019Sgabor                if (current.isInterface())
3526219019Sgabor                    interfaces.append(current);
3527219019Sgabor                else
3528219019Sgabor                    classes.append(current);
3529219019Sgabor                for (Type t : cl.tail) {
3530219019Sgabor                    // skip supertypes of 'current' in cl.tail
3531219019Sgabor                    if (isSubtypeNoCapture(current, t))
3532219019Sgabor                        toSkip.add(t);
3533219019Sgabor                }
3534219019Sgabor            }
3535219019Sgabor            cl = cl.tail;
3536219019Sgabor        }
3537219019Sgabor        return classes.appendList(interfaces).toList();
3538219019Sgabor    }
3539219019Sgabor
3540219019Sgabor    /**
3541219019Sgabor     * Return the least upper bound of list of types.  if the lub does
3542219019Sgabor     * not exist return null.
3543219019Sgabor     */
3544219019Sgabor    public Type lub(List<Type> ts) {
3545219019Sgabor        return lub(ts.toArray(new Type[ts.length()]));
3546219019Sgabor    }
3547219019Sgabor
3548219019Sgabor    /**
3549219019Sgabor     * Return the least upper bound (lub) of set of types.  If the lub
3550219019Sgabor     * does not exist return the type of null (bottom).
3551219019Sgabor     */
3552219019Sgabor    public Type lub(Type... ts) {
3553219019Sgabor        final int UNKNOWN_BOUND = 0;
3554219019Sgabor        final int ARRAY_BOUND = 1;
3555219019Sgabor        final int CLASS_BOUND = 2;
3556219019Sgabor
3557219019Sgabor        int[] kinds = new int[ts.length];
3558219019Sgabor
3559219019Sgabor        int boundkind = UNKNOWN_BOUND;
3560219019Sgabor        for (int i = 0 ; i < ts.length ; i++) {
3561219019Sgabor            Type t = ts[i];
3562219019Sgabor            switch (t.getTag()) {
3563219019Sgabor            case CLASS:
3564219019Sgabor                boundkind |= kinds[i] = CLASS_BOUND;
3565219019Sgabor                break;
3566219019Sgabor            case ARRAY:
3567219019Sgabor                boundkind |= kinds[i] = ARRAY_BOUND;
3568219019Sgabor                break;
3569219019Sgabor            case  TYPEVAR:
3570219019Sgabor                do {
3571219019Sgabor                    t = t.getUpperBound();
3572219019Sgabor                } while (t.hasTag(TYPEVAR));
3573219019Sgabor                if (t.hasTag(ARRAY)) {
3574219019Sgabor                    boundkind |= kinds[i] = ARRAY_BOUND;
3575219019Sgabor                } else {
3576219019Sgabor                    boundkind |= kinds[i] = CLASS_BOUND;
3577219019Sgabor                }
3578219019Sgabor                break;
3579219019Sgabor            default:
3580219019Sgabor                kinds[i] = UNKNOWN_BOUND;
3581219019Sgabor                if (t.isPrimitive())
3582219019Sgabor                    return syms.errType;
3583219019Sgabor            }
3584219019Sgabor        }
3585219019Sgabor        switch (boundkind) {
3586219019Sgabor        case 0:
3587219019Sgabor            return syms.botType;
3588219019Sgabor
3589219019Sgabor        case ARRAY_BOUND:
3590219019Sgabor            // calculate lub(A[], B[])
3591219019Sgabor            Type[] elements = new Type[ts.length];
3592219019Sgabor            for (int i = 0 ; i < ts.length ; i++) {
3593219019Sgabor                Type elem = elements[i] = elemTypeFun.apply(ts[i]);
3594219019Sgabor                if (elem.isPrimitive()) {
3595219019Sgabor                    // if a primitive type is found, then return
3596219019Sgabor                    // arraySuperType unless all the types are the
3597219019Sgabor                    // same
3598219019Sgabor                    Type first = ts[0];
3599219019Sgabor                    for (int j = 1 ; j < ts.length ; j++) {
3600219019Sgabor                        if (!isSameType(first, ts[j])) {
3601219019Sgabor                             // lub(int[], B[]) is Cloneable & Serializable
3602219019Sgabor                            return arraySuperType();
3603219019Sgabor                        }
3604219019Sgabor                    }
3605219019Sgabor                    // all the array types are the same, return one
3606219019Sgabor                    // lub(int[], int[]) is int[]
3607219019Sgabor                    return first;
3608219019Sgabor                }
3609219019Sgabor            }
3610219019Sgabor            // lub(A[], B[]) is lub(A, B)[]
3611219019Sgabor            return new ArrayType(lub(elements), syms.arrayClass);
3612219019Sgabor
3613219019Sgabor        case CLASS_BOUND:
3614219019Sgabor            // calculate lub(A, B)
3615219019Sgabor            int startIdx = 0;
3616219019Sgabor            for (int i = 0; i < ts.length ; i++) {
3617219019Sgabor                Type t = ts[i];
3618219019Sgabor                if (t.hasTag(CLASS) || t.hasTag(TYPEVAR)) {
3619219019Sgabor                    break;
3620219019Sgabor                } else {
3621219019Sgabor                    startIdx++;
3622219019Sgabor                }
3623219019Sgabor            }
3624219019Sgabor            Assert.check(startIdx < ts.length);
3625219019Sgabor            //step 1 - compute erased candidate set (EC)
3626219019Sgabor            List<Type> cl = erasedSupertypes(ts[startIdx]);
3627219019Sgabor            for (int i = startIdx + 1 ; i < ts.length ; i++) {
3628219019Sgabor                Type t = ts[i];
3629219019Sgabor                if (t.hasTag(CLASS) || t.hasTag(TYPEVAR))
3630219019Sgabor                    cl = intersect(cl, erasedSupertypes(t));
3631219019Sgabor            }
3632219019Sgabor            //step 2 - compute minimal erased candidate set (MEC)
3633219019Sgabor            List<Type> mec = closureMin(cl);
3634219019Sgabor            //step 3 - for each element G in MEC, compute lci(Inv(G))
3635219019Sgabor            List<Type> candidates = List.nil();
3636219019Sgabor            for (Type erasedSupertype : mec) {
3637219019Sgabor                List<Type> lci = List.of(asSuper(ts[startIdx], erasedSupertype.tsym));
3638219019Sgabor                for (int i = startIdx + 1 ; i < ts.length ; i++) {
3639219019Sgabor                    Type superType = asSuper(ts[i], erasedSupertype.tsym);
3640219019Sgabor                    lci = intersect(lci, superType != null ? List.of(superType) : List.<Type>nil());
3641219019Sgabor                }
3642219019Sgabor                candidates = candidates.appendList(lci);
3643219019Sgabor            }
3644219019Sgabor            //step 4 - let MEC be { G1, G2 ... Gn }, then we have that
3645219019Sgabor            //lub = lci(Inv(G1)) & lci(Inv(G2)) & ... & lci(Inv(Gn))
3646219019Sgabor            return compoundMin(candidates);
3647219019Sgabor
3648219019Sgabor        default:
3649219019Sgabor            // calculate lub(A, B[])
3650219019Sgabor            List<Type> classes = List.of(arraySuperType());
3651219019Sgabor            for (int i = 0 ; i < ts.length ; i++) {
3652219019Sgabor                if (kinds[i] != ARRAY_BOUND) // Filter out any arrays
3653219019Sgabor                    classes = classes.prepend(ts[i]);
3654219019Sgabor            }
3655219019Sgabor            // lub(A, B[]) is lub(A, arraySuperType)
3656219019Sgabor            return lub(classes);
3657219019Sgabor        }
3658219019Sgabor    }
3659219019Sgabor    // where
3660219019Sgabor        List<Type> erasedSupertypes(Type t) {
3661219019Sgabor            ListBuffer<Type> buf = new ListBuffer<>();
3662219019Sgabor            for (Type sup : closure(t)) {
3663219019Sgabor                if (sup.hasTag(TYPEVAR)) {
3664219019Sgabor                    buf.append(sup);
3665219019Sgabor                } else {
3666219019Sgabor                    buf.append(erasure(sup));
3667219019Sgabor                }
3668219019Sgabor            }
3669219019Sgabor            return buf.toList();
3670219019Sgabor        }
3671219019Sgabor
3672219019Sgabor        private Type arraySuperType = null;
3673219019Sgabor        private Type arraySuperType() {
3674219019Sgabor            // initialized lazily to avoid problems during compiler startup
3675219019Sgabor            if (arraySuperType == null) {
3676219019Sgabor                synchronized (this) {
3677219019Sgabor                    if (arraySuperType == null) {
3678219019Sgabor                        // JLS 10.8: all arrays implement Cloneable and Serializable.
3679219019Sgabor                        arraySuperType = makeIntersectionType(List.of(syms.serializableType,
3680219019Sgabor                                syms.cloneableType), true);
3681219019Sgabor                    }
3682219019Sgabor                }
3683219019Sgabor            }
3684219019Sgabor            return arraySuperType;
3685219019Sgabor        }
3686219019Sgabor    // </editor-fold>
3687219019Sgabor
3688219019Sgabor    // <editor-fold defaultstate="collapsed" desc="Greatest lower bound">
3689219019Sgabor    public Type glb(List<Type> ts) {
3690219019Sgabor        Type t1 = ts.head;
3691219019Sgabor        for (Type t2 : ts.tail) {
3692219019Sgabor            if (t1.isErroneous())
3693219019Sgabor                return t1;
3694219019Sgabor            t1 = glb(t1, t2);
3695219019Sgabor        }
3696219019Sgabor        return t1;
3697219019Sgabor    }
3698219019Sgabor    //where
3699219019Sgabor    public Type glb(Type t, Type s) {
3700219019Sgabor        if (s == null)
3701219019Sgabor            return t;
3702219019Sgabor        else if (t.isPrimitive() || s.isPrimitive())
3703219019Sgabor            return syms.errType;
3704219019Sgabor        else if (isSubtypeNoCapture(t, s))
3705219019Sgabor            return t;
3706219019Sgabor        else if (isSubtypeNoCapture(s, t))
3707219019Sgabor            return s;
3708219019Sgabor
3709219019Sgabor        List<Type> closure = union(closure(t), closure(s));
3710219019Sgabor        return glbFlattened(closure, t);
3711219019Sgabor    }
3712219019Sgabor    //where
3713219019Sgabor    /**
3714219019Sgabor     * Perform glb for a list of non-primitive, non-error, non-compound types;
3715219019Sgabor     * redundant elements are removed.  Bounds should be ordered according to
3716219019Sgabor     * {@link Symbol#precedes(TypeSymbol,Types)}.
3717219019Sgabor     *
3718219019Sgabor     * @param flatBounds List of type to glb
3719219019Sgabor     * @param errT Original type to use if the result is an error type
3720219019Sgabor     */
3721219019Sgabor    private Type glbFlattened(List<Type> flatBounds, Type errT) {
3722219019Sgabor        List<Type> bounds = closureMin(flatBounds);
3723219019Sgabor
3724219019Sgabor        if (bounds.isEmpty()) {             // length == 0
3725219019Sgabor            return syms.objectType;
3726219019Sgabor        } else if (bounds.tail.isEmpty()) { // length == 1
3727219019Sgabor            return bounds.head;
3728219019Sgabor        } else {                            // length > 1
3729219019Sgabor            int classCount = 0;
3730219019Sgabor            List<Type> lowers = List.nil();
3731219019Sgabor            for (Type bound : bounds) {
3732219019Sgabor                if (!bound.isInterface()) {
3733219019Sgabor                    classCount++;
3734219019Sgabor                    Type lower = cvarLowerBound(bound);
3735219019Sgabor                    if (bound != lower && !lower.hasTag(BOT))
3736219019Sgabor                        lowers = insert(lowers, lower);
3737219019Sgabor                }
3738219019Sgabor            }
3739219019Sgabor            if (classCount > 1) {
3740219019Sgabor                if (lowers.isEmpty())
3741219019Sgabor                    return createErrorType(errT);
3742219019Sgabor                else
3743219019Sgabor                    return glbFlattened(union(bounds, lowers), errT);
3744219019Sgabor            }
3745219019Sgabor        }
3746219019Sgabor        return makeIntersectionType(bounds);
3747219019Sgabor    }
3748219019Sgabor    // </editor-fold>
3749219019Sgabor
3750219019Sgabor    // <editor-fold defaultstate="collapsed" desc="hashCode">
3751219019Sgabor    /**
3752219019Sgabor     * Compute a hash code on a type.
3753219019Sgabor     */
3754219019Sgabor    public int hashCode(Type t) {
3755219019Sgabor        return hashCode.visit(t);
3756219019Sgabor    }
3757219019Sgabor    // where
3758219019Sgabor        private static final UnaryVisitor<Integer> hashCode = new UnaryVisitor<Integer>() {
3759219019Sgabor
3760219019Sgabor            public Integer visitType(Type t, Void ignored) {
3761219019Sgabor                return t.getTag().ordinal();
3762219019Sgabor            }
3763219019Sgabor
3764219019Sgabor            @Override
3765219019Sgabor            public Integer visitClassType(ClassType t, Void ignored) {
3766219019Sgabor                int result = visit(t.getEnclosingType());
3767219019Sgabor                result *= 127;
3768219019Sgabor                result += t.tsym.flatName().hashCode();
3769219019Sgabor                for (Type s : t.getTypeArguments()) {
3770219019Sgabor                    result *= 127;
3771219019Sgabor                    result += visit(s);
3772219019Sgabor                }
3773219019Sgabor                return result;
3774219019Sgabor            }
3775219019Sgabor
3776219019Sgabor            @Override
3777219019Sgabor            public Integer visitMethodType(MethodType t, Void ignored) {
3778219019Sgabor                int h = METHOD.ordinal();
3779219019Sgabor                for (List<Type> thisargs = t.argtypes;
3780219019Sgabor                     thisargs.tail != null;
3781219019Sgabor                     thisargs = thisargs.tail)
3782219019Sgabor                    h = (h << 5) + visit(thisargs.head);
3783219019Sgabor                return (h << 5) + visit(t.restype);
3784219019Sgabor            }
3785219019Sgabor
3786219019Sgabor            @Override
3787219019Sgabor            public Integer visitWildcardType(WildcardType t, Void ignored) {
3788219019Sgabor                int result = t.kind.hashCode();
3789219019Sgabor                if (t.type != null) {
3790219019Sgabor                    result *= 127;
3791219019Sgabor                    result += visit(t.type);
3792219019Sgabor                }
3793219019Sgabor                return result;
3794219019Sgabor            }
3795219019Sgabor
3796219019Sgabor            @Override
3797219019Sgabor            public Integer visitArrayType(ArrayType t, Void ignored) {
3798219019Sgabor                return visit(t.elemtype) + 12;
3799219019Sgabor            }
3800219019Sgabor
3801219019Sgabor            @Override
3802219019Sgabor            public Integer visitTypeVar(TypeVar t, Void ignored) {
3803219019Sgabor                return System.identityHashCode(t.tsym);
3804219019Sgabor            }
3805219019Sgabor
3806219019Sgabor            @Override
3807219019Sgabor            public Integer visitUndetVar(UndetVar t, Void ignored) {
3808219019Sgabor                return System.identityHashCode(t);
3809219019Sgabor            }
3810219019Sgabor
3811219019Sgabor            @Override
3812219019Sgabor            public Integer visitErrorType(ErrorType t, Void ignored) {
3813219019Sgabor                return 0;
3814219019Sgabor            }
3815219019Sgabor        };
3816219019Sgabor    // </editor-fold>
3817219019Sgabor
3818219019Sgabor    // <editor-fold defaultstate="collapsed" desc="Return-Type-Substitutable">
3819219019Sgabor    /**
3820219019Sgabor     * Does t have a result that is a subtype of the result type of s,
3821219019Sgabor     * suitable for covariant returns?  It is assumed that both types
3822219019Sgabor     * are (possibly polymorphic) method types.  Monomorphic method
3823219019Sgabor     * types are handled in the obvious way.  Polymorphic method types
3824219019Sgabor     * require renaming all type variables of one to corresponding
3825219019Sgabor     * type variables in the other, where correspondence is by
3826219019Sgabor     * position in the type parameter list. */
3827219019Sgabor    public boolean resultSubtype(Type t, Type s, Warner warner) {
3828219019Sgabor        List<Type> tvars = t.getTypeArguments();
3829219019Sgabor        List<Type> svars = s.getTypeArguments();
3830219019Sgabor        Type tres = t.getReturnType();
3831219019Sgabor        Type sres = subst(s.getReturnType(), svars, tvars);
3832219019Sgabor        return covariantReturnType(tres, sres, warner);
3833219019Sgabor    }
3834219019Sgabor
3835219019Sgabor    /**
3836219019Sgabor     * Return-Type-Substitutable.
3837219019Sgabor     * @jls section 8.4.5
3838219019Sgabor     */
3839219019Sgabor    public boolean returnTypeSubstitutable(Type r1, Type r2) {
3840219019Sgabor        if (hasSameArgs(r1, r2))
3841219019Sgabor            return resultSubtype(r1, r2, noWarnings);
3842219019Sgabor        else
3843219019Sgabor            return covariantReturnType(r1.getReturnType(),
3844219019Sgabor                                       erasure(r2.getReturnType()),
3845219019Sgabor                                       noWarnings);
3846219019Sgabor    }
3847219019Sgabor
3848219019Sgabor    public boolean returnTypeSubstitutable(Type r1,
3849219019Sgabor                                           Type r2, Type r2res,
3850219019Sgabor                                           Warner warner) {
3851219019Sgabor        if (isSameType(r1.getReturnType(), r2res))
3852219019Sgabor            return true;
3853219019Sgabor        if (r1.getReturnType().isPrimitive() || r2res.isPrimitive())
3854219019Sgabor            return false;
3855219019Sgabor
3856219019Sgabor        if (hasSameArgs(r1, r2))
3857219019Sgabor            return covariantReturnType(r1.getReturnType(), r2res, warner);
3858219019Sgabor        if (isSubtypeUnchecked(r1.getReturnType(), r2res, warner))
3859219019Sgabor            return true;
3860219019Sgabor        if (!isSubtype(r1.getReturnType(), erasure(r2res)))
3861219019Sgabor            return false;
3862219019Sgabor        warner.warn(LintCategory.UNCHECKED);
3863219019Sgabor        return true;
3864219019Sgabor    }
3865219019Sgabor
3866219019Sgabor    /**
3867219019Sgabor     * Is t an appropriate return type in an overrider for a
3868219019Sgabor     * method that returns s?
3869219019Sgabor     */
3870219019Sgabor    public boolean covariantReturnType(Type t, Type s, Warner warner) {
3871219019Sgabor        return
3872219019Sgabor            isSameType(t, s) ||
3873219019Sgabor            !t.isPrimitive() &&
3874219019Sgabor            !s.isPrimitive() &&
3875219019Sgabor            isAssignable(t, s, warner);
3876219019Sgabor    }
3877219019Sgabor    // </editor-fold>
3878219019Sgabor
3879219019Sgabor    // <editor-fold defaultstate="collapsed" desc="Box/unbox support">
3880219019Sgabor    /**
3881219019Sgabor     * Return the class that boxes the given primitive.
3882219019Sgabor     */
3883219019Sgabor    public ClassSymbol boxedClass(Type t) {
3884219019Sgabor        return syms.enterClass(syms.boxedName[t.getTag().ordinal()]);
3885219019Sgabor    }
3886219019Sgabor
3887219019Sgabor    /**
3888219019Sgabor     * Return the boxed type if 't' is primitive, otherwise return 't' itself.
3889219019Sgabor     */
3890219019Sgabor    public Type boxedTypeOrType(Type t) {
3891219019Sgabor        return t.isPrimitive() ?
3892219019Sgabor            boxedClass(t).type :
3893219019Sgabor            t;
3894219019Sgabor    }
3895219019Sgabor
3896219019Sgabor    /**
3897219019Sgabor     * Return the primitive type corresponding to a boxed type.
3898219019Sgabor     */
3899219019Sgabor    public Type unboxedType(Type t) {
3900219019Sgabor        for (int i=0; i<syms.boxedName.length; i++) {
3901219019Sgabor            Name box = syms.boxedName[i];
3902219019Sgabor            if (box != null &&
3903219019Sgabor                asSuper(t, syms.enterClass(box)) != null)
3904219019Sgabor                return syms.typeOfTag[i];
3905219019Sgabor        }
3906219019Sgabor        return Type.noType;
3907219019Sgabor    }
3908219019Sgabor
3909219019Sgabor    /**
3910219019Sgabor     * Return the unboxed type if 't' is a boxed class, otherwise return 't' itself.
3911219019Sgabor     */
3912219019Sgabor    public Type unboxedTypeOrType(Type t) {
3913219019Sgabor        Type unboxedType = unboxedType(t);
3914219019Sgabor        return unboxedType.hasTag(NONE) ? t : unboxedType;
3915219019Sgabor    }
3916219019Sgabor    // </editor-fold>
3917219019Sgabor
3918219019Sgabor    // <editor-fold defaultstate="collapsed" desc="Capture conversion">
3919219019Sgabor    /*
3920219019Sgabor     * JLS 5.1.10 Capture Conversion:
3921219019Sgabor     *
3922219019Sgabor     * Let G name a generic type declaration with n formal type
3923219019Sgabor     * parameters A1 ... An with corresponding bounds U1 ... Un. There
3924219019Sgabor     * exists a capture conversion from G<T1 ... Tn> to G<S1 ... Sn>,
3925219019Sgabor     * where, for 1 <= i <= n:
3926219019Sgabor     *
3927219019Sgabor     * + If Ti is a wildcard type argument (4.5.1) of the form ? then
3928219019Sgabor     *   Si is a fresh type variable whose upper bound is
3929219019Sgabor     *   Ui[A1 := S1, ..., An := Sn] and whose lower bound is the null
3930219019Sgabor     *   type.
3931219019Sgabor     *
3932219019Sgabor     * + If Ti is a wildcard type argument of the form ? extends Bi,
3933219019Sgabor     *   then Si is a fresh type variable whose upper bound is
3934219019Sgabor     *   glb(Bi, Ui[A1 := S1, ..., An := Sn]) and whose lower bound is
3935219019Sgabor     *   the null type, where glb(V1,... ,Vm) is V1 & ... & Vm. It is
3936219019Sgabor     *   a compile-time error if for any two classes (not interfaces)
3937219019Sgabor     *   Vi and Vj,Vi is not a subclass of Vj or vice versa.
3938219019Sgabor     *
3939219019Sgabor     * + If Ti is a wildcard type argument of the form ? super Bi,
3940219019Sgabor     *   then Si is a fresh type variable whose upper bound is
3941219019Sgabor     *   Ui[A1 := S1, ..., An := Sn] and whose lower bound is Bi.
3942219019Sgabor     *
3943219019Sgabor     * + Otherwise, Si = Ti.
3944219019Sgabor     *
3945219019Sgabor     * Capture conversion on any type other than a parameterized type
3946219019Sgabor     * (4.5) acts as an identity conversion (5.1.1). Capture
3947219019Sgabor     * conversions never require a special action at run time and
3948219019Sgabor     * therefore never throw an exception at run time.
3949219019Sgabor     *
3950219019Sgabor     * Capture conversion is not applied recursively.
3951219019Sgabor     */
3952219019Sgabor    /**
3953219019Sgabor     * Capture conversion as specified by the JLS.
3954219019Sgabor     */
3955219019Sgabor
3956219019Sgabor    public List<Type> capture(List<Type> ts) {
3957219019Sgabor        List<Type> buf = List.nil();
3958219019Sgabor        for (Type t : ts) {
3959219019Sgabor            buf = buf.prepend(capture(t));
3960219019Sgabor        }
3961219019Sgabor        return buf.reverse();
3962219019Sgabor    }
3963219019Sgabor
3964219019Sgabor    public Type capture(Type t) {
3965219019Sgabor        if (!t.hasTag(CLASS)) {
3966219019Sgabor            return t;
3967219019Sgabor        }
3968219019Sgabor        if (t.getEnclosingType() != Type.noType) {
3969219019Sgabor            Type capturedEncl = capture(t.getEnclosingType());
3970219019Sgabor            if (capturedEncl != t.getEnclosingType()) {
3971219019Sgabor                Type type1 = memberType(capturedEncl, t.tsym);
3972219019Sgabor                t = subst(type1, t.tsym.type.getTypeArguments(), t.getTypeArguments());
3973219019Sgabor            }
3974219019Sgabor        }
3975219019Sgabor        ClassType cls = (ClassType)t;
3976219019Sgabor        if (cls.isRaw() || !cls.isParameterized())
3977219019Sgabor            return cls;
3978219019Sgabor
3979219019Sgabor        ClassType G = (ClassType)cls.asElement().asType();
3980219019Sgabor        List<Type> A = G.getTypeArguments();
3981219019Sgabor        List<Type> T = cls.getTypeArguments();
3982219019Sgabor        List<Type> S = freshTypeVariables(T);
3983219019Sgabor
3984219019Sgabor        List<Type> currentA = A;
3985219019Sgabor        List<Type> currentT = T;
3986219019Sgabor        List<Type> currentS = S;
3987219019Sgabor        boolean captured = false;
3988219019Sgabor        while (!currentA.isEmpty() &&
3989219019Sgabor               !currentT.isEmpty() &&
3990219019Sgabor               !currentS.isEmpty()) {
3991219019Sgabor            if (currentS.head != currentT.head) {
3992219019Sgabor                captured = true;
3993219019Sgabor                WildcardType Ti = (WildcardType)currentT.head;
3994219019Sgabor                Type Ui = currentA.head.getUpperBound();
3995219019Sgabor                CapturedType Si = (CapturedType)currentS.head;
3996219019Sgabor                if (Ui == null)
3997219019Sgabor                    Ui = syms.objectType;
3998219019Sgabor                switch (Ti.kind) {
3999219019Sgabor                case UNBOUND:
4000219019Sgabor                    Si.bound = subst(Ui, A, S);
4001219019Sgabor                    Si.lower = syms.botType;
4002219019Sgabor                    break;
4003219019Sgabor                case EXTENDS:
4004219019Sgabor                    Si.bound = glb(Ti.getExtendsBound(), subst(Ui, A, S));
4005219019Sgabor                    Si.lower = syms.botType;
4006219019Sgabor                    break;
4007219019Sgabor                case SUPER:
4008219019Sgabor                    Si.bound = subst(Ui, A, S);
4009219019Sgabor                    Si.lower = Ti.getSuperBound();
4010219019Sgabor                    break;
4011219019Sgabor                }
4012219019Sgabor                Type tmpBound = Si.bound.hasTag(UNDETVAR) ? ((UndetVar)Si.bound).qtype : Si.bound;
4013219019Sgabor                Type tmpLower = Si.lower.hasTag(UNDETVAR) ? ((UndetVar)Si.lower).qtype : Si.lower;
4014219019Sgabor                if (!Si.bound.hasTag(ERROR) &&
4015219019Sgabor                    !Si.lower.hasTag(ERROR) &&
4016219019Sgabor                    isSameType(tmpBound, tmpLower, false)) {
4017219019Sgabor                    currentS.head = Si.bound;
4018219019Sgabor                }
4019219019Sgabor            }
4020219019Sgabor            currentA = currentA.tail;
4021219019Sgabor            currentT = currentT.tail;
4022219019Sgabor            currentS = currentS.tail;
4023219019Sgabor        }
4024219019Sgabor        if (!currentA.isEmpty() || !currentT.isEmpty() || !currentS.isEmpty())
4025219019Sgabor            return erasure(t); // some "rare" type involved
4026219019Sgabor
4027219019Sgabor        if (captured)
4028219019Sgabor            return new ClassType(cls.getEnclosingType(), S, cls.tsym,
4029219019Sgabor                                 cls.getMetadata());
4030219019Sgabor        else
4031219019Sgabor            return t;
4032219019Sgabor    }
4033219019Sgabor    // where
4034219019Sgabor        public List<Type> freshTypeVariables(List<Type> types) {
4035219019Sgabor            ListBuffer<Type> result = new ListBuffer<>();
4036219019Sgabor            for (Type t : types) {
4037219019Sgabor                if (t.hasTag(WILDCARD)) {
4038219019Sgabor                    Type bound = ((WildcardType)t).getExtendsBound();
4039219019Sgabor                    if (bound == null)
4040219019Sgabor                        bound = syms.objectType;
4041219019Sgabor                    result.append(new CapturedType(capturedName,
4042219019Sgabor                                                   syms.noSymbol,
4043219019Sgabor                                                   bound,
4044219019Sgabor                                                   syms.botType,
4045219019Sgabor                                                   (WildcardType)t));
4046219019Sgabor                } else {
4047219019Sgabor                    result.append(t);
4048219019Sgabor                }
4049219019Sgabor            }
4050219019Sgabor            return result.toList();
4051219019Sgabor        }
4052219019Sgabor    // </editor-fold>
4053219019Sgabor
4054219019Sgabor    // <editor-fold defaultstate="collapsed" desc="Internal utility methods">
4055219019Sgabor    private boolean sideCast(Type from, Type to, Warner warn) {
4056219019Sgabor        // We are casting from type $from$ to type $to$, which are
4057219019Sgabor        // non-final unrelated types.  This method
4058219019Sgabor        // tries to reject a cast by transferring type parameters
4059219019Sgabor        // from $to$ to $from$ by common superinterfaces.
4060219019Sgabor        boolean reverse = false;
4061219019Sgabor        Type target = to;
4062219019Sgabor        if ((to.tsym.flags() & INTERFACE) == 0) {
4063219019Sgabor            Assert.check((from.tsym.flags() & INTERFACE) != 0);
4064219019Sgabor            reverse = true;
4065219019Sgabor            to = from;
4066219019Sgabor            from = target;
4067219019Sgabor        }
4068219019Sgabor        List<Type> commonSupers = superClosure(to, erasure(from));
4069219019Sgabor        boolean giveWarning = commonSupers.isEmpty();
4070219019Sgabor        // The arguments to the supers could be unified here to
4071219019Sgabor        // get a more accurate analysis
4072219019Sgabor        while (commonSupers.nonEmpty()) {
4073219019Sgabor            Type t1 = asSuper(from, commonSupers.head.tsym);
4074219019Sgabor            Type t2 = commonSupers.head; // same as asSuper(to, commonSupers.head.tsym);
4075219019Sgabor            if (disjointTypes(t1.getTypeArguments(), t2.getTypeArguments()))
4076219019Sgabor                return false;
4077219019Sgabor            giveWarning = giveWarning || (reverse ? giveWarning(t2, t1) : giveWarning(t1, t2));
4078219019Sgabor            commonSupers = commonSupers.tail;
4079219019Sgabor        }
4080219019Sgabor        if (giveWarning && !isReifiable(reverse ? from : to))
4081219019Sgabor            warn.warn(LintCategory.UNCHECKED);
4082219019Sgabor        return true;
4083219019Sgabor    }
4084219019Sgabor
4085219019Sgabor    private boolean sideCastFinal(Type from, Type to, Warner warn) {
4086219019Sgabor        // We are casting from type $from$ to type $to$, which are
4087219019Sgabor        // unrelated types one of which is final and the other of
4088219019Sgabor        // which is an interface.  This method
4089219019Sgabor        // tries to reject a cast by transferring type parameters
4090219019Sgabor        // from the final class to the interface.
4091219019Sgabor        boolean reverse = false;
4092219019Sgabor        Type target = to;
4093219019Sgabor        if ((to.tsym.flags() & INTERFACE) == 0) {
4094219019Sgabor            Assert.check((from.tsym.flags() & INTERFACE) != 0);
4095219019Sgabor            reverse = true;
4096219019Sgabor            to = from;
4097219019Sgabor            from = target;
4098219019Sgabor        }
4099219019Sgabor        Assert.check((from.tsym.flags() & FINAL) != 0);
4100219019Sgabor        Type t1 = asSuper(from, to.tsym);
4101219019Sgabor        if (t1 == null) return false;
4102219019Sgabor        Type t2 = to;
4103219019Sgabor        if (disjointTypes(t1.getTypeArguments(), t2.getTypeArguments()))
4104219019Sgabor            return false;
4105219019Sgabor        if (!isReifiable(target) &&
4106219019Sgabor            (reverse ? giveWarning(t2, t1) : giveWarning(t1, t2)))
4107219019Sgabor            warn.warn(LintCategory.UNCHECKED);
4108219019Sgabor        return true;
4109219019Sgabor    }
4110219019Sgabor
4111219019Sgabor    private boolean giveWarning(Type from, Type to) {
4112219019Sgabor        List<Type> bounds = to.isCompound() ?
4113219019Sgabor                ((IntersectionClassType)to).getComponents() : List.of(to);
4114219019Sgabor        for (Type b : bounds) {
4115219019Sgabor            Type subFrom = asSub(from, b.tsym);
4116219019Sgabor            if (b.isParameterized() &&
4117219019Sgabor                    (!(isUnbounded(b) ||
4118219019Sgabor                    isSubtype(from, b) ||
4119219019Sgabor                    ((subFrom != null) && containsType(b.allparams(), subFrom.allparams()))))) {
4120219019Sgabor                return true;
4121219019Sgabor            }
4122219019Sgabor        }
4123219019Sgabor        return false;
4124219019Sgabor    }
4125219019Sgabor
4126219019Sgabor    private List<Type> superClosure(Type t, Type s) {
4127219019Sgabor        List<Type> cl = List.nil();
4128219019Sgabor        for (List<Type> l = interfaces(t); l.nonEmpty(); l = l.tail) {
4129219019Sgabor            if (isSubtype(s, erasure(l.head))) {
4130219019Sgabor                cl = insert(cl, l.head);
4131219019Sgabor            } else {
4132219019Sgabor                cl = union(cl, superClosure(l.head, s));
4133219019Sgabor            }
4134219019Sgabor        }
4135219019Sgabor        return cl;
4136219019Sgabor    }
4137219019Sgabor
4138219019Sgabor    private boolean containsTypeEquivalent(Type t, Type s) {
4139219019Sgabor        return isSameType(t, s) || // shortcut
4140219019Sgabor            containsType(t, s) && containsType(s, t);
4141219019Sgabor    }
4142219019Sgabor
4143219019Sgabor    // <editor-fold defaultstate="collapsed" desc="adapt">
4144219019Sgabor    /**
4145219019Sgabor     * Adapt a type by computing a substitution which maps a source
4146219019Sgabor     * type to a target type.
4147219019Sgabor     *
4148219019Sgabor     * @param source    the source type
4149219019Sgabor     * @param target    the target type
4150219019Sgabor     * @param from      the type variables of the computed substitution
4151219019Sgabor     * @param to        the types of the computed substitution.
4152219019Sgabor     */
4153219019Sgabor    public void adapt(Type source,
4154219019Sgabor                       Type target,
4155219019Sgabor                       ListBuffer<Type> from,
4156219019Sgabor                       ListBuffer<Type> to) throws AdaptFailure {
4157219019Sgabor        new Adapter(from, to).adapt(source, target);
4158219019Sgabor    }
4159219019Sgabor
4160219019Sgabor    class Adapter extends SimpleVisitor<Void, Type> {
4161219019Sgabor
4162219019Sgabor        ListBuffer<Type> from;
4163219019Sgabor        ListBuffer<Type> to;
4164219019Sgabor        Map<Symbol,Type> mapping;
4165219019Sgabor
4166219019Sgabor        Adapter(ListBuffer<Type> from, ListBuffer<Type> to) {
4167219019Sgabor            this.from = from;
4168219019Sgabor            this.to = to;
4169219019Sgabor            mapping = new HashMap<>();
4170219019Sgabor        }
4171219019Sgabor
4172219019Sgabor        public void adapt(Type source, Type target) throws AdaptFailure {
4173219019Sgabor            visit(source, target);
4174219019Sgabor            List<Type> fromList = from.toList();
4175219019Sgabor            List<Type> toList = to.toList();
4176219019Sgabor            while (!fromList.isEmpty()) {
4177219019Sgabor                Type val = mapping.get(fromList.head.tsym);
4178219019Sgabor                if (toList.head != val)
4179219019Sgabor                    toList.head = val;
4180219019Sgabor                fromList = fromList.tail;
4181219019Sgabor                toList = toList.tail;
4182219019Sgabor            }
4183219019Sgabor        }
4184219019Sgabor
4185219019Sgabor        @Override
4186219019Sgabor        public Void visitClassType(ClassType source, Type target) throws AdaptFailure {
4187219019Sgabor            if (target.hasTag(CLASS))
4188219019Sgabor                adaptRecursive(source.allparams(), target.allparams());
4189219019Sgabor            return null;
4190219019Sgabor        }
4191219019Sgabor
4192219019Sgabor        @Override
4193219019Sgabor        public Void visitArrayType(ArrayType source, Type target) throws AdaptFailure {
4194219019Sgabor            if (target.hasTag(ARRAY))
4195219019Sgabor                adaptRecursive(elemtype(source), elemtype(target));
4196219019Sgabor            return null;
4197219019Sgabor        }
4198219019Sgabor
4199219019Sgabor        @Override
4200219019Sgabor        public Void visitWildcardType(WildcardType source, Type target) throws AdaptFailure {
4201219019Sgabor            if (source.isExtendsBound())
4202219019Sgabor                adaptRecursive(wildUpperBound(source), wildUpperBound(target));
4203219019Sgabor            else if (source.isSuperBound())
4204219019Sgabor                adaptRecursive(wildLowerBound(source), wildLowerBound(target));
4205219019Sgabor            return null;
4206219019Sgabor        }
4207219019Sgabor
4208219019Sgabor        @Override
4209219019Sgabor        public Void visitTypeVar(TypeVar source, Type target) throws AdaptFailure {
4210219019Sgabor            // Check to see if there is
4211219019Sgabor            // already a mapping for $source$, in which case
4212219019Sgabor            // the old mapping will be merged with the new
4213219019Sgabor            Type val = mapping.get(source.tsym);
4214219019Sgabor            if (val != null) {
4215219019Sgabor                if (val.isSuperBound() && target.isSuperBound()) {
4216219019Sgabor                    val = isSubtype(wildLowerBound(val), wildLowerBound(target))
4217219019Sgabor                        ? target : val;
4218219019Sgabor                } else if (val.isExtendsBound() && target.isExtendsBound()) {
4219219019Sgabor                    val = isSubtype(wildUpperBound(val), wildUpperBound(target))
4220219019Sgabor                        ? val : target;
4221219019Sgabor                } else if (!isSameType(val, target)) {
4222219019Sgabor                    throw new AdaptFailure();
4223219019Sgabor                }
4224219019Sgabor            } else {
4225219019Sgabor                val = target;
4226219019Sgabor                from.append(source);
4227219019Sgabor                to.append(target);
4228219019Sgabor            }
4229219019Sgabor            mapping.put(source.tsym, val);
4230219019Sgabor            return null;
4231219019Sgabor        }
4232219019Sgabor
4233219019Sgabor        @Override
4234219019Sgabor        public Void visitType(Type source, Type target) {
4235219019Sgabor            return null;
4236219019Sgabor        }
4237219019Sgabor
4238219019Sgabor        private Set<TypePair> cache = new HashSet<>();
4239219019Sgabor
4240219019Sgabor        private void adaptRecursive(Type source, Type target) {
4241219019Sgabor            TypePair pair = new TypePair(source, target);
4242219019Sgabor            if (cache.add(pair)) {
4243219019Sgabor                try {
4244219019Sgabor                    visit(source, target);
4245219019Sgabor                } finally {
4246219019Sgabor                    cache.remove(pair);
4247219019Sgabor                }
4248219019Sgabor            }
4249219019Sgabor        }
4250219019Sgabor
4251219019Sgabor        private void adaptRecursive(List<Type> source, List<Type> target) {
4252219019Sgabor            if (source.length() == target.length()) {
4253219019Sgabor                while (source.nonEmpty()) {
4254219019Sgabor                    adaptRecursive(source.head, target.head);
4255219019Sgabor                    source = source.tail;
4256219019Sgabor                    target = target.tail;
4257219019Sgabor                }
4258219019Sgabor            }
4259219019Sgabor        }
4260219019Sgabor    }
4261219019Sgabor
4262219019Sgabor    public static class AdaptFailure extends RuntimeException {
4263219019Sgabor        static final long serialVersionUID = -7490231548272701566L;
4264219019Sgabor    }
4265219019Sgabor
4266219019Sgabor    private void adaptSelf(Type t,
4267219019Sgabor                           ListBuffer<Type> from,
4268219019Sgabor                           ListBuffer<Type> to) {
4269219019Sgabor        try {
4270219019Sgabor            //if (t.tsym.type != t)
4271219019Sgabor                adapt(t.tsym.type, t, from, to);
4272219019Sgabor        } catch (AdaptFailure ex) {
4273219019Sgabor            // Adapt should never fail calculating a mapping from
4274219019Sgabor            // t.tsym.type to t as there can be no merge problem.
4275219019Sgabor            throw new AssertionError(ex);
4276219019Sgabor        }
4277219019Sgabor    }
4278219019Sgabor    // </editor-fold>
4279219019Sgabor
4280219019Sgabor    /**
4281219019Sgabor     * Rewrite all type variables (universal quantifiers) in the given
4282219019Sgabor     * type to wildcards (existential quantifiers).  This is used to
4283219019Sgabor     * determine if a cast is allowed.  For example, if high is true
4284219019Sgabor     * and {@code T <: Number}, then {@code List<T>} is rewritten to
4285219019Sgabor     * {@code List<?  extends Number>}.  Since {@code List<Integer> <:
4286219019Sgabor     * List<? extends Number>} a {@code List<T>} can be cast to {@code
4287219019Sgabor     * List<Integer>} with a warning.
4288219019Sgabor     * @param t a type
4289219019Sgabor     * @param high if true return an upper bound; otherwise a lower
4290219019Sgabor     * bound
4291219019Sgabor     * @param rewriteTypeVars only rewrite captured wildcards if false;
4292219019Sgabor     * otherwise rewrite all type variables
4293219019Sgabor     * @return the type rewritten with wildcards (existential
4294219019Sgabor     * quantifiers) only
4295219019Sgabor     */
4296219019Sgabor    private Type rewriteQuantifiers(Type t, boolean high, boolean rewriteTypeVars) {
4297219019Sgabor        return new Rewriter(high, rewriteTypeVars).visit(t);
4298219019Sgabor    }
4299219019Sgabor
4300219019Sgabor    class Rewriter extends UnaryVisitor<Type> {
4301219019Sgabor
4302219019Sgabor        boolean high;
4303219019Sgabor        boolean rewriteTypeVars;
4304219019Sgabor
4305219019Sgabor        Rewriter(boolean high, boolean rewriteTypeVars) {
4306219019Sgabor            this.high = high;
4307219019Sgabor            this.rewriteTypeVars = rewriteTypeVars;
4308219019Sgabor        }
4309219019Sgabor
4310219019Sgabor        @Override
4311219019Sgabor        public Type visitClassType(ClassType t, Void s) {
4312219019Sgabor            ListBuffer<Type> rewritten = new ListBuffer<>();
4313219019Sgabor            boolean changed = false;
4314219019Sgabor            for (Type arg : t.allparams()) {
4315219019Sgabor                Type bound = visit(arg);
4316219019Sgabor                if (arg != bound) {
4317219019Sgabor                    changed = true;
4318219019Sgabor                }
4319219019Sgabor                rewritten.append(bound);
4320219019Sgabor            }
4321219019Sgabor            if (changed)
4322219019Sgabor                return subst(t.tsym.type,
4323219019Sgabor                        t.tsym.type.allparams(),
4324219019Sgabor                        rewritten.toList());
4325219019Sgabor            else
4326219019Sgabor                return t;
4327219019Sgabor        }
4328219019Sgabor
4329219019Sgabor        public Type visitType(Type t, Void s) {
4330219019Sgabor            return t;
4331219019Sgabor        }
4332219019Sgabor
4333219019Sgabor        @Override
4334219019Sgabor        public Type visitCapturedType(CapturedType t, Void s) {
4335219019Sgabor            Type w_bound = t.wildcard.type;
4336219019Sgabor            Type bound = w_bound.contains(t) ?
4337219019Sgabor                        erasure(w_bound) :
4338219019Sgabor                        visit(w_bound);
4339219019Sgabor            return rewriteAsWildcardType(visit(bound), t.wildcard.bound, t.wildcard.kind);
4340219019Sgabor        }
4341219019Sgabor
4342219019Sgabor        @Override
4343219019Sgabor        public Type visitTypeVar(TypeVar t, Void s) {
4344219019Sgabor            if (rewriteTypeVars) {
4345219019Sgabor                Type bound = t.bound.contains(t) ?
4346219019Sgabor                        erasure(t.bound) :
4347219019Sgabor                        visit(t.bound);
4348219019Sgabor                return rewriteAsWildcardType(bound, t, EXTENDS);
4349219019Sgabor            } else {
4350219019Sgabor                return t;
4351219019Sgabor            }
4352219019Sgabor        }
4353219019Sgabor
4354219019Sgabor        @Override
4355219019Sgabor        public Type visitWildcardType(WildcardType t, Void s) {
4356219019Sgabor            Type bound2 = visit(t.type);
4357219019Sgabor            return t.type == bound2 ? t : rewriteAsWildcardType(bound2, t.bound, t.kind);
4358219019Sgabor        }
4359219019Sgabor
4360219019Sgabor        private Type rewriteAsWildcardType(Type bound, TypeVar formal, BoundKind bk) {
4361219019Sgabor            switch (bk) {
4362219019Sgabor               case EXTENDS: return high ?
4363219019Sgabor                       makeExtendsWildcard(B(bound), formal) :
4364219019Sgabor                       makeExtendsWildcard(syms.objectType, formal);
4365219019Sgabor               case SUPER: return high ?
4366219019Sgabor                       makeSuperWildcard(syms.botType, formal) :
4367219019Sgabor                       makeSuperWildcard(B(bound), formal);
4368219019Sgabor               case UNBOUND: return makeExtendsWildcard(syms.objectType, formal);
4369219019Sgabor               default:
4370219019Sgabor                   Assert.error("Invalid bound kind " + bk);
4371219019Sgabor                   return null;
4372219019Sgabor            }
4373219019Sgabor        }
4374219019Sgabor
4375219019Sgabor        Type B(Type t) {
4376219019Sgabor            while (t.hasTag(WILDCARD)) {
4377219019Sgabor                WildcardType w = (WildcardType)t;
4378219019Sgabor                t = high ?
4379219019Sgabor                    w.getExtendsBound() :
4380219019Sgabor                    w.getSuperBound();
4381219019Sgabor                if (t == null) {
4382219019Sgabor                    t = high ? syms.objectType : syms.botType;
4383219019Sgabor                }
4384219019Sgabor            }
4385219019Sgabor            return t;
4386219019Sgabor        }
4387219019Sgabor    }
4388219019Sgabor
4389219019Sgabor
4390219019Sgabor    /**
4391219019Sgabor     * Create a wildcard with the given upper (extends) bound; create
4392219019Sgabor     * an unbounded wildcard if bound is Object.
4393219019Sgabor     *
4394219019Sgabor     * @param bound the upper bound
4395219019Sgabor     * @param formal the formal type parameter that will be
4396219019Sgabor     * substituted by the wildcard
4397219019Sgabor     */
4398219019Sgabor    private WildcardType makeExtendsWildcard(Type bound, TypeVar formal) {
4399219019Sgabor        if (bound == syms.objectType) {
4400219019Sgabor            return new WildcardType(syms.objectType,
4401219019Sgabor                                    BoundKind.UNBOUND,
4402219019Sgabor                                    syms.boundClass,
4403219019Sgabor                                    formal);
4404219019Sgabor        } else {
4405219019Sgabor            return new WildcardType(bound,
4406219019Sgabor                                    BoundKind.EXTENDS,
4407219019Sgabor                                    syms.boundClass,
4408219019Sgabor                                    formal);
4409219019Sgabor        }
4410219019Sgabor    }
4411219019Sgabor
4412219019Sgabor    /**
4413219019Sgabor     * Create a wildcard with the given lower (super) bound; create an
4414219019Sgabor     * unbounded wildcard if bound is bottom (type of {@code null}).
4415219019Sgabor     *
4416219019Sgabor     * @param bound the lower bound
4417219019Sgabor     * @param formal the formal type parameter that will be
4418219019Sgabor     * substituted by the wildcard
4419219019Sgabor     */
4420219019Sgabor    private WildcardType makeSuperWildcard(Type bound, TypeVar formal) {
4421219019Sgabor        if (bound.hasTag(BOT)) {
4422219019Sgabor            return new WildcardType(syms.objectType,
4423219019Sgabor                                    BoundKind.UNBOUND,
4424219019Sgabor                                    syms.boundClass,
4425219019Sgabor                                    formal);
4426219019Sgabor        } else {
4427219019Sgabor            return new WildcardType(bound,
4428219019Sgabor                                    BoundKind.SUPER,
4429219019Sgabor                                    syms.boundClass,
4430219019Sgabor                                    formal);
4431219019Sgabor        }
4432219019Sgabor    }
4433219019Sgabor
4434219019Sgabor    /**
4435219019Sgabor     * A wrapper for a type that allows use in sets.
4436219019Sgabor     */
4437219019Sgabor    public static class UniqueType {
4438219019Sgabor        public final Type type;
4439219019Sgabor        final Types types;
4440219019Sgabor
4441219019Sgabor        public UniqueType(Type type, Types types) {
4442219019Sgabor            this.type = type;
4443219019Sgabor            this.types = types;
4444219019Sgabor        }
4445219019Sgabor
4446219019Sgabor        public int hashCode() {
4447219019Sgabor            return types.hashCode(type);
4448219019Sgabor        }
4449219019Sgabor
4450219019Sgabor        public boolean equals(Object obj) {
4451219019Sgabor            return (obj instanceof UniqueType) &&
4452219019Sgabor                types.isSameType(type, ((UniqueType)obj).type);
4453219019Sgabor        }
4454219019Sgabor
4455219019Sgabor        public String toString() {
4456219019Sgabor            return type.toString();
4457219019Sgabor        }
4458219019Sgabor
4459219019Sgabor    }
4460219019Sgabor    // </editor-fold>
4461219019Sgabor
4462219019Sgabor    // <editor-fold defaultstate="collapsed" desc="Visitors">
4463219019Sgabor    /**
4464219019Sgabor     * A default visitor for types.  All visitor methods except
4465219019Sgabor     * visitType are implemented by delegating to visitType.  Concrete
4466219019Sgabor     * subclasses must provide an implementation of visitType and can
4467219019Sgabor     * override other methods as needed.
4468219019Sgabor     *
4469219019Sgabor     * @param <R> the return type of the operation implemented by this
4470219019Sgabor     * visitor; use Void if no return type is needed.
4471219019Sgabor     * @param <S> the type of the second argument (the first being the
4472219019Sgabor     * type itself) of the operation implemented by this visitor; use
4473219019Sgabor     * Void if a second argument is not needed.
4474219019Sgabor     */
4475219019Sgabor    public static abstract class DefaultTypeVisitor<R,S> implements Type.Visitor<R,S> {
4476219019Sgabor        final public R visit(Type t, S s)               { return t.accept(this, s); }
4477219019Sgabor        public R visitClassType(ClassType t, S s)       { return visitType(t, s); }
4478219019Sgabor        public R visitWildcardType(WildcardType t, S s) { return visitType(t, s); }
4479219019Sgabor        public R visitArrayType(ArrayType t, S s)       { return visitType(t, s); }
4480219019Sgabor        public R visitMethodType(MethodType t, S s)     { return visitType(t, s); }
4481219019Sgabor        public R visitPackageType(PackageType t, S s)   { return visitType(t, s); }
4482219019Sgabor        public R visitTypeVar(TypeVar t, S s)           { return visitType(t, s); }
4483219019Sgabor        public R visitCapturedType(CapturedType t, S s) { return visitType(t, s); }
4484219019Sgabor        public R visitForAll(ForAll t, S s)             { return visitType(t, s); }
4485219019Sgabor        public R visitUndetVar(UndetVar t, S s)         { return visitType(t, s); }
4486219019Sgabor        public R visitErrorType(ErrorType t, S s)       { return visitType(t, s); }
4487219019Sgabor    }
4488219019Sgabor
4489219019Sgabor    /**
4490219019Sgabor     * A default visitor for symbols.  All visitor methods except
4491219019Sgabor     * visitSymbol are implemented by delegating to visitSymbol.  Concrete
4492219019Sgabor     * subclasses must provide an implementation of visitSymbol and can
4493219019Sgabor     * override other methods as needed.
4494219019Sgabor     *
4495219019Sgabor     * @param <R> the return type of the operation implemented by this
4496219019Sgabor     * visitor; use Void if no return type is needed.
4497219019Sgabor     * @param <S> the type of the second argument (the first being the
4498219019Sgabor     * symbol itself) of the operation implemented by this visitor; use
4499219019Sgabor     * Void if a second argument is not needed.
4500219019Sgabor     */
4501219019Sgabor    public static abstract class DefaultSymbolVisitor<R,S> implements Symbol.Visitor<R,S> {
4502219019Sgabor        final public R visit(Symbol s, S arg)                   { return s.accept(this, arg); }
4503219019Sgabor        public R visitClassSymbol(ClassSymbol s, S arg)         { return visitSymbol(s, arg); }
4504219019Sgabor        public R visitMethodSymbol(MethodSymbol s, S arg)       { return visitSymbol(s, arg); }
4505219019Sgabor        public R visitOperatorSymbol(OperatorSymbol s, S arg)   { return visitSymbol(s, arg); }
4506219019Sgabor        public R visitPackageSymbol(PackageSymbol s, S arg)     { return visitSymbol(s, arg); }
4507219019Sgabor        public R visitTypeSymbol(TypeSymbol s, S arg)           { return visitSymbol(s, arg); }
4508219019Sgabor        public R visitVarSymbol(VarSymbol s, S arg)             { return visitSymbol(s, arg); }
4509219019Sgabor    }
4510219019Sgabor
4511219019Sgabor    /**
4512219019Sgabor     * A <em>simple</em> visitor for types.  This visitor is simple as
4513219019Sgabor     * captured wildcards, for-all types (generic methods), and
4514219019Sgabor     * undetermined type variables (part of inference) are hidden.
4515219019Sgabor     * Captured wildcards are hidden by treating them as type
4516219019Sgabor     * variables and the rest are hidden by visiting their qtypes.
4517219019Sgabor     *
4518219019Sgabor     * @param <R> the return type of the operation implemented by this
4519219019Sgabor     * visitor; use Void if no return type is needed.
4520219019Sgabor     * @param <S> the type of the second argument (the first being the
4521219019Sgabor     * type itself) of the operation implemented by this visitor; use
4522219019Sgabor     * Void if a second argument is not needed.
4523219019Sgabor     */
4524219019Sgabor    public static abstract class SimpleVisitor<R,S> extends DefaultTypeVisitor<R,S> {
4525219019Sgabor        @Override
4526219019Sgabor        public R visitCapturedType(CapturedType t, S s) {
4527219019Sgabor            return visitTypeVar(t, s);
4528219019Sgabor        }
4529219019Sgabor        @Override
4530219019Sgabor        public R visitForAll(ForAll t, S s) {
4531219019Sgabor            return visit(t.qtype, s);
4532219019Sgabor        }
4533219019Sgabor        @Override
4534219019Sgabor        public R visitUndetVar(UndetVar t, S s) {
4535219019Sgabor            return visit(t.qtype, s);
4536219019Sgabor        }
4537219019Sgabor    }
4538219019Sgabor
4539219019Sgabor    /**
4540219019Sgabor     * A plain relation on types.  That is a 2-ary function on the
4541219019Sgabor     * form Type&nbsp;&times;&nbsp;Type&nbsp;&rarr;&nbsp;Boolean.
4542219019Sgabor     * <!-- In plain text: Type x Type -> Boolean -->
4543219019Sgabor     */
4544219019Sgabor    public static abstract class TypeRelation extends SimpleVisitor<Boolean,Type> {}
4545219019Sgabor
4546219019Sgabor    /**
4547219019Sgabor     * A convenience visitor for implementing operations that only
4548219019Sgabor     * require one argument (the type itself), that is, unary
4549219019Sgabor     * operations.
4550219019Sgabor     *
4551219019Sgabor     * @param <R> the return type of the operation implemented by this
4552219019Sgabor     * visitor; use Void if no return type is needed.
4553219019Sgabor     */
4554219019Sgabor    public static abstract class UnaryVisitor<R> extends SimpleVisitor<R,Void> {
4555219019Sgabor        final public R visit(Type t) { return t.accept(this, null); }
4556219019Sgabor    }
4557219019Sgabor
4558219019Sgabor    /**
4559219019Sgabor     * A visitor for implementing a mapping from types to types.  The
4560219019Sgabor     * default behavior of this class is to implement the identity
4561219019Sgabor     * mapping (mapping a type to itself).  This can be overridden in
4562219019Sgabor     * subclasses.
4563219019Sgabor     *
4564219019Sgabor     * @param <S> the type of the second argument (the first being the
4565219019Sgabor     * type itself) of this mapping; use Void if a second argument is
4566219019Sgabor     * not needed.
4567219019Sgabor     */
4568219019Sgabor    public static class MapVisitor<S> extends DefaultTypeVisitor<Type,S> {
4569219019Sgabor        final public Type visit(Type t) { return t.accept(this, null); }
4570219019Sgabor        public Type visitType(Type t, S s) { return t; }
4571219019Sgabor    }
4572219019Sgabor    // </editor-fold>
4573219019Sgabor
4574219019Sgabor
4575219019Sgabor    // <editor-fold defaultstate="collapsed" desc="Annotation support">
4576219019Sgabor
4577219019Sgabor    public RetentionPolicy getRetention(Attribute.Compound a) {
4578219019Sgabor        return getRetention(a.type.tsym);
4579219019Sgabor    }
4580219019Sgabor
4581219019Sgabor    public RetentionPolicy getRetention(TypeSymbol sym) {
4582219019Sgabor        RetentionPolicy vis = RetentionPolicy.CLASS; // the default
4583219019Sgabor        Attribute.Compound c = sym.attribute(syms.retentionType.tsym);
4584219019Sgabor        if (c != null) {
4585219019Sgabor            Attribute value = c.member(names.value);
4586219019Sgabor            if (value != null && value instanceof Attribute.Enum) {
4587219019Sgabor                Name levelName = ((Attribute.Enum)value).value.name;
4588219019Sgabor                if (levelName == names.SOURCE) vis = RetentionPolicy.SOURCE;
4589219019Sgabor                else if (levelName == names.CLASS) vis = RetentionPolicy.CLASS;
4590219019Sgabor                else if (levelName == names.RUNTIME) vis = RetentionPolicy.RUNTIME;
4591219019Sgabor                else ;// /* fail soft */ throw new AssertionError(levelName);
4592219019Sgabor            }
4593219019Sgabor        }
4594219019Sgabor        return vis;
4595219019Sgabor    }
4596219019Sgabor    // </editor-fold>
4597219019Sgabor
4598219019Sgabor    // <editor-fold defaultstate="collapsed" desc="Signature Generation">
4599219019Sgabor
4600219019Sgabor    public static abstract class SignatureGenerator {
4601219019Sgabor
4602219019Sgabor        private final Types types;
4603219019Sgabor
4604219019Sgabor        protected abstract void append(char ch);
4605219019Sgabor        protected abstract void append(byte[] ba);
4606219019Sgabor        protected abstract void append(Name name);
4607219019Sgabor        protected void classReference(ClassSymbol c) { /* by default: no-op */ }
4608219019Sgabor
4609219019Sgabor        protected SignatureGenerator(Types types) {
4610219019Sgabor            this.types = types;
4611219019Sgabor        }
4612219019Sgabor
4613219019Sgabor        /**
4614219019Sgabor         * Assemble signature of given type in string buffer.
4615219019Sgabor         */
4616219019Sgabor        public void assembleSig(Type type) {
4617219019Sgabor            switch (type.getTag()) {
4618219019Sgabor                case BYTE:
4619219019Sgabor                    append('B');
4620219019Sgabor                    break;
4621219019Sgabor                case SHORT:
4622219019Sgabor                    append('S');
4623219019Sgabor                    break;
4624219019Sgabor                case CHAR:
4625219019Sgabor                    append('C');
4626219019Sgabor                    break;
4627219019Sgabor                case INT:
4628219019Sgabor                    append('I');
4629219019Sgabor                    break;
4630219019Sgabor                case LONG:
4631219019Sgabor                    append('J');
4632219019Sgabor                    break;
4633219019Sgabor                case FLOAT:
4634219019Sgabor                    append('F');
4635219019Sgabor                    break;
4636219019Sgabor                case DOUBLE:
4637219019Sgabor                    append('D');
4638219019Sgabor                    break;
4639219019Sgabor                case BOOLEAN:
4640219019Sgabor                    append('Z');
4641219019Sgabor                    break;
4642219019Sgabor                case VOID:
4643219019Sgabor                    append('V');
4644219019Sgabor                    break;
4645219019Sgabor                case CLASS:
4646219019Sgabor                    append('L');
4647219019Sgabor                    assembleClassSig(type);
4648219019Sgabor                    append(';');
4649219019Sgabor                    break;
4650219019Sgabor                case ARRAY:
4651219019Sgabor                    ArrayType at = (ArrayType) type;
4652219019Sgabor                    append('[');
4653219019Sgabor                    assembleSig(at.elemtype);
4654219019Sgabor                    break;
4655219019Sgabor                case METHOD:
4656219019Sgabor                    MethodType mt = (MethodType) type;
4657219019Sgabor                    append('(');
4658219019Sgabor                    assembleSig(mt.argtypes);
4659219019Sgabor                    append(')');
4660219019Sgabor                    assembleSig(mt.restype);
4661219019Sgabor                    if (hasTypeVar(mt.thrown)) {
4662219019Sgabor                        for (List<Type> l = mt.thrown; l.nonEmpty(); l = l.tail) {
4663219019Sgabor                            append('^');
4664219019Sgabor                            assembleSig(l.head);
4665219019Sgabor                        }
4666219019Sgabor                    }
4667219019Sgabor                    break;
4668219019Sgabor                case WILDCARD: {
4669219019Sgabor                    Type.WildcardType ta = (Type.WildcardType) type;
4670219019Sgabor                    switch (ta.kind) {
4671219019Sgabor                        case SUPER:
4672219019Sgabor                            append('-');
4673219019Sgabor                            assembleSig(ta.type);
4674219019Sgabor                            break;
4675219019Sgabor                        case EXTENDS:
4676219019Sgabor                            append('+');
4677219019Sgabor                            assembleSig(ta.type);
4678219019Sgabor                            break;
4679219019Sgabor                        case UNBOUND:
4680219019Sgabor                            append('*');
4681219019Sgabor                            break;
4682219019Sgabor                        default:
4683219019Sgabor                            throw new AssertionError(ta.kind);
4684219019Sgabor                    }
4685219019Sgabor                    break;
4686219019Sgabor                }
4687219019Sgabor                case TYPEVAR:
4688219019Sgabor                    append('T');
4689219019Sgabor                    append(type.tsym.name);
4690219019Sgabor                    append(';');
4691219019Sgabor                    break;
4692219019Sgabor                case FORALL:
4693219019Sgabor                    Type.ForAll ft = (Type.ForAll) type;
4694219019Sgabor                    assembleParamsSig(ft.tvars);
4695219019Sgabor                    assembleSig(ft.qtype);
4696219019Sgabor                    break;
4697219019Sgabor                default:
4698219019Sgabor                    throw new AssertionError("typeSig " + type.getTag());
4699219019Sgabor            }
4700219019Sgabor        }
4701219019Sgabor
4702219019Sgabor        public boolean hasTypeVar(List<Type> l) {
4703219019Sgabor            while (l.nonEmpty()) {
4704219019Sgabor                if (l.head.hasTag(TypeTag.TYPEVAR)) {
4705219019Sgabor                    return true;
4706219019Sgabor                }
4707219019Sgabor                l = l.tail;
4708219019Sgabor            }
4709219019Sgabor            return false;
4710219019Sgabor        }
4711219019Sgabor
4712219019Sgabor        public void assembleClassSig(Type type) {
4713219019Sgabor            ClassType ct = (ClassType) type;
4714219019Sgabor            ClassSymbol c = (ClassSymbol) ct.tsym;
4715219019Sgabor            classReference(c);
4716219019Sgabor            Type outer = ct.getEnclosingType();
4717219019Sgabor            if (outer.allparams().nonEmpty()) {
4718219019Sgabor                boolean rawOuter =
4719219019Sgabor                        c.owner.kind == MTH || // either a local class
4720219019Sgabor                        c.name == types.names.empty; // or anonymous
4721219019Sgabor                assembleClassSig(rawOuter
4722219019Sgabor                        ? types.erasure(outer)
4723219019Sgabor                        : outer);
4724219019Sgabor                append(rawOuter ? '$' : '.');
4725219019Sgabor                Assert.check(c.flatname.startsWith(c.owner.enclClass().flatname));
4726219019Sgabor                append(rawOuter
4727219019Sgabor                        ? c.flatname.subName(c.owner.enclClass().flatname.getByteLength() + 1, c.flatname.getByteLength())
4728219019Sgabor                        : c.name);
4729219019Sgabor            } else {
4730219019Sgabor                append(externalize(c.flatname));
4731219019Sgabor            }
4732219019Sgabor            if (ct.getTypeArguments().nonEmpty()) {
4733219019Sgabor                append('<');
4734219019Sgabor                assembleSig(ct.getTypeArguments());
4735219019Sgabor                append('>');
4736219019Sgabor            }
4737219019Sgabor        }
4738219019Sgabor
4739219019Sgabor        public void assembleParamsSig(List<Type> typarams) {
4740219019Sgabor            append('<');
4741219019Sgabor            for (List<Type> ts = typarams; ts.nonEmpty(); ts = ts.tail) {
4742219019Sgabor                Type.TypeVar tvar = (Type.TypeVar) ts.head;
4743219019Sgabor                append(tvar.tsym.name);
4744219019Sgabor                List<Type> bounds = types.getBounds(tvar);
4745219019Sgabor                if ((bounds.head.tsym.flags() & INTERFACE) != 0) {
4746219019Sgabor                    append(':');
4747219019Sgabor                }
4748219019Sgabor                for (List<Type> l = bounds; l.nonEmpty(); l = l.tail) {
4749219019Sgabor                    append(':');
4750219019Sgabor                    assembleSig(l.head);
4751219019Sgabor                }
4752219019Sgabor            }
4753219019Sgabor            append('>');
4754219019Sgabor        }
4755219019Sgabor
4756219019Sgabor        private void assembleSig(List<Type> types) {
4757219019Sgabor            for (List<Type> ts = types; ts.nonEmpty(); ts = ts.tail) {
4758219019Sgabor                assembleSig(ts.head);
4759219019Sgabor            }
4760219019Sgabor        }
4761219019Sgabor    }
4762219019Sgabor    // </editor-fold>
4763219019Sgabor
4764219019Sgabor    public void newRound() {
4765219019Sgabor        descCache._map.clear();
4766219019Sgabor        isDerivedRawCache.clear();
4767219019Sgabor        implCache._map.clear();
4768219019Sgabor        membersCache._map.clear();
4769219019Sgabor        closureCache.clear();
4770219019Sgabor    }
4771219019Sgabor}
4772219019Sgabor