/*
 * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.sun.tools.javac.code;

import java.lang.ref.SoftReference;
import java.util.HashSet;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;

import javax.tools.JavaFileObject;

import com.sun.tools.javac.code.Attribute.RetentionPolicy;
import com.sun.tools.javac.code.Lint.LintCategory;
import com.sun.tools.javac.code.Type.UndetVar.InferenceBound;
import com.sun.tools.javac.comp.AttrContext;
import com.sun.tools.javac.comp.Check;
import com.sun.tools.javac.comp.Enter;
import com.sun.tools.javac.comp.Env;
import com.sun.tools.javac.util.*;

import static com.sun.tools.javac.code.BoundKind.*;
import static com.sun.tools.javac.code.Flags.*;
import static com.sun.tools.javac.code.Scope.*;
import static com.sun.tools.javac.code.Symbol.*;
import static com.sun.tools.javac.code.Type.*;
import static com.sun.tools.javac.code.TypeTag.*;
import static com.sun.tools.javac.jvm.ClassFile.externalize;

/**
 * Utility class containing various operations on types.
 *
 * <p>Unless other names are more illustrative, the following naming
 * conventions should be observed in this file:
 *
 * <dl>
 * <dt>t</dt>
 * <dd>If the first argument to an operation is a type, it should be named t.</dd>
 * <dt>s</dt>
 * <dd>Similarly, if the second argument to an operation is a type, it should be named s.</dd>
 * <dt>ts</dt>
 * <dd>If an operations takes a list of types, the first should be named ts.</dd>
 * <dt>ss</dt>
 * <dd>A second list of types should be named ss.</dd>
 * </dl>
 *
 * <p><b>This is NOT part of any supported API.
 * If you write code that depends on this, you do so at your own risk.
 * This code and its internal interfaces are subject to change or
 * deletion without notice.</b>
 */
public class Types {
    protected static final Context.Key<Types> typesKey = new Context.Key<>();

    final Symtab syms;
    final JavacMessages messages;
    final Names names;
    final boolean allowBoxing;
    final boolean allowCovariantReturns;
    final boolean allowObjectToPrimitiveCast;
    final Check chk;
    final Enter enter;
    JCDiagnostic.Factory diags;
    List<Warner> warnStack = List.nil();
    final Name capturedName;
    private final FunctionDescriptorLookupError functionDescriptorLookupError;

    public final Warner noWarnings;

    // <editor-fold defaultstate="collapsed" desc="Instantiating">
    public static Types instance(Context context) {
        Types instance = context.get(typesKey);
        if (instance == null)
            instance = new Types(context);
        return instance;
    }

    protected Types(Context context) {
        context.put(typesKey, this);
        syms = Symtab.instance(context);
        names = Names.instance(context);
        Source source = Source.instance(context);
        allowBoxing = source.allowBoxing();
        allowCovariantReturns = source.allowCovariantReturns();
        allowObjectToPrimitiveCast = source.allowObjectToPrimitiveCast();
        chk = Check.instance(context);
        enter = Enter.instance(context);
        capturedName = names.fromString("<captured wildcard>");
        messages = JavacMessages.instance(context);
        diags = JCDiagnostic.Factory.instance(context);
        functionDescriptorLookupError = new FunctionDescriptorLookupError();
        noWarnings = new Warner(null);
    }
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="bounds">
    /**
     * Get a wildcard's upper bound, returning non-wildcards unchanged.
     * @param t a type argument, either a wildcard or a type
     */
    public Type wildUpperBound(Type t) {
        if (t.hasTag(WILDCARD)) {
            WildcardType w = (WildcardType) t;
            if (w.isSuperBound())
                return w.bound == null ? syms.objectType : w.bound.bound;
            else
                return wildUpperBound(w.type);
        }
        else return t;
    }

    /**
     * Get a capture variable's upper bound, returning other types unchanged.
     * @param t a type
     */
    public Type cvarUpperBound(Type t) {
        if (t.hasTag(TYPEVAR)) {
            TypeVar v = (TypeVar) t;
            return v.isCaptured() ? cvarUpperBound(v.bound) : v;
        }
        else return t;
    }

    /**
     * Get a wildcard's lower bound, returning non-wildcards unchanged.
     * @param t a type argument, either a wildcard or a type
     */
    public Type wildLowerBound(Type t) {
        if (t.hasTag(WILDCARD)) {
            WildcardType w = (WildcardType) t;
            return w.isExtendsBound() ? syms.botType : wildLowerBound(w.type);
        }
        else return t;
    }

    /**
     * Get a capture variable's lower bound, returning other types unchanged.
     * @param t a type
     */
    public Type cvarLowerBound(Type t) {
        if (t.hasTag(TYPEVAR) && ((TypeVar) t).isCaptured()) {
            return cvarLowerBound(t.getLowerBound());
        }
        else return t;
    }
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="isUnbounded">
    /**
     * Checks that all the arguments to a class are unbounded
     * wildcards or something else that doesn't make any restrictions
     * on the arguments. If a class isUnbounded, a raw super- or
     * subclass can be cast to it without a warning.
     * @param t a type
     * @return true iff the given type is unbounded or raw
     */
    public boolean isUnbounded(Type t) {
        return isUnbounded.visit(t);
    }
    // where
        private final UnaryVisitor<Boolean> isUnbounded = new UnaryVisitor<Boolean>() {

            public Boolean visitType(Type t, Void ignored) {
                return true;
            }

            @Override
            public Boolean visitClassType(ClassType t, Void ignored) {
                List<Type> parms = t.tsym.type.allparams();
                List<Type> args = t.allparams();
                while (parms.nonEmpty()) {
                    WildcardType unb = new WildcardType(syms.objectType,
                                                        BoundKind.UNBOUND,
                                                        syms.boundClass,
                                                        (TypeVar)parms.head);
                    if (!containsType(args.head, unb))
                        return false;
                    parms = parms.tail;
                    args = args.tail;
                }
                return true;
            }
        };
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="asSub">
    /**
     * Return the least specific subtype of t that starts with symbol
     * sym.  If none exists, return null.  The least specific subtype
     * is determined as follows:
     *
     * <p>If there is exactly one parameterized instance of sym that is a
     * subtype of t, that parameterized instance is returned.<br>
     * Otherwise, if the plain type or raw type `sym' is a subtype of
     * type t, the type `sym' itself is returned.  Otherwise, null is
     * returned.
     */
    public Type asSub(Type t, Symbol sym) {
        return asSub.visit(t, sym);
    }
    // where
        private final SimpleVisitor<Type,Symbol> asSub = new SimpleVisitor<Type,Symbol>() {

            public Type visitType(Type t, Symbol sym) {
                return null;
            }

            @Override
            public Type visitClassType(ClassType t, Symbol sym) {
                if (t.tsym == sym)
                    return t;
                Type base = asSuper(sym.type, t.tsym);
                if (base == null)
                    return null;
                ListBuffer<Type> from = new ListBuffer<>();
                ListBuffer<Type> to = new ListBuffer<>();
                try {
                    adapt(base, t, from, to);
                } catch (AdaptFailure ex) {
                    return null;
                }
                Type res = subst(sym.type, from.toList(), to.toList());
                if (!isSubtype(res, t))
                    return null;
                ListBuffer<Type> openVars = new ListBuffer<>();
                for (List<Type> l = sym.type.allparams();
                     l.nonEmpty(); l = l.tail)
                    if (res.contains(l.head) && !t.contains(l.head))
                        openVars.append(l.head);
                if (openVars.nonEmpty()) {
                    if (t.isRaw()) {
                        // The subtype of a raw type is raw
                        res = erasure(res);
                    } else {
                        // Unbound type arguments default to ?
                        List<Type> opens = openVars.toList();
                        ListBuffer<Type> qs = new ListBuffer<>();
                        for (List<Type> iter = opens; iter.nonEmpty(); iter = iter.tail) {
                            qs.append(new WildcardType(syms.objectType, BoundKind.UNBOUND,
                                                       syms.boundClass, (TypeVar) iter.head,
                                                       Type.noAnnotations));
                        }
                        res = subst(res, opens, qs.toList());
                    }
                }
                return res;
            }

            @Override
            public Type visitErrorType(ErrorType t, Symbol sym) {
                return t;
            }
        };
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="isConvertible">
    /**
     * Is t a subtype of or convertible via boxing/unboxing
     * conversion to s?
     */
    public boolean isConvertible(Type t, Type s, Warner warn) {
        if (t.hasTag(ERROR)) {
            return true;
        }
        boolean tPrimitive = t.isPrimitive();
        boolean sPrimitive = s.isPrimitive();
        if (tPrimitive == sPrimitive) {
            return isSubtypeUnchecked(t, s, warn);
        }
        if (!allowBoxing) return false;
        return tPrimitive
            ? isSubtype(boxedClass(t).type, s)
            : isSubtype(unboxedType(t), s);
    }

    /**
     * Is t a subtype of or convertible via boxing/unboxing
     * conversions to s?
     */
    public boolean isConvertible(Type t, Type s) {
        return isConvertible(t, s, noWarnings);
    }
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="findSam">

    /**
     * Exception used to report a function descriptor lookup failure. The exception
     * wraps a diagnostic that can be used to generate more details error
     * messages.
     */
    public static class FunctionDescriptorLookupError extends RuntimeException {
        private static final long serialVersionUID = 0;

        JCDiagnostic diagnostic;

        FunctionDescriptorLookupError() {
            this.diagnostic = null;
        }

        FunctionDescriptorLookupError setMessage(JCDiagnostic diag) {
            this.diagnostic = diag;
            return this;
        }

        public JCDiagnostic getDiagnostic() {
            return diagnostic;
        }
    }

    /**
     * A cache that keeps track of function descriptors associated with given
     * functional interfaces.
     */
    class DescriptorCache {

        private WeakHashMap<TypeSymbol, Entry> _map = new WeakHashMap<>();

        class FunctionDescriptor {
            Symbol descSym;

            FunctionDescriptor(Symbol descSym) {
                this.descSym = descSym;
            }

            public Symbol getSymbol() {
                return descSym;
            }

            public Type getType(Type site) {
                site = removeWildcards(site);
                if (!chk.checkValidGenericType(site)) {
                    //if the inferred functional interface type is not well-formed,
                    //or if it's not a subtype of the original target, issue an error
                    throw failure(diags.fragment("no.suitable.functional.intf.inst", site));
                }
                return memberType(site, descSym);
            }
        }

        class Entry {
            final FunctionDescriptor cachedDescRes;
            final int prevMark;

            public Entry(FunctionDescriptor cachedDescRes,
                    int prevMark) {
                this.cachedDescRes = cachedDescRes;
                this.prevMark = prevMark;
            }

            boolean matches(int mark) {
                return  this.prevMark == mark;
            }
        }

        FunctionDescriptor get(TypeSymbol origin) throws FunctionDescriptorLookupError {
            Entry e = _map.get(origin);
            CompoundScope members = membersClosure(origin.type, false);
            if (e == null ||
                    !e.matches(members.getMark())) {
                FunctionDescriptor descRes = findDescriptorInternal(origin, members);
                _map.put(origin, new Entry(descRes, members.getMark()));
                return descRes;
            }
            else {
                return e.cachedDescRes;
            }
        }

        /**
         * Compute the function descriptor associated with a given functional interface
         */
        public FunctionDescriptor findDescriptorInternal(TypeSymbol origin,
                CompoundScope membersCache) throws FunctionDescriptorLookupError {
            if (!origin.isInterface() || (origin.flags() & ANNOTATION) != 0) {
                //t must be an interface
                throw failure("not.a.functional.intf", origin);
            }

            final ListBuffer<Symbol> abstracts = new ListBuffer<>();
            for (Symbol sym : membersCache.getElements(new DescriptorFilter(origin))) {
                Type mtype = memberType(origin.type, sym);
                if (abstracts.isEmpty() ||
                        (sym.name == abstracts.first().name &&
                        overrideEquivalent(mtype, memberType(origin.type, abstracts.first())))) {
                    abstracts.append(sym);
                } else {
                    //the target method(s) should be the only abstract members of t
                    throw failure("not.a.functional.intf.1",  origin,
                            diags.fragment("incompatible.abstracts", Kinds.kindName(origin), origin));
                }
            }
            if (abstracts.isEmpty()) {
                //t must define a suitable non-generic method
                throw failure("not.a.functional.intf.1", origin,
                            diags.fragment("no.abstracts", Kinds.kindName(origin), origin));
            } else if (abstracts.size() == 1) {
                return new FunctionDescriptor(abstracts.first());
            } else { // size > 1
                FunctionDescriptor descRes = mergeDescriptors(origin, abstracts.toList());
                if (descRes == null) {
                    //we can get here if the functional interface is ill-formed
                    ListBuffer<JCDiagnostic> descriptors = new ListBuffer<>();
                    for (Symbol desc : abstracts) {
                        String key = desc.type.getThrownTypes().nonEmpty() ?
                                "descriptor.throws" : "descriptor";
                        descriptors.append(diags.fragment(key, desc.name,
                                desc.type.getParameterTypes(),
                                desc.type.getReturnType(),
                                desc.type.getThrownTypes()));
                    }
                    JCDiagnostic.MultilineDiagnostic incompatibleDescriptors =
                            new JCDiagnostic.MultilineDiagnostic(diags.fragment("incompatible.descs.in.functional.intf",
                            Kinds.kindName(origin), origin), descriptors.toList());
                    throw failure(incompatibleDescriptors);
                }
                return descRes;
            }
        }

        /**
         * Compute a synthetic type for the target descriptor given a list
         * of override-equivalent methods in the functional interface type.
         * The resulting method type is a method type that is override-equivalent
         * and return-type substitutable with each method in the original list.
         */
        private FunctionDescriptor mergeDescriptors(TypeSymbol origin, List<Symbol> methodSyms) {
            //pick argument types - simply take the signature that is a
            //subsignature of all other signatures in the list (as per JLS 8.4.2)
            List<Symbol> mostSpecific = List.nil();
            outer: for (Symbol msym1 : methodSyms) {
                Type mt1 = memberType(origin.type, msym1);
                for (Symbol msym2 : methodSyms) {
                    Type mt2 = memberType(origin.type, msym2);
                    if (!isSubSignature(mt1, mt2)) {
                        continue outer;
                    }
                }
                mostSpecific = mostSpecific.prepend(msym1);
            }
            if (mostSpecific.isEmpty()) {
                return null;
            }


            //pick return types - this is done in two phases: (i) first, the most
            //specific return type is chosen using strict subtyping; if this fails,
            //a second attempt is made using return type substitutability (see JLS 8.4.5)
            boolean phase2 = false;
            Symbol bestSoFar = null;
            while (bestSoFar == null) {
                outer: for (Symbol msym1 : mostSpecific) {
                    Type mt1 = memberType(origin.type, msym1);
                    for (Symbol msym2 : methodSyms) {
                        Type mt2 = memberType(origin.type, msym2);
                        if (phase2 ?
                                !returnTypeSubstitutable(mt1, mt2) :
                                !isSubtypeInternal(mt1.getReturnType(), mt2.getReturnType())) {
                            continue outer;
                        }
                    }
                    bestSoFar = msym1;
                }
                if (phase2) {
                    break;
                } else {
                    phase2 = true;
                }
            }
            if (bestSoFar == null) return null;

            //merge thrown types - form the intersection of all the thrown types in
            //all the signatures in the list
            boolean toErase = !bestSoFar.type.hasTag(FORALL);
            List<Type> thrown = null;
            Type mt1 = memberType(origin.type, bestSoFar);
            for (Symbol msym2 : methodSyms) {
                Type mt2 = memberType(origin.type, msym2);
                List<Type> thrown_mt2 = mt2.getThrownTypes();
                if (toErase) {
                    thrown_mt2 = erasure(thrown_mt2);
                } else {
                    /* If bestSoFar is generic then all the methods are generic.
                     * The opposite is not true: a non generic method can override
                     * a generic method (raw override) so it's safe to cast mt1 and
                     * mt2 to ForAll.
                     */
                    ForAll fa1 = (ForAll)mt1;
                    ForAll fa2 = (ForAll)mt2;
                    thrown_mt2 = subst(thrown_mt2, fa2.tvars, fa1.tvars);
                }
                thrown = (thrown == null) ?
                    thrown_mt2 :
                    chk.intersect(thrown_mt2, thrown);
            }

            final List<Type> thrown1 = thrown;
            return new FunctionDescriptor(bestSoFar) {
                @Override
                public Type getType(Type origin) {
                    Type mt = memberType(origin, getSymbol());
                    return createMethodTypeWithThrown(mt, thrown1);
                }
            };
        }

        boolean isSubtypeInternal(Type s, Type t) {
            return (s.isPrimitive() && t.isPrimitive()) ?
                    isSameType(t, s) :
                    isSubtype(s, t);
        }

        FunctionDescriptorLookupError failure(String msg, Object... args) {
            return failure(diags.fragment(msg, args));
        }

        FunctionDescriptorLookupError failure(JCDiagnostic diag) {
            return functionDescriptorLookupError.setMessage(diag);
        }
    }

    private DescriptorCache descCache = new DescriptorCache();

    /**
     * Find the method descriptor associated to this class symbol - if the
     * symbol 'origin' is not a functional interface, an exception is thrown.
     */
    public Symbol findDescriptorSymbol(TypeSymbol origin) throws FunctionDescriptorLookupError {
        return descCache.get(origin).getSymbol();
    }

    /**
     * Find the type of the method descriptor associated to this class symbol -
     * if the symbol 'origin' is not a functional interface, an exception is thrown.
     */
    public Type findDescriptorType(Type origin) throws FunctionDescriptorLookupError {
        return descCache.get(origin.tsym).getType(origin);
    }

    /**
     * Is given type a functional interface?
     */
    public boolean isFunctionalInterface(TypeSymbol tsym) {
        try {
            findDescriptorSymbol(tsym);
            return true;
        } catch (FunctionDescriptorLookupError ex) {
            return false;
        }
    }

    public boolean isFunctionalInterface(Type site) {
        try {
            findDescriptorType(site);
            return true;
        } catch (FunctionDescriptorLookupError ex) {
            return false;
        }
    }

    public Type removeWildcards(Type site) {
        Type capturedSite = capture(site);
        if (capturedSite != site) {
            Type formalInterface = site.tsym.type;
            ListBuffer<Type> typeargs = new ListBuffer<>();
            List<Type> actualTypeargs = site.getTypeArguments();
            List<Type> capturedTypeargs = capturedSite.getTypeArguments();
            //simply replace the wildcards with its bound
            for (Type t : formalInterface.getTypeArguments()) {
                if (actualTypeargs.head.hasTag(WILDCARD)) {
                    WildcardType wt = (WildcardType)actualTypeargs.head;
                    Type bound;
                    switch (wt.kind) {
                        case EXTENDS:
                        case UNBOUND:
                            CapturedType capVar = (CapturedType)capturedTypeargs.head;
                            //use declared bound if it doesn't depend on formal type-args
                            bound = capVar.bound.containsAny(capturedSite.getTypeArguments()) ?
                                    wt.type : capVar.bound;
                            break;
                        default:
                            bound = wt.type;
                    }
                    typeargs.append(bound);
                } else {
                    typeargs.append(actualTypeargs.head);
                }
                actualTypeargs = actualTypeargs.tail;
                capturedTypeargs = capturedTypeargs.tail;
            }
            return subst(formalInterface, formalInterface.getTypeArguments(), typeargs.toList());
        } else {
            return site;
        }
    }

