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