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