    /**
     * Create a symbol for a class that implements a given functional interface
     * and overrides its functional descriptor. This routine is used for two
     * main purposes: (i) checking well-formedness of a functional interface;
     * (ii) perform functional interface bridge calculation.
     */
    public ClassSymbol makeFunctionalInterfaceClass(Env<AttrContext> env, Name name, List<Type> targets, long cflags) {
        if (targets.isEmpty() || !isFunctionalInterface(targets.head)) {
            return null;
        }
        Symbol descSym = findDescriptorSymbol(targets.head.tsym);
        Type descType = findDescriptorType(targets.head);
        ClassSymbol csym = new ClassSymbol(cflags, name, env.enclClass.sym.outermostClass());
        csym.completer = null;
        csym.members_field = new Scope(csym);
        MethodSymbol instDescSym = new MethodSymbol(descSym.flags(), descSym.name, descType, csym);
        csym.members_field.enter(instDescSym);
        Type.ClassType ctype = new Type.ClassType(Type.noType, List.<Type>nil(), csym,
                                                  Type.noAnnotations);
        ctype.supertype_field = syms.objectType;
        ctype.interfaces_field = targets;
        csym.type = ctype;
        csym.sourcefile = ((ClassSymbol)csym.owner).sourcefile;
        return csym;
    }

    /**
     * Find the minimal set of methods that are overridden by the functional
     * descriptor in 'origin'. All returned methods are assumed to have different
     * erased signatures.
     */
    public List<Symbol> functionalInterfaceBridges(TypeSymbol origin) {
        Assert.check(isFunctionalInterface(origin));
        Symbol descSym = findDescriptorSymbol(origin);
        CompoundScope members = membersClosure(origin.type, false);
        ListBuffer<Symbol> overridden = new ListBuffer<>();
        outer: for (Symbol m2 : members.getElementsByName(descSym.name, bridgeFilter)) {
            if (m2 == descSym) continue;
            else if (descSym.overrides(m2, origin, Types.this, false)) {
                for (Symbol m3 : overridden) {
                    if (isSameType(m3.erasure(Types.this), m2.erasure(Types.this)) ||
                            (m3.overrides(m2, origin, Types.this, false) &&
                            (pendingBridges((ClassSymbol)origin, m3.enclClass()) ||
                            (((MethodSymbol)m2).binaryImplementation((ClassSymbol)m3.owner, Types.this) != null)))) {
                        continue outer;
                    }
                }
                overridden.add(m2);
            }
        }
        return overridden.toList();
    }
    //where
        private Filter<Symbol> bridgeFilter = new Filter<Symbol>() {
            public boolean accepts(Symbol t) {
                return t.kind == Kinds.MTH &&
                        t.name != names.init &&
                        t.name != names.clinit &&
                        (t.flags() & SYNTHETIC) == 0;
            }
        };
        private boolean pendingBridges(ClassSymbol origin, TypeSymbol s) {
            //a symbol will be completed from a classfile if (a) symbol has
            //an associated file object with CLASS kind and (b) the symbol has
            //not been entered
            if (origin.classfile != null &&
                    origin.classfile.getKind() == JavaFileObject.Kind.CLASS &&
                    enter.getEnv(origin) == null) {
                return false;
            }
            if (origin == s) {
                return true;
            }
            for (Type t : interfaces(origin.type)) {
                if (pendingBridges((ClassSymbol)t.tsym, s)) {
                    return true;
                }
            }
            return false;
        }
    // </editor-fold>

   /**
    * Scope filter used to skip methods that should be ignored (such as methods
    * overridden by j.l.Object) during function interface conversion interface check
    */
    class DescriptorFilter implements Filter<Symbol> {

       TypeSymbol origin;

       DescriptorFilter(TypeSymbol origin) {
           this.origin = origin;
       }

       @Override
       public boolean accepts(Symbol sym) {
           return sym.kind == Kinds.MTH &&
                   (sym.flags() & (ABSTRACT | DEFAULT)) == ABSTRACT &&
                   !overridesObjectMethod(origin, sym) &&
                   (interfaceCandidates(origin.type, (MethodSymbol)sym).head.flags() & DEFAULT) == 0;
       }
    }

    // <editor-fold defaultstate="collapsed" desc="isSubtype">
    /**
     * Is t an unchecked subtype of s?
     */
    public boolean isSubtypeUnchecked(Type t, Type s) {
        return isSubtypeUnchecked(t, s, noWarnings);
    }
    /**
     * Is t an unchecked subtype of s?
     */
    public boolean isSubtypeUnchecked(Type t, Type s, Warner warn) {
        boolean result = isSubtypeUncheckedInternal(t, s, warn);
        if (result) {
            checkUnsafeVarargsConversion(t, s, warn);
        }
        return result;
    }
    //where
        private boolean isSubtypeUncheckedInternal(Type t, Type s, Warner warn) {
            if (t.hasTag(ARRAY) && s.hasTag(ARRAY)) {
                if (((ArrayType)t).elemtype.isPrimitive()) {
                    return isSameType(elemtype(t), elemtype(s));
                } else {
                    return isSubtypeUnchecked(elemtype(t), elemtype(s), warn);
                }
            } else if (isSubtype(t, s)) {
                return true;
            } else if (t.hasTag(TYPEVAR)) {
                return isSubtypeUnchecked(t.getUpperBound(), s, warn);
            } else if (!s.isRaw()) {
                Type t2 = asSuper(t, s.tsym);
                if (t2 != null && t2.isRaw()) {
                    if (isReifiable(s)) {
                        warn.silentWarn(LintCategory.UNCHECKED);
                    } else {
                        warn.warn(LintCategory.UNCHECKED);
                    }
                    return true;
                }
            }
            return false;
        }

        private void checkUnsafeVarargsConversion(Type t, Type s, Warner warn) {
            if (!t.hasTag(ARRAY) || isReifiable(t)) {
                return;
            }
            ArrayType from = (ArrayType)t;
            boolean shouldWarn = false;
            switch (s.getTag()) {
                case ARRAY:
                    ArrayType to = (ArrayType)s;
                    shouldWarn = from.isVarargs() &&
                            !to.isVarargs() &&
                            !isReifiable(from);
                    break;
                case CLASS:
                    shouldWarn = from.isVarargs();
                    break;
            }
            if (shouldWarn) {
                warn.warn(LintCategory.VARARGS);
            }
        }

    /**
     * Is t a subtype of s?<br>
     * (not defined for Method and ForAll types)
     */
    final public boolean isSubtype(Type t, Type s) {
        return isSubtype(t, s, true);
    }
    final public boolean isSubtypeNoCapture(Type t, Type s) {
        return isSubtype(t, s, false);
    }
    public boolean isSubtype(Type t, Type s, boolean capture) {
        if (t == s)
            return true;

        if (s.isPartial())
            return isSuperType(s, t);

        if (s.isCompound()) {
            for (Type s2 : interfaces(s).prepend(supertype(s))) {
                if (!isSubtype(t, s2, capture))
                    return false;
            }
            return true;
        }

        // Generally, if 's' is a type variable, recur on lower bound; but
        // for inference variables and intersections, we need to keep 's'
        // (see JLS 4.10.2 for intersections and 18.2.3 for inference vars)
        if (!t.hasTag(UNDETVAR) && !t.isCompound()) {
            // TODO: JDK-8039198, bounds checking sometimes passes in a wildcard as s
            Type lower = cvarLowerBound(wildLowerBound(s));
            if (s != lower)
                return isSubtype(capture ? capture(t) : t, lower, false);
        }

        return isSubtype.visit(capture ? capture(t) : t, s);
    }
    // where
        private TypeRelation isSubtype = new TypeRelation()
        {
            @Override
            public Boolean visitType(Type t, Type s) {
                switch (t.getTag()) {
                 case BYTE:
                     return (!s.hasTag(CHAR) && t.getTag().isSubRangeOf(s.getTag()));
                 case CHAR:
                     return (!s.hasTag(SHORT) && t.getTag().isSubRangeOf(s.getTag()));
                 case SHORT: case INT: case LONG:
                 case FLOAT: case DOUBLE:
                     return t.getTag().isSubRangeOf(s.getTag());
                 case BOOLEAN: case VOID:
                     return t.hasTag(s.getTag());
                 case TYPEVAR:
                     return isSubtypeNoCapture(t.getUpperBound(), s);
                 case BOT:
                     return
                         s.hasTag(BOT) || s.hasTag(CLASS) ||
                         s.hasTag(ARRAY) || s.hasTag(TYPEVAR);
                 case WILDCARD: //we shouldn't be here - avoids crash (see 7034495)
                 case NONE:
                     return false;
                 default:
                     throw new AssertionError("isSubtype " + t.getTag());
                 }
            }

            private Set<TypePair> cache = new HashSet<>();

            private boolean containsTypeRecursive(Type t, Type s) {
                TypePair pair = new TypePair(t, s);
                if (cache.add(pair)) {
                    try {
                        return containsType(t.getTypeArguments(),
                                            s.getTypeArguments());
                    } finally {
                        cache.remove(pair);
                    }
                } else {
                    return containsType(t.getTypeArguments(),
                                        rewriteSupers(s).getTypeArguments());
                }
            }

            private Type rewriteSupers(Type t) {
                if (!t.isParameterized())
                    return t;
                ListBuffer<Type> from = new ListBuffer<>();
                ListBuffer<Type> to = new ListBuffer<>();
                adaptSelf(t, from, to);
                if (from.isEmpty())
                    return t;
                ListBuffer<Type> rewrite = new ListBuffer<>();
                boolean changed = false;
                for (Type orig : to.toList()) {
                    Type s = rewriteSupers(orig);
                    if (s.isSuperBound() && !s.isExtendsBound()) {
                        s = new WildcardType(syms.objectType,
                                             BoundKind.UNBOUND,
                                             syms.boundClass,
                                             s.getAnnotationMirrors());
                        changed = true;
                    } else if (s != orig) {
                        s = new WildcardType(wildUpperBound(s),
                                             BoundKind.EXTENDS,
                                             syms.boundClass,
                                             s.getAnnotationMirrors());
                        changed = true;
                    }
                    rewrite.append(s);
                }
                if (changed)
                    return subst(t.tsym.type, from.toList(), rewrite.toList());
                else
                    return t;
            }

            @Override
            public Boolean visitClassType(ClassType t, Type s) {
                Type sup = asSuper(t, s.tsym);
                if (sup == null) return false;
                // If t is an intersection, sup might not be a class type
                if (!sup.hasTag(CLASS)) return isSubtypeNoCapture(sup, s);
                return sup.tsym == s.tsym
                     // Check type variable containment
                    && (!s.isParameterized() || containsTypeRecursive(s, sup))
                    && isSubtypeNoCapture(sup.getEnclosingType(),
                                          s.getEnclosingType());
            }

            @Override
            public Boolean visitArrayType(ArrayType t, Type s) {
                if (s.hasTag(ARRAY)) {
                    if (t.elemtype.isPrimitive())
                        return isSameType(t.elemtype, elemtype(s));
                    else
                        return isSubtypeNoCapture(t.elemtype, elemtype(s));
                }

                if (s.hasTag(CLASS)) {
                    Name sname = s.tsym.getQualifiedName();
                    return sname == names.java_lang_Object
                        || sname == names.java_lang_Cloneable
                        || sname == names.java_io_Serializable;
                }

                return false;
            }

            @Override
            public Boolean visitUndetVar(UndetVar t, Type s) {
                //todo: test against origin needed? or replace with substitution?
                if (t == s || t.qtype == s || s.hasTag(ERROR) || s.hasTag(UNKNOWN)) {
                    return true;
                } else if (s.hasTag(BOT)) {
                    //if 's' is 'null' there's no instantiated type U for which
                    //U <: s (but 'null' itself, which is not a valid type)
                    return false;
                }

                t.addBound(InferenceBound.UPPER, s, Types.this);
                return true;
            }

            @Override
            public Boolean visitErrorType(ErrorType t, Type s) {
                return true;
            }
        };

    /**
     * Is t a subtype of every type in given list `ts'?<br>
     * (not defined for Method and ForAll types)<br>
     * Allows unchecked conversions.
     */
    public boolean isSubtypeUnchecked(Type t, List<Type> ts, Warner warn) {
        for (List<Type> l = ts; l.nonEmpty(); l = l.tail)
            if (!isSubtypeUnchecked(t, l.head, warn))
                return false;
        return true;
    }

    /**
     * Are corresponding elements of ts subtypes of ss?  If lists are
     * of different length, return false.
     */
    public boolean isSubtypes(List<Type> ts, List<Type> ss) {
        while (ts.tail != null && ss.tail != null
               /*inlined: ts.nonEmpty() && ss.nonEmpty()*/ &&
               isSubtype(ts.head, ss.head)) {
            ts = ts.tail;
            ss = ss.tail;
        }
        return ts.tail == null && ss.tail == null;
        /*inlined: ts.isEmpty() && ss.isEmpty();*/
    }

    /**
     * Are corresponding elements of ts subtypes of ss, allowing
     * unchecked conversions?  If lists are of different length,
     * return false.
     **/
    public boolean isSubtypesUnchecked(List<Type> ts, List<Type> ss, Warner warn) {
        while (ts.tail != null && ss.tail != null
               /*inlined: ts.nonEmpty() && ss.nonEmpty()*/ &&
               isSubtypeUnchecked(ts.head, ss.head, warn)) {
            ts = ts.tail;
            ss = ss.tail;
        }
        return ts.tail == null && ss.tail == null;
        /*inlined: ts.isEmpty() && ss.isEmpty();*/
    }
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="isSuperType">
    /**
     * Is t a supertype of s?
     */
    public boolean isSuperType(Type t, Type s) {
        switch (t.getTag()) {
        case ERROR:
            return true;
        case UNDETVAR: {
            UndetVar undet = (UndetVar)t;
            if (t == s ||
                undet.qtype == s ||
                s.hasTag(ERROR) ||
                s.hasTag(BOT)) {
                return true;
            }
            undet.addBound(InferenceBound.LOWER, s, this);
            return true;
        }
        default:
            return isSubtype(s, t);
        }
    }
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="isSameType">
    /**
     * Are corresponding elements of the lists the same type?  If
     * lists are of different length, return false.
     */
    public boolean isSameTypes(List<Type> ts, List<Type> ss) {
        return isSameTypes(ts, ss, false);
    }
    public boolean isSameTypes(List<Type> ts, List<Type> ss, boolean strict) {
        while (ts.tail != null && ss.tail != null
               /*inlined: ts.nonEmpty() && ss.nonEmpty()*/ &&
               isSameType(ts.head, ss.head, strict)) {
            ts = ts.tail;
            ss = ss.tail;
        }
        return ts.tail == null && ss.tail == null;
        /*inlined: ts.isEmpty() && ss.isEmpty();*/
    }

    /**
    * A polymorphic signature method (JLS SE 7, 8.4.1) is a method that
    * (i) is declared in the java.lang.invoke.MethodHandle class, (ii) takes
    * a single variable arity parameter (iii) whose declared type is Object[],
    * (iv) has a return type of Object and (v) is native.
    */
   public boolean isSignaturePolymorphic(MethodSymbol msym) {
       List<Type> argtypes = msym.type.getParameterTypes();
       return (msym.flags_field & NATIVE) != 0 &&
               msym.owner == syms.methodHandleType.tsym &&
               argtypes.tail.tail == null &&
               argtypes.head.hasTag(TypeTag.ARRAY) &&
               msym.type.getReturnType().tsym == syms.objectType.tsym &&
               ((ArrayType)argtypes.head).elemtype.tsym == syms.objectType.tsym;
   }

    /**
     * Is t the same type as s?
     */
    public boolean isSameType(Type t, Type s) {
        return isSameType(t, s, false);
    }
    public boolean isSameType(Type t, Type s, boolean strict) {
        return strict ?
                isSameTypeStrict.visit(t, s) :
                isSameTypeLoose.visit(t, s);
    }
    public boolean isSameAnnotatedType(Type t, Type s) {
        return isSameAnnotatedType.visit(t, s);
    }
    // where
        abstract class SameTypeVisitor extends TypeRelation {

            public Boolean visitType(Type t, Type s) {
                if (t == s)
                    return true;

                if (s.isPartial())
                    return visit(s, t);

                switch (t.getTag()) {
                case BYTE: case CHAR: case SHORT: case INT: case LONG: case FLOAT:
                case DOUBLE: case BOOLEAN: case VOID: case BOT: case NONE:
                    return t.hasTag(s.getTag());
                case TYPEVAR: {
                    if (s.hasTag(TYPEVAR)) {
                        //type-substitution does not preserve type-var types
                        //check that type var symbols and bounds are indeed the same
                        return sameTypeVars((TypeVar)t, (TypeVar)s);
                    }
                    else {
                        //special case for s == ? super X, where upper(s) = u
                        //check that u == t, where u has been set by Type.withTypeVar
                        return s.isSuperBound() &&
                                !s.isExtendsBound() &&
                                visit(t, wildUpperBound(s));
                    }
                }
                default:
                    throw new AssertionError("isSameType " + t.getTag());
                }
            }

            abstract boolean sameTypeVars(TypeVar tv1, TypeVar tv2);

            @Override
            public Boolean visitWildcardType(WildcardType t, Type s) {
                if (s.isPartial())
                    return visit(s, t);
                else
                    return false;
            }

            @Override
            public Boolean visitClassType(ClassType t, Type s) {
                if (t == s)
                    return true;

                if (s.isPartial())
                    return visit(s, t);

                if (s.isSuperBound() && !s.isExtendsBound())
                    return visit(t, wildUpperBound(s)) && visit(t, wildLowerBound(s));

                if (t.isCompound() && s.isCompound()) {
                    if (!visit(supertype(t), supertype(s)))
                        return false;

                    HashSet<UniqueType> set = new HashSet<>();
                    for (Type x : interfaces(t))
                        set.add(new UniqueType(x, Types.this));
                    for (Type x : interfaces(s)) {
                        if (!set.remove(new UniqueType(x, Types.this)))
                            return false;
                    }
                    return (set.isEmpty());
                }
                return t.tsym == s.tsym
                    && visit(t.getEnclosingType(), s.getEnclosingType())
                    && containsTypes(t.getTypeArguments(), s.getTypeArguments());
            }

            abstract protected boolean containsTypes(List<Type> ts1, List<Type> ts2);

