1 /*
   2  * Copyright (c) 1999, 2026, 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.comp;
  27 
  28 import com.sun.tools.javac.api.Formattable.LocalizedString;
  29 import com.sun.tools.javac.code.*;
  30 import com.sun.tools.javac.code.Scope.WriteableScope;
  31 import com.sun.tools.javac.code.Source.Feature;
  32 import com.sun.tools.javac.code.Symbol.*;
  33 import com.sun.tools.javac.code.Type.*;
  34 import com.sun.tools.javac.comp.Attr.ResultInfo;
  35 import com.sun.tools.javac.comp.Check.CheckContext;
  36 import com.sun.tools.javac.comp.DeferredAttr.AttrMode;
  37 import com.sun.tools.javac.comp.DeferredAttr.DeferredAttrContext;
  38 import com.sun.tools.javac.comp.DeferredAttr.DeferredType;
  39 import com.sun.tools.javac.comp.Resolve.MethodResolutionContext.Candidate;
  40 import com.sun.tools.javac.comp.Resolve.MethodResolutionDiagHelper.Template;
  41 import com.sun.tools.javac.comp.Resolve.ReferenceLookupResult.StaticKind;
  42 import com.sun.tools.javac.jvm.*;
  43 import com.sun.tools.javac.main.Option;
  44 import com.sun.tools.javac.resources.CompilerProperties.Errors;
  45 import com.sun.tools.javac.resources.CompilerProperties.Fragments;
  46 import com.sun.tools.javac.resources.CompilerProperties.Warnings;
  47 import com.sun.tools.javac.tree.*;
  48 import com.sun.tools.javac.tree.JCTree.*;
  49 import com.sun.tools.javac.tree.JCTree.JCMemberReference.ReferenceKind;
  50 import com.sun.tools.javac.tree.JCTree.JCPolyExpression.*;
  51 import com.sun.tools.javac.util.*;
  52 import com.sun.tools.javac.util.DefinedBy.Api;
  53 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
  54 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
  55 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticType;
  56 
  57 import java.util.Arrays;
  58 import java.util.Collection;
  59 import java.util.EnumSet;
  60 import java.util.HashSet;
  61 import java.util.Iterator;
  62 import java.util.LinkedHashMap;
  63 import java.util.Map;
  64 import java.util.Set;
  65 import java.util.function.BiFunction;
  66 import java.util.function.BiPredicate;
  67 import java.util.function.Function;
  68 import java.util.function.Predicate;
  69 import java.util.function.UnaryOperator;
  70 import java.util.stream.Stream;
  71 import java.util.stream.StreamSupport;
  72 
  73 import javax.lang.model.element.ElementVisitor;
  74 
  75 import static com.sun.tools.javac.code.Flags.*;
  76 import static com.sun.tools.javac.code.Flags.BLOCK;
  77 import static com.sun.tools.javac.code.Flags.STATIC;
  78 import static com.sun.tools.javac.code.Kinds.*;
  79 import static com.sun.tools.javac.code.Kinds.Kind.*;
  80 import static com.sun.tools.javac.code.TypeTag.*;
  81 import static com.sun.tools.javac.comp.Resolve.MethodResolutionPhase.*;
  82 import static com.sun.tools.javac.main.Option.DOE;
  83 import static com.sun.tools.javac.tree.JCTree.Tag.*;
  84 import static com.sun.tools.javac.util.Iterators.createCompoundIterator;
  85 
  86 /** Helper class for name resolution, used mostly by the attribution phase.
  87  *
  88  *  <p><b>This is NOT part of any supported API.
  89  *  If you write code that depends on this, you do so at your own risk.
  90  *  This code and its internal interfaces are subject to change or
  91  *  deletion without notice.</b>
  92  */
  93 public class Resolve {
  94     protected static final Context.Key<Resolve> resolveKey = new Context.Key<>();
  95 
  96     Names names;
  97     Log log;
  98     Symtab syms;
  99     Attr attr;
 100     AttrRecover attrRecover;
 101     DeferredAttr deferredAttr;
 102     Check chk;
 103     Infer infer;
 104     Preview preview;
 105     ClassFinder finder;
 106     ModuleFinder moduleFinder;
 107     Types types;
 108     JCDiagnostic.Factory diags;
 109     public final boolean allowModules;
 110     public final boolean allowRecords;
 111     private final boolean compactMethodDiags;
 112     private final boolean allowLocalVariableTypeInference;
 113     private final boolean allowYieldStatement;
 114     private final boolean allowPrivateMembersInPermitsClause;
 115     final EnumSet<VerboseResolutionMode> verboseResolutionMode;
 116     final boolean dumpMethodReferenceSearchResults;
 117     final boolean dumpStacktraceOnError;
 118 
 119     WriteableScope polymorphicSignatureScope;
 120 
 121     @SuppressWarnings("this-escape")
 122     protected Resolve(Context context) {
 123         context.put(resolveKey, this);
 124         syms = Symtab.instance(context);
 125 
 126         varNotFound = new SymbolNotFoundError(ABSENT_VAR);
 127         methodNotFound = new SymbolNotFoundError(ABSENT_MTH);
 128         typeNotFound = new SymbolNotFoundError(ABSENT_TYP);
 129         referenceNotFound = ReferenceLookupResult.error(methodNotFound);
 130 
 131         names = Names.instance(context);
 132         log = Log.instance(context);
 133         attr = Attr.instance(context);
 134         attrRecover = AttrRecover.instance(context);
 135         deferredAttr = DeferredAttr.instance(context);
 136         chk = Check.instance(context);
 137         infer = Infer.instance(context);
 138         finder = ClassFinder.instance(context);
 139         moduleFinder = ModuleFinder.instance(context);
 140         types = Types.instance(context);
 141         diags = JCDiagnostic.Factory.instance(context);
 142         preview = Preview.instance(context);
 143         Source source = Source.instance(context);
 144         Options options = Options.instance(context);
 145         compactMethodDiags = options.isSet(Option.XDIAGS, "compact") ||
 146                 options.isUnset(Option.XDIAGS) && options.isUnset("rawDiagnostics");
 147         verboseResolutionMode = VerboseResolutionMode.getVerboseResolutionMode(options);
 148         Target target = Target.instance(context);
 149         allowLocalVariableTypeInference = Feature.LOCAL_VARIABLE_TYPE_INFERENCE.allowedInSource(source);
 150         allowYieldStatement = Feature.SWITCH_EXPRESSION.allowedInSource(source);
 151         allowPrivateMembersInPermitsClause = Feature.PRIVATE_MEMBERS_IN_PERMITS_CLAUSE.allowedInSource(source);
 152         polymorphicSignatureScope = WriteableScope.create(syms.noSymbol);
 153         allowModules = Feature.MODULES.allowedInSource(source);
 154         allowRecords = Feature.RECORDS.allowedInSource(source);
 155         dumpMethodReferenceSearchResults = options.isSet("debug.dumpMethodReferenceSearchResults");
 156         dumpStacktraceOnError = options.isSet("dev") || options.isSet(DOE);
 157     }
 158 
 159     /** error symbols, which are returned when resolution fails
 160      */
 161     private final SymbolNotFoundError varNotFound;
 162     private final SymbolNotFoundError methodNotFound;
 163     private final SymbolNotFoundError typeNotFound;
 164 
 165     /** empty reference lookup result */
 166     private final ReferenceLookupResult referenceNotFound;
 167 
 168     public static Resolve instance(Context context) {
 169         Resolve instance = context.get(resolveKey);
 170         if (instance == null)
 171             instance = new Resolve(context);
 172         return instance;
 173     }
 174 
 175     private static Symbol bestOf(Symbol s1,
 176                                  Symbol s2) {
 177         return s1.kind.betterThan(s2.kind) ? s1 : s2;
 178     }
 179 
 180     // <editor-fold defaultstate="collapsed" desc="Verbose resolution diagnostics support">
 181     enum VerboseResolutionMode {
 182         SUCCESS("success"),
 183         FAILURE("failure"),
 184         APPLICABLE("applicable"),
 185         INAPPLICABLE("inapplicable"),
 186         DEFERRED_INST("deferred-inference"),
 187         PREDEF("predef"),
 188         OBJECT_INIT("object-init"),
 189         INTERNAL("internal");
 190 
 191         final String opt;
 192 
 193         private VerboseResolutionMode(String opt) {
 194             this.opt = opt;
 195         }
 196 
 197         static EnumSet<VerboseResolutionMode> getVerboseResolutionMode(Options opts) {
 198             String s = opts.get("debug.verboseResolution");
 199             EnumSet<VerboseResolutionMode> res = EnumSet.noneOf(VerboseResolutionMode.class);
 200             if (s == null) return res;
 201             if (s.contains("all")) {
 202                 res = EnumSet.allOf(VerboseResolutionMode.class);
 203             }
 204             Collection<String> args = Arrays.asList(s.split(","));
 205             for (VerboseResolutionMode mode : values()) {
 206                 if (args.contains(mode.opt)) {
 207                     res.add(mode);
 208                 } else if (args.contains("-" + mode.opt)) {
 209                     res.remove(mode);
 210                 }
 211             }
 212             return res;
 213         }
 214     }
 215 
 216     void reportVerboseResolutionDiagnostic(DiagnosticPosition dpos, Name name, Type site,
 217             List<Type> argtypes, List<Type> typeargtypes, Symbol bestSoFar) {
 218         boolean success = !bestSoFar.kind.isResolutionError();
 219 
 220         if (success && !verboseResolutionMode.contains(VerboseResolutionMode.SUCCESS)) {
 221             return;
 222         } else if (!success && !verboseResolutionMode.contains(VerboseResolutionMode.FAILURE)) {
 223             return;
 224         }
 225 
 226         if (bestSoFar.name == names.init &&
 227                 bestSoFar.owner == syms.objectType.tsym &&
 228                 !verboseResolutionMode.contains(VerboseResolutionMode.OBJECT_INIT)) {
 229             return; //skip diags for Object constructor resolution
 230         } else if (site == syms.predefClass.type &&
 231                 !verboseResolutionMode.contains(VerboseResolutionMode.PREDEF)) {
 232             return; //skip spurious diags for predef symbols (i.e. operators)
 233         } else if (currentResolutionContext.internalResolution &&
 234                 !verboseResolutionMode.contains(VerboseResolutionMode.INTERNAL)) {
 235             return;
 236         }
 237 
 238         int pos = 0;
 239         int mostSpecificPos = -1;
 240         ListBuffer<JCDiagnostic> subDiags = new ListBuffer<>();
 241         for (Candidate c : currentResolutionContext.candidates) {
 242             if (currentResolutionContext.step != c.step ||
 243                     (c.isApplicable() && !verboseResolutionMode.contains(VerboseResolutionMode.APPLICABLE)) ||
 244                     (!c.isApplicable() && !verboseResolutionMode.contains(VerboseResolutionMode.INAPPLICABLE))) {
 245                 continue;
 246             } else {
 247                 subDiags.append(c.isApplicable() ?
 248                         getVerboseApplicableCandidateDiag(pos, c.sym, c.mtype) :
 249                         getVerboseInapplicableCandidateDiag(pos, c.sym, c.details));
 250                 if (c.sym == bestSoFar)
 251                     mostSpecificPos = pos;
 252                 pos++;
 253             }
 254         }
 255         String key = success ? "verbose.resolve.multi" : "verbose.resolve.multi.1";
 256         List<Type> argtypes2 = argtypes.map(deferredAttr.new RecoveryDeferredTypeMap(AttrMode.SPECULATIVE, bestSoFar, currentResolutionContext.step));
 257         JCDiagnostic main = diags.note(log.currentSource(), dpos, key, name,
 258                 site.tsym, mostSpecificPos, currentResolutionContext.step,
 259                 methodArguments(argtypes2),
 260                 methodArguments(typeargtypes));
 261         JCDiagnostic d = new JCDiagnostic.MultilineDiagnostic(main, subDiags.toList());
 262         log.report(d);
 263     }
 264 
 265     JCDiagnostic getVerboseApplicableCandidateDiag(int pos, Symbol sym, Type inst) {
 266         JCDiagnostic subDiag = null;
 267         if (sym.type.hasTag(FORALL)) {
 268             subDiag = diags.fragment(Fragments.PartialInstSig(inst));
 269         }
 270 
 271         String key = subDiag == null ?
 272                 "applicable.method.found" :
 273                 "applicable.method.found.1";
 274 
 275         return diags.fragment(key, pos, sym, subDiag);
 276     }
 277 
 278     JCDiagnostic getVerboseInapplicableCandidateDiag(int pos, Symbol sym, JCDiagnostic subDiag) {
 279         return diags.fragment(Fragments.NotApplicableMethodFound(pos, sym, subDiag));
 280     }
 281     // </editor-fold>
 282 
 283 /* ************************************************************************
 284  * Identifier resolution
 285  *************************************************************************/
 286 
 287     /** An environment is "static" if its static level is greater than
 288      *  the one of its outer environment
 289      */
 290     protected static boolean isStatic(Env<AttrContext> env) {
 291         return env.outer != null && env.info.staticLevel > env.outer.info.staticLevel;
 292     }
 293 
 294     /** An environment is an "initializer" if it is a constructor or
 295      *  an instance initializer.
 296      */
 297     static boolean isInitializer(Env<AttrContext> env) {
 298         Symbol owner = env.info.scope.owner;
 299         return owner.isConstructor() ||
 300             owner.owner.kind == TYP &&
 301             (owner.kind == VAR ||
 302              owner.kind == MTH && (owner.flags() & BLOCK) != 0) &&
 303             (owner.flags() & STATIC) == 0;
 304     }
 305 
 306     /** Is class accessible in given environment?
 307      *  @param env    The current environment.
 308      *  @param c      The class whose accessibility is checked.
 309      */
 310     public boolean isAccessible(Env<AttrContext> env, TypeSymbol c) {
 311         return isAccessible(env, c, false);
 312     }
 313 
 314     public boolean isAccessible(Env<AttrContext> env, TypeSymbol c, boolean checkInner) {
 315 
 316         /* 15.9.5.1: Note that it is possible for the signature of the anonymous constructor
 317            to refer to an inaccessible type
 318         */
 319         if (env.enclMethod != null && (env.enclMethod.mods.flags & ANONCONSTR) != 0)
 320             return true;
 321 
 322         if (env.info.visitingServiceImplementation &&
 323             env.toplevel.modle == c.packge().modle) {
 324             return true;
 325         }
 326 
 327         boolean isAccessible = false;
 328         switch ((short)(c.flags() & AccessFlags)) {
 329             case PRIVATE:
 330                 isAccessible =
 331                     env.enclClass.sym.outermostClass() ==
 332                     c.owner.outermostClass();
 333                 break;
 334             case 0:
 335                 isAccessible =
 336                     env.toplevel.packge == c.owner // fast special case
 337                     ||
 338                     env.toplevel.packge == c.packge();
 339                 break;
 340             default: // error recovery
 341                 isAccessible = true;
 342                 break;
 343             case PUBLIC:
 344                 if (allowModules) {
 345                     ModuleSymbol currModule = env.toplevel.modle;
 346                     currModule.complete();
 347                     PackageSymbol p = c.packge();
 348                     isAccessible =
 349                         currModule == p.modle ||
 350                         currModule.visiblePackages.get(p.fullname) == p ||
 351                         p == syms.rootPackage ||
 352                         (p.modle == syms.unnamedModule && currModule.readModules.contains(p.modle));
 353                 } else {
 354                     isAccessible = true;
 355                 }
 356                 break;
 357             case PROTECTED:
 358                 isAccessible =
 359                     env.toplevel.packge == c.owner // fast special case
 360                     ||
 361                     env.toplevel.packge == c.packge()
 362                     ||
 363                     isInnerSubClass(env.enclClass.sym, c.owner)
 364                     ||
 365                     env.info.allowProtectedAccess;
 366                 break;
 367         }
 368         return (checkInner == false || c.type.getEnclosingType() == Type.noType) ?
 369             isAccessible :
 370             isAccessible && isAccessible(env, c.type.getEnclosingType(), checkInner);
 371     }
 372     //where
 373         /** Is given class a subclass of given base class, or an inner class
 374          *  of a subclass?
 375          *  Return null if no such class exists.
 376          *  @param c     The class which is the subclass or is contained in it.
 377          *  @param base  The base class
 378          */
 379         private boolean isInnerSubClass(ClassSymbol c, Symbol base) {
 380             while (c != null && !c.isSubClass(base, types)) {
 381                 c = c.owner.enclClass();
 382             }
 383             return c != null;
 384         }
 385 
 386     boolean isAccessible(Env<AttrContext> env, Type t) {
 387         return isAccessible(env, t, false);
 388     }
 389 
 390     boolean isAccessible(Env<AttrContext> env, Type t, boolean checkInner) {
 391         if (t.hasTag(ARRAY)) {
 392             return isAccessible(env, types.cvarUpperBound(types.elemtype(t)));
 393         } else if (t.isUnion()) {
 394             return StreamSupport.stream(((UnionClassType) t).getAlternativeTypes().spliterator(), false)
 395                     .allMatch(alternative -> isAccessible(env, alternative.tsym, checkInner));
 396         } else {
 397             return isAccessible(env, t.tsym, checkInner);
 398         }
 399     }
 400 
 401     /** Is symbol accessible as a member of given type in given environment?
 402      *  @param env    The current environment.
 403      *  @param site   The type of which the tested symbol is regarded
 404      *                as a member.
 405      *  @param sym    The symbol.
 406      */
 407     public boolean isAccessible(Env<AttrContext> env, Type site, Symbol sym) {
 408         return isAccessible(env, site, sym, false);
 409     }
 410     public boolean isAccessible(Env<AttrContext> env, Type site, Symbol sym, boolean checkInner) {
 411         if (sym.name == names.init && sym.owner != site.tsym) return false;
 412 
 413         /* 15.9.5.1: Note that it is possible for the signature of the anonymous constructor
 414            to refer to an inaccessible type
 415         */
 416         if (env.enclMethod != null && (env.enclMethod.mods.flags & ANONCONSTR) != 0)
 417             return true;
 418 
 419         if (env.info.visitingServiceImplementation &&
 420             env.toplevel.modle == sym.packge().modle) {
 421             return true;
 422         }
 423 
 424         switch ((short)(sym.flags() & AccessFlags)) {
 425         case PRIVATE:
 426             return
 427                 (env.enclClass.sym == sym.owner // fast special case
 428                  ||
 429                  env.enclClass.sym.outermostClass() ==
 430                  sym.owner.outermostClass()
 431                  ||
 432                  privateMemberInPermitsClauseIfAllowed(env, sym))
 433                 &&
 434                 sym.isInheritedIn(site.tsym, types);
 435         case 0:
 436             return
 437                 (env.toplevel.packge == sym.owner.owner // fast special case
 438                  ||
 439                  env.toplevel.packge == sym.packge())
 440                 &&
 441                 isAccessible(env, site, checkInner)
 442                 &&
 443                 sym.isInheritedIn(site.tsym, types)
 444                 &&
 445                 notOverriddenIn(site, sym);
 446         case PROTECTED:
 447             return
 448                 (env.toplevel.packge == sym.owner.owner // fast special case
 449                  ||
 450                  env.toplevel.packge == sym.packge()
 451                  ||
 452                  isProtectedAccessible(sym, env.enclClass.sym, site)
 453                  ||
 454                  // OK to select instance method or field from 'super' or type name
 455                  // (but type names should be disallowed elsewhere!)
 456                  env.info.selectSuper && (sym.flags() & STATIC) == 0 && sym.kind != TYP)
 457                 &&
 458                 isAccessible(env, site, checkInner)
 459                 &&
 460                 notOverriddenIn(site, sym);
 461         default: // this case includes erroneous combinations as well
 462             return isAccessible(env, site, checkInner) && notOverriddenIn(site, sym);
 463         }
 464     }
 465 
 466     private boolean privateMemberInPermitsClauseIfAllowed(Env<AttrContext> env, Symbol sym) {
 467         return allowPrivateMembersInPermitsClause &&
 468             env.info.isPermitsClause &&
 469             ((JCClassDecl) env.tree).sym.outermostClass() == sym.owner.outermostClass();
 470     }
 471 
 472     //where
 473     /* `sym' is accessible only if not overridden by
 474      * another symbol which is a member of `site'
 475      * (because, if it is overridden, `sym' is not strictly
 476      * speaking a member of `site'). A polymorphic signature method
 477      * cannot be overridden (e.g. MH.invokeExact(Object[])).
 478      */
 479     private boolean notOverriddenIn(Type site, Symbol sym) {
 480         if (sym.kind != MTH || sym.isConstructor() || sym.isStatic())
 481             return true;
 482         else {
 483             Symbol s2 = ((MethodSymbol)sym).implementation(site.tsym, types, true);
 484             return (s2 == null || s2 == sym || sym.owner == s2.owner || (sym.owner.isInterface() && s2.owner == syms.objectType.tsym) ||
 485                     !types.isSubSignature(types.memberType(site, s2), types.memberType(site, sym)));
 486         }
 487     }
 488     //where
 489         /** Is given protected symbol accessible if it is selected from given site
 490          *  and the selection takes place in given class?
 491          *  @param sym     The symbol with protected access
 492          *  @param c       The class where the access takes place
 493          *  @param site    The type of the qualifier
 494          */
 495         private
 496         boolean isProtectedAccessible(Symbol sym, ClassSymbol c, Type site) {
 497             Type newSite = site.hasTag(TYPEVAR) ? site.getUpperBound() : site;
 498             while (c != null &&
 499                    !(c.isSubClass(sym.owner, types) &&
 500                      (c.flags() & INTERFACE) == 0 &&
 501                      // In JLS 2e 6.6.2.1, the subclass restriction applies
 502                      // only to instance fields and methods -- types are excluded
 503                      // regardless of whether they are declared 'static' or not.
 504                      ((sym.flags() & STATIC) != 0 || sym.kind == TYP || newSite.tsym.isSubClass(c, types))))
 505                 c = c.owner.enclClass();
 506             return c != null;
 507         }
 508 
 509     /**
 510      * Performs a recursive scan of a type looking for accessibility problems
 511      * from current attribution environment
 512      */
 513     void checkAccessibleType(Env<AttrContext> env, Type t) {
 514         accessibilityChecker.visit(t, env);
 515     }
 516 
 517     /**
 518      * Accessibility type-visitor
 519      */
 520     Types.SimpleVisitor<Void, Env<AttrContext>> accessibilityChecker =
 521             new Types.SimpleVisitor<Void, Env<AttrContext>>() {
 522 
 523         void visit(List<Type> ts, Env<AttrContext> env) {
 524             for (Type t : ts) {
 525                 visit(t, env);
 526             }
 527         }
 528 
 529         public Void visitType(Type t, Env<AttrContext> env) {
 530             return null;
 531         }
 532 
 533         @Override
 534         public Void visitArrayType(ArrayType t, Env<AttrContext> env) {
 535             visit(t.elemtype, env);
 536             return null;
 537         }
 538 
 539         @Override
 540         public Void visitClassType(ClassType t, Env<AttrContext> env) {
 541             visit(t.getTypeArguments(), env);
 542             if (!isAccessible(env, t, true)) {
 543                 accessBase(new AccessError(env, null, t.tsym), env.tree.pos(), env.enclClass.sym, t, t.tsym.name, true);
 544             }
 545             return null;
 546         }
 547 
 548         @Override
 549         public Void visitWildcardType(WildcardType t, Env<AttrContext> env) {
 550             visit(t.type, env);
 551             return null;
 552         }
 553 
 554         @Override
 555         public Void visitMethodType(MethodType t, Env<AttrContext> env) {
 556             visit(t.getParameterTypes(), env);
 557             visit(t.getReturnType(), env);
 558             visit(t.getThrownTypes(), env);
 559             return null;
 560         }
 561     };
 562 
 563     /** Try to instantiate the type of a method so that it fits
 564      *  given type arguments and argument types. If successful, return
 565      *  the method's instantiated type, else return null.
 566      *  The instantiation will take into account an additional leading
 567      *  formal parameter if the method is an instance method seen as a member
 568      *  of an under determined site. In this case, we treat site as an additional
 569      *  parameter and the parameters of the class containing the method as
 570      *  additional type variables that get instantiated.
 571      *
 572      *  @param env         The current environment
 573      *  @param site        The type of which the method is a member.
 574      *  @param m           The method symbol.
 575      *  @param argtypes    The invocation's given value arguments.
 576      *  @param typeargtypes    The invocation's given type arguments.
 577      *  @param allowBoxing Allow boxing conversions of arguments.
 578      *  @param useVarargs Box trailing arguments into an array for varargs.
 579      */
 580     Type rawInstantiate(Env<AttrContext> env,
 581                         Type site,
 582                         Symbol m,
 583                         ResultInfo resultInfo,
 584                         List<Type> argtypes,
 585                         List<Type> typeargtypes,
 586                         boolean allowBoxing,
 587                         boolean useVarargs,
 588                         Warner warn) throws Infer.InferenceException {
 589         Type mt = types.memberType(site, m);
 590         // tvars is the list of formal type variables for which type arguments
 591         // need to inferred.
 592         List<Type> tvars = List.nil();
 593         if (typeargtypes == null) typeargtypes = List.nil();
 594         if (!mt.hasTag(FORALL) && typeargtypes.nonEmpty()) {
 595             // This is not a polymorphic method, but typeargs are supplied
 596             // which is fine, see JLS 15.12.2.1
 597         } else if (mt.hasTag(FORALL) && typeargtypes.nonEmpty()) {
 598             ForAll pmt = (ForAll) mt;
 599             if (typeargtypes.length() != pmt.tvars.length())
 600                  // not enough args
 601                 throw new InapplicableMethodException(diags.fragment(Fragments.WrongNumberTypeArgs(Integer.toString(pmt.tvars.length()))), dumpStacktraceOnError);
 602             // Check type arguments are within bounds
 603             List<Type> formals = pmt.tvars;
 604             List<Type> actuals = typeargtypes;
 605             while (formals.nonEmpty() && actuals.nonEmpty()) {
 606                 List<Type> bounds = types.subst(types.getBounds((TypeVar)formals.head),
 607                                                 pmt.tvars, typeargtypes);
 608                 for (; bounds.nonEmpty(); bounds = bounds.tail) {
 609                     if (!types.isSubtypeUnchecked(actuals.head, bounds.head, warn)) {
 610                         throw new InapplicableMethodException(diags.fragment(Fragments.ExplicitParamDoNotConformToBounds(actuals.head, bounds)), dumpStacktraceOnError);
 611                     }
 612                 }
 613                 formals = formals.tail;
 614                 actuals = actuals.tail;
 615             }
 616             mt = types.subst(pmt.qtype, pmt.tvars, typeargtypes);
 617         } else if (mt.hasTag(FORALL)) {
 618             ForAll pmt = (ForAll) mt;
 619             List<Type> tvars1 = types.newInstances(pmt.tvars);
 620             tvars = tvars.appendList(tvars1);
 621             mt = types.subst(pmt.qtype, pmt.tvars, tvars1);
 622         }
 623 
 624         // find out whether we need to go the slow route via infer
 625         boolean instNeeded = tvars.tail != null; /*inlined: tvars.nonEmpty()*/
 626         for (List<Type> l = argtypes;
 627              l.tail != null/*inlined: l.nonEmpty()*/ && !instNeeded;
 628              l = l.tail) {
 629             if (l.head.hasTag(FORALL)) instNeeded = true;
 630         }
 631 
 632         if (instNeeded) {
 633             return infer.instantiateMethod(env,
 634                                     tvars,
 635                                     (MethodType)mt,
 636                                     resultInfo,
 637                                     (MethodSymbol)m,
 638                                     argtypes,
 639                                     allowBoxing,
 640                                     useVarargs,
 641                                     currentResolutionContext,
 642                                     warn);
 643         }
 644 
 645         DeferredAttr.DeferredAttrContext dc = currentResolutionContext.deferredAttrContext(m, infer.emptyContext, resultInfo, warn);
 646         currentResolutionContext.methodCheck.argumentsAcceptable(env, dc,
 647                                 argtypes, mt.getParameterTypes(), warn);
 648         dc.complete();
 649         return mt;
 650     }
 651 
 652     Type checkMethod(Env<AttrContext> env,
 653                      Type site,
 654                      Symbol m,
 655                      ResultInfo resultInfo,
 656                      List<Type> argtypes,
 657                      List<Type> typeargtypes,
 658                      Warner warn) {
 659         MethodResolutionContext prevContext = currentResolutionContext;
 660         try {
 661             currentResolutionContext = new MethodResolutionContext();
 662             currentResolutionContext.attrMode = (resultInfo.pt == Infer.anyPoly) ?
 663                     AttrMode.SPECULATIVE : DeferredAttr.AttrMode.CHECK;
 664             if (env.tree.hasTag(JCTree.Tag.REFERENCE)) {
 665                 //method/constructor references need special check class
 666                 //to handle inference variables in 'argtypes' (might happen
 667                 //during an unsticking round)
 668                 currentResolutionContext.methodCheck =
 669                         new MethodReferenceCheck(resultInfo.checkContext.inferenceContext());
 670             }
 671             MethodResolutionPhase step = currentResolutionContext.step = env.info.pendingResolutionPhase;
 672             return rawInstantiate(env, site, m, resultInfo, argtypes, typeargtypes,
 673                     step.isBoxingRequired(), step.isVarargsRequired(), warn);
 674         }
 675         finally {
 676             currentResolutionContext = prevContext;
 677         }
 678     }
 679 
 680     /** Same but returns null instead throwing a NoInstanceException
 681      */
 682     Type instantiate(Env<AttrContext> env,
 683                      Type site,
 684                      Symbol m,
 685                      ResultInfo resultInfo,
 686                      List<Type> argtypes,
 687                      List<Type> typeargtypes,
 688                      boolean allowBoxing,
 689                      boolean useVarargs,
 690                      Warner warn) {
 691         try {
 692             return rawInstantiate(env, site, m, resultInfo, argtypes, typeargtypes,
 693                                   allowBoxing, useVarargs, warn);
 694         } catch (InapplicableMethodException ex) {
 695             return null;
 696         }
 697     }
 698 
 699     /**
 700      * This interface defines an entry point that should be used to perform a
 701      * method check. A method check usually consist in determining as to whether
 702      * a set of types (actuals) is compatible with another set of types (formals).
 703      * Since the notion of compatibility can vary depending on the circumstances,
 704      * this interfaces allows to easily add new pluggable method check routines.
 705      */
 706     interface MethodCheck {
 707         /**
 708          * Main method check routine. A method check usually consist in determining
 709          * as to whether a set of types (actuals) is compatible with another set of
 710          * types (formals). If an incompatibility is found, an unchecked exception
 711          * is assumed to be thrown.
 712          */
 713         void argumentsAcceptable(Env<AttrContext> env,
 714                                 DeferredAttrContext deferredAttrContext,
 715                                 List<Type> argtypes,
 716                                 List<Type> formals,
 717                                 Warner warn);
 718 
 719         /**
 720          * Retrieve the method check object that will be used during a
 721          * most specific check.
 722          */
 723         MethodCheck mostSpecificCheck(List<Type> actuals);
 724     }
 725 
 726     /**
 727      * Helper enum defining all method check diagnostics (used by resolveMethodCheck).
 728      */
 729     enum MethodCheckDiag {
 730         /**
 731          * Actuals and formals differs in length.
 732          */
 733         ARITY_MISMATCH("arg.length.mismatch", "infer.arg.length.mismatch"),
 734         /**
 735          * An actual is incompatible with a formal.
 736          */
 737         ARG_MISMATCH("no.conforming.assignment.exists", "infer.no.conforming.assignment.exists"),
 738         /**
 739          * An actual is incompatible with the varargs element type.
 740          */
 741         VARARG_MISMATCH("varargs.argument.mismatch", "infer.varargs.argument.mismatch"),
 742         /**
 743          * The varargs element type is inaccessible.
 744          */
 745         INACCESSIBLE_VARARGS("inaccessible.varargs.type", "inaccessible.varargs.type");
 746 
 747         final String basicKey;
 748         final String inferKey;
 749 
 750         MethodCheckDiag(String basicKey, String inferKey) {
 751             this.basicKey = basicKey;
 752             this.inferKey = inferKey;
 753         }
 754 
 755         String regex() {
 756             return String.format("([a-z]*\\.)*(%s|%s)", basicKey, inferKey);
 757         }
 758     }
 759 
 760     /**
 761      * Dummy method check object. All methods are deemed applicable, regardless
 762      * of their formal parameter types.
 763      */
 764     MethodCheck nilMethodCheck = new MethodCheck() {
 765         public void argumentsAcceptable(Env<AttrContext> env, DeferredAttrContext deferredAttrContext, List<Type> argtypes, List<Type> formals, Warner warn) {
 766             //do nothing - method always applicable regardless of actuals
 767         }
 768 
 769         public MethodCheck mostSpecificCheck(List<Type> actuals) {
 770             return this;
 771         }
 772     };
 773 
 774     /**
 775      * Base class for 'real' method checks. The class defines the logic for
 776      * iterating through formals and actuals and provides and entry point
 777      * that can be used by subclasses in order to define the actual check logic.
 778      */
 779     abstract class AbstractMethodCheck implements MethodCheck {
 780         @Override
 781         public void argumentsAcceptable(final Env<AttrContext> env,
 782                                     DeferredAttrContext deferredAttrContext,
 783                                     List<Type> argtypes,
 784                                     List<Type> formals,
 785                                     Warner warn) {
 786             //should we expand formals?
 787             boolean useVarargs = deferredAttrContext.phase.isVarargsRequired();
 788             JCTree callTree = treeForDiagnostics(env);
 789             List<JCExpression> trees = TreeInfo.args(callTree);
 790 
 791             //inference context used during this method check
 792             InferenceContext inferenceContext = deferredAttrContext.inferenceContext;
 793 
 794             Type varargsFormal = useVarargs ? formals.last() : null;
 795 
 796             if (varargsFormal == null &&
 797                     argtypes.size() != formals.size()) {
 798                 reportMC(callTree, MethodCheckDiag.ARITY_MISMATCH, inferenceContext); // not enough args
 799             }
 800 
 801             while (argtypes.nonEmpty() && formals.head != varargsFormal) {
 802                 DiagnosticPosition pos = trees != null ? trees.head : null;
 803                 checkArg(pos, false, argtypes.head, formals.head, deferredAttrContext, warn);
 804                 argtypes = argtypes.tail;
 805                 formals = formals.tail;
 806                 trees = trees != null ? trees.tail : trees;
 807             }
 808 
 809             if (formals.head != varargsFormal) {
 810                 reportMC(callTree, MethodCheckDiag.ARITY_MISMATCH, inferenceContext); // not enough args
 811             }
 812 
 813             if (useVarargs) {
 814                 //note: if applicability check is triggered by most specific test,
 815                 //the last argument of a varargs is _not_ an array type (see JLS 15.12.2.5)
 816                 final Type elt = types.elemtype(varargsFormal);
 817                 while (argtypes.nonEmpty()) {
 818                     DiagnosticPosition pos = trees != null ? trees.head : null;
 819                     checkArg(pos, true, argtypes.head, elt, deferredAttrContext, warn);
 820                     argtypes = argtypes.tail;
 821                     trees = trees != null ? trees.tail : trees;
 822                 }
 823             }
 824         }
 825 
 826             // where
 827             private JCTree treeForDiagnostics(Env<AttrContext> env) {
 828                 return env.info.preferredTreeForDiagnostics != null ? env.info.preferredTreeForDiagnostics : env.tree;
 829             }
 830 
 831         /**
 832          * Does the actual argument conforms to the corresponding formal?
 833          */
 834         abstract void checkArg(DiagnosticPosition pos, boolean varargs, Type actual, Type formal, DeferredAttrContext deferredAttrContext, Warner warn);
 835 
 836         protected void reportMC(DiagnosticPosition pos, MethodCheckDiag diag, InferenceContext inferenceContext, Object... args) {
 837             boolean inferDiag = inferenceContext != infer.emptyContext;
 838             if (inferDiag && (!diag.inferKey.equals(diag.basicKey))) {
 839                 Object[] args2 = new Object[args.length + 1];
 840                 System.arraycopy(args, 0, args2, 1, args.length);
 841                 args2[0] = inferenceContext.inferenceVars();
 842                 args = args2;
 843             }
 844             String key = inferDiag ? diag.inferKey : diag.basicKey;
 845             throw inferDiag ?
 846                 infer.error(diags.create(DiagnosticType.FRAGMENT, log.currentSource(), pos, key, args)) :
 847                 getMethodCheckFailure().setMessage(diags.create(DiagnosticType.FRAGMENT, log.currentSource(), pos, key, args));
 848         }
 849 
 850         /**
 851          * To eliminate the overhead associated with allocating an exception object in such an
 852          * hot execution path, we use flyweight pattern - and share the same exception instance
 853          * across multiple method check failures.
 854          */
 855         class SharedInapplicableMethodException extends InapplicableMethodException {
 856             private static final long serialVersionUID = 0;
 857 
 858             SharedInapplicableMethodException() {
 859                 super(null, Resolve.this.dumpStacktraceOnError);
 860             }
 861 
 862             SharedInapplicableMethodException setMessage(JCDiagnostic details) {
 863                 this.diagnostic = details;
 864                 return this;
 865             }
 866         }
 867 
 868         private SharedInapplicableMethodException methodCheckFailure;
 869 
 870         public MethodCheck mostSpecificCheck(List<Type> actuals) {
 871             return nilMethodCheck;
 872         }
 873 
 874         private SharedInapplicableMethodException getMethodCheckFailure() {
 875             return methodCheckFailure == null ? methodCheckFailure = new SharedInapplicableMethodException() : methodCheckFailure;
 876         }
 877     }
 878 
 879     /**
 880      * Arity-based method check. A method is applicable if the number of actuals
 881      * supplied conforms to the method signature.
 882      */
 883     MethodCheck arityMethodCheck = new AbstractMethodCheck() {
 884         @Override
 885         void checkArg(DiagnosticPosition pos, boolean varargs, Type actual, Type formal, DeferredAttrContext deferredAttrContext, Warner warn) {
 886             //do nothing - actual always compatible to formals
 887         }
 888 
 889         @Override
 890         public String toString() {
 891             return "arityMethodCheck";
 892         }
 893     };
 894 
 895     /**
 896      * Main method applicability routine. Given a list of actual types A,
 897      * a list of formal types F, determines whether the types in A are
 898      * compatible (by method invocation conversion) with the types in F.
 899      *
 900      * Since this routine is shared between overload resolution and method
 901      * type-inference, a (possibly empty) inference context is used to convert
 902      * formal types to the corresponding 'undet' form ahead of a compatibility
 903      * check so that constraints can be propagated and collected.
 904      *
 905      * Moreover, if one or more types in A is a deferred type, this routine uses
 906      * DeferredAttr in order to perform deferred attribution. If one or more actual
 907      * deferred types are stuck, they are placed in a queue and revisited later
 908      * after the remainder of the arguments have been seen. If this is not sufficient
 909      * to 'unstuck' the argument, a cyclic inference error is called out.
 910      *
 911      * A method check handler (see above) is used in order to report errors.
 912      */
 913     MethodCheck resolveMethodCheck = new AbstractMethodCheck() {
 914 
 915         @Override
 916         void checkArg(DiagnosticPosition pos, boolean varargs, Type actual, Type formal, DeferredAttrContext deferredAttrContext, Warner warn) {
 917             ResultInfo mresult = methodCheckResult(varargs, formal, deferredAttrContext, warn);
 918             mresult.check(pos, actual);
 919         }
 920 
 921         @Override
 922         public void argumentsAcceptable(final Env<AttrContext> env,
 923                                     DeferredAttrContext deferredAttrContext,
 924                                     List<Type> argtypes,
 925                                     List<Type> formals,
 926                                     Warner warn) {
 927             super.argumentsAcceptable(env, deferredAttrContext, argtypes, formals, warn);
 928             // should we check varargs element type accessibility?
 929             if (deferredAttrContext.phase.isVarargsRequired()) {
 930                 if (deferredAttrContext.mode == AttrMode.CHECK) {
 931                     varargsAccessible(env, types.elemtype(formals.last()), deferredAttrContext.inferenceContext);
 932                 }
 933             }
 934         }
 935 
 936         /**
 937          * Test that the runtime array element type corresponding to 't' is accessible.  't' should be the
 938          * varargs element type of either the method invocation type signature (after inference completes)
 939          * or the method declaration signature (before inference completes).
 940          */
 941         private void varargsAccessible(final Env<AttrContext> env, final Type t, final InferenceContext inferenceContext) {
 942             if (inferenceContext.free(t)) {
 943                 inferenceContext.addFreeTypeListener(List.of(t),
 944                         solvedContext -> varargsAccessible(env, solvedContext.asInstType(t), solvedContext));
 945             } else {
 946                 if (!isAccessible(env, types.erasure(t))) {
 947                     Symbol location = env.enclClass.sym;
 948                     reportMC(env.tree, MethodCheckDiag.INACCESSIBLE_VARARGS, inferenceContext, t, Kinds.kindName(location), location);
 949                 }
 950             }
 951         }
 952 
 953         private ResultInfo methodCheckResult(final boolean varargsCheck, Type to,
 954                 final DeferredAttr.DeferredAttrContext deferredAttrContext, Warner rsWarner) {
 955             CheckContext checkContext = new MethodCheckContext(!deferredAttrContext.phase.isBoxingRequired(), deferredAttrContext, rsWarner) {
 956                 MethodCheckDiag methodDiag = varargsCheck ?
 957                                  MethodCheckDiag.VARARG_MISMATCH : MethodCheckDiag.ARG_MISMATCH;
 958 
 959                 @Override
 960                 public void report(DiagnosticPosition pos, JCDiagnostic details) {
 961                     reportMC(pos, methodDiag, deferredAttrContext.inferenceContext, details);
 962                 }
 963             };
 964             return new MethodResultInfo(to, checkContext);
 965         }
 966 
 967         @Override
 968         public MethodCheck mostSpecificCheck(List<Type> actuals) {
 969             return new MostSpecificCheck(actuals);
 970         }
 971 
 972         @Override
 973         public String toString() {
 974             return "resolveMethodCheck";
 975         }
 976     };
 977 
 978     /**
 979      * This class handles method reference applicability checks; since during
 980      * these checks it's sometime possible to have inference variables on
 981      * the actual argument types list, the method applicability check must be
 982      * extended so that inference variables are 'opened' as needed.
 983      */
 984     class MethodReferenceCheck extends AbstractMethodCheck {
 985 
 986         InferenceContext pendingInferenceContext;
 987 
 988         MethodReferenceCheck(InferenceContext pendingInferenceContext) {
 989             this.pendingInferenceContext = pendingInferenceContext;
 990         }
 991 
 992         @Override
 993         void checkArg(DiagnosticPosition pos, boolean varargs, Type actual, Type formal, DeferredAttrContext deferredAttrContext, Warner warn) {
 994             ResultInfo mresult = methodCheckResult(varargs, formal, deferredAttrContext, warn);
 995             mresult.check(pos, actual);
 996         }
 997 
 998         private ResultInfo methodCheckResult(final boolean varargsCheck, Type to,
 999                 final DeferredAttr.DeferredAttrContext deferredAttrContext, Warner rsWarner) {
1000             CheckContext checkContext = new MethodCheckContext(!deferredAttrContext.phase.isBoxingRequired(), deferredAttrContext, rsWarner) {
1001                 MethodCheckDiag methodDiag = varargsCheck ?
1002                                  MethodCheckDiag.VARARG_MISMATCH : MethodCheckDiag.ARG_MISMATCH;
1003 
1004                 @Override
1005                 public boolean compatible(Type found, Type req, Warner warn) {
1006                     found = pendingInferenceContext.asUndetVar(found);
1007                     if (found.hasTag(UNDETVAR) && req.isPrimitive()) {
1008                         req = types.boxedClass(req).type;
1009                     }
1010                     return super.compatible(found, req, warn);
1011                 }
1012 
1013                 @Override
1014                 public void report(DiagnosticPosition pos, JCDiagnostic details) {
1015                     reportMC(pos, methodDiag, deferredAttrContext.inferenceContext, details);
1016                 }
1017             };
1018             return new MethodResultInfo(to, checkContext);
1019         }
1020 
1021         @Override
1022         public MethodCheck mostSpecificCheck(List<Type> actuals) {
1023             return new MostSpecificCheck(actuals);
1024         }
1025 
1026         @Override
1027         public String toString() {
1028             return "MethodReferenceCheck";
1029         }
1030     }
1031 
1032     /**
1033      * Check context to be used during method applicability checks. A method check
1034      * context might contain inference variables.
1035      */
1036     abstract class MethodCheckContext implements CheckContext {
1037 
1038         boolean strict;
1039         DeferredAttrContext deferredAttrContext;
1040         Warner rsWarner;
1041 
1042         public MethodCheckContext(boolean strict, DeferredAttrContext deferredAttrContext, Warner rsWarner) {
1043            this.strict = strict;
1044            this.deferredAttrContext = deferredAttrContext;
1045            this.rsWarner = rsWarner;
1046         }
1047 
1048         public boolean compatible(Type found, Type req, Warner warn) {
1049             InferenceContext inferenceContext = deferredAttrContext.inferenceContext;
1050             return strict ?
1051                     types.isSubtypeUnchecked(inferenceContext.asUndetVar(found), inferenceContext.asUndetVar(req), warn) :
1052                     types.isConvertible(inferenceContext.asUndetVar(found), inferenceContext.asUndetVar(req), warn);
1053         }
1054 
1055         public void report(DiagnosticPosition pos, JCDiagnostic details) {
1056             throw new InapplicableMethodException(details, Resolve.this.dumpStacktraceOnError);
1057         }
1058 
1059         public Warner checkWarner(DiagnosticPosition pos, Type found, Type req) {
1060             return rsWarner;
1061         }
1062 
1063         public InferenceContext inferenceContext() {
1064             return deferredAttrContext.inferenceContext;
1065         }
1066 
1067         public DeferredAttrContext deferredAttrContext() {
1068             return deferredAttrContext;
1069         }
1070 
1071         @Override
1072         public String toString() {
1073             return "MethodCheckContext";
1074         }
1075     }
1076 
1077     /**
1078      * ResultInfo class to be used during method applicability checks. Check
1079      * for deferred types goes through special path.
1080      */
1081     class MethodResultInfo extends ResultInfo {
1082 
1083         public MethodResultInfo(Type pt, CheckContext checkContext) {
1084             attr.super(KindSelector.VAL, pt, checkContext);
1085         }
1086 
1087         @Override
1088         protected Type check(DiagnosticPosition pos, Type found) {
1089             if (found.hasTag(DEFERRED)) {
1090                 DeferredType dt = (DeferredType)found;
1091                 return dt.check(this);
1092             } else {
1093                 Type uResult = U(found);
1094                 Type capturedType = pos == null || pos.getTree() == null ?
1095                         types.capture(uResult) :
1096                         checkContext.inferenceContext()
1097                             .cachedCapture(pos.getTree(), uResult, true);
1098                 return super.check(pos, chk.checkNonVoid(pos, capturedType));
1099             }
1100         }
1101 
1102         /**
1103          * javac has a long-standing 'simplification' (see 6391995):
1104          * given an actual argument type, the method check is performed
1105          * on its upper bound. This leads to inconsistencies when an
1106          * argument type is checked against itself. For example, given
1107          * a type-variable T, it is not true that {@code U(T) <: T},
1108          * so we need to guard against that.
1109          */
1110         private Type U(Type found) {
1111             return found == pt ?
1112                     found : types.cvarUpperBound(found);
1113         }
1114 
1115         @Override
1116         protected MethodResultInfo dup(Type newPt) {
1117             return new MethodResultInfo(newPt, checkContext);
1118         }
1119 
1120         @Override
1121         protected ResultInfo dup(CheckContext newContext) {
1122             return new MethodResultInfo(pt, newContext);
1123         }
1124 
1125         @Override
1126         protected ResultInfo dup(Type newPt, CheckContext newContext) {
1127             return new MethodResultInfo(newPt, newContext);
1128         }
1129     }
1130 
1131     /**
1132      * Most specific method applicability routine. Given a list of actual types A,
1133      * a list of formal types F1, and a list of formal types F2, the routine determines
1134      * as to whether the types in F1 can be considered more specific than those in F2 w.r.t.
1135      * argument types A.
1136      */
1137     class MostSpecificCheck implements MethodCheck {
1138 
1139         List<Type> actuals;
1140 
1141         MostSpecificCheck(List<Type> actuals) {
1142             this.actuals = actuals;
1143         }
1144 
1145         @Override
1146         public void argumentsAcceptable(final Env<AttrContext> env,
1147                                     DeferredAttrContext deferredAttrContext,
1148                                     List<Type> formals1,
1149                                     List<Type> formals2,
1150                                     Warner warn) {
1151             formals2 = adjustArgs(formals2, deferredAttrContext.msym, formals1.length(), deferredAttrContext.phase.isVarargsRequired());
1152             while (formals2.nonEmpty()) {
1153                 ResultInfo mresult = methodCheckResult(formals2.head, deferredAttrContext, warn, actuals.head);
1154                 mresult.check(null, formals1.head);
1155                 formals1 = formals1.tail;
1156                 formals2 = formals2.tail;
1157                 actuals = actuals.isEmpty() ? actuals : actuals.tail;
1158             }
1159         }
1160 
1161        /**
1162         * Create a method check context to be used during the most specific applicability check
1163         */
1164         ResultInfo methodCheckResult(Type to, DeferredAttr.DeferredAttrContext deferredAttrContext,
1165                Warner rsWarner, Type actual) {
1166             return attr.new ResultInfo(KindSelector.VAL, to,
1167                    new MostSpecificCheckContext(deferredAttrContext, rsWarner, actual));
1168         }
1169 
1170         /**
1171          * Subclass of method check context class that implements most specific
1172          * method conversion. If the actual type under analysis is a deferred type
1173          * a full blown structural analysis is carried out.
1174          */
1175         class MostSpecificCheckContext extends MethodCheckContext {
1176 
1177             Type actual;
1178 
1179             public MostSpecificCheckContext(DeferredAttrContext deferredAttrContext, Warner rsWarner, Type actual) {
1180                 super(true, deferredAttrContext, rsWarner);
1181                 this.actual = actual;
1182             }
1183 
1184             public boolean compatible(Type found, Type req, Warner warn) {
1185                 if (unrelatedFunctionalInterfaces(found, req) &&
1186                     (actual != null && actual.getTag() == DEFERRED)) {
1187                     DeferredType dt = (DeferredType) actual;
1188                     JCTree speculativeTree = dt.speculativeTree(deferredAttrContext);
1189                     if (speculativeTree != deferredAttr.stuckTree) {
1190                         return functionalInterfaceMostSpecific(found, req, speculativeTree);
1191                     }
1192                 }
1193                 return compatibleBySubtyping(found, req);
1194             }
1195 
1196             private boolean compatibleBySubtyping(Type found, Type req) {
1197                 if (!strict && found.isPrimitive() != req.isPrimitive()) {
1198                     found = found.isPrimitive() ? types.boxedClass(found).type : types.unboxedType(found);
1199                 }
1200                 return types.isSubtypeNoCapture(found, deferredAttrContext.inferenceContext.asUndetVar(req));
1201             }
1202 
1203             /** Whether {@code t} and {@code s} are unrelated functional interface types. */
1204             private boolean unrelatedFunctionalInterfaces(Type t, Type s) {
1205                 return types.isFunctionalInterface(t.tsym) &&
1206                        types.isFunctionalInterface(s.tsym) &&
1207                        unrelatedInterfaces(t, s);
1208             }
1209 
1210             /** Whether {@code t} and {@code s} are unrelated interface types; recurs on intersections. **/
1211             private boolean unrelatedInterfaces(Type t, Type s) {
1212                 if (t.isCompound()) {
1213                     for (Type ti : types.interfaces(t)) {
1214                         if (!unrelatedInterfaces(ti, s)) {
1215                             return false;
1216                         }
1217                     }
1218                     return true;
1219                 } else if (s.isCompound()) {
1220                     for (Type si : types.interfaces(s)) {
1221                         if (!unrelatedInterfaces(t, si)) {
1222                             return false;
1223                         }
1224                     }
1225                     return true;
1226                 } else {
1227                     return types.asSuper(t, s.tsym) == null && types.asSuper(s, t.tsym) == null;
1228                 }
1229             }
1230 
1231             /** Parameters {@code t} and {@code s} are unrelated functional interface types. */
1232             private boolean functionalInterfaceMostSpecific(Type t, Type s, JCTree tree) {
1233                 Type tDesc;
1234                 Type tDescNoCapture;
1235                 Type sDesc;
1236                 try {
1237                     tDesc = types.findDescriptorType(types.capture(t));
1238                     tDescNoCapture = types.findDescriptorType(t);
1239                     sDesc = types.findDescriptorType(s);
1240                 } catch (Types.FunctionDescriptorLookupError ex) {
1241                     // don't report, a more meaningful error should be reported upstream
1242                     return false;
1243                 }
1244                 final List<Type> tTypeParams = tDesc.getTypeArguments();
1245                 final List<Type> tTypeParamsNoCapture = tDescNoCapture.getTypeArguments();
1246                 final List<Type> sTypeParams = sDesc.getTypeArguments();
1247 
1248                 // compare type parameters
1249                 if (tDesc.hasTag(FORALL) && !types.hasSameBounds((ForAll) tDesc, (ForAll) tDescNoCapture)) {
1250                     return false;
1251                 }
1252                 // can't use Types.hasSameBounds on sDesc because bounds may have ivars
1253                 List<Type> tIter = tTypeParams;
1254                 List<Type> sIter = sTypeParams;
1255                 while (tIter.nonEmpty() && sIter.nonEmpty()) {
1256                     Type tBound = tIter.head.getUpperBound();
1257                     Type sBound = types.subst(sIter.head.getUpperBound(), sTypeParams, tTypeParams);
1258                     if (tBound.containsAny(tTypeParams) && inferenceContext().free(sBound)) {
1259                         return false;
1260                     }
1261                     if (!types.isSameType(tBound, inferenceContext().asUndetVar(sBound))) {
1262                         return false;
1263                     }
1264                     tIter = tIter.tail;
1265                     sIter = sIter.tail;
1266                 }
1267                 if (!tIter.isEmpty() || !sIter.isEmpty()) {
1268                     return false;
1269                 }
1270 
1271                 // compare parameters
1272                 List<Type> tParams = tDesc.getParameterTypes();
1273                 List<Type> tParamsNoCapture = tDescNoCapture.getParameterTypes();
1274                 List<Type> sParams = sDesc.getParameterTypes();
1275                 while (tParams.nonEmpty() && tParamsNoCapture.nonEmpty() && sParams.nonEmpty()) {
1276                     Type tParam = tParams.head;
1277                     Type tParamNoCapture = types.subst(tParamsNoCapture.head, tTypeParamsNoCapture, tTypeParams);
1278                     Type sParam = types.subst(sParams.head, sTypeParams, tTypeParams);
1279                     if (tParam.containsAny(tTypeParams) && inferenceContext().free(sParam)) {
1280                         return false;
1281                     }
1282                     if (!types.isSubtype(inferenceContext().asUndetVar(sParam), tParam)) {
1283                         return false;
1284                     }
1285                     if (!types.isSameType(tParamNoCapture, inferenceContext().asUndetVar(sParam))) {
1286                         return false;
1287                     }
1288                     tParams = tParams.tail;
1289                     tParamsNoCapture = tParamsNoCapture.tail;
1290                     sParams = sParams.tail;
1291                 }
1292                 if (!tParams.isEmpty() || !tParamsNoCapture.isEmpty() || !sParams.isEmpty()) {
1293                     return false;
1294                 }
1295 
1296                 // compare returns
1297                 Type tRet = tDesc.getReturnType();
1298                 Type sRet = types.subst(sDesc.getReturnType(), sTypeParams, tTypeParams);
1299                 if (tRet.containsAny(tTypeParams) && inferenceContext().free(sRet)) {
1300                     return false;
1301                 }
1302                 MostSpecificFunctionReturnChecker msc = new MostSpecificFunctionReturnChecker(tRet, sRet);
1303                 msc.scan(tree);
1304                 return msc.result;
1305             }
1306 
1307             /**
1308              * Tests whether one functional interface type can be considered more specific
1309              * than another unrelated functional interface type for the scanned expression.
1310              */
1311             class MostSpecificFunctionReturnChecker extends DeferredAttr.PolyScanner {
1312 
1313                 final Type tRet;
1314                 final Type sRet;
1315                 boolean result;
1316 
1317                 /** Parameters {@code t} and {@code s} are unrelated functional interface types. */
1318                 MostSpecificFunctionReturnChecker(Type tRet, Type sRet) {
1319                     this.tRet = tRet;
1320                     this.sRet = sRet;
1321                     result = true;
1322                 }
1323 
1324                 @Override
1325                 void skip(JCTree tree) {
1326                     result = false;
1327                 }
1328 
1329                 @Override
1330                 public void visitConditional(JCConditional tree) {
1331                     scan(asExpr(tree.truepart));
1332                     scan(asExpr(tree.falsepart));
1333                 }
1334 
1335                 @Override
1336                 public void visitReference(JCMemberReference tree) {
1337                     if (sRet.hasTag(VOID)) {
1338                         // do nothing
1339                     } else if (tRet.hasTag(VOID)) {
1340                         result = false;
1341                     } else if (tRet.isPrimitive() != sRet.isPrimitive()) {
1342                         boolean retValIsPrimitive =
1343                                 tree.refPolyKind == PolyKind.STANDALONE &&
1344                                 tree.sym.type.getReturnType().isPrimitive();
1345                         result &= (retValIsPrimitive == tRet.isPrimitive()) &&
1346                                   (retValIsPrimitive != sRet.isPrimitive());
1347                     } else {
1348                         result &= compatibleBySubtyping(tRet, sRet);
1349                     }
1350                 }
1351 
1352                 @Override
1353                 public void visitParens(JCParens tree) {
1354                     scan(asExpr(tree.expr));
1355                 }
1356 
1357                 @Override
1358                 public void visitLambda(JCLambda tree) {
1359                     if (sRet.hasTag(VOID)) {
1360                         // do nothing
1361                     } else if (tRet.hasTag(VOID)) {
1362                         result = false;
1363                     } else {
1364                         List<JCExpression> lambdaResults = lambdaResults(tree);
1365                         if (!lambdaResults.isEmpty() && unrelatedFunctionalInterfaces(tRet, sRet)) {
1366                             for (JCExpression expr : lambdaResults) {
1367                                 result &= functionalInterfaceMostSpecific(tRet, sRet, expr);
1368                             }
1369                         } else if (!lambdaResults.isEmpty() && tRet.isPrimitive() != sRet.isPrimitive()) {
1370                             for (JCExpression expr : lambdaResults) {
1371                                 boolean retValIsPrimitive = expr.isStandalone() && expr.type.isPrimitive();
1372                                 result &= (retValIsPrimitive == tRet.isPrimitive()) &&
1373                                         (retValIsPrimitive != sRet.isPrimitive());
1374                             }
1375                         } else {
1376                             result &= compatibleBySubtyping(tRet, sRet);
1377                         }
1378                     }
1379                 }
1380                 //where
1381 
1382                 private List<JCExpression> lambdaResults(JCLambda lambda) {
1383                     if (lambda.getBodyKind() == JCTree.JCLambda.BodyKind.EXPRESSION) {
1384                         return List.of(asExpr((JCExpression) lambda.body));
1385                     } else {
1386                         final ListBuffer<JCExpression> buffer = new ListBuffer<>();
1387                         DeferredAttr.LambdaReturnScanner lambdaScanner =
1388                                 new DeferredAttr.LambdaReturnScanner() {
1389                                     @Override
1390                                     public void visitReturn(JCReturn tree) {
1391                                         if (tree.expr != null) {
1392                                             buffer.append(asExpr(tree.expr));
1393                                         }
1394                                     }
1395                                 };
1396                         lambdaScanner.scan(lambda.body);
1397                         return buffer.toList();
1398                     }
1399                 }
1400 
1401                 private JCExpression asExpr(JCExpression expr) {
1402                     if (expr.type.hasTag(DEFERRED)) {
1403                         JCTree speculativeTree = ((DeferredType)expr.type).speculativeTree(deferredAttrContext);
1404                         if (speculativeTree != deferredAttr.stuckTree) {
1405                             expr = (JCExpression)speculativeTree;
1406                         }
1407                     }
1408                     return expr;
1409                 }
1410             }
1411 
1412         }
1413 
1414         public MethodCheck mostSpecificCheck(List<Type> actuals) {
1415             Assert.error("Cannot get here!");
1416             return null;
1417         }
1418     }
1419 
1420     public static class InapplicableMethodException extends CompilerInternalException {
1421         private static final long serialVersionUID = 0;
1422 
1423         transient JCDiagnostic diagnostic;
1424 
1425         InapplicableMethodException(JCDiagnostic diag, boolean dumpStackTraceOnError) {
1426             super(dumpStackTraceOnError);
1427             this.diagnostic = diag;
1428         }
1429 
1430         public JCDiagnostic getDiagnostic() {
1431             return diagnostic;
1432         }
1433     }
1434 
1435 /* ***************************************************************************
1436  *  Symbol lookup
1437  *  the following naming conventions for arguments are used
1438  *
1439  *       env      is the environment where the symbol was mentioned
1440  *       site     is the type of which the symbol is a member
1441  *       name     is the symbol's name
1442  *                if no arguments are given
1443  *       argtypes are the value arguments, if we search for a method
1444  *
1445  *  If no symbol was found, a ResolveError detailing the problem is returned.
1446  ****************************************************************************/
1447 
1448     /** Find field. Synthetic fields are always skipped.
1449      *  @param env     The current environment.
1450      *  @param site    The original type from where the selection takes place.
1451      *  @param name    The name of the field.
1452      *  @param c       The class to search for the field. This is always
1453      *                 a superclass or implemented interface of site's class.
1454      */
1455     Symbol findField(Env<AttrContext> env,
1456                      Type site,
1457                      Name name,
1458                      TypeSymbol c) {
1459         while (c.type.hasTag(TYPEVAR))
1460             c = c.type.getUpperBound().tsym;
1461         Symbol bestSoFar = varNotFound;
1462         Symbol sym;
1463         for (Symbol s : c.members().getSymbolsByName(name)) {
1464             if (s.kind == VAR && (s.flags_field & SYNTHETIC) == 0) {
1465                 return isAccessible(env, site, s)
1466                     ? s : new AccessError(env, site, s);
1467             }
1468         }
1469         Type st = types.supertype(c.type);
1470         if (st != null && (st.hasTag(CLASS) || st.hasTag(TYPEVAR))) {
1471             sym = findField(env, site, name, st.tsym);
1472             bestSoFar = bestOf(bestSoFar, sym);
1473         }
1474         for (List<Type> l = types.interfaces(c.type);
1475              bestSoFar.kind != AMBIGUOUS && l.nonEmpty();
1476              l = l.tail) {
1477             sym = findField(env, site, name, l.head.tsym);
1478             if (bestSoFar.exists() && sym.exists() &&
1479                 sym.owner != bestSoFar.owner)
1480                 bestSoFar = new AmbiguityError(bestSoFar, sym);
1481             else
1482                 bestSoFar = bestOf(bestSoFar, sym);
1483         }
1484         return bestSoFar;
1485     }
1486 
1487     /** Resolve a field identifier, throw a fatal error if not found.
1488      *  @param pos       The position to use for error reporting.
1489      *  @param env       The environment current at the method invocation.
1490      *  @param site      The type of the qualifying expression, in which
1491      *                   identifier is searched.
1492      *  @param name      The identifier's name.
1493      */
1494     public VarSymbol resolveInternalField(DiagnosticPosition pos, Env<AttrContext> env,
1495                                           Type site, Name name) {
1496         Symbol sym = findField(env, site, name, site.tsym);
1497         if (sym.kind == VAR) return (VarSymbol)sym;
1498         else throw new FatalError(
1499                  diags.fragment(Fragments.FatalErrCantLocateField(name)));
1500     }
1501 
1502     /** Find unqualified variable or field with given name.
1503      *  Synthetic fields always skipped.
1504      *  @param pos       The position to use for error reporting.
1505      *  @param env     The current environment.
1506      *  @param name    The name of the variable or field.
1507      */
1508     Symbol findVar(DiagnosticPosition pos, Env<AttrContext> env, Name name) {
1509         Symbol bestSoFar = varNotFound;
1510         Env<AttrContext> env1 = env;
1511         boolean staticOnly = false;
1512         while (env1.outer != null) {
1513             Symbol sym = null;
1514             for (Symbol s : env1.info.scope.getSymbolsByName(name)) {
1515                 if (s.kind == VAR && (s.flags_field & SYNTHETIC) == 0) {
1516                     sym = s;
1517                     if (staticOnly) {
1518                         return new StaticError(sym);
1519                     }
1520                     break;
1521                 }
1522             }
1523             if (isStatic(env1)) staticOnly = true;
1524             if (sym == null) {
1525                 sym = findField(env1, env1.enclClass.sym.type, name, env1.enclClass.sym);
1526             }
1527             if (sym.exists()) {
1528                 if (sym.kind == VAR &&
1529                         sym.owner.kind == TYP &&
1530                         (sym.flags() & STATIC) == 0) {
1531                     if (staticOnly)
1532                         return new StaticError(sym);
1533                     if (env1.info.ctorPrologue && !isAllowedEarlyReference(pos, env1, (VarSymbol)sym))
1534                         return new RefBeforeCtorCalledError(sym);
1535                 }
1536                 return sym;
1537             } else {
1538                 bestSoFar = bestOf(bestSoFar, sym);
1539             }
1540 
1541             if ((env1.enclClass.sym.flags() & STATIC) != 0) staticOnly = true;
1542             env1 = env1.outer;
1543         }
1544 
1545         Symbol sym = findField(env, syms.predefClass.type, name, syms.predefClass);
1546         if (sym.exists())
1547             return sym;
1548         if (bestSoFar.exists())
1549             return bestSoFar;
1550 
1551         Symbol origin = null;
1552         for (Scope sc : new Scope[] { env.toplevel.namedImportScope, env.toplevel.starImportScope }) {
1553             for (Symbol currentSymbol : sc.getSymbolsByName(name)) {
1554                 if (currentSymbol.kind != VAR)
1555                     continue;
1556                 // invariant: sym.kind == Symbol.Kind.VAR
1557                 if (!bestSoFar.kind.isResolutionError() &&
1558                     currentSymbol.owner != bestSoFar.owner)
1559                     return new AmbiguityError(bestSoFar, currentSymbol);
1560                 else if (!bestSoFar.kind.betterThan(VAR)) {
1561                     origin = sc.getOrigin(currentSymbol).owner;
1562                     bestSoFar = isAccessible(env, origin.type, currentSymbol)
1563                         ? currentSymbol : new AccessError(env, origin.type, currentSymbol);
1564                 }
1565             }
1566             if (bestSoFar.exists()) break;
1567         }
1568         if (bestSoFar.kind == VAR && bestSoFar.owner.type != origin.type)
1569             return bestSoFar.clone(origin);
1570         else
1571             return bestSoFar;
1572     }
1573 
1574     Warner noteWarner = new Warner();
1575 
1576     /** Select the best method for a call site among two choices.
1577      *  @param env              The current environment.
1578      *  @param site             The original type from where the
1579      *                          selection takes place.
1580      *  @param argtypes         The invocation's value arguments,
1581      *  @param typeargtypes     The invocation's type arguments,
1582      *  @param sym              Proposed new best match.
1583      *  @param bestSoFar        Previously found best match.
1584      *  @param allowBoxing Allow boxing conversions of arguments.
1585      *  @param useVarargs Box trailing arguments into an array for varargs.
1586      */
1587     @SuppressWarnings("fallthrough")
1588     Symbol selectBest(Env<AttrContext> env,
1589                       Type site,
1590                       List<Type> argtypes,
1591                       List<Type> typeargtypes,
1592                       Symbol sym,
1593                       Symbol bestSoFar,
1594                       boolean allowBoxing,
1595                       boolean useVarargs) {
1596         if (sym.kind == ERR ||
1597                 (site.tsym != sym.owner && !sym.isInheritedIn(site.tsym, types)) ||
1598                 !notOverriddenIn(site, sym)) {
1599             return bestSoFar;
1600         } else if (useVarargs && (sym.flags() & VARARGS) == 0) {
1601             return bestSoFar.kind.isResolutionError() ?
1602                     new BadVarargsMethod((ResolveError)bestSoFar.baseSymbol()) :
1603                     bestSoFar;
1604         }
1605         Assert.check(!sym.kind.isResolutionError());
1606         try {
1607             types.noWarnings.clear();
1608             Type mt = rawInstantiate(env, site, sym, null, argtypes, typeargtypes,
1609                                allowBoxing, useVarargs, types.noWarnings);
1610             currentResolutionContext.addApplicableCandidate(sym, mt);
1611         } catch (InapplicableMethodException ex) {
1612             currentResolutionContext.addInapplicableCandidate(sym, ex.getDiagnostic());
1613             // Currently, an InapplicableMethodException occurs.
1614             // If bestSoFar.kind was ABSENT_MTH, return an InapplicableSymbolError(kind is WRONG_MTH).
1615             // If bestSoFar.kind was HIDDEN(AccessError)/WRONG_MTH/WRONG_MTHS, return an InapplicableSymbolsError(kind is WRONG_MTHS).
1616             // See JDK-8255968 for more information.
1617             switch (bestSoFar.kind) {
1618                 case ABSENT_MTH:
1619                     return new InapplicableSymbolError(currentResolutionContext);
1620                 case HIDDEN:
1621                     if (bestSoFar instanceof AccessError accessError) {
1622                         // Add the JCDiagnostic of previous AccessError to the currentResolutionContext
1623                         // and construct InapplicableSymbolsError.
1624                         // Intentionally fallthrough.
1625                         currentResolutionContext.addInapplicableCandidate(accessError.sym,
1626                                 accessError.getDiagnostic(JCDiagnostic.DiagnosticType.FRAGMENT, null, null, site, null, argtypes, typeargtypes));
1627                     } else {
1628                         return bestSoFar;
1629                     }
1630                 case WRONG_MTH:
1631                     bestSoFar = new InapplicableSymbolsError(currentResolutionContext);
1632                 default:
1633                     return bestSoFar;
1634             }
1635         }
1636         if (!isAccessible(env, site, sym)) {
1637             AccessError curAccessError = new AccessError(env, site, sym);
1638             JCDiagnostic curDiagnostic = curAccessError.getDiagnostic(JCDiagnostic.DiagnosticType.FRAGMENT, null, null, site, null, argtypes, typeargtypes);
1639             // Currently, an AccessError occurs.
1640             // If bestSoFar.kind was ABSENT_MTH, return an AccessError(kind is HIDDEN).
1641             // If bestSoFar.kind was HIDDEN(AccessError), WRONG_MTH, WRONG_MTHS, return an InapplicableSymbolsError(kind is WRONG_MTHS).
1642             // See JDK-8255968 for more information.
1643             if (bestSoFar.kind == ABSENT_MTH) {
1644                 bestSoFar = curAccessError;
1645             } else if (bestSoFar.kind == WRONG_MTH) {
1646                 // Add the JCDiagnostic of current AccessError to the currentResolutionContext
1647                 // and construct InapplicableSymbolsError.
1648                 currentResolutionContext.addInapplicableCandidate(sym, curDiagnostic);
1649                 bestSoFar = new InapplicableSymbolsError(currentResolutionContext);
1650             } else if (bestSoFar.kind == WRONG_MTHS) {
1651                 // Add the JCDiagnostic of current AccessError to the currentResolutionContext
1652                 currentResolutionContext.addInapplicableCandidate(sym, curDiagnostic);
1653             } else if (bestSoFar.kind == HIDDEN && bestSoFar instanceof AccessError accessError) {
1654                 // Add the JCDiagnostics of previous and current AccessError to the currentResolutionContext
1655                 // and construct InapplicableSymbolsError.
1656                 currentResolutionContext.addInapplicableCandidate(accessError.sym,
1657                         accessError.getDiagnostic(JCDiagnostic.DiagnosticType.FRAGMENT, null, null, site, null, argtypes, typeargtypes));
1658                 currentResolutionContext.addInapplicableCandidate(sym, curDiagnostic);
1659                 bestSoFar = new InapplicableSymbolsError(currentResolutionContext);
1660             }
1661             return bestSoFar;
1662         }
1663         return (bestSoFar.kind.isResolutionError() && bestSoFar.kind != AMBIGUOUS)
1664             ? sym
1665             : mostSpecific(argtypes, sym, bestSoFar, env, site, useVarargs);
1666     }
1667 
1668     /* Return the most specific of the two methods for a call,
1669      *  given that both are accessible and applicable.
1670      *  @param m1               A new candidate for most specific.
1671      *  @param m2               The previous most specific candidate.
1672      *  @param env              The current environment.
1673      *  @param site             The original type from where the selection
1674      *                          takes place.
1675      *  @param allowBoxing Allow boxing conversions of arguments.
1676      *  @param useVarargs Box trailing arguments into an array for varargs.
1677      */
1678     Symbol mostSpecific(List<Type> argtypes, Symbol m1,
1679                         Symbol m2,
1680                         Env<AttrContext> env,
1681                         final Type site,
1682                         boolean useVarargs) {
1683         switch (m2.kind) {
1684         case MTH:
1685             if (m1 == m2) return m1;
1686             boolean m1SignatureMoreSpecific =
1687                     signatureMoreSpecific(argtypes, env, site, m1, m2, useVarargs);
1688             boolean m2SignatureMoreSpecific =
1689                     signatureMoreSpecific(argtypes, env, site, m2, m1, useVarargs);
1690             if (m1SignatureMoreSpecific && m2SignatureMoreSpecific) {
1691                 Type mt1 = types.memberType(site, m1);
1692                 Type mt2 = types.memberType(site, m2);
1693                 if (!types.overrideEquivalent(mt1, mt2))
1694                     return ambiguityError(m1, m2);
1695 
1696                 // same signature; select (a) the non-bridge method, or
1697                 // (b) the one that overrides the other, or (c) the concrete
1698                 // one, or (d) merge both abstract signatures
1699                 if ((m1.flags() & BRIDGE) != (m2.flags() & BRIDGE))
1700                     return ((m1.flags() & BRIDGE) != 0) ? m2 : m1;
1701 
1702                 if (m1.baseSymbol() == m2.baseSymbol()) {
1703                     // this is the same imported symbol which has been cloned twice.
1704                     // Return the first one (either will do).
1705                     return m1;
1706                 }
1707 
1708                 // if one overrides or hides the other, use it
1709                 TypeSymbol m1Owner = (TypeSymbol)m1.owner;
1710                 TypeSymbol m2Owner = (TypeSymbol)m2.owner;
1711                 // the two owners can never be the same if the target methods are compiled from source,
1712                 // but we need to protect against cases where the methods are defined in some classfile
1713                 // and make sure we issue an ambiguity error accordingly (by skipping the logic below).
1714                 if (m1Owner != m2Owner) {
1715                     if (types.asSuper(m1Owner.type, m2Owner) != null &&
1716                         ((m1.owner.flags_field & INTERFACE) == 0 ||
1717                          (m2.owner.flags_field & INTERFACE) != 0) &&
1718                         m1.overrides(m2, m1Owner, types, false))
1719                         return m1;
1720                     if (types.asSuper(m2Owner.type, m1Owner) != null &&
1721                         ((m2.owner.flags_field & INTERFACE) == 0 ||
1722                          (m1.owner.flags_field & INTERFACE) != 0) &&
1723                         m2.overrides(m1, m2Owner, types, false))
1724                         return m2;
1725                 }
1726                 boolean m1Abstract = (m1.flags() & ABSTRACT) != 0;
1727                 boolean m2Abstract = (m2.flags() & ABSTRACT) != 0;
1728                 if (m1Abstract && !m2Abstract) return m2;
1729                 if (m2Abstract && !m1Abstract) return m1;
1730                 // both abstract or both concrete
1731                 return ambiguityError(m1, m2);
1732             }
1733             if (m1SignatureMoreSpecific) return m1;
1734             if (m2SignatureMoreSpecific) return m2;
1735             return ambiguityError(m1, m2);
1736         case AMBIGUOUS:
1737             //compare m1 to ambiguous methods in m2
1738             AmbiguityError e = (AmbiguityError)m2.baseSymbol();
1739             boolean m1MoreSpecificThanAnyAmbiguous = true;
1740             boolean allAmbiguousMoreSpecificThanM1 = true;
1741             for (Symbol s : e.ambiguousSyms) {
1742                 Symbol moreSpecific = mostSpecific(argtypes, m1, s, env, site, useVarargs);
1743                 m1MoreSpecificThanAnyAmbiguous &= moreSpecific == m1;
1744                 allAmbiguousMoreSpecificThanM1 &= moreSpecific == s;
1745             }
1746             if (m1MoreSpecificThanAnyAmbiguous)
1747                 return m1;
1748             //if m1 is more specific than some ambiguous methods, but other ambiguous methods are
1749             //more specific than m1, add it as a new ambiguous method:
1750             if (!allAmbiguousMoreSpecificThanM1)
1751                 e.addAmbiguousSymbol(m1);
1752             return e;
1753         default:
1754             throw new AssertionError();
1755         }
1756     }
1757     //where
1758     private boolean signatureMoreSpecific(List<Type> actuals, Env<AttrContext> env, Type site, Symbol m1, Symbol m2, boolean useVarargs) {
1759         noteWarner.clear();
1760         int maxLength = Math.max(
1761                             Math.max(m1.type.getParameterTypes().length(), actuals.length()),
1762                             m2.type.getParameterTypes().length());
1763         MethodResolutionContext prevResolutionContext = currentResolutionContext;
1764         try {
1765             currentResolutionContext = new MethodResolutionContext();
1766             currentResolutionContext.step = prevResolutionContext.step;
1767             currentResolutionContext.methodCheck =
1768                     prevResolutionContext.methodCheck.mostSpecificCheck(actuals);
1769             Type mst = instantiate(env, site, m2, null,
1770                     adjustArgs(types.cvarLowerBounds(types.memberType(site, m1).getParameterTypes()), m1, maxLength, useVarargs), null,
1771                     false, useVarargs, noteWarner);
1772             return mst != null &&
1773                     !noteWarner.hasLint(Lint.LintCategory.UNCHECKED);
1774         } finally {
1775             currentResolutionContext = prevResolutionContext;
1776         }
1777     }
1778 
1779     List<Type> adjustArgs(List<Type> args, Symbol msym, int length, boolean allowVarargs) {
1780         if ((msym.flags() & VARARGS) != 0 && allowVarargs) {
1781             Type varargsElem = types.elemtype(args.last());
1782             if (varargsElem == null) {
1783                 Assert.error("Bad varargs = " + args.last() + " " + msym);
1784             }
1785             List<Type> newArgs = args.reverse().tail.prepend(varargsElem).reverse();
1786             while (newArgs.length() < length) {
1787                 newArgs = newArgs.append(newArgs.last());
1788             }
1789             return newArgs;
1790         } else {
1791             return args;
1792         }
1793     }
1794     //where
1795     Symbol ambiguityError(Symbol m1, Symbol m2) {
1796         if (((m1.flags() | m2.flags()) & CLASH) != 0) {
1797             return (m1.flags() & CLASH) == 0 ? m1 : m2;
1798         } else {
1799             return new AmbiguityError(m1, m2);
1800         }
1801     }
1802 
1803     Symbol findMethodInScope(Env<AttrContext> env,
1804             Type site,
1805             Name name,
1806             List<Type> argtypes,
1807             List<Type> typeargtypes,
1808             Scope sc,
1809             Symbol bestSoFar,
1810             boolean allowBoxing,
1811             boolean useVarargs,
1812             boolean abstractok) {
1813         for (Symbol s : sc.getSymbolsByName(name, new LookupFilter(abstractok))) {
1814             bestSoFar = selectBest(env, site, argtypes, typeargtypes, s,
1815                     bestSoFar, allowBoxing, useVarargs);
1816         }
1817         return bestSoFar;
1818     }
1819     //where
1820         class LookupFilter implements Predicate<Symbol> {
1821 
1822             boolean abstractOk;
1823 
1824             LookupFilter(boolean abstractOk) {
1825                 this.abstractOk = abstractOk;
1826             }
1827 
1828             @Override
1829             public boolean test(Symbol s) {
1830                 long flags = s.flags();
1831                 return s.kind == MTH &&
1832                         (flags & SYNTHETIC) == 0 &&
1833                         (abstractOk ||
1834                         (flags & DEFAULT) != 0 ||
1835                         (flags & ABSTRACT) == 0);
1836             }
1837         }
1838 
1839     /** Find best qualified method matching given name, type and value
1840      *  arguments.
1841      *  @param env       The current environment.
1842      *  @param site      The original type from where the selection
1843      *                   takes place.
1844      *  @param name      The method's name.
1845      *  @param argtypes  The method's value arguments.
1846      *  @param typeargtypes The method's type arguments
1847      *  @param allowBoxing Allow boxing conversions of arguments.
1848      *  @param useVarargs Box trailing arguments into an array for varargs.
1849      */
1850     Symbol findMethod(Env<AttrContext> env,
1851                       Type site,
1852                       Name name,
1853                       List<Type> argtypes,
1854                       List<Type> typeargtypes,
1855                       boolean allowBoxing,
1856                       boolean useVarargs) {
1857         Symbol bestSoFar = methodNotFound;
1858         bestSoFar = findMethod(env,
1859                           site,
1860                           name,
1861                           argtypes,
1862                           typeargtypes,
1863                           site.tsym.type,
1864                           bestSoFar,
1865                           allowBoxing,
1866                           useVarargs);
1867         if (bestSoFar.kind == AMBIGUOUS) {
1868             AmbiguityError a_err = (AmbiguityError)bestSoFar.baseSymbol();
1869             bestSoFar = a_err.mergeAbstracts(site);
1870         }
1871         return bestSoFar;
1872     }
1873     // where
1874     private Symbol findMethod(Env<AttrContext> env,
1875                               Type site,
1876                               Name name,
1877                               List<Type> argtypes,
1878                               List<Type> typeargtypes,
1879                               Type intype,
1880                               Symbol bestSoFar,
1881                               boolean allowBoxing,
1882                               boolean useVarargs) {
1883         @SuppressWarnings({"unchecked","rawtypes"})
1884         List<Type>[] itypes = (List<Type>[])new List[] { List.<Type>nil(), List.<Type>nil() };
1885 
1886         InterfaceLookupPhase iphase = InterfaceLookupPhase.ABSTRACT_OK;
1887         boolean isInterface = site.tsym.isInterface();
1888         for (TypeSymbol s : isInterface ? List.of(intype.tsym) : superclasses(intype)) {
1889             bestSoFar = findMethodInScope(env, site, name, argtypes, typeargtypes,
1890                     s.members(), bestSoFar, allowBoxing, useVarargs, true);
1891             if (name == names.init) return bestSoFar;
1892             iphase = (iphase == null) ? null : iphase.update(s, this);
1893             if (iphase != null) {
1894                 for (Type itype : types.interfaces(s.type)) {
1895                     itypes[iphase.ordinal()] = types.union(types.closure(itype), itypes[iphase.ordinal()]);
1896                 }
1897             }
1898         }
1899 
1900         Symbol concrete = bestSoFar.kind.isValid() &&
1901                 (bestSoFar.flags() & ABSTRACT) == 0 ?
1902                 bestSoFar : methodNotFound;
1903 
1904         for (InterfaceLookupPhase iphase2 : InterfaceLookupPhase.values()) {
1905             //keep searching for abstract methods
1906             for (Type itype : itypes[iphase2.ordinal()]) {
1907                 if (!itype.isInterface()) continue; //skip j.l.Object (included by Types.closure())
1908                 if (iphase2 == InterfaceLookupPhase.DEFAULT_OK &&
1909                         (itype.tsym.flags() & DEFAULT) == 0) continue;
1910                 bestSoFar = findMethodInScope(env, site, name, argtypes, typeargtypes,
1911                         itype.tsym.members(), bestSoFar, allowBoxing, useVarargs, true);
1912                 if (concrete != bestSoFar &&
1913                     concrete.kind.isValid() &&
1914                     bestSoFar.kind.isValid() &&
1915                         types.isSubSignature(concrete.type, bestSoFar.type)) {
1916                     //this is an hack - as javac does not do full membership checks
1917                     //most specific ends up comparing abstract methods that might have
1918                     //been implemented by some concrete method in a subclass and,
1919                     //because of raw override, it is possible for an abstract method
1920                     //to be more specific than the concrete method - so we need
1921                     //to explicitly call that out (see CR 6178365)
1922                     bestSoFar = concrete;
1923                 }
1924             }
1925         }
1926         if (isInterface && bestSoFar.kind.isResolutionError()) {
1927             bestSoFar = findMethodInScope(env, site, name, argtypes, typeargtypes,
1928                     syms.objectType.tsym.members(), bestSoFar, allowBoxing, useVarargs, true);
1929             if (bestSoFar.kind.isValid()) {
1930                 Symbol baseSymbol = bestSoFar;
1931                 bestSoFar = new MethodSymbol(bestSoFar.flags_field, bestSoFar.name, bestSoFar.type, intype.tsym) {
1932                     @Override
1933                     public Symbol baseSymbol() {
1934                         return baseSymbol;
1935                     }
1936                 };
1937             }
1938         }
1939         return bestSoFar;
1940     }
1941 
1942     enum InterfaceLookupPhase {
1943         ABSTRACT_OK() {
1944             @Override
1945             InterfaceLookupPhase update(Symbol s, Resolve rs) {
1946                 //We should not look for abstract methods if receiver is a concrete class
1947                 //(as concrete classes are expected to implement all abstracts coming
1948                 //from superinterfaces)
1949                 if ((s.flags() & (ABSTRACT | INTERFACE | ENUM)) != 0) {
1950                     return this;
1951                 } else {
1952                     return DEFAULT_OK;
1953                 }
1954             }
1955         },
1956         DEFAULT_OK() {
1957             @Override
1958             InterfaceLookupPhase update(Symbol s, Resolve rs) {
1959                 return this;
1960             }
1961         };
1962 
1963         abstract InterfaceLookupPhase update(Symbol s, Resolve rs);
1964     }
1965 
1966     /**
1967      * Return an Iterable object to scan the superclasses of a given type.
1968      * It's crucial that the scan is done lazily, as we don't want to accidentally
1969      * access more supertypes than strictly needed (as this could trigger completion
1970      * errors if some of the not-needed supertypes are missing/ill-formed).
1971      */
1972     Iterable<TypeSymbol> superclasses(final Type intype) {
1973         return () -> new Iterator<TypeSymbol>() {
1974 
1975             List<TypeSymbol> seen = List.nil();
1976             TypeSymbol currentSym = symbolFor(intype);
1977             TypeSymbol prevSym = null;
1978 
1979             public boolean hasNext() {
1980                 if (currentSym == syms.noSymbol) {
1981                     currentSym = symbolFor(types.supertype(prevSym.type));
1982                 }
1983                 return currentSym != null;
1984             }
1985 
1986             public TypeSymbol next() {
1987                 prevSym = currentSym;
1988                 currentSym = syms.noSymbol;
1989                 Assert.check(prevSym != null || prevSym != syms.noSymbol);
1990                 return prevSym;
1991             }
1992 
1993             public void remove() {
1994                 throw new UnsupportedOperationException();
1995             }
1996 
1997             TypeSymbol symbolFor(Type t) {
1998                 if (!t.hasTag(CLASS) &&
1999                         !t.hasTag(TYPEVAR)) {
2000                     return null;
2001                 }
2002                 t = types.skipTypeVars(t, false);
2003                 if (seen.contains(t.tsym)) {
2004                     //degenerate case in which we have a circular
2005                     //class hierarchy - because of ill-formed classfiles
2006                     return null;
2007                 }
2008                 seen = seen.prepend(t.tsym);
2009                 return t.tsym;
2010             }
2011         };
2012     }
2013 
2014     /** Find unqualified method matching given name, type and value arguments.
2015      *  @param env       The current environment.
2016      *  @param name      The method's name.
2017      *  @param argtypes  The method's value arguments.
2018      *  @param typeargtypes  The method's type arguments.
2019      *  @param allowBoxing Allow boxing conversions of arguments.
2020      *  @param useVarargs Box trailing arguments into an array for varargs.
2021      */
2022     Symbol findFun(Env<AttrContext> env, Name name,
2023                    List<Type> argtypes, List<Type> typeargtypes,
2024                    boolean allowBoxing, boolean useVarargs) {
2025         Symbol bestSoFar = methodNotFound;
2026         Env<AttrContext> env1 = env;
2027         boolean staticOnly = false;
2028         while (env1.outer != null) {
2029             if (isStatic(env1)) staticOnly = true;
2030             Assert.check(env1.info.preferredTreeForDiagnostics == null);
2031             env1.info.preferredTreeForDiagnostics = env.tree;
2032             try {
2033                 Symbol sym = findMethod(
2034                     env1, env1.enclClass.sym.type, name, argtypes, typeargtypes,
2035                     allowBoxing, useVarargs);
2036                 if (sym.exists()) {
2037                     if (sym.kind == MTH &&
2038                             sym.owner.kind == TYP &&
2039                             (sym.flags() & STATIC) == 0) {
2040                         if (staticOnly)
2041                             return new StaticError(sym);
2042                         if (env1.info.ctorPrologue && env1 == env)
2043                             return new RefBeforeCtorCalledError(sym);
2044                     }
2045                     return sym;
2046                 } else {
2047                     bestSoFar = bestOf(bestSoFar, sym);
2048                 }
2049             } finally {
2050                 env1.info.preferredTreeForDiagnostics = null;
2051             }
2052             if ((env1.enclClass.sym.flags() & STATIC) != 0) staticOnly = true;
2053             env1 = env1.outer;
2054         }
2055 
2056         Symbol sym = findMethod(env, syms.predefClass.type, name, argtypes,
2057                                 typeargtypes, allowBoxing, useVarargs);
2058         if (sym.exists())
2059             return sym;
2060 
2061         for (Symbol currentSym : env.toplevel.namedImportScope.getSymbolsByName(name)) {
2062             Symbol origin = env.toplevel.namedImportScope.getOrigin(currentSym).owner;
2063             if (currentSym.kind == MTH) {
2064                 if (currentSym.owner.type != origin.type)
2065                     currentSym = currentSym.clone(origin);
2066                 if (!isAccessible(env, origin.type, currentSym))
2067                     currentSym = new AccessError(env, origin.type, currentSym);
2068                 bestSoFar = selectBest(env, origin.type,
2069                                        argtypes, typeargtypes,
2070                                        currentSym, bestSoFar,
2071                                        allowBoxing, useVarargs);
2072             }
2073         }
2074         if (bestSoFar.exists())
2075             return bestSoFar;
2076 
2077         for (Symbol currentSym : env.toplevel.starImportScope.getSymbolsByName(name)) {
2078             Symbol origin = env.toplevel.starImportScope.getOrigin(currentSym).owner;
2079             if (currentSym.kind == MTH) {
2080                 if (currentSym.owner.type != origin.type)
2081                     currentSym = currentSym.clone(origin);
2082                 if (!isAccessible(env, origin.type, currentSym))
2083                     currentSym = new AccessError(env, origin.type, currentSym);
2084                 bestSoFar = selectBest(env, origin.type,
2085                                        argtypes, typeargtypes,
2086                                        currentSym, bestSoFar,
2087                                        allowBoxing, useVarargs);
2088             }
2089         }
2090         return bestSoFar;
2091     }
2092 
2093     /** Load toplevel or member class with given fully qualified name and
2094      *  verify that it is accessible.
2095      *  @param env       The current environment.
2096      *  @param name      The fully qualified name of the class to be loaded.
2097      */
2098     Symbol loadClass(Env<AttrContext> env, Name name, RecoveryLoadClass recoveryLoadClass) {
2099         try {
2100             ClassSymbol c = finder.loadClass(env.toplevel.modle, name);
2101             return isAccessible(env, c) ? c : new AccessError(env, null, c);
2102         } catch (ClassFinder.BadClassFile err) {
2103             return new BadClassFileError(err);
2104         } catch (CompletionFailure ex) {
2105             Symbol candidate = recoveryLoadClass.loadClass(env, name);
2106 
2107             if (candidate != null) {
2108                 return candidate;
2109             }
2110 
2111             return typeNotFound;
2112         }
2113     }
2114 
2115     public interface RecoveryLoadClass {
2116         Symbol loadClass(Env<AttrContext> env, Name name);
2117     }
2118 
2119     private final RecoveryLoadClass noRecovery = (env, name) -> null;
2120 
2121     private final RecoveryLoadClass doRecoveryLoadClass = new RecoveryLoadClass() {
2122         @Override public Symbol loadClass(Env<AttrContext> env, Name name) {
2123             List<Name> candidates = Convert.classCandidates(name);
2124             return lookupInvisibleSymbol(env, name,
2125                                          n -> () -> createCompoundIterator(candidates,
2126                                                                            c -> syms.getClassesForName(c)
2127                                                                                     .iterator()),
2128                                          (ms, n) -> {
2129                 for (Name candidate : candidates) {
2130                     try {
2131                         return finder.loadClass(ms, candidate);
2132                     } catch (CompletionFailure cf) {
2133                         //ignore
2134                     }
2135                 }
2136                 return null;
2137             }, sym -> sym.kind == Kind.TYP, typeNotFound);
2138         }
2139     };
2140 
2141     private final RecoveryLoadClass namedImportScopeRecovery = (env, name) -> {
2142         Scope importScope = env.toplevel.namedImportScope;
2143         Symbol existing = importScope.findFirst(Convert.shortName(name),
2144                                                 sym -> sym.kind == TYP && sym.flatName() == name);
2145 
2146         if (existing != null) {
2147             return new InvisibleSymbolError(env, true, existing);
2148         }
2149         return null;
2150     };
2151 
2152     private final RecoveryLoadClass starImportScopeRecovery =
2153             onDemandImportScopeRecovery(false);
2154 
2155     private final RecoveryLoadClass moduleImportScopeRecovery =
2156             onDemandImportScopeRecovery(true);
2157 
2158     private RecoveryLoadClass onDemandImportScopeRecovery(boolean moduleImportScope) {
2159         return (env, name) -> {
2160             Scope importScope = moduleImportScope ? env.toplevel.moduleImportScope
2161                                                   : env.toplevel.starImportScope;
2162             Symbol existing = importScope.findFirst(Convert.shortName(name),
2163                                                     sym -> sym.kind == TYP && sym.flatName() == name);
2164 
2165             if (existing != null) {
2166                 try {
2167                     existing = finder.loadClass(existing.packge().modle, name);
2168 
2169                     return new InvisibleSymbolError(env, true, existing);
2170                 } catch (CompletionFailure cf) {
2171                     //ignore
2172                 }
2173             }
2174 
2175             return null;
2176         };
2177     }
2178 
2179     Symbol lookupPackage(Env<AttrContext> env, Name name) {
2180         PackageSymbol pack = syms.lookupPackage(env.toplevel.modle, name);
2181 
2182         if (allowModules && isImportOnDemand(env, name)) {
2183             if (pack.members().isEmpty()) {
2184                 return lookupInvisibleSymbol(env, name, syms::getPackagesForName, syms::enterPackage, sym -> {
2185                     sym.complete();
2186                     return !sym.members().isEmpty();
2187                 }, pack);
2188             }
2189         }
2190 
2191         return pack;
2192     }
2193 
2194     private boolean isImportOnDemand(Env<AttrContext> env, Name name) {
2195         if (!env.tree.hasTag(IMPORT))
2196             return false;
2197 
2198         JCTree qualid = ((JCImport) env.tree).qualid;
2199 
2200         if (!qualid.hasTag(SELECT))
2201             return false;
2202 
2203         if (TreeInfo.name(qualid) != names.asterisk)
2204             return false;
2205 
2206         return TreeInfo.fullName(((JCFieldAccess) qualid).selected) == name;
2207     }
2208 
2209     private <S extends Symbol> Symbol lookupInvisibleSymbol(Env<AttrContext> env,
2210                                                             Name name,
2211                                                             Function<Name, Iterable<S>> get,
2212                                                             BiFunction<ModuleSymbol, Name, S> load,
2213                                                             Predicate<S> validate,
2214                                                             Symbol defaultResult) {
2215         //even if a class/package cannot be found in the current module and among packages in modules
2216         //it depends on that are exported for any or this module, the class/package may exist internally
2217         //in some of these modules, or may exist in a module on which this module does not depend.
2218         //Provide better diagnostic in such cases by looking for the class in any module:
2219         Iterable<? extends S> candidates = get.apply(name);
2220 
2221         for (S sym : candidates) {
2222             if (validate.test(sym))
2223                 return createInvisibleSymbolError(env, sym);
2224         }
2225 
2226         Set<ModuleSymbol> recoverableModules = new HashSet<>(syms.getAllModules());
2227 
2228         recoverableModules.add(syms.unnamedModule);
2229         recoverableModules.remove(env.toplevel.modle);
2230 
2231         for (ModuleSymbol ms : recoverableModules) {
2232             //avoid overly eager completing classes from source-based modules, as those
2233             //may not be completable with the current compiler settings:
2234             if (ms.sourceLocation == null) {
2235                 if (ms.classLocation == null) {
2236                     ms = moduleFinder.findModule(ms);
2237                 }
2238 
2239                 if (ms.kind != ERR) {
2240                     S sym = load.apply(ms, name);
2241 
2242                     if (sym != null && validate.test(sym)) {
2243                         return createInvisibleSymbolError(env, sym);
2244                     }
2245                 }
2246             }
2247         }
2248 
2249         return defaultResult;
2250     }
2251 
2252     private Symbol createInvisibleSymbolError(Env<AttrContext> env, Symbol sym) {
2253         if (symbolPackageVisible(env, sym)) {
2254             return new AccessError(env, null, sym);
2255         } else {
2256             return new InvisibleSymbolError(env, false, sym);
2257         }
2258     }
2259 
2260     private boolean symbolPackageVisible(Env<AttrContext> env, Symbol sym) {
2261         ModuleSymbol envMod = env.toplevel.modle;
2262         PackageSymbol symPack = sym.packge();
2263         return envMod == symPack.modle ||
2264                envMod.visiblePackages.containsKey(symPack.fullname);
2265     }
2266 
2267     /**
2268      * Find a type declared in a scope (not inherited).  Return null
2269      * if none is found.
2270      *  @param env       The current environment.
2271      *  @param site      The original type from where the selection takes
2272      *                   place.
2273      *  @param name      The type's name.
2274      *  @param c         The class to search for the member type. This is
2275      *                   always a superclass or implemented interface of
2276      *                   site's class.
2277      */
2278     Symbol findImmediateMemberType(Env<AttrContext> env,
2279                                    Type site,
2280                                    Name name,
2281                                    TypeSymbol c) {
2282         for (Symbol sym : c.members().getSymbolsByName(name)) {
2283             if (sym.kind == TYP) {
2284                 return isAccessible(env, site, sym)
2285                     ? sym
2286                     : new AccessError(env, site, sym);
2287             }
2288         }
2289         return typeNotFound;
2290     }
2291 
2292     /** Find a member type inherited from a superclass or interface.
2293      *  @param env       The current environment.
2294      *  @param site      The original type from where the selection takes
2295      *                   place.
2296      *  @param name      The type's name.
2297      *  @param c         The class to search for the member type. This is
2298      *                   always a superclass or implemented interface of
2299      *                   site's class.
2300      */
2301     Symbol findInheritedMemberType(Env<AttrContext> env,
2302                                    Type site,
2303                                    Name name,
2304                                    TypeSymbol c) {
2305         Symbol bestSoFar = typeNotFound;
2306         Symbol sym;
2307         Type st = types.supertype(c.type);
2308         if (st != null && st.hasTag(CLASS)) {
2309             sym = findMemberType(env, site, name, st.tsym);
2310             bestSoFar = bestOf(bestSoFar, sym);
2311         }
2312         for (List<Type> l = types.interfaces(c.type);
2313              bestSoFar.kind != AMBIGUOUS && l.nonEmpty();
2314              l = l.tail) {
2315             sym = findMemberType(env, site, name, l.head.tsym);
2316             if (!bestSoFar.kind.isResolutionError() &&
2317                 !sym.kind.isResolutionError() &&
2318                 sym.owner != bestSoFar.owner)
2319                 bestSoFar = new AmbiguityError(bestSoFar, sym);
2320             else
2321                 bestSoFar = bestOf(bestSoFar, sym);
2322         }
2323         return bestSoFar;
2324     }
2325 
2326     /** Find qualified member type.
2327      *  @param env       The current environment.
2328      *  @param site      The original type from where the selection takes
2329      *                   place.
2330      *  @param name      The type's name.
2331      *  @param c         The class to search for the member type. This is
2332      *                   always a superclass or implemented interface of
2333      *                   site's class.
2334      */
2335     Symbol findMemberType(Env<AttrContext> env,
2336                           Type site,
2337                           Name name,
2338                           TypeSymbol c) {
2339         Symbol sym = findImmediateMemberType(env, site, name, c);
2340 
2341         if (sym != typeNotFound)
2342             return sym;
2343 
2344         return findInheritedMemberType(env, site, name, c);
2345 
2346     }
2347 
2348     /** Find a global type in given scope and load corresponding class.
2349      *  @param env       The current environment.
2350      *  @param scope     The scope in which to look for the type.
2351      *  @param name      The type's name.
2352      */
2353     Symbol findGlobalType(Env<AttrContext> env, Scope scope, Name name, RecoveryLoadClass recoveryLoadClass) {
2354         Symbol bestSoFar = typeNotFound;
2355         for (Symbol s : scope.getSymbolsByName(name)) {
2356             Symbol sym = loadClass(env, s.flatName(), recoveryLoadClass);
2357             if (bestSoFar.kind == TYP && sym.kind == TYP &&
2358                 bestSoFar != sym) {
2359                 return new AmbiguityError(bestSoFar, sym);
2360             } else if (env.toplevel.namedImportScope == scope &&
2361                     ((sym == typeNotFound && s.kind.matches(KindSelector.TYP)) ||
2362                     (sym.kind == ERR && s.kind == ERR))) {
2363                 bestSoFar = bestOf(bestSoFar, new UnresolvableGlobalSymbolError(s));
2364             } else
2365                 bestSoFar = bestOf(bestSoFar, sym);
2366         }
2367         return bestSoFar;
2368     }
2369 
2370     Symbol findTypeVar(Env<AttrContext> env, Name name, boolean staticOnly) {
2371         for (Symbol sym : env.info.scope.getSymbolsByName(name)) {
2372             if (sym.kind == TYP) {
2373                 if (sym.type.hasTag(TYPEVAR) &&
2374                         (staticOnly || (isStatic(env) && sym.owner.kind == TYP)))
2375                     // if staticOnly is set, it means that we have recursed through a static declaration,
2376                     // so type variable symbols should not be accessible. If staticOnly is unset, but
2377                     // we are in a static declaration (field or method), we should not allow type-variables
2378                     // defined in the enclosing class to "leak" into this context.
2379                     return new StaticError(sym);
2380                 return sym;
2381             }
2382         }
2383         return typeNotFound;
2384     }
2385 
2386     /** Find an unqualified type symbol.
2387      *  @param env       The current environment.
2388      *  @param name      The type's name.
2389      */
2390     Symbol findType(Env<AttrContext> env, Name name) {
2391         if (name == names.empty)
2392             return typeNotFound; // do not allow inadvertent "lookup" of anonymous types
2393         Symbol bestSoFar = typeNotFound;
2394         Symbol sym;
2395         boolean staticOnly = false;
2396         for (Env<AttrContext> env1 = env; env1.outer != null; env1 = env1.outer) {
2397             // First, look for a type variable and the first member type
2398             final Symbol tyvar = findTypeVar(env1, name, staticOnly);
2399             if (isStatic(env1)) staticOnly = true;
2400             sym = findImmediateMemberType(env1, env1.enclClass.sym.type,
2401                                           name, env1.enclClass.sym);
2402 
2403             // Return the type variable if we have it, and have no
2404             // immediate member, OR the type variable is for a method.
2405             if (tyvar != typeNotFound) {
2406                 if (env.baseClause || sym == typeNotFound ||
2407                     (tyvar.kind == TYP && tyvar.exists() &&
2408                      tyvar.owner.kind == MTH)) {
2409                     return tyvar;
2410                 }
2411             }
2412 
2413             // If the environment is a class def, finish up,
2414             // otherwise, do the entire findMemberType
2415             if (sym == typeNotFound)
2416                 sym = findInheritedMemberType(env1, env1.enclClass.sym.type,
2417                                               name, env1.enclClass.sym);
2418 
2419             if (staticOnly && sym.kind == TYP &&
2420                 sym.type.hasTag(CLASS) &&
2421                 sym.type.getEnclosingType().hasTag(CLASS) &&
2422                 env1.enclClass.sym.type.isParameterized() &&
2423                 sym.type.getEnclosingType().isParameterized())
2424                 return new StaticError(sym);
2425             else if (sym.exists()) return sym;
2426             else bestSoFar = bestOf(bestSoFar, sym);
2427 
2428             JCClassDecl encl = env1.baseClause ? (JCClassDecl)env1.tree : env1.enclClass;
2429             if ((encl.sym.flags() & STATIC) != 0)
2430                 staticOnly = true;
2431         }
2432 
2433         if (!env.tree.hasTag(IMPORT)) {
2434             sym = findGlobalType(env, env.toplevel.namedImportScope, name, namedImportScopeRecovery);
2435             if (sym.exists()) return sym;
2436             else bestSoFar = bestOf(bestSoFar, sym);
2437 
2438             sym = findGlobalType(env, env.toplevel.toplevelScope, name, noRecovery);
2439             if (sym.exists()) return sym;
2440             else bestSoFar = bestOf(bestSoFar, sym);
2441 
2442             sym = findGlobalType(env, env.toplevel.packge.members(), name, noRecovery);
2443             if (sym.exists()) return sym;
2444             else bestSoFar = bestOf(bestSoFar, sym);
2445 
2446             sym = findGlobalType(env, env.toplevel.starImportScope, name, starImportScopeRecovery);
2447             if (sym.exists()) return sym;
2448             else bestSoFar = bestOf(bestSoFar, sym);
2449 
2450             sym = findGlobalType(env, env.toplevel.moduleImportScope, name, moduleImportScopeRecovery);
2451             if (sym.exists()) return sym;
2452 
2453             else bestSoFar = bestOf(bestSoFar, sym);
2454         }
2455 
2456         return bestSoFar;
2457     }
2458 
2459     /** Find an unqualified identifier which matches a specified kind set.
2460      *  @param pos       position on which report warnings, if any;
2461      *                   null warnings should not be reported
2462      *  @param env       The current environment.
2463      *  @param name      The identifier's name.
2464      *  @param kind      Indicates the possible symbol kinds
2465      *                   (a subset of VAL, TYP, PCK).
2466      */
2467     Symbol findIdent(DiagnosticPosition pos, Env<AttrContext> env, Name name, KindSelector kind) {
2468         try {
2469             return checkNonExistentType(checkRestrictedType(pos, findIdentInternal(pos, env, name, kind), name));
2470         } catch (ClassFinder.BadClassFile err) {
2471             return new BadClassFileError(err);
2472         } catch (CompletionFailure cf) {
2473             chk.completionError(pos, cf);
2474             return typeNotFound;
2475         }
2476     }
2477 
2478     Symbol findIdentInternal(DiagnosticPosition pos, Env<AttrContext> env, Name name, KindSelector kind) {
2479         Symbol bestSoFar = typeNotFound;
2480         Symbol sym;
2481 
2482         if (kind.contains(KindSelector.VAL)) {
2483             sym = findVar(pos, env, name);
2484             if (sym.exists()) return sym;
2485             else bestSoFar = bestOf(bestSoFar, sym);
2486         }
2487 
2488         if (kind.contains(KindSelector.TYP)) {
2489             sym = findType(env, name);
2490             if (sym.exists()) return sym;
2491             else bestSoFar = bestOf(bestSoFar, sym);
2492         }
2493 
2494         if (kind.contains(KindSelector.PCK))
2495             return lookupPackage(env, name);
2496         else return bestSoFar;
2497     }
2498 
2499     /** Find an identifier in a package which matches a specified kind set.
2500      *  @param pos       position on which report warnings, if any;
2501      *                   null warnings should not be reported
2502      *  @param env       The current environment.
2503      *  @param name      The identifier's name.
2504      *  @param kind      Indicates the possible symbol kinds
2505      *                   (a nonempty subset of TYP, PCK).
2506      */
2507     Symbol findIdentInPackage(DiagnosticPosition pos,
2508                               Env<AttrContext> env, TypeSymbol pck,
2509                               Name name, KindSelector kind) {
2510         return checkNonExistentType(checkRestrictedType(pos, findIdentInPackageInternal(env, pck, name, kind), name));
2511     }
2512 
2513     Symbol findIdentInPackageInternal(Env<AttrContext> env, TypeSymbol pck,
2514                               Name name, KindSelector kind) {
2515         Name fullname = TypeSymbol.formFullName(name, pck);
2516         Symbol bestSoFar = typeNotFound;
2517         if (kind.contains(KindSelector.TYP)) {
2518             RecoveryLoadClass recoveryLoadClass =
2519                     allowModules && !kind.contains(KindSelector.PCK) &&
2520                     !pck.exists() && !env.info.attributionMode.isSpeculative ?
2521                         doRecoveryLoadClass : noRecovery;
2522             Symbol sym = loadClass(env, fullname, recoveryLoadClass);
2523             if (sym.exists()) {
2524                 // don't allow programs to use flatnames
2525                 if (name == sym.name) return sym;
2526             }
2527             else bestSoFar = bestOf(bestSoFar, sym);
2528         }
2529         if (kind.contains(KindSelector.PCK)) {
2530             return lookupPackage(env, fullname);
2531         }
2532         return bestSoFar;
2533     }
2534 
2535     /** Find an identifier among the members of a given type `site'.
2536      *  @param pos       position on which report warnings, if any;
2537      *                   null warnings should not be reported
2538      *  @param env       The current environment.
2539      *  @param site      The type containing the symbol to be found.
2540      *  @param name      The identifier's name.
2541      *  @param kind      Indicates the possible symbol kinds
2542      *                   (a subset of VAL, TYP).
2543      */
2544     Symbol findIdentInType(DiagnosticPosition pos,
2545                            Env<AttrContext> env, Type site,
2546                            Name name, KindSelector kind) {
2547         try {
2548             return checkNonExistentType(checkRestrictedType(pos, findIdentInTypeInternal(env, site, name, kind), name));
2549         } catch (ClassFinder.BadClassFile err) {
2550             return new BadClassFileError(err);
2551         } catch (CompletionFailure cf) {
2552             chk.completionError(pos, cf);
2553             return typeNotFound;
2554         }
2555     }
2556 
2557     private Symbol checkNonExistentType(Symbol symbol) {
2558         /*  Guard against returning a type is not on the class path of the current compilation,
2559          *  but *was* on the class path of a separate compilation that produced a class file
2560          *  that is on the class path of the current compilation. Such a type will fail completion
2561          *  but the completion failure may have been silently swallowed (e.g. missing annotation types)
2562          *  with an error stub symbol lingering in the symbol tables.
2563          */
2564         return symbol instanceof ClassSymbol c && c.type.isErroneous() && c.classfile == null ? typeNotFound : symbol;
2565     }
2566 
2567     Symbol findIdentInTypeInternal(Env<AttrContext> env, Type site,
2568                            Name name, KindSelector kind) {
2569         Symbol bestSoFar = typeNotFound;
2570         Symbol sym;
2571         if (kind.contains(KindSelector.VAL)) {
2572             sym = findField(env, site, name, site.tsym);
2573             if (sym.exists()) return sym;
2574             else bestSoFar = bestOf(bestSoFar, sym);
2575         }
2576 
2577         if (kind.contains(KindSelector.TYP)) {
2578             sym = findMemberType(env, site, name, site.tsym);
2579             if (sym.exists()) return sym;
2580             else bestSoFar = bestOf(bestSoFar, sym);
2581         }
2582         return bestSoFar;
2583     }
2584 
2585     private Symbol checkRestrictedType(DiagnosticPosition pos, Symbol bestSoFar, Name name) {
2586         if (bestSoFar.kind == TYP || bestSoFar.kind == ABSENT_TYP) {
2587             if (allowLocalVariableTypeInference && name.equals(names.var)) {
2588                 bestSoFar = new BadRestrictedTypeError(names.var);
2589             } else if (name.equals(names.yield)) {
2590                 if (allowYieldStatement) {
2591                     bestSoFar = new BadRestrictedTypeError(names.yield);
2592                 } else if (pos != null) {
2593                     log.warning(pos, Warnings.IllegalRefToRestrictedType(names.yield));
2594                 }
2595             }
2596         }
2597         return bestSoFar;
2598     }
2599 
2600 /* ***************************************************************************
2601  *  Access checking
2602  *  The following methods convert ResolveErrors to ErrorSymbols, issuing
2603  *  an error message in the process
2604  ****************************************************************************/
2605 
2606     /** If `sym' is a bad symbol: report error and return errSymbol
2607      *  else pass through unchanged,
2608      *  additional arguments duplicate what has been used in trying to find the
2609      *  symbol {@literal (--> flyweight pattern)}. This improves performance since we
2610      *  expect misses to happen frequently.
2611      *
2612      *  @param sym       The symbol that was found, or a ResolveError.
2613      *  @param pos       The position to use for error reporting.
2614      *  @param location  The symbol the served as a context for this lookup
2615      *  @param site      The original type from where the selection took place.
2616      *  @param name      The symbol's name.
2617      *  @param qualified Did we get here through a qualified expression resolution?
2618      *  @param argtypes  The invocation's value arguments,
2619      *                   if we looked for a method.
2620      *  @param typeargtypes  The invocation's type arguments,
2621      *                   if we looked for a method.
2622      *  @param logResolveHelper helper class used to log resolve errors
2623      */
2624     Symbol accessInternal(Symbol sym,
2625                   DiagnosticPosition pos,
2626                   Symbol location,
2627                   Type site,
2628                   Name name,
2629                   boolean qualified,
2630                   List<Type> argtypes,
2631                   List<Type> typeargtypes,
2632                   LogResolveHelper logResolveHelper) {
2633         if (sym.kind.isResolutionError()) {
2634             ResolveError errSym = (ResolveError)sym.baseSymbol();
2635             sym = errSym.access(name, qualified ? site.tsym : syms.noSymbol);
2636             argtypes = logResolveHelper.getArgumentTypes(errSym, sym, name, argtypes);
2637             if (logResolveHelper.resolveDiagnosticNeeded(site, argtypes, typeargtypes)) {
2638                 logResolveError(errSym, pos, location, site, name, argtypes, typeargtypes);
2639             }
2640         }
2641         return sym;
2642     }
2643 
2644     /**
2645      * Variant of the generalized access routine, to be used for generating method
2646      * resolution diagnostics
2647      */
2648     Symbol accessMethod(Symbol sym,
2649                   DiagnosticPosition pos,
2650                   Symbol location,
2651                   Type site,
2652                   Name name,
2653                   boolean qualified,
2654                   List<Type> argtypes,
2655                   List<Type> typeargtypes) {
2656         return accessInternal(sym, pos, location, site, name, qualified, argtypes, typeargtypes, methodLogResolveHelper);
2657     }
2658 
2659     /** Same as original accessMethod(), but without location.
2660      */
2661     Symbol accessMethod(Symbol sym,
2662                   DiagnosticPosition pos,
2663                   Type site,
2664                   Name name,
2665                   boolean qualified,
2666                   List<Type> argtypes,
2667                   List<Type> typeargtypes) {
2668         return accessMethod(sym, pos, site.tsym, site, name, qualified, argtypes, typeargtypes);
2669     }
2670 
2671     /**
2672      * Variant of the generalized access routine, to be used for generating variable,
2673      * type resolution diagnostics
2674      */
2675     Symbol accessBase(Symbol sym,
2676                   DiagnosticPosition pos,
2677                   Symbol location,
2678                   Type site,
2679                   Name name,
2680                   boolean qualified) {
2681         return accessInternal(sym, pos, location, site, name, qualified, List.nil(), null, basicLogResolveHelper);
2682     }
2683 
2684     /** Same as original accessBase(), but without location.
2685      */
2686     Symbol accessBase(Symbol sym,
2687                   DiagnosticPosition pos,
2688                   Type site,
2689                   Name name,
2690                   boolean qualified) {
2691         return accessBase(sym, pos, site.tsym, site, name, qualified);
2692     }
2693 
2694     interface LogResolveHelper {
2695         boolean resolveDiagnosticNeeded(Type site, List<Type> argtypes, List<Type> typeargtypes);
2696         List<Type> getArgumentTypes(ResolveError errSym, Symbol accessedSym, Name name, List<Type> argtypes);
2697     }
2698 
2699     LogResolveHelper basicLogResolveHelper = new LogResolveHelper() {
2700         public boolean resolveDiagnosticNeeded(Type site, List<Type> argtypes, List<Type> typeargtypes) {
2701             return !site.isErroneous();
2702         }
2703         public List<Type> getArgumentTypes(ResolveError errSym, Symbol accessedSym, Name name, List<Type> argtypes) {
2704             return argtypes;
2705         }
2706     };
2707 
2708     LogResolveHelper silentLogResolveHelper = new LogResolveHelper() {
2709         public boolean resolveDiagnosticNeeded(Type site, List<Type> argtypes, List<Type> typeargtypes) {
2710             return false;
2711         }
2712         public List<Type> getArgumentTypes(ResolveError errSym, Symbol accessedSym, Name name, List<Type> argtypes) {
2713             return argtypes;
2714         }
2715     };
2716 
2717     LogResolveHelper methodLogResolveHelper = new LogResolveHelper() {
2718         public boolean resolveDiagnosticNeeded(Type site, List<Type> argtypes, List<Type> typeargtypes) {
2719             return !site.isErroneous() &&
2720                         !Type.isErroneous(argtypes) &&
2721                         (typeargtypes == null || !Type.isErroneous(typeargtypes));
2722         }
2723         public List<Type> getArgumentTypes(ResolveError errSym, Symbol accessedSym, Name name, List<Type> argtypes) {
2724             return argtypes.map(new ResolveDeferredRecoveryMap(AttrMode.SPECULATIVE, accessedSym, currentResolutionContext.step));
2725         }
2726     };
2727 
2728     class ResolveDeferredRecoveryMap extends DeferredAttr.RecoveryDeferredTypeMap {
2729 
2730         public ResolveDeferredRecoveryMap(AttrMode mode, Symbol msym, MethodResolutionPhase step) {
2731             deferredAttr.super(mode, msym, step);
2732         }
2733 
2734         @Override
2735         protected Type typeOf(DeferredType dt, Type pt) {
2736             Type res = super.typeOf(dt, pt);
2737             if (!res.isErroneous()) {
2738                 switch (TreeInfo.skipParens(dt.tree).getTag()) {
2739                     case LAMBDA:
2740                     case REFERENCE:
2741                         return dt;
2742                     case CONDEXPR:
2743                         return res == Type.recoveryType ?
2744                                 dt : res;
2745                 }
2746             }
2747             return res;
2748         }
2749     }
2750 
2751     /** Check that sym is not an abstract method.
2752      */
2753     void checkNonAbstract(DiagnosticPosition pos, Symbol sym) {
2754         if ((sym.flags() & ABSTRACT) != 0 && (sym.flags() & DEFAULT) == 0)
2755             log.error(pos,
2756                       Errors.AbstractCantBeAccessedDirectly(kindName(sym),sym, sym.location()));
2757     }
2758 
2759 /* ***************************************************************************
2760  *  Name resolution
2761  *  Naming conventions are as for symbol lookup
2762  *  Unlike the find... methods these methods will report access errors
2763  ****************************************************************************/
2764 
2765     /** Resolve an unqualified (non-method) identifier.
2766      *  @param pos       The position to use for error reporting.
2767      *  @param env       The environment current at the identifier use.
2768      *  @param name      The identifier's name.
2769      *  @param kind      The set of admissible symbol kinds for the identifier.
2770      */
2771     Symbol resolveIdent(DiagnosticPosition pos, Env<AttrContext> env,
2772                         Name name, KindSelector kind) {
2773         return accessBase(
2774             findIdent(pos, env, name, kind),
2775             pos, env.enclClass.sym.type, name, false);
2776     }
2777 
2778     /** Resolve an unqualified method identifier.
2779      *  @param pos       The position to use for error reporting.
2780      *  @param env       The environment current at the method invocation.
2781      *  @param name      The identifier's name.
2782      *  @param argtypes  The types of the invocation's value arguments.
2783      *  @param typeargtypes  The types of the invocation's type arguments.
2784      */
2785     Symbol resolveMethod(DiagnosticPosition pos,
2786                          Env<AttrContext> env,
2787                          Name name,
2788                          List<Type> argtypes,
2789                          List<Type> typeargtypes) {
2790         return lookupMethod(env, pos, env.enclClass.sym, resolveMethodCheck,
2791                 new BasicLookupHelper(name, env.enclClass.sym.type, argtypes, typeargtypes) {
2792                     @Override
2793                     Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) {
2794                         return findFun(env, name, argtypes, typeargtypes,
2795                                 phase.isBoxingRequired(),
2796                                 phase.isVarargsRequired());
2797                     }});
2798     }
2799 
2800     /** Resolve a qualified method identifier
2801      *  @param pos       The position to use for error reporting.
2802      *  @param env       The environment current at the method invocation.
2803      *  @param site      The type of the qualifying expression, in which
2804      *                   identifier is searched.
2805      *  @param name      The identifier's name.
2806      *  @param argtypes  The types of the invocation's value arguments.
2807      *  @param typeargtypes  The types of the invocation's type arguments.
2808      */
2809     Symbol resolveQualifiedMethod(DiagnosticPosition pos, Env<AttrContext> env,
2810                                   Type site, Name name, List<Type> argtypes,
2811                                   List<Type> typeargtypes) {
2812         return resolveQualifiedMethod(pos, env, site.tsym, site, name, argtypes, typeargtypes);
2813     }
2814     Symbol resolveQualifiedMethod(DiagnosticPosition pos, Env<AttrContext> env,
2815                                   Symbol location, Type site, Name name, List<Type> argtypes,
2816                                   List<Type> typeargtypes) {
2817         try {
2818             return resolveQualifiedMethod(new MethodResolutionContext(), pos, env, location, site, name, argtypes, typeargtypes);
2819         } catch (CompletionFailure cf) {
2820             chk.completionError(pos, cf);
2821             return methodNotFound.access(name, site.tsym);
2822         }
2823     }
2824     private Symbol resolveQualifiedMethod(MethodResolutionContext resolveContext,
2825                                   DiagnosticPosition pos, Env<AttrContext> env,
2826                                   Symbol location, Type site, Name name, List<Type> argtypes,
2827                                   List<Type> typeargtypes) {
2828         return lookupMethod(env, pos, location, resolveContext, new BasicLookupHelper(name, site, argtypes, typeargtypes) {
2829             @Override
2830             Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) {
2831                 return findMethod(env, site, name, argtypes, typeargtypes,
2832                         phase.isBoxingRequired(),
2833                         phase.isVarargsRequired());
2834             }
2835             @Override
2836             Symbol access(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, Symbol sym) {
2837                 if (sym.kind.isResolutionError()) {
2838                     sym = super.access(env, pos, location, sym);
2839                 } else {
2840                     MethodSymbol msym = (MethodSymbol)sym;
2841                     if ((msym.flags() & SIGNATURE_POLYMORPHIC) != 0) {
2842                         env.info.pendingResolutionPhase = BASIC;
2843                         return findPolymorphicSignatureInstance(env, sym, argtypes);
2844                     }
2845                 }
2846                 return sym;
2847             }
2848         });
2849     }
2850 
2851     /** Find or create an implicit method of exactly the given type (after erasure).
2852      *  Searches in a side table, not the main scope of the site.
2853      *  This emulates the lookup process required by JSR 292 in JVM.
2854      *  @param env       Attribution environment
2855      *  @param spMethod  signature polymorphic method - i.e. MH.invokeExact
2856      *  @param argtypes  The required argument types
2857      */
2858     Symbol findPolymorphicSignatureInstance(Env<AttrContext> env,
2859                                             final Symbol spMethod,
2860                                             List<Type> argtypes) {
2861         Type mtype = infer.instantiatePolymorphicSignatureInstance(env,
2862                 (MethodSymbol)spMethod, currentResolutionContext, argtypes);
2863         return findPolymorphicSignatureInstance(spMethod, mtype);
2864     }
2865 
2866     Symbol findPolymorphicSignatureInstance(final Symbol spMethod,
2867                                             Type mtype) {
2868         for (Symbol sym : polymorphicSignatureScope.getSymbolsByName(spMethod.name)) {
2869             // Check that there is already a method symbol for the method
2870             // type and owner
2871             if (types.isSameType(mtype, sym.type) &&
2872                 spMethod.owner == sym.owner) {
2873                 return sym;
2874             }
2875         }
2876 
2877         Type spReturnType = spMethod.asType().getReturnType();
2878         if (types.isSameType(spReturnType, syms.objectType)) {
2879             // Polymorphic return, pass through mtype
2880         } else if (!types.isSameType(spReturnType, mtype.getReturnType())) {
2881             // Retain the sig poly method's return type, which differs from that of mtype
2882             // Will result in an incompatible return type error
2883             mtype = new MethodType(mtype.getParameterTypes(),
2884                     spReturnType,
2885                     mtype.getThrownTypes(),
2886                     syms.methodClass);
2887         }
2888 
2889         // Create the desired method
2890         // Retain static modifier is to support invocations to
2891         // MethodHandle.linkTo* methods
2892         long flags = ABSTRACT | HYPOTHETICAL |
2893                      spMethod.flags() & (Flags.AccessFlags | Flags.STATIC);
2894         Symbol msym = new MethodSymbol(flags, spMethod.name, mtype, spMethod.owner) {
2895             @Override
2896             public Symbol baseSymbol() {
2897                 return spMethod;
2898             }
2899         };
2900         if (!mtype.isErroneous()) { // Cache only if kosher.
2901             polymorphicSignatureScope.enter(msym);
2902         }
2903         return msym;
2904     }
2905 
2906     /** Resolve a qualified method identifier, throw a fatal error if not
2907      *  found.
2908      *  @param pos       The position to use for error reporting.
2909      *  @param env       The environment current at the method invocation.
2910      *  @param site      The type of the qualifying expression, in which
2911      *                   identifier is searched.
2912      *  @param name      The identifier's name.
2913      *  @param argtypes  The types of the invocation's value arguments.
2914      *  @param typeargtypes  The types of the invocation's type arguments.
2915      */
2916     public MethodSymbol resolveInternalMethod(DiagnosticPosition pos, Env<AttrContext> env,
2917                                         Type site, Name name,
2918                                         List<Type> argtypes,
2919                                         List<Type> typeargtypes) {
2920         MethodResolutionContext resolveContext = new MethodResolutionContext();
2921         resolveContext.internalResolution = true;
2922         Symbol sym = resolveQualifiedMethod(resolveContext, pos, env, site.tsym,
2923                 site, name, argtypes, typeargtypes);
2924         if (sym.kind == MTH) return (MethodSymbol)sym;
2925         else throw new FatalError(
2926                  diags.fragment(Fragments.FatalErrCantLocateMeth(name)));
2927     }
2928 
2929     /** Resolve constructor.
2930      *  @param pos       The position to use for error reporting.
2931      *  @param env       The environment current at the constructor invocation.
2932      *  @param site      The type of class for which a constructor is searched.
2933      *  @param argtypes  The types of the constructor invocation's value
2934      *                   arguments.
2935      *  @param typeargtypes  The types of the constructor invocation's type
2936      *                   arguments.
2937      */
2938     Symbol resolveConstructor(DiagnosticPosition pos,
2939                               Env<AttrContext> env,
2940                               Type site,
2941                               List<Type> argtypes,
2942                               List<Type> typeargtypes) {
2943         return resolveConstructor(new MethodResolutionContext(), pos, env, site, argtypes, typeargtypes);
2944     }
2945 
2946     private Symbol resolveConstructor(MethodResolutionContext resolveContext,
2947                               final DiagnosticPosition pos,
2948                               Env<AttrContext> env,
2949                               Type site,
2950                               List<Type> argtypes,
2951                               List<Type> typeargtypes) {
2952         return lookupMethod(env, pos, site.tsym, resolveContext, new BasicLookupHelper(names.init, site, argtypes, typeargtypes) {
2953             @Override
2954             Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) {
2955                 return findConstructor(pos, env, site, argtypes, typeargtypes,
2956                         phase.isBoxingRequired(),
2957                         phase.isVarargsRequired());
2958             }
2959         });
2960     }
2961 
2962     /** Resolve a constructor, throw a fatal error if not found.
2963      *  @param pos       The position to use for error reporting.
2964      *  @param env       The environment current at the method invocation.
2965      *  @param site      The type to be constructed.
2966      *  @param argtypes  The types of the invocation's value arguments.
2967      *  @param typeargtypes  The types of the invocation's type arguments.
2968      */
2969     public MethodSymbol resolveInternalConstructor(DiagnosticPosition pos, Env<AttrContext> env,
2970                                         Type site,
2971                                         List<Type> argtypes,
2972                                         List<Type> typeargtypes) {
2973         MethodResolutionContext resolveContext = new MethodResolutionContext();
2974         resolveContext.internalResolution = true;
2975         Symbol sym = resolveConstructor(resolveContext, pos, env, site, argtypes, typeargtypes);
2976         if (sym.kind == MTH) return (MethodSymbol)sym;
2977         else throw new FatalError(
2978                  diags.fragment(Fragments.FatalErrCantLocateCtor(site)));
2979     }
2980 
2981     Symbol findConstructor(DiagnosticPosition pos, Env<AttrContext> env,
2982                               Type site, List<Type> argtypes,
2983                               List<Type> typeargtypes,
2984                               boolean allowBoxing,
2985                               boolean useVarargs) {
2986         Symbol sym = findMethod(env, site,
2987                                     names.init, argtypes,
2988                                     typeargtypes, allowBoxing,
2989                                     useVarargs);
2990         chk.checkDeprecated(pos, env.info.scope.owner, sym);
2991         chk.checkPreview(pos, env.info.scope.owner, sym);
2992         return sym;
2993     }
2994 
2995     /** Resolve constructor using diamond inference.
2996      *  @param pos       The position to use for error reporting.
2997      *  @param env       The environment current at the constructor invocation.
2998      *  @param site      The type of class for which a constructor is searched.
2999      *                   The scope of this class has been touched in attribution.
3000      *  @param argtypes  The types of the constructor invocation's value
3001      *                   arguments.
3002      *  @param typeargtypes  The types of the constructor invocation's type
3003      *                   arguments.
3004      */
3005     Symbol resolveDiamond(DiagnosticPosition pos,
3006                               Env<AttrContext> env,
3007                               Type site,
3008                               List<Type> argtypes,
3009                               List<Type> typeargtypes) {
3010         return lookupMethod(env, pos, site.tsym, resolveMethodCheck,
3011                 new BasicLookupHelper(names.init, site, argtypes, typeargtypes) {
3012                     @Override
3013                     Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) {
3014                         return findDiamond(pos, env, site, argtypes, typeargtypes,
3015                                 phase.isBoxingRequired(),
3016                                 phase.isVarargsRequired());
3017                     }
3018                     @Override
3019                     Symbol access(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, Symbol sym) {
3020                         if (sym.kind.isResolutionError()) {
3021                             if (sym.kind != WRONG_MTH &&
3022                                 sym.kind != WRONG_MTHS) {
3023                                 sym = super.access(env, pos, location, sym);
3024                             } else {
3025                                 sym = new DiamondError(sym, currentResolutionContext);
3026                                 sym = accessMethod(sym, pos, site, names.init, true, argtypes, typeargtypes);
3027                                 env.info.pendingResolutionPhase = currentResolutionContext.step;
3028                             }
3029                         }
3030                         return sym;
3031                     }});
3032     }
3033 
3034     /** Find the constructor using diamond inference and do some checks(deprecated and preview).
3035      *  @param pos          The position to use for error reporting.
3036      *  @param env          The environment current at the constructor invocation.
3037      *  @param site         The type of class for which a constructor is searched.
3038      *                      The scope of this class has been touched in attribution.
3039      *  @param argtypes     The types of the constructor invocation's value arguments.
3040      *  @param typeargtypes The types of the constructor invocation's type arguments.
3041      *  @param allowBoxing  Allow boxing conversions of arguments.
3042      *  @param useVarargs   Box trailing arguments into an array for varargs.
3043      */
3044     private Symbol findDiamond(DiagnosticPosition pos,
3045                                Env<AttrContext> env,
3046                                Type site,
3047                                List<Type> argtypes,
3048                                List<Type> typeargtypes,
3049                                boolean allowBoxing,
3050                                boolean useVarargs) {
3051         Symbol sym = findDiamond(env, site, argtypes, typeargtypes, allowBoxing, useVarargs);
3052         chk.checkDeprecated(pos, env.info.scope.owner, sym);
3053         chk.checkPreview(pos, env.info.scope.owner, sym);
3054         return sym;
3055     }
3056 
3057     /** This method scans all the constructor symbol in a given class scope -
3058      *  assuming that the original scope contains a constructor of the kind:
3059      *  {@code Foo(X x, Y y)}, where X,Y are class type-variables declared in Foo,
3060      *  a method check is executed against the modified constructor type:
3061      *  {@code <X,Y>Foo<X,Y>(X x, Y y)}. This is crucial in order to enable diamond
3062      *  inference. The inferred return type of the synthetic constructor IS
3063      *  the inferred type for the diamond operator.
3064      */
3065     private Symbol findDiamond(Env<AttrContext> env,
3066                               Type site,
3067                               List<Type> argtypes,
3068                               List<Type> typeargtypes,
3069                               boolean allowBoxing,
3070                               boolean useVarargs) {
3071         Symbol bestSoFar = methodNotFound;
3072         TypeSymbol tsym = site.tsym.isInterface() ? syms.objectType.tsym : site.tsym;
3073         for (final Symbol sym : tsym.members().getSymbolsByName(names.init)) {
3074             //- System.out.println(" e " + e.sym);
3075             if (sym.kind == MTH &&
3076                 (sym.flags_field & SYNTHETIC) == 0) {
3077                     List<Type> oldParams = sym.type.hasTag(FORALL) ?
3078                             ((ForAll)sym.type).tvars :
3079                             List.nil();
3080                     Type constrType = new ForAll(site.tsym.type.getTypeArguments().appendList(oldParams),
3081                                                  types.createMethodTypeWithReturn(sym.type.asMethodType(), site));
3082                     MethodSymbol newConstr = new MethodSymbol(sym.flags(), names.init, constrType, site.tsym) {
3083                         @Override
3084                         public Symbol baseSymbol() {
3085                             return sym;
3086                         }
3087                     };
3088                     bestSoFar = selectBest(env, site, argtypes, typeargtypes,
3089                             newConstr,
3090                             bestSoFar,
3091                             allowBoxing,
3092                             useVarargs);
3093             }
3094         }
3095         return bestSoFar;
3096     }
3097 
3098     Symbol getMemberReference(DiagnosticPosition pos,
3099             Env<AttrContext> env,
3100             JCMemberReference referenceTree,
3101             Type site,
3102             Name name) {
3103 
3104         site = types.capture(site);
3105 
3106         ReferenceLookupHelper lookupHelper = makeReferenceLookupHelper(
3107                 referenceTree, site, name, List.nil(), null, VARARITY);
3108 
3109         Env<AttrContext> newEnv = env.dup(env.tree, env.info.dup());
3110         Symbol sym = lookupMethod(newEnv, env.tree.pos(), site.tsym,
3111                 nilMethodCheck, lookupHelper);
3112 
3113         env.info.pendingResolutionPhase = newEnv.info.pendingResolutionPhase;
3114 
3115         return sym;
3116     }
3117 
3118     ReferenceLookupHelper makeReferenceLookupHelper(JCMemberReference referenceTree,
3119                                   Type site,
3120                                   Name name,
3121                                   List<Type> argtypes,
3122                                   List<Type> typeargtypes,
3123                                   MethodResolutionPhase maxPhase) {
3124         if (!name.equals(names.init)) {
3125             //method reference
3126             return new MethodReferenceLookupHelper(referenceTree, name, site, argtypes, typeargtypes, maxPhase);
3127         } else if (site.hasTag(ARRAY)) {
3128             //array constructor reference
3129             return new ArrayConstructorReferenceLookupHelper(referenceTree, site, argtypes, typeargtypes, maxPhase);
3130         } else {
3131             //class constructor reference
3132             return new ConstructorReferenceLookupHelper(referenceTree, site, argtypes, typeargtypes, maxPhase);
3133         }
3134     }
3135 
3136     /**
3137      * Resolution of member references is typically done as a single
3138      * overload resolution step, where the argument types A are inferred from
3139      * the target functional descriptor.
3140      *
3141      * If the member reference is a method reference with a type qualifier,
3142      * a two-step lookup process is performed. The first step uses the
3143      * expected argument list A, while the second step discards the first
3144      * type from A (which is treated as a receiver type).
3145      *
3146      * There are two cases in which inference is performed: (i) if the member
3147      * reference is a constructor reference and the qualifier type is raw - in
3148      * which case diamond inference is used to infer a parameterization for the
3149      * type qualifier; (ii) if the member reference is an unbound reference
3150      * where the type qualifier is raw - in that case, during the unbound lookup
3151      * the receiver argument type is used to infer an instantiation for the raw
3152      * qualifier type.
3153      *
3154      * When a multi-step resolution process is exploited, the process of picking
3155      * the resulting symbol is delegated to an helper class {@link com.sun.tools.javac.comp.Resolve.ReferenceChooser}.
3156      *
3157      * This routine returns a pair (T,S), where S is the member reference symbol,
3158      * and T is the type of the class in which S is defined. This is necessary as
3159      * the type T might be dynamically inferred (i.e. if constructor reference
3160      * has a raw qualifier).
3161      */
3162     Pair<Symbol, ReferenceLookupHelper> resolveMemberReference(Env<AttrContext> env,
3163                                   JCMemberReference referenceTree,
3164                                   Type site,
3165                                   Name name,
3166                                   List<Type> argtypes,
3167                                   List<Type> typeargtypes,
3168                                   Type descriptor,
3169                                   MethodCheck methodCheck,
3170                                   InferenceContext inferenceContext,
3171                                   ReferenceChooser referenceChooser) {
3172 
3173         //step 1 - bound lookup
3174         ReferenceLookupHelper boundLookupHelper = makeReferenceLookupHelper(
3175                 referenceTree, site, name, argtypes, typeargtypes, VARARITY);
3176         Env<AttrContext> boundEnv = env.dup(env.tree, env.info.dup());
3177         MethodResolutionContext boundSearchResolveContext = new MethodResolutionContext();
3178         boundSearchResolveContext.methodCheck = methodCheck;
3179         Symbol boundSym = lookupMethod(boundEnv, env.tree.pos(),
3180                 site.tsym, boundSearchResolveContext, boundLookupHelper);
3181         boolean isStaticSelector = TreeInfo.isStaticSelector(referenceTree.expr, names);
3182         ReferenceLookupResult boundRes = new ReferenceLookupResult(boundSym, boundSearchResolveContext, isStaticSelector);
3183         if (dumpMethodReferenceSearchResults) {
3184             dumpMethodReferenceSearchResults(referenceTree, boundSearchResolveContext, boundSym, true);
3185         }
3186 
3187         //step 2 - unbound lookup
3188         Symbol unboundSym = methodNotFound;
3189         Env<AttrContext> unboundEnv = env.dup(env.tree, env.info.dup());
3190         ReferenceLookupHelper unboundLookupHelper = boundLookupHelper.unboundLookup(inferenceContext);
3191         ReferenceLookupResult unboundRes = referenceNotFound;
3192         if (unboundLookupHelper != null) {
3193             MethodResolutionContext unboundSearchResolveContext =
3194                     new MethodResolutionContext();
3195             unboundSearchResolveContext.methodCheck = methodCheck;
3196             unboundSym = lookupMethod(unboundEnv, env.tree.pos(),
3197                     site.tsym, unboundSearchResolveContext, unboundLookupHelper);
3198             unboundRes = new ReferenceLookupResult(unboundSym, unboundSearchResolveContext, isStaticSelector);
3199             if (dumpMethodReferenceSearchResults) {
3200                 dumpMethodReferenceSearchResults(referenceTree, unboundSearchResolveContext, unboundSym, false);
3201             }
3202         }
3203 
3204         //merge results
3205         Pair<Symbol, ReferenceLookupHelper> res;
3206         ReferenceLookupResult bestRes = referenceChooser.result(boundRes, unboundRes);
3207         res = new Pair<>(bestRes.sym,
3208                 bestRes == unboundRes ? unboundLookupHelper : boundLookupHelper);
3209         env.info.pendingResolutionPhase = bestRes == unboundRes ?
3210                 unboundEnv.info.pendingResolutionPhase :
3211                 boundEnv.info.pendingResolutionPhase;
3212 
3213         if (!res.fst.kind.isResolutionError()) {
3214             //handle sigpoly method references
3215             MethodSymbol msym = (MethodSymbol)res.fst;
3216             if ((msym.flags() & SIGNATURE_POLYMORPHIC) != 0) {
3217                 env.info.pendingResolutionPhase = BASIC;
3218                 res = new Pair<>(findPolymorphicSignatureInstance(msym, descriptor), res.snd);
3219             }
3220         }
3221 
3222         return res;
3223     }
3224 
3225     private void dumpMethodReferenceSearchResults(JCMemberReference referenceTree,
3226                                                   MethodResolutionContext resolutionContext,
3227                                                   Symbol bestSoFar,
3228                                                   boolean bound) {
3229         ListBuffer<JCDiagnostic> subDiags = new ListBuffer<>();
3230         int pos = 0;
3231         int mostSpecificPos = -1;
3232         for (Candidate c : resolutionContext.candidates) {
3233             if (resolutionContext.step != c.step || !c.isApplicable()) {
3234                 continue;
3235             } else {
3236                 JCDiagnostic subDiag = null;
3237                 if (c.sym.type.hasTag(FORALL)) {
3238                     subDiag = diags.fragment(Fragments.PartialInstSig(c.mtype));
3239                 }
3240 
3241                 String key = subDiag == null ?
3242                         "applicable.method.found.2" :
3243                         "applicable.method.found.3";
3244                 subDiags.append(diags.fragment(key, pos,
3245                         c.sym.isStatic() ? Fragments.Static : Fragments.NonStatic, c.sym, subDiag));
3246                 if (c.sym == bestSoFar)
3247                     mostSpecificPos = pos;
3248                 pos++;
3249             }
3250         }
3251         JCDiagnostic main = diags.note(
3252                 log.currentSource(),
3253                 referenceTree,
3254                 "method.ref.search.results.multi",
3255                 bound ? Fragments.Bound : Fragments.Unbound,
3256                 referenceTree.toString(), mostSpecificPos);
3257         JCDiagnostic d = new JCDiagnostic.MultilineDiagnostic(main, subDiags.toList());
3258         log.report(d);
3259     }
3260 
3261     /**
3262      * This class is used to represent a method reference lookup result. It keeps track of two
3263      * things: (i) the symbol found during a method reference lookup and (ii) the static kind
3264      * of the lookup (see {@link com.sun.tools.javac.comp.Resolve.ReferenceLookupResult.StaticKind}).
3265      */
3266     static class ReferenceLookupResult {
3267 
3268         /**
3269          * Static kind associated with a method reference lookup. Erroneous lookups end up with
3270          * the UNDEFINED kind; successful lookups will end up with either STATIC, NON_STATIC,
3271          * depending on whether all applicable candidates are static or non-static methods,
3272          * respectively. If a successful lookup has both static and non-static applicable methods,
3273          * its kind is set to BOTH.
3274          */
3275         enum StaticKind {
3276             STATIC,
3277             NON_STATIC,
3278             BOTH,
3279             UNDEFINED;
3280 
3281             /**
3282              * Retrieve the static kind associated with a given (method) symbol.
3283              */
3284             static StaticKind from(Symbol s) {
3285                 return s.isStatic() ?
3286                         STATIC : NON_STATIC;
3287             }
3288 
3289             /**
3290              * Merge two static kinds together.
3291              */
3292             static StaticKind reduce(StaticKind sk1, StaticKind sk2) {
3293                 if (sk1 == UNDEFINED) {
3294                     return sk2;
3295                 } else if (sk2 == UNDEFINED) {
3296                     return sk1;
3297                 } else {
3298                     return sk1 == sk2 ? sk1 : BOTH;
3299                 }
3300             }
3301         }
3302 
3303         /** The static kind. */
3304         StaticKind staticKind;
3305 
3306         /** The lookup result. */
3307         Symbol sym;
3308 
3309         ReferenceLookupResult(Symbol sym, MethodResolutionContext resolutionContext, boolean isStaticSelector) {
3310             this(sym, staticKind(sym, resolutionContext, isStaticSelector));
3311         }
3312 
3313         private ReferenceLookupResult(Symbol sym, StaticKind staticKind) {
3314             this.staticKind = staticKind;
3315             this.sym = sym;
3316         }
3317 
3318         private static StaticKind staticKind(Symbol sym, MethodResolutionContext resolutionContext, boolean isStaticSelector) {
3319             if (sym.kind == MTH && !isStaticSelector) {
3320                 return StaticKind.from(sym);
3321             } else if (sym.kind == MTH || sym.kind == AMBIGUOUS) {
3322                 return resolutionContext.candidates.stream()
3323                         .filter(c -> c.isApplicable() && c.step == resolutionContext.step)
3324                         .map(c -> StaticKind.from(c.sym))
3325                         .reduce(StaticKind::reduce)
3326                         .orElse(StaticKind.UNDEFINED);
3327             } else {
3328                 return StaticKind.UNDEFINED;
3329             }
3330         }
3331 
3332         /**
3333          * Does this result corresponds to a successful lookup (i.e. one where a method has been found?)
3334          */
3335         boolean isSuccess() {
3336             return staticKind != StaticKind.UNDEFINED;
3337         }
3338 
3339         /**
3340          * Does this result have given static kind?
3341          */
3342         boolean hasKind(StaticKind sk) {
3343             return this.staticKind == sk;
3344         }
3345 
3346         /**
3347          * Error recovery helper: can this lookup result be ignored (for the purpose of returning
3348          * some 'better' result) ?
3349          */
3350         boolean canIgnore() {
3351             switch (sym.kind) {
3352                 case ABSENT_MTH:
3353                     return true;
3354                 case WRONG_MTH:
3355                     InapplicableSymbolError errSym =
3356                             (InapplicableSymbolError)sym.baseSymbol();
3357                     return new Template(MethodCheckDiag.ARITY_MISMATCH.regex())
3358                             .matches(errSym.errCandidate().snd);
3359                 case WRONG_MTHS:
3360                     InapplicableSymbolsError errSyms =
3361                             (InapplicableSymbolsError)sym.baseSymbol();
3362                     return errSyms.filterCandidates(errSyms.mapCandidates()).isEmpty();
3363                 default:
3364                     return false;
3365             }
3366         }
3367 
3368         static ReferenceLookupResult error(Symbol sym) {
3369             return new ReferenceLookupResult(sym, StaticKind.UNDEFINED);
3370         }
3371     }
3372 
3373     /**
3374      * This abstract class embodies the logic that converts one (bound lookup) or two (unbound lookup)
3375      * {@code ReferenceLookupResult} objects into a {@code Symbol}, which is then regarded as the
3376      * result of method reference resolution.
3377      */
3378     abstract class ReferenceChooser {
3379         /**
3380          * Generate a result from a pair of lookup result objects. This method delegates to the
3381          * appropriate result generation routine.
3382          */
3383         ReferenceLookupResult result(ReferenceLookupResult boundRes, ReferenceLookupResult unboundRes) {
3384             return unboundRes != referenceNotFound ?
3385                     unboundResult(boundRes, unboundRes) :
3386                     boundResult(boundRes);
3387         }
3388 
3389         /**
3390          * Generate a symbol from a given bound lookup result.
3391          */
3392         abstract ReferenceLookupResult boundResult(ReferenceLookupResult boundRes);
3393 
3394         /**
3395          * Generate a symbol from a pair of bound/unbound lookup results.
3396          */
3397         abstract ReferenceLookupResult unboundResult(ReferenceLookupResult boundRes, ReferenceLookupResult unboundRes);
3398     }
3399 
3400     /**
3401      * This chooser implements the selection strategy used during a full lookup; this logic
3402      * is described in JLS SE 8 (15.3.2).
3403      */
3404     ReferenceChooser basicReferenceChooser = new ReferenceChooser() {
3405 
3406         @Override
3407         ReferenceLookupResult boundResult(ReferenceLookupResult boundRes) {
3408             return !boundRes.isSuccess() || boundRes.hasKind(StaticKind.NON_STATIC) ?
3409                     boundRes : //the search produces a non-static method
3410                     ReferenceLookupResult.error(new BadMethodReferenceError(boundRes.sym, false));
3411         }
3412 
3413         @Override
3414         ReferenceLookupResult unboundResult(ReferenceLookupResult boundRes, ReferenceLookupResult unboundRes) {
3415             if (boundRes.isSuccess() && boundRes.sym.isStatic() &&
3416                     (!unboundRes.isSuccess() || unboundRes.hasKind(StaticKind.STATIC))) {
3417                 //the first search produces a static method and no non-static method is applicable
3418                 //during the second search
3419                 return boundRes;
3420             } else if (unboundRes.isSuccess() && !unboundRes.sym.isStatic() &&
3421                     (!boundRes.isSuccess() || boundRes.hasKind(StaticKind.NON_STATIC))) {
3422                 //the second search produces a non-static method and no static method is applicable
3423                 //during the first search
3424                 return unboundRes;
3425             } else if (boundRes.isSuccess() && unboundRes.isSuccess()) {
3426                 //both searches produce some result; ambiguity (error recovery)
3427                 return ReferenceLookupResult.error(ambiguityError(boundRes.sym, unboundRes.sym));
3428             } else if (boundRes.isSuccess() || unboundRes.isSuccess()) {
3429                 //Both searches failed to produce a result with correct staticness (i.e. first search
3430                 //produces an non-static method). Alternatively, a given search produced a result
3431                 //with the right staticness, but the other search has applicable methods with wrong
3432                 //staticness (error recovery)
3433                 return ReferenceLookupResult.error(new BadMethodReferenceError(boundRes.isSuccess() ?
3434                         boundRes.sym : unboundRes.sym, true));
3435             } else {
3436                 //both searches fail to produce a result - pick 'better' error using heuristics (error recovery)
3437                 return (boundRes.canIgnore() && !unboundRes.canIgnore()) ?
3438                         unboundRes : boundRes;
3439             }
3440         }
3441     };
3442 
3443     /**
3444      * This chooser implements the selection strategy used during an arity-based lookup; this logic
3445      * is described in JLS SE 8 (15.12.2.1).
3446      */
3447     ReferenceChooser structuralReferenceChooser = new ReferenceChooser() {
3448 
3449         @Override
3450         ReferenceLookupResult boundResult(ReferenceLookupResult boundRes) {
3451             return (!boundRes.isSuccess() || !boundRes.hasKind(StaticKind.STATIC)) ?
3452                     boundRes : //the search has at least one applicable non-static method
3453                     ReferenceLookupResult.error(new BadMethodReferenceError(boundRes.sym, false));
3454         }
3455 
3456         @Override
3457         ReferenceLookupResult unboundResult(ReferenceLookupResult boundRes, ReferenceLookupResult unboundRes) {
3458             if (boundRes.isSuccess() && !boundRes.hasKind(StaticKind.NON_STATIC)) {
3459                 //the first search has at least one applicable static method
3460                 return boundRes;
3461             } else if (unboundRes.isSuccess() && !unboundRes.hasKind(StaticKind.STATIC)) {
3462                 //the second search has at least one applicable non-static method
3463                 return unboundRes;
3464             } else if (boundRes.isSuccess() || unboundRes.isSuccess()) {
3465                 //either the first search produces a non-static method, or second search produces
3466                 //a non-static method (error recovery)
3467                 return ReferenceLookupResult.error(new BadMethodReferenceError(boundRes.isSuccess() ?
3468                         boundRes.sym : unboundRes.sym, true));
3469             } else {
3470                 //both searches fail to produce a result - pick 'better' error using heuristics (error recovery)
3471                 return (boundRes.canIgnore() && !unboundRes.canIgnore()) ?
3472                         unboundRes : boundRes;
3473             }
3474         }
3475     };
3476 
3477     /**
3478      * Helper for defining custom method-like lookup logic; a lookup helper
3479      * provides hooks for (i) the actual lookup logic and (ii) accessing the
3480      * lookup result (this step might result in compiler diagnostics to be generated)
3481      */
3482     abstract class LookupHelper {
3483 
3484         /** name of the symbol to lookup */
3485         Name name;
3486 
3487         /** location in which the lookup takes place */
3488         Type site;
3489 
3490         /** actual types used during the lookup */
3491         List<Type> argtypes;
3492 
3493         /** type arguments used during the lookup */
3494         List<Type> typeargtypes;
3495 
3496         /** Max overload resolution phase handled by this helper */
3497         MethodResolutionPhase maxPhase;
3498 
3499         LookupHelper(Name name, Type site, List<Type> argtypes, List<Type> typeargtypes, MethodResolutionPhase maxPhase) {
3500             this.name = name;
3501             this.site = site;
3502             this.argtypes = argtypes;
3503             this.typeargtypes = typeargtypes;
3504             this.maxPhase = maxPhase;
3505         }
3506 
3507         /**
3508          * Should lookup stop at given phase with given result
3509          */
3510         final boolean shouldStop(Symbol sym, MethodResolutionPhase phase) {
3511             return phase.ordinal() > maxPhase.ordinal() ||
3512                  !sym.kind.isResolutionError() || sym.kind == AMBIGUOUS || sym.kind == STATICERR;
3513         }
3514 
3515         /**
3516          * Search for a symbol under a given overload resolution phase - this method
3517          * is usually called several times, once per each overload resolution phase
3518          */
3519         abstract Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase);
3520 
3521         /**
3522          * Dump overload resolution info
3523          */
3524         void debug(DiagnosticPosition pos, Symbol sym) {
3525             //do nothing
3526         }
3527 
3528         /**
3529          * Validate the result of the lookup
3530          */
3531         abstract Symbol access(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, Symbol sym);
3532     }
3533 
3534     abstract class BasicLookupHelper extends LookupHelper {
3535 
3536         BasicLookupHelper(Name name, Type site, List<Type> argtypes, List<Type> typeargtypes) {
3537             this(name, site, argtypes, typeargtypes, MethodResolutionPhase.VARARITY);
3538         }
3539 
3540         BasicLookupHelper(Name name, Type site, List<Type> argtypes, List<Type> typeargtypes, MethodResolutionPhase maxPhase) {
3541             super(name, site, argtypes, typeargtypes, maxPhase);
3542         }
3543 
3544         @Override
3545         Symbol access(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, Symbol sym) {
3546             if (sym.kind.isResolutionError()) {
3547                 //if nothing is found return the 'first' error
3548                 sym = accessMethod(sym, pos, location, site, name, true, argtypes, typeargtypes);
3549             }
3550             return sym;
3551         }
3552 
3553         @Override
3554         void debug(DiagnosticPosition pos, Symbol sym) {
3555             reportVerboseResolutionDiagnostic(pos, name, site, argtypes, typeargtypes, sym);
3556         }
3557     }
3558 
3559     /**
3560      * Helper class for member reference lookup. A reference lookup helper
3561      * defines the basic logic for member reference lookup; a method gives
3562      * access to an 'unbound' helper used to perform an unbound member
3563      * reference lookup.
3564      */
3565     abstract class ReferenceLookupHelper extends LookupHelper {
3566 
3567         /** The member reference tree */
3568         JCMemberReference referenceTree;
3569 
3570         ReferenceLookupHelper(JCMemberReference referenceTree, Name name, Type site,
3571                 List<Type> argtypes, List<Type> typeargtypes, MethodResolutionPhase maxPhase) {
3572             super(name, site, argtypes, typeargtypes, maxPhase);
3573             this.referenceTree = referenceTree;
3574         }
3575 
3576         /**
3577          * Returns an unbound version of this lookup helper. By default, this
3578          * method returns an dummy lookup helper.
3579          */
3580         ReferenceLookupHelper unboundLookup(InferenceContext inferenceContext) {
3581             return null;
3582         }
3583 
3584         /**
3585          * Get the kind of the member reference
3586          */
3587         abstract JCMemberReference.ReferenceKind referenceKind(Symbol sym);
3588 
3589         Symbol access(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, Symbol sym) {
3590             //skip error reporting
3591             return sym;
3592         }
3593     }
3594 
3595     /**
3596      * Helper class for method reference lookup. The lookup logic is based
3597      * upon Resolve.findMethod; in certain cases, this helper class has a
3598      * corresponding unbound helper class (see UnboundMethodReferenceLookupHelper).
3599      * In such cases, non-static lookup results are thrown away.
3600      */
3601     class MethodReferenceLookupHelper extends ReferenceLookupHelper {
3602 
3603         /** The original method reference lookup site. */
3604         Type originalSite;
3605 
3606         MethodReferenceLookupHelper(JCMemberReference referenceTree, Name name, Type site,
3607                 List<Type> argtypes, List<Type> typeargtypes, MethodResolutionPhase maxPhase) {
3608             super(referenceTree, name, types.skipTypeVars(site, true), argtypes, typeargtypes, maxPhase);
3609             this.originalSite = site;
3610         }
3611 
3612         @Override
3613         final Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) {
3614             return findMethod(env, site, name, argtypes, typeargtypes,
3615                     phase.isBoxingRequired(), phase.isVarargsRequired());
3616         }
3617 
3618         @Override
3619         ReferenceLookupHelper unboundLookup(InferenceContext inferenceContext) {
3620             if (TreeInfo.isStaticSelector(referenceTree.expr, names)) {
3621                 if (argtypes.nonEmpty() &&
3622                         (argtypes.head.hasTag(NONE) ||
3623                         types.isSubtypeUnchecked(inferenceContext.asUndetVar(argtypes.head), originalSite))) {
3624                     return new UnboundMethodReferenceLookupHelper(referenceTree, name,
3625                             originalSite, argtypes, typeargtypes, maxPhase);
3626                 } else {
3627                     return new ReferenceLookupHelper(referenceTree, name, site, argtypes, typeargtypes, maxPhase) {
3628                         @Override
3629                         ReferenceLookupHelper unboundLookup(InferenceContext inferenceContext) {
3630                             return this;
3631                         }
3632 
3633                         @Override
3634                         Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) {
3635                             return methodNotFound;
3636                         }
3637 
3638                         @Override
3639                         ReferenceKind referenceKind(Symbol sym) {
3640                             Assert.error();
3641                             return null;
3642                         }
3643                     };
3644                 }
3645             } else {
3646                 return super.unboundLookup(inferenceContext);
3647             }
3648         }
3649 
3650         @Override
3651         ReferenceKind referenceKind(Symbol sym) {
3652             if (sym.isStatic()) {
3653                 return ReferenceKind.STATIC;
3654             } else {
3655                 Name selName = TreeInfo.name(referenceTree.getQualifierExpression());
3656                 return selName != null && selName == names._super ?
3657                         ReferenceKind.SUPER :
3658                         ReferenceKind.BOUND;
3659             }
3660         }
3661 
3662         @Override
3663         Symbol access(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, Symbol sym) {
3664             if (originalSite.hasTag(TYPEVAR) && sym.kind == MTH) {
3665                 sym = (sym.flags() & Flags.PRIVATE) != 0 ?
3666                         new AccessError(env, site, sym) :
3667                         sym;
3668                 return accessBase(sym, pos, location, originalSite, name, true);
3669             } else {
3670                 return super.access(env, pos, location, sym);
3671             }
3672         }
3673     }
3674 
3675     /**
3676      * Helper class for unbound method reference lookup. Essentially the same
3677      * as the basic method reference lookup helper; main difference is that static
3678      * lookup results are thrown away. If qualifier type is raw, an attempt to
3679      * infer a parameterized type is made using the first actual argument (that
3680      * would otherwise be ignored during the lookup).
3681      */
3682     class UnboundMethodReferenceLookupHelper extends MethodReferenceLookupHelper {
3683 
3684         UnboundMethodReferenceLookupHelper(JCMemberReference referenceTree, Name name, Type site,
3685                 List<Type> argtypes, List<Type> typeargtypes, MethodResolutionPhase maxPhase) {
3686             super(referenceTree, name, site, argtypes.tail, typeargtypes, maxPhase);
3687             if (site.isRaw() && !argtypes.head.hasTag(NONE)) {
3688                 Type asSuperSite = types.asSuper(argtypes.head, site.tsym);
3689                 this.site = types.skipTypeVars(asSuperSite, true);
3690             }
3691         }
3692 
3693         @Override
3694         ReferenceLookupHelper unboundLookup(InferenceContext inferenceContext) {
3695             return this;
3696         }
3697 
3698         @Override
3699         ReferenceKind referenceKind(Symbol sym) {
3700             return ReferenceKind.UNBOUND;
3701         }
3702     }
3703 
3704     /**
3705      * Helper class for array constructor lookup; an array constructor lookup
3706      * is simulated by looking up a method that returns the array type specified
3707      * as qualifier, and that accepts a single int parameter (size of the array).
3708      */
3709     class ArrayConstructorReferenceLookupHelper extends ReferenceLookupHelper {
3710 
3711         ArrayConstructorReferenceLookupHelper(JCMemberReference referenceTree, Type site, List<Type> argtypes,
3712                 List<Type> typeargtypes, MethodResolutionPhase maxPhase) {
3713             super(referenceTree, names.init, site, argtypes, typeargtypes, maxPhase);
3714         }
3715 
3716         @Override
3717         protected Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) {
3718             WriteableScope sc = WriteableScope.create(syms.arrayClass);
3719             MethodSymbol arrayConstr = new MethodSymbol(PUBLIC, name, null, site.tsym);
3720             arrayConstr.type = new MethodType(List.of(syms.intType), site, List.nil(), syms.methodClass);
3721             sc.enter(arrayConstr);
3722             return findMethodInScope(env, site, name, argtypes, typeargtypes, sc, methodNotFound, phase.isBoxingRequired(), phase.isVarargsRequired(), false);
3723         }
3724 
3725         @Override
3726         ReferenceKind referenceKind(Symbol sym) {
3727             return ReferenceKind.ARRAY_CTOR;
3728         }
3729     }
3730 
3731     /**
3732      * Helper class for constructor reference lookup. The lookup logic is based
3733      * upon either Resolve.findMethod or Resolve.findDiamond - depending on
3734      * whether the constructor reference needs diamond inference (this is the case
3735      * if the qualifier type is raw). A special erroneous symbol is returned
3736      * if the lookup returns the constructor of an inner class and there's no
3737      * enclosing instance in scope.
3738      */
3739     class ConstructorReferenceLookupHelper extends ReferenceLookupHelper {
3740 
3741         boolean needsInference;
3742 
3743         ConstructorReferenceLookupHelper(JCMemberReference referenceTree, Type site, List<Type> argtypes,
3744                 List<Type> typeargtypes, MethodResolutionPhase maxPhase) {
3745             super(referenceTree, names.init, site, argtypes, typeargtypes, maxPhase);
3746             if (site.isRaw()) {
3747                 this.site = new ClassType(site.getEnclosingType(),
3748                         !(site.tsym.isInner() && site.getEnclosingType().isRaw()) ?
3749                                 site.tsym.type.getTypeArguments() : List.nil(), site.tsym, site.getMetadata());
3750                 needsInference = true;
3751             }
3752         }
3753 
3754         @Override
3755         protected Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) {
3756             return needsInference ?
3757                 findDiamond(env, site, argtypes, typeargtypes, phase.isBoxingRequired(), phase.isVarargsRequired()) :
3758                 findMethod(env, site, name, argtypes, typeargtypes,
3759                         phase.isBoxingRequired(), phase.isVarargsRequired());
3760         }
3761 
3762         @Override
3763         ReferenceKind referenceKind(Symbol sym) {
3764             return site.getEnclosingType().hasTag(NONE) ?
3765                     ReferenceKind.TOPLEVEL : ReferenceKind.IMPLICIT_INNER;
3766         }
3767     }
3768 
3769     /**
3770      * Main overload resolution routine. On each overload resolution step, a
3771      * lookup helper class is used to perform the method/constructor lookup;
3772      * at the end of the lookup, the helper is used to validate the results
3773      * (this last step might trigger overload resolution diagnostics).
3774      */
3775     Symbol lookupMethod(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, MethodCheck methodCheck, LookupHelper lookupHelper) {
3776         MethodResolutionContext resolveContext = new MethodResolutionContext();
3777         resolveContext.methodCheck = methodCheck;
3778         return lookupMethod(env, pos, location, resolveContext, lookupHelper);
3779     }
3780 
3781     Symbol lookupMethod(Env<AttrContext> env, DiagnosticPosition pos, Symbol location,
3782             MethodResolutionContext resolveContext, LookupHelper lookupHelper) {
3783         MethodResolutionContext prevResolutionContext = currentResolutionContext;
3784         try {
3785             Symbol bestSoFar = methodNotFound;
3786             currentResolutionContext = resolveContext;
3787             for (MethodResolutionPhase phase : methodResolutionSteps) {
3788                 if (lookupHelper.shouldStop(bestSoFar, phase))
3789                     break;
3790                 MethodResolutionPhase prevPhase = currentResolutionContext.step;
3791                 Symbol prevBest = bestSoFar;
3792                 currentResolutionContext.step = phase;
3793                 Symbol sym = lookupHelper.lookup(env, phase);
3794                 lookupHelper.debug(pos, sym);
3795                 bestSoFar = phase.mergeResults(bestSoFar, sym);
3796                 env.info.pendingResolutionPhase = (prevBest == bestSoFar) ? prevPhase : phase;
3797             }
3798             return lookupHelper.access(env, pos, location, bestSoFar);
3799         } finally {
3800             currentResolutionContext = prevResolutionContext;
3801         }
3802     }
3803 
3804     /**
3805      * Find a "valid" reference to an enclosing 'A.this' such that A is a subclass of the provided class symbol.
3806      * A reference to an enclosing 'A.this' is "valid" if (a) we're not in the early-construction context for A
3807      * and (b) if the current class is not an inner class of A.
3808      */
3809     Symbol findSelfContaining(DiagnosticPosition pos,
3810                     Env<AttrContext> env,
3811                     TypeSymbol c,
3812                     boolean isSuper) {
3813         Env<AttrContext> env1 = isSuper ? env.outer : env;
3814         boolean staticOnly = false;
3815         while (env1.outer != null) {
3816             if (isStatic(env1)) staticOnly = true;
3817             if (env1.enclClass.sym.isSubClass(c, types)) {
3818                 Symbol sym = env1.info.scope.findFirst(names._this);
3819                 if (sym != null) {
3820                     if (staticOnly) {
3821                         // current class is not an inner class, stop search
3822                         return new StaticError(sym);
3823                     } else if (env1.info.ctorPrologue && !isAllowedEarlyReference(pos, env1, (VarSymbol)sym)) {
3824                         // early construction context, stop search
3825                         return new RefBeforeCtorCalledError(sym);
3826                     } else {
3827                         // found it
3828                         return sym;
3829                     }
3830                 }
3831             }
3832             if ((env1.enclClass.sym.flags() & STATIC) != 0) staticOnly = true;
3833             env1 = env1.outer;
3834         }
3835         return varNotFound;
3836     }
3837 
3838     /**
3839      * Resolve the (method) owner of a local class. This can fail if the local class
3840      * is referenced from a static context nested inside the local class. Effectively,
3841      * this lookup succeeds if we can access a local variable declared inside the owner
3842      * method from the provided env.
3843      */
3844     Symbol findLocalClassOwner(Env<AttrContext> env, TypeSymbol c) {
3845         Symbol owner = c.owner;
3846         Assert.check(owner.kind == MTH || owner.kind == VAR);
3847         Env<AttrContext> env1 = env;
3848         boolean staticOnly = false;
3849         while (env1.outer != null) {
3850             // If the local class is defined inside a static method, and the instance creation expression
3851             // occurs in that same method, the creation occurs (technically) inside a static context, but that's ok.
3852             if (env1.info.scope.owner == owner) {
3853                 return (staticOnly) ?
3854                     new BadLocalClassCreation(c) :
3855                     owner;
3856             } else if (isStatic(env1) || env1.enclClass.sym.isStatic()) {
3857                 staticOnly = true;
3858             }
3859             env1 = env1.outer;
3860         }
3861         return owner.kind == MTH ?
3862                 methodNotFound :
3863                 varNotFound;
3864     }
3865 
3866     /**
3867      * Resolve `c.name' where name == this or name == super.
3868      * @param pos           The position to use for error reporting.
3869      * @param env           The environment current at the expression.
3870      * @param c             The type of the selected expression
3871      * @param tree          The expression
3872      */
3873     Symbol resolveSelf(DiagnosticPosition pos,
3874                        Env<AttrContext> env,
3875                        TypeSymbol c,
3876                        JCFieldAccess tree) {
3877         Name name = tree.name;
3878         Assert.check(name == names._this || name == names._super);
3879         Env<AttrContext> env1 = env;
3880         boolean staticOnly = false;
3881         while (env1.outer != null) {
3882             if (isStatic(env1)) staticOnly = true;
3883             if (env1.enclClass.sym == c) {
3884                 Symbol sym = env1.info.scope.findFirst(name);
3885                 if (sym != null) {
3886                     if (staticOnly)
3887                         sym = new StaticError(sym);
3888                     else if (env1.info.ctorPrologue &&
3889                             !isReceiverParameter(env, tree) &&
3890                             !isAllowedEarlyReference(pos, env1, (VarSymbol)sym))
3891                         sym = new RefBeforeCtorCalledError(sym);
3892                     return accessBase(sym, pos, env.enclClass.sym.type,
3893                             name, true);
3894                 }
3895             }
3896             if ((env1.enclClass.sym.flags() & STATIC) != 0) staticOnly = true;
3897             env1 = env1.outer;
3898         }
3899         if (c.isInterface() &&
3900                 name == names._super && !isStatic(env) &&
3901                 types.isDirectSuperInterface(c, env.enclClass.sym)) {
3902             //this might be a default super call if one of the superinterfaces is 'c'
3903             for (Type t : pruneInterfaces(env.enclClass.type)) {
3904                 if (t.tsym == c) {
3905                     if (env.info.ctorPrologue)
3906                         log.error(pos, Errors.CantRefBeforeCtorCalled(name));
3907                     env.info.defaultSuperCallSite = t;
3908                     return new VarSymbol(0, names._super,
3909                             types.asSuper(env.enclClass.type, c), env.enclClass.sym);
3910                 }
3911             }
3912             //find a direct supertype that is a subtype of 'c'
3913             for (Type i : types.directSupertypes(env.enclClass.type)) {
3914                 if (i.tsym.isSubClass(c, types) && i.tsym != c) {
3915                     log.error(pos,
3916                             Errors.IllegalDefaultSuperCall(c,
3917                                     Fragments.RedundantSupertype(c, i)));
3918                     return syms.errSymbol;
3919                 }
3920             }
3921             Assert.error();
3922         }
3923         log.error(pos, Errors.NotEnclClass(c));
3924         return syms.errSymbol;
3925     }
3926     //where
3927     private List<Type> pruneInterfaces(Type t) {
3928         ListBuffer<Type> result = new ListBuffer<>();
3929         for (Type t1 : types.interfaces(t)) {
3930             boolean shouldAdd = true;
3931             for (Type t2 : types.directSupertypes(t)) {
3932                 if (t1 != t2 && !t2.hasTag(ERROR) && types.isSubtypeNoCapture(t2, t1)) {
3933                     shouldAdd = false;
3934                 }
3935             }
3936             if (shouldAdd) {
3937                 result.append(t1);
3938             }
3939         }
3940         return result.toList();
3941     }
3942     private boolean isReceiverParameter(Env<AttrContext> env, JCFieldAccess tree) {
3943         if (env.tree.getTag() != METHODDEF)
3944             return false;
3945         JCMethodDecl method = (JCMethodDecl)env.tree;
3946         return method.recvparam != null && tree == method.recvparam.nameexpr;
3947     }
3948 
3949     /**
3950      * Determine if an early instance field reference may appear in a constructor prologue.
3951      *
3952      * <p>
3953      * This is only allowed when:
3954      *  - The field is being assigned a value (i.e., written but not read)
3955      *  - The field is not inherited from a superclass
3956      *  - The assignment is not within a lambda, because that would require
3957      *    capturing 'this' which is not allowed prior to super().
3958      *
3959      * <p>
3960      * Note, this method doesn't catch all such scenarios, because this method
3961      * is invoked for symbol "x" only for "x = 42" but not for "this.x = 42".
3962      * We also don't verify that the field has no initializer, which is required.
3963      * To catch those cases, we rely on similar logic in Attr.checkAssignable().
3964      */
3965     private boolean isAllowedEarlyReference(DiagnosticPosition pos, Env<AttrContext> env, VarSymbol v) {
3966 
3967         // Check assumptions
3968         Assert.check(env.info.ctorPrologue);
3969         Assert.check((v.flags_field & STATIC) == 0);
3970 
3971         // The symbol must appear in the LHS of an assignment statement
3972         if (!(env.tree instanceof JCAssign assign))
3973             return false;
3974 
3975         // The assignment statement must not be within a lambda
3976         if (env.info.isLambda)
3977             return false;
3978 
3979         // Get the symbol's qualifier, if any
3980         JCExpression lhs = TreeInfo.skipParens(assign.lhs);
3981         JCExpression base;
3982         switch (lhs.getTag()) {
3983         case IDENT:
3984             base = null;
3985             break;
3986         case SELECT:
3987             JCFieldAccess select = (JCFieldAccess)lhs;
3988             base = select.selected;
3989             if (!TreeInfo.isExplicitThisReference(types, (ClassType)env.enclClass.type, base))
3990                 return false;
3991             break;
3992         default:
3993             return false;
3994         }
3995 
3996         // If an early reference, the field must not be declared in a superclass
3997         if (isEarlyReference(env, base, v) && v.owner != env.enclClass.sym)
3998             return false;
3999 
4000         // The flexible constructors feature must be enabled
4001         preview.checkSourceLevel(pos, Feature.FLEXIBLE_CONSTRUCTORS);
4002 
4003         // OK
4004         return true;
4005     }
4006 
4007     /**
4008      * Determine if the variable appearance constitutes an early reference to the current class.
4009      *
4010      * <p>
4011      * This means the variable is an instance field of the current class and it appears
4012      * in an early initialization context of it (i.e., one of its constructor prologues).
4013      *
4014      * <p>
4015      * Such a reference is only allowed for assignments to non-initialized fields that are
4016      * not inherited from a superclass, though that is not enforced by this method.
4017      *
4018      * @param env    The current environment
4019      * @param base   Variable qualifier, if any, otherwise null
4020      * @param v      The variable
4021      */
4022     public boolean isEarlyReference(Env<AttrContext> env, JCTree base, VarSymbol v) {
4023         if (env.info.ctorPrologue &&
4024                 (v.flags() & STATIC) == 0 &&
4025                 v.isMemberOf(env.enclClass.sym, types)) {
4026 
4027             // Allow "Foo.this.x" when "Foo" is (also) an outer class, as this refers to the outer instance
4028             if (base != null) {
4029                 return TreeInfo.isExplicitThisReference(types, (ClassType)env.enclClass.type, base);
4030             }
4031 
4032             // It's an early reference to an instance field member of the current instance
4033             return true;
4034         }
4035         return false;
4036     }
4037 
4038 /* ***************************************************************************
4039  *  ResolveError classes, indicating error situations when accessing symbols
4040  ****************************************************************************/
4041 
4042     //used by TransTypes when checking target type of synthetic cast
4043     public void logAccessErrorInternal(Env<AttrContext> env, JCTree tree, Type type) {
4044         AccessError error = new AccessError(env, env.enclClass.type, type.tsym);
4045         logResolveError(error, tree.pos(), env.enclClass.sym, env.enclClass.type, null, null, null);
4046     }
4047     //where
4048     private void logResolveError(ResolveError error,
4049             DiagnosticPosition pos,
4050             Symbol location,
4051             Type site,
4052             Name name,
4053             List<Type> argtypes,
4054             List<Type> typeargtypes) {
4055         JCDiagnostic d = error.getDiagnostic(JCDiagnostic.DiagnosticType.ERROR,
4056                 pos, location, site, name, argtypes, typeargtypes);
4057         if (d != null) {
4058             d.setFlag(DiagnosticFlag.RESOLVE_ERROR);
4059             log.report(d);
4060         }
4061     }
4062 
4063     private final LocalizedString noArgs = new LocalizedString("compiler.misc.no.args");
4064 
4065     public Object methodArguments(List<Type> argtypes) {
4066         if (argtypes == null || argtypes.isEmpty()) {
4067             return noArgs;
4068         } else {
4069             ListBuffer<Object> diagArgs = new ListBuffer<>();
4070             for (Type t : argtypes) {
4071                 if (t.hasTag(DEFERRED)) {
4072                     diagArgs.append(((DeferredAttr.DeferredType)t).tree);
4073                 } else {
4074                     diagArgs.append(t);
4075                 }
4076             }
4077             return diagArgs;
4078         }
4079     }
4080 
4081     /** check if a type is a subtype of Serializable, if that is available.*/
4082     boolean isSerializable(Type t) {
4083         try {
4084             syms.serializableType.complete();
4085         }
4086         catch (CompletionFailure e) {
4087             return false;
4088         }
4089         return types.isSubtype(t, syms.serializableType);
4090     }
4091 
4092     /**
4093      * Root class for resolution errors. Subclass of ResolveError
4094      * represent a different kinds of resolution error - as such they must
4095      * specify how they map into concrete compiler diagnostics.
4096      */
4097     abstract class ResolveError extends Symbol {
4098 
4099         /** The name of the kind of error, for debugging only. */
4100         final String debugName;
4101 
4102         ResolveError(Kind kind, String debugName) {
4103             super(kind, 0, null, null, null);
4104             this.debugName = debugName;
4105         }
4106 
4107         @Override @DefinedBy(Api.LANGUAGE_MODEL)
4108         public <R, P> R accept(ElementVisitor<R, P> v, P p) {
4109             throw new AssertionError();
4110         }
4111 
4112         @Override
4113         public String toString() {
4114             return debugName;
4115         }
4116 
4117         @Override
4118         public boolean exists() {
4119             return false;
4120         }
4121 
4122         @Override
4123         public boolean isStatic() {
4124             return false;
4125         }
4126 
4127         /**
4128          * Create an external representation for this erroneous symbol to be
4129          * used during attribution - by default this returns the symbol of a
4130          * brand new error type which stores the original type found
4131          * during resolution.
4132          *
4133          * @param name     the name used during resolution
4134          * @param location the location from which the symbol is accessed
4135          */
4136         protected Symbol access(Name name, TypeSymbol location) {
4137             return types.createErrorType(name, location, syms.errSymbol.type).tsym;
4138         }
4139 
4140         /**
4141          * Create a diagnostic representing this resolution error.
4142          *
4143          * @param dkind     The kind of the diagnostic to be created (e.g error).
4144          * @param pos       The position to be used for error reporting.
4145          * @param site      The original type from where the selection took place.
4146          * @param name      The name of the symbol to be resolved.
4147          * @param argtypes  The invocation's value arguments,
4148          *                  if we looked for a method.
4149          * @param typeargtypes  The invocation's type arguments,
4150          *                      if we looked for a method.
4151          */
4152         abstract JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind,
4153                 DiagnosticPosition pos,
4154                 Symbol location,
4155                 Type site,
4156                 Name name,
4157                 List<Type> argtypes,
4158                 List<Type> typeargtypes);
4159     }
4160 
4161     class UnresolvableGlobalSymbolError extends InvalidSymbolError {
4162 
4163         UnresolvableGlobalSymbolError(Symbol sym) {
4164             super(HIDDEN, sym, "unresolvable class error");
4165             this.name = sym.name;
4166         }
4167 
4168         @Override
4169         JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind,
4170                 DiagnosticPosition pos,
4171                 Symbol location,
4172                 Type site,
4173                 Name name,
4174                 List<Type> argtypes,
4175                 List<Type> typeargtypes) {
4176             //the error should have already been reported, ignore:
4177             return null;
4178         }
4179 
4180         @Override
4181         public Symbol access(Name name, TypeSymbol location) {
4182             return sym;
4183         }
4184     }
4185 
4186     /**
4187      * This class is the root class of all resolution errors caused by
4188      * an invalid symbol being found during resolution.
4189      */
4190     abstract class InvalidSymbolError extends ResolveError {
4191 
4192         /** The invalid symbol found during resolution */
4193         Symbol sym;
4194 
4195         InvalidSymbolError(Kind kind, Symbol sym, String debugName) {
4196             super(kind, debugName);
4197             this.sym = sym;
4198         }
4199 
4200         @Override
4201         public boolean exists() {
4202             return true;
4203         }
4204 
4205         @Override
4206         public String toString() {
4207              return super.toString() + " wrongSym=" + sym;
4208         }
4209 
4210         @Override
4211         public Symbol access(Name name, TypeSymbol location) {
4212             if (!sym.kind.isResolutionError() && sym.kind.matches(KindSelector.TYP))
4213                 return types.createErrorType(name, location, sym.type).tsym;
4214             else
4215                 return sym;
4216         }
4217     }
4218 
4219     class BadRestrictedTypeError extends ResolveError {
4220         private final Name typeName;
4221         BadRestrictedTypeError(Name typeName) {
4222             super(Kind.BAD_RESTRICTED_TYPE, "bad var use");
4223             this.typeName = typeName;
4224         }
4225 
4226         @Override
4227         JCDiagnostic getDiagnostic(DiagnosticType dkind, DiagnosticPosition pos, Symbol location, Type site, Name name, List<Type> argtypes, List<Type> typeargtypes) {
4228             return diags.create(dkind, log.currentSource(), pos, "illegal.ref.to.restricted.type", typeName);
4229         }
4230     }
4231 
4232     /**
4233      * InvalidSymbolError error class indicating that a symbol matching a
4234      * given name does not exists in a given site.
4235      */
4236     class SymbolNotFoundError extends ResolveError {
4237 
4238         SymbolNotFoundError(Kind kind) {
4239             this(kind, "symbol not found error");
4240         }
4241 
4242         SymbolNotFoundError(Kind kind, String debugName) {
4243             super(kind, debugName);
4244         }
4245 
4246         @Override
4247         JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind,
4248                 DiagnosticPosition pos,
4249                 Symbol location,
4250                 Type site,
4251                 Name name,
4252                 List<Type> argtypes,
4253                 List<Type> typeargtypes) {
4254             argtypes = argtypes == null ? List.nil() : argtypes;
4255             typeargtypes = typeargtypes == null ? List.nil() : typeargtypes;
4256             if (name == names.error)
4257                 return null;
4258 
4259             boolean hasLocation = false;
4260             if (location == null) {
4261                 location = site.tsym;
4262             }
4263             if (!location.name.isEmpty()) {
4264                 if (location.kind == PCK && !site.tsym.exists() && location.name != names.java) {
4265                     return diags.create(dkind, log.currentSource(), pos,
4266                         "doesnt.exist", location);
4267                 }
4268                 hasLocation = !location.name.equals(names._this) &&
4269                         !location.name.equals(names._super);
4270             }
4271             boolean isConstructor = name == names.init;
4272             KindName kindname = isConstructor ? KindName.CONSTRUCTOR : kind.absentKind();
4273             Name idname = isConstructor ? site.tsym.name : name;
4274             String errKey = getErrorKey(kindname, typeargtypes.nonEmpty(), hasLocation);
4275             if (hasLocation) {
4276                 return diags.create(dkind, log.currentSource(), pos,
4277                         errKey, kindname, idname, //symbol kindname, name
4278                         typeargtypes, args(argtypes), //type parameters and arguments (if any)
4279                         getLocationDiag(location, site)); //location kindname, type
4280             }
4281             else {
4282                 return diags.create(dkind, log.currentSource(), pos,
4283                         errKey, kindname, idname, //symbol kindname, name
4284                         typeargtypes, args(argtypes)); //type parameters and arguments (if any)
4285             }
4286         }
4287         //where
4288         private Object args(List<Type> args) {
4289             return args.isEmpty() ? args : methodArguments(args);
4290         }
4291 
4292         private String getErrorKey(KindName kindname, boolean hasTypeArgs, boolean hasLocation) {
4293             String key = "cant.resolve";
4294             String suffix = hasLocation ? ".location" : "";
4295             switch (kindname) {
4296                 case METHOD:
4297                 case CONSTRUCTOR: {
4298                     suffix += ".args";
4299                     suffix += hasTypeArgs ? ".params" : "";
4300                 }
4301             }
4302             return key + suffix;
4303         }
4304         private JCDiagnostic getLocationDiag(Symbol location, Type site) {
4305             if (location.kind == VAR) {
4306                 return diags.fragment(Fragments.Location1(kindName(location),
4307                                                           location,
4308                                                           location.type));
4309             } else {
4310                 return diags.fragment(Fragments.Location(typeKindName(site),
4311                                       site,
4312                                       null));
4313             }
4314         }
4315     }
4316 
4317     /**
4318      * InvalidSymbolError error class indicating that a given symbol
4319      * (either a method, a constructor or an operand) is not applicable
4320      * given an actual arguments/type argument list.
4321      */
4322     class InapplicableSymbolError extends ResolveError {
4323 
4324         protected MethodResolutionContext resolveContext;
4325 
4326         InapplicableSymbolError(MethodResolutionContext context) {
4327             this(WRONG_MTH, "inapplicable symbol error", context);
4328         }
4329 
4330         protected InapplicableSymbolError(Kind kind, String debugName, MethodResolutionContext context) {
4331             super(kind, debugName);
4332             this.resolveContext = context;
4333         }
4334 
4335         @Override
4336         public String toString() {
4337             return super.toString();
4338         }
4339 
4340         @Override
4341         public boolean exists() {
4342             return true;
4343         }
4344 
4345         @Override
4346         JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind,
4347                 DiagnosticPosition pos,
4348                 Symbol location,
4349                 Type site,
4350                 Name name,
4351                 List<Type> argtypes,
4352                 List<Type> typeargtypes) {
4353             if (name == names.error)
4354                 return null;
4355 
4356             Pair<Symbol, JCDiagnostic> c = errCandidate();
4357             Symbol ws = c.fst.asMemberOf(site, types);
4358             UnaryOperator<JCDiagnostic> rewriter = compactMethodDiags ?
4359               d -> MethodResolutionDiagHelper.rewrite(diags, pos, log.currentSource(), dkind, c.snd) : null;
4360 
4361             // If the problem is due to type arguments, then the method parameters aren't relevant,
4362             // so use the error message that omits them to avoid confusion.
4363             switch (c.snd.getCode()) {
4364                 case "compiler.misc.wrong.number.type.args":
4365                 case "compiler.misc.explicit.param.do.not.conform.to.bounds":
4366                     return diags.create(dkind, log.currentSource(), pos,
4367                               "cant.apply.symbol.noargs",
4368                               rewriter,
4369                               kindName(ws),
4370                               ws.name == names.init ? ws.owner.name : ws.name,
4371                               kindName(ws.owner),
4372                               ws.owner.type,
4373                               c.snd);
4374                 default:
4375                     // Avoid saying "constructor Array in class Array"
4376                     if (ws.owner == syms.arrayClass && ws.name == names.init) {
4377                         return diags.create(dkind, log.currentSource(), pos,
4378                                   "cant.apply.array.ctor",
4379                                   rewriter,
4380                                   methodArguments(ws.type.getParameterTypes()),
4381                                   methodArguments(argtypes),
4382                                   c.snd);
4383                     }
4384                     return diags.create(dkind, log.currentSource(), pos,
4385                               "cant.apply.symbol",
4386                               rewriter,
4387                               kindName(ws),
4388                               ws.name == names.init ? ws.owner.name : ws.name,
4389                               methodArguments(ws.type.getParameterTypes()),
4390                               methodArguments(argtypes),
4391                               kindName(ws.owner),
4392                               ws.owner.type,
4393                               c.snd);
4394             }
4395         }
4396 
4397         @Override
4398         public Symbol access(Name name, TypeSymbol location) {
4399             Pair<Symbol, JCDiagnostic> cand = errCandidate();
4400             TypeSymbol errSymbol = types.createErrorType(name, location, cand != null ? cand.fst.type : syms.errSymbol.type).tsym;
4401             if (cand != null) {
4402                 attrRecover.wrongMethodSymbolCandidate(errSymbol, cand.fst, cand.snd);
4403             }
4404             return errSymbol;
4405         }
4406 
4407         protected Pair<Symbol, JCDiagnostic> errCandidate() {
4408             Candidate bestSoFar = null;
4409             for (Candidate c : resolveContext.candidates) {
4410                 if (c.isApplicable()) continue;
4411                 bestSoFar = c;
4412             }
4413             Assert.checkNonNull(bestSoFar);
4414             return new Pair<>(bestSoFar.sym, bestSoFar.details);
4415         }
4416     }
4417 
4418     /**
4419      * ResolveError error class indicating that a symbol (either methods, constructors or operand)
4420      * is not applicable given an actual arguments/type argument list.
4421      */
4422     class InapplicableSymbolsError extends InapplicableSymbolError {
4423 
4424         InapplicableSymbolsError(MethodResolutionContext context) {
4425             super(WRONG_MTHS, "inapplicable symbols", context);
4426         }
4427 
4428         @Override
4429         JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind,
4430                 DiagnosticPosition pos,
4431                 Symbol location,
4432                 Type site,
4433                 Name name,
4434                 List<Type> argtypes,
4435                 List<Type> typeargtypes) {
4436             Map<Symbol, JCDiagnostic> candidatesMap = mapCandidates();
4437             Map<Symbol, JCDiagnostic> filteredCandidates = compactMethodDiags ?
4438                     filterCandidates(candidatesMap) :
4439                     mapCandidates();
4440             if (filteredCandidates.isEmpty()) {
4441                 filteredCandidates = candidatesMap;
4442             }
4443             boolean truncatedDiag = candidatesMap.size() != filteredCandidates.size();
4444             if (filteredCandidates.size() > 1) {
4445                 JCDiagnostic err = diags.create(dkind,
4446                         null,
4447                         truncatedDiag ?
4448                                 EnumSet.of(DiagnosticFlag.COMPRESSED) :
4449                                 EnumSet.noneOf(DiagnosticFlag.class),
4450                         log.currentSource(),
4451                         pos,
4452                         "cant.apply.symbols",
4453                         name == names.init ? KindName.CONSTRUCTOR : kind.absentKind(),
4454                         name == names.init ? site.tsym.name : name,
4455                         methodArguments(argtypes));
4456                 return new JCDiagnostic.MultilineDiagnostic(err, candidateDetails(filteredCandidates, site));
4457             } else if (filteredCandidates.size() == 1) {
4458                 Map.Entry<Symbol, JCDiagnostic> _e =
4459                                 filteredCandidates.entrySet().iterator().next();
4460                 final Pair<Symbol, JCDiagnostic> p = new Pair<>(_e.getKey(), _e.getValue());
4461                 JCDiagnostic d = new InapplicableSymbolError(resolveContext) {
4462                     @Override
4463                     protected Pair<Symbol, JCDiagnostic> errCandidate() {
4464                         return p;
4465                     }
4466                 }.getDiagnostic(dkind, pos,
4467                     location, site, name, argtypes, typeargtypes);
4468                 if (truncatedDiag) {
4469                     d.setFlag(DiagnosticFlag.COMPRESSED);
4470                 }
4471                 return d;
4472             } else {
4473                 return new SymbolNotFoundError(ABSENT_MTH).getDiagnostic(dkind, pos,
4474                     location, site, name, argtypes, typeargtypes);
4475             }
4476         }
4477         //where
4478             private Map<Symbol, JCDiagnostic> mapCandidates() {
4479                 MostSpecificMap candidates = new MostSpecificMap();
4480                 for (Candidate c : resolveContext.candidates) {
4481                     if (c.isApplicable()) continue;
4482                     candidates.put(c);
4483                 }
4484                 return candidates;
4485             }
4486 
4487             @SuppressWarnings("serial")
4488             private class MostSpecificMap extends LinkedHashMap<Symbol, JCDiagnostic> {
4489                 private void put(Candidate c) {
4490                     ListBuffer<Symbol> overridden = new ListBuffer<>();
4491                     for (Symbol s : keySet()) {
4492                         if (s == c.sym) {
4493                             continue;
4494                         }
4495                         if (c.sym.overrides(s, (TypeSymbol)s.owner, types, false)) {
4496                             overridden.add(s);
4497                         } else if (s.overrides(c.sym, (TypeSymbol)c.sym.owner, types, false)) {
4498                             return;
4499                         }
4500                     }
4501                     for (Symbol s : overridden) {
4502                         remove(s);
4503                     }
4504                     put(c.sym, c.details);
4505                 }
4506             }
4507 
4508             Map<Symbol, JCDiagnostic> filterCandidates(Map<Symbol, JCDiagnostic> candidatesMap) {
4509                 Map<Symbol, JCDiagnostic> candidates = new LinkedHashMap<>();
4510                 for (Map.Entry<Symbol, JCDiagnostic> _entry : candidatesMap.entrySet()) {
4511                     JCDiagnostic d = _entry.getValue();
4512                     if (!new Template(MethodCheckDiag.ARITY_MISMATCH.regex()).matches(d)) {
4513                         candidates.put(_entry.getKey(), d);
4514                     }
4515                 }
4516                 return candidates;
4517             }
4518 
4519             private List<JCDiagnostic> candidateDetails(Map<Symbol, JCDiagnostic> candidatesMap, Type site) {
4520                 List<JCDiagnostic> details = List.nil();
4521                 for (Map.Entry<Symbol, JCDiagnostic> _entry : candidatesMap.entrySet()) {
4522                     Symbol sym = _entry.getKey();
4523                     JCDiagnostic detailDiag =
4524                             diags.fragment(Fragments.InapplicableMethod(Kinds.kindName(sym),
4525                                                                         sym.location(site, types),
4526                                                                         sym.asMemberOf(site, types),
4527                                                                         _entry.getValue()));
4528                     details = details.prepend(detailDiag);
4529                 }
4530                 //typically members are visited in reverse order (see Scope)
4531                 //so we need to reverse the candidate list so that candidates
4532                 //conform to source order
4533                 return details;
4534             }
4535 
4536         @Override
4537         protected Pair<Symbol, JCDiagnostic> errCandidate() {
4538             Map<Symbol, JCDiagnostic> candidatesMap = mapCandidates();
4539             Map<Symbol, JCDiagnostic> filteredCandidates = filterCandidates(candidatesMap);
4540             if (filteredCandidates.size() == 1) {
4541                 return Pair.of(filteredCandidates.keySet().iterator().next(),
4542                                filteredCandidates.values().iterator().next());
4543             }
4544             return null;
4545         }
4546     }
4547 
4548     /**
4549      * DiamondError error class indicating that a constructor symbol is not applicable
4550      * given an actual arguments/type argument list using diamond inference.
4551      */
4552     class DiamondError extends InapplicableSymbolError {
4553 
4554         Symbol sym;
4555 
4556         public DiamondError(Symbol sym, MethodResolutionContext context) {
4557             super(sym.kind, "diamondError", context);
4558             this.sym = sym;
4559         }
4560 
4561         JCDiagnostic getDetails() {
4562             return (sym.kind == WRONG_MTH) ?
4563                     ((InapplicableSymbolError)sym.baseSymbol()).errCandidate().snd :
4564                     null;
4565         }
4566 
4567         @Override
4568         JCDiagnostic getDiagnostic(DiagnosticType dkind, DiagnosticPosition pos,
4569                 Symbol location, Type site, Name name, List<Type> argtypes, List<Type> typeargtypes) {
4570             JCDiagnostic details = getDetails();
4571             if (details != null && compactMethodDiags) {
4572                 JCDiagnostic simpleDiag =
4573                         MethodResolutionDiagHelper.rewrite(diags, pos, log.currentSource(), dkind, details);
4574                 if (simpleDiag != null) {
4575                     return simpleDiag;
4576                 }
4577             }
4578             String key = details == null ?
4579                 "cant.apply.diamond" :
4580                 "cant.apply.diamond.1";
4581             return diags.create(dkind, log.currentSource(), pos, key,
4582                     Fragments.Diamond(site.tsym), details);
4583         }
4584     }
4585 
4586     /**
4587      * An InvalidSymbolError error class indicating that a symbol is not
4588      * accessible from a given site
4589      */
4590     class AccessError extends InvalidSymbolError {
4591 
4592         private Env<AttrContext> env;
4593         private Type site;
4594 
4595         AccessError(Env<AttrContext> env, Type site, Symbol sym) {
4596             super(HIDDEN, sym, "access error");
4597             this.env = env;
4598             this.site = site;
4599         }
4600 
4601         @Override
4602         public boolean exists() {
4603             return false;
4604         }
4605 
4606         @Override
4607         JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind,
4608                 DiagnosticPosition pos,
4609                 Symbol location,
4610                 Type site,
4611                 Name name,
4612                 List<Type> argtypes,
4613                 List<Type> typeargtypes) {
4614             if (sym.name == names.init && sym.owner != site.tsym) {
4615                 return new SymbolNotFoundError(ABSENT_MTH).getDiagnostic(dkind,
4616                         pos, location, site, name, argtypes, typeargtypes);
4617             }
4618             else if ((sym.flags() & PUBLIC) != 0
4619                 || (env != null && this.site != null
4620                     && !isAccessible(env, this.site))) {
4621                 if (sym.owner.kind == PCK) {
4622                     return diags.create(dkind, log.currentSource(),
4623                             pos, "not.def.access.package.cant.access",
4624                         sym, sym.location(), inaccessiblePackageReason(env, sym.packge()));
4625                 } else if (   sym.packge() != syms.rootPackage
4626                            && !symbolPackageVisible(env, sym)) {
4627                     return diags.create(dkind, log.currentSource(),
4628                             pos, "not.def.access.class.intf.cant.access.reason",
4629                             sym, sym.location(), sym.location().packge(),
4630                             inaccessiblePackageReason(env, sym.packge()));
4631                 } else {
4632                     return diags.create(dkind, log.currentSource(),
4633                             pos, "not.def.access.class.intf.cant.access",
4634                         sym, sym.location());
4635                 }
4636             }
4637             else if ((sym.flags() & (PRIVATE | PROTECTED)) != 0) {
4638                 return diags.create(dkind, log.currentSource(),
4639                         pos, "report.access", sym,
4640                         asFlagSet(sym.flags() & (PRIVATE | PROTECTED)),
4641                         sym.location());
4642             }
4643             else {
4644                 return diags.create(dkind, log.currentSource(),
4645                         pos, "not.def.public.cant.access", sym, sym.location());
4646             }
4647         }
4648 
4649         private String toString(Type type) {
4650             StringBuilder sb = new StringBuilder();
4651             sb.append(type);
4652             if (type != null) {
4653                 sb.append("[tsym:").append(type.tsym);
4654                 if (type.tsym != null)
4655                     sb.append("packge:").append(type.tsym.packge());
4656                 sb.append("]");
4657             }
4658             return sb.toString();
4659         }
4660     }
4661 
4662     class InvisibleSymbolError extends InvalidSymbolError {
4663 
4664         private final Env<AttrContext> env;
4665         private final boolean suppressError;
4666 
4667         InvisibleSymbolError(Env<AttrContext> env, boolean suppressError, Symbol sym) {
4668             super(HIDDEN, sym, "invisible class error");
4669             this.env = env;
4670             this.suppressError = suppressError;
4671             this.name = sym.name;
4672         }
4673 
4674         @Override
4675         JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind,
4676                 DiagnosticPosition pos,
4677                 Symbol location,
4678                 Type site,
4679                 Name name,
4680                 List<Type> argtypes,
4681                 List<Type> typeargtypes) {
4682             if (suppressError)
4683                 return null;
4684 
4685             if (sym.kind == PCK) {
4686                 JCDiagnostic details = inaccessiblePackageReason(env, sym.packge());
4687                 return diags.create(dkind, log.currentSource(),
4688                         pos, "package.not.visible", sym, details);
4689             }
4690 
4691             JCDiagnostic details = inaccessiblePackageReason(env, sym.packge());
4692 
4693             if (pos.getTree() != null) {
4694                 Symbol o = sym;
4695                 JCTree tree = pos.getTree();
4696 
4697                 while (o.kind != PCK && tree.hasTag(SELECT)) {
4698                     o = o.owner;
4699                     tree = ((JCFieldAccess) tree).selected;
4700                 }
4701 
4702                 if (o.kind == PCK) {
4703                     pos = tree.pos();
4704 
4705                     return diags.create(dkind, log.currentSource(),
4706                             pos, "package.not.visible", o, details);
4707                 }
4708             }
4709 
4710             return diags.create(dkind, log.currentSource(),
4711                     pos, "not.def.access.package.cant.access", sym, sym.packge(), details);
4712         }
4713     }
4714 
4715     JCDiagnostic inaccessiblePackageReason(Env<AttrContext> env, PackageSymbol sym) {
4716         //no dependency:
4717         if (!env.toplevel.modle.readModules.contains(sym.modle)) {
4718             //does not read:
4719             if (sym.modle != syms.unnamedModule) {
4720                 if (env.toplevel.modle != syms.unnamedModule) {
4721                     return diags.fragment(Fragments.NotDefAccessDoesNotRead(env.toplevel.modle,
4722                                                                             sym,
4723                                                                             sym.modle));
4724                 } else {
4725                     return diags.fragment(Fragments.NotDefAccessDoesNotReadFromUnnamed(sym,
4726                                                                                        sym.modle));
4727                 }
4728             } else {
4729                 return diags.fragment(Fragments.NotDefAccessDoesNotReadUnnamed(sym,
4730                                                                                env.toplevel.modle));
4731             }
4732         } else {
4733             if (sym.packge().modle.exports.stream().anyMatch(e -> e.packge == sym)) {
4734                 //not exported to this module:
4735                 if (env.toplevel.modle != syms.unnamedModule) {
4736                     return diags.fragment(Fragments.NotDefAccessNotExportedToModule(sym,
4737                                                                                     sym.modle,
4738                                                                                     env.toplevel.modle));
4739                 } else {
4740                     return diags.fragment(Fragments.NotDefAccessNotExportedToModuleFromUnnamed(sym,
4741                                                                                                sym.modle));
4742                 }
4743             } else {
4744                 //not exported:
4745                 if (env.toplevel.modle != syms.unnamedModule) {
4746                     return diags.fragment(Fragments.NotDefAccessNotExported(sym,
4747                                                                             sym.modle));
4748                 } else {
4749                     return diags.fragment(Fragments.NotDefAccessNotExportedFromUnnamed(sym,
4750                                                                                        sym.modle));
4751                 }
4752             }
4753         }
4754     }
4755 
4756     /**
4757      * InvalidSymbolError error class indicating that an instance member
4758      * has erroneously been accessed from a static context.
4759      */
4760     class StaticError extends InvalidSymbolError {
4761 
4762         StaticError(Symbol sym) {
4763             this(sym, "static error");
4764         }
4765 
4766         StaticError(Symbol sym, String debugName) {
4767             super(STATICERR, sym, debugName);
4768         }
4769 
4770         @Override
4771         JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind,
4772                 DiagnosticPosition pos,
4773                 Symbol location,
4774                 Type site,
4775                 Name name,
4776                 List<Type> argtypes,
4777                 List<Type> typeargtypes) {
4778             Symbol errSym = ((sym.kind == TYP && sym.type.hasTag(CLASS))
4779                 ? types.erasure(sym.type).tsym
4780                 : sym);
4781             return diags.create(dkind, log.currentSource(), pos,
4782                     "non-static.cant.be.ref", kindName(sym), errSym);
4783         }
4784     }
4785 
4786     /**
4787      * Specialization of {@link StaticError} for illegal
4788      * creation of local class instances from a static context.
4789      */
4790     class BadLocalClassCreation extends StaticError {
4791         BadLocalClassCreation(Symbol sym) {
4792             super(sym, "bad local class creation");
4793         }
4794 
4795         @Override
4796         JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind,
4797                                    DiagnosticPosition pos,
4798                                    Symbol location,
4799                                    Type site,
4800                                    Name name,
4801                                    List<Type> argtypes,
4802                                    List<Type> typeargtypes) {
4803             return diags.create(dkind, log.currentSource(), pos,
4804                     "local.cant.be.inst.static", kindName(sym), sym);
4805         }
4806     }
4807 
4808     /**
4809      * Specialization of {@link InvalidSymbolError} for illegal
4810      * early accesses within a constructor prologue.
4811      */
4812     class RefBeforeCtorCalledError extends StaticError {
4813 
4814         RefBeforeCtorCalledError(Symbol sym) {
4815             super(sym, "prologue error");
4816         }
4817 
4818         @Override
4819         JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind,
4820                 DiagnosticPosition pos,
4821                 Symbol location,
4822                 Type site,
4823                 Name name,
4824                 List<Type> argtypes,
4825                 List<Type> typeargtypes) {
4826             Symbol errSym = ((sym.kind == TYP && sym.type.hasTag(CLASS))
4827                 ? types.erasure(sym.type).tsym
4828                 : sym);
4829             return diags.create(dkind, log.currentSource(), pos,
4830                     "cant.ref.before.ctor.called", errSym);
4831         }
4832     }
4833 
4834     /**
4835      * InvalidSymbolError error class indicating that a pair of symbols
4836      * (either methods, constructors or operands) are ambiguous
4837      * given an actual arguments/type argument list.
4838      */
4839     class AmbiguityError extends ResolveError {
4840 
4841         /** The other maximally specific symbol */
4842         List<Symbol> ambiguousSyms = List.nil();
4843 
4844         @Override
4845         public boolean exists() {
4846             return true;
4847         }
4848 
4849         AmbiguityError(Symbol sym1, Symbol sym2) {
4850             super(AMBIGUOUS, "ambiguity error");
4851             ambiguousSyms = flatten(sym2).appendList(flatten(sym1));
4852         }
4853 
4854         private List<Symbol> flatten(Symbol sym) {
4855             if (sym.kind == AMBIGUOUS) {
4856                 return ((AmbiguityError)sym.baseSymbol()).ambiguousSyms;
4857             } else {
4858                 return List.of(sym);
4859             }
4860         }
4861 
4862         AmbiguityError addAmbiguousSymbol(Symbol s) {
4863             ambiguousSyms = ambiguousSyms.prepend(s);
4864             return this;
4865         }
4866 
4867         @Override
4868         JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind,
4869                 DiagnosticPosition pos,
4870                 Symbol location,
4871                 Type site,
4872                 Name name,
4873                 List<Type> argtypes,
4874                 List<Type> typeargtypes) {
4875             List<Symbol> diagSyms = ambiguousSyms.reverse();
4876             Symbol s1 = diagSyms.head;
4877             Symbol s2 = diagSyms.tail.head;
4878             Name sname = s1.name;
4879             if (sname == names.init) sname = s1.owner.name;
4880             return diags.create(dkind, log.currentSource(),
4881                     pos, "ref.ambiguous", sname,
4882                     kindName(s1),
4883                     s1,
4884                     s1.location(site, types),
4885                     kindName(s2),
4886                     s2,
4887                     s2.location(site, types));
4888         }
4889 
4890         /**
4891          * If multiple applicable methods are found during overload and none of them
4892          * is more specific than the others, attempt to merge their signatures.
4893          */
4894         Symbol mergeAbstracts(Type site) {
4895             List<Symbol> ambiguousInOrder = ambiguousSyms.reverse();
4896             return types.mergeAbstracts(ambiguousInOrder, site, true).orElse(this);
4897         }
4898 
4899         @Override
4900         protected Symbol access(Name name, TypeSymbol location) {
4901             Symbol firstAmbiguity = ambiguousSyms.last();
4902             return firstAmbiguity.kind == TYP ?
4903                     types.createErrorType(name, location, firstAmbiguity.type).tsym :
4904                     firstAmbiguity;
4905         }
4906     }
4907 
4908     class BadVarargsMethod extends ResolveError {
4909 
4910         ResolveError delegatedError;
4911 
4912         BadVarargsMethod(ResolveError delegatedError) {
4913             super(delegatedError.kind, "badVarargs");
4914             this.delegatedError = delegatedError;
4915         }
4916 
4917         @Override
4918         public Symbol baseSymbol() {
4919             return delegatedError.baseSymbol();
4920         }
4921 
4922         @Override
4923         protected Symbol access(Name name, TypeSymbol location) {
4924             return delegatedError.access(name, location);
4925         }
4926 
4927         @Override
4928         public boolean exists() {
4929             return true;
4930         }
4931 
4932         @Override
4933         JCDiagnostic getDiagnostic(DiagnosticType dkind, DiagnosticPosition pos, Symbol location, Type site, Name name, List<Type> argtypes, List<Type> typeargtypes) {
4934             return delegatedError.getDiagnostic(dkind, pos, location, site, name, argtypes, typeargtypes);
4935         }
4936     }
4937 
4938     /**
4939      * BadMethodReferenceError error class indicating that a method reference symbol has been found,
4940      * but with the wrong staticness.
4941      */
4942     class BadMethodReferenceError extends StaticError {
4943 
4944         boolean unboundLookup;
4945 
4946         public BadMethodReferenceError(Symbol sym, boolean unboundLookup) {
4947             super(sym, "bad method ref error");
4948             this.unboundLookup = unboundLookup;
4949         }
4950 
4951         @Override
4952         JCDiagnostic getDiagnostic(DiagnosticType dkind, DiagnosticPosition pos, Symbol location, Type site, Name name, List<Type> argtypes, List<Type> typeargtypes) {
4953             final String key;
4954             if (!unboundLookup) {
4955                 key = "bad.static.method.in.bound.lookup";
4956             } else if (sym.isStatic()) {
4957                 key = "bad.static.method.in.unbound.lookup";
4958             } else {
4959                 key = "bad.instance.method.in.unbound.lookup";
4960             }
4961             return sym.kind.isResolutionError() ?
4962                     ((ResolveError)sym).getDiagnostic(dkind, pos, location, site, name, argtypes, typeargtypes) :
4963                     diags.create(dkind, log.currentSource(), pos, key, Kinds.kindName(sym), sym);
4964         }
4965     }
4966 
4967     class BadClassFileError extends InvalidSymbolError {
4968 
4969         private final CompletionFailure ex;
4970 
4971         public BadClassFileError(CompletionFailure ex) {
4972             super(HIDDEN, ex.sym, "BadClassFileError");
4973             this.name = sym.name;
4974             this.ex = ex;
4975         }
4976 
4977         @Override
4978         JCDiagnostic getDiagnostic(DiagnosticType dkind, DiagnosticPosition pos, Symbol location, Type site, Name name, List<Type> argtypes, List<Type> typeargtypes) {
4979             JCDiagnostic d = diags.create(dkind, log.currentSource(), pos,
4980                 "cant.access", ex.sym, ex.getDetailValue());
4981 
4982             d.setFlag(DiagnosticFlag.NON_DEFERRABLE);
4983             return d;
4984         }
4985 
4986     }
4987 
4988     /**
4989      * Helper class for method resolution diagnostic simplification.
4990      * Certain resolution diagnostic are rewritten as simpler diagnostic
4991      * where the enclosing resolution diagnostic (i.e. 'inapplicable method')
4992      * is stripped away, as it doesn't carry additional info. The logic
4993      * for matching a given diagnostic is given in terms of a template
4994      * hierarchy: a diagnostic template can be specified programmatically,
4995      * so that only certain diagnostics are matched. Each templete is then
4996      * associated with a rewriter object that carries out the task of rewtiting
4997      * the diagnostic to a simpler one.
4998      */
4999     static class MethodResolutionDiagHelper {
5000 
5001         /**
5002          * A diagnostic rewriter transforms a method resolution diagnostic
5003          * into a simpler one
5004          */
5005         interface DiagnosticRewriter {
5006             JCDiagnostic rewriteDiagnostic(JCDiagnostic.Factory diags,
5007                     DiagnosticPosition preferredPos, DiagnosticSource preferredSource,
5008                     DiagnosticType preferredKind, JCDiagnostic d);
5009         }
5010 
5011         /**
5012          * A diagnostic template is made up of two ingredients: (i) a regular
5013          * expression for matching a diagnostic key and (ii) a list of sub-templates
5014          * for matching diagnostic arguments.
5015          */
5016         static class Template {
5017 
5018             /** regex used to match diag key */
5019             String regex;
5020 
5021             /** templates used to match diagnostic args */
5022             Template[] subTemplates;
5023 
5024             Template(String key, Template... subTemplates) {
5025                 this.regex = key;
5026                 this.subTemplates = subTemplates;
5027             }
5028 
5029             /**
5030              * Returns true if the regex matches the diagnostic key and if
5031              * all diagnostic arguments are matches by corresponding sub-templates.
5032              */
5033             boolean matches(Object o) {
5034                 JCDiagnostic d = (JCDiagnostic)o;
5035                 Object[] args = d.getArgs();
5036                 if (!d.getCode().matches(regex) ||
5037                         subTemplates.length != d.getArgs().length) {
5038                     return false;
5039                 }
5040                 for (int i = 0; i < args.length ; i++) {
5041                     if (!subTemplates[i].matches(args[i])) {
5042                         return false;
5043                     }
5044                 }
5045                 return true;
5046             }
5047         }
5048 
5049         /**
5050          * Common rewriter for all argument mismatch simplifications.
5051          */
5052         static class ArgMismatchRewriter implements DiagnosticRewriter {
5053 
5054             /** the index of the subdiagnostic to be used as primary. */
5055             int causeIndex;
5056 
5057             public ArgMismatchRewriter(int causeIndex) {
5058                 this.causeIndex = causeIndex;
5059             }
5060 
5061             @Override
5062             public JCDiagnostic rewriteDiagnostic(JCDiagnostic.Factory diags,
5063                     DiagnosticPosition preferredPos, DiagnosticSource preferredSource,
5064                     DiagnosticType preferredKind, JCDiagnostic d) {
5065                 JCDiagnostic cause = (JCDiagnostic)d.getArgs()[causeIndex];
5066                 DiagnosticPosition pos = d.getDiagnosticPosition();
5067                 if (pos == null) {
5068                     pos = preferredPos;
5069                 }
5070                 return diags.create(preferredKind, preferredSource, pos,
5071                         "prob.found.req", cause);
5072             }
5073         }
5074 
5075         /** a dummy template that match any diagnostic argument */
5076         static final Template skip = new Template("") {
5077             @Override
5078             boolean matches(Object d) {
5079                 return true;
5080             }
5081         };
5082 
5083         /** template for matching inference-free arguments mismatch failures */
5084         static final Template argMismatchTemplate = new Template(MethodCheckDiag.ARG_MISMATCH.regex(), skip);
5085 
5086         /** template for matching inference related arguments mismatch failures */
5087         static final Template inferArgMismatchTemplate = new Template(MethodCheckDiag.ARG_MISMATCH.regex(), skip, skip) {
5088             @Override
5089             boolean matches(Object o) {
5090                 if (!super.matches(o)) {
5091                     return false;
5092                 }
5093                 JCDiagnostic d = (JCDiagnostic)o;
5094                 @SuppressWarnings("unchecked")
5095                 List<Type> tvars = (List<Type>)d.getArgs()[0];
5096                 return !containsAny(d, tvars);
5097             }
5098 
5099             BiPredicate<Object, List<Type>> containsPredicate = (o, ts) -> {
5100                 if (o instanceof Type type) {
5101                     return type.containsAny(ts);
5102                 } else if (o instanceof JCDiagnostic diagnostic) {
5103                     return containsAny(diagnostic, ts);
5104                 } else {
5105                     return false;
5106                 }
5107             };
5108 
5109             boolean containsAny(JCDiagnostic d, List<Type> ts) {
5110                 return Stream.of(d.getArgs())
5111                         .anyMatch(o -> containsPredicate.test(o, ts));
5112             }
5113         };
5114 
5115         /** rewriter map used for method resolution simplification */
5116         static final Map<Template, DiagnosticRewriter> rewriters = new LinkedHashMap<>();
5117 
5118         static {
5119             rewriters.put(argMismatchTemplate, new ArgMismatchRewriter(0));
5120             rewriters.put(inferArgMismatchTemplate, new ArgMismatchRewriter(1));
5121         }
5122 
5123         /**
5124          * Main entry point for diagnostic rewriting - given a diagnostic, see if any templates matches it,
5125          * and rewrite it accordingly.
5126          */
5127         static JCDiagnostic rewrite(JCDiagnostic.Factory diags, DiagnosticPosition pos, DiagnosticSource source,
5128                                     DiagnosticType dkind, JCDiagnostic d) {
5129             for (Map.Entry<Template, DiagnosticRewriter> _entry : rewriters.entrySet()) {
5130                 if (_entry.getKey().matches(d)) {
5131                     JCDiagnostic simpleDiag =
5132                             _entry.getValue().rewriteDiagnostic(diags, pos, source, dkind, d);
5133                     simpleDiag.setFlag(DiagnosticFlag.COMPRESSED);
5134                     return simpleDiag;
5135                 }
5136             }
5137             return null;
5138         }
5139     }
5140 
5141     enum MethodResolutionPhase {
5142         BASIC(false, false),
5143         BOX(true, false),
5144         VARARITY(true, true) {
5145             @Override
5146             public Symbol mergeResults(Symbol bestSoFar, Symbol sym) {
5147                 //Check invariants (see {@code LookupHelper.shouldStop})
5148                 Assert.check(bestSoFar.kind.isResolutionError() && bestSoFar.kind != AMBIGUOUS);
5149                 if (!sym.kind.isResolutionError()) {
5150                     //varargs resolution successful
5151                     return sym;
5152                 } else {
5153                     //pick best error
5154                     switch (bestSoFar.kind) {
5155                         case WRONG_MTH:
5156                         case WRONG_MTHS:
5157                             //Override previous errors if they were caused by argument mismatch.
5158                             //This generally means preferring current symbols - but we need to pay
5159                             //attention to the fact that the varargs lookup returns 'less' candidates
5160                             //than the previous rounds, and adjust that accordingly.
5161                             switch (sym.kind) {
5162                                 case WRONG_MTH:
5163                                     //if the previous round matched more than one method, return that
5164                                     //result instead
5165                                     return bestSoFar.kind == WRONG_MTHS ?
5166                                             bestSoFar : sym;
5167                                 case ABSENT_MTH:
5168                                     //do not override erroneous symbol if the arity lookup did not
5169                                     //match any method
5170                                     return bestSoFar;
5171                                 case WRONG_MTHS:
5172                                 default:
5173                                     //safe to override
5174                                     return sym;
5175                             }
5176                         default:
5177                             //otherwise, return first error
5178                             return bestSoFar;
5179                     }
5180                 }
5181             }
5182         };
5183 
5184         final boolean isBoxingRequired;
5185         final boolean isVarargsRequired;
5186 
5187         MethodResolutionPhase(boolean isBoxingRequired, boolean isVarargsRequired) {
5188            this.isBoxingRequired = isBoxingRequired;
5189            this.isVarargsRequired = isVarargsRequired;
5190         }
5191 
5192         public boolean isBoxingRequired() {
5193             return isBoxingRequired;
5194         }
5195 
5196         public boolean isVarargsRequired() {
5197             return isVarargsRequired;
5198         }
5199 
5200         public Symbol mergeResults(Symbol prev, Symbol sym) {
5201             return sym;
5202         }
5203     }
5204 
5205     final List<MethodResolutionPhase> methodResolutionSteps = List.of(BASIC, BOX, VARARITY);
5206 
5207     /**
5208      * A resolution context is used to keep track of intermediate results of
5209      * overload resolution, such as list of method that are not applicable
5210      * (used to generate more precise diagnostics) and so on. Resolution contexts
5211      * can be nested - this means that when each overload resolution routine should
5212      * work within the resolution context it created.
5213      */
5214     class MethodResolutionContext {
5215 
5216         private List<Candidate> candidates = List.nil();
5217 
5218         MethodResolutionPhase step = null;
5219 
5220         MethodCheck methodCheck = resolveMethodCheck;
5221 
5222         private boolean internalResolution = false;
5223         private DeferredAttr.AttrMode attrMode = DeferredAttr.AttrMode.SPECULATIVE;
5224 
5225         void addInapplicableCandidate(Symbol sym, JCDiagnostic details) {
5226             Candidate c = new Candidate(currentResolutionContext.step, sym, details, null);
5227             candidates = candidates.append(c);
5228         }
5229 
5230         void addApplicableCandidate(Symbol sym, Type mtype) {
5231             Candidate c = new Candidate(currentResolutionContext.step, sym, null, mtype);
5232             candidates = candidates.append(c);
5233         }
5234 
5235         DeferredAttrContext deferredAttrContext(Symbol sym, InferenceContext inferenceContext, ResultInfo pendingResult, Warner warn) {
5236             DeferredAttrContext parent = (pendingResult == null)
5237                 ? deferredAttr.emptyDeferredAttrContext
5238                 : pendingResult.checkContext.deferredAttrContext();
5239             return deferredAttr.new DeferredAttrContext(attrMode, sym, step,
5240                     inferenceContext, parent, warn);
5241         }
5242 
5243         /**
5244          * This class represents an overload resolution candidate. There are two
5245          * kinds of candidates: applicable methods and inapplicable methods;
5246          * applicable methods have a pointer to the instantiated method type,
5247          * while inapplicable candidates contain further details about the
5248          * reason why the method has been considered inapplicable.
5249          */
5250         class Candidate {
5251 
5252             final MethodResolutionPhase step;
5253             final Symbol sym;
5254             final JCDiagnostic details;
5255             final Type mtype;
5256 
5257             private Candidate(MethodResolutionPhase step, Symbol sym, JCDiagnostic details, Type mtype) {
5258                 this.step = step;
5259                 this.sym = sym;
5260                 this.details = details;
5261                 this.mtype = mtype;
5262             }
5263 
5264             boolean isApplicable() {
5265                 return mtype != null;
5266             }
5267         }
5268 
5269         DeferredAttr.AttrMode attrMode() {
5270             return attrMode;
5271         }
5272 
5273         boolean internal() {
5274             return internalResolution;
5275         }
5276     }
5277 
5278     MethodResolutionContext currentResolutionContext = null;
5279 }