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