            @Override
            public Boolean visitArrayType(ArrayType t, Type s) {
                if (t == s)
                    return true;

                if (s.isPartial())
                    return visit(s, t);

                return s.hasTag(ARRAY)
                    && containsTypeEquivalent(t.elemtype, elemtype(s));
            }

            @Override
            public Boolean visitMethodType(MethodType t, Type s) {
                // isSameType for methods does not take thrown
                // exceptions into account!
                return hasSameArgs(t, s) && visit(t.getReturnType(), s.getReturnType());
            }

            @Override
            public Boolean visitPackageType(PackageType t, Type s) {
                return t == s;
            }

            @Override
            public Boolean visitForAll(ForAll t, Type s) {
                if (!s.hasTag(FORALL)) {
                    return false;
                }

                ForAll forAll = (ForAll)s;
                return hasSameBounds(t, forAll)
                    && visit(t.qtype, subst(forAll.qtype, forAll.tvars, t.tvars));
            }

            @Override
            public Boolean visitUndetVar(UndetVar t, Type s) {
                if (s.hasTag(WILDCARD)) {
                    // FIXME, this might be leftovers from before capture conversion
                    return false;
                }

                if (t == s || t.qtype == s || s.hasTag(ERROR) || s.hasTag(UNKNOWN)) {
                    return true;
                }

                t.addBound(InferenceBound.EQ, s, Types.this);

                return true;
            }

            @Override
            public Boolean visitErrorType(ErrorType t, Type s) {
                return true;
            }
        }

        /**
         * Standard type-equality relation - type variables are considered
         * equals if they share the same type symbol.
         */
        TypeRelation isSameTypeLoose = new LooseSameTypeVisitor();

        private class LooseSameTypeVisitor extends SameTypeVisitor {
            @Override
            boolean sameTypeVars(TypeVar tv1, TypeVar tv2) {
                return tv1.tsym == tv2.tsym && visit(tv1.getUpperBound(), tv2.getUpperBound());
            }
            @Override
            protected boolean containsTypes(List<Type> ts1, List<Type> ts2) {
                return containsTypeEquivalent(ts1, ts2);
            }
        }

    /**
         * Strict type-equality relation - type variables are considered
         * equals if they share the same object identity.
         */
        TypeRelation isSameTypeStrict = new SameTypeVisitor() {
            @Override
            boolean sameTypeVars(TypeVar tv1, TypeVar tv2) {
                return tv1 == tv2;
            }
            @Override
            protected boolean containsTypes(List<Type> ts1, List<Type> ts2) {
                return isSameTypes(ts1, ts2, true);
            }

            @Override
            public Boolean visitWildcardType(WildcardType t, Type s) {
                if (!s.hasTag(WILDCARD)) {
                    return false;
                } else {
                    WildcardType t2 = (WildcardType)s;
                    return t.kind == t2.kind &&
                            isSameType(t.type, t2.type, true);
                }
            }
        };

    // </editor-fold>

    TypeRelation isSameAnnotatedType = new LooseSameTypeVisitor() {
            private Boolean compareAnnotations(Type t1, Type t2) {
                List<Attribute.TypeCompound> annos1 = t1.getAnnotationMirrors();
                List<Attribute.TypeCompound> annos2 = t2.getAnnotationMirrors();
                return annos1.containsAll(annos2) && annos2.containsAll(annos1);
            }

            @Override
            public Boolean visitType(Type t, Type s) {
                return compareAnnotations(t, s) && super.visitType(t, s);
            }

            @Override
            public Boolean visitWildcardType(WildcardType t, Type s) {
                return compareAnnotations(t, s) && super.visitWildcardType(t, s);
            }

            @Override
            public Boolean visitClassType(ClassType t, Type s) {
                return compareAnnotations(t, s) && super.visitClassType(t, s);
            }

            @Override
            public Boolean visitArrayType(ArrayType t, Type s) {
                return compareAnnotations(t, s) && super.visitArrayType(t, s);
            }

            @Override
            public Boolean visitForAll(ForAll t, Type s) {
                return compareAnnotations(t, s) && super.visitForAll(t, s);
            }
        };

    // <editor-fold defaultstate="collapsed" desc="Contains Type">
    public boolean containedBy(Type t, Type s) {
        switch (t.getTag()) {
        case UNDETVAR:
            if (s.hasTag(WILDCARD)) {
                UndetVar undetvar = (UndetVar)t;
                WildcardType wt = (WildcardType)s;
                switch(wt.kind) {
                    case UNBOUND: //similar to ? extends Object
                    case EXTENDS: {
                        Type bound = wildUpperBound(s);
                        undetvar.addBound(InferenceBound.UPPER, bound, this);
                        break;
                    }
                    case SUPER: {
                        Type bound = wildLowerBound(s);
                        undetvar.addBound(InferenceBound.LOWER, bound, this);
                        break;
                    }
                }
                return true;
            } else {
                return isSameType(t, s);
            }
        case ERROR:
            return true;
        default:
            return containsType(s, t);
        }
    }

    boolean containsType(List<Type> ts, List<Type> ss) {
        while (ts.nonEmpty() && ss.nonEmpty()
               && containsType(ts.head, ss.head)) {
            ts = ts.tail;
            ss = ss.tail;
        }
        return ts.isEmpty() && ss.isEmpty();
    }

    /**
     * Check if t contains s.
     *
     * <p>T contains S if:
     *
     * <p>{@code L(T) <: L(S) && U(S) <: U(T)}
     *
     * <p>This relation is only used by ClassType.isSubtype(), that
     * is,
     *
     * <p>{@code C<S> <: C<T> if T contains S.}
     *
     * <p>Because of F-bounds, this relation can lead to infinite
     * recursion.  Thus we must somehow break that recursion.  Notice
     * that containsType() is only called from ClassType.isSubtype().
     * Since the arguments have already been checked against their
     * bounds, we know:
     *
     * <p>{@code U(S) <: U(T) if T is "super" bound (U(T) *is* the bound)}
     *
     * <p>{@code L(T) <: L(S) if T is "extends" bound (L(T) is bottom)}
     *
     * @param t a type
     * @param s a type
     */
    public boolean containsType(Type t, Type s) {
        return containsType.visit(t, s);
    }
    // where
        private TypeRelation containsType = new TypeRelation() {

            public Boolean visitType(Type t, Type s) {
                if (s.isPartial())
                    return containedBy(s, t);
                else
                    return isSameType(t, s);
            }

//            void debugContainsType(WildcardType t, Type s) {
//                System.err.println();
//                System.err.format(" does %s contain %s?%n", t, s);
//                System.err.format(" %s U(%s) <: U(%s) %s = %s%n",
//                                  wildUpperBound(s), s, t, wildUpperBound(t),
//                                  t.isSuperBound()
//                                  || isSubtypeNoCapture(wildUpperBound(s), wildUpperBound(t)));
//                System.err.format(" %s L(%s) <: L(%s) %s = %s%n",
//                                  wildLowerBound(t), t, s, wildLowerBound(s),
//                                  t.isExtendsBound()
//                                  || isSubtypeNoCapture(wildLowerBound(t), wildLowerBound(s)));
//                System.err.println();
//            }

            @Override
            public Boolean visitWildcardType(WildcardType t, Type s) {
                if (s.isPartial())
                    return containedBy(s, t);
                else {
//                    debugContainsType(t, s);
                    return isSameWildcard(t, s)
                        || isCaptureOf(s, t)
                        || ((t.isExtendsBound() || isSubtypeNoCapture(wildLowerBound(t), wildLowerBound(s))) &&
                            // TODO: JDK-8039214, cvarUpperBound call here is incorrect
                            (t.isSuperBound() || isSubtypeNoCapture(cvarUpperBound(wildUpperBound(s)), wildUpperBound(t))));
                }
            }

            @Override
            public Boolean visitUndetVar(UndetVar t, Type s) {
                if (!s.hasTag(WILDCARD)) {
                    return isSameType(t, s);
                } else {
                    return false;
                }
            }

            @Override
            public Boolean visitErrorType(ErrorType t, Type s) {
                return true;
            }
        };

    public boolean isCaptureOf(Type s, WildcardType t) {
        if (!s.hasTag(TYPEVAR) || !((TypeVar)s).isCaptured())
            return false;
        return isSameWildcard(t, ((CapturedType)s).wildcard);
    }

    public boolean isSameWildcard(WildcardType t, Type s) {
        if (!s.hasTag(WILDCARD))
            return false;
        WildcardType w = (WildcardType)s;
        return w.kind == t.kind && w.type == t.type;
    }

    public boolean containsTypeEquivalent(List<Type> ts, List<Type> ss) {
        while (ts.nonEmpty() && ss.nonEmpty()
               && containsTypeEquivalent(ts.head, ss.head)) {
            ts = ts.tail;
            ss = ss.tail;
        }
        return ts.isEmpty() && ss.isEmpty();
    }
    // </editor-fold>

    /**
     * Can t and s be compared for equality?  Any primitive ==
     * primitive or primitive == object comparisons here are an error.
     * Unboxing and correct primitive == primitive comparisons are
     * already dealt with in Attr.visitBinary.
     *
     */
    public boolean isEqualityComparable(Type s, Type t, Warner warn) {
        if (t.isNumeric() && s.isNumeric())
            return true;

        boolean tPrimitive = t.isPrimitive();
        boolean sPrimitive = s.isPrimitive();
        if (!tPrimitive && !sPrimitive) {
            return isCastable(s, t, warn) || isCastable(t, s, warn);
        } else {
            return false;
        }
    }

    // <editor-fold defaultstate="collapsed" desc="isCastable">
    public boolean isCastable(Type t, Type s) {
        return isCastable(t, s, noWarnings);
    }

    /**
     * Is t is castable to s?<br>
     * s is assumed to be an erased type.<br>
     * (not defined for Method and ForAll types).
     */
    public boolean isCastable(Type t, Type s, Warner warn) {
        if (t == s)
            return true;

        if (t.isPrimitive() != s.isPrimitive())
            return allowBoxing && (
                    isConvertible(t, s, warn)
                    || (allowObjectToPrimitiveCast &&
                        s.isPrimitive() &&
                        isSubtype(boxedClass(s).type, t)));
        if (warn != warnStack.head) {
            try {
                warnStack = warnStack.prepend(warn);
                checkUnsafeVarargsConversion(t, s, warn);
                return isCastable.visit(t,s);
            } finally {
                warnStack = warnStack.tail;
            }
        } else {
            return isCastable.visit(t,s);
        }
    }
    // where
        private TypeRelation isCastable = new TypeRelation() {

            public Boolean visitType(Type t, Type s) {
                if (s.hasTag(ERROR))
                    return true;

                switch (t.getTag()) {
                case BYTE: case CHAR: case SHORT: case INT: case LONG: case FLOAT:
                case DOUBLE:
                    return s.isNumeric();
                case BOOLEAN:
                    return s.hasTag(BOOLEAN);
                case VOID:
                    return false;
                case BOT:
                    return isSubtype(t, s);
                default:
                    throw new AssertionError();
                }
            }

            @Override
            public Boolean visitWildcardType(WildcardType t, Type s) {
                return isCastable(wildUpperBound(t), s, warnStack.head);
            }

            @Override
            public Boolean visitClassType(ClassType t, Type s) {
                if (s.hasTag(ERROR) || s.hasTag(BOT))
                    return true;

                if (s.hasTag(TYPEVAR)) {
                    if (isCastable(t, s.getUpperBound(), noWarnings)) {
                        warnStack.head.warn(LintCategory.UNCHECKED);
                        return true;
                    } else {
                        return false;
                    }
                }

                if (t.isCompound() || s.isCompound()) {
                    return !t.isCompound() ?
                            visitIntersectionType((IntersectionClassType)s, t, true) :
                            visitIntersectionType((IntersectionClassType)t, s, false);
                }

                if (s.hasTag(CLASS) || s.hasTag(ARRAY)) {
                    boolean upcast;
                    if ((upcast = isSubtype(erasure(t), erasure(s)))
                        || isSubtype(erasure(s), erasure(t))) {
                        if (!upcast && s.hasTag(ARRAY)) {
                            if (!isReifiable(s))
                                warnStack.head.warn(LintCategory.UNCHECKED);
                            return true;
                        } else if (s.isRaw()) {
                            return true;
                        } else if (t.isRaw()) {
                            if (!isUnbounded(s))
                                warnStack.head.warn(LintCategory.UNCHECKED);
                            return true;
                        }
                        // Assume |a| <: |b|
                        final Type a = upcast ? t : s;
                        final Type b = upcast ? s : t;
                        final boolean HIGH = true;
                        final boolean LOW = false;
                        final boolean DONT_REWRITE_TYPEVARS = false;
                        Type aHigh = rewriteQuantifiers(a, HIGH, DONT_REWRITE_TYPEVARS);
                        Type aLow  = rewriteQuantifiers(a, LOW,  DONT_REWRITE_TYPEVARS);
                        Type bHigh = rewriteQuantifiers(b, HIGH, DONT_REWRITE_TYPEVARS);
                        Type bLow  = rewriteQuantifiers(b, LOW,  DONT_REWRITE_TYPEVARS);
                        Type lowSub = asSub(bLow, aLow.tsym);
                        Type highSub = (lowSub == null) ? null : asSub(bHigh, aHigh.tsym);
                        if (highSub == null) {
                            final boolean REWRITE_TYPEVARS = true;
                            aHigh = rewriteQuantifiers(a, HIGH, REWRITE_TYPEVARS);
                            aLow  = rewriteQuantifiers(a, LOW,  REWRITE_TYPEVARS);
                            bHigh = rewriteQuantifiers(b, HIGH, REWRITE_TYPEVARS);
                            bLow  = rewriteQuantifiers(b, LOW,  REWRITE_TYPEVARS);
                            lowSub = asSub(bLow, aLow.tsym);
                            highSub = (lowSub == null) ? null : asSub(bHigh, aHigh.tsym);
                        }
                        if (highSub != null) {
                            if (!(a.tsym == highSub.tsym && a.tsym == lowSub.tsym)) {
                                Assert.error(a.tsym + " != " + highSub.tsym + " != " + lowSub.tsym);
                            }
                            if (!disjointTypes(aHigh.allparams(), highSub.allparams())
                                && !disjointTypes(aHigh.allparams(), lowSub.allparams())
                                && !disjointTypes(aLow.allparams(), highSub.allparams())
                                && !disjointTypes(aLow.allparams(), lowSub.allparams())) {
                                if (upcast ? giveWarning(a, b) :
                                    giveWarning(b, a))
                                    warnStack.head.warn(LintCategory.UNCHECKED);
                                return true;
                            }
                        }
                        if (isReifiable(s))
                            return isSubtypeUnchecked(a, b);
                        else
                            return isSubtypeUnchecked(a, b, warnStack.head);
                    }

                    // Sidecast
                    if (s.hasTag(CLASS)) {
                        if ((s.tsym.flags() & INTERFACE) != 0) {
                            return ((t.tsym.flags() & FINAL) == 0)
                                ? sideCast(t, s, warnStack.head)
                                : sideCastFinal(t, s, warnStack.head);
                        } else if ((t.tsym.flags() & INTERFACE) != 0) {
                            return ((s.tsym.flags() & FINAL) == 0)
                                ? sideCast(t, s, warnStack.head)
                                : sideCastFinal(t, s, warnStack.head);
                        } else {
                            // unrelated class types
                            return false;
                        }
                    }
                }
                return false;
            }

            boolean visitIntersectionType(IntersectionClassType ict, Type s, boolean reverse) {
                Warner warn = noWarnings;
                for (Type c : ict.getComponents()) {
                    warn.clear();
                    if (reverse ? !isCastable(s, c, warn) : !isCastable(c, s, warn))
                        return false;
                }
                if (warn.hasLint(LintCategory.UNCHECKED))
                    warnStack.head.warn(LintCategory.UNCHECKED);
                return true;
            }

            @Override
            public Boolean visitArrayType(ArrayType t, Type s) {
                switch (s.getTag()) {
                case ERROR:
                case BOT:
                    return true;
                case TYPEVAR:
                    if (isCastable(s, t, noWarnings)) {
                        warnStack.head.warn(LintCategory.UNCHECKED);
                        return true;
                    } else {
                        return false;
                    }
                case CLASS:
                    return isSubtype(t, s);
                case ARRAY:
                    if (elemtype(t).isPrimitive() || elemtype(s).isPrimitive()) {
                        return elemtype(t).hasTag(elemtype(s).getTag());
                    } else {
                        return visit(elemtype(t), elemtype(s));
                    }
                default:
                    return false;
                }
            }

            @Override
            public Boolean visitTypeVar(TypeVar t, Type s) {
                switch (s.getTag()) {
                case ERROR:
                case BOT:
                    return true;
                case TYPEVAR:
                    if (isSubtype(t, s)) {
                        return true;
                    } else if (isCastable(t.bound, s, noWarnings)) {
                        warnStack.head.warn(LintCategory.UNCHECKED);
                        return true;
                    } else {
                        return false;
                    }
                default:
                    return isCastable(t.bound, s, warnStack.head);
                }
            }

            @Override
            public Boolean visitErrorType(ErrorType t, Type s) {
                return true;
            }
        };
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="disjointTypes">
    public boolean disjointTypes(List<Type> ts, List<Type> ss) {
        while (ts.tail != null && ss.tail != null) {
            if (disjointType(ts.head, ss.head)) return true;
            ts = ts.tail;
            ss = ss.tail;
        }
        return false;
    }

