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