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