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