    /**
     * Two types or wildcards are considered disjoint if it can be
     * proven that no type can be contained in both. It is
     * conservative in that it is allowed to say that two types are
     * not disjoint, even though they actually are.
     *
     * The type {@code C<X>} is castable to {@code C<Y>} exactly if
     * {@code X} and {@code Y} are not disjoint.
     */
    public boolean disjointType(Type t, Type s) {
        return disjointType.visit(t, s);
    }
    // where
        private TypeRelation disjointType = new TypeRelation() {

            private Set<TypePair> cache = new HashSet<>();

            @Override
            public Boolean visitType(Type t, Type s) {
                if (s.hasTag(WILDCARD))
                    return visit(s, t);
                else
                    return notSoftSubtypeRecursive(t, s) || notSoftSubtypeRecursive(s, t);
            }

            private boolean isCastableRecursive(Type t, Type s) {
                TypePair pair = new TypePair(t, s);
                if (cache.add(pair)) {
                    try {
                        return Types.this.isCastable(t, s);
                    } finally {
                        cache.remove(pair);
                    }
                } else {
                    return true;
                }
            }

            private boolean notSoftSubtypeRecursive(Type t, Type s) {
                TypePair pair = new TypePair(t, s);
                if (cache.add(pair)) {
                    try {
                        return Types.this.notSoftSubtype(t, s);
                    } finally {
                        cache.remove(pair);
                    }
                } else {
                    return false;
                }
            }

            @Override
            public Boolean visitWildcardType(WildcardType t, Type s) {
                if (t.isUnbound())
                    return false;

                if (!s.hasTag(WILDCARD)) {
                    if (t.isExtendsBound())
                        return notSoftSubtypeRecursive(s, t.type);
                    else
                        return notSoftSubtypeRecursive(t.type, s);
                }

                if (s.isUnbound())
                    return false;

                if (t.isExtendsBound()) {
                    if (s.isExtendsBound())
                        return !isCastableRecursive(t.type, wildUpperBound(s));
                    else if (s.isSuperBound())
                        return notSoftSubtypeRecursive(wildLowerBound(s), t.type);
                } else if (t.isSuperBound()) {
                    if (s.isExtendsBound())
                        return notSoftSubtypeRecursive(t.type, wildUpperBound(s));
                }
                return false;
            }
        };
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="cvarLowerBounds">
    public List<Type> cvarLowerBounds(List<Type> ts) {
        return map(ts, cvarLowerBoundMapping);
    }
    private final Mapping cvarLowerBoundMapping = new Mapping("cvarLowerBound") {
            public Type apply(Type t) {
                return cvarLowerBound(t);
            }
        };
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="notSoftSubtype">
    /**
     * This relation answers the question: is impossible that
     * something of type `t' can be a subtype of `s'? This is
     * different from the question "is `t' not a subtype of `s'?"
     * when type variables are involved: Integer is not a subtype of T
     * where {@code <T extends Number>} but it is not true that Integer cannot
     * possibly be a subtype of T.
     */
    public boolean notSoftSubtype(Type t, Type s) {
        if (t == s) return false;
        if (t.hasTag(TYPEVAR)) {
            TypeVar tv = (TypeVar) t;
            return !isCastable(tv.bound,
                               relaxBound(s),
                               noWarnings);
        }
        if (!s.hasTag(WILDCARD))
            s = cvarUpperBound(s);

        return !isSubtype(t, relaxBound(s));
    }

    private Type relaxBound(Type t) {
        if (t.hasTag(TYPEVAR)) {
            while (t.hasTag(TYPEVAR))
                t = t.getUpperBound();
            t = rewriteQuantifiers(t, true, true);
        }
        return t;
    }
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="isReifiable">
    public boolean isReifiable(Type t) {
        return isReifiable.visit(t);
    }
    // where
        private UnaryVisitor<Boolean> isReifiable = new UnaryVisitor<Boolean>() {

            public Boolean visitType(Type t, Void ignored) {
                return true;
            }

            @Override
            public Boolean visitClassType(ClassType t, Void ignored) {
                if (t.isCompound())
                    return false;
                else {
                    if (!t.isParameterized())
                        return true;

                    for (Type param : t.allparams()) {
                        if (!param.isUnbound())
                            return false;
                    }
                    return true;
                }
            }

            @Override
            public Boolean visitArrayType(ArrayType t, Void ignored) {
                return visit(t.elemtype);
            }

            @Override
            public Boolean visitTypeVar(TypeVar t, Void ignored) {
                return false;
            }
        };
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="Array Utils">
    public boolean isArray(Type t) {
        while (t.hasTag(WILDCARD))
            t = wildUpperBound(t);
        return t.hasTag(ARRAY);
    }

    /**
     * The element type of an array.
     */
    public Type elemtype(Type t) {
        switch (t.getTag()) {
        case WILDCARD:
            return elemtype(wildUpperBound(t));
        case ARRAY:
            return ((ArrayType)t).elemtype;
        case FORALL:
            return elemtype(((ForAll)t).qtype);
        case ERROR:
            return t;
        default:
            return null;
        }
    }

    public Type elemtypeOrType(Type t) {
        Type elemtype = elemtype(t);
        return elemtype != null ?
            elemtype :
            t;
    }

    /**
     * Mapping to take element type of an arraytype
     */
    private Mapping elemTypeFun = new Mapping ("elemTypeFun") {
        public Type apply(Type t) { return elemtype(t); }
    };

    /**
     * The number of dimensions of an array type.
     */
    public int dimensions(Type t) {
        int result = 0;
        while (t.hasTag(ARRAY)) {
            result++;
            t = elemtype(t);
        }
        return result;
    }

    /**
     * Returns an ArrayType with the component type t
     *
     * @param t The component type of the ArrayType
     * @return the ArrayType for the given component
     */
    public ArrayType makeArrayType(Type t) {
        if (t.hasTag(VOID) || t.hasTag(PACKAGE)) {
            Assert.error("Type t must not be a VOID or PACKAGE type, " + t.toString());
        }
        return new ArrayType(t, syms.arrayClass, Type.noAnnotations);
    }
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="asSuper">
    /**
     * Return the (most specific) base type of t that starts with the
     * given symbol.  If none exists, return null.
     *
     * @param t a type
     * @param sym a symbol
     */
    public Type asSuper(Type t, Symbol sym) {
        /* Some examples:
         *
         * (Enum<E>, Comparable) => Comparable<E>
         * (c.s.s.d.AttributeTree.ValueKind, Enum) => Enum<c.s.s.d.AttributeTree.ValueKind>
         * (c.s.s.t.ExpressionTree, c.s.s.t.Tree) => c.s.s.t.Tree
         * (j.u.List<capture#160 of ? extends c.s.s.d.DocTree>, Iterable) =>
         *     Iterable<capture#160 of ? extends c.s.s.d.DocTree>
         */
        if (sym.type == syms.objectType) { //optimization
            return syms.objectType;
        }
        return asSuper.visit(t, sym);
    }
    // where
        private SimpleVisitor<Type,Symbol> asSuper = new SimpleVisitor<Type,Symbol>() {

            public Type visitType(Type t, Symbol sym) {
                return null;
            }

            @Override
            public Type visitClassType(ClassType t, Symbol sym) {
                if (t.tsym == sym)
                    return t;

                Type st = supertype(t);
                if (st.hasTag(CLASS) || st.hasTag(TYPEVAR)) {
                    Type x = asSuper(st, sym);
                    if (x != null)
                        return x;
                }
                if ((sym.flags() & INTERFACE) != 0) {
                    for (List<Type> l = interfaces(t); l.nonEmpty(); l = l.tail) {
                        if (!l.head.hasTag(ERROR)) {
                            Type x = asSuper(l.head, sym);
                            if (x != null)
                                return x;
                        }
                    }
                }
                return null;
            }

            @Override
            public Type visitArrayType(ArrayType t, Symbol sym) {
                return isSubtype(t, sym.type) ? sym.type : null;
            }

            @Override
            public Type visitTypeVar(TypeVar t, Symbol sym) {
                if (t.tsym == sym)
                    return t;
                else
                    return asSuper(t.bound, sym);
            }

            @Override
            public Type visitErrorType(ErrorType t, Symbol sym) {
                return t;
            }
        };

    /**
     * Return the base type of t or any of its outer types that starts
     * with the given symbol.  If none exists, return null.
     *
     * @param t a type
     * @param sym a symbol
     */
    public Type asOuterSuper(Type t, Symbol sym) {
        switch (t.getTag()) {
        case CLASS:
            do {
                Type s = asSuper(t, sym);
                if (s != null) return s;
                t = t.getEnclosingType();
            } while (t.hasTag(CLASS));
            return null;
        case ARRAY:
            return isSubtype(t, sym.type) ? sym.type : null;
        case TYPEVAR:
            return asSuper(t, sym);
        case ERROR:
            return t;
        default:
            return null;
        }
    }

    /**
     * Return the base type of t or any of its enclosing types that
     * starts with the given symbol.  If none exists, return null.
     *
     * @param t a type
     * @param sym a symbol
     */
    public Type asEnclosingSuper(Type t, Symbol sym) {
        switch (t.getTag()) {
        case CLASS:
            do {
                Type s = asSuper(t, sym);
                if (s != null) return s;
                Type outer = t.getEnclosingType();
                t = (outer.hasTag(CLASS)) ? outer :
                    (t.tsym.owner.enclClass() != null) ? t.tsym.owner.enclClass().type :
                    Type.noType;
            } while (t.hasTag(CLASS));
            return null;
        case ARRAY:
            return isSubtype(t, sym.type) ? sym.type : null;
        case TYPEVAR:
            return asSuper(t, sym);
        case ERROR:
            return t;
        default:
            return null;
        }
    }
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="memberType">
    /**
     * The type of given symbol, seen as a member of t.
     *
     * @param t a type
     * @param sym a symbol
     */
    public Type memberType(Type t, Symbol sym) {
        return (sym.flags() & STATIC) != 0
            ? sym.type
            : memberType.visit(t, sym);
        }
    // where
        private SimpleVisitor<Type,Symbol> memberType = new SimpleVisitor<Type,Symbol>() {

            public Type visitType(Type t, Symbol sym) {
                return sym.type;
            }

            @Override
            public Type visitWildcardType(WildcardType t, Symbol sym) {
                return memberType(wildUpperBound(t), sym);
            }

            @Override
            public Type visitClassType(ClassType t, Symbol sym) {
                Symbol owner = sym.owner;
                long flags = sym.flags();
                if (((flags & STATIC) == 0) && owner.type.isParameterized()) {
                    Type base = asOuterSuper(t, owner);
                    //if t is an intersection type T = CT & I1 & I2 ... & In
                    //its supertypes CT, I1, ... In might contain wildcards
                    //so we need to go through capture conversion
                    base = t.isCompound() ? capture(base) : base;
                    if (base != null) {
                        List<Type> ownerParams = owner.type.allparams();
                        List<Type> baseParams = base.allparams();
                        if (ownerParams.nonEmpty()) {
                            if (baseParams.isEmpty()) {
                                // then base is a raw type
                                return erasure(sym.type);
                            } else {
                                return subst(sym.type, ownerParams, baseParams);
                            }
                        }
                    }
                }
                return sym.type;
            }

            @Override
            public Type visitTypeVar(TypeVar t, Symbol sym) {
                return memberType(t.bound, sym);
            }

            @Override
            public Type visitErrorType(ErrorType t, Symbol sym) {
                return t;
            }
        };
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="isAssignable">
    public boolean isAssignable(Type t, Type s) {
        return isAssignable(t, s, noWarnings);
    }

    /**
     * Is t assignable to s?<br>
     * Equivalent to subtype except for constant values and raw
     * types.<br>
     * (not defined for Method and ForAll types)
     */
    public boolean isAssignable(Type t, Type s, Warner warn) {
        if (t.hasTag(ERROR))
            return true;
        if (t.getTag().isSubRangeOf(INT) && t.constValue() != null) {
            int value = ((Number)t.constValue()).intValue();
            switch (s.getTag()) {
            case BYTE:
                if (Byte.MIN_VALUE <= value && value <= Byte.MAX_VALUE)
                    return true;
                break;
            case CHAR:
                if (Character.MIN_VALUE <= value && value <= Character.MAX_VALUE)
                    return true;
                break;
            case SHORT:
                if (Short.MIN_VALUE <= value && value <= Short.MAX_VALUE)
                    return true;
                break;
            case INT:
                return true;
            case CLASS:
                switch (unboxedType(s).getTag()) {
                case BYTE:
                case CHAR:
                case SHORT:
                    return isAssignable(t, unboxedType(s), warn);
                }
                break;
            }
        }
        return isConvertible(t, s, warn);
    }
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="erasure">
    /**
     * The erasure of t {@code |t|} -- the type that results when all
     * type parameters in t are deleted.
     */
    public Type erasure(Type t) {
        return eraseNotNeeded(t)? t : erasure(t, false);
    }
    //where
    private boolean eraseNotNeeded(Type t) {
        // We don't want to erase primitive types and String type as that
        // operation is idempotent. Also, erasing these could result in loss
        // of information such as constant values attached to such types.
        return (t.isPrimitive()) || (syms.stringType.tsym == t.tsym);
    }

    private Type erasure(Type t, boolean recurse) {
        if (t.isPrimitive()) {
            return t; /* fast special case */
        } else {
            Type out = erasure.visit(t, recurse);
            return out;
        }
        }
    // where
        private SimpleVisitor<Type, Boolean> erasure = new SimpleVisitor<Type, Boolean>() {
            public Type visitType(Type t, Boolean recurse) {
                if (t.isPrimitive())
                    return t; /*fast special case*/
                else {
                    final List<Attribute.TypeCompound> annos = t.getAnnotationMirrors();
                    Type erased = t.map(recurse ? erasureRecFun : erasureFun);
                    if (!annos.isEmpty()) {
                        erased = erased.annotatedType(annos);
                    }
                    return erased;
                }
            }

            @Override
            public Type visitWildcardType(WildcardType t, Boolean recurse) {
                final List<Attribute.TypeCompound> annos = t.getAnnotationMirrors();
                Type erased = erasure(wildUpperBound(t), recurse);
                if (!annos.isEmpty()) {
                    erased = erased.annotatedType(annos);
                }
                return erased;
            }

            @Override
            public Type visitClassType(ClassType t, Boolean recurse) {
                Type erased = t.tsym.erasure(Types.this);
                List<Attribute.TypeCompound> annos = t.getAnnotationMirrors();
                if (recurse) {
                    erased = new ErasedClassType(erased.getEnclosingType(),erased.tsym);
                }
                if (!annos.isEmpty()) {
                    erased = erased.annotatedType(annos);
                }
                return erased;
            }

            @Override
            public Type visitTypeVar(TypeVar t, Boolean recurse) {
                final List<Attribute.TypeCompound> annos = t.getAnnotationMirrors();
                Type erased = erasure(t.bound, recurse);
                if (!annos.isEmpty()) {
                    erased = erased.annotatedType(annos);
                }
                return erased;
            }

            @Override
            public Type visitErrorType(ErrorType t, Boolean recurse) {
                return t;
            }
        };

    private Mapping erasureFun = new Mapping ("erasure") {
            public Type apply(Type t) { return erasure(t); }
        };

    private Mapping erasureRecFun = new Mapping ("erasureRecursive") {
        public Type apply(Type t) { return erasureRecursive(t); }
    };

    public List<Type> erasure(List<Type> ts) {
        return Type.map(ts, erasureFun);
    }

    public Type erasureRecursive(Type t) {
        return erasure(t, true);
    }

    public List<Type> erasureRecursive(List<Type> ts) {
        return Type.map(ts, erasureRecFun);
    }
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="makeCompoundType">
    /**
     * Make a compound type from non-empty list of types.  The list should be
     * ordered according to {@link Symbol#precedes(TypeSymbol,Types)}.
     *
     * @param bounds            the types from which the compound type is formed
     * @param supertype         is objectType if all bounds are interfaces,
     *                          null otherwise.
     */
    public Type makeCompoundType(List<Type> bounds) {
        return makeCompoundType(bounds, bounds.head.tsym.isInterface());
    }
    public Type makeCompoundType(List<Type> bounds, boolean allInterfaces) {
        Assert.check(bounds.nonEmpty());
        Type firstExplicitBound = bounds.head;
        if (allInterfaces) {
            bounds = bounds.prepend(syms.objectType);
        }
        ClassSymbol bc =
            new ClassSymbol(ABSTRACT|PUBLIC|SYNTHETIC|COMPOUND|ACYCLIC,
                            Type.moreInfo
                                ? names.fromString(bounds.toString())
                                : names.empty,
                            null,
                            syms.noSymbol);
        bc.type = new IntersectionClassType(bounds, bc, allInterfaces);
        bc.erasure_field = (bounds.head.hasTag(TYPEVAR)) ?
                syms.objectType : // error condition, recover
                erasure(firstExplicitBound);
        bc.members_field = new Scope(bc);
        return bc.type;
    }

    /**
     * A convenience wrapper for {@link #makeCompoundType(List)}; the
     * arguments are converted to a list and passed to the other
     * method.  Note that this might cause a symbol completion.
     * Hence, this version of makeCompoundType may not be called
     * during a classfile read.
     */
    public Type makeCompoundType(Type bound1, Type bound2) {
        return makeCompoundType(List.of(bound1, bound2));
    }
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="supertype">
    public Type supertype(Type t) {
        return supertype.visit(t);
    }
    // where
        private UnaryVisitor<Type> supertype = new UnaryVisitor<Type>() {

            public Type visitType(Type t, Void ignored) {
                // A note on wildcards: there is no good way to
                // determine a supertype for a super bounded wildcard.
                return null;
            }

            @Override
            public Type visitClassType(ClassType t, Void ignored) {
                if (t.supertype_field == null) {
                    Type supertype = ((ClassSymbol)t.tsym).getSuperclass();
                    // An interface has no superclass; its supertype is Object.
                    if (t.isInterface())
                        supertype = ((ClassType)t.tsym.type).supertype_field;
                    if (t.supertype_field == null) {
                        List<Type> actuals = classBound(t).allparams();
                        List<Type> formals = t.tsym.type.allparams();
                        if (t.hasErasedSupertypes()) {
                            t.supertype_field = erasureRecursive(supertype);
                        } else if (formals.nonEmpty()) {
                            t.supertype_field = subst(supertype, formals, actuals);
                        }
                        else {
                            t.supertype_field = supertype;
                        }
                    }
                }
                return t.supertype_field;
            }

            /**
             * The supertype is always a class type. If the type
             * variable's bounds start with a class type, this is also
             * the supertype.  Otherwise, the supertype is
             * java.lang.Object.
             */
            @Override
            public Type visitTypeVar(TypeVar t, Void ignored) {
                if (t.bound.hasTag(TYPEVAR) ||
                    (!t.bound.isCompound() && !t.bound.isInterface())) {
                    return t.bound;
                } else {
                    return supertype(t.bound);
                }
            }

            @Override
            public Type visitArrayType(ArrayType t, Void ignored) {
                if (t.elemtype.isPrimitive() || isSameType(t.elemtype, syms.objectType))
                    return arraySuperType();
                else
                    return new ArrayType(supertype(t.elemtype), t.tsym);
            }

            @Override
            public Type visitErrorType(ErrorType t, Void ignored) {
                return Type.noType;
            }
        };
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="interfaces">
    /**
     * Return the interfaces implemented by this class.
     */
    public List<Type> interfaces(Type t) {
        return interfaces.visit(t);
    }
    // where
        private UnaryVisitor<List<Type>> interfaces = new UnaryVisitor<List<Type>>() {

            public List<Type> visitType(Type t, Void ignored) {
                return List.nil();
            }

            @Override
            public List<Type> visitClassType(ClassType t, Void ignored) {
                if (t.interfaces_field == null) {
                    List<Type> interfaces = ((ClassSymbol)t.tsym).getInterfaces();
                    if (t.interfaces_field == null) {
                        // If t.interfaces_field is null, then t must
                        // be a parameterized type (not to be confused
                        // with a generic type declaration).
                        // Terminology:
                        //    Parameterized type: List<String>
                        //    Generic type declaration: class List<E> { ... }
                        // So t corresponds to List<String> and
                        // t.tsym.type corresponds to List<E>.
                        // The reason t must be parameterized type is
                        // that completion will happen as a side
                        // effect of calling
                        // ClassSymbol.getInterfaces.  Since
                        // t.interfaces_field is null after
                        // completion, we can assume that t is not the
                        // type of a class/interface declaration.
                        Assert.check(t != t.tsym.type, t);
                        List<Type> actuals = t.allparams();
                        List<Type> formals = t.tsym.type.allparams();
                        if (t.hasErasedSupertypes()) {
                            t.interfaces_field = erasureRecursive(interfaces);
                        } else if (formals.nonEmpty()) {
                            t.interfaces_field = subst(interfaces, formals, actuals);
                        }
                        else {
                            t.interfaces_field = interfaces;
                        }
                    }
                }
                return t.interfaces_field;
            }

            @Override
            public List<Type> visitTypeVar(TypeVar t, Void ignored) {
                if (t.bound.isCompound())
                    return interfaces(t.bound);

                if (t.bound.isInterface())
                    return List.of(t.bound);

                return List.nil();
            }
        };

