Types.java revision 3735:85a8bfb00296
1/*
2 * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package com.sun.tools.javac.code;
27
28import java.lang.ref.SoftReference;
29import java.util.HashSet;
30import java.util.HashMap;
31import java.util.Locale;
32import java.util.Map;
33import java.util.Optional;
34import java.util.Set;
35import java.util.WeakHashMap;
36import java.util.function.BiPredicate;
37import java.util.stream.Collector;
38
39import javax.tools.JavaFileObject;
40
41import com.sun.tools.javac.code.Attribute.RetentionPolicy;
42import com.sun.tools.javac.code.Lint.LintCategory;
43import com.sun.tools.javac.code.Type.UndetVar.InferenceBound;
44import com.sun.tools.javac.code.TypeMetadata.Entry.Kind;
45import com.sun.tools.javac.comp.AttrContext;
46import com.sun.tools.javac.comp.Check;
47import com.sun.tools.javac.comp.Enter;
48import com.sun.tools.javac.comp.Env;
49import com.sun.tools.javac.util.*;
50
51import static com.sun.tools.javac.code.BoundKind.*;
52import static com.sun.tools.javac.code.Flags.*;
53import static com.sun.tools.javac.code.Kinds.Kind.*;
54import static com.sun.tools.javac.code.Scope.*;
55import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE;
56import static com.sun.tools.javac.code.Symbol.*;
57import static com.sun.tools.javac.code.Type.*;
58import static com.sun.tools.javac.code.TypeTag.*;
59import static com.sun.tools.javac.jvm.ClassFile.externalize;
60
61/**
62 * Utility class containing various operations on types.
63 *
64 * <p>Unless other names are more illustrative, the following naming
65 * conventions should be observed in this file:
66 *
67 * <dl>
68 * <dt>t</dt>
69 * <dd>If the first argument to an operation is a type, it should be named t.</dd>
70 * <dt>s</dt>
71 * <dd>Similarly, if the second argument to an operation is a type, it should be named s.</dd>
72 * <dt>ts</dt>
73 * <dd>If an operations takes a list of types, the first should be named ts.</dd>
74 * <dt>ss</dt>
75 * <dd>A second list of types should be named ss.</dd>
76 * </dl>
77 *
78 * <p><b>This is NOT part of any supported API.
79 * If you write code that depends on this, you do so at your own risk.
80 * This code and its internal interfaces are subject to change or
81 * deletion without notice.</b>
82 */
83public class Types {
84    protected static final Context.Key<Types> typesKey = new Context.Key<>();
85
86    final Symtab syms;
87    final JavacMessages messages;
88    final Names names;
89    final boolean allowObjectToPrimitiveCast;
90    final boolean allowDefaultMethods;
91    final Check chk;
92    final Enter enter;
93    JCDiagnostic.Factory diags;
94    List<Warner> warnStack = List.nil();
95    final Name capturedName;
96    private final FunctionDescriptorLookupError functionDescriptorLookupError;
97
98    public final Warner noWarnings;
99
100    // <editor-fold defaultstate="collapsed" desc="Instantiating">
101    public static Types instance(Context context) {
102        Types instance = context.get(typesKey);
103        if (instance == null)
104            instance = new Types(context);
105        return instance;
106    }
107
108    protected Types(Context context) {
109        context.put(typesKey, this);
110        syms = Symtab.instance(context);
111        names = Names.instance(context);
112        Source source = Source.instance(context);
113        allowObjectToPrimitiveCast = source.allowObjectToPrimitiveCast();
114        allowDefaultMethods = source.allowDefaultMethods();
115        chk = Check.instance(context);
116        enter = Enter.instance(context);
117        capturedName = names.fromString("<captured wildcard>");
118        messages = JavacMessages.instance(context);
119        diags = JCDiagnostic.Factory.instance(context);
120        functionDescriptorLookupError = new FunctionDescriptorLookupError();
121        noWarnings = new Warner(null);
122    }
123    // </editor-fold>
124
125    // <editor-fold defaultstate="collapsed" desc="bounds">
126    /**
127     * Get a wildcard's upper bound, returning non-wildcards unchanged.
128     * @param t a type argument, either a wildcard or a type
129     */
130    public Type wildUpperBound(Type t) {
131        if (t.hasTag(WILDCARD)) {
132            WildcardType w = (WildcardType) t;
133            if (w.isSuperBound())
134                return w.bound == null ? syms.objectType : w.bound.bound;
135            else
136                return wildUpperBound(w.type);
137        }
138        else return t;
139    }
140
141    /**
142     * Get a capture variable's upper bound, returning other types unchanged.
143     * @param t a type
144     */
145    public Type cvarUpperBound(Type t) {
146        if (t.hasTag(TYPEVAR)) {
147            TypeVar v = (TypeVar) t;
148            return v.isCaptured() ? cvarUpperBound(v.bound) : v;
149        }
150        else return t;
151    }
152
153    /**
154     * Get a wildcard's lower bound, returning non-wildcards unchanged.
155     * @param t a type argument, either a wildcard or a type
156     */
157    public Type wildLowerBound(Type t) {
158        if (t.hasTag(WILDCARD)) {
159            WildcardType w = (WildcardType) t;
160            return w.isExtendsBound() ? syms.botType : wildLowerBound(w.type);
161        }
162        else return t;
163    }
164
165    /**
166     * Get a capture variable's lower bound, returning other types unchanged.
167     * @param t a type
168     */
169    public Type cvarLowerBound(Type t) {
170        if (t.hasTag(TYPEVAR) && ((TypeVar) t).isCaptured()) {
171            return cvarLowerBound(t.getLowerBound());
172        }
173        else return t;
174    }
175
176    /**
177     * Recursively skip type-variables until a class/array type is found; capture conversion is then
178     * (optionally) applied to the resulting type. This is useful for i.e. computing a site that is
179     * suitable for a method lookup.
180     */
181    public Type skipTypeVars(Type site, boolean capture) {
182        while (site.hasTag(TYPEVAR)) {
183            site = site.getUpperBound();
184        }
185        return capture ? capture(site) : site;
186    }
187    // </editor-fold>
188
189    // <editor-fold defaultstate="collapsed" desc="isUnbounded">
190    /**
191     * Checks that all the arguments to a class are unbounded
192     * wildcards or something else that doesn't make any restrictions
193     * on the arguments. If a class isUnbounded, a raw super- or
194     * subclass can be cast to it without a warning.
195     * @param t a type
196     * @return true iff the given type is unbounded or raw
197     */
198    public boolean isUnbounded(Type t) {
199        return isUnbounded.visit(t);
200    }
201    // where
202        private final UnaryVisitor<Boolean> isUnbounded = new UnaryVisitor<Boolean>() {
203
204            public Boolean visitType(Type t, Void ignored) {
205                return true;
206            }
207
208            @Override
209            public Boolean visitClassType(ClassType t, Void ignored) {
210                List<Type> parms = t.tsym.type.allparams();
211                List<Type> args = t.allparams();
212                while (parms.nonEmpty()) {
213                    WildcardType unb = new WildcardType(syms.objectType,
214                                                        BoundKind.UNBOUND,
215                                                        syms.boundClass,
216                                                        (TypeVar)parms.head);
217                    if (!containsType(args.head, unb))
218                        return false;
219                    parms = parms.tail;
220                    args = args.tail;
221                }
222                return true;
223            }
224        };
225    // </editor-fold>
226
227    // <editor-fold defaultstate="collapsed" desc="asSub">
228    /**
229     * Return the least specific subtype of t that starts with symbol
230     * sym.  If none exists, return null.  The least specific subtype
231     * is determined as follows:
232     *
233     * <p>If there is exactly one parameterized instance of sym that is a
234     * subtype of t, that parameterized instance is returned.<br>
235     * Otherwise, if the plain type or raw type `sym' is a subtype of
236     * type t, the type `sym' itself is returned.  Otherwise, null is
237     * returned.
238     */
239    public Type asSub(Type t, Symbol sym) {
240        return asSub.visit(t, sym);
241    }
242    // where
243        private final SimpleVisitor<Type,Symbol> asSub = new SimpleVisitor<Type,Symbol>() {
244
245            public Type visitType(Type t, Symbol sym) {
246                return null;
247            }
248
249            @Override
250            public Type visitClassType(ClassType t, Symbol sym) {
251                if (t.tsym == sym)
252                    return t;
253                Type base = asSuper(sym.type, t.tsym);
254                if (base == null)
255                    return null;
256                ListBuffer<Type> from = new ListBuffer<>();
257                ListBuffer<Type> to = new ListBuffer<>();
258                try {
259                    adapt(base, t, from, to);
260                } catch (AdaptFailure ex) {
261                    return null;
262                }
263                Type res = subst(sym.type, from.toList(), to.toList());
264                if (!isSubtype(res, t))
265                    return null;
266                ListBuffer<Type> openVars = new ListBuffer<>();
267                for (List<Type> l = sym.type.allparams();
268                     l.nonEmpty(); l = l.tail)
269                    if (res.contains(l.head) && !t.contains(l.head))
270                        openVars.append(l.head);
271                if (openVars.nonEmpty()) {
272                    if (t.isRaw()) {
273                        // The subtype of a raw type is raw
274                        res = erasure(res);
275                    } else {
276                        // Unbound type arguments default to ?
277                        List<Type> opens = openVars.toList();
278                        ListBuffer<Type> qs = new ListBuffer<>();
279                        for (List<Type> iter = opens; iter.nonEmpty(); iter = iter.tail) {
280                            qs.append(new WildcardType(syms.objectType, BoundKind.UNBOUND,
281                                                       syms.boundClass, (TypeVar) iter.head));
282                        }
283                        res = subst(res, opens, qs.toList());
284                    }
285                }
286                return res;
287            }
288
289            @Override
290            public Type visitErrorType(ErrorType t, Symbol sym) {
291                return t;
292            }
293        };
294    // </editor-fold>
295
296    // <editor-fold defaultstate="collapsed" desc="isConvertible">
297    /**
298     * Is t a subtype of or convertible via boxing/unboxing
299     * conversion to s?
300     */
301    public boolean isConvertible(Type t, Type s, Warner warn) {
302        if (t.hasTag(ERROR)) {
303            return true;
304        }
305        boolean tPrimitive = t.isPrimitive();
306        boolean sPrimitive = s.isPrimitive();
307        if (tPrimitive == sPrimitive) {
308            return isSubtypeUnchecked(t, s, warn);
309        }
310        return tPrimitive
311            ? isSubtype(boxedClass(t).type, s)
312            : isSubtype(unboxedType(t), s);
313    }
314
315    /**
316     * Is t a subtype of or convertible via boxing/unboxing
317     * conversions to s?
318     */
319    public boolean isConvertible(Type t, Type s) {
320        return isConvertible(t, s, noWarnings);
321    }
322    // </editor-fold>
323
324    // <editor-fold defaultstate="collapsed" desc="findSam">
325
326    /**
327     * Exception used to report a function descriptor lookup failure. The exception
328     * wraps a diagnostic that can be used to generate more details error
329     * messages.
330     */
331    public static class FunctionDescriptorLookupError extends RuntimeException {
332        private static final long serialVersionUID = 0;
333
334        JCDiagnostic diagnostic;
335
336        FunctionDescriptorLookupError() {
337            this.diagnostic = null;
338        }
339
340        FunctionDescriptorLookupError setMessage(JCDiagnostic diag) {
341            this.diagnostic = diag;
342            return this;
343        }
344
345        public JCDiagnostic getDiagnostic() {
346            return diagnostic;
347        }
348    }
349
350    /**
351     * A cache that keeps track of function descriptors associated with given
352     * functional interfaces.
353     */
354    class DescriptorCache {
355
356        private WeakHashMap<TypeSymbol, Entry> _map = new WeakHashMap<>();
357
358        class FunctionDescriptor {
359            Symbol descSym;
360
361            FunctionDescriptor(Symbol descSym) {
362                this.descSym = descSym;
363            }
364
365            public Symbol getSymbol() {
366                return descSym;
367            }
368
369            public Type getType(Type site) {
370                site = removeWildcards(site);
371                if (!chk.checkValidGenericType(site)) {
372                    //if the inferred functional interface type is not well-formed,
373                    //or if it's not a subtype of the original target, issue an error
374                    throw failure(diags.fragment("no.suitable.functional.intf.inst", site));
375                }
376                return memberType(site, descSym);
377            }
378        }
379
380        class Entry {
381            final FunctionDescriptor cachedDescRes;
382            final int prevMark;
383
384            public Entry(FunctionDescriptor cachedDescRes,
385                    int prevMark) {
386                this.cachedDescRes = cachedDescRes;
387                this.prevMark = prevMark;
388            }
389
390            boolean matches(int mark) {
391                return  this.prevMark == mark;
392            }
393        }
394
395        FunctionDescriptor get(TypeSymbol origin) throws FunctionDescriptorLookupError {
396            Entry e = _map.get(origin);
397            CompoundScope members = membersClosure(origin.type, false);
398            if (e == null ||
399                    !e.matches(members.getMark())) {
400                FunctionDescriptor descRes = findDescriptorInternal(origin, members);
401                _map.put(origin, new Entry(descRes, members.getMark()));
402                return descRes;
403            }
404            else {
405                return e.cachedDescRes;
406            }
407        }
408
409        /**
410         * Compute the function descriptor associated with a given functional interface
411         */
412        public FunctionDescriptor findDescriptorInternal(TypeSymbol origin,
413                CompoundScope membersCache) throws FunctionDescriptorLookupError {
414            if (!origin.isInterface() || (origin.flags() & ANNOTATION) != 0) {
415                //t must be an interface
416                throw failure("not.a.functional.intf", origin);
417            }
418
419            final ListBuffer<Symbol> abstracts = new ListBuffer<>();
420            for (Symbol sym : membersCache.getSymbols(new DescriptorFilter(origin))) {
421                Type mtype = memberType(origin.type, sym);
422                if (abstracts.isEmpty()) {
423                    abstracts.append(sym);
424                } else if ((sym.name == abstracts.first().name &&
425                        overrideEquivalent(mtype, memberType(origin.type, abstracts.first())))) {
426                    if (!abstracts.stream().filter(msym -> msym.owner.isSubClass(sym.enclClass(), Types.this))
427                            .map(msym -> memberType(origin.type, msym))
428                            .anyMatch(abstractMType -> isSubSignature(abstractMType, mtype))) {
429                        abstracts.append(sym);
430                    }
431                } else {
432                    //the target method(s) should be the only abstract members of t
433                    throw failure("not.a.functional.intf.1",  origin,
434                            diags.fragment("incompatible.abstracts", Kinds.kindName(origin), origin));
435                }
436            }
437            if (abstracts.isEmpty()) {
438                //t must define a suitable non-generic method
439                throw failure("not.a.functional.intf.1", origin,
440                            diags.fragment("no.abstracts", Kinds.kindName(origin), origin));
441            } else if (abstracts.size() == 1) {
442                return new FunctionDescriptor(abstracts.first());
443            } else { // size > 1
444                FunctionDescriptor descRes = mergeDescriptors(origin, abstracts.toList());
445                if (descRes == null) {
446                    //we can get here if the functional interface is ill-formed
447                    ListBuffer<JCDiagnostic> descriptors = new ListBuffer<>();
448                    for (Symbol desc : abstracts) {
449                        String key = desc.type.getThrownTypes().nonEmpty() ?
450                                "descriptor.throws" : "descriptor";
451                        descriptors.append(diags.fragment(key, desc.name,
452                                desc.type.getParameterTypes(),
453                                desc.type.getReturnType(),
454                                desc.type.getThrownTypes()));
455                    }
456                    JCDiagnostic.MultilineDiagnostic incompatibleDescriptors =
457                            new JCDiagnostic.MultilineDiagnostic(diags.fragment("incompatible.descs.in.functional.intf",
458                            Kinds.kindName(origin), origin), descriptors.toList());
459                    throw failure(incompatibleDescriptors);
460                }
461                return descRes;
462            }
463        }
464
465        /**
466         * Compute a synthetic type for the target descriptor given a list
467         * of override-equivalent methods in the functional interface type.
468         * The resulting method type is a method type that is override-equivalent
469         * and return-type substitutable with each method in the original list.
470         */
471        private FunctionDescriptor mergeDescriptors(TypeSymbol origin, List<Symbol> methodSyms) {
472            return mergeAbstracts(methodSyms, origin.type, false)
473                    .map(bestSoFar -> new FunctionDescriptor(bestSoFar.baseSymbol()) {
474                        @Override
475                        public Type getType(Type origin) {
476                            Type mt = memberType(origin, getSymbol());
477                            return createMethodTypeWithThrown(mt, bestSoFar.type.getThrownTypes());
478                        }
479                    }).orElse(null);
480        }
481
482        FunctionDescriptorLookupError failure(String msg, Object... args) {
483            return failure(diags.fragment(msg, args));
484        }
485
486        FunctionDescriptorLookupError failure(JCDiagnostic diag) {
487            return functionDescriptorLookupError.setMessage(diag);
488        }
489    }
490
491    private DescriptorCache descCache = new DescriptorCache();
492
493    /**
494     * Find the method descriptor associated to this class symbol - if the
495     * symbol 'origin' is not a functional interface, an exception is thrown.
496     */
497    public Symbol findDescriptorSymbol(TypeSymbol origin) throws FunctionDescriptorLookupError {
498        return descCache.get(origin).getSymbol();
499    }
500
501    /**
502     * Find the type of the method descriptor associated to this class symbol -
503     * if the symbol 'origin' is not a functional interface, an exception is thrown.
504     */
505    public Type findDescriptorType(Type origin) throws FunctionDescriptorLookupError {
506        return descCache.get(origin.tsym).getType(origin);
507    }
508
509    /**
510     * Is given type a functional interface?
511     */
512    public boolean isFunctionalInterface(TypeSymbol tsym) {
513        try {
514            findDescriptorSymbol(tsym);
515            return true;
516        } catch (FunctionDescriptorLookupError ex) {
517            return false;
518        }
519    }
520
521    public boolean isFunctionalInterface(Type site) {
522        try {
523            findDescriptorType(site);
524            return true;
525        } catch (FunctionDescriptorLookupError ex) {
526            return false;
527        }
528    }
529
530    public Type removeWildcards(Type site) {
531        if (site.getTypeArguments().stream().anyMatch(t -> t.hasTag(WILDCARD))) {
532            //compute non-wildcard parameterization - JLS 9.9
533            List<Type> actuals = site.getTypeArguments();
534            List<Type> formals = site.tsym.type.getTypeArguments();
535            ListBuffer<Type> targs = new ListBuffer<>();
536            for (Type formal : formals) {
537                Type actual = actuals.head;
538                Type bound = formal.getUpperBound();
539                if (actuals.head.hasTag(WILDCARD)) {
540                    WildcardType wt = (WildcardType)actual;
541                    //check that bound does not contain other formals
542                    if (bound.containsAny(formals)) {
543                        targs.add(wt.type);
544                    } else {
545                        //compute new type-argument based on declared bound and wildcard bound
546                        switch (wt.kind) {
547                            case UNBOUND:
548                                targs.add(bound);
549                                break;
550                            case EXTENDS:
551                                targs.add(glb(bound, wt.type));
552                                break;
553                            case SUPER:
554                                targs.add(wt.type);
555                                break;
556                            default:
557                                Assert.error("Cannot get here!");
558                        }
559                    }
560                } else {
561                    //not a wildcard - the new type argument remains unchanged
562                    targs.add(actual);
563                }
564                actuals = actuals.tail;
565            }
566            return subst(site.tsym.type, formals, targs.toList());
567        } else {
568            return site;
569        }
570    }
571
572    /**
573     * Create a symbol for a class that implements a given functional interface
574     * and overrides its functional descriptor. This routine is used for two
575     * main purposes: (i) checking well-formedness of a functional interface;
576     * (ii) perform functional interface bridge calculation.
577     */
578    public ClassSymbol makeFunctionalInterfaceClass(Env<AttrContext> env, Name name, List<Type> targets, long cflags) {
579        if (targets.isEmpty()) {
580            return null;
581        }
582        Symbol descSym = findDescriptorSymbol(targets.head.tsym);
583        Type descType = findDescriptorType(targets.head);
584        ClassSymbol csym = new ClassSymbol(cflags, name, env.enclClass.sym.outermostClass());
585        csym.completer = Completer.NULL_COMPLETER;
586        csym.members_field = WriteableScope.create(csym);
587        MethodSymbol instDescSym = new MethodSymbol(descSym.flags(), descSym.name, descType, csym);
588        csym.members_field.enter(instDescSym);
589        Type.ClassType ctype = new Type.ClassType(Type.noType, List.<Type>nil(), csym);
590        ctype.supertype_field = syms.objectType;
591        ctype.interfaces_field = targets;
592        csym.type = ctype;
593        csym.sourcefile = ((ClassSymbol)csym.owner).sourcefile;
594        return csym;
595    }
596
597    /**
598     * Find the minimal set of methods that are overridden by the functional
599     * descriptor in 'origin'. All returned methods are assumed to have different
600     * erased signatures.
601     */
602    public List<Symbol> functionalInterfaceBridges(TypeSymbol origin) {
603        Assert.check(isFunctionalInterface(origin));
604        Symbol descSym = findDescriptorSymbol(origin);
605        CompoundScope members = membersClosure(origin.type, false);
606        ListBuffer<Symbol> overridden = new ListBuffer<>();
607        outer: for (Symbol m2 : members.getSymbolsByName(descSym.name, bridgeFilter)) {
608            if (m2 == descSym) continue;
609            else if (descSym.overrides(m2, origin, Types.this, false)) {
610                for (Symbol m3 : overridden) {
611                    if (isSameType(m3.erasure(Types.this), m2.erasure(Types.this)) ||
612                            (m3.overrides(m2, origin, Types.this, false) &&
613                            (pendingBridges((ClassSymbol)origin, m3.enclClass()) ||
614                            (((MethodSymbol)m2).binaryImplementation((ClassSymbol)m3.owner, Types.this) != null)))) {
615                        continue outer;
616                    }
617                }
618                overridden.add(m2);
619            }
620        }
621        return overridden.toList();
622    }
623    //where
624        private Filter<Symbol> bridgeFilter = new Filter<Symbol>() {
625            public boolean accepts(Symbol t) {
626                return t.kind == MTH &&
627                        t.name != names.init &&
628                        t.name != names.clinit &&
629                        (t.flags() & SYNTHETIC) == 0;
630            }
631        };
632        private boolean pendingBridges(ClassSymbol origin, TypeSymbol s) {
633            //a symbol will be completed from a classfile if (a) symbol has
634            //an associated file object with CLASS kind and (b) the symbol has
635            //not been entered
636            if (origin.classfile != null &&
637                    origin.classfile.getKind() == JavaFileObject.Kind.CLASS &&
638                    enter.getEnv(origin) == null) {
639                return false;
640            }
641            if (origin == s) {
642                return true;
643            }
644            for (Type t : interfaces(origin.type)) {
645                if (pendingBridges((ClassSymbol)t.tsym, s)) {
646                    return true;
647                }
648            }
649            return false;
650        }
651    // </editor-fold>
652
653   /**
654    * Scope filter used to skip methods that should be ignored (such as methods
655    * overridden by j.l.Object) during function interface conversion interface check
656    */
657    class DescriptorFilter implements Filter<Symbol> {
658
659       TypeSymbol origin;
660
661       DescriptorFilter(TypeSymbol origin) {
662           this.origin = origin;
663       }
664
665       @Override
666       public boolean accepts(Symbol sym) {
667           return sym.kind == MTH &&
668                   (sym.flags() & (ABSTRACT | DEFAULT)) == ABSTRACT &&
669                   !overridesObjectMethod(origin, sym) &&
670                   (interfaceCandidates(origin.type, (MethodSymbol)sym).head.flags() & DEFAULT) == 0;
671       }
672    }
673
674    // <editor-fold defaultstate="collapsed" desc="isSubtype">
675    /**
676     * Is t an unchecked subtype of s?
677     */
678    public boolean isSubtypeUnchecked(Type t, Type s) {
679        return isSubtypeUnchecked(t, s, noWarnings);
680    }
681    /**
682     * Is t an unchecked subtype of s?
683     */
684    public boolean isSubtypeUnchecked(Type t, Type s, Warner warn) {
685        boolean result = isSubtypeUncheckedInternal(t, s, true, warn);
686        if (result) {
687            checkUnsafeVarargsConversion(t, s, warn);
688        }
689        return result;
690    }
691    //where
692        private boolean isSubtypeUncheckedInternal(Type t, Type s, boolean capture, Warner warn) {
693            if (t.hasTag(ARRAY) && s.hasTag(ARRAY)) {
694                if (((ArrayType)t).elemtype.isPrimitive()) {
695                    return isSameType(elemtype(t), elemtype(s));
696                } else {
697                    return isSubtypeUncheckedInternal(elemtype(t), elemtype(s), false, warn);
698                }
699            } else if (isSubtype(t, s, capture)) {
700                return true;
701            } else if (t.hasTag(TYPEVAR)) {
702                return isSubtypeUncheckedInternal(t.getUpperBound(), s, false, warn);
703            } else if (!s.isRaw()) {
704                Type t2 = asSuper(t, s.tsym);
705                if (t2 != null && t2.isRaw()) {
706                    if (isReifiable(s)) {
707                        warn.silentWarn(LintCategory.UNCHECKED);
708                    } else {
709                        warn.warn(LintCategory.UNCHECKED);
710                    }
711                    return true;
712                }
713            }
714            return false;
715        }
716
717        private void checkUnsafeVarargsConversion(Type t, Type s, Warner warn) {
718            if (!t.hasTag(ARRAY) || isReifiable(t)) {
719                return;
720            }
721            ArrayType from = (ArrayType)t;
722            boolean shouldWarn = false;
723            switch (s.getTag()) {
724                case ARRAY:
725                    ArrayType to = (ArrayType)s;
726                    shouldWarn = from.isVarargs() &&
727                            !to.isVarargs() &&
728                            !isReifiable(from);
729                    break;
730                case CLASS:
731                    shouldWarn = from.isVarargs();
732                    break;
733            }
734            if (shouldWarn) {
735                warn.warn(LintCategory.VARARGS);
736            }
737        }
738
739    /**
740     * Is t a subtype of s?<br>
741     * (not defined for Method and ForAll types)
742     */
743    final public boolean isSubtype(Type t, Type s) {
744        return isSubtype(t, s, true);
745    }
746    final public boolean isSubtypeNoCapture(Type t, Type s) {
747        return isSubtype(t, s, false);
748    }
749    public boolean isSubtype(Type t, Type s, boolean capture) {
750        if (t.equalsIgnoreMetadata(s))
751            return true;
752        if (s.isPartial())
753            return isSuperType(s, t);
754
755        if (s.isCompound()) {
756            for (Type s2 : interfaces(s).prepend(supertype(s))) {
757                if (!isSubtype(t, s2, capture))
758                    return false;
759            }
760            return true;
761        }
762
763        // Generally, if 's' is a lower-bounded type variable, recur on lower bound; but
764        // for inference variables and intersections, we need to keep 's'
765        // (see JLS 4.10.2 for intersections and 18.2.3 for inference vars)
766        if (!t.hasTag(UNDETVAR) && !t.isCompound()) {
767            // TODO: JDK-8039198, bounds checking sometimes passes in a wildcard as s
768            Type lower = cvarLowerBound(wildLowerBound(s));
769            if (s != lower && !lower.hasTag(BOT))
770                return isSubtype(capture ? capture(t) : t, lower, false);
771        }
772
773        return isSubtype.visit(capture ? capture(t) : t, s);
774    }
775    // where
776        private TypeRelation isSubtype = new TypeRelation()
777        {
778            @Override
779            public Boolean visitType(Type t, Type s) {
780                switch (t.getTag()) {
781                 case BYTE:
782                     return (!s.hasTag(CHAR) && t.getTag().isSubRangeOf(s.getTag()));
783                 case CHAR:
784                     return (!s.hasTag(SHORT) && t.getTag().isSubRangeOf(s.getTag()));
785                 case SHORT: case INT: case LONG:
786                 case FLOAT: case DOUBLE:
787                     return t.getTag().isSubRangeOf(s.getTag());
788                 case BOOLEAN: case VOID:
789                     return t.hasTag(s.getTag());
790                 case TYPEVAR:
791                     return isSubtypeNoCapture(t.getUpperBound(), s);
792                 case BOT:
793                     return
794                         s.hasTag(BOT) || s.hasTag(CLASS) ||
795                         s.hasTag(ARRAY) || s.hasTag(TYPEVAR);
796                 case WILDCARD: //we shouldn't be here - avoids crash (see 7034495)
797                 case NONE:
798                     return false;
799                 default:
800                     throw new AssertionError("isSubtype " + t.getTag());
801                 }
802            }
803
804            private Set<TypePair> cache = new HashSet<>();
805
806            private boolean containsTypeRecursive(Type t, Type s) {
807                TypePair pair = new TypePair(t, s);
808                if (cache.add(pair)) {
809                    try {
810                        return containsType(t.getTypeArguments(),
811                                            s.getTypeArguments());
812                    } finally {
813                        cache.remove(pair);
814                    }
815                } else {
816                    return containsType(t.getTypeArguments(),
817                                        rewriteSupers(s).getTypeArguments());
818                }
819            }
820
821            private Type rewriteSupers(Type t) {
822                if (!t.isParameterized())
823                    return t;
824                ListBuffer<Type> from = new ListBuffer<>();
825                ListBuffer<Type> to = new ListBuffer<>();
826                adaptSelf(t, from, to);
827                if (from.isEmpty())
828                    return t;
829                ListBuffer<Type> rewrite = new ListBuffer<>();
830                boolean changed = false;
831                for (Type orig : to.toList()) {
832                    Type s = rewriteSupers(orig);
833                    if (s.isSuperBound() && !s.isExtendsBound()) {
834                        s = new WildcardType(syms.objectType,
835                                             BoundKind.UNBOUND,
836                                             syms.boundClass,
837                                             s.getMetadata());
838                        changed = true;
839                    } else if (s != orig) {
840                        s = new WildcardType(wildUpperBound(s),
841                                             BoundKind.EXTENDS,
842                                             syms.boundClass,
843                                             s.getMetadata());
844                        changed = true;
845                    }
846                    rewrite.append(s);
847                }
848                if (changed)
849                    return subst(t.tsym.type, from.toList(), rewrite.toList());
850                else
851                    return t;
852            }
853
854            @Override
855            public Boolean visitClassType(ClassType t, Type s) {
856                Type sup = asSuper(t, s.tsym);
857                if (sup == null) return false;
858                // If t is an intersection, sup might not be a class type
859                if (!sup.hasTag(CLASS)) return isSubtypeNoCapture(sup, s);
860                return sup.tsym == s.tsym
861                     // Check type variable containment
862                    && (!s.isParameterized() || containsTypeRecursive(s, sup))
863                    && isSubtypeNoCapture(sup.getEnclosingType(),
864                                          s.getEnclosingType());
865            }
866
867            @Override
868            public Boolean visitArrayType(ArrayType t, Type s) {
869                if (s.hasTag(ARRAY)) {
870                    if (t.elemtype.isPrimitive())
871                        return isSameType(t.elemtype, elemtype(s));
872                    else
873                        return isSubtypeNoCapture(t.elemtype, elemtype(s));
874                }
875
876                if (s.hasTag(CLASS)) {
877                    Name sname = s.tsym.getQualifiedName();
878                    return sname == names.java_lang_Object
879                        || sname == names.java_lang_Cloneable
880                        || sname == names.java_io_Serializable;
881                }
882
883                return false;
884            }
885
886            @Override
887            public Boolean visitUndetVar(UndetVar t, Type s) {
888                //todo: test against origin needed? or replace with substitution?
889                if (t == s || t.qtype == s || s.hasTag(ERROR) || s.hasTag(UNKNOWN)) {
890                    return true;
891                } else if (s.hasTag(BOT)) {
892                    //if 's' is 'null' there's no instantiated type U for which
893                    //U <: s (but 'null' itself, which is not a valid type)
894                    return false;
895                }
896
897                t.addBound(InferenceBound.UPPER, s, Types.this);
898                return true;
899            }
900
901            @Override
902            public Boolean visitErrorType(ErrorType t, Type s) {
903                return true;
904            }
905        };
906
907    /**
908     * Is t a subtype of every type in given list `ts'?<br>
909     * (not defined for Method and ForAll types)<br>
910     * Allows unchecked conversions.
911     */
912    public boolean isSubtypeUnchecked(Type t, List<Type> ts, Warner warn) {
913        for (List<Type> l = ts; l.nonEmpty(); l = l.tail)
914            if (!isSubtypeUnchecked(t, l.head, warn))
915                return false;
916        return true;
917    }
918
919    /**
920     * Are corresponding elements of ts subtypes of ss?  If lists are
921     * of different length, return false.
922     */
923    public boolean isSubtypes(List<Type> ts, List<Type> ss) {
924        while (ts.tail != null && ss.tail != null
925               /*inlined: ts.nonEmpty() && ss.nonEmpty()*/ &&
926               isSubtype(ts.head, ss.head)) {
927            ts = ts.tail;
928            ss = ss.tail;
929        }
930        return ts.tail == null && ss.tail == null;
931        /*inlined: ts.isEmpty() && ss.isEmpty();*/
932    }
933
934    /**
935     * Are corresponding elements of ts subtypes of ss, allowing
936     * unchecked conversions?  If lists are of different length,
937     * return false.
938     **/
939    public boolean isSubtypesUnchecked(List<Type> ts, List<Type> ss, Warner warn) {
940        while (ts.tail != null && ss.tail != null
941               /*inlined: ts.nonEmpty() && ss.nonEmpty()*/ &&
942               isSubtypeUnchecked(ts.head, ss.head, warn)) {
943            ts = ts.tail;
944            ss = ss.tail;
945        }
946        return ts.tail == null && ss.tail == null;
947        /*inlined: ts.isEmpty() && ss.isEmpty();*/
948    }
949    // </editor-fold>
950
951    // <editor-fold defaultstate="collapsed" desc="isSuperType">
952    /**
953     * Is t a supertype of s?
954     */
955    public boolean isSuperType(Type t, Type s) {
956        switch (t.getTag()) {
957        case ERROR:
958            return true;
959        case UNDETVAR: {
960            UndetVar undet = (UndetVar)t;
961            if (t == s ||
962                undet.qtype == s ||
963                s.hasTag(ERROR) ||
964                s.hasTag(BOT)) {
965                return true;
966            }
967            undet.addBound(InferenceBound.LOWER, s, this);
968            return true;
969        }
970        default:
971            return isSubtype(s, t);
972        }
973    }
974    // </editor-fold>
975
976    // <editor-fold defaultstate="collapsed" desc="isSameType">
977    /**
978     * Are corresponding elements of the lists the same type?  If
979     * lists are of different length, return false.
980     */
981    public boolean isSameTypes(List<Type> ts, List<Type> ss) {
982        return isSameTypes(ts, ss, false);
983    }
984    public boolean isSameTypes(List<Type> ts, List<Type> ss, boolean strict) {
985        while (ts.tail != null && ss.tail != null
986               /*inlined: ts.nonEmpty() && ss.nonEmpty()*/ &&
987               isSameType(ts.head, ss.head, strict)) {
988            ts = ts.tail;
989            ss = ss.tail;
990        }
991        return ts.tail == null && ss.tail == null;
992        /*inlined: ts.isEmpty() && ss.isEmpty();*/
993    }
994
995    /**
996     * A polymorphic signature method (JLS 15.12.3) is a method that
997     *   (i) is declared in the java.lang.invoke.MethodHandle/VarHandle classes;
998     *  (ii) takes a single variable arity parameter;
999     * (iii) whose declared type is Object[];
1000     *  (iv) has any return type, Object signifying a polymorphic return type; and
1001     *   (v) is native.
1002    */
1003   public boolean isSignaturePolymorphic(MethodSymbol msym) {
1004       List<Type> argtypes = msym.type.getParameterTypes();
1005       return (msym.flags_field & NATIVE) != 0 &&
1006              (msym.owner == syms.methodHandleType.tsym || msym.owner == syms.varHandleType.tsym) &&
1007               argtypes.length() == 1 &&
1008               argtypes.head.hasTag(TypeTag.ARRAY) &&
1009               ((ArrayType)argtypes.head).elemtype.tsym == syms.objectType.tsym;
1010   }
1011
1012    /**
1013     * Is t the same type as s?
1014     */
1015    public boolean isSameType(Type t, Type s) {
1016        return isSameType(t, s, false);
1017    }
1018    public boolean isSameType(Type t, Type s, boolean strict) {
1019        return strict ?
1020                isSameTypeStrict.visit(t, s) :
1021                isSameTypeLoose.visit(t, s);
1022    }
1023    // where
1024        abstract class SameTypeVisitor extends TypeRelation {
1025
1026            public Boolean visitType(Type t, Type s) {
1027                if (t.equalsIgnoreMetadata(s))
1028                    return true;
1029
1030                if (s.isPartial())
1031                    return visit(s, t);
1032
1033                switch (t.getTag()) {
1034                case BYTE: case CHAR: case SHORT: case INT: case LONG: case FLOAT:
1035                case DOUBLE: case BOOLEAN: case VOID: case BOT: case NONE:
1036                    return t.hasTag(s.getTag());
1037                case TYPEVAR: {
1038                    if (s.hasTag(TYPEVAR)) {
1039                        //type-substitution does not preserve type-var types
1040                        //check that type var symbols and bounds are indeed the same
1041                        return sameTypeVars((TypeVar)t, (TypeVar)s);
1042                    }
1043                    else {
1044                        //special case for s == ? super X, where upper(s) = u
1045                        //check that u == t, where u has been set by Type.withTypeVar
1046                        return s.isSuperBound() &&
1047                                !s.isExtendsBound() &&
1048                                visit(t, wildUpperBound(s));
1049                    }
1050                }
1051                default:
1052                    throw new AssertionError("isSameType " + t.getTag());
1053                }
1054            }
1055
1056            abstract boolean sameTypeVars(TypeVar tv1, TypeVar tv2);
1057
1058            @Override
1059            public Boolean visitWildcardType(WildcardType t, Type s) {
1060                if (!s.hasTag(WILDCARD)) {
1061                    return false;
1062                } else {
1063                    WildcardType t2 = (WildcardType)s;
1064                    return (t.kind == t2.kind || (t.isExtendsBound() && s.isExtendsBound())) &&
1065                            isSameType(t.type, t2.type, true);
1066                }
1067            }
1068
1069            @Override
1070            public Boolean visitClassType(ClassType t, Type s) {
1071                if (t == s)
1072                    return true;
1073
1074                if (s.isPartial())
1075                    return visit(s, t);
1076
1077                if (s.isSuperBound() && !s.isExtendsBound())
1078                    return visit(t, wildUpperBound(s)) && visit(t, wildLowerBound(s));
1079
1080                if (t.isCompound() && s.isCompound()) {
1081                    if (!visit(supertype(t), supertype(s)))
1082                        return false;
1083
1084                    Map<Symbol,Type> tMap = new HashMap<>();
1085                    for (Type ti : interfaces(t)) {
1086                        if (tMap.containsKey(ti)) {
1087                            throw new AssertionError("Malformed intersection");
1088                        }
1089                        tMap.put(ti.tsym, ti);
1090                    }
1091                    for (Type si : interfaces(s)) {
1092                        if (!tMap.containsKey(si.tsym))
1093                            return false;
1094                        Type ti = tMap.remove(si.tsym);
1095                        if (!visit(ti, si))
1096                            return false;
1097                    }
1098                    return tMap.isEmpty();
1099                }
1100                return t.tsym == s.tsym
1101                    && visit(t.getEnclosingType(), s.getEnclosingType())
1102                    && containsTypes(t.getTypeArguments(), s.getTypeArguments());
1103            }
1104
1105            abstract protected boolean containsTypes(List<Type> ts1, List<Type> ts2);
1106
1107            @Override
1108            public Boolean visitArrayType(ArrayType t, Type s) {
1109                if (t == s)
1110                    return true;
1111
1112                if (s.isPartial())
1113                    return visit(s, t);
1114
1115                return s.hasTag(ARRAY)
1116                    && containsTypeEquivalent(t.elemtype, elemtype(s));
1117            }
1118
1119            @Override
1120            public Boolean visitMethodType(MethodType t, Type s) {
1121                // isSameType for methods does not take thrown
1122                // exceptions into account!
1123                return hasSameArgs(t, s) && visit(t.getReturnType(), s.getReturnType());
1124            }
1125
1126            @Override
1127            public Boolean visitPackageType(PackageType t, Type s) {
1128                return t == s;
1129            }
1130
1131            @Override
1132            public Boolean visitForAll(ForAll t, Type s) {
1133                if (!s.hasTag(FORALL)) {
1134                    return false;
1135                }
1136
1137                ForAll forAll = (ForAll)s;
1138                return hasSameBounds(t, forAll)
1139                    && visit(t.qtype, subst(forAll.qtype, forAll.tvars, t.tvars));
1140            }
1141
1142            @Override
1143            public Boolean visitUndetVar(UndetVar t, Type s) {
1144                if (s.hasTag(WILDCARD)) {
1145                    // FIXME, this might be leftovers from before capture conversion
1146                    return false;
1147                }
1148
1149                if (t == s || t.qtype == s || s.hasTag(ERROR) || s.hasTag(UNKNOWN)) {
1150                    return true;
1151                }
1152
1153                t.addBound(InferenceBound.EQ, s, Types.this);
1154
1155                return true;
1156            }
1157
1158            @Override
1159            public Boolean visitErrorType(ErrorType t, Type s) {
1160                return true;
1161            }
1162        }
1163
1164        /**
1165         * Standard type-equality relation - type variables are considered
1166         * equals if they share the same type symbol.
1167         */
1168        TypeRelation isSameTypeLoose = new LooseSameTypeVisitor();
1169
1170        private class LooseSameTypeVisitor extends SameTypeVisitor {
1171
1172            /** cache of the type-variable pairs being (recursively) tested. */
1173            private Set<TypePair> cache = new HashSet<>();
1174
1175            @Override
1176            boolean sameTypeVars(TypeVar tv1, TypeVar tv2) {
1177                return tv1.tsym == tv2.tsym && checkSameBounds(tv1, tv2);
1178            }
1179            @Override
1180            protected boolean containsTypes(List<Type> ts1, List<Type> ts2) {
1181                return containsTypeEquivalent(ts1, ts2);
1182            }
1183
1184            /**
1185             * Since type-variable bounds can be recursive, we need to protect against
1186             * infinite loops - where the same bounds are checked over and over recursively.
1187             */
1188            private boolean checkSameBounds(TypeVar tv1, TypeVar tv2) {
1189                TypePair p = new TypePair(tv1, tv2, true);
1190                if (cache.add(p)) {
1191                    try {
1192                        return visit(tv1.getUpperBound(), tv2.getUpperBound());
1193                    } finally {
1194                        cache.remove(p);
1195                    }
1196                } else {
1197                    return false;
1198                }
1199            }
1200        };
1201
1202        /**
1203         * Strict type-equality relation - type variables are considered
1204         * equals if they share the same object identity.
1205         */
1206        TypeRelation isSameTypeStrict = new SameTypeVisitor() {
1207            @Override
1208            boolean sameTypeVars(TypeVar tv1, TypeVar tv2) {
1209                return tv1 == tv2;
1210            }
1211            @Override
1212            protected boolean containsTypes(List<Type> ts1, List<Type> ts2) {
1213                return isSameTypes(ts1, ts2, true);
1214            }
1215
1216            @Override
1217            public Boolean visitWildcardType(WildcardType t, Type s) {
1218                if (!s.hasTag(WILDCARD)) {
1219                    return false;
1220                } else {
1221                    WildcardType t2 = (WildcardType)s;
1222                    return t.kind == t2.kind &&
1223                            isSameType(t.type, t2.type, true);
1224                }
1225            }
1226        };
1227
1228    // </editor-fold>
1229
1230    // <editor-fold defaultstate="collapsed" desc="Contains Type">
1231    public boolean containedBy(Type t, Type s) {
1232        switch (t.getTag()) {
1233        case UNDETVAR:
1234            if (s.hasTag(WILDCARD)) {
1235                UndetVar undetvar = (UndetVar)t;
1236                WildcardType wt = (WildcardType)s;
1237                switch(wt.kind) {
1238                    case UNBOUND:
1239                        break;
1240                    case EXTENDS: {
1241                        Type bound = wildUpperBound(s);
1242                        undetvar.addBound(InferenceBound.UPPER, bound, this);
1243                        break;
1244                    }
1245                    case SUPER: {
1246                        Type bound = wildLowerBound(s);
1247                        undetvar.addBound(InferenceBound.LOWER, bound, this);
1248                        break;
1249                    }
1250                }
1251                return true;
1252            } else {
1253                return isSameType(t, s);
1254            }
1255        case ERROR:
1256            return true;
1257        default:
1258            return containsType(s, t);
1259        }
1260    }
1261
1262    boolean containsType(List<Type> ts, List<Type> ss) {
1263        while (ts.nonEmpty() && ss.nonEmpty()
1264               && containsType(ts.head, ss.head)) {
1265            ts = ts.tail;
1266            ss = ss.tail;
1267        }
1268        return ts.isEmpty() && ss.isEmpty();
1269    }
1270
1271    /**
1272     * Check if t contains s.
1273     *
1274     * <p>T contains S if:
1275     *
1276     * <p>{@code L(T) <: L(S) && U(S) <: U(T)}
1277     *
1278     * <p>This relation is only used by ClassType.isSubtype(), that
1279     * is,
1280     *
1281     * <p>{@code C<S> <: C<T> if T contains S.}
1282     *
1283     * <p>Because of F-bounds, this relation can lead to infinite
1284     * recursion.  Thus we must somehow break that recursion.  Notice
1285     * that containsType() is only called from ClassType.isSubtype().
1286     * Since the arguments have already been checked against their
1287     * bounds, we know:
1288     *
1289     * <p>{@code U(S) <: U(T) if T is "super" bound (U(T) *is* the bound)}
1290     *
1291     * <p>{@code L(T) <: L(S) if T is "extends" bound (L(T) is bottom)}
1292     *
1293     * @param t a type
1294     * @param s a type
1295     */
1296    public boolean containsType(Type t, Type s) {
1297        return containsType.visit(t, s);
1298    }
1299    // where
1300        private TypeRelation containsType = new TypeRelation() {
1301
1302            public Boolean visitType(Type t, Type s) {
1303                if (s.isPartial())
1304                    return containedBy(s, t);
1305                else
1306                    return isSameType(t, s);
1307            }
1308
1309//            void debugContainsType(WildcardType t, Type s) {
1310//                System.err.println();
1311//                System.err.format(" does %s contain %s?%n", t, s);
1312//                System.err.format(" %s U(%s) <: U(%s) %s = %s%n",
1313//                                  wildUpperBound(s), s, t, wildUpperBound(t),
1314//                                  t.isSuperBound()
1315//                                  || isSubtypeNoCapture(wildUpperBound(s), wildUpperBound(t)));
1316//                System.err.format(" %s L(%s) <: L(%s) %s = %s%n",
1317//                                  wildLowerBound(t), t, s, wildLowerBound(s),
1318//                                  t.isExtendsBound()
1319//                                  || isSubtypeNoCapture(wildLowerBound(t), wildLowerBound(s)));
1320//                System.err.println();
1321//            }
1322
1323            @Override
1324            public Boolean visitWildcardType(WildcardType t, Type s) {
1325                if (s.isPartial())
1326                    return containedBy(s, t);
1327                else {
1328//                    debugContainsType(t, s);
1329                    return isSameWildcard(t, s)
1330                        || isCaptureOf(s, t)
1331                        || ((t.isExtendsBound() || isSubtypeNoCapture(wildLowerBound(t), wildLowerBound(s))) &&
1332                            (t.isSuperBound() || isSubtypeNoCapture(wildUpperBound(s), wildUpperBound(t))));
1333                }
1334            }
1335
1336            @Override
1337            public Boolean visitUndetVar(UndetVar t, Type s) {
1338                if (!s.hasTag(WILDCARD)) {
1339                    return isSameType(t, s);
1340                } else {
1341                    return false;
1342                }
1343            }
1344
1345            @Override
1346            public Boolean visitErrorType(ErrorType t, Type s) {
1347                return true;
1348            }
1349        };
1350
1351    public boolean isCaptureOf(Type s, WildcardType t) {
1352        if (!s.hasTag(TYPEVAR) || !((TypeVar)s).isCaptured())
1353            return false;
1354        return isSameWildcard(t, ((CapturedType)s).wildcard);
1355    }
1356
1357    public boolean isSameWildcard(WildcardType t, Type s) {
1358        if (!s.hasTag(WILDCARD))
1359            return false;
1360        WildcardType w = (WildcardType)s;
1361        return w.kind == t.kind && w.type == t.type;
1362    }
1363
1364    public boolean containsTypeEquivalent(List<Type> ts, List<Type> ss) {
1365        while (ts.nonEmpty() && ss.nonEmpty()
1366               && containsTypeEquivalent(ts.head, ss.head)) {
1367            ts = ts.tail;
1368            ss = ss.tail;
1369        }
1370        return ts.isEmpty() && ss.isEmpty();
1371    }
1372    // </editor-fold>
1373
1374    // <editor-fold defaultstate="collapsed" desc="isCastable">
1375    public boolean isCastable(Type t, Type s) {
1376        return isCastable(t, s, noWarnings);
1377    }
1378
1379    /**
1380     * Is t is castable to s?<br>
1381     * s is assumed to be an erased type.<br>
1382     * (not defined for Method and ForAll types).
1383     */
1384    public boolean isCastable(Type t, Type s, Warner warn) {
1385        if (t == s)
1386            return true;
1387        if (t.isPrimitive() != s.isPrimitive()) {
1388            t = skipTypeVars(t, false);
1389            return (isConvertible(t, s, warn)
1390                    || (allowObjectToPrimitiveCast &&
1391                        s.isPrimitive() &&
1392                        isSubtype(boxedClass(s).type, t)));
1393        }
1394        if (warn != warnStack.head) {
1395            try {
1396                warnStack = warnStack.prepend(warn);
1397                checkUnsafeVarargsConversion(t, s, warn);
1398                return isCastable.visit(t,s);
1399            } finally {
1400                warnStack = warnStack.tail;
1401            }
1402        } else {
1403            return isCastable.visit(t,s);
1404        }
1405    }
1406    // where
1407        private TypeRelation isCastable = new TypeRelation() {
1408
1409            public Boolean visitType(Type t, Type s) {
1410                if (s.hasTag(ERROR))
1411                    return true;
1412
1413                switch (t.getTag()) {
1414                case BYTE: case CHAR: case SHORT: case INT: case LONG: case FLOAT:
1415                case DOUBLE:
1416                    return s.isNumeric();
1417                case BOOLEAN:
1418                    return s.hasTag(BOOLEAN);
1419                case VOID:
1420                    return false;
1421                case BOT:
1422                    return isSubtype(t, s);
1423                default:
1424                    throw new AssertionError();
1425                }
1426            }
1427
1428            @Override
1429            public Boolean visitWildcardType(WildcardType t, Type s) {
1430                return isCastable(wildUpperBound(t), s, warnStack.head);
1431            }
1432
1433            @Override
1434            public Boolean visitClassType(ClassType t, Type s) {
1435                if (s.hasTag(ERROR) || s.hasTag(BOT))
1436                    return true;
1437
1438                if (s.hasTag(TYPEVAR)) {
1439                    if (isCastable(t, s.getUpperBound(), noWarnings)) {
1440                        warnStack.head.warn(LintCategory.UNCHECKED);
1441                        return true;
1442                    } else {
1443                        return false;
1444                    }
1445                }
1446
1447                if (t.isCompound() || s.isCompound()) {
1448                    return !t.isCompound() ?
1449                            visitCompoundType((ClassType)s, t, true) :
1450                            visitCompoundType(t, s, false);
1451                }
1452
1453                if (s.hasTag(CLASS) || s.hasTag(ARRAY)) {
1454                    boolean upcast;
1455                    if ((upcast = isSubtype(erasure(t), erasure(s)))
1456                        || isSubtype(erasure(s), erasure(t))) {
1457                        if (!upcast && s.hasTag(ARRAY)) {
1458                            if (!isReifiable(s))
1459                                warnStack.head.warn(LintCategory.UNCHECKED);
1460                            return true;
1461                        } else if (s.isRaw()) {
1462                            return true;
1463                        } else if (t.isRaw()) {
1464                            if (!isUnbounded(s))
1465                                warnStack.head.warn(LintCategory.UNCHECKED);
1466                            return true;
1467                        }
1468                        // Assume |a| <: |b|
1469                        final Type a = upcast ? t : s;
1470                        final Type b = upcast ? s : t;
1471                        final boolean HIGH = true;
1472                        final boolean LOW = false;
1473                        final boolean DONT_REWRITE_TYPEVARS = false;
1474                        Type aHigh = rewriteQuantifiers(a, HIGH, DONT_REWRITE_TYPEVARS);
1475                        Type aLow  = rewriteQuantifiers(a, LOW,  DONT_REWRITE_TYPEVARS);
1476                        Type bHigh = rewriteQuantifiers(b, HIGH, DONT_REWRITE_TYPEVARS);
1477                        Type bLow  = rewriteQuantifiers(b, LOW,  DONT_REWRITE_TYPEVARS);
1478                        Type lowSub = asSub(bLow, aLow.tsym);
1479                        Type highSub = (lowSub == null) ? null : asSub(bHigh, aHigh.tsym);
1480                        if (highSub == null) {
1481                            final boolean REWRITE_TYPEVARS = true;
1482                            aHigh = rewriteQuantifiers(a, HIGH, REWRITE_TYPEVARS);
1483                            aLow  = rewriteQuantifiers(a, LOW,  REWRITE_TYPEVARS);
1484                            bHigh = rewriteQuantifiers(b, HIGH, REWRITE_TYPEVARS);
1485                            bLow  = rewriteQuantifiers(b, LOW,  REWRITE_TYPEVARS);
1486                            lowSub = asSub(bLow, aLow.tsym);
1487                            highSub = (lowSub == null) ? null : asSub(bHigh, aHigh.tsym);
1488                        }
1489                        if (highSub != null) {
1490                            if (!(a.tsym == highSub.tsym && a.tsym == lowSub.tsym)) {
1491                                Assert.error(a.tsym + " != " + highSub.tsym + " != " + lowSub.tsym);
1492                            }
1493                            if (!disjointTypes(aHigh.allparams(), highSub.allparams())
1494                                && !disjointTypes(aHigh.allparams(), lowSub.allparams())
1495                                && !disjointTypes(aLow.allparams(), highSub.allparams())
1496                                && !disjointTypes(aLow.allparams(), lowSub.allparams())) {
1497                                if (upcast ? giveWarning(a, b) :
1498                                    giveWarning(b, a))
1499                                    warnStack.head.warn(LintCategory.UNCHECKED);
1500                                return true;
1501                            }
1502                        }
1503                        if (isReifiable(s))
1504                            return isSubtypeUnchecked(a, b);
1505                        else
1506                            return isSubtypeUnchecked(a, b, warnStack.head);
1507                    }
1508
1509                    // Sidecast
1510                    if (s.hasTag(CLASS)) {
1511                        if ((s.tsym.flags() & INTERFACE) != 0) {
1512                            return ((t.tsym.flags() & FINAL) == 0)
1513                                ? sideCast(t, s, warnStack.head)
1514                                : sideCastFinal(t, s, warnStack.head);
1515                        } else if ((t.tsym.flags() & INTERFACE) != 0) {
1516                            return ((s.tsym.flags() & FINAL) == 0)
1517                                ? sideCast(t, s, warnStack.head)
1518                                : sideCastFinal(t, s, warnStack.head);
1519                        } else {
1520                            // unrelated class types
1521                            return false;
1522                        }
1523                    }
1524                }
1525                return false;
1526            }
1527
1528            boolean visitCompoundType(ClassType ct, Type s, boolean reverse) {
1529                Warner warn = noWarnings;
1530                for (Type c : directSupertypes(ct)) {
1531                    warn.clear();
1532                    if (reverse ? !isCastable(s, c, warn) : !isCastable(c, s, warn))
1533                        return false;
1534                }
1535                if (warn.hasLint(LintCategory.UNCHECKED))
1536                    warnStack.head.warn(LintCategory.UNCHECKED);
1537                return true;
1538            }
1539
1540            @Override
1541            public Boolean visitArrayType(ArrayType t, Type s) {
1542                switch (s.getTag()) {
1543                case ERROR:
1544                case BOT:
1545                    return true;
1546                case TYPEVAR:
1547                    if (isCastable(s, t, noWarnings)) {
1548                        warnStack.head.warn(LintCategory.UNCHECKED);
1549                        return true;
1550                    } else {
1551                        return false;
1552                    }
1553                case CLASS:
1554                    return isSubtype(t, s);
1555                case ARRAY:
1556                    if (elemtype(t).isPrimitive() || elemtype(s).isPrimitive()) {
1557                        return elemtype(t).hasTag(elemtype(s).getTag());
1558                    } else {
1559                        return visit(elemtype(t), elemtype(s));
1560                    }
1561                default:
1562                    return false;
1563                }
1564            }
1565
1566            @Override
1567            public Boolean visitTypeVar(TypeVar t, Type s) {
1568                switch (s.getTag()) {
1569                case ERROR:
1570                case BOT:
1571                    return true;
1572                case TYPEVAR:
1573                    if (isSubtype(t, s)) {
1574                        return true;
1575                    } else if (isCastable(t.bound, s, noWarnings)) {
1576                        warnStack.head.warn(LintCategory.UNCHECKED);
1577                        return true;
1578                    } else {
1579                        return false;
1580                    }
1581                default:
1582                    return isCastable(t.bound, s, warnStack.head);
1583                }
1584            }
1585
1586            @Override
1587            public Boolean visitErrorType(ErrorType t, Type s) {
1588                return true;
1589            }
1590        };
1591    // </editor-fold>
1592
1593    // <editor-fold defaultstate="collapsed" desc="disjointTypes">
1594    public boolean disjointTypes(List<Type> ts, List<Type> ss) {
1595        while (ts.tail != null && ss.tail != null) {
1596            if (disjointType(ts.head, ss.head)) return true;
1597            ts = ts.tail;
1598            ss = ss.tail;
1599        }
1600        return false;
1601    }
1602
1603    /**
1604     * Two types or wildcards are considered disjoint if it can be
1605     * proven that no type can be contained in both. It is
1606     * conservative in that it is allowed to say that two types are
1607     * not disjoint, even though they actually are.
1608     *
1609     * The type {@code C<X>} is castable to {@code C<Y>} exactly if
1610     * {@code X} and {@code Y} are not disjoint.
1611     */
1612    public boolean disjointType(Type t, Type s) {
1613        return disjointType.visit(t, s);
1614    }
1615    // where
1616        private TypeRelation disjointType = new TypeRelation() {
1617
1618            private Set<TypePair> cache = new HashSet<>();
1619
1620            @Override
1621            public Boolean visitType(Type t, Type s) {
1622                if (s.hasTag(WILDCARD))
1623                    return visit(s, t);
1624                else
1625                    return notSoftSubtypeRecursive(t, s) || notSoftSubtypeRecursive(s, t);
1626            }
1627
1628            private boolean isCastableRecursive(Type t, Type s) {
1629                TypePair pair = new TypePair(t, s);
1630                if (cache.add(pair)) {
1631                    try {
1632                        return Types.this.isCastable(t, s);
1633                    } finally {
1634                        cache.remove(pair);
1635                    }
1636                } else {
1637                    return true;
1638                }
1639            }
1640
1641            private boolean notSoftSubtypeRecursive(Type t, Type s) {
1642                TypePair pair = new TypePair(t, s);
1643                if (cache.add(pair)) {
1644                    try {
1645                        return Types.this.notSoftSubtype(t, s);
1646                    } finally {
1647                        cache.remove(pair);
1648                    }
1649                } else {
1650                    return false;
1651                }
1652            }
1653
1654            @Override
1655            public Boolean visitWildcardType(WildcardType t, Type s) {
1656                if (t.isUnbound())
1657                    return false;
1658
1659                if (!s.hasTag(WILDCARD)) {
1660                    if (t.isExtendsBound())
1661                        return notSoftSubtypeRecursive(s, t.type);
1662                    else
1663                        return notSoftSubtypeRecursive(t.type, s);
1664                }
1665
1666                if (s.isUnbound())
1667                    return false;
1668
1669                if (t.isExtendsBound()) {
1670                    if (s.isExtendsBound())
1671                        return !isCastableRecursive(t.type, wildUpperBound(s));
1672                    else if (s.isSuperBound())
1673                        return notSoftSubtypeRecursive(wildLowerBound(s), t.type);
1674                } else if (t.isSuperBound()) {
1675                    if (s.isExtendsBound())
1676                        return notSoftSubtypeRecursive(t.type, wildUpperBound(s));
1677                }
1678                return false;
1679            }
1680        };
1681    // </editor-fold>
1682
1683    // <editor-fold defaultstate="collapsed" desc="cvarLowerBounds">
1684    public List<Type> cvarLowerBounds(List<Type> ts) {
1685        return ts.map(cvarLowerBoundMapping);
1686    }
1687        private final TypeMapping<Void> cvarLowerBoundMapping = new TypeMapping<Void>() {
1688            @Override
1689            public Type visitCapturedType(CapturedType t, Void _unused) {
1690                return cvarLowerBound(t);
1691            }
1692        };
1693    // </editor-fold>
1694
1695    // <editor-fold defaultstate="collapsed" desc="notSoftSubtype">
1696    /**
1697     * This relation answers the question: is impossible that
1698     * something of type `t' can be a subtype of `s'? This is
1699     * different from the question "is `t' not a subtype of `s'?"
1700     * when type variables are involved: Integer is not a subtype of T
1701     * where {@code <T extends Number>} but it is not true that Integer cannot
1702     * possibly be a subtype of T.
1703     */
1704    public boolean notSoftSubtype(Type t, Type s) {
1705        if (t == s) return false;
1706        if (t.hasTag(TYPEVAR)) {
1707            TypeVar tv = (TypeVar) t;
1708            return !isCastable(tv.bound,
1709                               relaxBound(s),
1710                               noWarnings);
1711        }
1712        if (!s.hasTag(WILDCARD))
1713            s = cvarUpperBound(s);
1714
1715        return !isSubtype(t, relaxBound(s));
1716    }
1717
1718    private Type relaxBound(Type t) {
1719        return (t.hasTag(TYPEVAR)) ?
1720                rewriteQuantifiers(skipTypeVars(t, false), true, true) :
1721                t;
1722    }
1723    // </editor-fold>
1724
1725    // <editor-fold defaultstate="collapsed" desc="isReifiable">
1726    public boolean isReifiable(Type t) {
1727        return isReifiable.visit(t);
1728    }
1729    // where
1730        private UnaryVisitor<Boolean> isReifiable = new UnaryVisitor<Boolean>() {
1731
1732            public Boolean visitType(Type t, Void ignored) {
1733                return true;
1734            }
1735
1736            @Override
1737            public Boolean visitClassType(ClassType t, Void ignored) {
1738                if (t.isCompound())
1739                    return false;
1740                else {
1741                    if (!t.isParameterized())
1742                        return true;
1743
1744                    for (Type param : t.allparams()) {
1745                        if (!param.isUnbound())
1746                            return false;
1747                    }
1748                    return true;
1749                }
1750            }
1751
1752            @Override
1753            public Boolean visitArrayType(ArrayType t, Void ignored) {
1754                return visit(t.elemtype);
1755            }
1756
1757            @Override
1758            public Boolean visitTypeVar(TypeVar t, Void ignored) {
1759                return false;
1760            }
1761        };
1762    // </editor-fold>
1763
1764    // <editor-fold defaultstate="collapsed" desc="Array Utils">
1765    public boolean isArray(Type t) {
1766        while (t.hasTag(WILDCARD))
1767            t = wildUpperBound(t);
1768        return t.hasTag(ARRAY);
1769    }
1770
1771    /**
1772     * The element type of an array.
1773     */
1774    public Type elemtype(Type t) {
1775        switch (t.getTag()) {
1776        case WILDCARD:
1777            return elemtype(wildUpperBound(t));
1778        case ARRAY:
1779            return ((ArrayType)t).elemtype;
1780        case FORALL:
1781            return elemtype(((ForAll)t).qtype);
1782        case ERROR:
1783            return t;
1784        default:
1785            return null;
1786        }
1787    }
1788
1789    public Type elemtypeOrType(Type t) {
1790        Type elemtype = elemtype(t);
1791        return elemtype != null ?
1792            elemtype :
1793            t;
1794    }
1795
1796    /**
1797     * Mapping to take element type of an arraytype
1798     */
1799    private TypeMapping<Void> elemTypeFun = new TypeMapping<Void>() {
1800        @Override
1801        public Type visitArrayType(ArrayType t, Void _unused) {
1802            return t.elemtype;
1803        }
1804
1805        @Override
1806        public Type visitTypeVar(TypeVar t, Void _unused) {
1807            return visit(skipTypeVars(t, false));
1808        }
1809    };
1810
1811    /**
1812     * The number of dimensions of an array type.
1813     */
1814    public int dimensions(Type t) {
1815        int result = 0;
1816        while (t.hasTag(ARRAY)) {
1817            result++;
1818            t = elemtype(t);
1819        }
1820        return result;
1821    }
1822
1823    /**
1824     * Returns an ArrayType with the component type t
1825     *
1826     * @param t The component type of the ArrayType
1827     * @return the ArrayType for the given component
1828     */
1829    public ArrayType makeArrayType(Type t) {
1830        if (t.hasTag(VOID) || t.hasTag(PACKAGE)) {
1831            Assert.error("Type t must not be a VOID or PACKAGE type, " + t.toString());
1832        }
1833        return new ArrayType(t, syms.arrayClass);
1834    }
1835    // </editor-fold>
1836
1837    // <editor-fold defaultstate="collapsed" desc="asSuper">
1838    /**
1839     * Return the (most specific) base type of t that starts with the
1840     * given symbol.  If none exists, return null.
1841     *
1842     * Caveat Emptor: Since javac represents the class of all arrays with a singleton
1843     * symbol Symtab.arrayClass, which by being a singleton cannot hold any discriminant,
1844     * this method could yield surprising answers when invoked on arrays. For example when
1845     * invoked with t being byte [] and sym being t.sym itself, asSuper would answer null.
1846     *
1847     * @param t a type
1848     * @param sym a symbol
1849     */
1850    public Type asSuper(Type t, Symbol sym) {
1851        /* Some examples:
1852         *
1853         * (Enum<E>, Comparable) => Comparable<E>
1854         * (c.s.s.d.AttributeTree.ValueKind, Enum) => Enum<c.s.s.d.AttributeTree.ValueKind>
1855         * (c.s.s.t.ExpressionTree, c.s.s.t.Tree) => c.s.s.t.Tree
1856         * (j.u.List<capture#160 of ? extends c.s.s.d.DocTree>, Iterable) =>
1857         *     Iterable<capture#160 of ? extends c.s.s.d.DocTree>
1858         */
1859        if (sym.type == syms.objectType) { //optimization
1860            return syms.objectType;
1861        }
1862        return asSuper.visit(t, sym);
1863    }
1864    // where
1865        private SimpleVisitor<Type,Symbol> asSuper = new SimpleVisitor<Type,Symbol>() {
1866
1867            public Type visitType(Type t, Symbol sym) {
1868                return null;
1869            }
1870
1871            @Override
1872            public Type visitClassType(ClassType t, Symbol sym) {
1873                if (t.tsym == sym)
1874                    return t;
1875
1876                Type st = supertype(t);
1877                if (st.hasTag(CLASS) || st.hasTag(TYPEVAR)) {
1878                    Type x = asSuper(st, sym);
1879                    if (x != null)
1880                        return x;
1881                }
1882                if ((sym.flags() & INTERFACE) != 0) {
1883                    for (List<Type> l = interfaces(t); l.nonEmpty(); l = l.tail) {
1884                        if (!l.head.hasTag(ERROR)) {
1885                            Type x = asSuper(l.head, sym);
1886                            if (x != null)
1887                                return x;
1888                        }
1889                    }
1890                }
1891                return null;
1892            }
1893
1894            @Override
1895            public Type visitArrayType(ArrayType t, Symbol sym) {
1896                return isSubtype(t, sym.type) ? sym.type : null;
1897            }
1898
1899            @Override
1900            public Type visitTypeVar(TypeVar t, Symbol sym) {
1901                if (t.tsym == sym)
1902                    return t;
1903                else
1904                    return asSuper(t.bound, sym);
1905            }
1906
1907            @Override
1908            public Type visitErrorType(ErrorType t, Symbol sym) {
1909                return t;
1910            }
1911        };
1912
1913    /**
1914     * Return the base type of t or any of its outer types that starts
1915     * with the given symbol.  If none exists, return null.
1916     *
1917     * @param t a type
1918     * @param sym a symbol
1919     */
1920    public Type asOuterSuper(Type t, Symbol sym) {
1921        switch (t.getTag()) {
1922        case CLASS:
1923            do {
1924                Type s = asSuper(t, sym);
1925                if (s != null) return s;
1926                t = t.getEnclosingType();
1927            } while (t.hasTag(CLASS));
1928            return null;
1929        case ARRAY:
1930            return isSubtype(t, sym.type) ? sym.type : null;
1931        case TYPEVAR:
1932            return asSuper(t, sym);
1933        case ERROR:
1934            return t;
1935        default:
1936            return null;
1937        }
1938    }
1939
1940    /**
1941     * Return the base type of t or any of its enclosing types that
1942     * starts with the given symbol.  If none exists, return null.
1943     *
1944     * @param t a type
1945     * @param sym a symbol
1946     */
1947    public Type asEnclosingSuper(Type t, Symbol sym) {
1948        switch (t.getTag()) {
1949        case CLASS:
1950            do {
1951                Type s = asSuper(t, sym);
1952                if (s != null) return s;
1953                Type outer = t.getEnclosingType();
1954                t = (outer.hasTag(CLASS)) ? outer :
1955                    (t.tsym.owner.enclClass() != null) ? t.tsym.owner.enclClass().type :
1956                    Type.noType;
1957            } while (t.hasTag(CLASS));
1958            return null;
1959        case ARRAY:
1960            return isSubtype(t, sym.type) ? sym.type : null;
1961        case TYPEVAR:
1962            return asSuper(t, sym);
1963        case ERROR:
1964            return t;
1965        default:
1966            return null;
1967        }
1968    }
1969    // </editor-fold>
1970
1971    // <editor-fold defaultstate="collapsed" desc="memberType">
1972    /**
1973     * The type of given symbol, seen as a member of t.
1974     *
1975     * @param t a type
1976     * @param sym a symbol
1977     */
1978    public Type memberType(Type t, Symbol sym) {
1979        return (sym.flags() & STATIC) != 0
1980            ? sym.type
1981            : memberType.visit(t, sym);
1982        }
1983    // where
1984        private SimpleVisitor<Type,Symbol> memberType = new SimpleVisitor<Type,Symbol>() {
1985
1986            public Type visitType(Type t, Symbol sym) {
1987                return sym.type;
1988            }
1989
1990            @Override
1991            public Type visitWildcardType(WildcardType t, Symbol sym) {
1992                return memberType(wildUpperBound(t), sym);
1993            }
1994
1995            @Override
1996            public Type visitClassType(ClassType t, Symbol sym) {
1997                Symbol owner = sym.owner;
1998                long flags = sym.flags();
1999                if (((flags & STATIC) == 0) && owner.type.isParameterized()) {
2000                    Type base = asOuterSuper(t, owner);
2001                    //if t is an intersection type T = CT & I1 & I2 ... & In
2002                    //its supertypes CT, I1, ... In might contain wildcards
2003                    //so we need to go through capture conversion
2004                    base = t.isCompound() ? capture(base) : base;
2005                    if (base != null) {
2006                        List<Type> ownerParams = owner.type.allparams();
2007                        List<Type> baseParams = base.allparams();
2008                        if (ownerParams.nonEmpty()) {
2009                            if (baseParams.isEmpty()) {
2010                                // then base is a raw type
2011                                return erasure(sym.type);
2012                            } else {
2013                                return subst(sym.type, ownerParams, baseParams);
2014                            }
2015                        }
2016                    }
2017                }
2018                return sym.type;
2019            }
2020
2021            @Override
2022            public Type visitTypeVar(TypeVar t, Symbol sym) {
2023                return memberType(t.bound, sym);
2024            }
2025
2026            @Override
2027            public Type visitErrorType(ErrorType t, Symbol sym) {
2028                return t;
2029            }
2030        };
2031    // </editor-fold>
2032
2033    // <editor-fold defaultstate="collapsed" desc="isAssignable">
2034    public boolean isAssignable(Type t, Type s) {
2035        return isAssignable(t, s, noWarnings);
2036    }
2037
2038    /**
2039     * Is t assignable to s?<br>
2040     * Equivalent to subtype except for constant values and raw
2041     * types.<br>
2042     * (not defined for Method and ForAll types)
2043     */
2044    public boolean isAssignable(Type t, Type s, Warner warn) {
2045        if (t.hasTag(ERROR))
2046            return true;
2047        if (t.getTag().isSubRangeOf(INT) && t.constValue() != null) {
2048            int value = ((Number)t.constValue()).intValue();
2049            switch (s.getTag()) {
2050            case BYTE:
2051                if (Byte.MIN_VALUE <= value && value <= Byte.MAX_VALUE)
2052                    return true;
2053                break;
2054            case CHAR:
2055                if (Character.MIN_VALUE <= value && value <= Character.MAX_VALUE)
2056                    return true;
2057                break;
2058            case SHORT:
2059                if (Short.MIN_VALUE <= value && value <= Short.MAX_VALUE)
2060                    return true;
2061                break;
2062            case INT:
2063                return true;
2064            case CLASS:
2065                switch (unboxedType(s).getTag()) {
2066                case BYTE:
2067                case CHAR:
2068                case SHORT:
2069                    return isAssignable(t, unboxedType(s), warn);
2070                }
2071                break;
2072            }
2073        }
2074        return isConvertible(t, s, warn);
2075    }
2076    // </editor-fold>
2077
2078    // <editor-fold defaultstate="collapsed" desc="erasure">
2079    /**
2080     * The erasure of t {@code |t|} -- the type that results when all
2081     * type parameters in t are deleted.
2082     */
2083    public Type erasure(Type t) {
2084        return eraseNotNeeded(t) ? t : erasure(t, false);
2085    }
2086    //where
2087    private boolean eraseNotNeeded(Type t) {
2088        // We don't want to erase primitive types and String type as that
2089        // operation is idempotent. Also, erasing these could result in loss
2090        // of information such as constant values attached to such types.
2091        return (t.isPrimitive()) || (syms.stringType.tsym == t.tsym);
2092    }
2093
2094    private Type erasure(Type t, boolean recurse) {
2095        if (t.isPrimitive()) {
2096            return t; /* fast special case */
2097        } else {
2098            Type out = erasure.visit(t, recurse);
2099            return out;
2100        }
2101        }
2102    // where
2103        private TypeMapping<Boolean> erasure = new TypeMapping<Boolean>() {
2104            private Type combineMetadata(final Type s,
2105                                         final Type t) {
2106                if (t.getMetadata() != TypeMetadata.EMPTY) {
2107                    switch (s.getKind()) {
2108                        case OTHER:
2109                        case UNION:
2110                        case INTERSECTION:
2111                        case PACKAGE:
2112                        case EXECUTABLE:
2113                        case NONE:
2114                        case VOID:
2115                        case ERROR:
2116                            return s;
2117                        default: return s.cloneWithMetadata(s.getMetadata().without(Kind.ANNOTATIONS));
2118                    }
2119                } else {
2120                    return s;
2121                }
2122            }
2123
2124            public Type visitType(Type t, Boolean recurse) {
2125                if (t.isPrimitive())
2126                    return t; /*fast special case*/
2127                else {
2128                    //other cases already handled
2129                    return combineMetadata(t, t);
2130                }
2131            }
2132
2133            @Override
2134            public Type visitWildcardType(WildcardType t, Boolean recurse) {
2135                Type erased = erasure(wildUpperBound(t), recurse);
2136                return combineMetadata(erased, t);
2137            }
2138
2139            @Override
2140            public Type visitClassType(ClassType t, Boolean recurse) {
2141                Type erased = t.tsym.erasure(Types.this);
2142                if (recurse) {
2143                    erased = new ErasedClassType(erased.getEnclosingType(),erased.tsym,
2144                            t.getMetadata().without(Kind.ANNOTATIONS));
2145                    return erased;
2146                } else {
2147                    return combineMetadata(erased, t);
2148                }
2149            }
2150
2151            @Override
2152            public Type visitTypeVar(TypeVar t, Boolean recurse) {
2153                Type erased = erasure(t.bound, recurse);
2154                return combineMetadata(erased, t);
2155            }
2156        };
2157
2158    public List<Type> erasure(List<Type> ts) {
2159        return erasure.visit(ts, false);
2160    }
2161
2162    public Type erasureRecursive(Type t) {
2163        return erasure(t, true);
2164    }
2165
2166    public List<Type> erasureRecursive(List<Type> ts) {
2167        return erasure.visit(ts, true);
2168    }
2169    // </editor-fold>
2170
2171    // <editor-fold defaultstate="collapsed" desc="makeIntersectionType">
2172    /**
2173     * Make an intersection type from non-empty list of types.  The list should be ordered according to
2174     * {@link TypeSymbol#precedes(TypeSymbol, Types)}. Note that this might cause a symbol completion.
2175     * Hence, this version of makeIntersectionType may not be called during a classfile read.
2176     *
2177     * @param bounds    the types from which the intersection type is formed
2178     */
2179    public IntersectionClassType makeIntersectionType(List<Type> bounds) {
2180        return makeIntersectionType(bounds, bounds.head.tsym.isInterface());
2181    }
2182
2183    /**
2184     * Make an intersection type from non-empty list of types.  The list should be ordered according to
2185     * {@link TypeSymbol#precedes(TypeSymbol, Types)}. This does not cause symbol completion as
2186     * an extra parameter indicates as to whether all bounds are interfaces - in which case the
2187     * supertype is implicitly assumed to be 'Object'.
2188     *
2189     * @param bounds        the types from which the intersection type is formed
2190     * @param allInterfaces are all bounds interface types?
2191     */
2192    public IntersectionClassType makeIntersectionType(List<Type> bounds, boolean allInterfaces) {
2193        Assert.check(bounds.nonEmpty());
2194        Type firstExplicitBound = bounds.head;
2195        if (allInterfaces) {
2196            bounds = bounds.prepend(syms.objectType);
2197        }
2198        ClassSymbol bc =
2199            new ClassSymbol(ABSTRACT|PUBLIC|SYNTHETIC|COMPOUND|ACYCLIC,
2200                            Type.moreInfo
2201                                ? names.fromString(bounds.toString())
2202                                : names.empty,
2203                            null,
2204                            syms.noSymbol);
2205        IntersectionClassType intersectionType = new IntersectionClassType(bounds, bc, allInterfaces);
2206        bc.type = intersectionType;
2207        bc.erasure_field = (bounds.head.hasTag(TYPEVAR)) ?
2208                syms.objectType : // error condition, recover
2209                erasure(firstExplicitBound);
2210        bc.members_field = WriteableScope.create(bc);
2211        return intersectionType;
2212    }
2213    // </editor-fold>
2214
2215    // <editor-fold defaultstate="collapsed" desc="supertype">
2216    public Type supertype(Type t) {
2217        return supertype.visit(t);
2218    }
2219    // where
2220        private UnaryVisitor<Type> supertype = new UnaryVisitor<Type>() {
2221
2222            public Type visitType(Type t, Void ignored) {
2223                // A note on wildcards: there is no good way to
2224                // determine a supertype for a super bounded wildcard.
2225                return Type.noType;
2226            }
2227
2228            @Override
2229            public Type visitClassType(ClassType t, Void ignored) {
2230                if (t.supertype_field == null) {
2231                    Type supertype = ((ClassSymbol)t.tsym).getSuperclass();
2232                    // An interface has no superclass; its supertype is Object.
2233                    if (t.isInterface())
2234                        supertype = ((ClassType)t.tsym.type).supertype_field;
2235                    if (t.supertype_field == null) {
2236                        List<Type> actuals = classBound(t).allparams();
2237                        List<Type> formals = t.tsym.type.allparams();
2238                        if (t.hasErasedSupertypes()) {
2239                            t.supertype_field = erasureRecursive(supertype);
2240                        } else if (formals.nonEmpty()) {
2241                            t.supertype_field = subst(supertype, formals, actuals);
2242                        }
2243                        else {
2244                            t.supertype_field = supertype;
2245                        }
2246                    }
2247                }
2248                return t.supertype_field;
2249            }
2250
2251            /**
2252             * The supertype is always a class type. If the type
2253             * variable's bounds start with a class type, this is also
2254             * the supertype.  Otherwise, the supertype is
2255             * java.lang.Object.
2256             */
2257            @Override
2258            public Type visitTypeVar(TypeVar t, Void ignored) {
2259                if (t.bound.hasTag(TYPEVAR) ||
2260                    (!t.bound.isCompound() && !t.bound.isInterface())) {
2261                    return t.bound;
2262                } else {
2263                    return supertype(t.bound);
2264                }
2265            }
2266
2267            @Override
2268            public Type visitArrayType(ArrayType t, Void ignored) {
2269                if (t.elemtype.isPrimitive() || isSameType(t.elemtype, syms.objectType))
2270                    return arraySuperType();
2271                else
2272                    return new ArrayType(supertype(t.elemtype), t.tsym);
2273            }
2274
2275            @Override
2276            public Type visitErrorType(ErrorType t, Void ignored) {
2277                return Type.noType;
2278            }
2279        };
2280    // </editor-fold>
2281
2282    // <editor-fold defaultstate="collapsed" desc="interfaces">
2283    /**
2284     * Return the interfaces implemented by this class.
2285     */
2286    public List<Type> interfaces(Type t) {
2287        return interfaces.visit(t);
2288    }
2289    // where
2290        private UnaryVisitor<List<Type>> interfaces = new UnaryVisitor<List<Type>>() {
2291
2292            public List<Type> visitType(Type t, Void ignored) {
2293                return List.nil();
2294            }
2295
2296            @Override
2297            public List<Type> visitClassType(ClassType t, Void ignored) {
2298                if (t.interfaces_field == null) {
2299                    List<Type> interfaces = ((ClassSymbol)t.tsym).getInterfaces();
2300                    if (t.interfaces_field == null) {
2301                        // If t.interfaces_field is null, then t must
2302                        // be a parameterized type (not to be confused
2303                        // with a generic type declaration).
2304                        // Terminology:
2305                        //    Parameterized type: List<String>
2306                        //    Generic type declaration: class List<E> { ... }
2307                        // So t corresponds to List<String> and
2308                        // t.tsym.type corresponds to List<E>.
2309                        // The reason t must be parameterized type is
2310                        // that completion will happen as a side
2311                        // effect of calling
2312                        // ClassSymbol.getInterfaces.  Since
2313                        // t.interfaces_field is null after
2314                        // completion, we can assume that t is not the
2315                        // type of a class/interface declaration.
2316                        Assert.check(t != t.tsym.type, t);
2317                        List<Type> actuals = t.allparams();
2318                        List<Type> formals = t.tsym.type.allparams();
2319                        if (t.hasErasedSupertypes()) {
2320                            t.interfaces_field = erasureRecursive(interfaces);
2321                        } else if (formals.nonEmpty()) {
2322                            t.interfaces_field = subst(interfaces, formals, actuals);
2323                        }
2324                        else {
2325                            t.interfaces_field = interfaces;
2326                        }
2327                    }
2328                }
2329                return t.interfaces_field;
2330            }
2331
2332            @Override
2333            public List<Type> visitTypeVar(TypeVar t, Void ignored) {
2334                if (t.bound.isCompound())
2335                    return interfaces(t.bound);
2336
2337                if (t.bound.isInterface())
2338                    return List.of(t.bound);
2339
2340                return List.nil();
2341            }
2342        };
2343
2344    public List<Type> directSupertypes(Type t) {
2345        return directSupertypes.visit(t);
2346    }
2347    // where
2348        private final UnaryVisitor<List<Type>> directSupertypes = new UnaryVisitor<List<Type>>() {
2349
2350            public List<Type> visitType(final Type type, final Void ignored) {
2351                if (!type.isIntersection()) {
2352                    final Type sup = supertype(type);
2353                    return (sup == Type.noType || sup == type || sup == null)
2354                        ? interfaces(type)
2355                        : interfaces(type).prepend(sup);
2356                } else {
2357                    return ((IntersectionClassType)type).getExplicitComponents();
2358                }
2359            }
2360        };
2361
2362    public boolean isDirectSuperInterface(TypeSymbol isym, TypeSymbol origin) {
2363        for (Type i2 : interfaces(origin.type)) {
2364            if (isym == i2.tsym) return true;
2365        }
2366        return false;
2367    }
2368    // </editor-fold>
2369
2370    // <editor-fold defaultstate="collapsed" desc="isDerivedRaw">
2371    Map<Type,Boolean> isDerivedRawCache = new HashMap<>();
2372
2373    public boolean isDerivedRaw(Type t) {
2374        Boolean result = isDerivedRawCache.get(t);
2375        if (result == null) {
2376            result = isDerivedRawInternal(t);
2377            isDerivedRawCache.put(t, result);
2378        }
2379        return result;
2380    }
2381
2382    public boolean isDerivedRawInternal(Type t) {
2383        if (t.isErroneous())
2384            return false;
2385        return
2386            t.isRaw() ||
2387            supertype(t) != Type.noType && isDerivedRaw(supertype(t)) ||
2388            isDerivedRaw(interfaces(t));
2389    }
2390
2391    public boolean isDerivedRaw(List<Type> ts) {
2392        List<Type> l = ts;
2393        while (l.nonEmpty() && !isDerivedRaw(l.head)) l = l.tail;
2394        return l.nonEmpty();
2395    }
2396    // </editor-fold>
2397
2398    // <editor-fold defaultstate="collapsed" desc="setBounds">
2399    /**
2400     * Same as {@link Types#setBounds(TypeVar, List, boolean)}, except that third parameter is computed directly,
2401     * as follows: if all all bounds are interface types, the computed supertype is Object,otherwise
2402     * the supertype is simply left null (in this case, the supertype is assumed to be the head of
2403     * the bound list passed as second argument). Note that this check might cause a symbol completion.
2404     * Hence, this version of setBounds may not be called during a classfile read.
2405     *
2406     * @param t         a type variable
2407     * @param bounds    the bounds, must be nonempty
2408     */
2409    public void setBounds(TypeVar t, List<Type> bounds) {
2410        setBounds(t, bounds, bounds.head.tsym.isInterface());
2411    }
2412
2413    /**
2414     * Set the bounds field of the given type variable to reflect a (possibly multiple) list of bounds.
2415     * This does not cause symbol completion as an extra parameter indicates as to whether all bounds
2416     * are interfaces - in which case the supertype is implicitly assumed to be 'Object'.
2417     *
2418     * @param t             a type variable
2419     * @param bounds        the bounds, must be nonempty
2420     * @param allInterfaces are all bounds interface types?
2421     */
2422    public void setBounds(TypeVar t, List<Type> bounds, boolean allInterfaces) {
2423        t.bound = bounds.tail.isEmpty() ?
2424                bounds.head :
2425                makeIntersectionType(bounds, allInterfaces);
2426        t.rank_field = -1;
2427    }
2428    // </editor-fold>
2429
2430    // <editor-fold defaultstate="collapsed" desc="getBounds">
2431    /**
2432     * Return list of bounds of the given type variable.
2433     */
2434    public List<Type> getBounds(TypeVar t) {
2435        if (t.bound.hasTag(NONE))
2436            return List.nil();
2437        else if (t.bound.isErroneous() || !t.bound.isCompound())
2438            return List.of(t.bound);
2439        else if ((erasure(t).tsym.flags() & INTERFACE) == 0)
2440            return interfaces(t).prepend(supertype(t));
2441        else
2442            // No superclass was given in bounds.
2443            // In this case, supertype is Object, erasure is first interface.
2444            return interfaces(t);
2445    }
2446    // </editor-fold>
2447
2448    // <editor-fold defaultstate="collapsed" desc="classBound">
2449    /**
2450     * If the given type is a (possibly selected) type variable,
2451     * return the bounding class of this type, otherwise return the
2452     * type itself.
2453     */
2454    public Type classBound(Type t) {
2455        return classBound.visit(t);
2456    }
2457    // where
2458        private UnaryVisitor<Type> classBound = new UnaryVisitor<Type>() {
2459
2460            public Type visitType(Type t, Void ignored) {
2461                return t;
2462            }
2463
2464            @Override
2465            public Type visitClassType(ClassType t, Void ignored) {
2466                Type outer1 = classBound(t.getEnclosingType());
2467                if (outer1 != t.getEnclosingType())
2468                    return new ClassType(outer1, t.getTypeArguments(), t.tsym,
2469                                         t.getMetadata());
2470                else
2471                    return t;
2472            }
2473
2474            @Override
2475            public Type visitTypeVar(TypeVar t, Void ignored) {
2476                return classBound(supertype(t));
2477            }
2478
2479            @Override
2480            public Type visitErrorType(ErrorType t, Void ignored) {
2481                return t;
2482            }
2483        };
2484    // </editor-fold>
2485
2486    // <editor-fold defaultstate="collapsed" desc="sub signature / override equivalence">
2487    /**
2488     * Returns true iff the first signature is a <em>sub
2489     * signature</em> of the other.  This is <b>not</b> an equivalence
2490     * relation.
2491     *
2492     * @jls section 8.4.2.
2493     * @see #overrideEquivalent(Type t, Type s)
2494     * @param t first signature (possibly raw).
2495     * @param s second signature (could be subjected to erasure).
2496     * @return true if t is a sub signature of s.
2497     */
2498    public boolean isSubSignature(Type t, Type s) {
2499        return isSubSignature(t, s, true);
2500    }
2501
2502    public boolean isSubSignature(Type t, Type s, boolean strict) {
2503        return hasSameArgs(t, s, strict) || hasSameArgs(t, erasure(s), strict);
2504    }
2505
2506    /**
2507     * Returns true iff these signatures are related by <em>override
2508     * equivalence</em>.  This is the natural extension of
2509     * isSubSignature to an equivalence relation.
2510     *
2511     * @jls section 8.4.2.
2512     * @see #isSubSignature(Type t, Type s)
2513     * @param t a signature (possible raw, could be subjected to
2514     * erasure).
2515     * @param s a signature (possible raw, could be subjected to
2516     * erasure).
2517     * @return true if either argument is a sub signature of the other.
2518     */
2519    public boolean overrideEquivalent(Type t, Type s) {
2520        return hasSameArgs(t, s) ||
2521            hasSameArgs(t, erasure(s)) || hasSameArgs(erasure(t), s);
2522    }
2523
2524    public boolean overridesObjectMethod(TypeSymbol origin, Symbol msym) {
2525        for (Symbol sym : syms.objectType.tsym.members().getSymbolsByName(msym.name)) {
2526            if (msym.overrides(sym, origin, Types.this, true)) {
2527                return true;
2528            }
2529        }
2530        return false;
2531    }
2532
2533    /**
2534     * This enum defines the strategy for implementing most specific return type check
2535     * during the most specific and functional interface checks.
2536     */
2537    public enum MostSpecificReturnCheck {
2538        /**
2539         * Return r1 is more specific than r2 if {@code r1 <: r2}. Extra care required for (i) handling
2540         * method type variables (if either method is generic) and (ii) subtyping should be replaced
2541         * by type-equivalence for primitives. This is essentially an inlined version of
2542         * {@link Types#resultSubtype(Type, Type, Warner)}, where the assignability check has been
2543         * replaced with a strict subtyping check.
2544         */
2545        BASIC() {
2546            @Override
2547            public boolean test(Type mt1, Type mt2, Types types) {
2548                List<Type> tvars = mt1.getTypeArguments();
2549                List<Type> svars = mt2.getTypeArguments();
2550                Type t = mt1.getReturnType();
2551                Type s = types.subst(mt2.getReturnType(), svars, tvars);
2552                return types.isSameType(t, s) ||
2553                    !t.isPrimitive() &&
2554                    !s.isPrimitive() &&
2555                    types.isSubtype(t, s);
2556            }
2557        },
2558        /**
2559         * Return r1 is more specific than r2 if r1 is return-type-substitutable for r2.
2560         */
2561        RTS() {
2562            @Override
2563            public boolean test(Type mt1, Type mt2, Types types) {
2564                return types.returnTypeSubstitutable(mt1, mt2);
2565            }
2566        };
2567
2568        public abstract boolean test(Type mt1, Type mt2, Types types);
2569    }
2570
2571    /**
2572     * Merge multiple abstract methods. The preferred method is a method that is a subsignature
2573     * of all the other signatures and whose return type is more specific {@see MostSpecificReturnCheck}.
2574     * The resulting preferred method has a thrown clause that is the intersection of the merged
2575     * methods' clauses.
2576     */
2577    public Optional<Symbol> mergeAbstracts(List<Symbol> ambiguousInOrder, Type site, boolean sigCheck) {
2578        //first check for preconditions
2579        boolean shouldErase = false;
2580        List<Type> erasedParams = ambiguousInOrder.head.erasure(this).getParameterTypes();
2581        for (Symbol s : ambiguousInOrder) {
2582            if ((s.flags() & ABSTRACT) == 0 ||
2583                    (sigCheck && !isSameTypes(erasedParams, s.erasure(this).getParameterTypes()))) {
2584                return Optional.empty();
2585            } else if (s.type.hasTag(FORALL)) {
2586                shouldErase = true;
2587            }
2588        }
2589        //then merge abstracts
2590        for (MostSpecificReturnCheck mostSpecificReturnCheck : MostSpecificReturnCheck.values()) {
2591            outer: for (Symbol s : ambiguousInOrder) {
2592                Type mt = memberType(site, s);
2593                List<Type> allThrown = mt.getThrownTypes();
2594                for (Symbol s2 : ambiguousInOrder) {
2595                    if (s != s2) {
2596                        Type mt2 = memberType(site, s2);
2597                        if (!isSubSignature(mt, mt2) ||
2598                                !mostSpecificReturnCheck.test(mt, mt2, this)) {
2599                            //ambiguity cannot be resolved
2600                            continue outer;
2601                        } else {
2602                            List<Type> thrownTypes2 = mt2.getThrownTypes();
2603                            if (!mt.hasTag(FORALL) && shouldErase) {
2604                                thrownTypes2 = erasure(thrownTypes2);
2605                            } else if (mt.hasTag(FORALL)) {
2606                                //subsignature implies that if most specific is generic, then all other
2607                                //methods are too
2608                                Assert.check(mt2.hasTag(FORALL));
2609                                // if both are generic methods, adjust thrown types ahead of intersection computation
2610                                thrownTypes2 = subst(thrownTypes2, mt2.getTypeArguments(), mt.getTypeArguments());
2611                            }
2612                            allThrown = chk.intersect(allThrown, thrownTypes2);
2613                        }
2614                    }
2615                }
2616                return (allThrown == mt.getThrownTypes()) ?
2617                        Optional.of(s) :
2618                        Optional.of(new MethodSymbol(
2619                                s.flags(),
2620                                s.name,
2621                                createMethodTypeWithThrown(s.type, allThrown),
2622                                s.owner) {
2623                            @Override
2624                            public Symbol baseSymbol() {
2625                                return s;
2626                            }
2627                        });
2628            }
2629        }
2630        return Optional.empty();
2631    }
2632
2633    // <editor-fold defaultstate="collapsed" desc="Determining method implementation in given site">
2634    class ImplementationCache {
2635
2636        private WeakHashMap<MethodSymbol, SoftReference<Map<TypeSymbol, Entry>>> _map = new WeakHashMap<>();
2637
2638        class Entry {
2639            final MethodSymbol cachedImpl;
2640            final Filter<Symbol> implFilter;
2641            final boolean checkResult;
2642            final int prevMark;
2643
2644            public Entry(MethodSymbol cachedImpl,
2645                    Filter<Symbol> scopeFilter,
2646                    boolean checkResult,
2647                    int prevMark) {
2648                this.cachedImpl = cachedImpl;
2649                this.implFilter = scopeFilter;
2650                this.checkResult = checkResult;
2651                this.prevMark = prevMark;
2652            }
2653
2654            boolean matches(Filter<Symbol> scopeFilter, boolean checkResult, int mark) {
2655                return this.implFilter == scopeFilter &&
2656                        this.checkResult == checkResult &&
2657                        this.prevMark == mark;
2658            }
2659        }
2660
2661        MethodSymbol get(MethodSymbol ms, TypeSymbol origin, boolean checkResult, Filter<Symbol> implFilter) {
2662            SoftReference<Map<TypeSymbol, Entry>> ref_cache = _map.get(ms);
2663            Map<TypeSymbol, Entry> cache = ref_cache != null ? ref_cache.get() : null;
2664            if (cache == null) {
2665                cache = new HashMap<>();
2666                _map.put(ms, new SoftReference<>(cache));
2667            }
2668            Entry e = cache.get(origin);
2669            CompoundScope members = membersClosure(origin.type, true);
2670            if (e == null ||
2671                    !e.matches(implFilter, checkResult, members.getMark())) {
2672                MethodSymbol impl = implementationInternal(ms, origin, checkResult, implFilter);
2673                cache.put(origin, new Entry(impl, implFilter, checkResult, members.getMark()));
2674                return impl;
2675            }
2676            else {
2677                return e.cachedImpl;
2678            }
2679        }
2680
2681        private MethodSymbol implementationInternal(MethodSymbol ms, TypeSymbol origin, boolean checkResult, Filter<Symbol> implFilter) {
2682            for (Type t = origin.type; t.hasTag(CLASS) || t.hasTag(TYPEVAR); t = supertype(t)) {
2683                t = skipTypeVars(t, false);
2684                TypeSymbol c = t.tsym;
2685                Symbol bestSoFar = null;
2686                for (Symbol sym : c.members().getSymbolsByName(ms.name, implFilter)) {
2687                    if (sym != null && sym.overrides(ms, origin, Types.this, checkResult)) {
2688                        bestSoFar = sym;
2689                        if ((sym.flags() & ABSTRACT) == 0) {
2690                            //if concrete impl is found, exit immediately
2691                            break;
2692                        }
2693                    }
2694                }
2695                if (bestSoFar != null) {
2696                    //return either the (only) concrete implementation or the first abstract one
2697                    return (MethodSymbol)bestSoFar;
2698                }
2699            }
2700            return null;
2701        }
2702    }
2703
2704    private ImplementationCache implCache = new ImplementationCache();
2705
2706    public MethodSymbol implementation(MethodSymbol ms, TypeSymbol origin, boolean checkResult, Filter<Symbol> implFilter) {
2707        return implCache.get(ms, origin, checkResult, implFilter);
2708    }
2709    // </editor-fold>
2710
2711    // <editor-fold defaultstate="collapsed" desc="compute transitive closure of all members in given site">
2712    class MembersClosureCache extends SimpleVisitor<Scope.CompoundScope, Void> {
2713
2714        private Map<TypeSymbol, CompoundScope> _map = new HashMap<>();
2715
2716        Set<TypeSymbol> seenTypes = new HashSet<>();
2717
2718        class MembersScope extends CompoundScope {
2719
2720            CompoundScope scope;
2721
2722            public MembersScope(CompoundScope scope) {
2723                super(scope.owner);
2724                this.scope = scope;
2725            }
2726
2727            Filter<Symbol> combine(Filter<Symbol> sf) {
2728                return s -> !s.owner.isInterface() && (sf == null || sf.accepts(s));
2729            }
2730
2731            @Override
2732            public Iterable<Symbol> getSymbols(Filter<Symbol> sf, LookupKind lookupKind) {
2733                return scope.getSymbols(combine(sf), lookupKind);
2734            }
2735
2736            @Override
2737            public Iterable<Symbol> getSymbolsByName(Name name, Filter<Symbol> sf, LookupKind lookupKind) {
2738                return scope.getSymbolsByName(name, combine(sf), lookupKind);
2739            }
2740
2741            @Override
2742            public int getMark() {
2743                return scope.getMark();
2744            }
2745        }
2746
2747        CompoundScope nilScope;
2748
2749        /** members closure visitor methods **/
2750
2751        public CompoundScope visitType(Type t, Void _unused) {
2752            if (nilScope == null) {
2753                nilScope = new CompoundScope(syms.noSymbol);
2754            }
2755            return nilScope;
2756        }
2757
2758        @Override
2759        public CompoundScope visitClassType(ClassType t, Void _unused) {
2760            if (!seenTypes.add(t.tsym)) {
2761                //this is possible when an interface is implemented in multiple
2762                //superclasses, or when a class hierarchy is circular - in such
2763                //cases we don't need to recurse (empty scope is returned)
2764                return new CompoundScope(t.tsym);
2765            }
2766            try {
2767                seenTypes.add(t.tsym);
2768                ClassSymbol csym = (ClassSymbol)t.tsym;
2769                CompoundScope membersClosure = _map.get(csym);
2770                if (membersClosure == null) {
2771                    membersClosure = new CompoundScope(csym);
2772                    for (Type i : interfaces(t)) {
2773                        membersClosure.prependSubScope(visit(i, null));
2774                    }
2775                    membersClosure.prependSubScope(visit(supertype(t), null));
2776                    membersClosure.prependSubScope(csym.members());
2777                    _map.put(csym, membersClosure);
2778                }
2779                return membersClosure;
2780            }
2781            finally {
2782                seenTypes.remove(t.tsym);
2783            }
2784        }
2785
2786        @Override
2787        public CompoundScope visitTypeVar(TypeVar t, Void _unused) {
2788            return visit(t.getUpperBound(), null);
2789        }
2790    }
2791
2792    private MembersClosureCache membersCache = new MembersClosureCache();
2793
2794    public CompoundScope membersClosure(Type site, boolean skipInterface) {
2795        CompoundScope cs = membersCache.visit(site, null);
2796        Assert.checkNonNull(cs, () -> "type " + site);
2797        return skipInterface ? membersCache.new MembersScope(cs) : cs;
2798    }
2799    // </editor-fold>
2800
2801
2802    /** Return first abstract member of class `sym'.
2803     */
2804    public MethodSymbol firstUnimplementedAbstract(ClassSymbol sym) {
2805        try {
2806            return firstUnimplementedAbstractImpl(sym, sym);
2807        } catch (CompletionFailure ex) {
2808            chk.completionError(enter.getEnv(sym).tree.pos(), ex);
2809            return null;
2810        }
2811    }
2812        //where:
2813        private MethodSymbol firstUnimplementedAbstractImpl(ClassSymbol impl, ClassSymbol c) {
2814            MethodSymbol undef = null;
2815            // Do not bother to search in classes that are not abstract,
2816            // since they cannot have abstract members.
2817            if (c == impl || (c.flags() & (ABSTRACT | INTERFACE)) != 0) {
2818                Scope s = c.members();
2819                for (Symbol sym : s.getSymbols(NON_RECURSIVE)) {
2820                    if (sym.kind == MTH &&
2821                        (sym.flags() & (ABSTRACT|DEFAULT|PRIVATE)) == ABSTRACT) {
2822                        MethodSymbol absmeth = (MethodSymbol)sym;
2823                        MethodSymbol implmeth = absmeth.implementation(impl, this, true);
2824                        if (implmeth == null || implmeth == absmeth) {
2825                            //look for default implementations
2826                            if (allowDefaultMethods) {
2827                                MethodSymbol prov = interfaceCandidates(impl.type, absmeth).head;
2828                                if (prov != null && prov.overrides(absmeth, impl, this, true)) {
2829                                    implmeth = prov;
2830                                }
2831                            }
2832                        }
2833                        if (implmeth == null || implmeth == absmeth) {
2834                            undef = absmeth;
2835                            break;
2836                        }
2837                    }
2838                }
2839                if (undef == null) {
2840                    Type st = supertype(c.type);
2841                    if (st.hasTag(CLASS))
2842                        undef = firstUnimplementedAbstractImpl(impl, (ClassSymbol)st.tsym);
2843                }
2844                for (List<Type> l = interfaces(c.type);
2845                     undef == null && l.nonEmpty();
2846                     l = l.tail) {
2847                    undef = firstUnimplementedAbstractImpl(impl, (ClassSymbol)l.head.tsym);
2848                }
2849            }
2850            return undef;
2851        }
2852
2853    public class CandidatesCache {
2854        public Map<Entry, List<MethodSymbol>> cache = new WeakHashMap<>();
2855
2856        class Entry {
2857            Type site;
2858            MethodSymbol msym;
2859
2860            Entry(Type site, MethodSymbol msym) {
2861                this.site = site;
2862                this.msym = msym;
2863            }
2864
2865            @Override
2866            public boolean equals(Object obj) {
2867                if (obj instanceof Entry) {
2868                    Entry e = (Entry)obj;
2869                    return e.msym == msym && isSameType(site, e.site);
2870                } else {
2871                    return false;
2872                }
2873            }
2874
2875            @Override
2876            public int hashCode() {
2877                return Types.this.hashCode(site) & ~msym.hashCode();
2878            }
2879        }
2880
2881        public List<MethodSymbol> get(Entry e) {
2882            return cache.get(e);
2883        }
2884
2885        public void put(Entry e, List<MethodSymbol> msymbols) {
2886            cache.put(e, msymbols);
2887        }
2888    }
2889
2890    public CandidatesCache candidatesCache = new CandidatesCache();
2891
2892    //where
2893    public List<MethodSymbol> interfaceCandidates(Type site, MethodSymbol ms) {
2894        CandidatesCache.Entry e = candidatesCache.new Entry(site, ms);
2895        List<MethodSymbol> candidates = candidatesCache.get(e);
2896        if (candidates == null) {
2897            Filter<Symbol> filter = new MethodFilter(ms, site);
2898            List<MethodSymbol> candidates2 = List.nil();
2899            for (Symbol s : membersClosure(site, false).getSymbols(filter)) {
2900                if (!site.tsym.isInterface() && !s.owner.isInterface()) {
2901                    return List.of((MethodSymbol)s);
2902                } else if (!candidates2.contains(s)) {
2903                    candidates2 = candidates2.prepend((MethodSymbol)s);
2904                }
2905            }
2906            candidates = prune(candidates2);
2907            candidatesCache.put(e, candidates);
2908        }
2909        return candidates;
2910    }
2911
2912    public List<MethodSymbol> prune(List<MethodSymbol> methods) {
2913        ListBuffer<MethodSymbol> methodsMin = new ListBuffer<>();
2914        for (MethodSymbol m1 : methods) {
2915            boolean isMin_m1 = true;
2916            for (MethodSymbol m2 : methods) {
2917                if (m1 == m2) continue;
2918                if (m2.owner != m1.owner &&
2919                        asSuper(m2.owner.type, m1.owner) != null) {
2920                    isMin_m1 = false;
2921                    break;
2922                }
2923            }
2924            if (isMin_m1)
2925                methodsMin.append(m1);
2926        }
2927        return methodsMin.toList();
2928    }
2929    // where
2930            private class MethodFilter implements Filter<Symbol> {
2931
2932                Symbol msym;
2933                Type site;
2934
2935                MethodFilter(Symbol msym, Type site) {
2936                    this.msym = msym;
2937                    this.site = site;
2938                }
2939
2940                public boolean accepts(Symbol s) {
2941                    return s.kind == MTH &&
2942                            s.name == msym.name &&
2943                            (s.flags() & SYNTHETIC) == 0 &&
2944                            s.isInheritedIn(site.tsym, Types.this) &&
2945                            overrideEquivalent(memberType(site, s), memberType(site, msym));
2946                }
2947            }
2948    // </editor-fold>
2949
2950    /**
2951     * Does t have the same arguments as s?  It is assumed that both
2952     * types are (possibly polymorphic) method types.  Monomorphic
2953     * method types "have the same arguments", if their argument lists
2954     * are equal.  Polymorphic method types "have the same arguments",
2955     * if they have the same arguments after renaming all type
2956     * variables of one to corresponding type variables in the other,
2957     * where correspondence is by position in the type parameter list.
2958     */
2959    public boolean hasSameArgs(Type t, Type s) {
2960        return hasSameArgs(t, s, true);
2961    }
2962
2963    public boolean hasSameArgs(Type t, Type s, boolean strict) {
2964        return hasSameArgs(t, s, strict ? hasSameArgs_strict : hasSameArgs_nonstrict);
2965    }
2966
2967    private boolean hasSameArgs(Type t, Type s, TypeRelation hasSameArgs) {
2968        return hasSameArgs.visit(t, s);
2969    }
2970    // where
2971        private class HasSameArgs extends TypeRelation {
2972
2973            boolean strict;
2974
2975            public HasSameArgs(boolean strict) {
2976                this.strict = strict;
2977            }
2978
2979            public Boolean visitType(Type t, Type s) {
2980                throw new AssertionError();
2981            }
2982
2983            @Override
2984            public Boolean visitMethodType(MethodType t, Type s) {
2985                return s.hasTag(METHOD)
2986                    && containsTypeEquivalent(t.argtypes, s.getParameterTypes());
2987            }
2988
2989            @Override
2990            public Boolean visitForAll(ForAll t, Type s) {
2991                if (!s.hasTag(FORALL))
2992                    return strict ? false : visitMethodType(t.asMethodType(), s);
2993
2994                ForAll forAll = (ForAll)s;
2995                return hasSameBounds(t, forAll)
2996                    && visit(t.qtype, subst(forAll.qtype, forAll.tvars, t.tvars));
2997            }
2998
2999            @Override
3000            public Boolean visitErrorType(ErrorType t, Type s) {
3001                return false;
3002            }
3003        }
3004
3005    TypeRelation hasSameArgs_strict = new HasSameArgs(true);
3006        TypeRelation hasSameArgs_nonstrict = new HasSameArgs(false);
3007
3008    // </editor-fold>
3009
3010    // <editor-fold defaultstate="collapsed" desc="subst">
3011    public List<Type> subst(List<Type> ts,
3012                            List<Type> from,
3013                            List<Type> to) {
3014        return ts.map(new Subst(from, to));
3015    }
3016
3017    /**
3018     * Substitute all occurrences of a type in `from' with the
3019     * corresponding type in `to' in 't'. Match lists `from' and `to'
3020     * from the right: If lists have different length, discard leading
3021     * elements of the longer list.
3022     */
3023    public Type subst(Type t, List<Type> from, List<Type> to) {
3024        return t.map(new Subst(from, to));
3025    }
3026
3027    private class Subst extends TypeMapping<Void> {
3028        List<Type> from;
3029        List<Type> to;
3030
3031        public Subst(List<Type> from, List<Type> to) {
3032            int fromLength = from.length();
3033            int toLength = to.length();
3034            while (fromLength > toLength) {
3035                fromLength--;
3036                from = from.tail;
3037            }
3038            while (fromLength < toLength) {
3039                toLength--;
3040                to = to.tail;
3041            }
3042            this.from = from;
3043            this.to = to;
3044        }
3045
3046        @Override
3047        public Type visitTypeVar(TypeVar t, Void ignored) {
3048            for (List<Type> from = this.from, to = this.to;
3049                 from.nonEmpty();
3050                 from = from.tail, to = to.tail) {
3051                if (t.equalsIgnoreMetadata(from.head)) {
3052                    return to.head.withTypeVar(t);
3053                }
3054            }
3055            return t;
3056        }
3057
3058        @Override
3059        public Type visitClassType(ClassType t, Void ignored) {
3060            if (!t.isCompound()) {
3061                return super.visitClassType(t, ignored);
3062            } else {
3063                Type st = visit(supertype(t));
3064                List<Type> is = visit(interfaces(t), ignored);
3065                if (st == supertype(t) && is == interfaces(t))
3066                    return t;
3067                else
3068                    return makeIntersectionType(is.prepend(st));
3069            }
3070        }
3071
3072        @Override
3073        public Type visitWildcardType(WildcardType t, Void ignored) {
3074            WildcardType t2 = (WildcardType)super.visitWildcardType(t, ignored);
3075            if (t2 != t && t.isExtendsBound() && t2.type.isExtendsBound()) {
3076                t2.type = wildUpperBound(t2.type);
3077            }
3078            return t2;
3079        }
3080
3081        @Override
3082        public Type visitForAll(ForAll t, Void ignored) {
3083            if (Type.containsAny(to, t.tvars)) {
3084                //perform alpha-renaming of free-variables in 't'
3085                //if 'to' types contain variables that are free in 't'
3086                List<Type> freevars = newInstances(t.tvars);
3087                t = new ForAll(freevars,
3088                               Types.this.subst(t.qtype, t.tvars, freevars));
3089            }
3090            List<Type> tvars1 = substBounds(t.tvars, from, to);
3091            Type qtype1 = visit(t.qtype);
3092            if (tvars1 == t.tvars && qtype1 == t.qtype) {
3093                return t;
3094            } else if (tvars1 == t.tvars) {
3095                return new ForAll(tvars1, qtype1) {
3096                    @Override
3097                    public boolean needsStripping() {
3098                        return true;
3099                    }
3100                };
3101            } else {
3102                return new ForAll(tvars1, Types.this.subst(qtype1, t.tvars, tvars1)) {
3103                    @Override
3104                    public boolean needsStripping() {
3105                        return true;
3106                    }
3107                };
3108            }
3109        }
3110    }
3111
3112    public List<Type> substBounds(List<Type> tvars,
3113                                  List<Type> from,
3114                                  List<Type> to) {
3115        if (tvars.isEmpty())
3116            return tvars;
3117        ListBuffer<Type> newBoundsBuf = new ListBuffer<>();
3118        boolean changed = false;
3119        // calculate new bounds
3120        for (Type t : tvars) {
3121            TypeVar tv = (TypeVar) t;
3122            Type bound = subst(tv.bound, from, to);
3123            if (bound != tv.bound)
3124                changed = true;
3125            newBoundsBuf.append(bound);
3126        }
3127        if (!changed)
3128            return tvars;
3129        ListBuffer<Type> newTvars = new ListBuffer<>();
3130        // create new type variables without bounds
3131        for (Type t : tvars) {
3132            newTvars.append(new TypeVar(t.tsym, null, syms.botType,
3133                                        t.getMetadata()));
3134        }
3135        // the new bounds should use the new type variables in place
3136        // of the old
3137        List<Type> newBounds = newBoundsBuf.toList();
3138        from = tvars;
3139        to = newTvars.toList();
3140        for (; !newBounds.isEmpty(); newBounds = newBounds.tail) {
3141            newBounds.head = subst(newBounds.head, from, to);
3142        }
3143        newBounds = newBoundsBuf.toList();
3144        // set the bounds of new type variables to the new bounds
3145        for (Type t : newTvars.toList()) {
3146            TypeVar tv = (TypeVar) t;
3147            tv.bound = newBounds.head;
3148            newBounds = newBounds.tail;
3149        }
3150        return newTvars.toList();
3151    }
3152
3153    public TypeVar substBound(TypeVar t, List<Type> from, List<Type> to) {
3154        Type bound1 = subst(t.bound, from, to);
3155        if (bound1 == t.bound)
3156            return t;
3157        else {
3158            // create new type variable without bounds
3159            TypeVar tv = new TypeVar(t.tsym, null, syms.botType,
3160                                     t.getMetadata());
3161            // the new bound should use the new type variable in place
3162            // of the old
3163            tv.bound = subst(bound1, List.<Type>of(t), List.<Type>of(tv));
3164            return tv;
3165        }
3166    }
3167    // </editor-fold>
3168
3169    // <editor-fold defaultstate="collapsed" desc="hasSameBounds">
3170    /**
3171     * Does t have the same bounds for quantified variables as s?
3172     */
3173    public boolean hasSameBounds(ForAll t, ForAll s) {
3174        List<Type> l1 = t.tvars;
3175        List<Type> l2 = s.tvars;
3176        while (l1.nonEmpty() && l2.nonEmpty() &&
3177               isSameType(l1.head.getUpperBound(),
3178                          subst(l2.head.getUpperBound(),
3179                                s.tvars,
3180                                t.tvars))) {
3181            l1 = l1.tail;
3182            l2 = l2.tail;
3183        }
3184        return l1.isEmpty() && l2.isEmpty();
3185    }
3186    // </editor-fold>
3187
3188    // <editor-fold defaultstate="collapsed" desc="newInstances">
3189    /** Create new vector of type variables from list of variables
3190     *  changing all recursive bounds from old to new list.
3191     */
3192    public List<Type> newInstances(List<Type> tvars) {
3193        List<Type> tvars1 = tvars.map(newInstanceFun);
3194        for (List<Type> l = tvars1; l.nonEmpty(); l = l.tail) {
3195            TypeVar tv = (TypeVar) l.head;
3196            tv.bound = subst(tv.bound, tvars, tvars1);
3197        }
3198        return tvars1;
3199    }
3200        private static final TypeMapping<Void> newInstanceFun = new TypeMapping<Void>() {
3201            @Override
3202            public TypeVar visitTypeVar(TypeVar t, Void _unused) {
3203                return new TypeVar(t.tsym, t.getUpperBound(), t.getLowerBound(), t.getMetadata());
3204            }
3205        };
3206    // </editor-fold>
3207
3208    public Type createMethodTypeWithParameters(Type original, List<Type> newParams) {
3209        return original.accept(methodWithParameters, newParams);
3210    }
3211    // where
3212        private final MapVisitor<List<Type>> methodWithParameters = new MapVisitor<List<Type>>() {
3213            public Type visitType(Type t, List<Type> newParams) {
3214                throw new IllegalArgumentException("Not a method type: " + t);
3215            }
3216            public Type visitMethodType(MethodType t, List<Type> newParams) {
3217                return new MethodType(newParams, t.restype, t.thrown, t.tsym);
3218            }
3219            public Type visitForAll(ForAll t, List<Type> newParams) {
3220                return new ForAll(t.tvars, t.qtype.accept(this, newParams));
3221            }
3222        };
3223
3224    public Type createMethodTypeWithThrown(Type original, List<Type> newThrown) {
3225        return original.accept(methodWithThrown, newThrown);
3226    }
3227    // where
3228        private final MapVisitor<List<Type>> methodWithThrown = new MapVisitor<List<Type>>() {
3229            public Type visitType(Type t, List<Type> newThrown) {
3230                throw new IllegalArgumentException("Not a method type: " + t);
3231            }
3232            public Type visitMethodType(MethodType t, List<Type> newThrown) {
3233                return new MethodType(t.argtypes, t.restype, newThrown, t.tsym);
3234            }
3235            public Type visitForAll(ForAll t, List<Type> newThrown) {
3236                return new ForAll(t.tvars, t.qtype.accept(this, newThrown));
3237            }
3238        };
3239
3240    public Type createMethodTypeWithReturn(Type original, Type newReturn) {
3241        return original.accept(methodWithReturn, newReturn);
3242    }
3243    // where
3244        private final MapVisitor<Type> methodWithReturn = new MapVisitor<Type>() {
3245            public Type visitType(Type t, Type newReturn) {
3246                throw new IllegalArgumentException("Not a method type: " + t);
3247            }
3248            public Type visitMethodType(MethodType t, Type newReturn) {
3249                return new MethodType(t.argtypes, newReturn, t.thrown, t.tsym) {
3250                    @Override
3251                    public Type baseType() {
3252                        return t;
3253                    }
3254                };
3255            }
3256            public Type visitForAll(ForAll t, Type newReturn) {
3257                return new ForAll(t.tvars, t.qtype.accept(this, newReturn)) {
3258                    @Override
3259                    public Type baseType() {
3260                        return t;
3261                    }
3262                };
3263            }
3264        };
3265
3266    // <editor-fold defaultstate="collapsed" desc="createErrorType">
3267    public Type createErrorType(Type originalType) {
3268        return new ErrorType(originalType, syms.errSymbol);
3269    }
3270
3271    public Type createErrorType(ClassSymbol c, Type originalType) {
3272        return new ErrorType(c, originalType);
3273    }
3274
3275    public Type createErrorType(Name name, TypeSymbol container, Type originalType) {
3276        return new ErrorType(name, container, originalType);
3277    }
3278    // </editor-fold>
3279
3280    // <editor-fold defaultstate="collapsed" desc="rank">
3281    /**
3282     * The rank of a class is the length of the longest path between
3283     * the class and java.lang.Object in the class inheritance
3284     * graph. Undefined for all but reference types.
3285     */
3286    public int rank(Type t) {
3287        switch(t.getTag()) {
3288        case CLASS: {
3289            ClassType cls = (ClassType)t;
3290            if (cls.rank_field < 0) {
3291                Name fullname = cls.tsym.getQualifiedName();
3292                if (fullname == names.java_lang_Object)
3293                    cls.rank_field = 0;
3294                else {
3295                    int r = rank(supertype(cls));
3296                    for (List<Type> l = interfaces(cls);
3297                         l.nonEmpty();
3298                         l = l.tail) {
3299                        if (rank(l.head) > r)
3300                            r = rank(l.head);
3301                    }
3302                    cls.rank_field = r + 1;
3303                }
3304            }
3305            return cls.rank_field;
3306        }
3307        case TYPEVAR: {
3308            TypeVar tvar = (TypeVar)t;
3309            if (tvar.rank_field < 0) {
3310                int r = rank(supertype(tvar));
3311                for (List<Type> l = interfaces(tvar);
3312                     l.nonEmpty();
3313                     l = l.tail) {
3314                    if (rank(l.head) > r) r = rank(l.head);
3315                }
3316                tvar.rank_field = r + 1;
3317            }
3318            return tvar.rank_field;
3319        }
3320        case ERROR:
3321        case NONE:
3322            return 0;
3323        default:
3324            throw new AssertionError();
3325        }
3326    }
3327    // </editor-fold>
3328
3329    /**
3330     * Helper method for generating a string representation of a given type
3331     * accordingly to a given locale
3332     */
3333    public String toString(Type t, Locale locale) {
3334        return Printer.createStandardPrinter(messages).visit(t, locale);
3335    }
3336
3337    /**
3338     * Helper method for generating a string representation of a given type
3339     * accordingly to a given locale
3340     */
3341    public String toString(Symbol t, Locale locale) {
3342        return Printer.createStandardPrinter(messages).visit(t, locale);
3343    }
3344
3345    // <editor-fold defaultstate="collapsed" desc="toString">
3346    /**
3347     * This toString is slightly more descriptive than the one on Type.
3348     *
3349     * @deprecated Types.toString(Type t, Locale l) provides better support
3350     * for localization
3351     */
3352    @Deprecated
3353    public String toString(Type t) {
3354        if (t.hasTag(FORALL)) {
3355            ForAll forAll = (ForAll)t;
3356            return typaramsString(forAll.tvars) + forAll.qtype;
3357        }
3358        return "" + t;
3359    }
3360    // where
3361        private String typaramsString(List<Type> tvars) {
3362            StringBuilder s = new StringBuilder();
3363            s.append('<');
3364            boolean first = true;
3365            for (Type t : tvars) {
3366                if (!first) s.append(", ");
3367                first = false;
3368                appendTyparamString(((TypeVar)t), s);
3369            }
3370            s.append('>');
3371            return s.toString();
3372        }
3373        private void appendTyparamString(TypeVar t, StringBuilder buf) {
3374            buf.append(t);
3375            if (t.bound == null ||
3376                t.bound.tsym.getQualifiedName() == names.java_lang_Object)
3377                return;
3378            buf.append(" extends "); // Java syntax; no need for i18n
3379            Type bound = t.bound;
3380            if (!bound.isCompound()) {
3381                buf.append(bound);
3382            } else if ((erasure(t).tsym.flags() & INTERFACE) == 0) {
3383                buf.append(supertype(t));
3384                for (Type intf : interfaces(t)) {
3385                    buf.append('&');
3386                    buf.append(intf);
3387                }
3388            } else {
3389                // No superclass was given in bounds.
3390                // In this case, supertype is Object, erasure is first interface.
3391                boolean first = true;
3392                for (Type intf : interfaces(t)) {
3393                    if (!first) buf.append('&');
3394                    first = false;
3395                    buf.append(intf);
3396                }
3397            }
3398        }
3399    // </editor-fold>
3400
3401    // <editor-fold defaultstate="collapsed" desc="Determining least upper bounds of types">
3402    /**
3403     * A cache for closures.
3404     *
3405     * <p>A closure is a list of all the supertypes and interfaces of
3406     * a class or interface type, ordered by ClassSymbol.precedes
3407     * (that is, subclasses come first, arbitrary but fixed
3408     * otherwise).
3409     */
3410    private Map<Type,List<Type>> closureCache = new HashMap<>();
3411
3412    /**
3413     * Returns the closure of a class or interface type.
3414     */
3415    public List<Type> closure(Type t) {
3416        List<Type> cl = closureCache.get(t);
3417        if (cl == null) {
3418            Type st = supertype(t);
3419            if (!t.isCompound()) {
3420                if (st.hasTag(CLASS)) {
3421                    cl = insert(closure(st), t);
3422                } else if (st.hasTag(TYPEVAR)) {
3423                    cl = closure(st).prepend(t);
3424                } else {
3425                    cl = List.of(t);
3426                }
3427            } else {
3428                cl = closure(supertype(t));
3429            }
3430            for (List<Type> l = interfaces(t); l.nonEmpty(); l = l.tail)
3431                cl = union(cl, closure(l.head));
3432            closureCache.put(t, cl);
3433        }
3434        return cl;
3435    }
3436
3437    /**
3438     * Collect types into a new closure (using a @code{ClosureHolder})
3439     */
3440    public Collector<Type, ClosureHolder, List<Type>> closureCollector(boolean minClosure, BiPredicate<Type, Type> shouldSkip) {
3441        return Collector.of(() -> new ClosureHolder(minClosure, shouldSkip),
3442                ClosureHolder::add,
3443                ClosureHolder::merge,
3444                ClosureHolder::closure);
3445    }
3446    //where
3447        class ClosureHolder {
3448            List<Type> closure;
3449            final boolean minClosure;
3450            final BiPredicate<Type, Type> shouldSkip;
3451
3452            ClosureHolder(boolean minClosure, BiPredicate<Type, Type> shouldSkip) {
3453                this.closure = List.nil();
3454                this.minClosure = minClosure;
3455                this.shouldSkip = shouldSkip;
3456            }
3457
3458            void add(Type type) {
3459                closure = insert(closure, type, shouldSkip);
3460            }
3461
3462            ClosureHolder merge(ClosureHolder other) {
3463                closure = union(closure, other.closure, shouldSkip);
3464                return this;
3465            }
3466
3467            List<Type> closure() {
3468                return minClosure ? closureMin(closure) : closure;
3469            }
3470        }
3471
3472    BiPredicate<Type, Type> basicClosureSkip = (t1, t2) -> t1.tsym == t2.tsym;
3473
3474    /**
3475     * Insert a type in a closure
3476     */
3477    public List<Type> insert(List<Type> cl, Type t, BiPredicate<Type, Type> shouldSkip) {
3478        if (cl.isEmpty()) {
3479            return cl.prepend(t);
3480        } else if (shouldSkip.test(t, cl.head)) {
3481            return cl;
3482        } else if (t.tsym.precedes(cl.head.tsym, this)) {
3483            return cl.prepend(t);
3484        } else {
3485            // t comes after head, or the two are unrelated
3486            return insert(cl.tail, t, shouldSkip).prepend(cl.head);
3487        }
3488    }
3489
3490    public List<Type> insert(List<Type> cl, Type t) {
3491        return insert(cl, t, basicClosureSkip);
3492    }
3493
3494    /**
3495     * Form the union of two closures
3496     */
3497    public List<Type> union(List<Type> cl1, List<Type> cl2, BiPredicate<Type, Type> shouldSkip) {
3498        if (cl1.isEmpty()) {
3499            return cl2;
3500        } else if (cl2.isEmpty()) {
3501            return cl1;
3502        } else if (shouldSkip.test(cl1.head, cl2.head)) {
3503            return union(cl1.tail, cl2.tail, shouldSkip).prepend(cl1.head);
3504        } else if (cl1.head.tsym.precedes(cl2.head.tsym, this)) {
3505            return union(cl1.tail, cl2, shouldSkip).prepend(cl1.head);
3506        } else if (cl2.head.tsym.precedes(cl1.head.tsym, this)) {
3507            return union(cl1, cl2.tail, shouldSkip).prepend(cl2.head);
3508        } else {
3509            // unrelated types
3510            return union(cl1.tail, cl2, shouldSkip).prepend(cl1.head);
3511        }
3512    }
3513
3514    public List<Type> union(List<Type> cl1, List<Type> cl2) {
3515        return union(cl1, cl2, basicClosureSkip);
3516    }
3517
3518    /**
3519     * Intersect two closures
3520     */
3521    public List<Type> intersect(List<Type> cl1, List<Type> cl2) {
3522        if (cl1 == cl2)
3523            return cl1;
3524        if (cl1.isEmpty() || cl2.isEmpty())
3525            return List.nil();
3526        if (cl1.head.tsym.precedes(cl2.head.tsym, this))
3527            return intersect(cl1.tail, cl2);
3528        if (cl2.head.tsym.precedes(cl1.head.tsym, this))
3529            return intersect(cl1, cl2.tail);
3530        if (isSameType(cl1.head, cl2.head))
3531            return intersect(cl1.tail, cl2.tail).prepend(cl1.head);
3532        if (cl1.head.tsym == cl2.head.tsym &&
3533            cl1.head.hasTag(CLASS) && cl2.head.hasTag(CLASS)) {
3534            if (cl1.head.isParameterized() && cl2.head.isParameterized()) {
3535                Type merge = merge(cl1.head,cl2.head);
3536                return intersect(cl1.tail, cl2.tail).prepend(merge);
3537            }
3538            if (cl1.head.isRaw() || cl2.head.isRaw())
3539                return intersect(cl1.tail, cl2.tail).prepend(erasure(cl1.head));
3540        }
3541        return intersect(cl1.tail, cl2.tail);
3542    }
3543    // where
3544        class TypePair {
3545            final Type t1;
3546            final Type t2;
3547            boolean strict;
3548
3549            TypePair(Type t1, Type t2) {
3550                this(t1, t2, false);
3551            }
3552
3553            TypePair(Type t1, Type t2, boolean strict) {
3554                this.t1 = t1;
3555                this.t2 = t2;
3556                this.strict = strict;
3557            }
3558            @Override
3559            public int hashCode() {
3560                return 127 * Types.this.hashCode(t1) + Types.this.hashCode(t2);
3561            }
3562            @Override
3563            public boolean equals(Object obj) {
3564                if (!(obj instanceof TypePair))
3565                    return false;
3566                TypePair typePair = (TypePair)obj;
3567                return isSameType(t1, typePair.t1, strict)
3568                    && isSameType(t2, typePair.t2, strict);
3569            }
3570        }
3571        Set<TypePair> mergeCache = new HashSet<>();
3572        private Type merge(Type c1, Type c2) {
3573            ClassType class1 = (ClassType) c1;
3574            List<Type> act1 = class1.getTypeArguments();
3575            ClassType class2 = (ClassType) c2;
3576            List<Type> act2 = class2.getTypeArguments();
3577            ListBuffer<Type> merged = new ListBuffer<>();
3578            List<Type> typarams = class1.tsym.type.getTypeArguments();
3579
3580            while (act1.nonEmpty() && act2.nonEmpty() && typarams.nonEmpty()) {
3581                if (containsType(act1.head, act2.head)) {
3582                    merged.append(act1.head);
3583                } else if (containsType(act2.head, act1.head)) {
3584                    merged.append(act2.head);
3585                } else {
3586                    TypePair pair = new TypePair(c1, c2);
3587                    Type m;
3588                    if (mergeCache.add(pair)) {
3589                        m = new WildcardType(lub(wildUpperBound(act1.head),
3590                                                 wildUpperBound(act2.head)),
3591                                             BoundKind.EXTENDS,
3592                                             syms.boundClass);
3593                        mergeCache.remove(pair);
3594                    } else {
3595                        m = new WildcardType(syms.objectType,
3596                                             BoundKind.UNBOUND,
3597                                             syms.boundClass);
3598                    }
3599                    merged.append(m.withTypeVar(typarams.head));
3600                }
3601                act1 = act1.tail;
3602                act2 = act2.tail;
3603                typarams = typarams.tail;
3604            }
3605            Assert.check(act1.isEmpty() && act2.isEmpty() && typarams.isEmpty());
3606            // There is no spec detailing how type annotations are to
3607            // be inherited.  So set it to noAnnotations for now
3608            return new ClassType(class1.getEnclosingType(), merged.toList(),
3609                                 class1.tsym);
3610        }
3611
3612    /**
3613     * Return the minimum type of a closure, a compound type if no
3614     * unique minimum exists.
3615     */
3616    private Type compoundMin(List<Type> cl) {
3617        if (cl.isEmpty()) return syms.objectType;
3618        List<Type> compound = closureMin(cl);
3619        if (compound.isEmpty())
3620            return null;
3621        else if (compound.tail.isEmpty())
3622            return compound.head;
3623        else
3624            return makeIntersectionType(compound);
3625    }
3626
3627    /**
3628     * Return the minimum types of a closure, suitable for computing
3629     * compoundMin or glb.
3630     */
3631    private List<Type> closureMin(List<Type> cl) {
3632        ListBuffer<Type> classes = new ListBuffer<>();
3633        ListBuffer<Type> interfaces = new ListBuffer<>();
3634        Set<Type> toSkip = new HashSet<>();
3635        while (!cl.isEmpty()) {
3636            Type current = cl.head;
3637            boolean keep = !toSkip.contains(current);
3638            if (keep && current.hasTag(TYPEVAR)) {
3639                // skip lower-bounded variables with a subtype in cl.tail
3640                for (Type t : cl.tail) {
3641                    if (isSubtypeNoCapture(t, current)) {
3642                        keep = false;
3643                        break;
3644                    }
3645                }
3646            }
3647            if (keep) {
3648                if (current.isInterface())
3649                    interfaces.append(current);
3650                else
3651                    classes.append(current);
3652                for (Type t : cl.tail) {
3653                    // skip supertypes of 'current' in cl.tail
3654                    if (isSubtypeNoCapture(current, t))
3655                        toSkip.add(t);
3656                }
3657            }
3658            cl = cl.tail;
3659        }
3660        return classes.appendList(interfaces).toList();
3661    }
3662
3663    /**
3664     * Return the least upper bound of list of types.  if the lub does
3665     * not exist return null.
3666     */
3667    public Type lub(List<Type> ts) {
3668        return lub(ts.toArray(new Type[ts.length()]));
3669    }
3670
3671    /**
3672     * Return the least upper bound (lub) of set of types.  If the lub
3673     * does not exist return the type of null (bottom).
3674     */
3675    public Type lub(Type... ts) {
3676        final int UNKNOWN_BOUND = 0;
3677        final int ARRAY_BOUND = 1;
3678        final int CLASS_BOUND = 2;
3679
3680        int[] kinds = new int[ts.length];
3681
3682        int boundkind = UNKNOWN_BOUND;
3683        for (int i = 0 ; i < ts.length ; i++) {
3684            Type t = ts[i];
3685            switch (t.getTag()) {
3686            case CLASS:
3687                boundkind |= kinds[i] = CLASS_BOUND;
3688                break;
3689            case ARRAY:
3690                boundkind |= kinds[i] = ARRAY_BOUND;
3691                break;
3692            case  TYPEVAR:
3693                do {
3694                    t = t.getUpperBound();
3695                } while (t.hasTag(TYPEVAR));
3696                if (t.hasTag(ARRAY)) {
3697                    boundkind |= kinds[i] = ARRAY_BOUND;
3698                } else {
3699                    boundkind |= kinds[i] = CLASS_BOUND;
3700                }
3701                break;
3702            default:
3703                kinds[i] = UNKNOWN_BOUND;
3704                if (t.isPrimitive())
3705                    return syms.errType;
3706            }
3707        }
3708        switch (boundkind) {
3709        case 0:
3710            return syms.botType;
3711
3712        case ARRAY_BOUND:
3713            // calculate lub(A[], B[])
3714            Type[] elements = new Type[ts.length];
3715            for (int i = 0 ; i < ts.length ; i++) {
3716                Type elem = elements[i] = elemTypeFun.apply(ts[i]);
3717                if (elem.isPrimitive()) {
3718                    // if a primitive type is found, then return
3719                    // arraySuperType unless all the types are the
3720                    // same
3721                    Type first = ts[0];
3722                    for (int j = 1 ; j < ts.length ; j++) {
3723                        if (!isSameType(first, ts[j])) {
3724                             // lub(int[], B[]) is Cloneable & Serializable
3725                            return arraySuperType();
3726                        }
3727                    }
3728                    // all the array types are the same, return one
3729                    // lub(int[], int[]) is int[]
3730                    return first;
3731                }
3732            }
3733            // lub(A[], B[]) is lub(A, B)[]
3734            return new ArrayType(lub(elements), syms.arrayClass);
3735
3736        case CLASS_BOUND:
3737            // calculate lub(A, B)
3738            int startIdx = 0;
3739            for (int i = 0; i < ts.length ; i++) {
3740                Type t = ts[i];
3741                if (t.hasTag(CLASS) || t.hasTag(TYPEVAR)) {
3742                    break;
3743                } else {
3744                    startIdx++;
3745                }
3746            }
3747            Assert.check(startIdx < ts.length);
3748            //step 1 - compute erased candidate set (EC)
3749            List<Type> cl = erasedSupertypes(ts[startIdx]);
3750            for (int i = startIdx + 1 ; i < ts.length ; i++) {
3751                Type t = ts[i];
3752                if (t.hasTag(CLASS) || t.hasTag(TYPEVAR))
3753                    cl = intersect(cl, erasedSupertypes(t));
3754            }
3755            //step 2 - compute minimal erased candidate set (MEC)
3756            List<Type> mec = closureMin(cl);
3757            //step 3 - for each element G in MEC, compute lci(Inv(G))
3758            List<Type> candidates = List.nil();
3759            for (Type erasedSupertype : mec) {
3760                List<Type> lci = List.of(asSuper(ts[startIdx], erasedSupertype.tsym));
3761                for (int i = startIdx + 1 ; i < ts.length ; i++) {
3762                    Type superType = asSuper(ts[i], erasedSupertype.tsym);
3763                    lci = intersect(lci, superType != null ? List.of(superType) : List.<Type>nil());
3764                }
3765                candidates = candidates.appendList(lci);
3766            }
3767            //step 4 - let MEC be { G1, G2 ... Gn }, then we have that
3768            //lub = lci(Inv(G1)) & lci(Inv(G2)) & ... & lci(Inv(Gn))
3769            return compoundMin(candidates);
3770
3771        default:
3772            // calculate lub(A, B[])
3773            List<Type> classes = List.of(arraySuperType());
3774            for (int i = 0 ; i < ts.length ; i++) {
3775                if (kinds[i] != ARRAY_BOUND) // Filter out any arrays
3776                    classes = classes.prepend(ts[i]);
3777            }
3778            // lub(A, B[]) is lub(A, arraySuperType)
3779            return lub(classes);
3780        }
3781    }
3782    // where
3783        List<Type> erasedSupertypes(Type t) {
3784            ListBuffer<Type> buf = new ListBuffer<>();
3785            for (Type sup : closure(t)) {
3786                if (sup.hasTag(TYPEVAR)) {
3787                    buf.append(sup);
3788                } else {
3789                    buf.append(erasure(sup));
3790                }
3791            }
3792            return buf.toList();
3793        }
3794
3795        private Type arraySuperType = null;
3796        private Type arraySuperType() {
3797            // initialized lazily to avoid problems during compiler startup
3798            if (arraySuperType == null) {
3799                synchronized (this) {
3800                    if (arraySuperType == null) {
3801                        // JLS 10.8: all arrays implement Cloneable and Serializable.
3802                        arraySuperType = makeIntersectionType(List.of(syms.serializableType,
3803                                syms.cloneableType), true);
3804                    }
3805                }
3806            }
3807            return arraySuperType;
3808        }
3809    // </editor-fold>
3810
3811    // <editor-fold defaultstate="collapsed" desc="Greatest lower bound">
3812    public Type glb(List<Type> ts) {
3813        Type t1 = ts.head;
3814        for (Type t2 : ts.tail) {
3815            if (t1.isErroneous())
3816                return t1;
3817            t1 = glb(t1, t2);
3818        }
3819        return t1;
3820    }
3821    //where
3822    public Type glb(Type t, Type s) {
3823        if (s == null)
3824            return t;
3825        else if (t.isPrimitive() || s.isPrimitive())
3826            return syms.errType;
3827        else if (isSubtypeNoCapture(t, s))
3828            return t;
3829        else if (isSubtypeNoCapture(s, t))
3830            return s;
3831
3832        List<Type> closure = union(closure(t), closure(s));
3833        return glbFlattened(closure, t);
3834    }
3835    //where
3836    /**
3837     * Perform glb for a list of non-primitive, non-error, non-compound types;
3838     * redundant elements are removed.  Bounds should be ordered according to
3839     * {@link Symbol#precedes(TypeSymbol,Types)}.
3840     *
3841     * @param flatBounds List of type to glb
3842     * @param errT Original type to use if the result is an error type
3843     */
3844    private Type glbFlattened(List<Type> flatBounds, Type errT) {
3845        List<Type> bounds = closureMin(flatBounds);
3846
3847        if (bounds.isEmpty()) {             // length == 0
3848            return syms.objectType;
3849        } else if (bounds.tail.isEmpty()) { // length == 1
3850            return bounds.head;
3851        } else {                            // length > 1
3852            int classCount = 0;
3853            List<Type> lowers = List.nil();
3854            for (Type bound : bounds) {
3855                if (!bound.isInterface()) {
3856                    classCount++;
3857                    Type lower = cvarLowerBound(bound);
3858                    if (bound != lower && !lower.hasTag(BOT))
3859                        lowers = insert(lowers, lower);
3860                }
3861            }
3862            if (classCount > 1) {
3863                if (lowers.isEmpty())
3864                    return createErrorType(errT);
3865                else
3866                    return glbFlattened(union(bounds, lowers), errT);
3867            }
3868        }
3869        return makeIntersectionType(bounds);
3870    }
3871    // </editor-fold>
3872
3873    // <editor-fold defaultstate="collapsed" desc="hashCode">
3874    /**
3875     * Compute a hash code on a type.
3876     */
3877    public int hashCode(Type t) {
3878        return hashCode(t, false);
3879    }
3880
3881    public int hashCode(Type t, boolean strict) {
3882        return strict ?
3883                hashCodeStrictVisitor.visit(t) :
3884                hashCodeVisitor.visit(t);
3885    }
3886    // where
3887        private static final HashCodeVisitor hashCodeVisitor = new HashCodeVisitor();
3888        private static final HashCodeVisitor hashCodeStrictVisitor = new HashCodeVisitor() {
3889            @Override
3890            public Integer visitTypeVar(TypeVar t, Void ignored) {
3891                return System.identityHashCode(t);
3892            }
3893        };
3894
3895        private static class HashCodeVisitor extends UnaryVisitor<Integer> {
3896            public Integer visitType(Type t, Void ignored) {
3897                return t.getTag().ordinal();
3898            }
3899
3900            @Override
3901            public Integer visitClassType(ClassType t, Void ignored) {
3902                int result = visit(t.getEnclosingType());
3903                result *= 127;
3904                result += t.tsym.flatName().hashCode();
3905                for (Type s : t.getTypeArguments()) {
3906                    result *= 127;
3907                    result += visit(s);
3908                }
3909                return result;
3910            }
3911
3912            @Override
3913            public Integer visitMethodType(MethodType t, Void ignored) {
3914                int h = METHOD.ordinal();
3915                for (List<Type> thisargs = t.argtypes;
3916                     thisargs.tail != null;
3917                     thisargs = thisargs.tail)
3918                    h = (h << 5) + visit(thisargs.head);
3919                return (h << 5) + visit(t.restype);
3920            }
3921
3922            @Override
3923            public Integer visitWildcardType(WildcardType t, Void ignored) {
3924                int result = t.kind.hashCode();
3925                if (t.type != null) {
3926                    result *= 127;
3927                    result += visit(t.type);
3928                }
3929                return result;
3930            }
3931
3932            @Override
3933            public Integer visitArrayType(ArrayType t, Void ignored) {
3934                return visit(t.elemtype) + 12;
3935            }
3936
3937            @Override
3938            public Integer visitTypeVar(TypeVar t, Void ignored) {
3939                return System.identityHashCode(t);
3940            }
3941
3942            @Override
3943            public Integer visitUndetVar(UndetVar t, Void ignored) {
3944                return System.identityHashCode(t);
3945            }
3946
3947            @Override
3948            public Integer visitErrorType(ErrorType t, Void ignored) {
3949                return 0;
3950            }
3951        }
3952    // </editor-fold>
3953
3954    // <editor-fold defaultstate="collapsed" desc="Return-Type-Substitutable">
3955    /**
3956     * Does t have a result that is a subtype of the result type of s,
3957     * suitable for covariant returns?  It is assumed that both types
3958     * are (possibly polymorphic) method types.  Monomorphic method
3959     * types are handled in the obvious way.  Polymorphic method types
3960     * require renaming all type variables of one to corresponding
3961     * type variables in the other, where correspondence is by
3962     * position in the type parameter list. */
3963    public boolean resultSubtype(Type t, Type s, Warner warner) {
3964        List<Type> tvars = t.getTypeArguments();
3965        List<Type> svars = s.getTypeArguments();
3966        Type tres = t.getReturnType();
3967        Type sres = subst(s.getReturnType(), svars, tvars);
3968        return covariantReturnType(tres, sres, warner);
3969    }
3970
3971    /**
3972     * Return-Type-Substitutable.
3973     * @jls section 8.4.5
3974     */
3975    public boolean returnTypeSubstitutable(Type r1, Type r2) {
3976        if (hasSameArgs(r1, r2))
3977            return resultSubtype(r1, r2, noWarnings);
3978        else
3979            return covariantReturnType(r1.getReturnType(),
3980                                       erasure(r2.getReturnType()),
3981                                       noWarnings);
3982    }
3983
3984    public boolean returnTypeSubstitutable(Type r1,
3985                                           Type r2, Type r2res,
3986                                           Warner warner) {
3987        if (isSameType(r1.getReturnType(), r2res))
3988            return true;
3989        if (r1.getReturnType().isPrimitive() || r2res.isPrimitive())
3990            return false;
3991
3992        if (hasSameArgs(r1, r2))
3993            return covariantReturnType(r1.getReturnType(), r2res, warner);
3994        if (isSubtypeUnchecked(r1.getReturnType(), r2res, warner))
3995            return true;
3996        if (!isSubtype(r1.getReturnType(), erasure(r2res)))
3997            return false;
3998        warner.warn(LintCategory.UNCHECKED);
3999        return true;
4000    }
4001
4002    /**
4003     * Is t an appropriate return type in an overrider for a
4004     * method that returns s?
4005     */
4006    public boolean covariantReturnType(Type t, Type s, Warner warner) {
4007        return
4008            isSameType(t, s) ||
4009            !t.isPrimitive() &&
4010            !s.isPrimitive() &&
4011            isAssignable(t, s, warner);
4012    }
4013    // </editor-fold>
4014
4015    // <editor-fold defaultstate="collapsed" desc="Box/unbox support">
4016    /**
4017     * Return the class that boxes the given primitive.
4018     */
4019    public ClassSymbol boxedClass(Type t) {
4020        return syms.enterClass(syms.java_base, syms.boxedName[t.getTag().ordinal()]);
4021    }
4022
4023    /**
4024     * Return the boxed type if 't' is primitive, otherwise return 't' itself.
4025     */
4026    public Type boxedTypeOrType(Type t) {
4027        return t.isPrimitive() ?
4028            boxedClass(t).type :
4029            t;
4030    }
4031
4032    /**
4033     * Return the primitive type corresponding to a boxed type.
4034     */
4035    public Type unboxedType(Type t) {
4036        for (int i=0; i<syms.boxedName.length; i++) {
4037            Name box = syms.boxedName[i];
4038            if (box != null &&
4039                asSuper(t, syms.enterClass(syms.java_base, box)) != null)
4040                return syms.typeOfTag[i];
4041        }
4042        return Type.noType;
4043    }
4044
4045    /**
4046     * Return the unboxed type if 't' is a boxed class, otherwise return 't' itself.
4047     */
4048    public Type unboxedTypeOrType(Type t) {
4049        Type unboxedType = unboxedType(t);
4050        return unboxedType.hasTag(NONE) ? t : unboxedType;
4051    }
4052    // </editor-fold>
4053
4054    // <editor-fold defaultstate="collapsed" desc="Capture conversion">
4055    /*
4056     * JLS 5.1.10 Capture Conversion:
4057     *
4058     * Let G name a generic type declaration with n formal type
4059     * parameters A1 ... An with corresponding bounds U1 ... Un. There
4060     * exists a capture conversion from G<T1 ... Tn> to G<S1 ... Sn>,
4061     * where, for 1 <= i <= n:
4062     *
4063     * + If Ti is a wildcard type argument (4.5.1) of the form ? then
4064     *   Si is a fresh type variable whose upper bound is
4065     *   Ui[A1 := S1, ..., An := Sn] and whose lower bound is the null
4066     *   type.
4067     *
4068     * + If Ti is a wildcard type argument of the form ? extends Bi,
4069     *   then Si is a fresh type variable whose upper bound is
4070     *   glb(Bi, Ui[A1 := S1, ..., An := Sn]) and whose lower bound is
4071     *   the null type, where glb(V1,... ,Vm) is V1 & ... & Vm. It is
4072     *   a compile-time error if for any two classes (not interfaces)
4073     *   Vi and Vj,Vi is not a subclass of Vj or vice versa.
4074     *
4075     * + If Ti is a wildcard type argument of the form ? super Bi,
4076     *   then Si is a fresh type variable whose upper bound is
4077     *   Ui[A1 := S1, ..., An := Sn] and whose lower bound is Bi.
4078     *
4079     * + Otherwise, Si = Ti.
4080     *
4081     * Capture conversion on any type other than a parameterized type
4082     * (4.5) acts as an identity conversion (5.1.1). Capture
4083     * conversions never require a special action at run time and
4084     * therefore never throw an exception at run time.
4085     *
4086     * Capture conversion is not applied recursively.
4087     */
4088    /**
4089     * Capture conversion as specified by the JLS.
4090     */
4091
4092    public List<Type> capture(List<Type> ts) {
4093        List<Type> buf = List.nil();
4094        for (Type t : ts) {
4095            buf = buf.prepend(capture(t));
4096        }
4097        return buf.reverse();
4098    }
4099
4100    public Type capture(Type t) {
4101        if (!t.hasTag(CLASS)) {
4102            return t;
4103        }
4104        if (t.getEnclosingType() != Type.noType) {
4105            Type capturedEncl = capture(t.getEnclosingType());
4106            if (capturedEncl != t.getEnclosingType()) {
4107                Type type1 = memberType(capturedEncl, t.tsym);
4108                t = subst(type1, t.tsym.type.getTypeArguments(), t.getTypeArguments());
4109            }
4110        }
4111        ClassType cls = (ClassType)t;
4112        if (cls.isRaw() || !cls.isParameterized())
4113            return cls;
4114
4115        ClassType G = (ClassType)cls.asElement().asType();
4116        List<Type> A = G.getTypeArguments();
4117        List<Type> T = cls.getTypeArguments();
4118        List<Type> S = freshTypeVariables(T);
4119
4120        List<Type> currentA = A;
4121        List<Type> currentT = T;
4122        List<Type> currentS = S;
4123        boolean captured = false;
4124        while (!currentA.isEmpty() &&
4125               !currentT.isEmpty() &&
4126               !currentS.isEmpty()) {
4127            if (currentS.head != currentT.head) {
4128                captured = true;
4129                WildcardType Ti = (WildcardType)currentT.head;
4130                Type Ui = currentA.head.getUpperBound();
4131                CapturedType Si = (CapturedType)currentS.head;
4132                if (Ui == null)
4133                    Ui = syms.objectType;
4134                switch (Ti.kind) {
4135                case UNBOUND:
4136                    Si.bound = subst(Ui, A, S);
4137                    Si.lower = syms.botType;
4138                    break;
4139                case EXTENDS:
4140                    Si.bound = glb(Ti.getExtendsBound(), subst(Ui, A, S));
4141                    Si.lower = syms.botType;
4142                    break;
4143                case SUPER:
4144                    Si.bound = subst(Ui, A, S);
4145                    Si.lower = Ti.getSuperBound();
4146                    break;
4147                }
4148                Type tmpBound = Si.bound.hasTag(UNDETVAR) ? ((UndetVar)Si.bound).qtype : Si.bound;
4149                Type tmpLower = Si.lower.hasTag(UNDETVAR) ? ((UndetVar)Si.lower).qtype : Si.lower;
4150                if (!Si.bound.hasTag(ERROR) &&
4151                    !Si.lower.hasTag(ERROR) &&
4152                    isSameType(tmpBound, tmpLower, false)) {
4153                    currentS.head = Si.bound;
4154                }
4155            }
4156            currentA = currentA.tail;
4157            currentT = currentT.tail;
4158            currentS = currentS.tail;
4159        }
4160        if (!currentA.isEmpty() || !currentT.isEmpty() || !currentS.isEmpty())
4161            return erasure(t); // some "rare" type involved
4162
4163        if (captured)
4164            return new ClassType(cls.getEnclosingType(), S, cls.tsym,
4165                                 cls.getMetadata());
4166        else
4167            return t;
4168    }
4169    // where
4170        public List<Type> freshTypeVariables(List<Type> types) {
4171            ListBuffer<Type> result = new ListBuffer<>();
4172            for (Type t : types) {
4173                if (t.hasTag(WILDCARD)) {
4174                    Type bound = ((WildcardType)t).getExtendsBound();
4175                    if (bound == null)
4176                        bound = syms.objectType;
4177                    result.append(new CapturedType(capturedName,
4178                                                   syms.noSymbol,
4179                                                   bound,
4180                                                   syms.botType,
4181                                                   (WildcardType)t));
4182                } else {
4183                    result.append(t);
4184                }
4185            }
4186            return result.toList();
4187        }
4188    // </editor-fold>
4189
4190    // <editor-fold defaultstate="collapsed" desc="Internal utility methods">
4191    private boolean sideCast(Type from, Type to, Warner warn) {
4192        // We are casting from type $from$ to type $to$, which are
4193        // non-final unrelated types.  This method
4194        // tries to reject a cast by transferring type parameters
4195        // from $to$ to $from$ by common superinterfaces.
4196        boolean reverse = false;
4197        Type target = to;
4198        if ((to.tsym.flags() & INTERFACE) == 0) {
4199            Assert.check((from.tsym.flags() & INTERFACE) != 0);
4200            reverse = true;
4201            to = from;
4202            from = target;
4203        }
4204        List<Type> commonSupers = superClosure(to, erasure(from));
4205        boolean giveWarning = commonSupers.isEmpty();
4206        // The arguments to the supers could be unified here to
4207        // get a more accurate analysis
4208        while (commonSupers.nonEmpty()) {
4209            Type t1 = asSuper(from, commonSupers.head.tsym);
4210            Type t2 = commonSupers.head; // same as asSuper(to, commonSupers.head.tsym);
4211            if (disjointTypes(t1.getTypeArguments(), t2.getTypeArguments()))
4212                return false;
4213            giveWarning = giveWarning || (reverse ? giveWarning(t2, t1) : giveWarning(t1, t2));
4214            commonSupers = commonSupers.tail;
4215        }
4216        if (giveWarning && !isReifiable(reverse ? from : to))
4217            warn.warn(LintCategory.UNCHECKED);
4218        return true;
4219    }
4220
4221    private boolean sideCastFinal(Type from, Type to, Warner warn) {
4222        // We are casting from type $from$ to type $to$, which are
4223        // unrelated types one of which is final and the other of
4224        // which is an interface.  This method
4225        // tries to reject a cast by transferring type parameters
4226        // from the final class to the interface.
4227        boolean reverse = false;
4228        Type target = to;
4229        if ((to.tsym.flags() & INTERFACE) == 0) {
4230            Assert.check((from.tsym.flags() & INTERFACE) != 0);
4231            reverse = true;
4232            to = from;
4233            from = target;
4234        }
4235        Assert.check((from.tsym.flags() & FINAL) != 0);
4236        Type t1 = asSuper(from, to.tsym);
4237        if (t1 == null) return false;
4238        Type t2 = to;
4239        if (disjointTypes(t1.getTypeArguments(), t2.getTypeArguments()))
4240            return false;
4241        if (!isReifiable(target) &&
4242            (reverse ? giveWarning(t2, t1) : giveWarning(t1, t2)))
4243            warn.warn(LintCategory.UNCHECKED);
4244        return true;
4245    }
4246
4247    private boolean giveWarning(Type from, Type to) {
4248        List<Type> bounds = to.isCompound() ?
4249                directSupertypes(to) : List.of(to);
4250        for (Type b : bounds) {
4251            Type subFrom = asSub(from, b.tsym);
4252            if (b.isParameterized() &&
4253                    (!(isUnbounded(b) ||
4254                    isSubtype(from, b) ||
4255                    ((subFrom != null) && containsType(b.allparams(), subFrom.allparams()))))) {
4256                return true;
4257            }
4258        }
4259        return false;
4260    }
4261
4262    private List<Type> superClosure(Type t, Type s) {
4263        List<Type> cl = List.nil();
4264        for (List<Type> l = interfaces(t); l.nonEmpty(); l = l.tail) {
4265            if (isSubtype(s, erasure(l.head))) {
4266                cl = insert(cl, l.head);
4267            } else {
4268                cl = union(cl, superClosure(l.head, s));
4269            }
4270        }
4271        return cl;
4272    }
4273
4274    private boolean containsTypeEquivalent(Type t, Type s) {
4275        return isSameType(t, s) || // shortcut
4276            containsType(t, s) && containsType(s, t);
4277    }
4278
4279    // <editor-fold defaultstate="collapsed" desc="adapt">
4280    /**
4281     * Adapt a type by computing a substitution which maps a source
4282     * type to a target type.
4283     *
4284     * @param source    the source type
4285     * @param target    the target type
4286     * @param from      the type variables of the computed substitution
4287     * @param to        the types of the computed substitution.
4288     */
4289    public void adapt(Type source,
4290                       Type target,
4291                       ListBuffer<Type> from,
4292                       ListBuffer<Type> to) throws AdaptFailure {
4293        new Adapter(from, to).adapt(source, target);
4294    }
4295
4296    class Adapter extends SimpleVisitor<Void, Type> {
4297
4298        ListBuffer<Type> from;
4299        ListBuffer<Type> to;
4300        Map<Symbol,Type> mapping;
4301
4302        Adapter(ListBuffer<Type> from, ListBuffer<Type> to) {
4303            this.from = from;
4304            this.to = to;
4305            mapping = new HashMap<>();
4306        }
4307
4308        public void adapt(Type source, Type target) throws AdaptFailure {
4309            visit(source, target);
4310            List<Type> fromList = from.toList();
4311            List<Type> toList = to.toList();
4312            while (!fromList.isEmpty()) {
4313                Type val = mapping.get(fromList.head.tsym);
4314                if (toList.head != val)
4315                    toList.head = val;
4316                fromList = fromList.tail;
4317                toList = toList.tail;
4318            }
4319        }
4320
4321        @Override
4322        public Void visitClassType(ClassType source, Type target) throws AdaptFailure {
4323            if (target.hasTag(CLASS))
4324                adaptRecursive(source.allparams(), target.allparams());
4325            return null;
4326        }
4327
4328        @Override
4329        public Void visitArrayType(ArrayType source, Type target) throws AdaptFailure {
4330            if (target.hasTag(ARRAY))
4331                adaptRecursive(elemtype(source), elemtype(target));
4332            return null;
4333        }
4334
4335        @Override
4336        public Void visitWildcardType(WildcardType source, Type target) throws AdaptFailure {
4337            if (source.isExtendsBound())
4338                adaptRecursive(wildUpperBound(source), wildUpperBound(target));
4339            else if (source.isSuperBound())
4340                adaptRecursive(wildLowerBound(source), wildLowerBound(target));
4341            return null;
4342        }
4343
4344        @Override
4345        public Void visitTypeVar(TypeVar source, Type target) throws AdaptFailure {
4346            // Check to see if there is
4347            // already a mapping for $source$, in which case
4348            // the old mapping will be merged with the new
4349            Type val = mapping.get(source.tsym);
4350            if (val != null) {
4351                if (val.isSuperBound() && target.isSuperBound()) {
4352                    val = isSubtype(wildLowerBound(val), wildLowerBound(target))
4353                        ? target : val;
4354                } else if (val.isExtendsBound() && target.isExtendsBound()) {
4355                    val = isSubtype(wildUpperBound(val), wildUpperBound(target))
4356                        ? val : target;
4357                } else if (!isSameType(val, target)) {
4358                    throw new AdaptFailure();
4359                }
4360            } else {
4361                val = target;
4362                from.append(source);
4363                to.append(target);
4364            }
4365            mapping.put(source.tsym, val);
4366            return null;
4367        }
4368
4369        @Override
4370        public Void visitType(Type source, Type target) {
4371            return null;
4372        }
4373
4374        private Set<TypePair> cache = new HashSet<>();
4375
4376        private void adaptRecursive(Type source, Type target) {
4377            TypePair pair = new TypePair(source, target);
4378            if (cache.add(pair)) {
4379                try {
4380                    visit(source, target);
4381                } finally {
4382                    cache.remove(pair);
4383                }
4384            }
4385        }
4386
4387        private void adaptRecursive(List<Type> source, List<Type> target) {
4388            if (source.length() == target.length()) {
4389                while (source.nonEmpty()) {
4390                    adaptRecursive(source.head, target.head);
4391                    source = source.tail;
4392                    target = target.tail;
4393                }
4394            }
4395        }
4396    }
4397
4398    public static class AdaptFailure extends RuntimeException {
4399        static final long serialVersionUID = -7490231548272701566L;
4400    }
4401
4402    private void adaptSelf(Type t,
4403                           ListBuffer<Type> from,
4404                           ListBuffer<Type> to) {
4405        try {
4406            //if (t.tsym.type != t)
4407                adapt(t.tsym.type, t, from, to);
4408        } catch (AdaptFailure ex) {
4409            // Adapt should never fail calculating a mapping from
4410            // t.tsym.type to t as there can be no merge problem.
4411            throw new AssertionError(ex);
4412        }
4413    }
4414    // </editor-fold>
4415
4416    /**
4417     * Rewrite all type variables (universal quantifiers) in the given
4418     * type to wildcards (existential quantifiers).  This is used to
4419     * determine if a cast is allowed.  For example, if high is true
4420     * and {@code T <: Number}, then {@code List<T>} is rewritten to
4421     * {@code List<?  extends Number>}.  Since {@code List<Integer> <:
4422     * List<? extends Number>} a {@code List<T>} can be cast to {@code
4423     * List<Integer>} with a warning.
4424     * @param t a type
4425     * @param high if true return an upper bound; otherwise a lower
4426     * bound
4427     * @param rewriteTypeVars only rewrite captured wildcards if false;
4428     * otherwise rewrite all type variables
4429     * @return the type rewritten with wildcards (existential
4430     * quantifiers) only
4431     */
4432    private Type rewriteQuantifiers(Type t, boolean high, boolean rewriteTypeVars) {
4433        return new Rewriter(high, rewriteTypeVars).visit(t);
4434    }
4435
4436    class Rewriter extends UnaryVisitor<Type> {
4437
4438        boolean high;
4439        boolean rewriteTypeVars;
4440
4441        Rewriter(boolean high, boolean rewriteTypeVars) {
4442            this.high = high;
4443            this.rewriteTypeVars = rewriteTypeVars;
4444        }
4445
4446        @Override
4447        public Type visitClassType(ClassType t, Void s) {
4448            ListBuffer<Type> rewritten = new ListBuffer<>();
4449            boolean changed = false;
4450            for (Type arg : t.allparams()) {
4451                Type bound = visit(arg);
4452                if (arg != bound) {
4453                    changed = true;
4454                }
4455                rewritten.append(bound);
4456            }
4457            if (changed)
4458                return subst(t.tsym.type,
4459                        t.tsym.type.allparams(),
4460                        rewritten.toList());
4461            else
4462                return t;
4463        }
4464
4465        public Type visitType(Type t, Void s) {
4466            return t;
4467        }
4468
4469        @Override
4470        public Type visitCapturedType(CapturedType t, Void s) {
4471            Type w_bound = t.wildcard.type;
4472            Type bound = w_bound.contains(t) ?
4473                        erasure(w_bound) :
4474                        visit(w_bound);
4475            return rewriteAsWildcardType(visit(bound), t.wildcard.bound, t.wildcard.kind);
4476        }
4477
4478        @Override
4479        public Type visitTypeVar(TypeVar t, Void s) {
4480            if (rewriteTypeVars) {
4481                Type bound = t.bound.contains(t) ?
4482                        erasure(t.bound) :
4483                        visit(t.bound);
4484                return rewriteAsWildcardType(bound, t, EXTENDS);
4485            } else {
4486                return t;
4487            }
4488        }
4489
4490        @Override
4491        public Type visitWildcardType(WildcardType t, Void s) {
4492            Type bound2 = visit(t.type);
4493            return t.type == bound2 ? t : rewriteAsWildcardType(bound2, t.bound, t.kind);
4494        }
4495
4496        private Type rewriteAsWildcardType(Type bound, TypeVar formal, BoundKind bk) {
4497            switch (bk) {
4498               case EXTENDS: return high ?
4499                       makeExtendsWildcard(B(bound), formal) :
4500                       makeExtendsWildcard(syms.objectType, formal);
4501               case SUPER: return high ?
4502                       makeSuperWildcard(syms.botType, formal) :
4503                       makeSuperWildcard(B(bound), formal);
4504               case UNBOUND: return makeExtendsWildcard(syms.objectType, formal);
4505               default:
4506                   Assert.error("Invalid bound kind " + bk);
4507                   return null;
4508            }
4509        }
4510
4511        Type B(Type t) {
4512            while (t.hasTag(WILDCARD)) {
4513                WildcardType w = (WildcardType)t;
4514                t = high ?
4515                    w.getExtendsBound() :
4516                    w.getSuperBound();
4517                if (t == null) {
4518                    t = high ? syms.objectType : syms.botType;
4519                }
4520            }
4521            return t;
4522        }
4523    }
4524
4525
4526    /**
4527     * Create a wildcard with the given upper (extends) bound; create
4528     * an unbounded wildcard if bound is Object.
4529     *
4530     * @param bound the upper bound
4531     * @param formal the formal type parameter that will be
4532     * substituted by the wildcard
4533     */
4534    private WildcardType makeExtendsWildcard(Type bound, TypeVar formal) {
4535        if (bound == syms.objectType) {
4536            return new WildcardType(syms.objectType,
4537                                    BoundKind.UNBOUND,
4538                                    syms.boundClass,
4539                                    formal);
4540        } else {
4541            return new WildcardType(bound,
4542                                    BoundKind.EXTENDS,
4543                                    syms.boundClass,
4544                                    formal);
4545        }
4546    }
4547
4548    /**
4549     * Create a wildcard with the given lower (super) bound; create an
4550     * unbounded wildcard if bound is bottom (type of {@code null}).
4551     *
4552     * @param bound the lower bound
4553     * @param formal the formal type parameter that will be
4554     * substituted by the wildcard
4555     */
4556    private WildcardType makeSuperWildcard(Type bound, TypeVar formal) {
4557        if (bound.hasTag(BOT)) {
4558            return new WildcardType(syms.objectType,
4559                                    BoundKind.UNBOUND,
4560                                    syms.boundClass,
4561                                    formal);
4562        } else {
4563            return new WildcardType(bound,
4564                                    BoundKind.SUPER,
4565                                    syms.boundClass,
4566                                    formal);
4567        }
4568    }
4569
4570    /**
4571     * A wrapper for a type that allows use in sets.
4572     */
4573    public static class UniqueType {
4574        public final Type type;
4575        final Types types;
4576
4577        public UniqueType(Type type, Types types) {
4578            this.type = type;
4579            this.types = types;
4580        }
4581
4582        public int hashCode() {
4583            return types.hashCode(type);
4584        }
4585
4586        public boolean equals(Object obj) {
4587            return (obj instanceof UniqueType) &&
4588                types.isSameType(type, ((UniqueType)obj).type);
4589        }
4590
4591        public String toString() {
4592            return type.toString();
4593        }
4594
4595    }
4596    // </editor-fold>
4597
4598    // <editor-fold defaultstate="collapsed" desc="Visitors">
4599    /**
4600     * A default visitor for types.  All visitor methods except
4601     * visitType are implemented by delegating to visitType.  Concrete
4602     * subclasses must provide an implementation of visitType and can
4603     * override other methods as needed.
4604     *
4605     * @param <R> the return type of the operation implemented by this
4606     * visitor; use Void if no return type is needed.
4607     * @param <S> the type of the second argument (the first being the
4608     * type itself) of the operation implemented by this visitor; use
4609     * Void if a second argument is not needed.
4610     */
4611    public static abstract class DefaultTypeVisitor<R,S> implements Type.Visitor<R,S> {
4612        final public R visit(Type t, S s)               { return t.accept(this, s); }
4613        public R visitClassType(ClassType t, S s)       { return visitType(t, s); }
4614        public R visitWildcardType(WildcardType t, S s) { return visitType(t, s); }
4615        public R visitArrayType(ArrayType t, S s)       { return visitType(t, s); }
4616        public R visitMethodType(MethodType t, S s)     { return visitType(t, s); }
4617        public R visitPackageType(PackageType t, S s)   { return visitType(t, s); }
4618        public R visitModuleType(ModuleType t, S s)     { return visitType(t, s); }
4619        public R visitTypeVar(TypeVar t, S s)           { return visitType(t, s); }
4620        public R visitCapturedType(CapturedType t, S s) { return visitType(t, s); }
4621        public R visitForAll(ForAll t, S s)             { return visitType(t, s); }
4622        public R visitUndetVar(UndetVar t, S s)         { return visitType(t, s); }
4623        public R visitErrorType(ErrorType t, S s)       { return visitType(t, s); }
4624    }
4625
4626    /**
4627     * A default visitor for symbols.  All visitor methods except
4628     * visitSymbol are implemented by delegating to visitSymbol.  Concrete
4629     * subclasses must provide an implementation of visitSymbol and can
4630     * override other methods as needed.
4631     *
4632     * @param <R> the return type of the operation implemented by this
4633     * visitor; use Void if no return type is needed.
4634     * @param <S> the type of the second argument (the first being the
4635     * symbol itself) of the operation implemented by this visitor; use
4636     * Void if a second argument is not needed.
4637     */
4638    public static abstract class DefaultSymbolVisitor<R,S> implements Symbol.Visitor<R,S> {
4639        final public R visit(Symbol s, S arg)                   { return s.accept(this, arg); }
4640        public R visitClassSymbol(ClassSymbol s, S arg)         { return visitSymbol(s, arg); }
4641        public R visitMethodSymbol(MethodSymbol s, S arg)       { return visitSymbol(s, arg); }
4642        public R visitOperatorSymbol(OperatorSymbol s, S arg)   { return visitSymbol(s, arg); }
4643        public R visitPackageSymbol(PackageSymbol s, S arg)     { return visitSymbol(s, arg); }
4644        public R visitTypeSymbol(TypeSymbol s, S arg)           { return visitSymbol(s, arg); }
4645        public R visitVarSymbol(VarSymbol s, S arg)             { return visitSymbol(s, arg); }
4646    }
4647
4648    /**
4649     * A <em>simple</em> visitor for types.  This visitor is simple as
4650     * captured wildcards, for-all types (generic methods), and
4651     * undetermined type variables (part of inference) are hidden.
4652     * Captured wildcards are hidden by treating them as type
4653     * variables and the rest are hidden by visiting their qtypes.
4654     *
4655     * @param <R> the return type of the operation implemented by this
4656     * visitor; use Void if no return type is needed.
4657     * @param <S> the type of the second argument (the first being the
4658     * type itself) of the operation implemented by this visitor; use
4659     * Void if a second argument is not needed.
4660     */
4661    public static abstract class SimpleVisitor<R,S> extends DefaultTypeVisitor<R,S> {
4662        @Override
4663        public R visitCapturedType(CapturedType t, S s) {
4664            return visitTypeVar(t, s);
4665        }
4666        @Override
4667        public R visitForAll(ForAll t, S s) {
4668            return visit(t.qtype, s);
4669        }
4670        @Override
4671        public R visitUndetVar(UndetVar t, S s) {
4672            return visit(t.qtype, s);
4673        }
4674    }
4675
4676    /**
4677     * A plain relation on types.  That is a 2-ary function on the
4678     * form Type&nbsp;&times;&nbsp;Type&nbsp;&rarr;&nbsp;Boolean.
4679     * <!-- In plain text: Type x Type -> Boolean -->
4680     */
4681    public static abstract class TypeRelation extends SimpleVisitor<Boolean,Type> {}
4682
4683    /**
4684     * A convenience visitor for implementing operations that only
4685     * require one argument (the type itself), that is, unary
4686     * operations.
4687     *
4688     * @param <R> the return type of the operation implemented by this
4689     * visitor; use Void if no return type is needed.
4690     */
4691    public static abstract class UnaryVisitor<R> extends SimpleVisitor<R,Void> {
4692        final public R visit(Type t) { return t.accept(this, null); }
4693    }
4694
4695    /**
4696     * A visitor for implementing a mapping from types to types.  The
4697     * default behavior of this class is to implement the identity
4698     * mapping (mapping a type to itself).  This can be overridden in
4699     * subclasses.
4700     *
4701     * @param <S> the type of the second argument (the first being the
4702     * type itself) of this mapping; use Void if a second argument is
4703     * not needed.
4704     */
4705    public static class MapVisitor<S> extends DefaultTypeVisitor<Type,S> {
4706        final public Type visit(Type t) { return t.accept(this, null); }
4707        public Type visitType(Type t, S s) { return t; }
4708    }
4709    // </editor-fold>
4710
4711
4712    // <editor-fold defaultstate="collapsed" desc="Annotation support">
4713
4714    public RetentionPolicy getRetention(Attribute.Compound a) {
4715        return getRetention(a.type.tsym);
4716    }
4717
4718    public RetentionPolicy getRetention(TypeSymbol sym) {
4719        RetentionPolicy vis = RetentionPolicy.CLASS; // the default
4720        Attribute.Compound c = sym.attribute(syms.retentionType.tsym);
4721        if (c != null) {
4722            Attribute value = c.member(names.value);
4723            if (value != null && value instanceof Attribute.Enum) {
4724                Name levelName = ((Attribute.Enum)value).value.name;
4725                if (levelName == names.SOURCE) vis = RetentionPolicy.SOURCE;
4726                else if (levelName == names.CLASS) vis = RetentionPolicy.CLASS;
4727                else if (levelName == names.RUNTIME) vis = RetentionPolicy.RUNTIME;
4728                else ;// /* fail soft */ throw new AssertionError(levelName);
4729            }
4730        }
4731        return vis;
4732    }
4733    // </editor-fold>
4734
4735    // <editor-fold defaultstate="collapsed" desc="Signature Generation">
4736
4737    public static abstract class SignatureGenerator {
4738
4739        private final Types types;
4740
4741        protected abstract void append(char ch);
4742        protected abstract void append(byte[] ba);
4743        protected abstract void append(Name name);
4744        protected void classReference(ClassSymbol c) { /* by default: no-op */ }
4745
4746        protected SignatureGenerator(Types types) {
4747            this.types = types;
4748        }
4749
4750        /**
4751         * Assemble signature of given type in string buffer.
4752         */
4753        public void assembleSig(Type type) {
4754            switch (type.getTag()) {
4755                case BYTE:
4756                    append('B');
4757                    break;
4758                case SHORT:
4759                    append('S');
4760                    break;
4761                case CHAR:
4762                    append('C');
4763                    break;
4764                case INT:
4765                    append('I');
4766                    break;
4767                case LONG:
4768                    append('J');
4769                    break;
4770                case FLOAT:
4771                    append('F');
4772                    break;
4773                case DOUBLE:
4774                    append('D');
4775                    break;
4776                case BOOLEAN:
4777                    append('Z');
4778                    break;
4779                case VOID:
4780                    append('V');
4781                    break;
4782                case CLASS:
4783                    append('L');
4784                    assembleClassSig(type);
4785                    append(';');
4786                    break;
4787                case ARRAY:
4788                    ArrayType at = (ArrayType) type;
4789                    append('[');
4790                    assembleSig(at.elemtype);
4791                    break;
4792                case METHOD:
4793                    MethodType mt = (MethodType) type;
4794                    append('(');
4795                    assembleSig(mt.argtypes);
4796                    append(')');
4797                    assembleSig(mt.restype);
4798                    if (hasTypeVar(mt.thrown)) {
4799                        for (List<Type> l = mt.thrown; l.nonEmpty(); l = l.tail) {
4800                            append('^');
4801                            assembleSig(l.head);
4802                        }
4803                    }
4804                    break;
4805                case WILDCARD: {
4806                    Type.WildcardType ta = (Type.WildcardType) type;
4807                    switch (ta.kind) {
4808                        case SUPER:
4809                            append('-');
4810                            assembleSig(ta.type);
4811                            break;
4812                        case EXTENDS:
4813                            append('+');
4814                            assembleSig(ta.type);
4815                            break;
4816                        case UNBOUND:
4817                            append('*');
4818                            break;
4819                        default:
4820                            throw new AssertionError(ta.kind);
4821                    }
4822                    break;
4823                }
4824                case TYPEVAR:
4825                    append('T');
4826                    append(type.tsym.name);
4827                    append(';');
4828                    break;
4829                case FORALL:
4830                    Type.ForAll ft = (Type.ForAll) type;
4831                    assembleParamsSig(ft.tvars);
4832                    assembleSig(ft.qtype);
4833                    break;
4834                default:
4835                    throw new AssertionError("typeSig " + type.getTag());
4836            }
4837        }
4838
4839        public boolean hasTypeVar(List<Type> l) {
4840            while (l.nonEmpty()) {
4841                if (l.head.hasTag(TypeTag.TYPEVAR)) {
4842                    return true;
4843                }
4844                l = l.tail;
4845            }
4846            return false;
4847        }
4848
4849        public void assembleClassSig(Type type) {
4850            ClassType ct = (ClassType) type;
4851            ClassSymbol c = (ClassSymbol) ct.tsym;
4852            classReference(c);
4853            Type outer = ct.getEnclosingType();
4854            if (outer.allparams().nonEmpty()) {
4855                boolean rawOuter =
4856                        c.owner.kind == MTH || // either a local class
4857                        c.name == types.names.empty; // or anonymous
4858                assembleClassSig(rawOuter
4859                        ? types.erasure(outer)
4860                        : outer);
4861                append(rawOuter ? '$' : '.');
4862                Assert.check(c.flatname.startsWith(c.owner.enclClass().flatname));
4863                append(rawOuter
4864                        ? c.flatname.subName(c.owner.enclClass().flatname.getByteLength() + 1, c.flatname.getByteLength())
4865                        : c.name);
4866            } else {
4867                append(externalize(c.flatname));
4868            }
4869            if (ct.getTypeArguments().nonEmpty()) {
4870                append('<');
4871                assembleSig(ct.getTypeArguments());
4872                append('>');
4873            }
4874        }
4875
4876        public void assembleParamsSig(List<Type> typarams) {
4877            append('<');
4878            for (List<Type> ts = typarams; ts.nonEmpty(); ts = ts.tail) {
4879                Type.TypeVar tvar = (Type.TypeVar) ts.head;
4880                append(tvar.tsym.name);
4881                List<Type> bounds = types.getBounds(tvar);
4882                if ((bounds.head.tsym.flags() & INTERFACE) != 0) {
4883                    append(':');
4884                }
4885                for (List<Type> l = bounds; l.nonEmpty(); l = l.tail) {
4886                    append(':');
4887                    assembleSig(l.head);
4888                }
4889            }
4890            append('>');
4891        }
4892
4893        private void assembleSig(List<Type> types) {
4894            for (List<Type> ts = types; ts.nonEmpty(); ts = ts.tail) {
4895                assembleSig(ts.head);
4896            }
4897        }
4898    }
4899    // </editor-fold>
4900
4901    public void newRound() {
4902        descCache._map.clear();
4903        isDerivedRawCache.clear();
4904        implCache._map.clear();
4905        membersCache._map.clear();
4906        closureCache.clear();
4907    }
4908}
4909