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