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