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