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