    public List<Type> directSupertypes(Type t) {
        return directSupertypes.visit(t);
    }
    // where
        private final UnaryVisitor<List<Type>> directSupertypes = new UnaryVisitor<List<Type>>() {

            public List<Type> visitType(final Type type, final Void ignored) {
                if (!type.isCompound()) {
                    final Type sup = supertype(type);
                    return (sup == Type.noType || sup == type || sup == null)
                        ? interfaces(type)
                        : interfaces(type).prepend(sup);
                } else {
                    return visitIntersectionType((IntersectionClassType) type);
                }
            }

            private List<Type> visitIntersectionType(final IntersectionClassType it) {
                return it.getExplicitComponents();
            }

        };

    public boolean isDirectSuperInterface(TypeSymbol isym, TypeSymbol origin) {
        for (Type i2 : interfaces(origin.type)) {
            if (isym == i2.tsym) return true;
        }
        return false;
    }
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="isDerivedRaw">
    Map<Type,Boolean> isDerivedRawCache = new HashMap<>();

    public boolean isDerivedRaw(Type t) {
        Boolean result = isDerivedRawCache.get(t);
        if (result == null) {
            result = isDerivedRawInternal(t);
            isDerivedRawCache.put(t, result);
        }
        return result;
    }

    public boolean isDerivedRawInternal(Type t) {
        if (t.isErroneous())
            return false;
        return
            t.isRaw() ||
            supertype(t) != null && isDerivedRaw(supertype(t)) ||
            isDerivedRaw(interfaces(t));
    }

    public boolean isDerivedRaw(List<Type> ts) {
        List<Type> l = ts;
        while (l.nonEmpty() && !isDerivedRaw(l.head)) l = l.tail;
        return l.nonEmpty();
    }
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="setBounds">
    /**
     * Set the bounds field of the given type variable to reflect a
     * (possibly multiple) list of bounds.
     * @param t                 a type variable
     * @param bounds            the bounds, must be nonempty
     * @param supertype         is objectType if all bounds are interfaces,
     *                          null otherwise.
     */
    public void setBounds(TypeVar t, List<Type> bounds) {
        setBounds(t, bounds, bounds.head.tsym.isInterface());
    }

    /**
     * Same as {@link #setBounds(Type.TypeVar,List,Type)}, except that
     * third parameter is computed directly, as follows: if all
     * all bounds are interface types, the computed supertype is Object,
     * otherwise the supertype is simply left null (in this case, the supertype
     * is assumed to be the head of the bound list passed as second argument).
     * Note that this check might cause a symbol completion. Hence, this version of
     * setBounds may not be called during a classfile read.
     */
    public void setBounds(TypeVar t, List<Type> bounds, boolean allInterfaces) {
        t.bound = bounds.tail.isEmpty() ?
                bounds.head :
                makeCompoundType(bounds, allInterfaces);
        t.rank_field = -1;
    }
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="getBounds">
    /**
     * Return list of bounds of the given type variable.
     */
    public List<Type> getBounds(TypeVar t) {
        if (t.bound.hasTag(NONE))
            return List.nil();
        else if (t.bound.isErroneous() || !t.bound.isCompound())
            return List.of(t.bound);
        else if ((erasure(t).tsym.flags() & INTERFACE) == 0)
            return interfaces(t).prepend(supertype(t));
        else
            // No superclass was given in bounds.
            // In this case, supertype is Object, erasure is first interface.
            return interfaces(t);
    }
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="classBound">
    /**
     * If the given type is a (possibly selected) type variable,
     * return the bounding class of this type, otherwise return the
     * type itself.
     */
    public Type classBound(Type t) {
        return classBound.visit(t);
    }
    // where
        private UnaryVisitor<Type> classBound = new UnaryVisitor<Type>() {

            public Type visitType(Type t, Void ignored) {
                return t;
            }

            @Override
            public Type visitClassType(ClassType t, Void ignored) {
                Type outer1 = classBound(t.getEnclosingType());
                if (outer1 != t.getEnclosingType())
                    return new ClassType(outer1, t.getTypeArguments(), t.tsym,
                                         t.getAnnotationMirrors());
                else
                    return t;
            }

            @Override
            public Type visitTypeVar(TypeVar t, Void ignored) {
                return classBound(supertype(t));
            }

            @Override
            public Type visitErrorType(ErrorType t, Void ignored) {
                return t;
            }
        };
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="sub signature / override equivalence">
    /**
     * Returns true iff the first signature is a <em>sub
     * signature</em> of the other.  This is <b>not</b> an equivalence
     * relation.
     *
     * @jls section 8.4.2.
     * @see #overrideEquivalent(Type t, Type s)
     * @param t first signature (possibly raw).
     * @param s second signature (could be subjected to erasure).
     * @return true if t is a sub signature of s.
     */
    public boolean isSubSignature(Type t, Type s) {
        return isSubSignature(t, s, true);
    }

    public boolean isSubSignature(Type t, Type s, boolean strict) {
        return hasSameArgs(t, s, strict) || hasSameArgs(t, erasure(s), strict);
    }

    /**
     * Returns true iff these signatures are related by <em>override
     * equivalence</em>.  This is the natural extension of
     * isSubSignature to an equivalence relation.
     *
     * @jls section 8.4.2.
     * @see #isSubSignature(Type t, Type s)
     * @param t a signature (possible raw, could be subjected to
     * erasure).
     * @param s a signature (possible raw, could be subjected to
     * erasure).
     * @return true if either argument is a sub signature of the other.
     */
    public boolean overrideEquivalent(Type t, Type s) {
        return hasSameArgs(t, s) ||
            hasSameArgs(t, erasure(s)) || hasSameArgs(erasure(t), s);
    }

    public boolean overridesObjectMethod(TypeSymbol origin, Symbol msym) {
        for (Scope.Entry e = syms.objectType.tsym.members().lookup(msym.name) ; e.scope != null ; e = e.next()) {
            if (msym.overrides(e.sym, origin, Types.this, true)) {
                return true;
            }
        }
        return false;
    }

    // <editor-fold defaultstate="collapsed" desc="Determining method implementation in given site">
    class ImplementationCache {

        private WeakHashMap<MethodSymbol, SoftReference<Map<TypeSymbol, Entry>>> _map = new WeakHashMap<>();

        class Entry {
            final MethodSymbol cachedImpl;
            final Filter<Symbol> implFilter;
            final boolean checkResult;
            final int prevMark;

            public Entry(MethodSymbol cachedImpl,
                    Filter<Symbol> scopeFilter,
                    boolean checkResult,
                    int prevMark) {
                this.cachedImpl = cachedImpl;
                this.implFilter = scopeFilter;
                this.checkResult = checkResult;
                this.prevMark = prevMark;
            }

            boolean matches(Filter<Symbol> scopeFilter, boolean checkResult, int mark) {
                return this.implFilter == scopeFilter &&
                        this.checkResult == checkResult &&
                        this.prevMark == mark;
            }
        }

        MethodSymbol get(MethodSymbol ms, TypeSymbol origin, boolean checkResult, Filter<Symbol> implFilter) {
            SoftReference<Map<TypeSymbol, Entry>> ref_cache = _map.get(ms);
            Map<TypeSymbol, Entry> cache = ref_cache != null ? ref_cache.get() : null;
            if (cache == null) {
                cache = new HashMap<>();
                _map.put(ms, new SoftReference<>(cache));
            }
            Entry e = cache.get(origin);
            CompoundScope members = membersClosure(origin.type, true);
            if (e == null ||
                    !e.matches(implFilter, checkResult, members.getMark())) {
                MethodSymbol impl = implementationInternal(ms, origin, checkResult, implFilter);
                cache.put(origin, new Entry(impl, implFilter, checkResult, members.getMark()));
                return impl;
            }
            else {
                return e.cachedImpl;
            }
        }

        private MethodSymbol implementationInternal(MethodSymbol ms, TypeSymbol origin, boolean checkResult, Filter<Symbol> implFilter) {
            for (Type t = origin.type; t.hasTag(CLASS) || t.hasTag(TYPEVAR); t = supertype(t)) {
                while (t.hasTag(TYPEVAR))
                    t = t.getUpperBound();
                TypeSymbol c = t.tsym;
                for (Scope.Entry e = c.members().lookup(ms.name, implFilter);
                     e.scope != null;
                     e = e.next(implFilter)) {
                    if (e.sym != null &&
                             e.sym.overrides(ms, origin, Types.this, checkResult))
                        return (MethodSymbol)e.sym;
                }
            }
            return null;
        }
    }

    private ImplementationCache implCache = new ImplementationCache();

    public MethodSymbol implementation(MethodSymbol ms, TypeSymbol origin, boolean checkResult, Filter<Symbol> implFilter) {
        return implCache.get(ms, origin, checkResult, implFilter);
    }
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="compute transitive closure of all members in given site">
    class MembersClosureCache extends SimpleVisitor<CompoundScope, Boolean> {

        private WeakHashMap<TypeSymbol, Entry> _map = new WeakHashMap<>();

        class Entry {
            final boolean skipInterfaces;
            final CompoundScope compoundScope;

            public Entry(boolean skipInterfaces, CompoundScope compoundScope) {
                this.skipInterfaces = skipInterfaces;
                this.compoundScope = compoundScope;
            }

            boolean matches(boolean skipInterfaces) {
                return this.skipInterfaces == skipInterfaces;
            }
        }

        List<TypeSymbol> seenTypes = List.nil();

        /** members closure visitor methods **/

        public CompoundScope visitType(Type t, Boolean skipInterface) {
            return null;
        }

        @Override
        public CompoundScope visitClassType(ClassType t, Boolean skipInterface) {
            if (seenTypes.contains(t.tsym)) {
                //this is possible when an interface is implemented in multiple
                //superclasses, or when a classs hierarchy is circular - in such
                //cases we don't need to recurse (empty scope is returned)
                return new CompoundScope(t.tsym);
            }
            try {
                seenTypes = seenTypes.prepend(t.tsym);
                ClassSymbol csym = (ClassSymbol)t.tsym;
                Entry e = _map.get(csym);
                if (e == null || !e.matches(skipInterface)) {
                    CompoundScope membersClosure = new CompoundScope(csym);
                    if (!skipInterface) {
                        for (Type i : interfaces(t)) {
                            membersClosure.addSubScope(visit(i, skipInterface));
                        }
                    }
                    membersClosure.addSubScope(visit(supertype(t), skipInterface));
                    membersClosure.addSubScope(csym.members());
                    e = new Entry(skipInterface, membersClosure);
                    _map.put(csym, e);
                }
                return e.compoundScope;
            }
            finally {
                seenTypes = seenTypes.tail;
            }
        }

        @Override
        public CompoundScope visitTypeVar(TypeVar t, Boolean skipInterface) {
            return visit(t.getUpperBound(), skipInterface);
        }
    }

    private MembersClosureCache membersCache = new MembersClosureCache();

    public CompoundScope membersClosure(Type site, boolean skipInterface) {
        return membersCache.visit(site, skipInterface);
    }
    // </editor-fold>


    //where
    public List<MethodSymbol> interfaceCandidates(Type site, MethodSymbol ms) {
        Filter<Symbol> filter = new MethodFilter(ms, site);
        List<MethodSymbol> candidates = List.nil();
            for (Symbol s : membersClosure(site, false).getElements(filter)) {
                if (!site.tsym.isInterface() && !s.owner.isInterface()) {
                    return List.of((MethodSymbol)s);
                } else if (!candidates.contains(s)) {
                    candidates = candidates.prepend((MethodSymbol)s);
                }
            }
            return prune(candidates);
        }

    public List<MethodSymbol> prune(List<MethodSymbol> methods) {
        ListBuffer<MethodSymbol> methodsMin = new ListBuffer<>();
        for (MethodSymbol m1 : methods) {
            boolean isMin_m1 = true;
            for (MethodSymbol m2 : methods) {
                if (m1 == m2) continue;
                if (m2.owner != m1.owner &&
                        asSuper(m2.owner.type, m1.owner) != null) {
                    isMin_m1 = false;
                    break;
                }
            }
            if (isMin_m1)
                methodsMin.append(m1);
        }
        return methodsMin.toList();
    }
    // where
            private class MethodFilter implements Filter<Symbol> {

                Symbol msym;
                Type site;

                MethodFilter(Symbol msym, Type site) {
                    this.msym = msym;
                    this.site = site;
                }

                public boolean accepts(Symbol s) {
                    return s.kind == Kinds.MTH &&
                            s.name == msym.name &&
                            (s.flags() & SYNTHETIC) == 0 &&
                            s.isInheritedIn(site.tsym, Types.this) &&
                            overrideEquivalent(memberType(site, s), memberType(site, msym));
                }
            }
    // </editor-fold>

    /**
     * Does t have the same arguments as s?  It is assumed that both
     * types are (possibly polymorphic) method types.  Monomorphic
     * method types "have the same arguments", if their argument lists
     * are equal.  Polymorphic method types "have the same arguments",
     * if they have the same arguments after renaming all type
     * variables of one to corresponding type variables in the other,
     * where correspondence is by position in the type parameter list.
     */
    public boolean hasSameArgs(Type t, Type s) {
        return hasSameArgs(t, s, true);
    }

    public boolean hasSameArgs(Type t, Type s, boolean strict) {
        return hasSameArgs(t, s, strict ? hasSameArgs_strict : hasSameArgs_nonstrict);
    }

    private boolean hasSameArgs(Type t, Type s, TypeRelation hasSameArgs) {
        return hasSameArgs.visit(t, s);
    }
    // where
        private class HasSameArgs extends TypeRelation {

            boolean strict;

            public HasSameArgs(boolean strict) {
                this.strict = strict;
            }

            public Boolean visitType(Type t, Type s) {
                throw new AssertionError();
            }

            @Override
            public Boolean visitMethodType(MethodType t, Type s) {
                return s.hasTag(METHOD)
                    && containsTypeEquivalent(t.argtypes, s.getParameterTypes());
            }

            @Override
            public Boolean visitForAll(ForAll t, Type s) {
                if (!s.hasTag(FORALL))
                    return strict ? false : visitMethodType(t.asMethodType(), s);

                ForAll forAll = (ForAll)s;
                return hasSameBounds(t, forAll)
                    && visit(t.qtype, subst(forAll.qtype, forAll.tvars, t.tvars));
            }

            @Override
            public Boolean visitErrorType(ErrorType t, Type s) {
                return false;
            }
        }

    TypeRelation hasSameArgs_strict = new HasSameArgs(true);
        TypeRelation hasSameArgs_nonstrict = new HasSameArgs(false);

    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="subst">
    public List<Type> subst(List<Type> ts,
                            List<Type> from,
                            List<Type> to) {
        return new Subst(from, to).subst(ts);
    }

    /**
     * Substitute all occurrences of a type in `from' with the
     * corresponding type in `to' in 't'. Match lists `from' and `to'
     * from the right: If lists have different length, discard leading
     * elements of the longer list.
     */
    public Type subst(Type t, List<Type> from, List<Type> to) {
        return new Subst(from, to).subst(t);
    }

    private class Subst extends UnaryVisitor<Type> {
        List<Type> from;
        List<Type> to;

        public Subst(List<Type> from, List<Type> to) {
            int fromLength = from.length();
            int toLength = to.length();
            while (fromLength > toLength) {
                fromLength--;
                from = from.tail;
            }
            while (fromLength < toLength) {
                toLength--;
                to = to.tail;
            }
            this.from = from;
            this.to = to;
        }

        Type subst(Type t) {
            if (from.tail == null)
                return t;
            else
                return visit(t);
            }

        List<Type> subst(List<Type> ts) {
            if (from.tail == null)
                return ts;
            boolean wild = false;
            if (ts.nonEmpty() && from.nonEmpty()) {
                Type head1 = subst(ts.head);
                List<Type> tail1 = subst(ts.tail);
                if (head1 != ts.head || tail1 != ts.tail)
                    return tail1.prepend(head1);
            }
            return ts;
        }

        public Type visitType(Type t, Void ignored) {
            return t;
        }

        @Override
        public Type visitMethodType(MethodType t, Void ignored) {
            List<Type> argtypes = subst(t.argtypes);
            Type restype = subst(t.restype);
            List<Type> thrown = subst(t.thrown);
            if (argtypes == t.argtypes &&
                restype == t.restype &&
                thrown == t.thrown)
                return t;
            else
                return new MethodType(argtypes, restype, thrown, t.tsym);
        }

        @Override
        public Type visitTypeVar(TypeVar t, Void ignored) {
            for (List<Type> from = this.from, to = this.to;
                 from.nonEmpty();
                 from = from.tail, to = to.tail) {
                if (t == from.head) {
                    return to.head.withTypeVar(t);
                }
            }
            return t;
        }

        @Override
        public Type visitClassType(ClassType t, Void ignored) {
            if (!t.isCompound()) {
                List<Type> typarams = t.getTypeArguments();
                List<Type> typarams1 = subst(typarams);
                Type outer = t.getEnclosingType();
                Type outer1 = subst(outer);
                if (typarams1 == typarams && outer1 == outer)
                    return t;
                else
                    return new ClassType(outer1, typarams1, t.tsym,
                                         t.getAnnotationMirrors());
            } else {
                Type st = subst(supertype(t));
                List<Type> is = subst(interfaces(t));
                if (st == supertype(t) && is == interfaces(t))
                    return t;
                else
                    return makeCompoundType(is.prepend(st));
            }
        }

        @Override
        public Type visitWildcardType(WildcardType t, Void ignored) {
            Type bound = t.type;
            if (t.kind != BoundKind.UNBOUND)
                bound = subst(bound);
            if (bound == t.type) {
                return t;
            } else {
                if (t.isExtendsBound() && bound.isExtendsBound())
                    bound = wildUpperBound(bound);
                return new WildcardType(bound, t.kind, syms.boundClass,
                                        t.bound, t.getAnnotationMirrors());
            }
        }

