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