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