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