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