        @Override
        public Type visitArrayType(ArrayType t, Void ignored) {
            Type elemtype = subst(t.elemtype);
            if (elemtype == t.elemtype)
                return t;
            else
                return new ArrayType(elemtype, t.tsym, t.getAnnotationMirrors());
        }

        @Override
        public Type visitForAll(ForAll t, Void ignored) {
            if (Type.containsAny(to, t.tvars)) {
                //perform alpha-renaming of free-variables in 't'
                //if 'to' types contain variables that are free in 't'
                List<Type> freevars = newInstances(t.tvars);
                t = new ForAll(freevars,
                               Types.this.subst(t.qtype, t.tvars, freevars));
            }
            List<Type> tvars1 = substBounds(t.tvars, from, to);
            Type qtype1 = subst(t.qtype);
            if (tvars1 == t.tvars && qtype1 == t.qtype) {
                return t;
            } else if (tvars1 == t.tvars) {
                return new ForAll(tvars1, qtype1);
            } else {
                return new ForAll(tvars1,
                                  Types.this.subst(qtype1, t.tvars, tvars1));
            }
        }

        @Override
        public Type visitErrorType(ErrorType t, Void ignored) {
            return t;
        }
    }

    public List<Type> substBounds(List<Type> tvars,
                                  List<Type> from,
                                  List<Type> to) {
        if (tvars.isEmpty())
            return tvars;
        ListBuffer<Type> newBoundsBuf = new ListBuffer<>();
        boolean changed = false;
        // calculate new bounds
        for (Type t : tvars) {
            TypeVar tv = (TypeVar) t;
            Type bound = subst(tv.bound, from, to);
            if (bound != tv.bound)
                changed = true;
            newBoundsBuf.append(bound);
        }
        if (!changed)
            return tvars;
        ListBuffer<Type> newTvars = new ListBuffer<>();
        // create new type variables without bounds
        for (Type t : tvars) {
            newTvars.append(new TypeVar(t.tsym, null, syms.botType,
                                        t.getAnnotationMirrors()));
        }
        // the new bounds should use the new type variables in place
        // of the old
        List<Type> newBounds = newBoundsBuf.toList();
        from = tvars;
        to = newTvars.toList();
        for (; !newBounds.isEmpty(); newBounds = newBounds.tail) {
            newBounds.head = subst(newBounds.head, from, to);
        }
        newBounds = newBoundsBuf.toList();
        // set the bounds of new type variables to the new bounds
        for (Type t : newTvars.toList()) {
            TypeVar tv = (TypeVar) t;
            tv.bound = newBounds.head;
            newBounds = newBounds.tail;
        }
        return newTvars.toList();
    }

    public TypeVar substBound(TypeVar t, List<Type> from, List<Type> to) {
        Type bound1 = subst(t.bound, from, to);
        if (bound1 == t.bound)
            return t;
        else {
            // create new type variable without bounds
            TypeVar tv = new TypeVar(t.tsym, null, syms.botType,
                                     t.getAnnotationMirrors());
            // the new bound should use the new type variable in place
            // of the old
            tv.bound = subst(bound1, List.<Type>of(t), List.<Type>of(tv));
            return tv;
        }
    }
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="hasSameBounds">
    /**
     * Does t have the same bounds for quantified variables as s?
     */
    public boolean hasSameBounds(ForAll t, ForAll s) {
        List<Type> l1 = t.tvars;
        List<Type> l2 = s.tvars;
        while (l1.nonEmpty() && l2.nonEmpty() &&
               isSameType(l1.head.getUpperBound(),
                          subst(l2.head.getUpperBound(),
                                s.tvars,
                                t.tvars))) {
            l1 = l1.tail;
            l2 = l2.tail;
        }
        return l1.isEmpty() && l2.isEmpty();
    }
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="newInstances">
    /** Create new vector of type variables from list of variables
     *  changing all recursive bounds from old to new list.
     */
    public List<Type> newInstances(List<Type> tvars) {
        List<Type> tvars1 = Type.map(tvars, newInstanceFun);
        for (List<Type> l = tvars1; l.nonEmpty(); l = l.tail) {
            TypeVar tv = (TypeVar) l.head;
            tv.bound = subst(tv.bound, tvars, tvars1);
        }
        return tvars1;
    }
    private static final Mapping newInstanceFun = new Mapping("newInstanceFun") {
            public Type apply(Type t) { return new TypeVar(t.tsym, t.getUpperBound(), t.getLowerBound(), t.getAnnotationMirrors()); }
        };
    // </editor-fold>

    public Type createMethodTypeWithParameters(Type original, List<Type> newParams) {
        return original.accept(methodWithParameters, newParams);
    }
    // where
        private final MapVisitor<List<Type>> methodWithParameters = new MapVisitor<List<Type>>() {
            public Type visitType(Type t, List<Type> newParams) {
                throw new IllegalArgumentException("Not a method type: " + t);
            }
            public Type visitMethodType(MethodType t, List<Type> newParams) {
                return new MethodType(newParams, t.restype, t.thrown, t.tsym);
            }
            public Type visitForAll(ForAll t, List<Type> newParams) {
                return new ForAll(t.tvars, t.qtype.accept(this, newParams));
            }
        };

    public Type createMethodTypeWithThrown(Type original, List<Type> newThrown) {
        return original.accept(methodWithThrown, newThrown);
    }
    // where
        private final MapVisitor<List<Type>> methodWithThrown = new MapVisitor<List<Type>>() {
            public Type visitType(Type t, List<Type> newThrown) {
                throw new IllegalArgumentException("Not a method type: " + t);
            }
            public Type visitMethodType(MethodType t, List<Type> newThrown) {
                return new MethodType(t.argtypes, t.restype, newThrown, t.tsym);
            }
            public Type visitForAll(ForAll t, List<Type> newThrown) {
                return new ForAll(t.tvars, t.qtype.accept(this, newThrown));
            }
        };

    public Type createMethodTypeWithReturn(Type original, Type newReturn) {
        return original.accept(methodWithReturn, newReturn);
    }
    // where
        private final MapVisitor<Type> methodWithReturn = new MapVisitor<Type>() {
            public Type visitType(Type t, Type newReturn) {
                throw new IllegalArgumentException("Not a method type: " + t);
            }
            public Type visitMethodType(MethodType t, Type newReturn) {
                return new MethodType(t.argtypes, newReturn, t.thrown, t.tsym);
            }
            public Type visitForAll(ForAll t, Type newReturn) {
                return new ForAll(t.tvars, t.qtype.accept(this, newReturn));
            }
        };

    // <editor-fold defaultstate="collapsed" desc="createErrorType">
    public Type createErrorType(Type originalType) {
        return new ErrorType(originalType, syms.errSymbol);
    }

    public Type createErrorType(ClassSymbol c, Type originalType) {
        return new ErrorType(c, originalType);
    }

    public Type createErrorType(Name name, TypeSymbol container, Type originalType) {
        return new ErrorType(name, container, originalType);
    }
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="rank">
    /**
     * The rank of a class is the length of the longest path between
     * the class and java.lang.Object in the class inheritance
     * graph. Undefined for all but reference types.
     */
    public int rank(Type t) {
        switch(t.getTag()) {
        case CLASS: {
            ClassType cls = (ClassType)t;
            if (cls.rank_field < 0) {
                Name fullname = cls.tsym.getQualifiedName();
                if (fullname == names.java_lang_Object)
                    cls.rank_field = 0;
                else {
                    int r = rank(supertype(cls));
                    for (List<Type> l = interfaces(cls);
                         l.nonEmpty();
                         l = l.tail) {
                        if (rank(l.head) > r)
                            r = rank(l.head);
                    }
                    cls.rank_field = r + 1;
                }
            }
            return cls.rank_field;
        }
        case TYPEVAR: {
            TypeVar tvar = (TypeVar)t;
            if (tvar.rank_field < 0) {
                int r = rank(supertype(tvar));
                for (List<Type> l = interfaces(tvar);
                     l.nonEmpty();
                     l = l.tail) {
                    if (rank(l.head) > r) r = rank(l.head);
                }
                tvar.rank_field = r + 1;
            }
            return tvar.rank_field;
        }
        case ERROR:
        case NONE:
            return 0;
        default:
            throw new AssertionError();
        }
    }
    // </editor-fold>

    /**
     * Helper method for generating a string representation of a given type
     * accordingly to a given locale
     */
    public String toString(Type t, Locale locale) {
        return Printer.createStandardPrinter(messages).visit(t, locale);
    }

    /**
     * Helper method for generating a string representation of a given type
     * accordingly to a given locale
     */
    public String toString(Symbol t, Locale locale) {
        return Printer.createStandardPrinter(messages).visit(t, locale);
    }

    // <editor-fold defaultstate="collapsed" desc="toString">
    /**
     * This toString is slightly more descriptive than the one on Type.
     *
     * @deprecated Types.toString(Type t, Locale l) provides better support
     * for localization
     */
    @Deprecated
    public String toString(Type t) {
        if (t.hasTag(FORALL)) {
            ForAll forAll = (ForAll)t;
            return typaramsString(forAll.tvars) + forAll.qtype;
        }
        return "" + t;
    }
    // where
        private String typaramsString(List<Type> tvars) {
            StringBuilder s = new StringBuilder();
            s.append('<');
            boolean first = true;
            for (Type t : tvars) {
                if (!first) s.append(", ");
                first = false;
                appendTyparamString(((TypeVar)t), s);
            }
            s.append('>');
            return s.toString();
        }
        private void appendTyparamString(TypeVar t, StringBuilder buf) {
            buf.append(t);
            if (t.bound == null ||
                t.bound.tsym.getQualifiedName() == names.java_lang_Object)
                return;
            buf.append(" extends "); // Java syntax; no need for i18n
            Type bound = t.bound;
            if (!bound.isCompound()) {
                buf.append(bound);
            } else if ((erasure(t).tsym.flags() & INTERFACE) == 0) {
                buf.append(supertype(t));
                for (Type intf : interfaces(t)) {
                    buf.append('&');
                    buf.append(intf);
                }
            } else {
                // No superclass was given in bounds.
                // In this case, supertype is Object, erasure is first interface.
                boolean first = true;
                for (Type intf : interfaces(t)) {
                    if (!first) buf.append('&');
                    first = false;
                    buf.append(intf);
                }
            }
        }
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="Determining least upper bounds of types">
    /**
     * A cache for closures.
     *
     * <p>A closure is a list of all the supertypes and interfaces of
     * a class or interface type, ordered by ClassSymbol.precedes
     * (that is, subclasses come first, arbitrary but fixed
     * otherwise).
     */
    private Map<Type,List<Type>> closureCache = new HashMap<>();

    /**
     * Returns the closure of a class or interface type.
     */
    public List<Type> closure(Type t) {
        List<Type> cl = closureCache.get(t);
        if (cl == null) {
            Type st = supertype(t);
            if (!t.isCompound()) {
                if (st.hasTag(CLASS)) {
                    cl = insert(closure(st), t);
                } else if (st.hasTag(TYPEVAR)) {
                    cl = closure(st).prepend(t);
                } else {
                    cl = List.of(t);
                }
            } else {
                cl = closure(supertype(t));
            }
            for (List<Type> l = interfaces(t); l.nonEmpty(); l = l.tail)
                cl = union(cl, closure(l.head));
            closureCache.put(t, cl);
        }
        return cl;
    }

    /**
     * Insert a type in a closure
     */
    public List<Type> insert(List<Type> cl, Type t) {
        if (cl.isEmpty()) {
            return cl.prepend(t);
        } else if (t.tsym == cl.head.tsym) {
            return cl;
        } else if (t.tsym.precedes(cl.head.tsym, this)) {
            return cl.prepend(t);
        } else {
            // t comes after head, or the two are unrelated
            return insert(cl.tail, t).prepend(cl.head);
        }
    }

    /**
     * Form the union of two closures
     */
    public List<Type> union(List<Type> cl1, List<Type> cl2) {
        if (cl1.isEmpty()) {
            return cl2;
        } else if (cl2.isEmpty()) {
            return cl1;
        } else if (cl1.head.tsym == cl2.head.tsym) {
            return union(cl1.tail, cl2.tail).prepend(cl1.head);
        } else if (cl1.head.tsym.precedes(cl2.head.tsym, this)) {
            return union(cl1.tail, cl2).prepend(cl1.head);
        } else if (cl2.head.tsym.precedes(cl1.head.tsym, this)) {
            return union(cl1, cl2.tail).prepend(cl2.head);
        } else {
            // unrelated types
            return union(cl1.tail, cl2).prepend(cl1.head);
        }
    }

    /**
     * Intersect two closures
     */
    public List<Type> intersect(List<Type> cl1, List<Type> cl2) {
        if (cl1 == cl2)
            return cl1;
        if (cl1.isEmpty() || cl2.isEmpty())
            return List.nil();
        if (cl1.head.tsym.precedes(cl2.head.tsym, this))
            return intersect(cl1.tail, cl2);
        if (cl2.head.tsym.precedes(cl1.head.tsym, this))
            return intersect(cl1, cl2.tail);
        if (isSameType(cl1.head, cl2.head))
            return intersect(cl1.tail, cl2.tail).prepend(cl1.head);
        if (cl1.head.tsym == cl2.head.tsym &&
            cl1.head.hasTag(CLASS) && cl2.head.hasTag(CLASS)) {
            if (cl1.head.isParameterized() && cl2.head.isParameterized()) {
                Type merge = merge(cl1.head,cl2.head);
                return intersect(cl1.tail, cl2.tail).prepend(merge);
            }
            if (cl1.head.isRaw() || cl2.head.isRaw())
                return intersect(cl1.tail, cl2.tail).prepend(erasure(cl1.head));
        }
        return intersect(cl1.tail, cl2.tail);
    }
    // where
        class TypePair {
            final Type t1;
            final Type t2;
            TypePair(Type t1, Type t2) {
                this.t1 = t1;
                this.t2 = t2;
            }
            @Override
            public int hashCode() {
                return 127 * Types.this.hashCode(t1) + Types.this.hashCode(t2);
            }
            @Override
            public boolean equals(Object obj) {
                if (!(obj instanceof TypePair))
                    return false;
                TypePair typePair = (TypePair)obj;
                return isSameType(t1, typePair.t1)
                    && isSameType(t2, typePair.t2);
            }
        }
        Set<TypePair> mergeCache = new HashSet<>();
        private Type merge(Type c1, Type c2) {
            ClassType class1 = (ClassType) c1;
            List<Type> act1 = class1.getTypeArguments();
            ClassType class2 = (ClassType) c2;
            List<Type> act2 = class2.getTypeArguments();
            ListBuffer<Type> merged = new ListBuffer<>();
            List<Type> typarams = class1.tsym.type.getTypeArguments();

            while (act1.nonEmpty() && act2.nonEmpty() && typarams.nonEmpty()) {
                if (containsType(act1.head, act2.head)) {
                    merged.append(act1.head);
                } else if (containsType(act2.head, act1.head)) {
                    merged.append(act2.head);
                } else {
                    TypePair pair = new TypePair(c1, c2);
                    Type m;
                    if (mergeCache.add(pair)) {
                        m = new WildcardType(lub(wildUpperBound(act1.head),
                                                 wildUpperBound(act2.head)),
                                             BoundKind.EXTENDS,
                                             syms.boundClass,
                                             Type.noAnnotations);
                        mergeCache.remove(pair);
                    } else {
                        m = new WildcardType(syms.objectType,
                                             BoundKind.UNBOUND,
                                             syms.boundClass,
                                             Type.noAnnotations);
                    }
                    merged.append(m.withTypeVar(typarams.head));
                }
                act1 = act1.tail;
                act2 = act2.tail;
                typarams = typarams.tail;
            }
            Assert.check(act1.isEmpty() && act2.isEmpty() && typarams.isEmpty());
            // There is no spec detailing how type annotations are to
            // be inherited.  So set it to noAnnotations for now
            return new ClassType(class1.getEnclosingType(), merged.toList(),
                                 class1.tsym, Type.noAnnotations);
        }

    /**
     * Return the minimum type of a closure, a compound type if no
     * unique minimum exists.
     */
    private Type compoundMin(List<Type> cl) {
        if (cl.isEmpty()) return syms.objectType;
        List<Type> compound = closureMin(cl);
        if (compound.isEmpty())
            return null;
        else if (compound.tail.isEmpty())
            return compound.head;
        else
            return makeCompoundType(compound);
    }

    /**
     * Return the minimum types of a closure, suitable for computing
     * compoundMin or glb.
     */
    private List<Type> closureMin(List<Type> cl) {
        ListBuffer<Type> classes = new ListBuffer<>();
        ListBuffer<Type> interfaces = new ListBuffer<>();
        Set<Type> toSkip = new HashSet<>();
        while (!cl.isEmpty()) {
            Type current = cl.head;
            boolean keep = !toSkip.contains(current);
            if (keep && current.hasTag(TYPEVAR)) {
                // skip lower-bounded variables with a subtype in cl.tail
                for (Type t : cl.tail) {
                    if (isSubtypeNoCapture(t, current)) {
                        keep = false;
                        break;
                    }
                }
            }
            if (keep) {
                if (current.isInterface())
                    interfaces.append(current);
                else
                    classes.append(current);
                for (Type t : cl.tail) {
                    // skip supertypes of 'current' in cl.tail
                    if (isSubtypeNoCapture(current, t))
                        toSkip.add(t);
                }
            }
            cl = cl.tail;
        }
        return classes.appendList(interfaces).toList();
    }

    /**
     * Return the least upper bound of pair of types.  if the lub does
     * not exist return null.
     */
    public Type lub(Type t1, Type t2) {
        return lub(List.of(t1, t2));
    }

