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