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