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