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