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