    /**
     * Return the least upper bound (lub) of set of types.  If the lub
     * does not exist return the type of null (bottom).
     */
    public Type lub(List<Type> ts) {
        final int ARRAY_BOUND = 1;
        final int CLASS_BOUND = 2;
        int boundkind = 0;
        for (Type t : ts) {
            switch (t.getTag()) {
            case CLASS:
                boundkind |= CLASS_BOUND;
                break;
            case ARRAY:
                boundkind |= ARRAY_BOUND;
                break;
            case  TYPEVAR:
                do {
                    t = t.getUpperBound();
                } while (t.hasTag(TYPEVAR));
                if (t.hasTag(ARRAY)) {
                    boundkind |= ARRAY_BOUND;
                } else {
                    boundkind |= CLASS_BOUND;
                }
                break;
            default:
                if (t.isPrimitive())
                    return syms.errType;
            }
        }
        switch (boundkind) {
        case 0:
            return syms.botType;

        case ARRAY_BOUND:
            // calculate lub(A[], B[])
            List<Type> elements = Type.map(ts, elemTypeFun);
            for (Type t : elements) {
                if (t.isPrimitive()) {
                    // if a primitive type is found, then return
                    // arraySuperType unless all the types are the
                    // same
                    Type first = ts.head;
                    for (Type s : ts.tail) {
                        if (!isSameType(first, s)) {
                             // lub(int[], B[]) is Cloneable & Serializable
                            return arraySuperType();
                        }
                    }
                    // all the array types are the same, return one
                    // lub(int[], int[]) is int[]
                    return first;
                }
            }
            // lub(A[], B[]) is lub(A, B)[]
            return new ArrayType(lub(elements), syms.arrayClass,
                                 Type.noAnnotations);

        case CLASS_BOUND:
            // calculate lub(A, B)
            while (!ts.head.hasTag(CLASS) && !ts.head.hasTag(TYPEVAR)) {
                ts = ts.tail;
            }
            Assert.check(!ts.isEmpty());
            //step 1 - compute erased candidate set (EC)
            List<Type> cl = erasedSupertypes(ts.head);
            for (Type t : ts.tail) {
                if (t.hasTag(CLASS) || t.hasTag(TYPEVAR))
                    cl = intersect(cl, erasedSupertypes(t));
            }
            //step 2 - compute minimal erased candidate set (MEC)
            List<Type> mec = closureMin(cl);
            //step 3 - for each element G in MEC, compute lci(Inv(G))
            List<Type> candidates = List.nil();
            for (Type erasedSupertype : mec) {
                List<Type> lci = List.of(asSuper(ts.head, erasedSupertype.tsym));
                for (Type t : ts) {
                    lci = intersect(lci, List.of(asSuper(t, erasedSupertype.tsym)));
                }
                candidates = candidates.appendList(lci);
            }
            //step 4 - let MEC be { G1, G2 ... Gn }, then we have that
            //lub = lci(Inv(G1)) & lci(Inv(G2)) & ... & lci(Inv(Gn))
            return compoundMin(candidates);

        default:
            // calculate lub(A, B[])
            List<Type> classes = List.of(arraySuperType());
            for (Type t : ts) {
                if (!t.hasTag(ARRAY)) // Filter out any arrays
                    classes = classes.prepend(t);
            }
            // lub(A, B[]) is lub(A, arraySuperType)
            return lub(classes);
        }
    }
    // where
        List<Type> erasedSupertypes(Type t) {
            ListBuffer<Type> buf = new ListBuffer<>();
            for (Type sup : closure(t)) {
                if (sup.hasTag(TYPEVAR)) {
                    buf.append(sup);
                } else {
                    buf.append(erasure(sup));
                }
            }
            return buf.toList();
        }

        private Type arraySuperType = null;
        private Type arraySuperType() {
            // initialized lazily to avoid problems during compiler startup
            if (arraySuperType == null) {
                synchronized (this) {
                    if (arraySuperType == null) {
                        // JLS 10.8: all arrays implement Cloneable and Serializable.
                        arraySuperType = makeCompoundType(List.of(syms.serializableType,
                                                                  syms.cloneableType), true);
                    }
                }
            }
            return arraySuperType;
        }
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="Greatest lower bound">
    public Type glb(List<Type> ts) {
        Type t1 = ts.head;
        for (Type t2 : ts.tail) {
            if (t1.isErroneous())
                return t1;
            t1 = glb(t1, t2);
        }
        return t1;
    }
    //where
    public Type glb(Type t, Type s) {
        if (s == null)
            return t;
        else if (t.isPrimitive() || s.isPrimitive())
            return syms.errType;
        else if (isSubtypeNoCapture(t, s))
            return t;
        else if (isSubtypeNoCapture(s, t))
            return s;

        List<Type> closure = union(closure(t), closure(s));
        return glbFlattened(closure, t);
    }
    //where
    /**
     * Perform glb for a list of non-primitive, non-error, non-compound types;
     * redundant elements are removed.  Bounds should be ordered according to
     * {@link Symbol#precedes(TypeSymbol,Types)}.
     *
     * @param flatBounds List of type to glb
     * @param errT Original type to use if the result is an error type
     */
    private Type glbFlattened(List<Type> flatBounds, Type errT) {
        List<Type> bounds = closureMin(flatBounds);

        if (bounds.isEmpty()) {             // length == 0
            return syms.objectType;
        } else if (bounds.tail.isEmpty()) { // length == 1
            return bounds.head;
        } else {                            // length > 1
            int classCount = 0;
            List<Type> lowers = List.nil();
            for (Type bound : bounds) {
                if (!bound.isInterface()) {
                    classCount++;
                    Type lower = cvarLowerBound(bound);
                    if (bound != lower && !lower.hasTag(BOT))
                        lowers = insert(lowers, lower);
                }
            }
            if (classCount > 1) {
                if (lowers.isEmpty())
                    return createErrorType(errT);
                else
                    return glbFlattened(union(bounds, lowers), errT);
            }
        }
        return makeCompoundType(bounds);
    }
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="hashCode">
    /**
     * Compute a hash code on a type.
     */
    public int hashCode(Type t) {
        return hashCode.visit(t);
    }
    // where
        private static final UnaryVisitor<Integer> hashCode = new UnaryVisitor<Integer>() {

            public Integer visitType(Type t, Void ignored) {
                return t.getTag().ordinal();
            }

            @Override
            public Integer visitClassType(ClassType t, Void ignored) {
                int result = visit(t.getEnclosingType());
                result *= 127;
                result += t.tsym.flatName().hashCode();
                for (Type s : t.getTypeArguments()) {
                    result *= 127;
                    result += visit(s);
                }
                return result;
            }

            @Override
            public Integer visitMethodType(MethodType t, Void ignored) {
                int h = METHOD.ordinal();
                for (List<Type> thisargs = t.argtypes;
                     thisargs.tail != null;
                     thisargs = thisargs.tail)
                    h = (h << 5) + visit(thisargs.head);
                return (h << 5) + visit(t.restype);
            }

            @Override
            public Integer visitWildcardType(WildcardType t, Void ignored) {
                int result = t.kind.hashCode();
                if (t.type != null) {
                    result *= 127;
                    result += visit(t.type);
                }
                return result;
            }

            @Override
            public Integer visitArrayType(ArrayType t, Void ignored) {
                return visit(t.elemtype) + 12;
            }

            @Override
            public Integer visitTypeVar(TypeVar t, Void ignored) {
                return System.identityHashCode(t.tsym);
            }

            @Override
            public Integer visitUndetVar(UndetVar t, Void ignored) {
                return System.identityHashCode(t);
            }

            @Override
            public Integer visitErrorType(ErrorType t, Void ignored) {
                return 0;
            }
        };
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="Return-Type-Substitutable">
    /**
     * Does t have a result that is a subtype of the result type of s,
     * suitable for covariant returns?  It is assumed that both types
     * are (possibly polymorphic) method types.  Monomorphic method
     * types are handled in the obvious way.  Polymorphic method types
     * require renaming all type variables of one to corresponding
     * type variables in the other, where correspondence is by
     * position in the type parameter list. */
    public boolean resultSubtype(Type t, Type s, Warner warner) {
        List<Type> tvars = t.getTypeArguments();
        List<Type> svars = s.getTypeArguments();
        Type tres = t.getReturnType();
        Type sres = subst(s.getReturnType(), svars, tvars);
        return covariantReturnType(tres, sres, warner);
    }

    /**
     * Return-Type-Substitutable.
     * @jls section 8.4.5
     */
    public boolean returnTypeSubstitutable(Type r1, Type r2) {
        if (hasSameArgs(r1, r2))
            return resultSubtype(r1, r2, noWarnings);
        else
            return covariantReturnType(r1.getReturnType(),
                                       erasure(r2.getReturnType()),
                                       noWarnings);
    }

    public boolean returnTypeSubstitutable(Type r1,
                                           Type r2, Type r2res,
                                           Warner warner) {
        if (isSameType(r1.getReturnType(), r2res))
            return true;
        if (r1.getReturnType().isPrimitive() || r2res.isPrimitive())
            return false;

        if (hasSameArgs(r1, r2))
            return covariantReturnType(r1.getReturnType(), r2res, warner);
        if (!allowCovariantReturns)
            return false;
        if (isSubtypeUnchecked(r1.getReturnType(), r2res, warner))
            return true;
        if (!isSubtype(r1.getReturnType(), erasure(r2res)))
            return false;
        warner.warn(LintCategory.UNCHECKED);
        return true;
    }

    /**
     * Is t an appropriate return type in an overrider for a
     * method that returns s?
     */
    public boolean covariantReturnType(Type t, Type s, Warner warner) {
        return
            isSameType(t, s) ||
            allowCovariantReturns &&
            !t.isPrimitive() &&
            !s.isPrimitive() &&
            isAssignable(t, s, warner);
    }
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="Box/unbox support">
    /**
     * Return the class that boxes the given primitive.
     */
    public ClassSymbol boxedClass(Type t) {
        return syms.enterClass(syms.boxedName[t.getTag().ordinal()]);
    }

    /**
     * Return the boxed type if 't' is primitive, otherwise return 't' itself.
     */
    public Type boxedTypeOrType(Type t) {
        return t.isPrimitive() ?
            boxedClass(t).type :
            t;
    }

    /**
     * Return the primitive type corresponding to a boxed type.
     */
    public Type unboxedType(Type t) {
        if (allowBoxing) {
            for (int i=0; i<syms.boxedName.length; i++) {
                Name box = syms.boxedName[i];
                if (box != null &&
                    asSuper(t, syms.enterClass(box)) != null)
                    return syms.typeOfTag[i];
            }
        }
        return Type.noType;
    }

    /**
     * Return the unboxed type if 't' is a boxed class, otherwise return 't' itself.
     */
    public Type unboxedTypeOrType(Type t) {
        Type unboxedType = unboxedType(t);
        return unboxedType.hasTag(NONE) ? t : unboxedType;
    }
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="Capture conversion">
    /*
     * JLS 5.1.10 Capture Conversion:
     *
     * Let G name a generic type declaration with n formal type
     * parameters A1 ... An with corresponding bounds U1 ... Un. There
     * exists a capture conversion from G<T1 ... Tn> to G<S1 ... Sn>,
     * where, for 1 <= i <= n:
     *
     * + If Ti is a wildcard type argument (4.5.1) of the form ? then
     *   Si is a fresh type variable whose upper bound is
     *   Ui[A1 := S1, ..., An := Sn] and whose lower bound is the null
     *   type.
     *
     * + If Ti is a wildcard type argument of the form ? extends Bi,
     *   then Si is a fresh type variable whose upper bound is
     *   glb(Bi, Ui[A1 := S1, ..., An := Sn]) and whose lower bound is
     *   the null type, where glb(V1,... ,Vm) is V1 & ... & Vm. It is
     *   a compile-time error if for any two classes (not interfaces)
     *   Vi and Vj,Vi is not a subclass of Vj or vice versa.
     *
     * + If Ti is a wildcard type argument of the form ? super Bi,
     *   then Si is a fresh type variable whose upper bound is
     *   Ui[A1 := S1, ..., An := Sn] and whose lower bound is Bi.
     *
     * + Otherwise, Si = Ti.
     *
     * Capture conversion on any type other than a parameterized type
     * (4.5) acts as an identity conversion (5.1.1). Capture
     * conversions never require a special action at run time and
     * therefore never throw an exception at run time.
     *
     * Capture conversion is not applied recursively.
     */
    /**
     * Capture conversion as specified by the JLS.
     */

    public List<Type> capture(List<Type> ts) {
        List<Type> buf = List.nil();
        for (Type t : ts) {
            buf = buf.prepend(capture(t));
        }
        return buf.reverse();
    }

    public Type capture(Type t) {
        if (!t.hasTag(CLASS)) {
            return t;
        }
        if (t.getEnclosingType() != Type.noType) {
            Type capturedEncl = capture(t.getEnclosingType());
            if (capturedEncl != t.getEnclosingType()) {
                Type type1 = memberType(capturedEncl, t.tsym);
                t = subst(type1, t.tsym.type.getTypeArguments(), t.getTypeArguments());
            }
        }
        ClassType cls = (ClassType)t;
        if (cls.isRaw() || !cls.isParameterized())
            return cls;

        ClassType G = (ClassType)cls.asElement().asType();
        List<Type> A = G.getTypeArguments();
        List<Type> T = cls.getTypeArguments();
        List<Type> S = freshTypeVariables(T);

        List<Type> currentA = A;
        List<Type> currentT = T;
        List<Type> currentS = S;
        boolean captured = false;
        while (!currentA.isEmpty() &&
               !currentT.isEmpty() &&
               !currentS.isEmpty()) {
            if (currentS.head != currentT.head) {
                captured = true;
                WildcardType Ti = (WildcardType)currentT.head;
                Type Ui = currentA.head.getUpperBound();
                CapturedType Si = (CapturedType)currentS.head;
                if (Ui == null)
                    Ui = syms.objectType;
                switch (Ti.kind) {
                case UNBOUND:
                    Si.bound = subst(Ui, A, S);
                    Si.lower = syms.botType;
                    break;
                case EXTENDS:
                    Si.bound = glb(Ti.getExtendsBound(), subst(Ui, A, S));
                    Si.lower = syms.botType;
                    break;
                case SUPER:
                    Si.bound = subst(Ui, A, S);
                    Si.lower = Ti.getSuperBound();
                    break;
                }
                Type tmpBound = Si.bound.hasTag(UNDETVAR) ? ((UndetVar)Si.bound).qtype : Si.bound;
                Type tmpLower = Si.lower.hasTag(UNDETVAR) ? ((UndetVar)Si.lower).qtype : Si.lower;
                if (!Si.bound.hasTag(ERROR) &&
                    !Si.lower.hasTag(ERROR) &&
                    isSameType(tmpBound, tmpLower, false)) {
                    currentS.head = Si.bound;
                }
            }
            currentA = currentA.tail;
            currentT = currentT.tail;
            currentS = currentS.tail;
        }
        if (!currentA.isEmpty() || !currentT.isEmpty() || !currentS.isEmpty())
            return erasure(t); // some "rare" type involved

        if (captured)
            return new ClassType(cls.getEnclosingType(), S, cls.tsym,
                                 cls.getAnnotationMirrors());
        else
            return t;
    }
    // where
        public List<Type> freshTypeVariables(List<Type> types) {
            ListBuffer<Type> result = new ListBuffer<>();
            for (Type t : types) {
                if (t.hasTag(WILDCARD)) {
                    Type bound = ((WildcardType)t).getExtendsBound();
                    if (bound == null)
                        bound = syms.objectType;
                    result.append(new CapturedType(capturedName,
                                                   syms.noSymbol,
                                                   bound,
                                                   syms.botType,
                                                   (WildcardType)t,
                                                   Type.noAnnotations));
                } else {
                    result.append(t);
                }
            }
            return result.toList();
        }
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="Internal utility methods">
    private boolean sideCast(Type from, Type to, Warner warn) {
        // We are casting from type $from$ to type $to$, which are
        // non-final unrelated types.  This method
        // tries to reject a cast by transferring type parameters
        // from $to$ to $from$ by common superinterfaces.
        boolean reverse = false;
        Type target = to;
        if ((to.tsym.flags() & INTERFACE) == 0) {
            Assert.check((from.tsym.flags() & INTERFACE) != 0);
            reverse = true;
            to = from;
            from = target;
        }
        List<Type> commonSupers = superClosure(to, erasure(from));
        boolean giveWarning = commonSupers.isEmpty();
        // The arguments to the supers could be unified here to
        // get a more accurate analysis
        while (commonSupers.nonEmpty()) {
            Type t1 = asSuper(from, commonSupers.head.tsym);
            Type t2 = commonSupers.head; // same as asSuper(to, commonSupers.head.tsym);
            if (disjointTypes(t1.getTypeArguments(), t2.getTypeArguments()))
                return false;
            giveWarning = giveWarning || (reverse ? giveWarning(t2, t1) : giveWarning(t1, t2));
            commonSupers = commonSupers.tail;
        }
        if (giveWarning && !isReifiable(reverse ? from : to))
            warn.warn(LintCategory.UNCHECKED);
        if (!allowCovariantReturns)
            // reject if there is a common method signature with
            // incompatible return types.
            chk.checkCompatibleAbstracts(warn.pos(), from, to);
        return true;
    }

    private boolean sideCastFinal(Type from, Type to, Warner warn) {
        // We are casting from type $from$ to type $to$, which are
        // unrelated types one of which is final and the other of
        // which is an interface.  This method
        // tries to reject a cast by transferring type parameters
        // from the final class to the interface.
        boolean reverse = false;
        Type target = to;
        if ((to.tsym.flags() & INTERFACE) == 0) {
            Assert.check((from.tsym.flags() & INTERFACE) != 0);
            reverse = true;
            to = from;
            from = target;
        }
        Assert.check((from.tsym.flags() & FINAL) != 0);
        Type t1 = asSuper(from, to.tsym);
        if (t1 == null) return false;
        Type t2 = to;
        if (disjointTypes(t1.getTypeArguments(), t2.getTypeArguments()))
            return false;
        if (!allowCovariantReturns)
            // reject if there is a common method signature with
            // incompatible return types.
            chk.checkCompatibleAbstracts(warn.pos(), from, to);
        if (!isReifiable(target) &&
            (reverse ? giveWarning(t2, t1) : giveWarning(t1, t2)))
            warn.warn(LintCategory.UNCHECKED);
        return true;
    }

    private boolean giveWarning(Type from, Type to) {
        List<Type> bounds = to.isCompound() ?
                ((IntersectionClassType)to).getComponents() : List.of(to);
        for (Type b : bounds) {
            Type subFrom = asSub(from, b.tsym);
            if (b.isParameterized() &&
                    (!(isUnbounded(b) ||
                    isSubtype(from, b) ||
                    ((subFrom != null) && containsType(b.allparams(), subFrom.allparams()))))) {
                return true;
            }
        }
        return false;
    }

    private List<Type> superClosure(Type t, Type s) {
        List<Type> cl = List.nil();
        for (List<Type> l = interfaces(t); l.nonEmpty(); l = l.tail) {
            if (isSubtype(s, erasure(l.head))) {
                cl = insert(cl, l.head);
            } else {
                cl = union(cl, superClosure(l.head, s));
            }
        }
        return cl;
    }

    private boolean containsTypeEquivalent(Type t, Type s) {
        return
            isSameType(t, s) || // shortcut
            containsType(t, s) && containsType(s, t);
    }

    // <editor-fold defaultstate="collapsed" desc="adapt">
    /**
     * Adapt a type by computing a substitution which maps a source
     * type to a target type.
     *
     * @param source    the source type
     * @param target    the target type
     * @param from      the type variables of the computed substitution
     * @param to        the types of the computed substitution.
     */
    public void adapt(Type source,
                       Type target,
                       ListBuffer<Type> from,
                       ListBuffer<Type> to) throws AdaptFailure {
        new Adapter(from, to).adapt(source, target);
    }

    class Adapter extends SimpleVisitor<Void, Type> {

        ListBuffer<Type> from;
        ListBuffer<Type> to;
        Map<Symbol,Type> mapping;

