Resolve.java revision 3707:645100bea379
1195333Simp/* 2195333Simp * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. 3195333Simp * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4195333Simp * 5195333Simp * This code is free software; you can redistribute it and/or modify it 6195333Simp * under the terms of the GNU General Public License version 2 only, as 7195333Simp * published by the Free Software Foundation. Oracle designates this 8195333Simp * particular file as subject to the "Classpath" exception as provided 9195333Simp * by Oracle in the LICENSE file that accompanied this code. 10195333Simp * 11195333Simp * This code is distributed in the hope that it will be useful, but WITHOUT 12195333Simp * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13195333Simp * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14195333Simp * version 2 for more details (a copy is included in the LICENSE file that 15195333Simp * accompanied this code). 16195333Simp * 17195333Simp * You should have received a copy of the GNU General Public License version 18195333Simp * 2 along with this work; if not, write to the Free Software Foundation, 19195333Simp * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20195333Simp * 21195333Simp * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22195333Simp * or visit www.oracle.com if you need additional information or have any 23195333Simp * questions. 24195333Simp */ 25195333Simp 26195333Simppackage com.sun.tools.javac.comp; 27195333Simp 28195333Simpimport com.sun.tools.javac.api.Formattable.LocalizedString; 29195333Simpimport com.sun.tools.javac.code.*; 30195333Simpimport com.sun.tools.javac.code.Scope.WriteableScope; 31195333Simpimport com.sun.tools.javac.code.Symbol.*; 32195333Simpimport com.sun.tools.javac.code.Type.*; 33195333Simpimport com.sun.tools.javac.comp.Attr.ResultInfo; 34195333Simpimport com.sun.tools.javac.comp.Check.CheckContext; 35195333Simpimport com.sun.tools.javac.comp.DeferredAttr.AttrMode; 36195333Simpimport com.sun.tools.javac.comp.DeferredAttr.DeferredAttrContext; 37195333Simpimport com.sun.tools.javac.comp.DeferredAttr.DeferredType; 38195333Simpimport com.sun.tools.javac.comp.Infer.FreeTypeListener; 39195333Simpimport com.sun.tools.javac.comp.Resolve.MethodResolutionContext.Candidate; 40195333Simpimport com.sun.tools.javac.comp.Resolve.MethodResolutionDiagHelper.Template; 41195333Simpimport com.sun.tools.javac.comp.Resolve.ReferenceLookupResult.StaticKind; 42195333Simpimport com.sun.tools.javac.jvm.*; 43195333Simpimport com.sun.tools.javac.main.Option; 44195333Simpimport com.sun.tools.javac.tree.*; 45195333Simpimport com.sun.tools.javac.tree.JCTree.*; 46195333Simpimport com.sun.tools.javac.tree.JCTree.JCMemberReference.ReferenceKind; 47195333Simpimport com.sun.tools.javac.tree.JCTree.JCPolyExpression.*; 48195333Simpimport com.sun.tools.javac.util.*; 49195333Simpimport com.sun.tools.javac.util.DefinedBy.Api; 50195333Simpimport com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag; 51195333Simpimport com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; 52195333Simpimport com.sun.tools.javac.util.JCDiagnostic.DiagnosticType; 53195333Simp 54195333Simpimport java.util.Arrays; 55195333Simpimport java.util.Collection; 56195333Simpimport java.util.EnumSet; 57195333Simpimport java.util.Iterator; 58195333Simpimport java.util.LinkedHashMap; 59195333Simpimport java.util.Map; 60195333Simpimport java.util.function.BiPredicate; 61195333Simpimport java.util.stream.Stream; 62195333Simp 63195333Simpimport javax.lang.model.element.ElementVisitor; 64195333Simp 65195333Simpimport static com.sun.tools.javac.code.Flags.*; 66195333Simpimport static com.sun.tools.javac.code.Flags.BLOCK; 67195333Simpimport static com.sun.tools.javac.code.Flags.STATIC; 68195333Simpimport static com.sun.tools.javac.code.Kinds.*; 69195333Simpimport static com.sun.tools.javac.code.Kinds.Kind.*; 70195333Simpimport static com.sun.tools.javac.code.TypeTag.*; 71195333Simpimport static com.sun.tools.javac.comp.Resolve.MethodResolutionPhase.*; 72195333Simpimport static com.sun.tools.javac.tree.JCTree.Tag.*; 73195333Simp 74195333Simp/** Helper class for name resolution, used mostly by the attribution phase. 75195333Simp * 76195333Simp * <p><b>This is NOT part of any supported API. 77203697Sneel * If you write code that depends on this, you do so at your own risk. 78203697Sneel * This code and its internal interfaces are subject to change or 79203697Sneel * deletion without notice.</b> 80203697Sneel */ 81195333Simppublic class Resolve { 82195333Simp protected static final Context.Key<Resolve> resolveKey = new Context.Key<>(); 83195333Simp 84195333Simp Names names; 85195333Simp Log log; 86195333Simp Symtab syms; 87195333Simp Attr attr; 88195333Simp DeferredAttr deferredAttr; 89195333Simp Check chk; 90195333Simp Infer infer; 91195333Simp ClassFinder finder; 92195333Simp Types types; 93195333Simp JCDiagnostic.Factory diags; 94195333Simp public final boolean allowMethodHandles; 95195333Simp public final boolean allowFunctionalInterfaceMostSpecific; 96195333Simp public final boolean allowModules; 97195333Simp public final boolean checkVarargsAccessAfterResolution; 98195333Simp private final boolean compactMethodDiags; 99195333Simp final EnumSet<VerboseResolutionMode> verboseResolutionMode; 100203000Sneel 101203000Sneel private final boolean checkModuleAccess; 102198669Srrs 103198669Srrs WriteableScope polymorphicSignatureScope; 104198669Srrs 105198669Srrs protected Resolve(Context context) { 106198669Srrs context.put(resolveKey, this); 107198669Srrs syms = Symtab.instance(context); 108195333Simp 109203510Sneel varNotFound = new SymbolNotFoundError(ABSENT_VAR); 110203510Sneel methodNotFound = new SymbolNotFoundError(ABSENT_MTH); 111203510Sneel typeNotFound = new SymbolNotFoundError(ABSENT_TYP); 112203510Sneel referenceNotFound = new ReferenceLookupResult(methodNotFound, null); 113203510Sneel 114203510Sneel names = Names.instance(context); 115203510Sneel log = Log.instance(context); 116203510Sneel attr = Attr.instance(context); 117203510Sneel deferredAttr = DeferredAttr.instance(context); 118203510Sneel chk = Check.instance(context); 119203510Sneel infer = Infer.instance(context); 120203510Sneel finder = ClassFinder.instance(context); 121203697Sneel types = Types.instance(context); 122203697Sneel diags = JCDiagnostic.Factory.instance(context); 123203697Sneel Source source = Source.instance(context); 124203697Sneel Options options = Options.instance(context); 125203697Sneel compactMethodDiags = options.isSet(Option.XDIAGS, "compact") || 126203697Sneel options.isUnset(Option.XDIAGS) && options.isUnset("rawDiagnostics"); 127203697Sneel verboseResolutionMode = VerboseResolutionMode.getVerboseResolutionMode(options); 128203697Sneel Target target = Target.instance(context); 129203697Sneel allowMethodHandles = target.hasMethodHandles(); 130203697Sneel allowFunctionalInterfaceMostSpecific = source.allowFunctionalInterfaceMostSpecific(); 131203697Sneel checkVarargsAccessAfterResolution = 132203697Sneel source.allowPostApplicabilityVarargsAccessCheck(); 133203697Sneel polymorphicSignatureScope = WriteableScope.create(syms.noSymbol); 134203510Sneel 135203510Sneel inapplicableMethodException = new InapplicableMethodException(diags); 136203510Sneel 137203510Sneel allowModules = source.allowModules(); 138195333Simp 139195333Simp // The following is required, for now, to support building 140195333Simp // Swing beaninfo via javadoc. 141195333Simp checkModuleAccess = !options.isSet("noModules"); 142195333Simp } 143195333Simp 144195333Simp /** error symbols, which are returned when resolution fails 145195333Simp */ 146195333Simp private final SymbolNotFoundError varNotFound; 147195333Simp private final SymbolNotFoundError methodNotFound; 148195333Simp private final SymbolNotFoundError typeNotFound; 149195333Simp 150195333Simp /** empty reference lookup result */ 151195333Simp private final ReferenceLookupResult referenceNotFound; 152195333Simp 153195333Simp public static Resolve instance(Context context) { 154195333Simp Resolve instance = context.get(resolveKey); 155195333Simp if (instance == null) 156195333Simp instance = new Resolve(context); 157195333Simp return instance; 158195333Simp } 159195333Simp 160195333Simp private static Symbol bestOf(Symbol s1, 161195333Simp Symbol s2) { 162195333Simp return s1.kind.betterThan(s2.kind) ? s1 : s2; 163195333Simp } 164195333Simp 165195333Simp // <editor-fold defaultstate="collapsed" desc="Verbose resolution diagnostics support"> 166195333Simp enum VerboseResolutionMode { 167195333Simp SUCCESS("success"), 168195333Simp FAILURE("failure"), 169195333Simp APPLICABLE("applicable"), 170195333Simp INAPPLICABLE("inapplicable"), 171195333Simp DEFERRED_INST("deferred-inference"), 172195333Simp PREDEF("predef"), 173195333Simp OBJECT_INIT("object-init"), 174195333Simp INTERNAL("internal"); 175195333Simp 176195333Simp final String opt; 177195333Simp 178195333Simp private VerboseResolutionMode(String opt) { 179195333Simp this.opt = opt; 180195333Simp } 181195333Simp 182195333Simp static EnumSet<VerboseResolutionMode> getVerboseResolutionMode(Options opts) { 183195333Simp String s = opts.get("debug.verboseResolution"); 184195333Simp EnumSet<VerboseResolutionMode> res = EnumSet.noneOf(VerboseResolutionMode.class); 185195333Simp if (s == null) return res; 186195333Simp if (s.contains("all")) { 187195333Simp res = EnumSet.allOf(VerboseResolutionMode.class); 188195333Simp } 189195333Simp Collection<String> args = Arrays.asList(s.split(",")); 190195333Simp for (VerboseResolutionMode mode : values()) { 191195333Simp if (args.contains(mode.opt)) { 192195333Simp res.add(mode); 193195333Simp } else if (args.contains("-" + mode.opt)) { 194195333Simp res.remove(mode); 195195333Simp } 196195333Simp } 197195333Simp return res; 198195333Simp } 199195333Simp } 200195333Simp 201195333Simp void reportVerboseResolutionDiagnostic(DiagnosticPosition dpos, Name name, Type site, 202195333Simp List<Type> argtypes, List<Type> typeargtypes, Symbol bestSoFar) { 203195333Simp boolean success = !bestSoFar.kind.isResolutionError(); 204195333Simp 205195333Simp if (success && !verboseResolutionMode.contains(VerboseResolutionMode.SUCCESS)) { 206195333Simp return; 207202954Sgonzo } else if (!success && !verboseResolutionMode.contains(VerboseResolutionMode.FAILURE)) { 208195333Simp return; 209195333Simp } 210195333Simp 211195333Simp if (bestSoFar.name == names.init && 212195333Simp bestSoFar.owner == syms.objectType.tsym && 213195333Simp !verboseResolutionMode.contains(VerboseResolutionMode.OBJECT_INIT)) { 214195333Simp return; //skip diags for Object constructor resolution 215195333Simp } else if (site == syms.predefClass.type && 216195333Simp !verboseResolutionMode.contains(VerboseResolutionMode.PREDEF)) { 217195333Simp return; //skip spurious diags for predef symbols (i.e. operators) 218195333Simp } else if (currentResolutionContext.internalResolution && 219195333Simp !verboseResolutionMode.contains(VerboseResolutionMode.INTERNAL)) { 220195333Simp return; 221203000Sneel } 222203000Sneel 223204689Sneel int pos = 0; 224204689Sneel int mostSpecificPos = -1; 225204689Sneel ListBuffer<JCDiagnostic> subDiags = new ListBuffer<>(); 226204689Sneel for (Candidate c : currentResolutionContext.candidates) { 227204689Sneel if (currentResolutionContext.step != c.step || 228204689Sneel (c.isApplicable() && !verboseResolutionMode.contains(VerboseResolutionMode.APPLICABLE)) || 229204689Sneel (!c.isApplicable() && !verboseResolutionMode.contains(VerboseResolutionMode.INAPPLICABLE))) { 230203000Sneel continue; 231203000Sneel } else { 232203000Sneel subDiags.append(c.isApplicable() ? 233203000Sneel getVerboseApplicableCandidateDiag(pos, c.sym, c.mtype) : 234203000Sneel getVerboseInapplicableCandidateDiag(pos, c.sym, c.details)); 235203000Sneel if (c.sym == bestSoFar) 236203000Sneel mostSpecificPos = pos; 237203000Sneel pos++; 238203000Sneel } 239203000Sneel } 240203000Sneel String key = success ? "verbose.resolve.multi" : "verbose.resolve.multi.1"; 241203000Sneel List<Type> argtypes2 = argtypes.map(deferredAttr.new RecoveryDeferredTypeMap(AttrMode.SPECULATIVE, bestSoFar, currentResolutionContext.step)); 242203000Sneel JCDiagnostic main = diags.note(log.currentSource(), dpos, key, name, 243203000Sneel site.tsym, mostSpecificPos, currentResolutionContext.step, 244203000Sneel methodArguments(argtypes2), 245203000Sneel methodArguments(typeargtypes)); 246203000Sneel JCDiagnostic d = new JCDiagnostic.MultilineDiagnostic(main, subDiags.toList()); 247203000Sneel log.report(d); 248203000Sneel } 249203000Sneel 250195333Simp JCDiagnostic getVerboseApplicableCandidateDiag(int pos, Symbol sym, Type inst) { 251195333Simp JCDiagnostic subDiag = null; 252195333Simp if (sym.type.hasTag(FORALL)) { 253195333Simp subDiag = diags.fragment("partial.inst.sig", inst); 254195333Simp } 255195333Simp 256195333Simp String key = subDiag == null ? 257195333Simp "applicable.method.found" : 258195333Simp "applicable.method.found.1"; 259195333Simp 260195333Simp return diags.fragment(key, pos, sym, subDiag); 261195333Simp } 262195333Simp 263195333Simp JCDiagnostic getVerboseInapplicableCandidateDiag(int pos, Symbol sym, JCDiagnostic subDiag) { 264195333Simp return diags.fragment("not.applicable.method.found", pos, sym, subDiag); 265195333Simp } 266195333Simp // </editor-fold> 267195333Simp 268195333Simp/* ************************************************************************ 269195333Simp * Identifier resolution 270195333Simp *************************************************************************/ 271195333Simp 272195333Simp /** An environment is "static" if its static level is greater than 273195333Simp * the one of its outer environment 274195333Simp */ 275195333Simp protected static boolean isStatic(Env<AttrContext> env) { 276195333Simp return env.outer != null && env.info.staticLevel > env.outer.info.staticLevel; 277195333Simp } 278195333Simp 279195333Simp /** An environment is an "initializer" if it is a constructor or 280195333Simp * an instance initializer. 281195333Simp */ 282195333Simp static boolean isInitializer(Env<AttrContext> env) { 283195333Simp Symbol owner = env.info.scope.owner; 284195333Simp return owner.isConstructor() || 285195333Simp owner.owner.kind == TYP && 286195333Simp (owner.kind == VAR || 287195333Simp owner.kind == MTH && (owner.flags() & BLOCK) != 0) && 288195333Simp (owner.flags() & STATIC) == 0; 289195333Simp } 290195333Simp 291195333Simp /** Is class accessible in given evironment? 292195333Simp * @param env The current environment. 293195333Simp * @param c The class whose accessibility is checked. 294195333Simp */ 295195333Simp public boolean isAccessible(Env<AttrContext> env, TypeSymbol c) { 296195333Simp return isAccessible(env, c, false); 297202864Sneel } 298202864Sneel 299202864Sneel public boolean isAccessible(Env<AttrContext> env, TypeSymbol c, boolean checkInner) { 300202864Sneel 301202864Sneel /* 15.9.5.1: Note that it is possible for the signature of the anonymous constructor 302202864Sneel to refer to an inaccessible type 303202864Sneel */ 304202864Sneel if (env.enclMethod != null && (env.enclMethod.mods.flags & ANONCONSTR) != 0) 305202864Sneel return true; 306202864Sneel 307202864Sneel boolean isAccessible = false; 308202864Sneel switch ((short)(c.flags() & AccessFlags)) { 309203697Sneel case PRIVATE: 310195333Simp isAccessible = 311203697Sneel env.enclClass.sym.outermostClass() == 312203697Sneel c.owner.outermostClass(); 313203697Sneel break; 314203697Sneel case 0: 315203697Sneel isAccessible = 316203697Sneel env.toplevel.packge == c.owner // fast special case 317203697Sneel || 318203697Sneel env.toplevel.packge == c.packge(); 319203697Sneel break; 320203697Sneel default: // error recovery 321203697Sneel isAccessible = true; 322203697Sneel break; 323203697Sneel case PUBLIC: 324203697Sneel isAccessible = true; 325203697Sneel if (allowModules && checkModuleAccess) { 326203697Sneel ModuleSymbol currModule = env.toplevel.modle; 327203697Sneel currModule.complete(); 328203697Sneel PackageSymbol p = c.packge(); 329203697Sneel isAccessible = 330203697Sneel (currModule == p.modle) || currModule.visiblePackages.get(p.fullname) == p || p == syms.rootPackage; 331203697Sneel } else { 332203697Sneel isAccessible = true; 333203697Sneel } 334203697Sneel break; 335203697Sneel case PROTECTED: 336203697Sneel isAccessible = 337203697Sneel env.toplevel.packge == c.owner // fast special case 338203697Sneel || 339203697Sneel env.toplevel.packge == c.packge() 340203697Sneel || 341203697Sneel isInnerSubClass(env.enclClass.sym, c.owner); 342203697Sneel break; 343203697Sneel } 344203697Sneel return (checkInner == false || c.type.getEnclosingType() == Type.noType) ? 345203697Sneel isAccessible : 346203697Sneel isAccessible && isAccessible(env, c.type.getEnclosingType(), checkInner); 347203697Sneel } 348203697Sneel //where 349203697Sneel /** Is given class a subclass of given base class, or an inner class 350203697Sneel * of a subclass? 351203697Sneel * Return null if no such class exists. 352203697Sneel * @param c The class which is the subclass or is contained in it. 353203697Sneel * @param base The base class 354203697Sneel */ 355203697Sneel private boolean isInnerSubClass(ClassSymbol c, Symbol base) { 356203697Sneel while (c != null && !c.isSubClass(base, types)) { 357203697Sneel c = c.owner.enclClass(); 358203697Sneel } 359203697Sneel return c != null; 360203697Sneel } 361203697Sneel 362203697Sneel boolean isAccessible(Env<AttrContext> env, Type t) { 363203697Sneel return isAccessible(env, t, false); 364203697Sneel } 365203697Sneel 366203697Sneel boolean isAccessible(Env<AttrContext> env, Type t, boolean checkInner) { 367203697Sneel return (t.hasTag(ARRAY)) 368201631Sneel ? isAccessible(env, types.cvarUpperBound(types.elemtype(t))) 369201631Sneel : isAccessible(env, t.tsym, checkInner); 370195333Simp } 371202864Sneel 372202864Sneel /** Is symbol accessible as a member of given type in given environment? 373202864Sneel * @param env The current environment. 374202864Sneel * @param site The type of which the tested symbol is regarded 375202864Sneel * as a member. 376195333Simp * @param sym The symbol. 377195333Simp */ 378202954Sgonzo public boolean isAccessible(Env<AttrContext> env, Type site, Symbol sym) { 379195333Simp return isAccessible(env, site, sym, false); 380203510Sneel } 381203510Sneel public boolean isAccessible(Env<AttrContext> env, Type site, Symbol sym, boolean checkInner) { 382201845Simp if (sym.name == names.init && sym.owner != site.tsym) return false; 383201881Simp 384201845Simp /* 15.9.5.1: Note that it is possible for the signature of the anonymous constructor 385195333Simp to refer to an inaccessible type 386195333Simp */ 387195333Simp if (env.enclMethod != null && (env.enclMethod.mods.flags & ANONCONSTR) != 0) 388195333Simp return true; 389201631Sneel 390201631Sneel switch ((short)(sym.flags() & AccessFlags)) { 391201631Sneel case PRIVATE: 392201631Sneel return 393201631Sneel (env.enclClass.sym == sym.owner // fast special case 394195333Simp || 395201631Sneel env.enclClass.sym.outermostClass() == 396201631Sneel sym.owner.outermostClass()) 397195333Simp && 398195333Simp sym.isInheritedIn(site.tsym, types); 399195333Simp case 0: 400195333Simp return 401195333Simp (env.toplevel.packge == sym.owner.owner // fast special case 402195333Simp || 403195333Simp env.toplevel.packge == sym.packge()) 404 && 405 isAccessible(env, site, checkInner) 406 && 407 sym.isInheritedIn(site.tsym, types) 408 && 409 notOverriddenIn(site, sym); 410 case PROTECTED: 411 return 412 (env.toplevel.packge == sym.owner.owner // fast special case 413 || 414 env.toplevel.packge == sym.packge() 415 || 416 isProtectedAccessible(sym, env.enclClass.sym, site) 417 || 418 // OK to select instance method or field from 'super' or type name 419 // (but type names should be disallowed elsewhere!) 420 env.info.selectSuper && (sym.flags() & STATIC) == 0 && sym.kind != TYP) 421 && 422 isAccessible(env, site, checkInner) 423 && 424 notOverriddenIn(site, sym); 425 default: // this case includes erroneous combinations as well 426 return isAccessible(env, site, checkInner) && notOverriddenIn(site, sym); 427 } 428 } 429 //where 430 /* `sym' is accessible only if not overridden by 431 * another symbol which is a member of `site' 432 * (because, if it is overridden, `sym' is not strictly 433 * speaking a member of `site'). A polymorphic signature method 434 * cannot be overridden (e.g. MH.invokeExact(Object[])). 435 */ 436 private boolean notOverriddenIn(Type site, Symbol sym) { 437 if (sym.kind != MTH || sym.isConstructor() || sym.isStatic()) 438 return true; 439 else { 440 Symbol s2 = ((MethodSymbol)sym).implementation(site.tsym, types, true); 441 return (s2 == null || s2 == sym || sym.owner == s2.owner || 442 !types.isSubSignature(types.memberType(site, s2), types.memberType(site, sym))); 443 } 444 } 445 //where 446 /** Is given protected symbol accessible if it is selected from given site 447 * and the selection takes place in given class? 448 * @param sym The symbol with protected access 449 * @param c The class where the access takes place 450 * @site The type of the qualifier 451 */ 452 private 453 boolean isProtectedAccessible(Symbol sym, ClassSymbol c, Type site) { 454 Type newSite = site.hasTag(TYPEVAR) ? site.getUpperBound() : site; 455 while (c != null && 456 !(c.isSubClass(sym.owner, types) && 457 (c.flags() & INTERFACE) == 0 && 458 // In JLS 2e 6.6.2.1, the subclass restriction applies 459 // only to instance fields and methods -- types are excluded 460 // regardless of whether they are declared 'static' or not. 461 ((sym.flags() & STATIC) != 0 || sym.kind == TYP || newSite.tsym.isSubClass(c, types)))) 462 c = c.owner.enclClass(); 463 return c != null; 464 } 465 466 /** 467 * Performs a recursive scan of a type looking for accessibility problems 468 * from current attribution environment 469 */ 470 void checkAccessibleType(Env<AttrContext> env, Type t) { 471 accessibilityChecker.visit(t, env); 472 } 473 474 /** 475 * Accessibility type-visitor 476 */ 477 Types.SimpleVisitor<Void, Env<AttrContext>> accessibilityChecker = 478 new Types.SimpleVisitor<Void, Env<AttrContext>>() { 479 480 void visit(List<Type> ts, Env<AttrContext> env) { 481 for (Type t : ts) { 482 visit(t, env); 483 } 484 } 485 486 public Void visitType(Type t, Env<AttrContext> env) { 487 return null; 488 } 489 490 @Override 491 public Void visitArrayType(ArrayType t, Env<AttrContext> env) { 492 visit(t.elemtype, env); 493 return null; 494 } 495 496 @Override 497 public Void visitClassType(ClassType t, Env<AttrContext> env) { 498 visit(t.getTypeArguments(), env); 499 if (!isAccessible(env, t, true)) { 500 accessBase(new AccessError(t.tsym), env.tree.pos(), env.enclClass.sym, t, t.tsym.name, true); 501 } 502 return null; 503 } 504 505 @Override 506 public Void visitWildcardType(WildcardType t, Env<AttrContext> env) { 507 visit(t.type, env); 508 return null; 509 } 510 511 @Override 512 public Void visitMethodType(MethodType t, Env<AttrContext> env) { 513 visit(t.getParameterTypes(), env); 514 visit(t.getReturnType(), env); 515 visit(t.getThrownTypes(), env); 516 return null; 517 } 518 }; 519 520 /** Try to instantiate the type of a method so that it fits 521 * given type arguments and argument types. If successful, return 522 * the method's instantiated type, else return null. 523 * The instantiation will take into account an additional leading 524 * formal parameter if the method is an instance method seen as a member 525 * of an under determined site. In this case, we treat site as an additional 526 * parameter and the parameters of the class containing the method as 527 * additional type variables that get instantiated. 528 * 529 * @param env The current environment 530 * @param site The type of which the method is a member. 531 * @param m The method symbol. 532 * @param argtypes The invocation's given value arguments. 533 * @param typeargtypes The invocation's given type arguments. 534 * @param allowBoxing Allow boxing conversions of arguments. 535 * @param useVarargs Box trailing arguments into an array for varargs. 536 */ 537 Type rawInstantiate(Env<AttrContext> env, 538 Type site, 539 Symbol m, 540 ResultInfo resultInfo, 541 List<Type> argtypes, 542 List<Type> typeargtypes, 543 boolean allowBoxing, 544 boolean useVarargs, 545 Warner warn) throws Infer.InferenceException { 546 Type mt = types.memberType(site, m); 547 // tvars is the list of formal type variables for which type arguments 548 // need to inferred. 549 List<Type> tvars = List.nil(); 550 if (typeargtypes == null) typeargtypes = List.nil(); 551 if (!mt.hasTag(FORALL) && typeargtypes.nonEmpty()) { 552 // This is not a polymorphic method, but typeargs are supplied 553 // which is fine, see JLS 15.12.2.1 554 } else if (mt.hasTag(FORALL) && typeargtypes.nonEmpty()) { 555 ForAll pmt = (ForAll) mt; 556 if (typeargtypes.length() != pmt.tvars.length()) 557 throw inapplicableMethodException.setMessage("arg.length.mismatch"); // not enough args 558 // Check type arguments are within bounds 559 List<Type> formals = pmt.tvars; 560 List<Type> actuals = typeargtypes; 561 while (formals.nonEmpty() && actuals.nonEmpty()) { 562 List<Type> bounds = types.subst(types.getBounds((TypeVar)formals.head), 563 pmt.tvars, typeargtypes); 564 for (; bounds.nonEmpty(); bounds = bounds.tail) { 565 if (!types.isSubtypeUnchecked(actuals.head, bounds.head, warn)) 566 throw inapplicableMethodException.setMessage("explicit.param.do.not.conform.to.bounds",actuals.head, bounds); 567 } 568 formals = formals.tail; 569 actuals = actuals.tail; 570 } 571 mt = types.subst(pmt.qtype, pmt.tvars, typeargtypes); 572 } else if (mt.hasTag(FORALL)) { 573 ForAll pmt = (ForAll) mt; 574 List<Type> tvars1 = types.newInstances(pmt.tvars); 575 tvars = tvars.appendList(tvars1); 576 mt = types.subst(pmt.qtype, pmt.tvars, tvars1); 577 } 578 579 // find out whether we need to go the slow route via infer 580 boolean instNeeded = tvars.tail != null; /*inlined: tvars.nonEmpty()*/ 581 for (List<Type> l = argtypes; 582 l.tail != null/*inlined: l.nonEmpty()*/ && !instNeeded; 583 l = l.tail) { 584 if (l.head.hasTag(FORALL)) instNeeded = true; 585 } 586 587 if (instNeeded) { 588 return infer.instantiateMethod(env, 589 tvars, 590 (MethodType)mt, 591 resultInfo, 592 (MethodSymbol)m, 593 argtypes, 594 allowBoxing, 595 useVarargs, 596 currentResolutionContext, 597 warn); 598 } 599 600 DeferredAttr.DeferredAttrContext dc = currentResolutionContext.deferredAttrContext(m, infer.emptyContext, resultInfo, warn); 601 currentResolutionContext.methodCheck.argumentsAcceptable(env, dc, 602 argtypes, mt.getParameterTypes(), warn); 603 dc.complete(); 604 return mt; 605 } 606 607 Type checkMethod(Env<AttrContext> env, 608 Type site, 609 Symbol m, 610 ResultInfo resultInfo, 611 List<Type> argtypes, 612 List<Type> typeargtypes, 613 Warner warn) { 614 MethodResolutionContext prevContext = currentResolutionContext; 615 try { 616 currentResolutionContext = new MethodResolutionContext(); 617 currentResolutionContext.attrMode = (resultInfo.pt == Infer.anyPoly) ? 618 AttrMode.SPECULATIVE : DeferredAttr.AttrMode.CHECK; 619 if (env.tree.hasTag(JCTree.Tag.REFERENCE)) { 620 //method/constructor references need special check class 621 //to handle inference variables in 'argtypes' (might happen 622 //during an unsticking round) 623 currentResolutionContext.methodCheck = 624 new MethodReferenceCheck(resultInfo.checkContext.inferenceContext()); 625 } 626 MethodResolutionPhase step = currentResolutionContext.step = env.info.pendingResolutionPhase; 627 return rawInstantiate(env, site, m, resultInfo, argtypes, typeargtypes, 628 step.isBoxingRequired(), step.isVarargsRequired(), warn); 629 } 630 finally { 631 currentResolutionContext = prevContext; 632 } 633 } 634 635 /** Same but returns null instead throwing a NoInstanceException 636 */ 637 Type instantiate(Env<AttrContext> env, 638 Type site, 639 Symbol m, 640 ResultInfo resultInfo, 641 List<Type> argtypes, 642 List<Type> typeargtypes, 643 boolean allowBoxing, 644 boolean useVarargs, 645 Warner warn) { 646 try { 647 return rawInstantiate(env, site, m, resultInfo, argtypes, typeargtypes, 648 allowBoxing, useVarargs, warn); 649 } catch (InapplicableMethodException ex) { 650 return null; 651 } 652 } 653 654 /** 655 * This interface defines an entry point that should be used to perform a 656 * method check. A method check usually consist in determining as to whether 657 * a set of types (actuals) is compatible with another set of types (formals). 658 * Since the notion of compatibility can vary depending on the circumstances, 659 * this interfaces allows to easily add new pluggable method check routines. 660 */ 661 interface MethodCheck { 662 /** 663 * Main method check routine. A method check usually consist in determining 664 * as to whether a set of types (actuals) is compatible with another set of 665 * types (formals). If an incompatibility is found, an unchecked exception 666 * is assumed to be thrown. 667 */ 668 void argumentsAcceptable(Env<AttrContext> env, 669 DeferredAttrContext deferredAttrContext, 670 List<Type> argtypes, 671 List<Type> formals, 672 Warner warn); 673 674 /** 675 * Retrieve the method check object that will be used during a 676 * most specific check. 677 */ 678 MethodCheck mostSpecificCheck(List<Type> actuals); 679 } 680 681 /** 682 * Helper enum defining all method check diagnostics (used by resolveMethodCheck). 683 */ 684 enum MethodCheckDiag { 685 /** 686 * Actuals and formals differs in length. 687 */ 688 ARITY_MISMATCH("arg.length.mismatch", "infer.arg.length.mismatch"), 689 /** 690 * An actual is incompatible with a formal. 691 */ 692 ARG_MISMATCH("no.conforming.assignment.exists", "infer.no.conforming.assignment.exists"), 693 /** 694 * An actual is incompatible with the varargs element type. 695 */ 696 VARARG_MISMATCH("varargs.argument.mismatch", "infer.varargs.argument.mismatch"), 697 /** 698 * The varargs element type is inaccessible. 699 */ 700 INACCESSIBLE_VARARGS("inaccessible.varargs.type", "inaccessible.varargs.type"); 701 702 final String basicKey; 703 final String inferKey; 704 705 MethodCheckDiag(String basicKey, String inferKey) { 706 this.basicKey = basicKey; 707 this.inferKey = inferKey; 708 } 709 710 String regex() { 711 return String.format("([a-z]*\\.)*(%s|%s)", basicKey, inferKey); 712 } 713 } 714 715 /** 716 * Dummy method check object. All methods are deemed applicable, regardless 717 * of their formal parameter types. 718 */ 719 MethodCheck nilMethodCheck = new MethodCheck() { 720 public void argumentsAcceptable(Env<AttrContext> env, DeferredAttrContext deferredAttrContext, List<Type> argtypes, List<Type> formals, Warner warn) { 721 //do nothing - method always applicable regardless of actuals 722 } 723 724 public MethodCheck mostSpecificCheck(List<Type> actuals) { 725 return this; 726 } 727 }; 728 729 /** 730 * Base class for 'real' method checks. The class defines the logic for 731 * iterating through formals and actuals and provides and entry point 732 * that can be used by subclasses in order to define the actual check logic. 733 */ 734 abstract class AbstractMethodCheck implements MethodCheck { 735 @Override 736 public void argumentsAcceptable(final Env<AttrContext> env, 737 DeferredAttrContext deferredAttrContext, 738 List<Type> argtypes, 739 List<Type> formals, 740 Warner warn) { 741 //should we expand formals? 742 boolean useVarargs = deferredAttrContext.phase.isVarargsRequired(); 743 JCTree callTree = treeForDiagnostics(env); 744 List<JCExpression> trees = TreeInfo.args(callTree); 745 746 //inference context used during this method check 747 InferenceContext inferenceContext = deferredAttrContext.inferenceContext; 748 749 Type varargsFormal = useVarargs ? formals.last() : null; 750 751 if (varargsFormal == null && 752 argtypes.size() != formals.size()) { 753 reportMC(callTree, MethodCheckDiag.ARITY_MISMATCH, inferenceContext); // not enough args 754 } 755 756 while (argtypes.nonEmpty() && formals.head != varargsFormal) { 757 DiagnosticPosition pos = trees != null ? trees.head : null; 758 checkArg(pos, false, argtypes.head, formals.head, deferredAttrContext, warn); 759 argtypes = argtypes.tail; 760 formals = formals.tail; 761 trees = trees != null ? trees.tail : trees; 762 } 763 764 if (formals.head != varargsFormal) { 765 reportMC(callTree, MethodCheckDiag.ARITY_MISMATCH, inferenceContext); // not enough args 766 } 767 768 if (useVarargs) { 769 //note: if applicability check is triggered by most specific test, 770 //the last argument of a varargs is _not_ an array type (see JLS 15.12.2.5) 771 final Type elt = types.elemtype(varargsFormal); 772 while (argtypes.nonEmpty()) { 773 DiagnosticPosition pos = trees != null ? trees.head : null; 774 checkArg(pos, true, argtypes.head, elt, deferredAttrContext, warn); 775 argtypes = argtypes.tail; 776 trees = trees != null ? trees.tail : trees; 777 } 778 } 779 } 780 781 // where 782 private JCTree treeForDiagnostics(Env<AttrContext> env) { 783 return env.info.preferredTreeForDiagnostics != null ? env.info.preferredTreeForDiagnostics : env.tree; 784 } 785 786 /** 787 * Does the actual argument conforms to the corresponding formal? 788 */ 789 abstract void checkArg(DiagnosticPosition pos, boolean varargs, Type actual, Type formal, DeferredAttrContext deferredAttrContext, Warner warn); 790 791 protected void reportMC(DiagnosticPosition pos, MethodCheckDiag diag, InferenceContext inferenceContext, Object... args) { 792 boolean inferDiag = inferenceContext != infer.emptyContext; 793 InapplicableMethodException ex = inferDiag ? 794 infer.inferenceException : inapplicableMethodException; 795 if (inferDiag && (!diag.inferKey.equals(diag.basicKey))) { 796 Object[] args2 = new Object[args.length + 1]; 797 System.arraycopy(args, 0, args2, 1, args.length); 798 args2[0] = inferenceContext.inferenceVars(); 799 args = args2; 800 } 801 String key = inferDiag ? diag.inferKey : diag.basicKey; 802 throw ex.setMessage(diags.create(DiagnosticType.FRAGMENT, log.currentSource(), pos, key, args)); 803 } 804 805 public MethodCheck mostSpecificCheck(List<Type> actuals) { 806 return nilMethodCheck; 807 } 808 809 } 810 811 /** 812 * Arity-based method check. A method is applicable if the number of actuals 813 * supplied conforms to the method signature. 814 */ 815 MethodCheck arityMethodCheck = new AbstractMethodCheck() { 816 @Override 817 void checkArg(DiagnosticPosition pos, boolean varargs, Type actual, Type formal, DeferredAttrContext deferredAttrContext, Warner warn) { 818 //do nothing - actual always compatible to formals 819 } 820 821 @Override 822 public String toString() { 823 return "arityMethodCheck"; 824 } 825 }; 826 827 List<Type> dummyArgs(int length) { 828 ListBuffer<Type> buf = new ListBuffer<>(); 829 for (int i = 0 ; i < length ; i++) { 830 buf.append(Type.noType); 831 } 832 return buf.toList(); 833 } 834 835 /** 836 * Main method applicability routine. Given a list of actual types A, 837 * a list of formal types F, determines whether the types in A are 838 * compatible (by method invocation conversion) with the types in F. 839 * 840 * Since this routine is shared between overload resolution and method 841 * type-inference, a (possibly empty) inference context is used to convert 842 * formal types to the corresponding 'undet' form ahead of a compatibility 843 * check so that constraints can be propagated and collected. 844 * 845 * Moreover, if one or more types in A is a deferred type, this routine uses 846 * DeferredAttr in order to perform deferred attribution. If one or more actual 847 * deferred types are stuck, they are placed in a queue and revisited later 848 * after the remainder of the arguments have been seen. If this is not sufficient 849 * to 'unstuck' the argument, a cyclic inference error is called out. 850 * 851 * A method check handler (see above) is used in order to report errors. 852 */ 853 MethodCheck resolveMethodCheck = new AbstractMethodCheck() { 854 855 @Override 856 void checkArg(DiagnosticPosition pos, boolean varargs, Type actual, Type formal, DeferredAttrContext deferredAttrContext, Warner warn) { 857 ResultInfo mresult = methodCheckResult(varargs, formal, deferredAttrContext, warn); 858 mresult.check(pos, actual); 859 } 860 861 @Override 862 public void argumentsAcceptable(final Env<AttrContext> env, 863 DeferredAttrContext deferredAttrContext, 864 List<Type> argtypes, 865 List<Type> formals, 866 Warner warn) { 867 super.argumentsAcceptable(env, deferredAttrContext, argtypes, formals, warn); 868 // should we check varargs element type accessibility? 869 if (deferredAttrContext.phase.isVarargsRequired()) { 870 if (deferredAttrContext.mode == AttrMode.CHECK || !checkVarargsAccessAfterResolution) { 871 varargsAccessible(env, types.elemtype(formals.last()), deferredAttrContext.inferenceContext); 872 } 873 } 874 } 875 876 /** 877 * Test that the runtime array element type corresponding to 't' is accessible. 't' should be the 878 * varargs element type of either the method invocation type signature (after inference completes) 879 * or the method declaration signature (before inference completes). 880 */ 881 private void varargsAccessible(final Env<AttrContext> env, final Type t, final InferenceContext inferenceContext) { 882 if (inferenceContext.free(t)) { 883 inferenceContext.addFreeTypeListener(List.of(t), new FreeTypeListener() { 884 @Override 885 public void typesInferred(InferenceContext inferenceContext) { 886 varargsAccessible(env, inferenceContext.asInstType(t), inferenceContext); 887 } 888 }); 889 } else { 890 if (!isAccessible(env, types.erasure(t))) { 891 Symbol location = env.enclClass.sym; 892 reportMC(env.tree, MethodCheckDiag.INACCESSIBLE_VARARGS, inferenceContext, t, Kinds.kindName(location), location); 893 } 894 } 895 } 896 897 private ResultInfo methodCheckResult(final boolean varargsCheck, Type to, 898 final DeferredAttr.DeferredAttrContext deferredAttrContext, Warner rsWarner) { 899 CheckContext checkContext = new MethodCheckContext(!deferredAttrContext.phase.isBoxingRequired(), deferredAttrContext, rsWarner) { 900 MethodCheckDiag methodDiag = varargsCheck ? 901 MethodCheckDiag.VARARG_MISMATCH : MethodCheckDiag.ARG_MISMATCH; 902 903 @Override 904 public void report(DiagnosticPosition pos, JCDiagnostic details) { 905 reportMC(pos, methodDiag, deferredAttrContext.inferenceContext, details); 906 } 907 }; 908 return new MethodResultInfo(to, checkContext); 909 } 910 911 @Override 912 public MethodCheck mostSpecificCheck(List<Type> actuals) { 913 return new MostSpecificCheck(actuals); 914 } 915 916 @Override 917 public String toString() { 918 return "resolveMethodCheck"; 919 } 920 }; 921 922 /** 923 * This class handles method reference applicability checks; since during 924 * these checks it's sometime possible to have inference variables on 925 * the actual argument types list, the method applicability check must be 926 * extended so that inference variables are 'opened' as needed. 927 */ 928 class MethodReferenceCheck extends AbstractMethodCheck { 929 930 InferenceContext pendingInferenceContext; 931 932 MethodReferenceCheck(InferenceContext pendingInferenceContext) { 933 this.pendingInferenceContext = pendingInferenceContext; 934 } 935 936 @Override 937 void checkArg(DiagnosticPosition pos, boolean varargs, Type actual, Type formal, DeferredAttrContext deferredAttrContext, Warner warn) { 938 ResultInfo mresult = methodCheckResult(varargs, formal, deferredAttrContext, warn); 939 mresult.check(pos, actual); 940 } 941 942 private ResultInfo methodCheckResult(final boolean varargsCheck, Type to, 943 final DeferredAttr.DeferredAttrContext deferredAttrContext, Warner rsWarner) { 944 CheckContext checkContext = new MethodCheckContext(!deferredAttrContext.phase.isBoxingRequired(), deferredAttrContext, rsWarner) { 945 MethodCheckDiag methodDiag = varargsCheck ? 946 MethodCheckDiag.VARARG_MISMATCH : MethodCheckDiag.ARG_MISMATCH; 947 948 @Override 949 public boolean compatible(Type found, Type req, Warner warn) { 950 found = pendingInferenceContext.asUndetVar(found); 951 if (found.hasTag(UNDETVAR) && req.isPrimitive()) { 952 req = types.boxedClass(req).type; 953 } 954 return super.compatible(found, req, warn); 955 } 956 957 @Override 958 public void report(DiagnosticPosition pos, JCDiagnostic details) { 959 reportMC(pos, methodDiag, deferredAttrContext.inferenceContext, details); 960 } 961 }; 962 return new MethodResultInfo(to, checkContext); 963 } 964 965 @Override 966 public MethodCheck mostSpecificCheck(List<Type> actuals) { 967 return new MostSpecificCheck(actuals); 968 } 969 970 @Override 971 public String toString() { 972 return "MethodReferenceCheck"; 973 } 974 } 975 976 /** 977 * Check context to be used during method applicability checks. A method check 978 * context might contain inference variables. 979 */ 980 abstract class MethodCheckContext implements CheckContext { 981 982 boolean strict; 983 DeferredAttrContext deferredAttrContext; 984 Warner rsWarner; 985 986 public MethodCheckContext(boolean strict, DeferredAttrContext deferredAttrContext, Warner rsWarner) { 987 this.strict = strict; 988 this.deferredAttrContext = deferredAttrContext; 989 this.rsWarner = rsWarner; 990 } 991 992 public boolean compatible(Type found, Type req, Warner warn) { 993 InferenceContext inferenceContext = deferredAttrContext.inferenceContext; 994 return strict ? 995 types.isSubtypeUnchecked(inferenceContext.asUndetVar(found), inferenceContext.asUndetVar(req), warn) : 996 types.isConvertible(inferenceContext.asUndetVar(found), inferenceContext.asUndetVar(req), warn); 997 } 998 999 public void report(DiagnosticPosition pos, JCDiagnostic details) { 1000 throw inapplicableMethodException.setMessage(details); 1001 } 1002 1003 public Warner checkWarner(DiagnosticPosition pos, Type found, Type req) { 1004 return rsWarner; 1005 } 1006 1007 public InferenceContext inferenceContext() { 1008 return deferredAttrContext.inferenceContext; 1009 } 1010 1011 public DeferredAttrContext deferredAttrContext() { 1012 return deferredAttrContext; 1013 } 1014 1015 @Override 1016 public String toString() { 1017 return "MethodCheckContext"; 1018 } 1019 } 1020 1021 /** 1022 * ResultInfo class to be used during method applicability checks. Check 1023 * for deferred types goes through special path. 1024 */ 1025 class MethodResultInfo extends ResultInfo { 1026 1027 public MethodResultInfo(Type pt, CheckContext checkContext) { 1028 attr.super(KindSelector.VAL, pt, checkContext); 1029 } 1030 1031 @Override 1032 protected Type check(DiagnosticPosition pos, Type found) { 1033 if (found.hasTag(DEFERRED)) { 1034 DeferredType dt = (DeferredType)found; 1035 return dt.check(this); 1036 } else { 1037 Type uResult = U(found); 1038 Type capturedType = pos == null || pos.getTree() == null ? 1039 types.capture(uResult) : 1040 checkContext.inferenceContext() 1041 .cachedCapture(pos.getTree(), uResult, true); 1042 return super.check(pos, chk.checkNonVoid(pos, capturedType)); 1043 } 1044 } 1045 1046 /** 1047 * javac has a long-standing 'simplification' (see 6391995): 1048 * given an actual argument type, the method check is performed 1049 * on its upper bound. This leads to inconsistencies when an 1050 * argument type is checked against itself. For example, given 1051 * a type-variable T, it is not true that {@code U(T) <: T}, 1052 * so we need to guard against that. 1053 */ 1054 private Type U(Type found) { 1055 return found == pt ? 1056 found : types.cvarUpperBound(found); 1057 } 1058 1059 @Override 1060 protected MethodResultInfo dup(Type newPt) { 1061 return new MethodResultInfo(newPt, checkContext); 1062 } 1063 1064 @Override 1065 protected ResultInfo dup(CheckContext newContext) { 1066 return new MethodResultInfo(pt, newContext); 1067 } 1068 1069 @Override 1070 protected ResultInfo dup(Type newPt, CheckContext newContext) { 1071 return new MethodResultInfo(newPt, newContext); 1072 } 1073 } 1074 1075 /** 1076 * Most specific method applicability routine. Given a list of actual types A, 1077 * a list of formal types F1, and a list of formal types F2, the routine determines 1078 * as to whether the types in F1 can be considered more specific than those in F2 w.r.t. 1079 * argument types A. 1080 */ 1081 class MostSpecificCheck implements MethodCheck { 1082 1083 List<Type> actuals; 1084 1085 MostSpecificCheck(List<Type> actuals) { 1086 this.actuals = actuals; 1087 } 1088 1089 @Override 1090 public void argumentsAcceptable(final Env<AttrContext> env, 1091 DeferredAttrContext deferredAttrContext, 1092 List<Type> formals1, 1093 List<Type> formals2, 1094 Warner warn) { 1095 formals2 = adjustArgs(formals2, deferredAttrContext.msym, formals1.length(), deferredAttrContext.phase.isVarargsRequired()); 1096 while (formals2.nonEmpty()) { 1097 ResultInfo mresult = methodCheckResult(formals2.head, deferredAttrContext, warn, actuals.head); 1098 mresult.check(null, formals1.head); 1099 formals1 = formals1.tail; 1100 formals2 = formals2.tail; 1101 actuals = actuals.isEmpty() ? actuals : actuals.tail; 1102 } 1103 } 1104 1105 /** 1106 * Create a method check context to be used during the most specific applicability check 1107 */ 1108 ResultInfo methodCheckResult(Type to, DeferredAttr.DeferredAttrContext deferredAttrContext, 1109 Warner rsWarner, Type actual) { 1110 return attr.new ResultInfo(KindSelector.VAL, to, 1111 new MostSpecificCheckContext(deferredAttrContext, rsWarner, actual)); 1112 } 1113 1114 /** 1115 * Subclass of method check context class that implements most specific 1116 * method conversion. If the actual type under analysis is a deferred type 1117 * a full blown structural analysis is carried out. 1118 */ 1119 class MostSpecificCheckContext extends MethodCheckContext { 1120 1121 Type actual; 1122 1123 public MostSpecificCheckContext(DeferredAttrContext deferredAttrContext, Warner rsWarner, Type actual) { 1124 super(true, deferredAttrContext, rsWarner); 1125 this.actual = actual; 1126 } 1127 1128 public boolean compatible(Type found, Type req, Warner warn) { 1129 if (allowFunctionalInterfaceMostSpecific && 1130 unrelatedFunctionalInterfaces(found, req) && 1131 (actual != null && actual.getTag() == DEFERRED)) { 1132 DeferredType dt = (DeferredType) actual; 1133 JCTree speculativeTree = dt.speculativeTree(deferredAttrContext); 1134 if (speculativeTree != deferredAttr.stuckTree) { 1135 return functionalInterfaceMostSpecific(found, req, speculativeTree); 1136 } 1137 } 1138 return compatibleBySubtyping(found, req); 1139 } 1140 1141 private boolean compatibleBySubtyping(Type found, Type req) { 1142 if (!strict && found.isPrimitive() != req.isPrimitive()) { 1143 found = found.isPrimitive() ? types.boxedClass(found).type : types.unboxedType(found); 1144 } 1145 return types.isSubtypeNoCapture(found, deferredAttrContext.inferenceContext.asUndetVar(req)); 1146 } 1147 1148 /** Whether {@code t} and {@code s} are unrelated functional interface types. */ 1149 private boolean unrelatedFunctionalInterfaces(Type t, Type s) { 1150 return types.isFunctionalInterface(t.tsym) && 1151 types.isFunctionalInterface(s.tsym) && 1152 unrelatedInterfaces(t, s); 1153 } 1154 1155 /** Whether {@code t} and {@code s} are unrelated interface types; recurs on intersections. **/ 1156 private boolean unrelatedInterfaces(Type t, Type s) { 1157 if (t.isCompound()) { 1158 for (Type ti : types.interfaces(t)) { 1159 if (!unrelatedInterfaces(ti, s)) { 1160 return false; 1161 } 1162 } 1163 return true; 1164 } else if (s.isCompound()) { 1165 for (Type si : types.interfaces(s)) { 1166 if (!unrelatedInterfaces(t, si)) { 1167 return false; 1168 } 1169 } 1170 return true; 1171 } else { 1172 return types.asSuper(t, s.tsym) == null && types.asSuper(s, t.tsym) == null; 1173 } 1174 } 1175 1176 /** Parameters {@code t} and {@code s} are unrelated functional interface types. */ 1177 private boolean functionalInterfaceMostSpecific(Type t, Type s, JCTree tree) { 1178 Type tDesc = types.findDescriptorType(types.capture(t)); 1179 Type tDescNoCapture = types.findDescriptorType(t); 1180 Type sDesc = types.findDescriptorType(s); 1181 final List<Type> tTypeParams = tDesc.getTypeArguments(); 1182 final List<Type> tTypeParamsNoCapture = tDescNoCapture.getTypeArguments(); 1183 final List<Type> sTypeParams = sDesc.getTypeArguments(); 1184 1185 // compare type parameters 1186 if (tDesc.hasTag(FORALL) && !types.hasSameBounds((ForAll) tDesc, (ForAll) tDescNoCapture)) { 1187 return false; 1188 } 1189 // can't use Types.hasSameBounds on sDesc because bounds may have ivars 1190 List<Type> tIter = tTypeParams; 1191 List<Type> sIter = sTypeParams; 1192 while (tIter.nonEmpty() && sIter.nonEmpty()) { 1193 Type tBound = tIter.head.getUpperBound(); 1194 Type sBound = types.subst(sIter.head.getUpperBound(), sTypeParams, tTypeParams); 1195 if (tBound.containsAny(tTypeParams) && inferenceContext().free(sBound)) { 1196 return false; 1197 } 1198 if (!types.isSameType(tBound, inferenceContext().asUndetVar(sBound))) { 1199 return false; 1200 } 1201 tIter = tIter.tail; 1202 sIter = sIter.tail; 1203 } 1204 if (!tIter.isEmpty() || !sIter.isEmpty()) { 1205 return false; 1206 } 1207 1208 // compare parameters 1209 List<Type> tParams = tDesc.getParameterTypes(); 1210 List<Type> tParamsNoCapture = tDescNoCapture.getParameterTypes(); 1211 List<Type> sParams = sDesc.getParameterTypes(); 1212 while (tParams.nonEmpty() && tParamsNoCapture.nonEmpty() && sParams.nonEmpty()) { 1213 Type tParam = tParams.head; 1214 Type tParamNoCapture = types.subst(tParamsNoCapture.head, tTypeParamsNoCapture, tTypeParams); 1215 Type sParam = types.subst(sParams.head, sTypeParams, tTypeParams); 1216 if (tParam.containsAny(tTypeParams) && inferenceContext().free(sParam)) { 1217 return false; 1218 } 1219 if (!types.isSubtype(inferenceContext().asUndetVar(sParam), tParam)) { 1220 return false; 1221 } 1222 if (!types.isSameType(tParamNoCapture, inferenceContext().asUndetVar(sParam))) { 1223 return false; 1224 } 1225 tParams = tParams.tail; 1226 tParamsNoCapture = tParamsNoCapture.tail; 1227 sParams = sParams.tail; 1228 } 1229 if (!tParams.isEmpty() || !tParamsNoCapture.isEmpty() || !sParams.isEmpty()) { 1230 return false; 1231 } 1232 1233 // compare returns 1234 Type tRet = tDesc.getReturnType(); 1235 Type sRet = types.subst(sDesc.getReturnType(), sTypeParams, tTypeParams); 1236 if (tRet.containsAny(tTypeParams) && inferenceContext().free(sRet)) { 1237 return false; 1238 } 1239 MostSpecificFunctionReturnChecker msc = new MostSpecificFunctionReturnChecker(tRet, sRet); 1240 msc.scan(tree); 1241 return msc.result; 1242 } 1243 1244 /** 1245 * Tests whether one functional interface type can be considered more specific 1246 * than another unrelated functional interface type for the scanned expression. 1247 */ 1248 class MostSpecificFunctionReturnChecker extends DeferredAttr.PolyScanner { 1249 1250 final Type tRet; 1251 final Type sRet; 1252 boolean result; 1253 1254 /** Parameters {@code t} and {@code s} are unrelated functional interface types. */ 1255 MostSpecificFunctionReturnChecker(Type tRet, Type sRet) { 1256 this.tRet = tRet; 1257 this.sRet = sRet; 1258 result = true; 1259 } 1260 1261 @Override 1262 void skip(JCTree tree) { 1263 result &= false; 1264 } 1265 1266 @Override 1267 public void visitConditional(JCConditional tree) { 1268 scan(asExpr(tree.truepart)); 1269 scan(asExpr(tree.falsepart)); 1270 } 1271 1272 @Override 1273 public void visitReference(JCMemberReference tree) { 1274 if (sRet.hasTag(VOID)) { 1275 result &= true; 1276 } else if (tRet.hasTag(VOID)) { 1277 result &= false; 1278 } else if (tRet.isPrimitive() != sRet.isPrimitive()) { 1279 boolean retValIsPrimitive = 1280 tree.refPolyKind == PolyKind.STANDALONE && 1281 tree.sym.type.getReturnType().isPrimitive(); 1282 result &= (retValIsPrimitive == tRet.isPrimitive()) && 1283 (retValIsPrimitive != sRet.isPrimitive()); 1284 } else { 1285 result &= compatibleBySubtyping(tRet, sRet); 1286 } 1287 } 1288 1289 @Override 1290 public void visitParens(JCParens tree) { 1291 scan(asExpr(tree.expr)); 1292 } 1293 1294 @Override 1295 public void visitLambda(JCLambda tree) { 1296 if (sRet.hasTag(VOID)) { 1297 result &= true; 1298 } else if (tRet.hasTag(VOID)) { 1299 result &= false; 1300 } else { 1301 List<JCExpression> lambdaResults = lambdaResults(tree); 1302 if (!lambdaResults.isEmpty() && unrelatedFunctionalInterfaces(tRet, sRet)) { 1303 for (JCExpression expr : lambdaResults) { 1304 result &= functionalInterfaceMostSpecific(tRet, sRet, expr); 1305 } 1306 } else if (!lambdaResults.isEmpty() && tRet.isPrimitive() != sRet.isPrimitive()) { 1307 for (JCExpression expr : lambdaResults) { 1308 boolean retValIsPrimitive = expr.isStandalone() && expr.type.isPrimitive(); 1309 result &= (retValIsPrimitive == tRet.isPrimitive()) && 1310 (retValIsPrimitive != sRet.isPrimitive()); 1311 } 1312 } else { 1313 result &= compatibleBySubtyping(tRet, sRet); 1314 } 1315 } 1316 } 1317 //where 1318 1319 private List<JCExpression> lambdaResults(JCLambda lambda) { 1320 if (lambda.getBodyKind() == JCTree.JCLambda.BodyKind.EXPRESSION) { 1321 return List.of(asExpr((JCExpression) lambda.body)); 1322 } else { 1323 final ListBuffer<JCExpression> buffer = new ListBuffer<>(); 1324 DeferredAttr.LambdaReturnScanner lambdaScanner = 1325 new DeferredAttr.LambdaReturnScanner() { 1326 @Override 1327 public void visitReturn(JCReturn tree) { 1328 if (tree.expr != null) { 1329 buffer.append(asExpr(tree.expr)); 1330 } 1331 } 1332 }; 1333 lambdaScanner.scan(lambda.body); 1334 return buffer.toList(); 1335 } 1336 } 1337 1338 private JCExpression asExpr(JCExpression expr) { 1339 if (expr.type.hasTag(DEFERRED)) { 1340 JCTree speculativeTree = ((DeferredType)expr.type).speculativeTree(deferredAttrContext); 1341 if (speculativeTree != deferredAttr.stuckTree) { 1342 expr = (JCExpression)speculativeTree; 1343 } 1344 } 1345 return expr; 1346 } 1347 } 1348 1349 } 1350 1351 public MethodCheck mostSpecificCheck(List<Type> actuals) { 1352 Assert.error("Cannot get here!"); 1353 return null; 1354 } 1355 } 1356 1357 public static class InapplicableMethodException extends RuntimeException { 1358 private static final long serialVersionUID = 0; 1359 1360 JCDiagnostic diagnostic; 1361 JCDiagnostic.Factory diags; 1362 1363 InapplicableMethodException(JCDiagnostic.Factory diags) { 1364 this.diagnostic = null; 1365 this.diags = diags; 1366 } 1367 InapplicableMethodException setMessage() { 1368 return setMessage((JCDiagnostic)null); 1369 } 1370 InapplicableMethodException setMessage(String key) { 1371 return setMessage(key != null ? diags.fragment(key) : null); 1372 } 1373 InapplicableMethodException setMessage(String key, Object... args) { 1374 return setMessage(key != null ? diags.fragment(key, args) : null); 1375 } 1376 InapplicableMethodException setMessage(JCDiagnostic diag) { 1377 this.diagnostic = diag; 1378 return this; 1379 } 1380 1381 public JCDiagnostic getDiagnostic() { 1382 return diagnostic; 1383 } 1384 } 1385 private final InapplicableMethodException inapplicableMethodException; 1386 1387/* *************************************************************************** 1388 * Symbol lookup 1389 * the following naming conventions for arguments are used 1390 * 1391 * env is the environment where the symbol was mentioned 1392 * site is the type of which the symbol is a member 1393 * name is the symbol's name 1394 * if no arguments are given 1395 * argtypes are the value arguments, if we search for a method 1396 * 1397 * If no symbol was found, a ResolveError detailing the problem is returned. 1398 ****************************************************************************/ 1399 1400 /** Find field. Synthetic fields are always skipped. 1401 * @param env The current environment. 1402 * @param site The original type from where the selection takes place. 1403 * @param name The name of the field. 1404 * @param c The class to search for the field. This is always 1405 * a superclass or implemented interface of site's class. 1406 */ 1407 Symbol findField(Env<AttrContext> env, 1408 Type site, 1409 Name name, 1410 TypeSymbol c) { 1411 while (c.type.hasTag(TYPEVAR)) 1412 c = c.type.getUpperBound().tsym; 1413 Symbol bestSoFar = varNotFound; 1414 Symbol sym; 1415 for (Symbol s : c.members().getSymbolsByName(name)) { 1416 if (s.kind == VAR && (s.flags_field & SYNTHETIC) == 0) { 1417 return isAccessible(env, site, s) 1418 ? s : new AccessError(env, site, s); 1419 } 1420 } 1421 Type st = types.supertype(c.type); 1422 if (st != null && (st.hasTag(CLASS) || st.hasTag(TYPEVAR))) { 1423 sym = findField(env, site, name, st.tsym); 1424 bestSoFar = bestOf(bestSoFar, sym); 1425 } 1426 for (List<Type> l = types.interfaces(c.type); 1427 bestSoFar.kind != AMBIGUOUS && l.nonEmpty(); 1428 l = l.tail) { 1429 sym = findField(env, site, name, l.head.tsym); 1430 if (bestSoFar.exists() && sym.exists() && 1431 sym.owner != bestSoFar.owner) 1432 bestSoFar = new AmbiguityError(bestSoFar, sym); 1433 else 1434 bestSoFar = bestOf(bestSoFar, sym); 1435 } 1436 return bestSoFar; 1437 } 1438 1439 /** Resolve a field identifier, throw a fatal error if not found. 1440 * @param pos The position to use for error reporting. 1441 * @param env The environment current at the method invocation. 1442 * @param site The type of the qualifying expression, in which 1443 * identifier is searched. 1444 * @param name The identifier's name. 1445 */ 1446 public VarSymbol resolveInternalField(DiagnosticPosition pos, Env<AttrContext> env, 1447 Type site, Name name) { 1448 Symbol sym = findField(env, site, name, site.tsym); 1449 if (sym.kind == VAR) return (VarSymbol)sym; 1450 else throw new FatalError( 1451 diags.fragment("fatal.err.cant.locate.field", 1452 name)); 1453 } 1454 1455 /** Find unqualified variable or field with given name. 1456 * Synthetic fields always skipped. 1457 * @param env The current environment. 1458 * @param name The name of the variable or field. 1459 */ 1460 Symbol findVar(Env<AttrContext> env, Name name) { 1461 Symbol bestSoFar = varNotFound; 1462 Env<AttrContext> env1 = env; 1463 boolean staticOnly = false; 1464 while (env1.outer != null) { 1465 Symbol sym = null; 1466 if (isStatic(env1)) staticOnly = true; 1467 for (Symbol s : env1.info.scope.getSymbolsByName(name)) { 1468 if (s.kind == VAR && (s.flags_field & SYNTHETIC) == 0) { 1469 sym = s; 1470 break; 1471 } 1472 } 1473 if (sym == null) { 1474 sym = findField(env1, env1.enclClass.sym.type, name, env1.enclClass.sym); 1475 } 1476 if (sym.exists()) { 1477 if (staticOnly && 1478 sym.kind == VAR && 1479 sym.owner.kind == TYP && 1480 (sym.flags() & STATIC) == 0) 1481 return new StaticError(sym); 1482 else 1483 return sym; 1484 } else { 1485 bestSoFar = bestOf(bestSoFar, sym); 1486 } 1487 1488 if ((env1.enclClass.sym.flags() & STATIC) != 0) staticOnly = true; 1489 env1 = env1.outer; 1490 } 1491 1492 Symbol sym = findField(env, syms.predefClass.type, name, syms.predefClass); 1493 if (sym.exists()) 1494 return sym; 1495 if (bestSoFar.exists()) 1496 return bestSoFar; 1497 1498 Symbol origin = null; 1499 for (Scope sc : new Scope[] { env.toplevel.namedImportScope, env.toplevel.starImportScope }) { 1500 for (Symbol currentSymbol : sc.getSymbolsByName(name)) { 1501 if (currentSymbol.kind != VAR) 1502 continue; 1503 // invariant: sym.kind == Symbol.Kind.VAR 1504 if (!bestSoFar.kind.isResolutionError() && 1505 currentSymbol.owner != bestSoFar.owner) 1506 return new AmbiguityError(bestSoFar, currentSymbol); 1507 else if (!bestSoFar.kind.betterThan(VAR)) { 1508 origin = sc.getOrigin(currentSymbol).owner; 1509 bestSoFar = isAccessible(env, origin.type, currentSymbol) 1510 ? currentSymbol : new AccessError(env, origin.type, currentSymbol); 1511 } 1512 } 1513 if (bestSoFar.exists()) break; 1514 } 1515 if (bestSoFar.kind == VAR && bestSoFar.owner.type != origin.type) 1516 return bestSoFar.clone(origin); 1517 else 1518 return bestSoFar; 1519 } 1520 1521 Warner noteWarner = new Warner(); 1522 1523 /** Select the best method for a call site among two choices. 1524 * @param env The current environment. 1525 * @param site The original type from where the 1526 * selection takes place. 1527 * @param argtypes The invocation's value arguments, 1528 * @param typeargtypes The invocation's type arguments, 1529 * @param sym Proposed new best match. 1530 * @param bestSoFar Previously found best match. 1531 * @param allowBoxing Allow boxing conversions of arguments. 1532 * @param useVarargs Box trailing arguments into an array for varargs. 1533 */ 1534 @SuppressWarnings("fallthrough") 1535 Symbol selectBest(Env<AttrContext> env, 1536 Type site, 1537 List<Type> argtypes, 1538 List<Type> typeargtypes, 1539 Symbol sym, 1540 Symbol bestSoFar, 1541 boolean allowBoxing, 1542 boolean useVarargs) { 1543 if (sym.kind == ERR || 1544 !sym.isInheritedIn(site.tsym, types)) { 1545 return bestSoFar; 1546 } else if (useVarargs && (sym.flags() & VARARGS) == 0) { 1547 return bestSoFar.kind.isResolutionError() ? 1548 new BadVarargsMethod((ResolveError)bestSoFar.baseSymbol()) : 1549 bestSoFar; 1550 } 1551 Assert.check(!sym.kind.isResolutionError()); 1552 try { 1553 types.noWarnings.clear(); 1554 Type mt = rawInstantiate(env, site, sym, null, argtypes, typeargtypes, 1555 allowBoxing, useVarargs, types.noWarnings); 1556 currentResolutionContext.addApplicableCandidate(sym, mt); 1557 } catch (InapplicableMethodException ex) { 1558 currentResolutionContext.addInapplicableCandidate(sym, ex.getDiagnostic()); 1559 switch (bestSoFar.kind) { 1560 case ABSENT_MTH: 1561 return new InapplicableSymbolError(currentResolutionContext); 1562 case WRONG_MTH: 1563 bestSoFar = new InapplicableSymbolsError(currentResolutionContext); 1564 default: 1565 return bestSoFar; 1566 } 1567 } 1568 if (!isAccessible(env, site, sym)) { 1569 return (bestSoFar.kind == ABSENT_MTH) 1570 ? new AccessError(env, site, sym) 1571 : bestSoFar; 1572 } 1573 return (bestSoFar.kind.isResolutionError() && bestSoFar.kind != AMBIGUOUS) 1574 ? sym 1575 : mostSpecific(argtypes, sym, bestSoFar, env, site, useVarargs); 1576 } 1577 1578 /* Return the most specific of the two methods for a call, 1579 * given that both are accessible and applicable. 1580 * @param m1 A new candidate for most specific. 1581 * @param m2 The previous most specific candidate. 1582 * @param env The current environment. 1583 * @param site The original type from where the selection 1584 * takes place. 1585 * @param allowBoxing Allow boxing conversions of arguments. 1586 * @param useVarargs Box trailing arguments into an array for varargs. 1587 */ 1588 Symbol mostSpecific(List<Type> argtypes, Symbol m1, 1589 Symbol m2, 1590 Env<AttrContext> env, 1591 final Type site, 1592 boolean useVarargs) { 1593 switch (m2.kind) { 1594 case MTH: 1595 if (m1 == m2) return m1; 1596 boolean m1SignatureMoreSpecific = 1597 signatureMoreSpecific(argtypes, env, site, m1, m2, useVarargs); 1598 boolean m2SignatureMoreSpecific = 1599 signatureMoreSpecific(argtypes, env, site, m2, m1, useVarargs); 1600 if (m1SignatureMoreSpecific && m2SignatureMoreSpecific) { 1601 Type mt1 = types.memberType(site, m1); 1602 Type mt2 = types.memberType(site, m2); 1603 if (!types.overrideEquivalent(mt1, mt2)) 1604 return ambiguityError(m1, m2); 1605 1606 // same signature; select (a) the non-bridge method, or 1607 // (b) the one that overrides the other, or (c) the concrete 1608 // one, or (d) merge both abstract signatures 1609 if ((m1.flags() & BRIDGE) != (m2.flags() & BRIDGE)) 1610 return ((m1.flags() & BRIDGE) != 0) ? m2 : m1; 1611 1612 // if one overrides or hides the other, use it 1613 TypeSymbol m1Owner = (TypeSymbol)m1.owner; 1614 TypeSymbol m2Owner = (TypeSymbol)m2.owner; 1615 if (types.asSuper(m1Owner.type, m2Owner) != null && 1616 ((m1.owner.flags_field & INTERFACE) == 0 || 1617 (m2.owner.flags_field & INTERFACE) != 0) && 1618 m1.overrides(m2, m1Owner, types, false)) 1619 return m1; 1620 if (types.asSuper(m2Owner.type, m1Owner) != null && 1621 ((m2.owner.flags_field & INTERFACE) == 0 || 1622 (m1.owner.flags_field & INTERFACE) != 0) && 1623 m2.overrides(m1, m2Owner, types, false)) 1624 return m2; 1625 boolean m1Abstract = (m1.flags() & ABSTRACT) != 0; 1626 boolean m2Abstract = (m2.flags() & ABSTRACT) != 0; 1627 if (m1Abstract && !m2Abstract) return m2; 1628 if (m2Abstract && !m1Abstract) return m1; 1629 // both abstract or both concrete 1630 return ambiguityError(m1, m2); 1631 } 1632 if (m1SignatureMoreSpecific) return m1; 1633 if (m2SignatureMoreSpecific) return m2; 1634 return ambiguityError(m1, m2); 1635 case AMBIGUOUS: 1636 //compare m1 to ambiguous methods in m2 1637 AmbiguityError e = (AmbiguityError)m2.baseSymbol(); 1638 boolean m1MoreSpecificThanAnyAmbiguous = true; 1639 boolean allAmbiguousMoreSpecificThanM1 = true; 1640 for (Symbol s : e.ambiguousSyms) { 1641 Symbol moreSpecific = mostSpecific(argtypes, m1, s, env, site, useVarargs); 1642 m1MoreSpecificThanAnyAmbiguous &= moreSpecific == m1; 1643 allAmbiguousMoreSpecificThanM1 &= moreSpecific == s; 1644 } 1645 if (m1MoreSpecificThanAnyAmbiguous) 1646 return m1; 1647 //if m1 is more specific than some ambiguous methods, but other ambiguous methods are 1648 //more specific than m1, add it as a new ambiguous method: 1649 if (!allAmbiguousMoreSpecificThanM1) 1650 e.addAmbiguousSymbol(m1); 1651 return e; 1652 default: 1653 throw new AssertionError(); 1654 } 1655 } 1656 //where 1657 private boolean signatureMoreSpecific(List<Type> actuals, Env<AttrContext> env, Type site, Symbol m1, Symbol m2, boolean useVarargs) { 1658 noteWarner.clear(); 1659 int maxLength = Math.max( 1660 Math.max(m1.type.getParameterTypes().length(), actuals.length()), 1661 m2.type.getParameterTypes().length()); 1662 MethodResolutionContext prevResolutionContext = currentResolutionContext; 1663 try { 1664 currentResolutionContext = new MethodResolutionContext(); 1665 currentResolutionContext.step = prevResolutionContext.step; 1666 currentResolutionContext.methodCheck = 1667 prevResolutionContext.methodCheck.mostSpecificCheck(actuals); 1668 Type mst = instantiate(env, site, m2, null, 1669 adjustArgs(types.cvarLowerBounds(types.memberType(site, m1).getParameterTypes()), m1, maxLength, useVarargs), null, 1670 false, useVarargs, noteWarner); 1671 return mst != null && 1672 !noteWarner.hasLint(Lint.LintCategory.UNCHECKED); 1673 } finally { 1674 currentResolutionContext = prevResolutionContext; 1675 } 1676 } 1677 1678 List<Type> adjustArgs(List<Type> args, Symbol msym, int length, boolean allowVarargs) { 1679 if ((msym.flags() & VARARGS) != 0 && allowVarargs) { 1680 Type varargsElem = types.elemtype(args.last()); 1681 if (varargsElem == null) { 1682 Assert.error("Bad varargs = " + args.last() + " " + msym); 1683 } 1684 List<Type> newArgs = args.reverse().tail.prepend(varargsElem).reverse(); 1685 while (newArgs.length() < length) { 1686 newArgs = newArgs.append(newArgs.last()); 1687 } 1688 return newArgs; 1689 } else { 1690 return args; 1691 } 1692 } 1693 //where 1694 Symbol ambiguityError(Symbol m1, Symbol m2) { 1695 if (((m1.flags() | m2.flags()) & CLASH) != 0) { 1696 return (m1.flags() & CLASH) == 0 ? m1 : m2; 1697 } else { 1698 return new AmbiguityError(m1, m2); 1699 } 1700 } 1701 1702 Symbol findMethodInScope(Env<AttrContext> env, 1703 Type site, 1704 Name name, 1705 List<Type> argtypes, 1706 List<Type> typeargtypes, 1707 Scope sc, 1708 Symbol bestSoFar, 1709 boolean allowBoxing, 1710 boolean useVarargs, 1711 boolean abstractok) { 1712 for (Symbol s : sc.getSymbolsByName(name, new LookupFilter(abstractok))) { 1713 bestSoFar = selectBest(env, site, argtypes, typeargtypes, s, 1714 bestSoFar, allowBoxing, useVarargs); 1715 } 1716 return bestSoFar; 1717 } 1718 //where 1719 class LookupFilter implements Filter<Symbol> { 1720 1721 boolean abstractOk; 1722 1723 LookupFilter(boolean abstractOk) { 1724 this.abstractOk = abstractOk; 1725 } 1726 1727 public boolean accepts(Symbol s) { 1728 long flags = s.flags(); 1729 return s.kind == MTH && 1730 (flags & SYNTHETIC) == 0 && 1731 (abstractOk || 1732 (flags & DEFAULT) != 0 || 1733 (flags & ABSTRACT) == 0); 1734 } 1735 } 1736 1737 /** Find best qualified method matching given name, type and value 1738 * arguments. 1739 * @param env The current environment. 1740 * @param site The original type from where the selection 1741 * takes place. 1742 * @param name The method's name. 1743 * @param argtypes The method's value arguments. 1744 * @param typeargtypes The method's type arguments 1745 * @param allowBoxing Allow boxing conversions of arguments. 1746 * @param useVarargs Box trailing arguments into an array for varargs. 1747 */ 1748 Symbol findMethod(Env<AttrContext> env, 1749 Type site, 1750 Name name, 1751 List<Type> argtypes, 1752 List<Type> typeargtypes, 1753 boolean allowBoxing, 1754 boolean useVarargs) { 1755 Symbol bestSoFar = methodNotFound; 1756 bestSoFar = findMethod(env, 1757 site, 1758 name, 1759 argtypes, 1760 typeargtypes, 1761 site.tsym.type, 1762 bestSoFar, 1763 allowBoxing, 1764 useVarargs); 1765 return bestSoFar; 1766 } 1767 // where 1768 private Symbol findMethod(Env<AttrContext> env, 1769 Type site, 1770 Name name, 1771 List<Type> argtypes, 1772 List<Type> typeargtypes, 1773 Type intype, 1774 Symbol bestSoFar, 1775 boolean allowBoxing, 1776 boolean useVarargs) { 1777 @SuppressWarnings({"unchecked","rawtypes"}) 1778 List<Type>[] itypes = (List<Type>[])new List[] { List.<Type>nil(), List.<Type>nil() }; 1779 1780 InterfaceLookupPhase iphase = InterfaceLookupPhase.ABSTRACT_OK; 1781 for (TypeSymbol s : superclasses(intype)) { 1782 bestSoFar = findMethodInScope(env, site, name, argtypes, typeargtypes, 1783 s.members(), bestSoFar, allowBoxing, useVarargs, true); 1784 if (name == names.init) return bestSoFar; 1785 iphase = (iphase == null) ? null : iphase.update(s, this); 1786 if (iphase != null) { 1787 for (Type itype : types.interfaces(s.type)) { 1788 itypes[iphase.ordinal()] = types.union(types.closure(itype), itypes[iphase.ordinal()]); 1789 } 1790 } 1791 } 1792 1793 Symbol concrete = bestSoFar.kind.isValid() && 1794 (bestSoFar.flags() & ABSTRACT) == 0 ? 1795 bestSoFar : methodNotFound; 1796 1797 for (InterfaceLookupPhase iphase2 : InterfaceLookupPhase.values()) { 1798 //keep searching for abstract methods 1799 for (Type itype : itypes[iphase2.ordinal()]) { 1800 if (!itype.isInterface()) continue; //skip j.l.Object (included by Types.closure()) 1801 if (iphase2 == InterfaceLookupPhase.DEFAULT_OK && 1802 (itype.tsym.flags() & DEFAULT) == 0) continue; 1803 bestSoFar = findMethodInScope(env, site, name, argtypes, typeargtypes, 1804 itype.tsym.members(), bestSoFar, allowBoxing, useVarargs, true); 1805 if (concrete != bestSoFar && 1806 concrete.kind.isValid() && 1807 bestSoFar.kind.isValid() && 1808 types.isSubSignature(concrete.type, bestSoFar.type)) { 1809 //this is an hack - as javac does not do full membership checks 1810 //most specific ends up comparing abstract methods that might have 1811 //been implemented by some concrete method in a subclass and, 1812 //because of raw override, it is possible for an abstract method 1813 //to be more specific than the concrete method - so we need 1814 //to explicitly call that out (see CR 6178365) 1815 bestSoFar = concrete; 1816 } 1817 } 1818 } 1819 return bestSoFar; 1820 } 1821 1822 enum InterfaceLookupPhase { 1823 ABSTRACT_OK() { 1824 @Override 1825 InterfaceLookupPhase update(Symbol s, Resolve rs) { 1826 //We should not look for abstract methods if receiver is a concrete class 1827 //(as concrete classes are expected to implement all abstracts coming 1828 //from superinterfaces) 1829 if ((s.flags() & (ABSTRACT | INTERFACE | ENUM)) != 0) { 1830 return this; 1831 } else { 1832 return DEFAULT_OK; 1833 } 1834 } 1835 }, 1836 DEFAULT_OK() { 1837 @Override 1838 InterfaceLookupPhase update(Symbol s, Resolve rs) { 1839 return this; 1840 } 1841 }; 1842 1843 abstract InterfaceLookupPhase update(Symbol s, Resolve rs); 1844 } 1845 1846 /** 1847 * Return an Iterable object to scan the superclasses of a given type. 1848 * It's crucial that the scan is done lazily, as we don't want to accidentally 1849 * access more supertypes than strictly needed (as this could trigger completion 1850 * errors if some of the not-needed supertypes are missing/ill-formed). 1851 */ 1852 Iterable<TypeSymbol> superclasses(final Type intype) { 1853 return new Iterable<TypeSymbol>() { 1854 public Iterator<TypeSymbol> iterator() { 1855 return new Iterator<TypeSymbol>() { 1856 1857 List<TypeSymbol> seen = List.nil(); 1858 TypeSymbol currentSym = symbolFor(intype); 1859 TypeSymbol prevSym = null; 1860 1861 public boolean hasNext() { 1862 if (currentSym == syms.noSymbol) { 1863 currentSym = symbolFor(types.supertype(prevSym.type)); 1864 } 1865 return currentSym != null; 1866 } 1867 1868 public TypeSymbol next() { 1869 prevSym = currentSym; 1870 currentSym = syms.noSymbol; 1871 Assert.check(prevSym != null || prevSym != syms.noSymbol); 1872 return prevSym; 1873 } 1874 1875 public void remove() { 1876 throw new UnsupportedOperationException(); 1877 } 1878 1879 TypeSymbol symbolFor(Type t) { 1880 if (!t.hasTag(CLASS) && 1881 !t.hasTag(TYPEVAR)) { 1882 return null; 1883 } 1884 t = types.skipTypeVars(t, false); 1885 if (seen.contains(t.tsym)) { 1886 //degenerate case in which we have a circular 1887 //class hierarchy - because of ill-formed classfiles 1888 return null; 1889 } 1890 seen = seen.prepend(t.tsym); 1891 return t.tsym; 1892 } 1893 }; 1894 } 1895 }; 1896 } 1897 1898 /** Find unqualified method matching given name, type and value arguments. 1899 * @param env The current environment. 1900 * @param name The method's name. 1901 * @param argtypes The method's value arguments. 1902 * @param typeargtypes The method's type arguments. 1903 * @param allowBoxing Allow boxing conversions of arguments. 1904 * @param useVarargs Box trailing arguments into an array for varargs. 1905 */ 1906 Symbol findFun(Env<AttrContext> env, Name name, 1907 List<Type> argtypes, List<Type> typeargtypes, 1908 boolean allowBoxing, boolean useVarargs) { 1909 Symbol bestSoFar = methodNotFound; 1910 Env<AttrContext> env1 = env; 1911 boolean staticOnly = false; 1912 while (env1.outer != null) { 1913 if (isStatic(env1)) staticOnly = true; 1914 Assert.check(env1.info.preferredTreeForDiagnostics == null); 1915 env1.info.preferredTreeForDiagnostics = env.tree; 1916 try { 1917 Symbol sym = findMethod( 1918 env1, env1.enclClass.sym.type, name, argtypes, typeargtypes, 1919 allowBoxing, useVarargs); 1920 if (sym.exists()) { 1921 if (staticOnly && 1922 sym.kind == MTH && 1923 sym.owner.kind == TYP && 1924 (sym.flags() & STATIC) == 0) return new StaticError(sym); 1925 else return sym; 1926 } else { 1927 bestSoFar = bestOf(bestSoFar, sym); 1928 } 1929 } finally { 1930 env1.info.preferredTreeForDiagnostics = null; 1931 } 1932 if ((env1.enclClass.sym.flags() & STATIC) != 0) staticOnly = true; 1933 env1 = env1.outer; 1934 } 1935 1936 Symbol sym = findMethod(env, syms.predefClass.type, name, argtypes, 1937 typeargtypes, allowBoxing, useVarargs); 1938 if (sym.exists()) 1939 return sym; 1940 1941 for (Symbol currentSym : env.toplevel.namedImportScope.getSymbolsByName(name)) { 1942 Symbol origin = env.toplevel.namedImportScope.getOrigin(currentSym).owner; 1943 if (currentSym.kind == MTH) { 1944 if (currentSym.owner.type != origin.type) 1945 currentSym = currentSym.clone(origin); 1946 if (!isAccessible(env, origin.type, currentSym)) 1947 currentSym = new AccessError(env, origin.type, currentSym); 1948 bestSoFar = selectBest(env, origin.type, 1949 argtypes, typeargtypes, 1950 currentSym, bestSoFar, 1951 allowBoxing, useVarargs); 1952 } 1953 } 1954 if (bestSoFar.exists()) 1955 return bestSoFar; 1956 1957 for (Symbol currentSym : env.toplevel.starImportScope.getSymbolsByName(name)) { 1958 Symbol origin = env.toplevel.starImportScope.getOrigin(currentSym).owner; 1959 if (currentSym.kind == MTH) { 1960 if (currentSym.owner.type != origin.type) 1961 currentSym = currentSym.clone(origin); 1962 if (!isAccessible(env, origin.type, currentSym)) 1963 currentSym = new AccessError(env, origin.type, currentSym); 1964 bestSoFar = selectBest(env, origin.type, 1965 argtypes, typeargtypes, 1966 currentSym, bestSoFar, 1967 allowBoxing, useVarargs); 1968 } 1969 } 1970 return bestSoFar; 1971 } 1972 1973 /** Load toplevel or member class with given fully qualified name and 1974 * verify that it is accessible. 1975 * @param env The current environment. 1976 * @param name The fully qualified name of the class to be loaded. 1977 */ 1978 Symbol loadClass(Env<AttrContext> env, Name name) { 1979 try { 1980 ClassSymbol c = finder.loadClass(env.toplevel.modle, name); 1981 return isAccessible(env, c) ? c : new AccessError(c); 1982 } catch (ClassFinder.BadClassFile err) { 1983 throw err; 1984 } catch (CompletionFailure ex) { 1985 //even if a class cannot be found in the current module and packages in modules it depends on that 1986 //are exported for any or this module, the class may exist internally in some of these modules, 1987 //or may exist in a module on which this module does not depend. Provide better diagnostic in 1988 //such cases by looking for the class in any module: 1989 for (ModuleSymbol ms : syms.getAllModules()) { 1990 //do not load currently unloaded classes, to avoid too eager completion of random things in other modules: 1991 ClassSymbol clazz = syms.getClass(ms, name); 1992 1993 if (clazz != null) { 1994 return new AccessError(clazz); 1995 } 1996 } 1997 return typeNotFound; 1998 } 1999 } 2000 2001 /** 2002 * Find a type declared in a scope (not inherited). Return null 2003 * if none is found. 2004 * @param env The current environment. 2005 * @param site The original type from where the selection takes 2006 * place. 2007 * @param name The type's name. 2008 * @param c The class to search for the member type. This is 2009 * always a superclass or implemented interface of 2010 * site's class. 2011 */ 2012 Symbol findImmediateMemberType(Env<AttrContext> env, 2013 Type site, 2014 Name name, 2015 TypeSymbol c) { 2016 for (Symbol sym : c.members().getSymbolsByName(name)) { 2017 if (sym.kind == TYP) { 2018 return isAccessible(env, site, sym) 2019 ? sym 2020 : new AccessError(env, site, sym); 2021 } 2022 } 2023 return typeNotFound; 2024 } 2025 2026 /** Find a member type inherited from a superclass or interface. 2027 * @param env The current environment. 2028 * @param site The original type from where the selection takes 2029 * place. 2030 * @param name The type's name. 2031 * @param c The class to search for the member type. This is 2032 * always a superclass or implemented interface of 2033 * site's class. 2034 */ 2035 Symbol findInheritedMemberType(Env<AttrContext> env, 2036 Type site, 2037 Name name, 2038 TypeSymbol c) { 2039 Symbol bestSoFar = typeNotFound; 2040 Symbol sym; 2041 Type st = types.supertype(c.type); 2042 if (st != null && st.hasTag(CLASS)) { 2043 sym = findMemberType(env, site, name, st.tsym); 2044 bestSoFar = bestOf(bestSoFar, sym); 2045 } 2046 for (List<Type> l = types.interfaces(c.type); 2047 bestSoFar.kind != AMBIGUOUS && l.nonEmpty(); 2048 l = l.tail) { 2049 sym = findMemberType(env, site, name, l.head.tsym); 2050 if (!bestSoFar.kind.isResolutionError() && 2051 !sym.kind.isResolutionError() && 2052 sym.owner != bestSoFar.owner) 2053 bestSoFar = new AmbiguityError(bestSoFar, sym); 2054 else 2055 bestSoFar = bestOf(bestSoFar, sym); 2056 } 2057 return bestSoFar; 2058 } 2059 2060 /** Find qualified member type. 2061 * @param env The current environment. 2062 * @param site The original type from where the selection takes 2063 * place. 2064 * @param name The type's name. 2065 * @param c The class to search for the member type. This is 2066 * always a superclass or implemented interface of 2067 * site's class. 2068 */ 2069 Symbol findMemberType(Env<AttrContext> env, 2070 Type site, 2071 Name name, 2072 TypeSymbol c) { 2073 Symbol sym = findImmediateMemberType(env, site, name, c); 2074 2075 if (sym != typeNotFound) 2076 return sym; 2077 2078 return findInheritedMemberType(env, site, name, c); 2079 2080 } 2081 2082 /** Find a global type in given scope and load corresponding class. 2083 * @param env The current environment. 2084 * @param scope The scope in which to look for the type. 2085 * @param name The type's name. 2086 */ 2087 Symbol findGlobalType(Env<AttrContext> env, Scope scope, Name name) { 2088 Symbol bestSoFar = typeNotFound; 2089 for (Symbol s : scope.getSymbolsByName(name)) { 2090 Symbol sym = loadClass(env, s.flatName()); 2091 if (bestSoFar.kind == TYP && sym.kind == TYP && 2092 bestSoFar != sym) 2093 return new AmbiguityError(bestSoFar, sym); 2094 else 2095 bestSoFar = bestOf(bestSoFar, sym); 2096 } 2097 return bestSoFar; 2098 } 2099 2100 Symbol findTypeVar(Env<AttrContext> env, Name name, boolean staticOnly) { 2101 for (Symbol sym : env.info.scope.getSymbolsByName(name)) { 2102 if (sym.kind == TYP) { 2103 if (staticOnly && 2104 sym.type.hasTag(TYPEVAR) && 2105 sym.owner.kind == TYP) 2106 return new StaticError(sym); 2107 return sym; 2108 } 2109 } 2110 return typeNotFound; 2111 } 2112 2113 /** Find an unqualified type symbol. 2114 * @param env The current environment. 2115 * @param name The type's name. 2116 */ 2117 Symbol findType(Env<AttrContext> env, Name name) { 2118 if (name == names.empty) 2119 return typeNotFound; // do not allow inadvertent "lookup" of anonymous types 2120 Symbol bestSoFar = typeNotFound; 2121 Symbol sym; 2122 boolean staticOnly = false; 2123 for (Env<AttrContext> env1 = env; env1.outer != null; env1 = env1.outer) { 2124 if (isStatic(env1)) staticOnly = true; 2125 // First, look for a type variable and the first member type 2126 final Symbol tyvar = findTypeVar(env1, name, staticOnly); 2127 sym = findImmediateMemberType(env1, env1.enclClass.sym.type, 2128 name, env1.enclClass.sym); 2129 2130 // Return the type variable if we have it, and have no 2131 // immediate member, OR the type variable is for a method. 2132 if (tyvar != typeNotFound) { 2133 if (env.baseClause || sym == typeNotFound || 2134 (tyvar.kind == TYP && tyvar.exists() && 2135 tyvar.owner.kind == MTH)) { 2136 return tyvar; 2137 } 2138 } 2139 2140 // If the environment is a class def, finish up, 2141 // otherwise, do the entire findMemberType 2142 if (sym == typeNotFound) 2143 sym = findInheritedMemberType(env1, env1.enclClass.sym.type, 2144 name, env1.enclClass.sym); 2145 2146 if (staticOnly && sym.kind == TYP && 2147 sym.type.hasTag(CLASS) && 2148 sym.type.getEnclosingType().hasTag(CLASS) && 2149 env1.enclClass.sym.type.isParameterized() && 2150 sym.type.getEnclosingType().isParameterized()) 2151 return new StaticError(sym); 2152 else if (sym.exists()) return sym; 2153 else bestSoFar = bestOf(bestSoFar, sym); 2154 2155 JCClassDecl encl = env1.baseClause ? (JCClassDecl)env1.tree : env1.enclClass; 2156 if ((encl.sym.flags() & STATIC) != 0) 2157 staticOnly = true; 2158 } 2159 2160 if (!env.tree.hasTag(IMPORT)) { 2161 sym = findGlobalType(env, env.toplevel.namedImportScope, name); 2162 if (sym.exists()) return sym; 2163 else bestSoFar = bestOf(bestSoFar, sym); 2164 2165 sym = findGlobalType(env, env.toplevel.packge.members(), name); 2166 if (sym.exists()) return sym; 2167 else bestSoFar = bestOf(bestSoFar, sym); 2168 2169 sym = findGlobalType(env, env.toplevel.starImportScope, name); 2170 if (sym.exists()) return sym; 2171 else bestSoFar = bestOf(bestSoFar, sym); 2172 } 2173 2174 return bestSoFar; 2175 } 2176 2177 /** Find an unqualified identifier which matches a specified kind set. 2178 * @param env The current environment. 2179 * @param name The identifier's name. 2180 * @param kind Indicates the possible symbol kinds 2181 * (a subset of VAL, TYP, PCK). 2182 */ 2183 Symbol findIdent(Env<AttrContext> env, Name name, KindSelector kind) { 2184 Symbol bestSoFar = typeNotFound; 2185 Symbol sym; 2186 2187 if (kind.contains(KindSelector.VAL)) { 2188 sym = findVar(env, name); 2189 if (sym.exists()) return sym; 2190 else bestSoFar = bestOf(bestSoFar, sym); 2191 } 2192 2193 if (kind.contains(KindSelector.TYP)) { 2194 sym = findType(env, name); 2195 2196 if (sym.exists()) return sym; 2197 else bestSoFar = bestOf(bestSoFar, sym); 2198 } 2199 2200 if (kind.contains(KindSelector.PCK)) 2201 return syms.lookupPackage(env.toplevel.modle, name); 2202 else return bestSoFar; 2203 } 2204 2205 /** Find an identifier in a package which matches a specified kind set. 2206 * @param env The current environment. 2207 * @param name The identifier's name. 2208 * @param kind Indicates the possible symbol kinds 2209 * (a nonempty subset of TYP, PCK). 2210 */ 2211 Symbol findIdentInPackage(Env<AttrContext> env, TypeSymbol pck, 2212 Name name, KindSelector kind) { 2213 Name fullname = TypeSymbol.formFullName(name, pck); 2214 Symbol bestSoFar = typeNotFound; 2215 PackageSymbol pack = null; 2216 if (kind.contains(KindSelector.PCK)) { 2217 pack = syms.lookupPackage(env.toplevel.modle, fullname); 2218 if (pack.exists()) return pack; 2219 } 2220 if (kind.contains(KindSelector.TYP)) { 2221 Symbol sym = loadClass(env, fullname); 2222 if (sym.exists()) { 2223 // don't allow programs to use flatnames 2224 if (name == sym.name) return sym; 2225 } 2226 else bestSoFar = bestOf(bestSoFar, sym); 2227 } 2228 return (pack != null) ? pack : bestSoFar; 2229 } 2230 2231 /** Find an identifier among the members of a given type `site'. 2232 * @param env The current environment. 2233 * @param site The type containing the symbol to be found. 2234 * @param name The identifier's name. 2235 * @param kind Indicates the possible symbol kinds 2236 * (a subset of VAL, TYP). 2237 */ 2238 Symbol findIdentInType(Env<AttrContext> env, Type site, 2239 Name name, KindSelector kind) { 2240 Symbol bestSoFar = typeNotFound; 2241 Symbol sym; 2242 if (kind.contains(KindSelector.VAL)) { 2243 sym = findField(env, site, name, site.tsym); 2244 if (sym.exists()) return sym; 2245 else bestSoFar = bestOf(bestSoFar, sym); 2246 } 2247 2248 if (kind.contains(KindSelector.TYP)) { 2249 sym = findMemberType(env, site, name, site.tsym); 2250 if (sym.exists()) return sym; 2251 else bestSoFar = bestOf(bestSoFar, sym); 2252 } 2253 return bestSoFar; 2254 } 2255 2256/* *************************************************************************** 2257 * Access checking 2258 * The following methods convert ResolveErrors to ErrorSymbols, issuing 2259 * an error message in the process 2260 ****************************************************************************/ 2261 2262 /** If `sym' is a bad symbol: report error and return errSymbol 2263 * else pass through unchanged, 2264 * additional arguments duplicate what has been used in trying to find the 2265 * symbol {@literal (--> flyweight pattern)}. This improves performance since we 2266 * expect misses to happen frequently. 2267 * 2268 * @param sym The symbol that was found, or a ResolveError. 2269 * @param pos The position to use for error reporting. 2270 * @param location The symbol the served as a context for this lookup 2271 * @param site The original type from where the selection took place. 2272 * @param name The symbol's name. 2273 * @param qualified Did we get here through a qualified expression resolution? 2274 * @param argtypes The invocation's value arguments, 2275 * if we looked for a method. 2276 * @param typeargtypes The invocation's type arguments, 2277 * if we looked for a method. 2278 * @param logResolveHelper helper class used to log resolve errors 2279 */ 2280 Symbol accessInternal(Symbol sym, 2281 DiagnosticPosition pos, 2282 Symbol location, 2283 Type site, 2284 Name name, 2285 boolean qualified, 2286 List<Type> argtypes, 2287 List<Type> typeargtypes, 2288 LogResolveHelper logResolveHelper) { 2289 if (sym.kind.isResolutionError()) { 2290 ResolveError errSym = (ResolveError)sym.baseSymbol(); 2291 sym = errSym.access(name, qualified ? site.tsym : syms.noSymbol); 2292 argtypes = logResolveHelper.getArgumentTypes(errSym, sym, name, argtypes); 2293 if (logResolveHelper.resolveDiagnosticNeeded(site, argtypes, typeargtypes)) { 2294 logResolveError(errSym, pos, location, site, name, argtypes, typeargtypes); 2295 } 2296 } 2297 return sym; 2298 } 2299 2300 /** 2301 * Variant of the generalized access routine, to be used for generating method 2302 * resolution diagnostics 2303 */ 2304 Symbol accessMethod(Symbol sym, 2305 DiagnosticPosition pos, 2306 Symbol location, 2307 Type site, 2308 Name name, 2309 boolean qualified, 2310 List<Type> argtypes, 2311 List<Type> typeargtypes) { 2312 return accessInternal(sym, pos, location, site, name, qualified, argtypes, typeargtypes, methodLogResolveHelper); 2313 } 2314 2315 /** Same as original accessMethod(), but without location. 2316 */ 2317 Symbol accessMethod(Symbol sym, 2318 DiagnosticPosition pos, 2319 Type site, 2320 Name name, 2321 boolean qualified, 2322 List<Type> argtypes, 2323 List<Type> typeargtypes) { 2324 return accessMethod(sym, pos, site.tsym, site, name, qualified, argtypes, typeargtypes); 2325 } 2326 2327 /** 2328 * Variant of the generalized access routine, to be used for generating variable, 2329 * type resolution diagnostics 2330 */ 2331 Symbol accessBase(Symbol sym, 2332 DiagnosticPosition pos, 2333 Symbol location, 2334 Type site, 2335 Name name, 2336 boolean qualified) { 2337 return accessInternal(sym, pos, location, site, name, qualified, List.<Type>nil(), null, basicLogResolveHelper); 2338 } 2339 2340 /** Same as original accessBase(), but without location. 2341 */ 2342 Symbol accessBase(Symbol sym, 2343 DiagnosticPosition pos, 2344 Type site, 2345 Name name, 2346 boolean qualified) { 2347 return accessBase(sym, pos, site.tsym, site, name, qualified); 2348 } 2349 2350 interface LogResolveHelper { 2351 boolean resolveDiagnosticNeeded(Type site, List<Type> argtypes, List<Type> typeargtypes); 2352 List<Type> getArgumentTypes(ResolveError errSym, Symbol accessedSym, Name name, List<Type> argtypes); 2353 } 2354 2355 LogResolveHelper basicLogResolveHelper = new LogResolveHelper() { 2356 public boolean resolveDiagnosticNeeded(Type site, List<Type> argtypes, List<Type> typeargtypes) { 2357 return !site.isErroneous(); 2358 } 2359 public List<Type> getArgumentTypes(ResolveError errSym, Symbol accessedSym, Name name, List<Type> argtypes) { 2360 return argtypes; 2361 } 2362 }; 2363 2364 LogResolveHelper methodLogResolveHelper = new LogResolveHelper() { 2365 public boolean resolveDiagnosticNeeded(Type site, List<Type> argtypes, List<Type> typeargtypes) { 2366 return !site.isErroneous() && 2367 !Type.isErroneous(argtypes) && 2368 (typeargtypes == null || !Type.isErroneous(typeargtypes)); 2369 } 2370 public List<Type> getArgumentTypes(ResolveError errSym, Symbol accessedSym, Name name, List<Type> argtypes) { 2371 return argtypes.map(new ResolveDeferredRecoveryMap(AttrMode.SPECULATIVE, accessedSym, currentResolutionContext.step)); 2372 } 2373 }; 2374 2375 class ResolveDeferredRecoveryMap extends DeferredAttr.RecoveryDeferredTypeMap { 2376 2377 public ResolveDeferredRecoveryMap(AttrMode mode, Symbol msym, MethodResolutionPhase step) { 2378 deferredAttr.super(mode, msym, step); 2379 } 2380 2381 @Override 2382 protected Type typeOf(DeferredType dt) { 2383 Type res = super.typeOf(dt); 2384 if (!res.isErroneous()) { 2385 switch (TreeInfo.skipParens(dt.tree).getTag()) { 2386 case LAMBDA: 2387 case REFERENCE: 2388 return dt; 2389 case CONDEXPR: 2390 return res == Type.recoveryType ? 2391 dt : res; 2392 } 2393 } 2394 return res; 2395 } 2396 } 2397 2398 /** Check that sym is not an abstract method. 2399 */ 2400 void checkNonAbstract(DiagnosticPosition pos, Symbol sym) { 2401 if ((sym.flags() & ABSTRACT) != 0 && (sym.flags() & DEFAULT) == 0) 2402 log.error(pos, "abstract.cant.be.accessed.directly", 2403 kindName(sym), sym, sym.location()); 2404 } 2405 2406/* *************************************************************************** 2407 * Name resolution 2408 * Naming conventions are as for symbol lookup 2409 * Unlike the find... methods these methods will report access errors 2410 ****************************************************************************/ 2411 2412 /** Resolve an unqualified (non-method) identifier. 2413 * @param pos The position to use for error reporting. 2414 * @param env The environment current at the identifier use. 2415 * @param name The identifier's name. 2416 * @param kind The set of admissible symbol kinds for the identifier. 2417 */ 2418 Symbol resolveIdent(DiagnosticPosition pos, Env<AttrContext> env, 2419 Name name, KindSelector kind) { 2420 return accessBase( 2421 findIdent(env, name, kind), 2422 pos, env.enclClass.sym.type, name, false); 2423 } 2424 2425 /** Resolve an unqualified method identifier. 2426 * @param pos The position to use for error reporting. 2427 * @param env The environment current at the method invocation. 2428 * @param name The identifier's name. 2429 * @param argtypes The types of the invocation's value arguments. 2430 * @param typeargtypes The types of the invocation's type arguments. 2431 */ 2432 Symbol resolveMethod(DiagnosticPosition pos, 2433 Env<AttrContext> env, 2434 Name name, 2435 List<Type> argtypes, 2436 List<Type> typeargtypes) { 2437 return lookupMethod(env, pos, env.enclClass.sym, resolveMethodCheck, 2438 new BasicLookupHelper(name, env.enclClass.sym.type, argtypes, typeargtypes) { 2439 @Override 2440 Symbol doLookup(Env<AttrContext> env, MethodResolutionPhase phase) { 2441 return findFun(env, name, argtypes, typeargtypes, 2442 phase.isBoxingRequired(), 2443 phase.isVarargsRequired()); 2444 }}); 2445 } 2446 2447 /** Resolve a qualified method identifier 2448 * @param pos The position to use for error reporting. 2449 * @param env The environment current at the method invocation. 2450 * @param site The type of the qualifying expression, in which 2451 * identifier is searched. 2452 * @param name The identifier's name. 2453 * @param argtypes The types of the invocation's value arguments. 2454 * @param typeargtypes The types of the invocation's type arguments. 2455 */ 2456 Symbol resolveQualifiedMethod(DiagnosticPosition pos, Env<AttrContext> env, 2457 Type site, Name name, List<Type> argtypes, 2458 List<Type> typeargtypes) { 2459 return resolveQualifiedMethod(pos, env, site.tsym, site, name, argtypes, typeargtypes); 2460 } 2461 Symbol resolveQualifiedMethod(DiagnosticPosition pos, Env<AttrContext> env, 2462 Symbol location, Type site, Name name, List<Type> argtypes, 2463 List<Type> typeargtypes) { 2464 return resolveQualifiedMethod(new MethodResolutionContext(), pos, env, location, site, name, argtypes, typeargtypes); 2465 } 2466 private Symbol resolveQualifiedMethod(MethodResolutionContext resolveContext, 2467 DiagnosticPosition pos, Env<AttrContext> env, 2468 Symbol location, Type site, Name name, List<Type> argtypes, 2469 List<Type> typeargtypes) { 2470 return lookupMethod(env, pos, location, resolveContext, new BasicLookupHelper(name, site, argtypes, typeargtypes) { 2471 @Override 2472 Symbol doLookup(Env<AttrContext> env, MethodResolutionPhase phase) { 2473 return findMethod(env, site, name, argtypes, typeargtypes, 2474 phase.isBoxingRequired(), 2475 phase.isVarargsRequired()); 2476 } 2477 @Override 2478 Symbol access(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, Symbol sym) { 2479 if (sym.kind.isResolutionError()) { 2480 sym = super.access(env, pos, location, sym); 2481 } else if (allowMethodHandles) { 2482 MethodSymbol msym = (MethodSymbol)sym; 2483 if ((msym.flags() & SIGNATURE_POLYMORPHIC) != 0) { 2484 return findPolymorphicSignatureInstance(env, sym, argtypes); 2485 } 2486 } 2487 return sym; 2488 } 2489 }); 2490 } 2491 2492 /** Find or create an implicit method of exactly the given type (after erasure). 2493 * Searches in a side table, not the main scope of the site. 2494 * This emulates the lookup process required by JSR 292 in JVM. 2495 * @param env Attribution environment 2496 * @param spMethod signature polymorphic method - i.e. MH.invokeExact 2497 * @param argtypes The required argument types 2498 */ 2499 Symbol findPolymorphicSignatureInstance(Env<AttrContext> env, 2500 final Symbol spMethod, 2501 List<Type> argtypes) { 2502 Type mtype = infer.instantiatePolymorphicSignatureInstance(env, 2503 (MethodSymbol)spMethod, currentResolutionContext, argtypes); 2504 for (Symbol sym : polymorphicSignatureScope.getSymbolsByName(spMethod.name)) { 2505 // Check that there is already a method symbol for the method 2506 // type and owner 2507 if (types.isSameType(mtype, sym.type) && 2508 spMethod.owner == sym.owner) { 2509 return sym; 2510 } 2511 } 2512 2513 // Create the desired method 2514 // Retain static modifier is to support invocations to 2515 // MethodHandle.linkTo* methods 2516 long flags = ABSTRACT | HYPOTHETICAL | 2517 spMethod.flags() & (Flags.AccessFlags | Flags.STATIC); 2518 Symbol msym = new MethodSymbol(flags, spMethod.name, mtype, spMethod.owner) { 2519 @Override 2520 public Symbol baseSymbol() { 2521 return spMethod; 2522 } 2523 }; 2524 if (!mtype.isErroneous()) { // Cache only if kosher. 2525 polymorphicSignatureScope.enter(msym); 2526 } 2527 return msym; 2528 } 2529 2530 /** Resolve a qualified method identifier, throw a fatal error if not 2531 * found. 2532 * @param pos The position to use for error reporting. 2533 * @param env The environment current at the method invocation. 2534 * @param site The type of the qualifying expression, in which 2535 * identifier is searched. 2536 * @param name The identifier's name. 2537 * @param argtypes The types of the invocation's value arguments. 2538 * @param typeargtypes The types of the invocation's type arguments. 2539 */ 2540 public MethodSymbol resolveInternalMethod(DiagnosticPosition pos, Env<AttrContext> env, 2541 Type site, Name name, 2542 List<Type> argtypes, 2543 List<Type> typeargtypes) { 2544 MethodResolutionContext resolveContext = new MethodResolutionContext(); 2545 resolveContext.internalResolution = true; 2546 Symbol sym = resolveQualifiedMethod(resolveContext, pos, env, site.tsym, 2547 site, name, argtypes, typeargtypes); 2548 if (sym.kind == MTH) return (MethodSymbol)sym; 2549 else throw new FatalError( 2550 diags.fragment("fatal.err.cant.locate.meth", 2551 name)); 2552 } 2553 2554 /** Resolve constructor. 2555 * @param pos The position to use for error reporting. 2556 * @param env The environment current at the constructor invocation. 2557 * @param site The type of class for which a constructor is searched. 2558 * @param argtypes The types of the constructor invocation's value 2559 * arguments. 2560 * @param typeargtypes The types of the constructor invocation's type 2561 * arguments. 2562 */ 2563 Symbol resolveConstructor(DiagnosticPosition pos, 2564 Env<AttrContext> env, 2565 Type site, 2566 List<Type> argtypes, 2567 List<Type> typeargtypes) { 2568 return resolveConstructor(new MethodResolutionContext(), pos, env, site, argtypes, typeargtypes); 2569 } 2570 2571 private Symbol resolveConstructor(MethodResolutionContext resolveContext, 2572 final DiagnosticPosition pos, 2573 Env<AttrContext> env, 2574 Type site, 2575 List<Type> argtypes, 2576 List<Type> typeargtypes) { 2577 return lookupMethod(env, pos, site.tsym, resolveContext, new BasicLookupHelper(names.init, site, argtypes, typeargtypes) { 2578 @Override 2579 Symbol doLookup(Env<AttrContext> env, MethodResolutionPhase phase) { 2580 return findConstructor(pos, env, site, argtypes, typeargtypes, 2581 phase.isBoxingRequired(), 2582 phase.isVarargsRequired()); 2583 } 2584 }); 2585 } 2586 2587 /** Resolve a constructor, throw a fatal error if not found. 2588 * @param pos The position to use for error reporting. 2589 * @param env The environment current at the method invocation. 2590 * @param site The type to be constructed. 2591 * @param argtypes The types of the invocation's value arguments. 2592 * @param typeargtypes The types of the invocation's type arguments. 2593 */ 2594 public MethodSymbol resolveInternalConstructor(DiagnosticPosition pos, Env<AttrContext> env, 2595 Type site, 2596 List<Type> argtypes, 2597 List<Type> typeargtypes) { 2598 MethodResolutionContext resolveContext = new MethodResolutionContext(); 2599 resolveContext.internalResolution = true; 2600 Symbol sym = resolveConstructor(resolveContext, pos, env, site, argtypes, typeargtypes); 2601 if (sym.kind == MTH) return (MethodSymbol)sym; 2602 else throw new FatalError( 2603 diags.fragment("fatal.err.cant.locate.ctor", site)); 2604 } 2605 2606 Symbol findConstructor(DiagnosticPosition pos, Env<AttrContext> env, 2607 Type site, List<Type> argtypes, 2608 List<Type> typeargtypes, 2609 boolean allowBoxing, 2610 boolean useVarargs) { 2611 Symbol sym = findMethod(env, site, 2612 names.init, argtypes, 2613 typeargtypes, allowBoxing, 2614 useVarargs); 2615 chk.checkDeprecated(pos, env.info.scope.owner, sym); 2616 return sym; 2617 } 2618 2619 /** Resolve constructor using diamond inference. 2620 * @param pos The position to use for error reporting. 2621 * @param env The environment current at the constructor invocation. 2622 * @param site The type of class for which a constructor is searched. 2623 * The scope of this class has been touched in attribution. 2624 * @param argtypes The types of the constructor invocation's value 2625 * arguments. 2626 * @param typeargtypes The types of the constructor invocation's type 2627 * arguments. 2628 */ 2629 Symbol resolveDiamond(DiagnosticPosition pos, 2630 Env<AttrContext> env, 2631 Type site, 2632 List<Type> argtypes, 2633 List<Type> typeargtypes) { 2634 return lookupMethod(env, pos, site.tsym, resolveMethodCheck, 2635 new BasicLookupHelper(names.init, site, argtypes, typeargtypes) { 2636 @Override 2637 Symbol doLookup(Env<AttrContext> env, MethodResolutionPhase phase) { 2638 return findDiamond(env, site, argtypes, typeargtypes, 2639 phase.isBoxingRequired(), 2640 phase.isVarargsRequired()); 2641 } 2642 @Override 2643 Symbol access(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, Symbol sym) { 2644 if (sym.kind.isResolutionError()) { 2645 if (sym.kind != WRONG_MTH && 2646 sym.kind != WRONG_MTHS) { 2647 sym = super.access(env, pos, location, sym); 2648 } else { 2649 final JCDiagnostic details = sym.kind == WRONG_MTH ? 2650 ((InapplicableSymbolError)sym.baseSymbol()).errCandidate().snd : 2651 null; 2652 sym = new DiamondError(sym, currentResolutionContext); 2653 sym = accessMethod(sym, pos, site, names.init, true, argtypes, typeargtypes); 2654 env.info.pendingResolutionPhase = currentResolutionContext.step; 2655 } 2656 } 2657 return sym; 2658 }}); 2659 } 2660 2661 /** This method scans all the constructor symbol in a given class scope - 2662 * assuming that the original scope contains a constructor of the kind: 2663 * {@code Foo(X x, Y y)}, where X,Y are class type-variables declared in Foo, 2664 * a method check is executed against the modified constructor type: 2665 * {@code <X,Y>Foo<X,Y>(X x, Y y)}. This is crucial in order to enable diamond 2666 * inference. The inferred return type of the synthetic constructor IS 2667 * the inferred type for the diamond operator. 2668 */ 2669 private Symbol findDiamond(Env<AttrContext> env, 2670 Type site, 2671 List<Type> argtypes, 2672 List<Type> typeargtypes, 2673 boolean allowBoxing, 2674 boolean useVarargs) { 2675 Symbol bestSoFar = methodNotFound; 2676 TypeSymbol tsym = site.tsym.isInterface() ? syms.objectType.tsym : site.tsym; 2677 for (final Symbol sym : tsym.members().getSymbolsByName(names.init)) { 2678 //- System.out.println(" e " + e.sym); 2679 if (sym.kind == MTH && 2680 (sym.flags_field & SYNTHETIC) == 0) { 2681 List<Type> oldParams = sym.type.hasTag(FORALL) ? 2682 ((ForAll)sym.type).tvars : 2683 List.<Type>nil(); 2684 Type constrType = new ForAll(site.tsym.type.getTypeArguments().appendList(oldParams), 2685 types.createMethodTypeWithReturn(sym.type.asMethodType(), site)); 2686 MethodSymbol newConstr = new MethodSymbol(sym.flags(), names.init, constrType, site.tsym) { 2687 @Override 2688 public Symbol baseSymbol() { 2689 return sym; 2690 } 2691 }; 2692 bestSoFar = selectBest(env, site, argtypes, typeargtypes, 2693 newConstr, 2694 bestSoFar, 2695 allowBoxing, 2696 useVarargs); 2697 } 2698 } 2699 return bestSoFar; 2700 } 2701 2702 Symbol getMemberReference(DiagnosticPosition pos, 2703 Env<AttrContext> env, 2704 JCMemberReference referenceTree, 2705 Type site, 2706 Name name) { 2707 2708 site = types.capture(site); 2709 2710 ReferenceLookupHelper lookupHelper = makeReferenceLookupHelper( 2711 referenceTree, site, name, List.<Type>nil(), null, VARARITY); 2712 2713 Env<AttrContext> newEnv = env.dup(env.tree, env.info.dup()); 2714 Symbol sym = lookupMethod(newEnv, env.tree.pos(), site.tsym, 2715 nilMethodCheck, lookupHelper); 2716 2717 env.info.pendingResolutionPhase = newEnv.info.pendingResolutionPhase; 2718 2719 return sym; 2720 } 2721 2722 ReferenceLookupHelper makeReferenceLookupHelper(JCMemberReference referenceTree, 2723 Type site, 2724 Name name, 2725 List<Type> argtypes, 2726 List<Type> typeargtypes, 2727 MethodResolutionPhase maxPhase) { 2728 if (!name.equals(names.init)) { 2729 //method reference 2730 return new MethodReferenceLookupHelper(referenceTree, name, site, argtypes, typeargtypes, maxPhase); 2731 } else if (site.hasTag(ARRAY)) { 2732 //array constructor reference 2733 return new ArrayConstructorReferenceLookupHelper(referenceTree, site, argtypes, typeargtypes, maxPhase); 2734 } else { 2735 //class constructor reference 2736 return new ConstructorReferenceLookupHelper(referenceTree, site, argtypes, typeargtypes, maxPhase); 2737 } 2738 } 2739 2740 /** 2741 * Resolution of member references is typically done as a single 2742 * overload resolution step, where the argument types A are inferred from 2743 * the target functional descriptor. 2744 * 2745 * If the member reference is a method reference with a type qualifier, 2746 * a two-step lookup process is performed. The first step uses the 2747 * expected argument list A, while the second step discards the first 2748 * type from A (which is treated as a receiver type). 2749 * 2750 * There are two cases in which inference is performed: (i) if the member 2751 * reference is a constructor reference and the qualifier type is raw - in 2752 * which case diamond inference is used to infer a parameterization for the 2753 * type qualifier; (ii) if the member reference is an unbound reference 2754 * where the type qualifier is raw - in that case, during the unbound lookup 2755 * the receiver argument type is used to infer an instantiation for the raw 2756 * qualifier type. 2757 * 2758 * When a multi-step resolution process is exploited, the process of picking 2759 * the resulting symbol is delegated to an helper class {@link com.sun.tools.javac.comp.Resolve.ReferenceChooser}. 2760 * 2761 * This routine returns a pair (T,S), where S is the member reference symbol, 2762 * and T is the type of the class in which S is defined. This is necessary as 2763 * the type T might be dynamically inferred (i.e. if constructor reference 2764 * has a raw qualifier). 2765 */ 2766 Pair<Symbol, ReferenceLookupHelper> resolveMemberReference(Env<AttrContext> env, 2767 JCMemberReference referenceTree, 2768 Type site, 2769 Name name, 2770 List<Type> argtypes, 2771 List<Type> typeargtypes, 2772 MethodCheck methodCheck, 2773 InferenceContext inferenceContext, 2774 ReferenceChooser referenceChooser) { 2775 2776 //step 1 - bound lookup 2777 ReferenceLookupHelper boundLookupHelper = makeReferenceLookupHelper( 2778 referenceTree, site, name, argtypes, typeargtypes, VARARITY); 2779 Env<AttrContext> boundEnv = env.dup(env.tree, env.info.dup()); 2780 MethodResolutionContext boundSearchResolveContext = new MethodResolutionContext(); 2781 boundSearchResolveContext.methodCheck = methodCheck; 2782 Symbol boundSym = lookupMethod(boundEnv, env.tree.pos(), 2783 site.tsym, boundSearchResolveContext, boundLookupHelper); 2784 ReferenceLookupResult boundRes = new ReferenceLookupResult(boundSym, boundSearchResolveContext); 2785 2786 //step 2 - unbound lookup 2787 Symbol unboundSym = methodNotFound; 2788 Env<AttrContext> unboundEnv = env.dup(env.tree, env.info.dup()); 2789 ReferenceLookupHelper unboundLookupHelper = boundLookupHelper.unboundLookup(inferenceContext); 2790 ReferenceLookupResult unboundRes = referenceNotFound; 2791 if (unboundLookupHelper != null) { 2792 MethodResolutionContext unboundSearchResolveContext = 2793 new MethodResolutionContext(); 2794 unboundSearchResolveContext.methodCheck = methodCheck; 2795 unboundSym = lookupMethod(unboundEnv, env.tree.pos(), 2796 site.tsym, unboundSearchResolveContext, unboundLookupHelper); 2797 unboundRes = new ReferenceLookupResult(unboundSym, unboundSearchResolveContext); 2798 } 2799 2800 //merge results 2801 Pair<Symbol, ReferenceLookupHelper> res; 2802 Symbol bestSym = referenceChooser.result(boundRes, unboundRes); 2803 res = new Pair<>(bestSym, 2804 bestSym == unboundSym ? unboundLookupHelper : boundLookupHelper); 2805 env.info.pendingResolutionPhase = bestSym == unboundSym ? 2806 unboundEnv.info.pendingResolutionPhase : 2807 boundEnv.info.pendingResolutionPhase; 2808 2809 return res; 2810 } 2811 2812 /** 2813 * This class is used to represent a method reference lookup result. It keeps track of two 2814 * things: (i) the symbol found during a method reference lookup and (ii) the static kind 2815 * of the lookup (see {@link com.sun.tools.javac.comp.Resolve.ReferenceLookupResult.StaticKind}). 2816 */ 2817 static class ReferenceLookupResult { 2818 2819 /** 2820 * Static kind associated with a method reference lookup. Erroneous lookups end up with 2821 * the UNDEFINED kind; successful lookups will end up with either STATIC, NON_STATIC, 2822 * depending on whether all applicable candidates are static or non-static methods, 2823 * respectively. If a successful lookup has both static and non-static applicable methods, 2824 * its kind is set to BOTH. 2825 */ 2826 enum StaticKind { 2827 STATIC, 2828 NON_STATIC, 2829 BOTH, 2830 UNDEFINED; 2831 2832 /** 2833 * Retrieve the static kind associated with a given (method) symbol. 2834 */ 2835 static StaticKind from(Symbol s) { 2836 return s.isStatic() ? 2837 STATIC : NON_STATIC; 2838 } 2839 2840 /** 2841 * Merge two static kinds together. 2842 */ 2843 static StaticKind reduce(StaticKind sk1, StaticKind sk2) { 2844 if (sk1 == UNDEFINED) { 2845 return sk2; 2846 } else if (sk2 == UNDEFINED) { 2847 return sk1; 2848 } else { 2849 return sk1 == sk2 ? sk1 : BOTH; 2850 } 2851 } 2852 } 2853 2854 /** The static kind. */ 2855 StaticKind staticKind; 2856 2857 /** The lookup result. */ 2858 Symbol sym; 2859 2860 ReferenceLookupResult(Symbol sym, MethodResolutionContext resolutionContext) { 2861 this.staticKind = staticKind(sym, resolutionContext); 2862 this.sym = sym; 2863 } 2864 2865 private StaticKind staticKind(Symbol sym, MethodResolutionContext resolutionContext) { 2866 switch (sym.kind) { 2867 case MTH: 2868 case AMBIGUOUS: 2869 return resolutionContext.candidates.stream() 2870 .filter(c -> c.isApplicable() && c.step == resolutionContext.step) 2871 .map(c -> StaticKind.from(c.sym)) 2872 .reduce(StaticKind::reduce) 2873 .orElse(StaticKind.UNDEFINED); 2874 default: 2875 return StaticKind.UNDEFINED; 2876 } 2877 } 2878 2879 /** 2880 * Does this result corresponds to a successful lookup (i.e. one where a method has been found?) 2881 */ 2882 boolean isSuccess() { 2883 return staticKind != StaticKind.UNDEFINED; 2884 } 2885 2886 /** 2887 * Does this result have given static kind? 2888 */ 2889 boolean hasKind(StaticKind sk) { 2890 return this.staticKind == sk; 2891 } 2892 2893 /** 2894 * Error recovery helper: can this lookup result be ignored (for the purpose of returning 2895 * some 'better' result) ? 2896 */ 2897 boolean canIgnore() { 2898 switch (sym.kind) { 2899 case ABSENT_MTH: 2900 return true; 2901 case WRONG_MTH: 2902 InapplicableSymbolError errSym = 2903 (InapplicableSymbolError)sym.baseSymbol(); 2904 return new Template(MethodCheckDiag.ARITY_MISMATCH.regex()) 2905 .matches(errSym.errCandidate().snd); 2906 case WRONG_MTHS: 2907 InapplicableSymbolsError errSyms = 2908 (InapplicableSymbolsError)sym.baseSymbol(); 2909 return errSyms.filterCandidates(errSyms.mapCandidates()).isEmpty(); 2910 default: 2911 return false; 2912 } 2913 } 2914 } 2915 2916 /** 2917 * This abstract class embodies the logic that converts one (bound lookup) or two (unbound lookup) 2918 * {@code ReferenceLookupResult} objects into a (@code Symbol), which is then regarded as the 2919 * result of method reference resolution. 2920 */ 2921 abstract class ReferenceChooser { 2922 /** 2923 * Generate a result from a pair of lookup result objects. This method delegates to the 2924 * appropriate result generation routine. 2925 */ 2926 Symbol result(ReferenceLookupResult boundRes, ReferenceLookupResult unboundRes) { 2927 return unboundRes != referenceNotFound ? 2928 unboundResult(boundRes, unboundRes) : 2929 boundResult(boundRes); 2930 } 2931 2932 /** 2933 * Generate a symbol from a given bound lookup result. 2934 */ 2935 abstract Symbol boundResult(ReferenceLookupResult boundRes); 2936 2937 /** 2938 * Generate a symbol from a pair of bound/unbound lookup results. 2939 */ 2940 abstract Symbol unboundResult(ReferenceLookupResult boundRes, ReferenceLookupResult unboundRes); 2941 } 2942 2943 /** 2944 * This chooser implements the selection strategy used during a full lookup; this logic 2945 * is described in JLS SE 8 (15.3.2). 2946 */ 2947 ReferenceChooser basicReferenceChooser = new ReferenceChooser() { 2948 2949 @Override 2950 Symbol boundResult(ReferenceLookupResult boundRes) { 2951 return !boundRes.isSuccess() || boundRes.hasKind(StaticKind.NON_STATIC) ? 2952 boundRes.sym : //the search produces a non-static method 2953 new BadMethodReferenceError(boundRes.sym, false); 2954 } 2955 2956 @Override 2957 Symbol unboundResult(ReferenceLookupResult boundRes, ReferenceLookupResult unboundRes) { 2958 if (boundRes.hasKind(StaticKind.STATIC) && 2959 (!unboundRes.isSuccess() || unboundRes.hasKind(StaticKind.STATIC))) { 2960 //the first search produces a static method and no non-static method is applicable 2961 //during the second search 2962 return boundRes.sym; 2963 } else if (unboundRes.hasKind(StaticKind.NON_STATIC) && 2964 (!boundRes.isSuccess() || boundRes.hasKind(StaticKind.NON_STATIC))) { 2965 //the second search produces a non-static method and no static method is applicable 2966 //during the first search 2967 return unboundRes.sym; 2968 } else if (boundRes.isSuccess() && unboundRes.isSuccess()) { 2969 //both searches produce some result; ambiguity (error recovery) 2970 return ambiguityError(boundRes.sym, unboundRes.sym); 2971 } else if (boundRes.isSuccess() || unboundRes.isSuccess()) { 2972 //Both searches failed to produce a result with correct staticness (i.e. first search 2973 //produces an non-static method). Alternatively, a given search produced a result 2974 //with the right staticness, but the other search has applicable methods with wrong 2975 //staticness (error recovery) 2976 return new BadMethodReferenceError(boundRes.isSuccess() ? boundRes.sym : unboundRes.sym, true); 2977 } else { 2978 //both searches fail to produce a result - pick 'better' error using heuristics (error recovery) 2979 return (boundRes.canIgnore() && !unboundRes.canIgnore()) ? 2980 unboundRes.sym : boundRes.sym; 2981 } 2982 } 2983 }; 2984 2985 /** 2986 * This chooser implements the selection strategy used during an arity-based lookup; this logic 2987 * is described in JLS SE 8 (15.12.2.1). 2988 */ 2989 ReferenceChooser structuralReferenceChooser = new ReferenceChooser() { 2990 2991 @Override 2992 Symbol boundResult(ReferenceLookupResult boundRes) { 2993 return (!boundRes.isSuccess() || !boundRes.hasKind(StaticKind.STATIC)) ? 2994 boundRes.sym : //the search has at least one applicable non-static method 2995 new BadMethodReferenceError(boundRes.sym, false); 2996 } 2997 2998 @Override 2999 Symbol unboundResult(ReferenceLookupResult boundRes, ReferenceLookupResult unboundRes) { 3000 if (boundRes.isSuccess() && !boundRes.hasKind(StaticKind.NON_STATIC)) { 3001 //the first serach has at least one applicable static method 3002 return boundRes.sym; 3003 } else if (unboundRes.isSuccess() && !unboundRes.hasKind(StaticKind.STATIC)) { 3004 //the second search has at least one applicable non-static method 3005 return unboundRes.sym; 3006 } else if (boundRes.isSuccess() || unboundRes.isSuccess()) { 3007 //either the first search produces a non-static method, or second search produces 3008 //a non-static method (error recovery) 3009 return new BadMethodReferenceError(boundRes.isSuccess() ? boundRes.sym : unboundRes.sym, true); 3010 } else { 3011 //both searches fail to produce a result - pick 'better' error using heuristics (error recovery) 3012 return (boundRes.canIgnore() && !unboundRes.canIgnore()) ? 3013 unboundRes.sym : boundRes.sym; 3014 } 3015 } 3016 }; 3017 3018 /** 3019 * Helper for defining custom method-like lookup logic; a lookup helper 3020 * provides hooks for (i) the actual lookup logic and (ii) accessing the 3021 * lookup result (this step might result in compiler diagnostics to be generated) 3022 */ 3023 abstract class LookupHelper { 3024 3025 /** name of the symbol to lookup */ 3026 Name name; 3027 3028 /** location in which the lookup takes place */ 3029 Type site; 3030 3031 /** actual types used during the lookup */ 3032 List<Type> argtypes; 3033 3034 /** type arguments used during the lookup */ 3035 List<Type> typeargtypes; 3036 3037 /** Max overload resolution phase handled by this helper */ 3038 MethodResolutionPhase maxPhase; 3039 3040 LookupHelper(Name name, Type site, List<Type> argtypes, List<Type> typeargtypes, MethodResolutionPhase maxPhase) { 3041 this.name = name; 3042 this.site = site; 3043 this.argtypes = argtypes; 3044 this.typeargtypes = typeargtypes; 3045 this.maxPhase = maxPhase; 3046 } 3047 3048 /** 3049 * Should lookup stop at given phase with given result 3050 */ 3051 final boolean shouldStop(Symbol sym, MethodResolutionPhase phase) { 3052 return phase.ordinal() > maxPhase.ordinal() || 3053 !sym.kind.isResolutionError() || sym.kind == AMBIGUOUS; 3054 } 3055 3056 /** 3057 * Search for a symbol under a given overload resolution phase - this method 3058 * is usually called several times, once per each overload resolution phase 3059 */ 3060 abstract Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase); 3061 3062 /** 3063 * Dump overload resolution info 3064 */ 3065 void debug(DiagnosticPosition pos, Symbol sym) { 3066 //do nothing 3067 } 3068 3069 /** 3070 * Validate the result of the lookup 3071 */ 3072 abstract Symbol access(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, Symbol sym); 3073 } 3074 3075 abstract class BasicLookupHelper extends LookupHelper { 3076 3077 BasicLookupHelper(Name name, Type site, List<Type> argtypes, List<Type> typeargtypes) { 3078 this(name, site, argtypes, typeargtypes, MethodResolutionPhase.VARARITY); 3079 } 3080 3081 BasicLookupHelper(Name name, Type site, List<Type> argtypes, List<Type> typeargtypes, MethodResolutionPhase maxPhase) { 3082 super(name, site, argtypes, typeargtypes, maxPhase); 3083 } 3084 3085 @Override 3086 final Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) { 3087 Symbol sym = doLookup(env, phase); 3088 if (sym.kind == AMBIGUOUS) { 3089 AmbiguityError a_err = (AmbiguityError)sym.baseSymbol(); 3090 sym = a_err.mergeAbstracts(site); 3091 } 3092 return sym; 3093 } 3094 3095 abstract Symbol doLookup(Env<AttrContext> env, MethodResolutionPhase phase); 3096 3097 @Override 3098 Symbol access(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, Symbol sym) { 3099 if (sym.kind.isResolutionError()) { 3100 //if nothing is found return the 'first' error 3101 sym = accessMethod(sym, pos, location, site, name, true, argtypes, typeargtypes); 3102 } 3103 return sym; 3104 } 3105 3106 @Override 3107 void debug(DiagnosticPosition pos, Symbol sym) { 3108 reportVerboseResolutionDiagnostic(pos, name, site, argtypes, typeargtypes, sym); 3109 } 3110 } 3111 3112 /** 3113 * Helper class for member reference lookup. A reference lookup helper 3114 * defines the basic logic for member reference lookup; a method gives 3115 * access to an 'unbound' helper used to perform an unbound member 3116 * reference lookup. 3117 */ 3118 abstract class ReferenceLookupHelper extends LookupHelper { 3119 3120 /** The member reference tree */ 3121 JCMemberReference referenceTree; 3122 3123 ReferenceLookupHelper(JCMemberReference referenceTree, Name name, Type site, 3124 List<Type> argtypes, List<Type> typeargtypes, MethodResolutionPhase maxPhase) { 3125 super(name, site, argtypes, typeargtypes, maxPhase); 3126 this.referenceTree = referenceTree; 3127 } 3128 3129 /** 3130 * Returns an unbound version of this lookup helper. By default, this 3131 * method returns an dummy lookup helper. 3132 */ 3133 ReferenceLookupHelper unboundLookup(InferenceContext inferenceContext) { 3134 return null; 3135 } 3136 3137 /** 3138 * Get the kind of the member reference 3139 */ 3140 abstract JCMemberReference.ReferenceKind referenceKind(Symbol sym); 3141 3142 Symbol access(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, Symbol sym) { 3143 if (sym.kind == AMBIGUOUS) { 3144 AmbiguityError a_err = (AmbiguityError)sym.baseSymbol(); 3145 sym = a_err.mergeAbstracts(site); 3146 } 3147 //skip error reporting 3148 return sym; 3149 } 3150 } 3151 3152 /** 3153 * Helper class for method reference lookup. The lookup logic is based 3154 * upon Resolve.findMethod; in certain cases, this helper class has a 3155 * corresponding unbound helper class (see UnboundMethodReferenceLookupHelper). 3156 * In such cases, non-static lookup results are thrown away. 3157 */ 3158 class MethodReferenceLookupHelper extends ReferenceLookupHelper { 3159 3160 /** The original method reference lookup site. */ 3161 Type originalSite; 3162 3163 MethodReferenceLookupHelper(JCMemberReference referenceTree, Name name, Type site, 3164 List<Type> argtypes, List<Type> typeargtypes, MethodResolutionPhase maxPhase) { 3165 super(referenceTree, name, types.skipTypeVars(site, true), argtypes, typeargtypes, maxPhase); 3166 this.originalSite = site; 3167 } 3168 3169 @Override 3170 final Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) { 3171 return findMethod(env, site, name, argtypes, typeargtypes, 3172 phase.isBoxingRequired(), phase.isVarargsRequired()); 3173 } 3174 3175 @Override 3176 ReferenceLookupHelper unboundLookup(InferenceContext inferenceContext) { 3177 if (TreeInfo.isStaticSelector(referenceTree.expr, names)) { 3178 if (argtypes.nonEmpty() && 3179 (argtypes.head.hasTag(NONE) || 3180 types.isSubtypeUnchecked(inferenceContext.asUndetVar(argtypes.head), site))) { 3181 return new UnboundMethodReferenceLookupHelper(referenceTree, name, 3182 originalSite, argtypes, typeargtypes, maxPhase); 3183 } else { 3184 return new ReferenceLookupHelper(referenceTree, name, site, argtypes, typeargtypes, maxPhase) { 3185 @Override 3186 ReferenceLookupHelper unboundLookup(InferenceContext inferenceContext) { 3187 return this; 3188 } 3189 3190 @Override 3191 Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) { 3192 return methodNotFound; 3193 } 3194 3195 @Override 3196 ReferenceKind referenceKind(Symbol sym) { 3197 Assert.error(); 3198 return null; 3199 } 3200 }; 3201 } 3202 } else { 3203 return super.unboundLookup(inferenceContext); 3204 } 3205 } 3206 3207 @Override 3208 ReferenceKind referenceKind(Symbol sym) { 3209 if (sym.isStatic()) { 3210 return ReferenceKind.STATIC; 3211 } else { 3212 Name selName = TreeInfo.name(referenceTree.getQualifierExpression()); 3213 return selName != null && selName == names._super ? 3214 ReferenceKind.SUPER : 3215 ReferenceKind.BOUND; 3216 } 3217 } 3218 } 3219 3220 /** 3221 * Helper class for unbound method reference lookup. Essentially the same 3222 * as the basic method reference lookup helper; main difference is that static 3223 * lookup results are thrown away. If qualifier type is raw, an attempt to 3224 * infer a parameterized type is made using the first actual argument (that 3225 * would otherwise be ignored during the lookup). 3226 */ 3227 class UnboundMethodReferenceLookupHelper extends MethodReferenceLookupHelper { 3228 3229 UnboundMethodReferenceLookupHelper(JCMemberReference referenceTree, Name name, Type site, 3230 List<Type> argtypes, List<Type> typeargtypes, MethodResolutionPhase maxPhase) { 3231 super(referenceTree, name, site, argtypes.tail, typeargtypes, maxPhase); 3232 if (site.isRaw() && !argtypes.head.hasTag(NONE)) { 3233 Type asSuperSite = types.asSuper(argtypes.head, site.tsym); 3234 this.site = types.skipTypeVars(asSuperSite, true); 3235 } 3236 } 3237 3238 @Override 3239 ReferenceLookupHelper unboundLookup(InferenceContext inferenceContext) { 3240 return this; 3241 } 3242 3243 @Override 3244 ReferenceKind referenceKind(Symbol sym) { 3245 return ReferenceKind.UNBOUND; 3246 } 3247 } 3248 3249 /** 3250 * Helper class for array constructor lookup; an array constructor lookup 3251 * is simulated by looking up a method that returns the array type specified 3252 * as qualifier, and that accepts a single int parameter (size of the array). 3253 */ 3254 class ArrayConstructorReferenceLookupHelper extends ReferenceLookupHelper { 3255 3256 ArrayConstructorReferenceLookupHelper(JCMemberReference referenceTree, Type site, List<Type> argtypes, 3257 List<Type> typeargtypes, MethodResolutionPhase maxPhase) { 3258 super(referenceTree, names.init, site, argtypes, typeargtypes, maxPhase); 3259 } 3260 3261 @Override 3262 protected Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) { 3263 WriteableScope sc = WriteableScope.create(syms.arrayClass); 3264 MethodSymbol arrayConstr = new MethodSymbol(PUBLIC, name, null, site.tsym); 3265 arrayConstr.type = new MethodType(List.<Type>of(syms.intType), site, List.<Type>nil(), syms.methodClass); 3266 sc.enter(arrayConstr); 3267 return findMethodInScope(env, site, name, argtypes, typeargtypes, sc, methodNotFound, phase.isBoxingRequired(), phase.isVarargsRequired(), false); 3268 } 3269 3270 @Override 3271 ReferenceKind referenceKind(Symbol sym) { 3272 return ReferenceKind.ARRAY_CTOR; 3273 } 3274 } 3275 3276 /** 3277 * Helper class for constructor reference lookup. The lookup logic is based 3278 * upon either Resolve.findMethod or Resolve.findDiamond - depending on 3279 * whether the constructor reference needs diamond inference (this is the case 3280 * if the qualifier type is raw). A special erroneous symbol is returned 3281 * if the lookup returns the constructor of an inner class and there's no 3282 * enclosing instance in scope. 3283 */ 3284 class ConstructorReferenceLookupHelper extends ReferenceLookupHelper { 3285 3286 boolean needsInference; 3287 3288 ConstructorReferenceLookupHelper(JCMemberReference referenceTree, Type site, List<Type> argtypes, 3289 List<Type> typeargtypes, MethodResolutionPhase maxPhase) { 3290 super(referenceTree, names.init, site, argtypes, typeargtypes, maxPhase); 3291 if (site.isRaw()) { 3292 this.site = new ClassType(site.getEnclosingType(), site.tsym.type.getTypeArguments(), site.tsym, site.getMetadata()); 3293 needsInference = true; 3294 } 3295 } 3296 3297 @Override 3298 protected Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) { 3299 Symbol sym = needsInference ? 3300 findDiamond(env, site, argtypes, typeargtypes, phase.isBoxingRequired(), phase.isVarargsRequired()) : 3301 findMethod(env, site, name, argtypes, typeargtypes, 3302 phase.isBoxingRequired(), phase.isVarargsRequired()); 3303 return enclosingInstanceMissing(env, site) ? new BadConstructorReferenceError(sym) : sym; 3304 } 3305 3306 @Override 3307 ReferenceKind referenceKind(Symbol sym) { 3308 return site.getEnclosingType().hasTag(NONE) ? 3309 ReferenceKind.TOPLEVEL : ReferenceKind.IMPLICIT_INNER; 3310 } 3311 } 3312 3313 /** 3314 * Main overload resolution routine. On each overload resolution step, a 3315 * lookup helper class is used to perform the method/constructor lookup; 3316 * at the end of the lookup, the helper is used to validate the results 3317 * (this last step might trigger overload resolution diagnostics). 3318 */ 3319 Symbol lookupMethod(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, MethodCheck methodCheck, LookupHelper lookupHelper) { 3320 MethodResolutionContext resolveContext = new MethodResolutionContext(); 3321 resolveContext.methodCheck = methodCheck; 3322 return lookupMethod(env, pos, location, resolveContext, lookupHelper); 3323 } 3324 3325 Symbol lookupMethod(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, 3326 MethodResolutionContext resolveContext, LookupHelper lookupHelper) { 3327 MethodResolutionContext prevResolutionContext = currentResolutionContext; 3328 try { 3329 Symbol bestSoFar = methodNotFound; 3330 currentResolutionContext = resolveContext; 3331 for (MethodResolutionPhase phase : methodResolutionSteps) { 3332 if (lookupHelper.shouldStop(bestSoFar, phase)) 3333 break; 3334 MethodResolutionPhase prevPhase = currentResolutionContext.step; 3335 Symbol prevBest = bestSoFar; 3336 currentResolutionContext.step = phase; 3337 Symbol sym = lookupHelper.lookup(env, phase); 3338 lookupHelper.debug(pos, sym); 3339 bestSoFar = phase.mergeResults(bestSoFar, sym); 3340 env.info.pendingResolutionPhase = (prevBest == bestSoFar) ? prevPhase : phase; 3341 } 3342 return lookupHelper.access(env, pos, location, bestSoFar); 3343 } finally { 3344 currentResolutionContext = prevResolutionContext; 3345 } 3346 } 3347 3348 /** 3349 * Resolve `c.name' where name == this or name == super. 3350 * @param pos The position to use for error reporting. 3351 * @param env The environment current at the expression. 3352 * @param c The qualifier. 3353 * @param name The identifier's name. 3354 */ 3355 Symbol resolveSelf(DiagnosticPosition pos, 3356 Env<AttrContext> env, 3357 TypeSymbol c, 3358 Name name) { 3359 Env<AttrContext> env1 = env; 3360 boolean staticOnly = false; 3361 while (env1.outer != null) { 3362 if (isStatic(env1)) staticOnly = true; 3363 if (env1.enclClass.sym == c) { 3364 Symbol sym = env1.info.scope.findFirst(name); 3365 if (sym != null) { 3366 if (staticOnly) sym = new StaticError(sym); 3367 return accessBase(sym, pos, env.enclClass.sym.type, 3368 name, true); 3369 } 3370 } 3371 if ((env1.enclClass.sym.flags() & STATIC) != 0) staticOnly = true; 3372 env1 = env1.outer; 3373 } 3374 if (c.isInterface() && 3375 name == names._super && !isStatic(env) && 3376 types.isDirectSuperInterface(c, env.enclClass.sym)) { 3377 //this might be a default super call if one of the superinterfaces is 'c' 3378 for (Type t : pruneInterfaces(env.enclClass.type)) { 3379 if (t.tsym == c) { 3380 env.info.defaultSuperCallSite = t; 3381 return new VarSymbol(0, names._super, 3382 types.asSuper(env.enclClass.type, c), env.enclClass.sym); 3383 } 3384 } 3385 //find a direct super type that is a subtype of 'c' 3386 for (Type i : types.directSupertypes(env.enclClass.type)) { 3387 if (i.tsym.isSubClass(c, types) && i.tsym != c) { 3388 log.error(pos, "illegal.default.super.call", c, 3389 diags.fragment("redundant.supertype", c, i)); 3390 return syms.errSymbol; 3391 } 3392 } 3393 Assert.error(); 3394 } 3395 log.error(pos, "not.encl.class", c); 3396 return syms.errSymbol; 3397 } 3398 //where 3399 private List<Type> pruneInterfaces(Type t) { 3400 ListBuffer<Type> result = new ListBuffer<>(); 3401 for (Type t1 : types.interfaces(t)) { 3402 boolean shouldAdd = true; 3403 for (Type t2 : types.directSupertypes(t)) { 3404 if (t1 != t2 && types.isSubtypeNoCapture(t2, t1)) { 3405 shouldAdd = false; 3406 } 3407 } 3408 if (shouldAdd) { 3409 result.append(t1); 3410 } 3411 } 3412 return result.toList(); 3413 } 3414 3415 3416 /** 3417 * Resolve `c.this' for an enclosing class c that contains the 3418 * named member. 3419 * @param pos The position to use for error reporting. 3420 * @param env The environment current at the expression. 3421 * @param member The member that must be contained in the result. 3422 */ 3423 Symbol resolveSelfContaining(DiagnosticPosition pos, 3424 Env<AttrContext> env, 3425 Symbol member, 3426 boolean isSuperCall) { 3427 Symbol sym = resolveSelfContainingInternal(env, member, isSuperCall); 3428 if (sym == null) { 3429 log.error(pos, "encl.class.required", member); 3430 return syms.errSymbol; 3431 } else { 3432 return accessBase(sym, pos, env.enclClass.sym.type, sym.name, true); 3433 } 3434 } 3435 3436 boolean enclosingInstanceMissing(Env<AttrContext> env, Type type) { 3437 if (type.hasTag(CLASS) && type.getEnclosingType().hasTag(CLASS)) { 3438 Symbol encl = resolveSelfContainingInternal(env, type.tsym, false); 3439 return encl == null || encl.kind.isResolutionError(); 3440 } 3441 return false; 3442 } 3443 3444 private Symbol resolveSelfContainingInternal(Env<AttrContext> env, 3445 Symbol member, 3446 boolean isSuperCall) { 3447 Name name = names._this; 3448 Env<AttrContext> env1 = isSuperCall ? env.outer : env; 3449 boolean staticOnly = false; 3450 if (env1 != null) { 3451 while (env1 != null && env1.outer != null) { 3452 if (isStatic(env1)) staticOnly = true; 3453 if (env1.enclClass.sym.isSubClass(member.owner.enclClass(), types)) { 3454 Symbol sym = env1.info.scope.findFirst(name); 3455 if (sym != null) { 3456 if (staticOnly) sym = new StaticError(sym); 3457 return sym; 3458 } 3459 } 3460 if ((env1.enclClass.sym.flags() & STATIC) != 0) 3461 staticOnly = true; 3462 env1 = env1.outer; 3463 } 3464 } 3465 return null; 3466 } 3467 3468 /** 3469 * Resolve an appropriate implicit this instance for t's container. 3470 * JLS 8.8.5.1 and 15.9.2 3471 */ 3472 Type resolveImplicitThis(DiagnosticPosition pos, Env<AttrContext> env, Type t) { 3473 return resolveImplicitThis(pos, env, t, false); 3474 } 3475 3476 Type resolveImplicitThis(DiagnosticPosition pos, Env<AttrContext> env, Type t, boolean isSuperCall) { 3477 Type thisType = (t.tsym.owner.kind.matches(KindSelector.VAL_MTH) 3478 ? resolveSelf(pos, env, t.getEnclosingType().tsym, names._this) 3479 : resolveSelfContaining(pos, env, t.tsym, isSuperCall)).type; 3480 if (env.info.isSelfCall && thisType.tsym == env.enclClass.sym) 3481 log.error(pos, "cant.ref.before.ctor.called", "this"); 3482 return thisType; 3483 } 3484 3485/* *************************************************************************** 3486 * ResolveError classes, indicating error situations when accessing symbols 3487 ****************************************************************************/ 3488 3489 //used by TransTypes when checking target type of synthetic cast 3490 public void logAccessErrorInternal(Env<AttrContext> env, JCTree tree, Type type) { 3491 AccessError error = new AccessError(env, env.enclClass.type, type.tsym); 3492 logResolveError(error, tree.pos(), env.enclClass.sym, env.enclClass.type, null, null, null); 3493 } 3494 //where 3495 private void logResolveError(ResolveError error, 3496 DiagnosticPosition pos, 3497 Symbol location, 3498 Type site, 3499 Name name, 3500 List<Type> argtypes, 3501 List<Type> typeargtypes) { 3502 JCDiagnostic d = error.getDiagnostic(JCDiagnostic.DiagnosticType.ERROR, 3503 pos, location, site, name, argtypes, typeargtypes); 3504 if (d != null) { 3505 d.setFlag(DiagnosticFlag.RESOLVE_ERROR); 3506 log.report(d); 3507 } 3508 } 3509 3510 private final LocalizedString noArgs = new LocalizedString("compiler.misc.no.args"); 3511 3512 public Object methodArguments(List<Type> argtypes) { 3513 if (argtypes == null || argtypes.isEmpty()) { 3514 return noArgs; 3515 } else { 3516 ListBuffer<Object> diagArgs = new ListBuffer<>(); 3517 for (Type t : argtypes) { 3518 if (t.hasTag(DEFERRED)) { 3519 diagArgs.append(((DeferredAttr.DeferredType)t).tree); 3520 } else { 3521 diagArgs.append(t); 3522 } 3523 } 3524 return diagArgs; 3525 } 3526 } 3527 3528 /** 3529 * Root class for resolution errors. Subclass of ResolveError 3530 * represent a different kinds of resolution error - as such they must 3531 * specify how they map into concrete compiler diagnostics. 3532 */ 3533 abstract class ResolveError extends Symbol { 3534 3535 /** The name of the kind of error, for debugging only. */ 3536 final String debugName; 3537 3538 ResolveError(Kind kind, String debugName) { 3539 super(kind, 0, null, null, null); 3540 this.debugName = debugName; 3541 } 3542 3543 @Override @DefinedBy(Api.LANGUAGE_MODEL) 3544 public <R, P> R accept(ElementVisitor<R, P> v, P p) { 3545 throw new AssertionError(); 3546 } 3547 3548 @Override 3549 public String toString() { 3550 return debugName; 3551 } 3552 3553 @Override 3554 public boolean exists() { 3555 return false; 3556 } 3557 3558 @Override 3559 public boolean isStatic() { 3560 return false; 3561 } 3562 3563 /** 3564 * Create an external representation for this erroneous symbol to be 3565 * used during attribution - by default this returns the symbol of a 3566 * brand new error type which stores the original type found 3567 * during resolution. 3568 * 3569 * @param name the name used during resolution 3570 * @param location the location from which the symbol is accessed 3571 */ 3572 protected Symbol access(Name name, TypeSymbol location) { 3573 return types.createErrorType(name, location, syms.errSymbol.type).tsym; 3574 } 3575 3576 /** 3577 * Create a diagnostic representing this resolution error. 3578 * 3579 * @param dkind The kind of the diagnostic to be created (e.g error). 3580 * @param pos The position to be used for error reporting. 3581 * @param site The original type from where the selection took place. 3582 * @param name The name of the symbol to be resolved. 3583 * @param argtypes The invocation's value arguments, 3584 * if we looked for a method. 3585 * @param typeargtypes The invocation's type arguments, 3586 * if we looked for a method. 3587 */ 3588 abstract JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind, 3589 DiagnosticPosition pos, 3590 Symbol location, 3591 Type site, 3592 Name name, 3593 List<Type> argtypes, 3594 List<Type> typeargtypes); 3595 } 3596 3597 /** 3598 * This class is the root class of all resolution errors caused by 3599 * an invalid symbol being found during resolution. 3600 */ 3601 abstract class InvalidSymbolError extends ResolveError { 3602 3603 /** The invalid symbol found during resolution */ 3604 Symbol sym; 3605 3606 InvalidSymbolError(Kind kind, Symbol sym, String debugName) { 3607 super(kind, debugName); 3608 this.sym = sym; 3609 } 3610 3611 @Override 3612 public boolean exists() { 3613 return true; 3614 } 3615 3616 @Override 3617 public String toString() { 3618 return super.toString() + " wrongSym=" + sym; 3619 } 3620 3621 @Override 3622 public Symbol access(Name name, TypeSymbol location) { 3623 if (!sym.kind.isResolutionError() && sym.kind.matches(KindSelector.TYP)) 3624 return types.createErrorType(name, location, sym.type).tsym; 3625 else 3626 return sym; 3627 } 3628 } 3629 3630 /** 3631 * InvalidSymbolError error class indicating that a symbol matching a 3632 * given name does not exists in a given site. 3633 */ 3634 class SymbolNotFoundError extends ResolveError { 3635 3636 SymbolNotFoundError(Kind kind) { 3637 this(kind, "symbol not found error"); 3638 } 3639 3640 SymbolNotFoundError(Kind kind, String debugName) { 3641 super(kind, debugName); 3642 } 3643 3644 @Override 3645 JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind, 3646 DiagnosticPosition pos, 3647 Symbol location, 3648 Type site, 3649 Name name, 3650 List<Type> argtypes, 3651 List<Type> typeargtypes) { 3652 argtypes = argtypes == null ? List.<Type>nil() : argtypes; 3653 typeargtypes = typeargtypes == null ? List.<Type>nil() : typeargtypes; 3654 if (name == names.error) 3655 return null; 3656 3657 boolean hasLocation = false; 3658 if (location == null) { 3659 location = site.tsym; 3660 } 3661 if (!location.name.isEmpty()) { 3662 if (location.kind == PCK && !site.tsym.exists()) { 3663 return diags.create(dkind, log.currentSource(), pos, 3664 "doesnt.exist", location); 3665 } 3666 hasLocation = !location.name.equals(names._this) && 3667 !location.name.equals(names._super); 3668 } 3669 boolean isConstructor = name == names.init; 3670 KindName kindname = isConstructor ? KindName.CONSTRUCTOR : kind.absentKind(); 3671 Name idname = isConstructor ? site.tsym.name : name; 3672 String errKey = getErrorKey(kindname, typeargtypes.nonEmpty(), hasLocation); 3673 if (hasLocation) { 3674 return diags.create(dkind, log.currentSource(), pos, 3675 errKey, kindname, idname, //symbol kindname, name 3676 typeargtypes, args(argtypes), //type parameters and arguments (if any) 3677 getLocationDiag(location, site)); //location kindname, type 3678 } 3679 else { 3680 return diags.create(dkind, log.currentSource(), pos, 3681 errKey, kindname, idname, //symbol kindname, name 3682 typeargtypes, args(argtypes)); //type parameters and arguments (if any) 3683 } 3684 } 3685 //where 3686 private Object args(List<Type> args) { 3687 return args.isEmpty() ? args : methodArguments(args); 3688 } 3689 3690 private String getErrorKey(KindName kindname, boolean hasTypeArgs, boolean hasLocation) { 3691 String key = "cant.resolve"; 3692 String suffix = hasLocation ? ".location" : ""; 3693 switch (kindname) { 3694 case METHOD: 3695 case CONSTRUCTOR: { 3696 suffix += ".args"; 3697 suffix += hasTypeArgs ? ".params" : ""; 3698 } 3699 } 3700 return key + suffix; 3701 } 3702 private JCDiagnostic getLocationDiag(Symbol location, Type site) { 3703 if (location.kind == VAR) { 3704 return diags.fragment("location.1", 3705 kindName(location), 3706 location, 3707 location.type); 3708 } else { 3709 return diags.fragment("location", 3710 typeKindName(site), 3711 site, 3712 null); 3713 } 3714 } 3715 } 3716 3717 /** 3718 * InvalidSymbolError error class indicating that a given symbol 3719 * (either a method, a constructor or an operand) is not applicable 3720 * given an actual arguments/type argument list. 3721 */ 3722 class InapplicableSymbolError extends ResolveError { 3723 3724 protected MethodResolutionContext resolveContext; 3725 3726 InapplicableSymbolError(MethodResolutionContext context) { 3727 this(WRONG_MTH, "inapplicable symbol error", context); 3728 } 3729 3730 protected InapplicableSymbolError(Kind kind, String debugName, MethodResolutionContext context) { 3731 super(kind, debugName); 3732 this.resolveContext = context; 3733 } 3734 3735 @Override 3736 public String toString() { 3737 return super.toString(); 3738 } 3739 3740 @Override 3741 public boolean exists() { 3742 return true; 3743 } 3744 3745 @Override 3746 JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind, 3747 DiagnosticPosition pos, 3748 Symbol location, 3749 Type site, 3750 Name name, 3751 List<Type> argtypes, 3752 List<Type> typeargtypes) { 3753 if (name == names.error) 3754 return null; 3755 3756 Pair<Symbol, JCDiagnostic> c = errCandidate(); 3757 if (compactMethodDiags) { 3758 JCDiagnostic simpleDiag = 3759 MethodResolutionDiagHelper.rewrite(diags, pos, log.currentSource(), dkind, c.snd); 3760 if (simpleDiag != null) { 3761 return simpleDiag; 3762 } 3763 } 3764 Symbol ws = c.fst.asMemberOf(site, types); 3765 return diags.create(dkind, log.currentSource(), pos, 3766 "cant.apply.symbol", 3767 kindName(ws), 3768 ws.name == names.init ? ws.owner.name : ws.name, 3769 methodArguments(ws.type.getParameterTypes()), 3770 methodArguments(argtypes), 3771 kindName(ws.owner), 3772 ws.owner.type, 3773 c.snd); 3774 } 3775 3776 @Override 3777 public Symbol access(Name name, TypeSymbol location) { 3778 return types.createErrorType(name, location, syms.errSymbol.type).tsym; 3779 } 3780 3781 protected Pair<Symbol, JCDiagnostic> errCandidate() { 3782 Candidate bestSoFar = null; 3783 for (Candidate c : resolveContext.candidates) { 3784 if (c.isApplicable()) continue; 3785 bestSoFar = c; 3786 } 3787 Assert.checkNonNull(bestSoFar); 3788 return new Pair<>(bestSoFar.sym, bestSoFar.details); 3789 } 3790 } 3791 3792 /** 3793 * ResolveError error class indicating that a symbol (either methods, constructors or operand) 3794 * is not applicable given an actual arguments/type argument list. 3795 */ 3796 class InapplicableSymbolsError extends InapplicableSymbolError { 3797 3798 InapplicableSymbolsError(MethodResolutionContext context) { 3799 super(WRONG_MTHS, "inapplicable symbols", context); 3800 } 3801 3802 @Override 3803 JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind, 3804 DiagnosticPosition pos, 3805 Symbol location, 3806 Type site, 3807 Name name, 3808 List<Type> argtypes, 3809 List<Type> typeargtypes) { 3810 Map<Symbol, JCDiagnostic> candidatesMap = mapCandidates(); 3811 Map<Symbol, JCDiagnostic> filteredCandidates = compactMethodDiags ? 3812 filterCandidates(candidatesMap) : 3813 mapCandidates(); 3814 if (filteredCandidates.isEmpty()) { 3815 filteredCandidates = candidatesMap; 3816 } 3817 boolean truncatedDiag = candidatesMap.size() != filteredCandidates.size(); 3818 if (filteredCandidates.size() > 1) { 3819 JCDiagnostic err = diags.create(dkind, 3820 null, 3821 truncatedDiag ? 3822 EnumSet.of(DiagnosticFlag.COMPRESSED) : 3823 EnumSet.noneOf(DiagnosticFlag.class), 3824 log.currentSource(), 3825 pos, 3826 "cant.apply.symbols", 3827 name == names.init ? KindName.CONSTRUCTOR : kind.absentKind(), 3828 name == names.init ? site.tsym.name : name, 3829 methodArguments(argtypes)); 3830 return new JCDiagnostic.MultilineDiagnostic(err, candidateDetails(filteredCandidates, site)); 3831 } else if (filteredCandidates.size() == 1) { 3832 Map.Entry<Symbol, JCDiagnostic> _e = 3833 filteredCandidates.entrySet().iterator().next(); 3834 final Pair<Symbol, JCDiagnostic> p = new Pair<>(_e.getKey(), _e.getValue()); 3835 JCDiagnostic d = new InapplicableSymbolError(resolveContext) { 3836 @Override 3837 protected Pair<Symbol, JCDiagnostic> errCandidate() { 3838 return p; 3839 } 3840 }.getDiagnostic(dkind, pos, 3841 location, site, name, argtypes, typeargtypes); 3842 if (truncatedDiag) { 3843 d.setFlag(DiagnosticFlag.COMPRESSED); 3844 } 3845 return d; 3846 } else { 3847 return new SymbolNotFoundError(ABSENT_MTH).getDiagnostic(dkind, pos, 3848 location, site, name, argtypes, typeargtypes); 3849 } 3850 } 3851 //where 3852 private Map<Symbol, JCDiagnostic> mapCandidates() { 3853 Map<Symbol, JCDiagnostic> candidates = new LinkedHashMap<>(); 3854 for (Candidate c : resolveContext.candidates) { 3855 if (c.isApplicable()) continue; 3856 candidates.put(c.sym, c.details); 3857 } 3858 return candidates; 3859 } 3860 3861 Map<Symbol, JCDiagnostic> filterCandidates(Map<Symbol, JCDiagnostic> candidatesMap) { 3862 Map<Symbol, JCDiagnostic> candidates = new LinkedHashMap<>(); 3863 for (Map.Entry<Symbol, JCDiagnostic> _entry : candidatesMap.entrySet()) { 3864 JCDiagnostic d = _entry.getValue(); 3865 if (!new Template(MethodCheckDiag.ARITY_MISMATCH.regex()).matches(d)) { 3866 candidates.put(_entry.getKey(), d); 3867 } 3868 } 3869 return candidates; 3870 } 3871 3872 private List<JCDiagnostic> candidateDetails(Map<Symbol, JCDiagnostic> candidatesMap, Type site) { 3873 List<JCDiagnostic> details = List.nil(); 3874 for (Map.Entry<Symbol, JCDiagnostic> _entry : candidatesMap.entrySet()) { 3875 Symbol sym = _entry.getKey(); 3876 JCDiagnostic detailDiag = diags.fragment("inapplicable.method", 3877 Kinds.kindName(sym), 3878 sym.location(site, types), 3879 sym.asMemberOf(site, types), 3880 _entry.getValue()); 3881 details = details.prepend(detailDiag); 3882 } 3883 //typically members are visited in reverse order (see Scope) 3884 //so we need to reverse the candidate list so that candidates 3885 //conform to source order 3886 return details; 3887 } 3888 } 3889 3890 /** 3891 * DiamondError error class indicating that a constructor symbol is not applicable 3892 * given an actual arguments/type argument list using diamond inference. 3893 */ 3894 class DiamondError extends InapplicableSymbolError { 3895 3896 Symbol sym; 3897 3898 public DiamondError(Symbol sym, MethodResolutionContext context) { 3899 super(sym.kind, "diamondError", context); 3900 this.sym = sym; 3901 } 3902 3903 JCDiagnostic getDetails() { 3904 return (sym.kind == WRONG_MTH) ? 3905 ((InapplicableSymbolError)sym.baseSymbol()).errCandidate().snd : 3906 null; 3907 } 3908 3909 @Override 3910 JCDiagnostic getDiagnostic(DiagnosticType dkind, DiagnosticPosition pos, 3911 Symbol location, Type site, Name name, List<Type> argtypes, List<Type> typeargtypes) { 3912 JCDiagnostic details = getDetails(); 3913 if (details != null && compactMethodDiags) { 3914 JCDiagnostic simpleDiag = 3915 MethodResolutionDiagHelper.rewrite(diags, pos, log.currentSource(), dkind, details); 3916 if (simpleDiag != null) { 3917 return simpleDiag; 3918 } 3919 } 3920 String key = details == null ? 3921 "cant.apply.diamond" : 3922 "cant.apply.diamond.1"; 3923 return diags.create(dkind, log.currentSource(), pos, key, 3924 diags.fragment("diamond", site.tsym), details); 3925 } 3926 } 3927 3928 /** 3929 * An InvalidSymbolError error class indicating that a symbol is not 3930 * accessible from a given site 3931 */ 3932 class AccessError extends InvalidSymbolError { 3933 3934 private Env<AttrContext> env; 3935 private Type site; 3936 3937 AccessError(Symbol sym) { 3938 this(null, null, sym); 3939 } 3940 3941 AccessError(Env<AttrContext> env, Type site, Symbol sym) { 3942 super(HIDDEN, sym, "access error"); 3943 this.env = env; 3944 this.site = site; 3945 } 3946 3947 @Override 3948 public boolean exists() { 3949 return false; 3950 } 3951 3952 @Override 3953 JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind, 3954 DiagnosticPosition pos, 3955 Symbol location, 3956 Type site, 3957 Name name, 3958 List<Type> argtypes, 3959 List<Type> typeargtypes) { 3960 if (sym.owner.type.hasTag(ERROR)) 3961 return null; 3962 3963 if (sym.name == names.init && sym.owner != site.tsym) { 3964 return new SymbolNotFoundError(ABSENT_MTH).getDiagnostic(dkind, 3965 pos, location, site, name, argtypes, typeargtypes); 3966 } 3967 else if ((sym.flags() & PUBLIC) != 0 3968 || (env != null && this.site != null 3969 && !isAccessible(env, this.site))) { 3970 if (sym.owner.kind == PCK) { 3971 return diags.create(dkind, log.currentSource(), 3972 pos, "not.def.access.package.cant.access", 3973 sym, sym.location()); 3974 } else { 3975 return diags.create(dkind, log.currentSource(), 3976 pos, "not.def.access.class.intf.cant.access", 3977 sym, sym.location()); 3978 } 3979 } 3980 else if ((sym.flags() & (PRIVATE | PROTECTED)) != 0) { 3981 return diags.create(dkind, log.currentSource(), 3982 pos, "report.access", sym, 3983 asFlagSet(sym.flags() & (PRIVATE | PROTECTED)), 3984 sym.location()); 3985 } 3986 else { 3987 return diags.create(dkind, log.currentSource(), 3988 pos, "not.def.public.cant.access", sym, sym.location()); 3989 } 3990 } 3991 3992 private String toString(Type type) { 3993 StringBuilder sb = new StringBuilder(); 3994 sb.append(type); 3995 if (type != null) { 3996 sb.append("[tsym:").append(type.tsym); 3997 if (type.tsym != null) 3998 sb.append("packge:").append(type.tsym.packge()); 3999 sb.append("]"); 4000 } 4001 return sb.toString(); 4002 } 4003 } 4004 4005 /** 4006 * InvalidSymbolError error class indicating that an instance member 4007 * has erroneously been accessed from a static context. 4008 */ 4009 class StaticError extends InvalidSymbolError { 4010 4011 StaticError(Symbol sym) { 4012 super(STATICERR, sym, "static error"); 4013 } 4014 4015 @Override 4016 JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind, 4017 DiagnosticPosition pos, 4018 Symbol location, 4019 Type site, 4020 Name name, 4021 List<Type> argtypes, 4022 List<Type> typeargtypes) { 4023 Symbol errSym = ((sym.kind == TYP && sym.type.hasTag(CLASS)) 4024 ? types.erasure(sym.type).tsym 4025 : sym); 4026 return diags.create(dkind, log.currentSource(), pos, 4027 "non-static.cant.be.ref", kindName(sym), errSym); 4028 } 4029 } 4030 4031 /** 4032 * InvalidSymbolError error class indicating that a pair of symbols 4033 * (either methods, constructors or operands) are ambiguous 4034 * given an actual arguments/type argument list. 4035 */ 4036 class AmbiguityError extends ResolveError { 4037 4038 /** The other maximally specific symbol */ 4039 List<Symbol> ambiguousSyms = List.nil(); 4040 4041 @Override 4042 public boolean exists() { 4043 return true; 4044 } 4045 4046 AmbiguityError(Symbol sym1, Symbol sym2) { 4047 super(AMBIGUOUS, "ambiguity error"); 4048 ambiguousSyms = flatten(sym2).appendList(flatten(sym1)); 4049 } 4050 4051 private List<Symbol> flatten(Symbol sym) { 4052 if (sym.kind == AMBIGUOUS) { 4053 return ((AmbiguityError)sym.baseSymbol()).ambiguousSyms; 4054 } else { 4055 return List.of(sym); 4056 } 4057 } 4058 4059 AmbiguityError addAmbiguousSymbol(Symbol s) { 4060 ambiguousSyms = ambiguousSyms.prepend(s); 4061 return this; 4062 } 4063 4064 @Override 4065 JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind, 4066 DiagnosticPosition pos, 4067 Symbol location, 4068 Type site, 4069 Name name, 4070 List<Type> argtypes, 4071 List<Type> typeargtypes) { 4072 List<Symbol> diagSyms = ambiguousSyms.reverse(); 4073 Symbol s1 = diagSyms.head; 4074 Symbol s2 = diagSyms.tail.head; 4075 Name sname = s1.name; 4076 if (sname == names.init) sname = s1.owner.name; 4077 return diags.create(dkind, log.currentSource(), 4078 pos, "ref.ambiguous", sname, 4079 kindName(s1), 4080 s1, 4081 s1.location(site, types), 4082 kindName(s2), 4083 s2, 4084 s2.location(site, types)); 4085 } 4086 4087 /** 4088 * If multiple applicable methods are found during overload and none of them 4089 * is more specific than the others, attempt to merge their signatures. 4090 */ 4091 Symbol mergeAbstracts(Type site) { 4092 List<Symbol> ambiguousInOrder = ambiguousSyms.reverse(); 4093 return types.mergeAbstracts(ambiguousInOrder, site, true).orElse(this); 4094 } 4095 4096 @Override 4097 protected Symbol access(Name name, TypeSymbol location) { 4098 Symbol firstAmbiguity = ambiguousSyms.last(); 4099 return firstAmbiguity.kind == TYP ? 4100 types.createErrorType(name, location, firstAmbiguity.type).tsym : 4101 firstAmbiguity; 4102 } 4103 } 4104 4105 class BadVarargsMethod extends ResolveError { 4106 4107 ResolveError delegatedError; 4108 4109 BadVarargsMethod(ResolveError delegatedError) { 4110 super(delegatedError.kind, "badVarargs"); 4111 this.delegatedError = delegatedError; 4112 } 4113 4114 @Override 4115 public Symbol baseSymbol() { 4116 return delegatedError.baseSymbol(); 4117 } 4118 4119 @Override 4120 protected Symbol access(Name name, TypeSymbol location) { 4121 return delegatedError.access(name, location); 4122 } 4123 4124 @Override 4125 public boolean exists() { 4126 return true; 4127 } 4128 4129 @Override 4130 JCDiagnostic getDiagnostic(DiagnosticType dkind, DiagnosticPosition pos, Symbol location, Type site, Name name, List<Type> argtypes, List<Type> typeargtypes) { 4131 return delegatedError.getDiagnostic(dkind, pos, location, site, name, argtypes, typeargtypes); 4132 } 4133 } 4134 4135 /** 4136 * BadMethodReferenceError error class indicating that a method reference symbol has been found, 4137 * but with the wrong staticness. 4138 */ 4139 class BadMethodReferenceError extends StaticError { 4140 4141 boolean unboundLookup; 4142 4143 public BadMethodReferenceError(Symbol sym, boolean unboundLookup) { 4144 super(sym); 4145 this.unboundLookup = unboundLookup; 4146 } 4147 4148 @Override 4149 JCDiagnostic getDiagnostic(DiagnosticType dkind, DiagnosticPosition pos, Symbol location, Type site, Name name, List<Type> argtypes, List<Type> typeargtypes) { 4150 final String key; 4151 if (!unboundLookup) { 4152 key = "bad.static.method.in.bound.lookup"; 4153 } else if (sym.isStatic()) { 4154 key = "bad.static.method.in.unbound.lookup"; 4155 } else { 4156 key = "bad.instance.method.in.unbound.lookup"; 4157 } 4158 return sym.kind.isResolutionError() ? 4159 ((ResolveError)sym).getDiagnostic(dkind, pos, location, site, name, argtypes, typeargtypes) : 4160 diags.create(dkind, log.currentSource(), pos, key, Kinds.kindName(sym), sym); 4161 } 4162 } 4163 4164 /** 4165 * BadConstructorReferenceError error class indicating that a constructor reference symbol has been found, 4166 * but pointing to a class for which an enclosing instance is not available. 4167 */ 4168 class BadConstructorReferenceError extends InvalidSymbolError { 4169 4170 public BadConstructorReferenceError(Symbol sym) { 4171 super(MISSING_ENCL, sym, "BadConstructorReferenceError"); 4172 } 4173 4174 @Override 4175 JCDiagnostic getDiagnostic(DiagnosticType dkind, DiagnosticPosition pos, Symbol location, Type site, Name name, List<Type> argtypes, List<Type> typeargtypes) { 4176 return diags.create(dkind, log.currentSource(), pos, 4177 "cant.access.inner.cls.constr", site.tsym.name, argtypes, site.getEnclosingType()); 4178 } 4179 } 4180 4181 /** 4182 * Helper class for method resolution diagnostic simplification. 4183 * Certain resolution diagnostic are rewritten as simpler diagnostic 4184 * where the enclosing resolution diagnostic (i.e. 'inapplicable method') 4185 * is stripped away, as it doesn't carry additional info. The logic 4186 * for matching a given diagnostic is given in terms of a template 4187 * hierarchy: a diagnostic template can be specified programmatically, 4188 * so that only certain diagnostics are matched. Each templete is then 4189 * associated with a rewriter object that carries out the task of rewtiting 4190 * the diagnostic to a simpler one. 4191 */ 4192 static class MethodResolutionDiagHelper { 4193 4194 /** 4195 * A diagnostic rewriter transforms a method resolution diagnostic 4196 * into a simpler one 4197 */ 4198 interface DiagnosticRewriter { 4199 JCDiagnostic rewriteDiagnostic(JCDiagnostic.Factory diags, 4200 DiagnosticPosition preferedPos, DiagnosticSource preferredSource, 4201 DiagnosticType preferredKind, JCDiagnostic d); 4202 } 4203 4204 /** 4205 * A diagnostic template is made up of two ingredients: (i) a regular 4206 * expression for matching a diagnostic key and (ii) a list of sub-templates 4207 * for matching diagnostic arguments. 4208 */ 4209 static class Template { 4210 4211 /** regex used to match diag key */ 4212 String regex; 4213 4214 /** templates used to match diagnostic args */ 4215 Template[] subTemplates; 4216 4217 Template(String key, Template... subTemplates) { 4218 this.regex = key; 4219 this.subTemplates = subTemplates; 4220 } 4221 4222 /** 4223 * Returns true if the regex matches the diagnostic key and if 4224 * all diagnostic arguments are matches by corresponding sub-templates. 4225 */ 4226 boolean matches(Object o) { 4227 JCDiagnostic d = (JCDiagnostic)o; 4228 Object[] args = d.getArgs(); 4229 if (!d.getCode().matches(regex) || 4230 subTemplates.length != d.getArgs().length) { 4231 return false; 4232 } 4233 for (int i = 0; i < args.length ; i++) { 4234 if (!subTemplates[i].matches(args[i])) { 4235 return false; 4236 } 4237 } 4238 return true; 4239 } 4240 } 4241 4242 /** 4243 * Common rewriter for all argument mismatch simplifications. 4244 */ 4245 static class ArgMismatchRewriter implements DiagnosticRewriter { 4246 4247 /** the index of the subdiagnostic to be used as primary. */ 4248 int causeIndex; 4249 4250 public ArgMismatchRewriter(int causeIndex) { 4251 this.causeIndex = causeIndex; 4252 } 4253 4254 @Override 4255 public JCDiagnostic rewriteDiagnostic(JCDiagnostic.Factory diags, 4256 DiagnosticPosition preferedPos, DiagnosticSource preferredSource, 4257 DiagnosticType preferredKind, JCDiagnostic d) { 4258 JCDiagnostic cause = (JCDiagnostic)d.getArgs()[causeIndex]; 4259 DiagnosticPosition pos = d.getDiagnosticPosition(); 4260 if (pos == null) { 4261 pos = preferedPos; 4262 } 4263 return diags.create(preferredKind, preferredSource, pos, 4264 "prob.found.req", cause); 4265 } 4266 } 4267 4268 /** a dummy template that match any diagnostic argument */ 4269 static final Template skip = new Template("") { 4270 @Override 4271 boolean matches(Object d) { 4272 return true; 4273 } 4274 }; 4275 4276 /** template for matching inference-free arguments mismatch failures */ 4277 static final Template argMismatchTemplate = new Template(MethodCheckDiag.ARG_MISMATCH.regex(), skip); 4278 4279 /** template for matching inference related arguments mismatch failures */ 4280 static final Template inferArgMismatchTemplate = new Template(MethodCheckDiag.ARG_MISMATCH.regex(), skip, skip) { 4281 @Override 4282 boolean matches(Object o) { 4283 if (!super.matches(o)) { 4284 return false; 4285 } 4286 JCDiagnostic d = (JCDiagnostic)o; 4287 @SuppressWarnings("unchecked") 4288 List<Type> tvars = (List<Type>)d.getArgs()[0]; 4289 return !containsAny(d, tvars); 4290 } 4291 4292 BiPredicate<Object, List<Type>> containsPredicate = (o, ts) -> { 4293 if (o instanceof Type) { 4294 return ((Type)o).containsAny(ts); 4295 } else if (o instanceof JCDiagnostic) { 4296 return containsAny((JCDiagnostic)o, ts); 4297 } else { 4298 return false; 4299 } 4300 }; 4301 4302 boolean containsAny(JCDiagnostic d, List<Type> ts) { 4303 return Stream.of(d.getArgs()) 4304 .anyMatch(o -> containsPredicate.test(o, ts)); 4305 } 4306 }; 4307 4308 /** rewriter map used for method resolution simplification */ 4309 static final Map<Template, DiagnosticRewriter> rewriters = new LinkedHashMap<>(); 4310 4311 static { 4312 rewriters.put(argMismatchTemplate, new ArgMismatchRewriter(0)); 4313 rewriters.put(inferArgMismatchTemplate, new ArgMismatchRewriter(1)); 4314 } 4315 4316 /** 4317 * Main entry point for diagnostic rewriting - given a diagnostic, see if any templates matches it, 4318 * and rewrite it accordingly. 4319 */ 4320 static JCDiagnostic rewrite(JCDiagnostic.Factory diags, DiagnosticPosition pos, DiagnosticSource source, 4321 DiagnosticType dkind, JCDiagnostic d) { 4322 for (Map.Entry<Template, DiagnosticRewriter> _entry : rewriters.entrySet()) { 4323 if (_entry.getKey().matches(d)) { 4324 JCDiagnostic simpleDiag = 4325 _entry.getValue().rewriteDiagnostic(diags, pos, source, dkind, d); 4326 simpleDiag.setFlag(DiagnosticFlag.COMPRESSED); 4327 return simpleDiag; 4328 } 4329 } 4330 return null; 4331 } 4332 } 4333 4334 enum MethodResolutionPhase { 4335 BASIC(false, false), 4336 BOX(true, false), 4337 VARARITY(true, true) { 4338 @Override 4339 public Symbol mergeResults(Symbol bestSoFar, Symbol sym) { 4340 //Check invariants (see {@code LookupHelper.shouldStop}) 4341 Assert.check(bestSoFar.kind.isResolutionError() && bestSoFar.kind != AMBIGUOUS); 4342 if (!sym.kind.isResolutionError()) { 4343 //varargs resolution successful 4344 return sym; 4345 } else { 4346 //pick best error 4347 switch (bestSoFar.kind) { 4348 case WRONG_MTH: 4349 case WRONG_MTHS: 4350 //Override previous errors if they were caused by argument mismatch. 4351 //This generally means preferring current symbols - but we need to pay 4352 //attention to the fact that the varargs lookup returns 'less' candidates 4353 //than the previous rounds, and adjust that accordingly. 4354 switch (sym.kind) { 4355 case WRONG_MTH: 4356 //if the previous round matched more than one method, return that 4357 //result instead 4358 return bestSoFar.kind == WRONG_MTHS ? 4359 bestSoFar : sym; 4360 case ABSENT_MTH: 4361 //do not override erroneous symbol if the arity lookup did not 4362 //match any method 4363 return bestSoFar; 4364 case WRONG_MTHS: 4365 default: 4366 //safe to override 4367 return sym; 4368 } 4369 default: 4370 //otherwise, return first error 4371 return bestSoFar; 4372 } 4373 } 4374 } 4375 }; 4376 4377 final boolean isBoxingRequired; 4378 final boolean isVarargsRequired; 4379 4380 MethodResolutionPhase(boolean isBoxingRequired, boolean isVarargsRequired) { 4381 this.isBoxingRequired = isBoxingRequired; 4382 this.isVarargsRequired = isVarargsRequired; 4383 } 4384 4385 public boolean isBoxingRequired() { 4386 return isBoxingRequired; 4387 } 4388 4389 public boolean isVarargsRequired() { 4390 return isVarargsRequired; 4391 } 4392 4393 public Symbol mergeResults(Symbol prev, Symbol sym) { 4394 return sym; 4395 } 4396 } 4397 4398 final List<MethodResolutionPhase> methodResolutionSteps = List.of(BASIC, BOX, VARARITY); 4399 4400 /** 4401 * A resolution context is used to keep track of intermediate results of 4402 * overload resolution, such as list of method that are not applicable 4403 * (used to generate more precise diagnostics) and so on. Resolution contexts 4404 * can be nested - this means that when each overload resolution routine should 4405 * work within the resolution context it created. 4406 */ 4407 class MethodResolutionContext { 4408 4409 private List<Candidate> candidates = List.nil(); 4410 4411 MethodResolutionPhase step = null; 4412 4413 MethodCheck methodCheck = resolveMethodCheck; 4414 4415 private boolean internalResolution = false; 4416 private DeferredAttr.AttrMode attrMode = DeferredAttr.AttrMode.SPECULATIVE; 4417 4418 void addInapplicableCandidate(Symbol sym, JCDiagnostic details) { 4419 Candidate c = new Candidate(currentResolutionContext.step, sym, details, null); 4420 candidates = candidates.append(c); 4421 } 4422 4423 void addApplicableCandidate(Symbol sym, Type mtype) { 4424 Candidate c = new Candidate(currentResolutionContext.step, sym, null, mtype); 4425 candidates = candidates.append(c); 4426 } 4427 4428 DeferredAttrContext deferredAttrContext(Symbol sym, InferenceContext inferenceContext, ResultInfo pendingResult, Warner warn) { 4429 DeferredAttrContext parent = (pendingResult == null) 4430 ? deferredAttr.emptyDeferredAttrContext 4431 : pendingResult.checkContext.deferredAttrContext(); 4432 return deferredAttr.new DeferredAttrContext(attrMode, sym, step, 4433 inferenceContext, parent, warn); 4434 } 4435 4436 /** 4437 * This class represents an overload resolution candidate. There are two 4438 * kinds of candidates: applicable methods and inapplicable methods; 4439 * applicable methods have a pointer to the instantiated method type, 4440 * while inapplicable candidates contain further details about the 4441 * reason why the method has been considered inapplicable. 4442 */ 4443 @SuppressWarnings("overrides") 4444 class Candidate { 4445 4446 final MethodResolutionPhase step; 4447 final Symbol sym; 4448 final JCDiagnostic details; 4449 final Type mtype; 4450 4451 private Candidate(MethodResolutionPhase step, Symbol sym, JCDiagnostic details, Type mtype) { 4452 this.step = step; 4453 this.sym = sym; 4454 this.details = details; 4455 this.mtype = mtype; 4456 } 4457 4458 @Override 4459 public boolean equals(Object o) { 4460 if (o instanceof Candidate) { 4461 Symbol s1 = this.sym; 4462 Symbol s2 = ((Candidate)o).sym; 4463 if ((s1 != s2 && 4464 (s1.overrides(s2, s1.owner.type.tsym, types, false) || 4465 (s2.overrides(s1, s2.owner.type.tsym, types, false)))) || 4466 ((s1.isConstructor() || s2.isConstructor()) && s1.owner != s2.owner)) 4467 return true; 4468 } 4469 return false; 4470 } 4471 4472 boolean isApplicable() { 4473 return mtype != null; 4474 } 4475 } 4476 4477 DeferredAttr.AttrMode attrMode() { 4478 return attrMode; 4479 } 4480 4481 boolean internal() { 4482 return internalResolution; 4483 } 4484 } 4485 4486 MethodResolutionContext currentResolutionContext = null; 4487} 4488