        Adapter(ListBuffer<Type> from, ListBuffer<Type> to) {
            this.from = from;
            this.to = to;
            mapping = new HashMap<>();
        }

        public void adapt(Type source, Type target) throws AdaptFailure {
            visit(source, target);
            List<Type> fromList = from.toList();
            List<Type> toList = to.toList();
            while (!fromList.isEmpty()) {
                Type val = mapping.get(fromList.head.tsym);
                if (toList.head != val)
                    toList.head = val;
                fromList = fromList.tail;
                toList = toList.tail;
            }
        }

        @Override
        public Void visitClassType(ClassType source, Type target) throws AdaptFailure {
            if (target.hasTag(CLASS))
                adaptRecursive(source.allparams(), target.allparams());
            return null;
        }

        @Override
        public Void visitArrayType(ArrayType source, Type target) throws AdaptFailure {
            if (target.hasTag(ARRAY))
                adaptRecursive(elemtype(source), elemtype(target));
            return null;
        }

        @Override
        public Void visitWildcardType(WildcardType source, Type target) throws AdaptFailure {
            if (source.isExtendsBound())
                adaptRecursive(wildUpperBound(source), wildUpperBound(target));
            else if (source.isSuperBound())
                adaptRecursive(wildLowerBound(source), wildLowerBound(target));
            return null;
        }

        @Override
        public Void visitTypeVar(TypeVar source, Type target) throws AdaptFailure {
            // Check to see if there is
            // already a mapping for $source$, in which case
            // the old mapping will be merged with the new
            Type val = mapping.get(source.tsym);
            if (val != null) {
                if (val.isSuperBound() && target.isSuperBound()) {
                    val = isSubtype(wildLowerBound(val), wildLowerBound(target))
                        ? target : val;
                } else if (val.isExtendsBound() && target.isExtendsBound()) {
                    val = isSubtype(wildUpperBound(val), wildUpperBound(target))
                        ? val : target;
                } else if (!isSameType(val, target)) {
                    throw new AdaptFailure();
                }
            } else {
                val = target;
                from.append(source);
                to.append(target);
            }
            mapping.put(source.tsym, val);
            return null;
        }

        @Override
        public Void visitType(Type source, Type target) {
            return null;
        }

        private Set<TypePair> cache = new HashSet<>();

        private void adaptRecursive(Type source, Type target) {
            TypePair pair = new TypePair(source, target);
            if (cache.add(pair)) {
                try {
                    visit(source, target);
                } finally {
                    cache.remove(pair);
                }
            }
        }

        private void adaptRecursive(List<Type> source, List<Type> target) {
            if (source.length() == target.length()) {
                while (source.nonEmpty()) {
                    adaptRecursive(source.head, target.head);
                    source = source.tail;
                    target = target.tail;
                }
            }
        }
    }

    public static class AdaptFailure extends RuntimeException {
        static final long serialVersionUID = -7490231548272701566L;
    }

    private void adaptSelf(Type t,
                           ListBuffer<Type> from,
                           ListBuffer<Type> to) {
        try {
            //if (t.tsym.type != t)
                adapt(t.tsym.type, t, from, to);
        } catch (AdaptFailure ex) {
            // Adapt should never fail calculating a mapping from
            // t.tsym.type to t as there can be no merge problem.
            throw new AssertionError(ex);
        }
    }
    // </editor-fold>

    /**
     * Rewrite all type variables (universal quantifiers) in the given
     * type to wildcards (existential quantifiers).  This is used to
     * determine if a cast is allowed.  For example, if high is true
     * and {@code T <: Number}, then {@code List<T>} is rewritten to
     * {@code List<?  extends Number>}.  Since {@code List<Integer> <:
     * List<? extends Number>} a {@code List<T>} can be cast to {@code
     * List<Integer>} with a warning.
     * @param t a type
     * @param high if true return an upper bound; otherwise a lower
     * bound
     * @param rewriteTypeVars only rewrite captured wildcards if false;
     * otherwise rewrite all type variables
     * @return the type rewritten with wildcards (existential
     * quantifiers) only
     */
    private Type rewriteQuantifiers(Type t, boolean high, boolean rewriteTypeVars) {
        return new Rewriter(high, rewriteTypeVars).visit(t);
    }

    class Rewriter extends UnaryVisitor<Type> {

        boolean high;
        boolean rewriteTypeVars;

        Rewriter(boolean high, boolean rewriteTypeVars) {
            this.high = high;
            this.rewriteTypeVars = rewriteTypeVars;
        }

        @Override
        public Type visitClassType(ClassType t, Void s) {
            ListBuffer<Type> rewritten = new ListBuffer<>();
            boolean changed = false;
            for (Type arg : t.allparams()) {
                Type bound = visit(arg);
                if (arg != bound) {
                    changed = true;
                }
                rewritten.append(bound);
            }
            if (changed)
                return subst(t.tsym.type,
                        t.tsym.type.allparams(),
                        rewritten.toList());
            else
                return t;
        }

        public Type visitType(Type t, Void s) {
            return t;
        }

        @Override
        public Type visitCapturedType(CapturedType t, Void s) {
            Type w_bound = t.wildcard.type;
            Type bound = w_bound.contains(t) ?
                        erasure(w_bound) :
                        visit(w_bound);
            return rewriteAsWildcardType(visit(bound), t.wildcard.bound, t.wildcard.kind);
        }

        @Override
        public Type visitTypeVar(TypeVar t, Void s) {
            if (rewriteTypeVars) {
                Type bound = t.bound.contains(t) ?
                        erasure(t.bound) :
                        visit(t.bound);
                return rewriteAsWildcardType(bound, t, EXTENDS);
            } else {
                return t;
            }
        }

        @Override
        public Type visitWildcardType(WildcardType t, Void s) {
            Type bound2 = visit(t.type);
            return t.type == bound2 ? t : rewriteAsWildcardType(bound2, t.bound, t.kind);
        }

        private Type rewriteAsWildcardType(Type bound, TypeVar formal, BoundKind bk) {
            switch (bk) {
               case EXTENDS: return high ?
                       makeExtendsWildcard(B(bound), formal) :
                       makeExtendsWildcard(syms.objectType, formal);
               case SUPER: return high ?
                       makeSuperWildcard(syms.botType, formal) :
                       makeSuperWildcard(B(bound), formal);
               case UNBOUND: return makeExtendsWildcard(syms.objectType, formal);
               default:
                   Assert.error("Invalid bound kind " + bk);
                   return null;
            }
        }

        Type B(Type t) {
            while (t.hasTag(WILDCARD)) {
                WildcardType w = (WildcardType)t;
                t = high ?
                    w.getExtendsBound() :
                    w.getSuperBound();
                if (t == null) {
                    t = high ? syms.objectType : syms.botType;
                }
            }
            return t;
        }
    }


    /**
     * Create a wildcard with the given upper (extends) bound; create
     * an unbounded wildcard if bound is Object.
     *
     * @param bound the upper bound
     * @param formal the formal type parameter that will be
     * substituted by the wildcard
     */
    private WildcardType makeExtendsWildcard(Type bound, TypeVar formal) {
        if (bound == syms.objectType) {
            return new WildcardType(syms.objectType,
                                    BoundKind.UNBOUND,
                                    syms.boundClass,
                                    formal,
                                    Type.noAnnotations);
        } else {
            return new WildcardType(bound,
                                    BoundKind.EXTENDS,
                                    syms.boundClass,
                                    formal,
                                    Type.noAnnotations);
        }
    }

    /**
     * Create a wildcard with the given lower (super) bound; create an
     * unbounded wildcard if bound is bottom (type of {@code null}).
     *
     * @param bound the lower bound
     * @param formal the formal type parameter that will be
     * substituted by the wildcard
     */
    private WildcardType makeSuperWildcard(Type bound, TypeVar formal) {
        if (bound.hasTag(BOT)) {
            return new WildcardType(syms.objectType,
                                    BoundKind.UNBOUND,
                                    syms.boundClass,
                                    formal,
                                    Type.noAnnotations);
        } else {
            return new WildcardType(bound,
                                    BoundKind.SUPER,
                                    syms.boundClass,
                                    formal,
                                    Type.noAnnotations);
        }
    }

    /**
     * A wrapper for a type that allows use in sets.
     */
    public static class UniqueType {
        public final Type type;
        final Types types;

        public UniqueType(Type type, Types types) {
            this.type = type;
            this.types = types;
        }

        public int hashCode() {
            return types.hashCode(type);
        }

        public boolean equals(Object obj) {
            return (obj instanceof UniqueType) &&
                types.isSameType(type, ((UniqueType)obj).type);
        }

        public String toString() {
            return type.toString();
        }

    }
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="Visitors">
    /**
     * A default visitor for types.  All visitor methods except
     * visitType are implemented by delegating to visitType.  Concrete
     * subclasses must provide an implementation of visitType and can
     * override other methods as needed.
     *
     * @param <R> the return type of the operation implemented by this
     * visitor; use Void if no return type is needed.
     * @param <S> the type of the second argument (the first being the
     * type itself) of the operation implemented by this visitor; use
     * Void if a second argument is not needed.
     */
    public static abstract class DefaultTypeVisitor<R,S> implements Type.Visitor<R,S> {
        final public R visit(Type t, S s)               { return t.accept(this, s); }
        public R visitClassType(ClassType t, S s)       { return visitType(t, s); }
        public R visitWildcardType(WildcardType t, S s) { return visitType(t, s); }
        public R visitArrayType(ArrayType t, S s)       { return visitType(t, s); }
        public R visitMethodType(MethodType t, S s)     { return visitType(t, s); }
        public R visitPackageType(PackageType t, S s)   { return visitType(t, s); }
        public R visitTypeVar(TypeVar t, S s)           { return visitType(t, s); }
        public R visitCapturedType(CapturedType t, S s) { return visitType(t, s); }
        public R visitForAll(ForAll t, S s)             { return visitType(t, s); }
        public R visitUndetVar(UndetVar t, S s)         { return visitType(t, s); }
        public R visitErrorType(ErrorType t, S s)       { return visitType(t, s); }
    }

    /**
     * A default visitor for symbols.  All visitor methods except
     * visitSymbol are implemented by delegating to visitSymbol.  Concrete
     * subclasses must provide an implementation of visitSymbol and can
     * override other methods as needed.
     *
     * @param <R> the return type of the operation implemented by this
     * visitor; use Void if no return type is needed.
     * @param <S> the type of the second argument (the first being the
     * symbol itself) of the operation implemented by this visitor; use
     * Void if a second argument is not needed.
     */
    public static abstract class DefaultSymbolVisitor<R,S> implements Symbol.Visitor<R,S> {
        final public R visit(Symbol s, S arg)                   { return s.accept(this, arg); }
        public R visitClassSymbol(ClassSymbol s, S arg)         { return visitSymbol(s, arg); }
        public R visitMethodSymbol(MethodSymbol s, S arg)       { return visitSymbol(s, arg); }
        public R visitOperatorSymbol(OperatorSymbol s, S arg)   { return visitSymbol(s, arg); }
        public R visitPackageSymbol(PackageSymbol s, S arg)     { return visitSymbol(s, arg); }
        public R visitTypeSymbol(TypeSymbol s, S arg)           { return visitSymbol(s, arg); }
        public R visitVarSymbol(VarSymbol s, S arg)             { return visitSymbol(s, arg); }
    }

    /**
     * A <em>simple</em> visitor for types.  This visitor is simple as
     * captured wildcards, for-all types (generic methods), and
     * undetermined type variables (part of inference) are hidden.
     * Captured wildcards are hidden by treating them as type
     * variables and the rest are hidden by visiting their qtypes.
     *
     * @param <R> the return type of the operation implemented by this
     * visitor; use Void if no return type is needed.
     * @param <S> the type of the second argument (the first being the
     * type itself) of the operation implemented by this visitor; use
     * Void if a second argument is not needed.
     */
    public static abstract class SimpleVisitor<R,S> extends DefaultTypeVisitor<R,S> {
        @Override
        public R visitCapturedType(CapturedType t, S s) {
            return visitTypeVar(t, s);
        }
        @Override
        public R visitForAll(ForAll t, S s) {
            return visit(t.qtype, s);
        }
        @Override
        public R visitUndetVar(UndetVar t, S s) {
            return visit(t.qtype, s);
        }
    }

    /**
     * A plain relation on types.  That is a 2-ary function on the
     * form Type&nbsp;&times;&nbsp;Type&nbsp;&rarr;&nbsp;Boolean.
     * <!-- In plain text: Type x Type -> Boolean -->
     */
    public static abstract class TypeRelation extends SimpleVisitor<Boolean,Type> {}

    /**
     * A convenience visitor for implementing operations that only
     * require one argument (the type itself), that is, unary
     * operations.
     *
     * @param <R> the return type of the operation implemented by this
     * visitor; use Void if no return type is needed.
     */
    public static abstract class UnaryVisitor<R> extends SimpleVisitor<R,Void> {
        final public R visit(Type t) { return t.accept(this, null); }
    }

    /**
     * A visitor for implementing a mapping from types to types.  The
     * default behavior of this class is to implement the identity
     * mapping (mapping a type to itself).  This can be overridden in
     * subclasses.
     *
     * @param <S> the type of the second argument (the first being the
     * type itself) of this mapping; use Void if a second argument is
     * not needed.
     */
    public static class MapVisitor<S> extends DefaultTypeVisitor<Type,S> {
        final public Type visit(Type t) { return t.accept(this, null); }
        public Type visitType(Type t, S s) { return t; }
    }
    // </editor-fold>


    // <editor-fold defaultstate="collapsed" desc="Annotation support">

    public RetentionPolicy getRetention(Attribute.Compound a) {
        return getRetention(a.type.tsym);
    }

    public RetentionPolicy getRetention(Symbol sym) {
        RetentionPolicy vis = RetentionPolicy.CLASS; // the default
        Attribute.Compound c = sym.attribute(syms.retentionType.tsym);
        if (c != null) {
            Attribute value = c.member(names.value);
            if (value != null && value instanceof Attribute.Enum) {
                Name levelName = ((Attribute.Enum)value).value.name;
                if (levelName == names.SOURCE) vis = RetentionPolicy.SOURCE;
                else if (levelName == names.CLASS) vis = RetentionPolicy.CLASS;
                else if (levelName == names.RUNTIME) vis = RetentionPolicy.RUNTIME;
                else ;// /* fail soft */ throw new AssertionError(levelName);
            }
        }
        return vis;
    }
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="Signature Generation">

    public static abstract class SignatureGenerator {

        private final Types types;

        protected abstract void append(char ch);
        protected abstract void append(byte[] ba);
        protected abstract void append(Name name);
        protected void classReference(ClassSymbol c) { /* by default: no-op */ }

        protected SignatureGenerator(Types types) {
            this.types = types;
        }

        /**
         * Assemble signature of given type in string buffer.
         */
        public void assembleSig(Type type) {
            switch (type.getTag()) {
                case BYTE:
                    append('B');
                    break;
                case SHORT:
                    append('S');
                    break;
                case CHAR:
                    append('C');
                    break;
                case INT:
                    append('I');
                    break;
                case LONG:
                    append('J');
                    break;
                case FLOAT:
                    append('F');
                    break;
                case DOUBLE:
                    append('D');
                    break;
                case BOOLEAN:
                    append('Z');
                    break;
                case VOID:
                    append('V');
                    break;
                case CLASS:
                    append('L');
                    assembleClassSig(type);
                    append(';');
                    break;
                case ARRAY:
                    ArrayType at = (ArrayType) type;
                    append('[');
                    assembleSig(at.elemtype);
                    break;
                case METHOD:
                    MethodType mt = (MethodType) type;
                    append('(');
                    assembleSig(mt.argtypes);
                    append(')');
                    assembleSig(mt.restype);
                    if (hasTypeVar(mt.thrown)) {
                        for (List<Type> l = mt.thrown; l.nonEmpty(); l = l.tail) {
                            append('^');
                            assembleSig(l.head);
                        }
                    }
                    break;
                case WILDCARD: {
                    Type.WildcardType ta = (Type.WildcardType) type;
                    switch (ta.kind) {
                        case SUPER:
                            append('-');
                            assembleSig(ta.type);
                            break;
                        case EXTENDS:
                            append('+');
                            assembleSig(ta.type);
                            break;
                        case UNBOUND:
                            append('*');
                            break;
                        default:
                            throw new AssertionError(ta.kind);
                    }
                    break;
                }
                case TYPEVAR:
                    append('T');
                    append(type.tsym.name);
                    append(';');
                    break;
                case FORALL:
                    Type.ForAll ft = (Type.ForAll) type;
                    assembleParamsSig(ft.tvars);
                    assembleSig(ft.qtype);
                    break;
                default:
                    throw new AssertionError("typeSig " + type.getTag());
            }
        }

        public boolean hasTypeVar(List<Type> l) {
            while (l.nonEmpty()) {
                if (l.head.hasTag(TypeTag.TYPEVAR)) {
                    return true;
                }
                l = l.tail;
            }
            return false;
        }

        public void assembleClassSig(Type type) {
            ClassType ct = (ClassType) type;
            ClassSymbol c = (ClassSymbol) ct.tsym;
            classReference(c);
            Type outer = ct.getEnclosingType();
            if (outer.allparams().nonEmpty()) {
                boolean rawOuter =
                        c.owner.kind == Kinds.MTH || // either a local class
                        c.name == types.names.empty; // or anonymous
                assembleClassSig(rawOuter
                        ? types.erasure(outer)
                        : outer);
                append(rawOuter ? '$' : '.');
                Assert.check(c.flatname.startsWith(c.owner.enclClass().flatname));
                append(rawOuter
                        ? c.flatname.subName(c.owner.enclClass().flatname.getByteLength() + 1, c.flatname.getByteLength())
                        : c.name);
            } else {
                append(externalize(c.flatname));
            }
            if (ct.getTypeArguments().nonEmpty()) {
                append('<');
                assembleSig(ct.getTypeArguments());
                append('>');
            }
        }

        public void assembleParamsSig(List<Type> typarams) {
            append('<');
            for (List<Type> ts = typarams; ts.nonEmpty(); ts = ts.tail) {
                Type.TypeVar tvar = (Type.TypeVar) ts.head;
                append(tvar.tsym.name);
                List<Type> bounds = types.getBounds(tvar);
                if ((bounds.head.tsym.flags() & INTERFACE) != 0) {
                    append(':');
                }
                for (List<Type> l = bounds; l.nonEmpty(); l = l.tail) {
                    append(':');
                    assembleSig(l.head);
                }
            }
            append('>');
        }

        private void assembleSig(List<Type> types) {
            for (List<Type> ts = types; ts.nonEmpty(); ts = ts.tail) {
                assembleSig(ts.head);
            }
        }
    }
    // </editor-fold>

    public void newRound() {
        descCache._map.clear();
        isDerivedRawCache.clear();
        implCache._map.clear();
        membersCache._map.clear();
        closureCache.clear();
    }
}
