Resolve.java revision 3243:645b5debcb07
1106813Ssimokawa/* 2113584Ssimokawa * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. 3106813Ssimokawa * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4106813Ssimokawa * 5106813Ssimokawa * This code is free software; you can redistribute it and/or modify it 6106813Ssimokawa * under the terms of the GNU General Public License version 2 only, as 7106813Ssimokawa * published by the Free Software Foundation. Oracle designates this 8106813Ssimokawa * particular file as subject to the "Classpath" exception as provided 9106813Ssimokawa * by Oracle in the LICENSE file that accompanied this code. 10106813Ssimokawa * 11106813Ssimokawa * This code is distributed in the hope that it will be useful, but WITHOUT 12106813Ssimokawa * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13106813Ssimokawa * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14106813Ssimokawa * version 2 for more details (a copy is included in the LICENSE file that 15106813Ssimokawa * accompanied this code). 16106813Ssimokawa * 17106813Ssimokawa * You should have received a copy of the GNU General Public License version 18106813Ssimokawa * 2 along with this work; if not, write to the Free Software Foundation, 19106813Ssimokawa * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20106813Ssimokawa * 21106813Ssimokawa * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22106813Ssimokawa * or visit www.oracle.com if you need additional information or have any 23106813Ssimokawa * questions. 24106813Ssimokawa */ 25106813Ssimokawa 26106813Ssimokawapackage com.sun.tools.javac.comp; 27106813Ssimokawa 28106813Ssimokawaimport com.sun.tools.javac.api.Formattable.LocalizedString; 29106813Ssimokawaimport com.sun.tools.javac.code.*; 30106813Ssimokawaimport com.sun.tools.javac.code.Scope.WriteableScope; 31106813Ssimokawaimport com.sun.tools.javac.code.Symbol.*; 32106813Ssimokawaimport com.sun.tools.javac.code.Type.*; 33106813Ssimokawaimport com.sun.tools.javac.comp.Attr.ResultInfo; 34106813Ssimokawaimport com.sun.tools.javac.comp.Check.CheckContext; 35106813Ssimokawaimport com.sun.tools.javac.comp.DeferredAttr.AttrMode; 36106813Ssimokawaimport com.sun.tools.javac.comp.DeferredAttr.DeferredAttrContext; 37106813Ssimokawaimport com.sun.tools.javac.comp.DeferredAttr.DeferredType; 38106813Ssimokawaimport com.sun.tools.javac.comp.Infer.FreeTypeListener; 39106813Ssimokawaimport com.sun.tools.javac.comp.Resolve.MethodResolutionContext.Candidate; 40106813Ssimokawaimport com.sun.tools.javac.comp.Resolve.MethodResolutionDiagHelper.Template; 41106813Ssimokawaimport com.sun.tools.javac.comp.Resolve.ReferenceLookupResult.StaticKind; 42120660Ssimokawaimport com.sun.tools.javac.jvm.*; 43120660Ssimokawaimport com.sun.tools.javac.main.Option; 44120660Ssimokawaimport com.sun.tools.javac.tree.*; 45120660Ssimokawaimport com.sun.tools.javac.tree.JCTree.*; 46120660Ssimokawaimport com.sun.tools.javac.tree.JCTree.JCMemberReference.ReferenceKind; 47106813Ssimokawaimport com.sun.tools.javac.tree.JCTree.JCPolyExpression.*; 48106813Ssimokawaimport com.sun.tools.javac.util.*; 49106813Ssimokawaimport com.sun.tools.javac.util.DefinedBy.Api; 50106813Ssimokawaimport com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag; 51106813Ssimokawaimport com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; 52106813Ssimokawaimport com.sun.tools.javac.util.JCDiagnostic.DiagnosticType; 53106813Ssimokawa 54118455Ssimokawaimport java.util.Arrays; 55113584Ssimokawaimport java.util.Collection; 56106813Ssimokawaimport java.util.EnumSet; 57106813Ssimokawaimport java.util.Iterator; 58106813Ssimokawaimport java.util.LinkedHashMap; 59106813Ssimokawaimport java.util.Map; 60106813Ssimokawaimport java.util.function.BiPredicate; 61113584Ssimokawaimport java.util.stream.Stream; 62106813Ssimokawa 63109282Ssimokawaimport javax.lang.model.element.ElementVisitor; 64106813Ssimokawa 65106813Ssimokawaimport static com.sun.tools.javac.code.Flags.*; 66106813Ssimokawaimport static com.sun.tools.javac.code.Flags.BLOCK; 67106813Ssimokawaimport static com.sun.tools.javac.code.Flags.STATIC; 68106813Ssimokawaimport static com.sun.tools.javac.code.Kinds.*; 69106813Ssimokawaimport static com.sun.tools.javac.code.Kinds.Kind.*; 70106813Ssimokawaimport static com.sun.tools.javac.code.TypeTag.*; 71106813Ssimokawaimport static com.sun.tools.javac.comp.Resolve.MethodResolutionPhase.*; 72106813Ssimokawaimport static com.sun.tools.javac.tree.JCTree.Tag.*; 73106813Ssimokawa 74120660Ssimokawa/** Helper class for name resolution, used mostly by the attribution phase. 75106813Ssimokawa * 76126080Sphk * <p><b>This is NOT part of any supported API. 77111942Ssimokawa * If you write code that depends on this, you do so at your own risk. 78126080Sphk * This code and its internal interfaces are subject to change or 79111815Sphk * deletion without notice.</b> 80111815Sphk */ 81111815Sphkpublic class Resolve { 82111815Sphk protected static final Context.Key<Resolve> resolveKey = new Context.Key<>(); 83111815Sphk 84111815Sphk Names names; 85111815Sphk Log log; 86120660Ssimokawa Symtab syms; 87111815Sphk Attr attr; 88126080Sphk DeferredAttr deferredAttr; 89111942Ssimokawa Check chk; 90111942Ssimokawa Infer infer; 91120660Ssimokawa ClassFinder finder; 92118455Ssimokawa Types types; 93111942Ssimokawa JCDiagnostic.Factory diags; 94106813Ssimokawa public final boolean allowMethodHandles; 95106813Ssimokawa public final boolean allowFunctionalInterfaceMostSpecific; 96118293Ssimokawa public final boolean checkVarargsAccessAfterResolution; 97118293Ssimokawa private final boolean compactMethodDiags; 98118293Ssimokawa final EnumSet<VerboseResolutionMode> verboseResolutionMode; 99118293Ssimokawa 100118293Ssimokawa WriteableScope polymorphicSignatureScope; 101118293Ssimokawa 102106813Ssimokawa protected Resolve(Context context) { 103118293Ssimokawa context.put(resolveKey, this); 104118293Ssimokawa syms = Symtab.instance(context); 105118293Ssimokawa 106118293Ssimokawa varNotFound = new SymbolNotFoundError(ABSENT_VAR); 107118293Ssimokawa methodNotFound = new SymbolNotFoundError(ABSENT_MTH); 108118293Ssimokawa typeNotFound = new SymbolNotFoundError(ABSENT_TYP); 109118293Ssimokawa referenceNotFound = new ReferenceLookupResult(methodNotFound, null); 110118293Ssimokawa 111118293Ssimokawa names = Names.instance(context); 112118293Ssimokawa log = Log.instance(context); 113118293Ssimokawa attr = Attr.instance(context); 114118293Ssimokawa deferredAttr = DeferredAttr.instance(context); 115118293Ssimokawa chk = Check.instance(context); 116118293Ssimokawa infer = Infer.instance(context); 117118293Ssimokawa finder = ClassFinder.instance(context); 118118293Ssimokawa types = Types.instance(context); 119118293Ssimokawa diags = JCDiagnostic.Factory.instance(context); 120118293Ssimokawa Source source = Source.instance(context); 121118293Ssimokawa Options options = Options.instance(context); 122118293Ssimokawa compactMethodDiags = options.isSet(Option.XDIAGS, "compact") || 123118293Ssimokawa options.isUnset(Option.XDIAGS) && options.isUnset("rawDiagnostics"); 124118293Ssimokawa verboseResolutionMode = VerboseResolutionMode.getVerboseResolutionMode(options); 125118293Ssimokawa Target target = Target.instance(context); 126118293Ssimokawa allowMethodHandles = target.hasMethodHandles(); 127118293Ssimokawa allowFunctionalInterfaceMostSpecific = source.allowFunctionalInterfaceMostSpecific(); 128118293Ssimokawa checkVarargsAccessAfterResolution = 129118293Ssimokawa source.allowPostApplicabilityVarargsAccessCheck(); 130118293Ssimokawa polymorphicSignatureScope = WriteableScope.create(syms.noSymbol); 131118293Ssimokawa 132118293Ssimokawa inapplicableMethodException = new InapplicableMethodException(diags); 133118293Ssimokawa } 134118293Ssimokawa 135118293Ssimokawa /** error symbols, which are returned when resolution fails 136118293Ssimokawa */ 137118293Ssimokawa private final SymbolNotFoundError varNotFound; 138118293Ssimokawa private final SymbolNotFoundError methodNotFound; 139118293Ssimokawa private final SymbolNotFoundError typeNotFound; 140118293Ssimokawa 141118293Ssimokawa /** empty reference lookup result */ 142118293Ssimokawa private final ReferenceLookupResult referenceNotFound; 143118293Ssimokawa 144118293Ssimokawa public static Resolve instance(Context context) { 145118293Ssimokawa Resolve instance = context.get(resolveKey); 146118293Ssimokawa if (instance == null) 147118293Ssimokawa instance = new Resolve(context); 148118293Ssimokawa return instance; 149118293Ssimokawa } 150118293Ssimokawa 151118293Ssimokawa private static Symbol bestOf(Symbol s1, 152118293Ssimokawa Symbol s2) { 153118293Ssimokawa return s1.kind.betterThan(s2.kind) ? s1 : s2; 154118293Ssimokawa } 155118293Ssimokawa 156118293Ssimokawa // <editor-fold defaultstate="collapsed" desc="Verbose resolution diagnostics support"> 157118293Ssimokawa enum VerboseResolutionMode { 158118293Ssimokawa SUCCESS("success"), 159118293Ssimokawa FAILURE("failure"), 160118293Ssimokawa APPLICABLE("applicable"), 161118293Ssimokawa INAPPLICABLE("inapplicable"), 162118293Ssimokawa DEFERRED_INST("deferred-inference"), 163118293Ssimokawa PREDEF("predef"), 164118293Ssimokawa OBJECT_INIT("object-init"), 165118293Ssimokawa INTERNAL("internal"); 166118293Ssimokawa 167106813Ssimokawa final String opt; 168106813Ssimokawa 169106813Ssimokawa private VerboseResolutionMode(String opt) { 170106813Ssimokawa this.opt = opt; 171122227Ssimokawa } 172122227Ssimokawa 173122227Ssimokawa static EnumSet<VerboseResolutionMode> getVerboseResolutionMode(Options opts) { 174118293Ssimokawa String s = opts.get("verboseResolution"); 175118293Ssimokawa EnumSet<VerboseResolutionMode> res = EnumSet.noneOf(VerboseResolutionMode.class); 176118293Ssimokawa if (s == null) return res; 177118293Ssimokawa if (s.contains("all")) { 178118455Ssimokawa res = EnumSet.allOf(VerboseResolutionMode.class); 179118455Ssimokawa } 180118455Ssimokawa Collection<String> args = Arrays.asList(s.split(",")); 181118455Ssimokawa for (VerboseResolutionMode mode : values()) { 182118293Ssimokawa if (args.contains(mode.opt)) { 183118293Ssimokawa res.add(mode); 184118293Ssimokawa } else if (args.contains("-" + mode.opt)) { 185118455Ssimokawa res.remove(mode); 186118455Ssimokawa } 187118293Ssimokawa } 188118293Ssimokawa return res; 189118293Ssimokawa } 190106813Ssimokawa } 191106813Ssimokawa 192106813Ssimokawa void reportVerboseResolutionDiagnostic(DiagnosticPosition dpos, Name name, Type site, 193106813Ssimokawa List<Type> argtypes, List<Type> typeargtypes, Symbol bestSoFar) { 194106813Ssimokawa boolean success = !bestSoFar.kind.isResolutionError(); 195106813Ssimokawa 196106813Ssimokawa if (success && !verboseResolutionMode.contains(VerboseResolutionMode.SUCCESS)) { 197118293Ssimokawa return; 198118293Ssimokawa } else if (!success && !verboseResolutionMode.contains(VerboseResolutionMode.FAILURE)) { 199106813Ssimokawa return; 200106813Ssimokawa } 201106813Ssimokawa 202106813Ssimokawa if (bestSoFar.name == names.init && 203106813Ssimokawa bestSoFar.owner == syms.objectType.tsym && 204106813Ssimokawa !verboseResolutionMode.contains(VerboseResolutionMode.OBJECT_INIT)) { 205106813Ssimokawa return; //skip diags for Object constructor resolution 206106813Ssimokawa } else if (site == syms.predefClass.type && 207106813Ssimokawa !verboseResolutionMode.contains(VerboseResolutionMode.PREDEF)) { 208118293Ssimokawa return; //skip spurious diags for predef symbols (i.e. operators) 209118293Ssimokawa } else if (currentResolutionContext.internalResolution && 210118293Ssimokawa !verboseResolutionMode.contains(VerboseResolutionMode.INTERNAL)) { 211118293Ssimokawa return; 212118293Ssimokawa } 213118293Ssimokawa 214118293Ssimokawa int pos = 0; 215118293Ssimokawa int mostSpecificPos = -1; 216118293Ssimokawa ListBuffer<JCDiagnostic> subDiags = new ListBuffer<>(); 217118293Ssimokawa for (Candidate c : currentResolutionContext.candidates) { 218118293Ssimokawa if (currentResolutionContext.step != c.step || 219118293Ssimokawa (c.isApplicable() && !verboseResolutionMode.contains(VerboseResolutionMode.APPLICABLE)) || 220118293Ssimokawa (!c.isApplicable() && !verboseResolutionMode.contains(VerboseResolutionMode.INAPPLICABLE))) { 221118293Ssimokawa continue; 222118293Ssimokawa } else { 223118293Ssimokawa subDiags.append(c.isApplicable() ? 224118293Ssimokawa getVerboseApplicableCandidateDiag(pos, c.sym, c.mtype) : 225118293Ssimokawa getVerboseInapplicableCandidateDiag(pos, c.sym, c.details)); 226118293Ssimokawa if (c.sym == bestSoFar) 227118293Ssimokawa mostSpecificPos = pos; 228118293Ssimokawa pos++; 229118293Ssimokawa } 230118293Ssimokawa } 231118293Ssimokawa String key = success ? "verbose.resolve.multi" : "verbose.resolve.multi.1"; 232118293Ssimokawa List<Type> argtypes2 = argtypes.map(deferredAttr.new RecoveryDeferredTypeMap(AttrMode.SPECULATIVE, bestSoFar, currentResolutionContext.step)); 233118293Ssimokawa JCDiagnostic main = diags.note(log.currentSource(), dpos, key, name, 234118293Ssimokawa site.tsym, mostSpecificPos, currentResolutionContext.step, 235118293Ssimokawa methodArguments(argtypes2), 236118293Ssimokawa methodArguments(typeargtypes)); 237118293Ssimokawa JCDiagnostic d = new JCDiagnostic.MultilineDiagnostic(main, subDiags.toList()); 238118293Ssimokawa log.report(d); 239118293Ssimokawa } 240118293Ssimokawa 241118293Ssimokawa JCDiagnostic getVerboseApplicableCandidateDiag(int pos, Symbol sym, Type inst) { 242106813Ssimokawa JCDiagnostic subDiag = null; 243118293Ssimokawa if (sym.type.hasTag(FORALL)) { 244118293Ssimokawa subDiag = diags.fragment("partial.inst.sig", inst); 245106813Ssimokawa } 246118293Ssimokawa 247118293Ssimokawa String key = subDiag == null ? 248118293Ssimokawa "applicable.method.found" : 249118293Ssimokawa "applicable.method.found.1"; 250118293Ssimokawa 251118293Ssimokawa return diags.fragment(key, pos, sym, subDiag); 252118293Ssimokawa } 253118293Ssimokawa 254118293Ssimokawa JCDiagnostic getVerboseInapplicableCandidateDiag(int pos, Symbol sym, JCDiagnostic subDiag) { 255118293Ssimokawa return diags.fragment("not.applicable.method.found", pos, sym, subDiag); 256118293Ssimokawa } 257106813Ssimokawa // </editor-fold> 258118293Ssimokawa 259118293Ssimokawa/* ************************************************************************ 260106813Ssimokawa * Identifier resolution 261106813Ssimokawa *************************************************************************/ 262106813Ssimokawa 263106813Ssimokawa /** An environment is "static" if its static level is greater than 264106813Ssimokawa * the one of its outer environment 265106813Ssimokawa */ 266106813Ssimokawa protected static boolean isStatic(Env<AttrContext> env) { 267106813Ssimokawa return env.outer != null && env.info.staticLevel > env.outer.info.staticLevel; 268106813Ssimokawa } 269106813Ssimokawa 270106813Ssimokawa /** An environment is an "initializer" if it is a constructor or 271106813Ssimokawa * an instance initializer. 272106813Ssimokawa */ 273106813Ssimokawa static boolean isInitializer(Env<AttrContext> env) { 274106813Ssimokawa Symbol owner = env.info.scope.owner; 275106813Ssimokawa return owner.isConstructor() || 276106813Ssimokawa owner.owner.kind == TYP && 277106813Ssimokawa (owner.kind == VAR || 278120660Ssimokawa owner.kind == MTH && (owner.flags() & BLOCK) != 0) && 279106813Ssimokawa (owner.flags() & STATIC) == 0; 280106813Ssimokawa } 281106813Ssimokawa 282118293Ssimokawa /** Is class accessible in given evironment? 283118293Ssimokawa * @param env The current environment. 284118293Ssimokawa * @param c The class whose accessibility is checked. 285106813Ssimokawa */ 286106813Ssimokawa public boolean isAccessible(Env<AttrContext> env, TypeSymbol c) { 287106813Ssimokawa return isAccessible(env, c, false); 288113584Ssimokawa } 289109988Ssimokawa 290106813Ssimokawa public boolean isAccessible(Env<AttrContext> env, TypeSymbol c, boolean checkInner) { 291109988Ssimokawa 292106813Ssimokawa /* 15.9.5.1: Note that it is possible for the signature of the anonymous constructor 293106813Ssimokawa to refer to an inaccessible type 294106813Ssimokawa */ 295106813Ssimokawa if (env.enclMethod != null && (env.enclMethod.mods.flags & ANONCONSTR) != 0) 296106813Ssimokawa return true; 297106813Ssimokawa 298109988Ssimokawa boolean isAccessible = false; 299109988Ssimokawa switch ((short)(c.flags() & AccessFlags)) { 300109988Ssimokawa case PRIVATE: 301106813Ssimokawa isAccessible = 302106813Ssimokawa env.enclClass.sym.outermostClass() == 303111748Sdes c.owner.outermostClass(); 304109988Ssimokawa break; 305109988Ssimokawa case 0: 306109988Ssimokawa isAccessible = 307109988Ssimokawa env.toplevel.packge == c.owner // fast special case 308106813Ssimokawa || 309109988Ssimokawa env.toplevel.packge == c.packge(); 310109988Ssimokawa break; 311120660Ssimokawa default: // error recovery 312113584Ssimokawa case PUBLIC: 313106813Ssimokawa isAccessible = true; 314106813Ssimokawa break; 315106813Ssimokawa case PROTECTED: 316106813Ssimokawa isAccessible = 317120660Ssimokawa env.toplevel.packge == c.owner // fast special case 318120660Ssimokawa || 319106813Ssimokawa env.toplevel.packge == c.packge() 320120660Ssimokawa || 321120660Ssimokawa isInnerSubClass(env.enclClass.sym, c.owner); 322113584Ssimokawa break; 323120660Ssimokawa } 324106813Ssimokawa return (checkInner == false || c.type.getEnclosingType() == Type.noType) ? 325109988Ssimokawa isAccessible : 326109988Ssimokawa isAccessible && isAccessible(env, c.type.getEnclosingType(), checkInner); 327113584Ssimokawa } 328113584Ssimokawa //where 329106813Ssimokawa /** Is given class a subclass of given base class, or an inner class 330106813Ssimokawa * of a subclass? 331113584Ssimokawa * Return null if no such class exists. 332106813Ssimokawa * @param c The class which is the subclass or is contained in it. 333106813Ssimokawa * @param base The base class 334106813Ssimokawa */ 335109988Ssimokawa private boolean isInnerSubClass(ClassSymbol c, Symbol base) { 336113584Ssimokawa while (c != null && !c.isSubClass(base, types)) { 337106813Ssimokawa c = c.owner.enclClass(); 338106813Ssimokawa } 339106813Ssimokawa return c != null; 340106813Ssimokawa } 341106813Ssimokawa 342118293Ssimokawa boolean isAccessible(Env<AttrContext> env, Type t) { 343106813Ssimokawa return isAccessible(env, t, false); 344106813Ssimokawa } 345109988Ssimokawa 346109988Ssimokawa boolean isAccessible(Env<AttrContext> env, Type t, boolean checkInner) { 347109988Ssimokawa return (t.hasTag(ARRAY)) 348109988Ssimokawa ? isAccessible(env, types.cvarUpperBound(types.elemtype(t))) 349106813Ssimokawa : isAccessible(env, t.tsym, checkInner); 350106813Ssimokawa } 351106813Ssimokawa 352106813Ssimokawa /** Is symbol accessible as a member of given type in given environment? 353106813Ssimokawa * @param env The current environment. 354106813Ssimokawa * @param site The type of which the tested symbol is regarded 355106813Ssimokawa * as a member. 356106813Ssimokawa * @param sym The symbol. 357106813Ssimokawa */ 358106813Ssimokawa public boolean isAccessible(Env<AttrContext> env, Type site, Symbol sym) { 359106813Ssimokawa return isAccessible(env, site, sym, false); 360106813Ssimokawa } 361106813Ssimokawa public boolean isAccessible(Env<AttrContext> env, Type site, Symbol sym, boolean checkInner) { 362106813Ssimokawa if (sym.name == names.init && sym.owner != site.tsym) return false; 363106813Ssimokawa 364106813Ssimokawa /* 15.9.5.1: Note that it is possible for the signature of the anonymous constructor 365120660Ssimokawa to refer to an inaccessible type 366106813Ssimokawa */ 367106813Ssimokawa if (env.enclMethod != null && (env.enclMethod.mods.flags & ANONCONSTR) != 0) 368106813Ssimokawa return true; 369118293Ssimokawa 370118293Ssimokawa switch ((short)(sym.flags() & AccessFlags)) { 371118293Ssimokawa case PRIVATE: 372106813Ssimokawa return 373113802Ssimokawa (env.enclClass.sym == sym.owner // fast special case 374113802Ssimokawa || 375113802Ssimokawa env.enclClass.sym.outermostClass() == 376106813Ssimokawa sym.owner.outermostClass()) 377113802Ssimokawa && 378106813Ssimokawa sym.isInheritedIn(site.tsym, types); 379113802Ssimokawa case 0: 380113802Ssimokawa return 381113802Ssimokawa (env.toplevel.packge == sym.owner.owner // fast special case 382118293Ssimokawa || 383113802Ssimokawa env.toplevel.packge == sym.packge()) 384113802Ssimokawa && 385113802Ssimokawa isAccessible(env, site, checkInner) 386113802Ssimokawa && 387113802Ssimokawa sym.isInheritedIn(site.tsym, types) 388109988Ssimokawa && 389113802Ssimokawa notOverriddenIn(site, sym); 390113802Ssimokawa case PROTECTED: 391106813Ssimokawa return 392106813Ssimokawa (env.toplevel.packge == sym.owner.owner // fast special case 393106813Ssimokawa || 394113802Ssimokawa env.toplevel.packge == sym.packge() 395113802Ssimokawa || 396113802Ssimokawa isProtectedAccessible(sym, env.enclClass.sym, site) 397113802Ssimokawa || 398113802Ssimokawa // OK to select instance method or field from 'super' or type name 399113802Ssimokawa // (but type names should be disallowed elsewhere!) 400113802Ssimokawa env.info.selectSuper && (sym.flags() & STATIC) == 0 && sym.kind != TYP) 401113802Ssimokawa && 402113802Ssimokawa isAccessible(env, site, checkInner) 403113802Ssimokawa && 404113802Ssimokawa notOverriddenIn(site, sym); 405118293Ssimokawa default: // this case includes erroneous combinations as well 406113802Ssimokawa return isAccessible(env, site, checkInner) && notOverriddenIn(site, sym); 407113802Ssimokawa } 408113802Ssimokawa } 409113802Ssimokawa //where 410113802Ssimokawa /* `sym' is accessible only if not overridden by 411113802Ssimokawa * another symbol which is a member of `site' 412106813Ssimokawa * (because, if it is overridden, `sym' is not strictly 413106813Ssimokawa * speaking a member of `site'). A polymorphic signature method 414106813Ssimokawa * cannot be overridden (e.g. MH.invokeExact(Object[])). 415106813Ssimokawa */ 416106813Ssimokawa private boolean notOverriddenIn(Type site, Symbol sym) { 417106813Ssimokawa if (sym.kind != MTH || sym.isConstructor() || sym.isStatic()) 418106813Ssimokawa return true; 419106813Ssimokawa else { 420118293Ssimokawa Symbol s2 = ((MethodSymbol)sym).implementation(site.tsym, types, true); 421118293Ssimokawa return (s2 == null || s2 == sym || sym.owner == s2.owner || 422106813Ssimokawa !types.isSubSignature(types.memberType(site, s2), types.memberType(site, sym))); 423113584Ssimokawa } 424106813Ssimokawa } 425106813Ssimokawa //where 426106813Ssimokawa /** Is given protected symbol accessible if it is selected from given site 427106813Ssimokawa * and the selection takes place in given class? 428106813Ssimokawa * @param sym The symbol with protected access 429109814Ssimokawa * @param c The class where the access takes place 430117473Ssimokawa * @site The type of the qualifier 431106813Ssimokawa */ 432106813Ssimokawa private 433106813Ssimokawa boolean isProtectedAccessible(Symbol sym, ClassSymbol c, Type site) { 434106813Ssimokawa Type newSite = site.hasTag(TYPEVAR) ? site.getUpperBound() : site; 435106813Ssimokawa while (c != null && 436106813Ssimokawa !(c.isSubClass(sym.owner, types) && 437106813Ssimokawa (c.flags() & INTERFACE) == 0 && 438106813Ssimokawa // In JLS 2e 6.6.2.1, the subclass restriction applies 439106813Ssimokawa // only to instance fields and methods -- types are excluded 440106813Ssimokawa // regardless of whether they are declared 'static' or not. 441106813Ssimokawa ((sym.flags() & STATIC) != 0 || sym.kind == TYP || newSite.tsym.isSubClass(c, types)))) 442106813Ssimokawa c = c.owner.enclClass(); 443106813Ssimokawa return c != null; 444106813Ssimokawa } 445118293Ssimokawa 446118293Ssimokawa /** 447118293Ssimokawa * Performs a recursive scan of a type looking for accessibility problems 448118293Ssimokawa * from current attribution environment 449118293Ssimokawa */ 450118293Ssimokawa void checkAccessibleType(Env<AttrContext> env, Type t) { 451106813Ssimokawa accessibilityChecker.visit(t, env); 452106813Ssimokawa } 453118293Ssimokawa 454118293Ssimokawa /** 455118293Ssimokawa * Accessibility type-visitor 456118293Ssimokawa */ 457118293Ssimokawa Types.SimpleVisitor<Void, Env<AttrContext>> accessibilityChecker = 458118293Ssimokawa new Types.SimpleVisitor<Void, Env<AttrContext>>() { 459118293Ssimokawa 460118293Ssimokawa void visit(List<Type> ts, Env<AttrContext> env) { 461118293Ssimokawa for (Type t : ts) { 462118293Ssimokawa visit(t, env); 463118293Ssimokawa } 464118293Ssimokawa } 465118293Ssimokawa 466118293Ssimokawa public Void visitType(Type t, Env<AttrContext> env) { 467118293Ssimokawa return null; 468118293Ssimokawa } 469118293Ssimokawa 470118293Ssimokawa @Override 471118293Ssimokawa public Void visitArrayType(ArrayType t, Env<AttrContext> env) { 472106813Ssimokawa visit(t.elemtype, env); 473106813Ssimokawa return null; 474118293Ssimokawa } 475118293Ssimokawa 476118293Ssimokawa @Override 477118293Ssimokawa public Void visitClassType(ClassType t, Env<AttrContext> env) { 478118293Ssimokawa visit(t.getTypeArguments(), env); 479106813Ssimokawa if (!isAccessible(env, t, true)) { 480106813Ssimokawa accessBase(new AccessError(t.tsym), env.tree.pos(), env.enclClass.sym, t, t.tsym.name, true); 481118293Ssimokawa } 482118293Ssimokawa return null; 483118293Ssimokawa } 484118293Ssimokawa 485118293Ssimokawa @Override 486118293Ssimokawa public Void visitWildcardType(WildcardType t, Env<AttrContext> env) { 487118293Ssimokawa visit(t.type, env); 488118293Ssimokawa return null; 489118293Ssimokawa } 490118293Ssimokawa 491118293Ssimokawa @Override 492118293Ssimokawa public Void visitMethodType(MethodType t, Env<AttrContext> env) { 493118293Ssimokawa visit(t.getParameterTypes(), env); 494118293Ssimokawa visit(t.getReturnType(), env); 495118293Ssimokawa visit(t.getThrownTypes(), env); 496118293Ssimokawa return null; 497118293Ssimokawa } 498118293Ssimokawa }; 499118293Ssimokawa 500118293Ssimokawa /** Try to instantiate the type of a method so that it fits 501106813Ssimokawa * given type arguments and argument types. If successful, return 502106813Ssimokawa * the method's instantiated type, else return null. 503118293Ssimokawa * The instantiation will take into account an additional leading 504118293Ssimokawa * formal parameter if the method is an instance method seen as a member 505118293Ssimokawa * of an under determined site. In this case, we treat site as an additional 506118293Ssimokawa * parameter and the parameters of the class containing the method as 507118293Ssimokawa * additional type variables that get instantiated. 508106813Ssimokawa * 509106813Ssimokawa * @param env The current environment 510118293Ssimokawa * @param site The type of which the method is a member. 511106813Ssimokawa * @param m The method symbol. 512106813Ssimokawa * @param argtypes The invocation's given value arguments. 513118293Ssimokawa * @param typeargtypes The invocation's given type arguments. 514118293Ssimokawa * @param allowBoxing Allow boxing conversions of arguments. 515118293Ssimokawa * @param useVarargs Box trailing arguments into an array for varargs. 516118293Ssimokawa */ 517118293Ssimokawa Type rawInstantiate(Env<AttrContext> env, 518118293Ssimokawa Type site, 519118293Ssimokawa Symbol m, 520118293Ssimokawa ResultInfo resultInfo, 521118293Ssimokawa List<Type> argtypes, 522118293Ssimokawa List<Type> typeargtypes, 523118293Ssimokawa boolean allowBoxing, 524118293Ssimokawa boolean useVarargs, 525106813Ssimokawa Warner warn) throws Infer.InferenceException { 526106813Ssimokawa Type mt = types.memberType(site, m); 527120660Ssimokawa // tvars is the list of formal type variables for which type arguments 528120660Ssimokawa // need to inferred. 529121466Ssimokawa List<Type> tvars = List.nil(); 530120660Ssimokawa if (typeargtypes == null) typeargtypes = List.nil(); 531106813Ssimokawa if (!mt.hasTag(FORALL) && typeargtypes.nonEmpty()) { 532121466Ssimokawa // This is not a polymorphic method, but typeargs are supplied 533121466Ssimokawa // which is fine, see JLS 15.12.2.1 534121466Ssimokawa } else if (mt.hasTag(FORALL) && typeargtypes.nonEmpty()) { 535121466Ssimokawa ForAll pmt = (ForAll) mt; 536121466Ssimokawa if (typeargtypes.length() != pmt.tvars.length()) 537121466Ssimokawa throw inapplicableMethodException.setMessage("arg.length.mismatch"); // not enough args 538121466Ssimokawa // Check type arguments are within bounds 539121466Ssimokawa List<Type> formals = pmt.tvars; 540121466Ssimokawa List<Type> actuals = typeargtypes; 541106813Ssimokawa while (formals.nonEmpty() && actuals.nonEmpty()) { 542106813Ssimokawa List<Type> bounds = types.subst(types.getBounds((TypeVar)formals.head), 543106813Ssimokawa pmt.tvars, typeargtypes); 544106813Ssimokawa for (; bounds.nonEmpty(); bounds = bounds.tail) { 545110072Ssimokawa if (!types.isSubtypeUnchecked(actuals.head, bounds.head, warn)) 546110582Ssimokawa throw inapplicableMethodException.setMessage("explicit.param.do.not.conform.to.bounds",actuals.head, bounds); 547106813Ssimokawa } 548108782Ssimokawa formals = formals.tail; 549108782Ssimokawa actuals = actuals.tail; 550106813Ssimokawa } 551121466Ssimokawa mt = types.subst(pmt.qtype, pmt.tvars, typeargtypes); 552106813Ssimokawa } else if (mt.hasTag(FORALL)) { 553120660Ssimokawa ForAll pmt = (ForAll) mt; 554106813Ssimokawa List<Type> tvars1 = types.newInstances(pmt.tvars); 555106813Ssimokawa tvars = tvars.appendList(tvars1); 556106813Ssimokawa mt = types.subst(pmt.qtype, pmt.tvars, tvars1); 557106813Ssimokawa } 558106813Ssimokawa 559106813Ssimokawa // find out whether we need to go the slow route via infer 560106813Ssimokawa boolean instNeeded = tvars.tail != null; /*inlined: tvars.nonEmpty()*/ 561106813Ssimokawa for (List<Type> l = argtypes; 562121466Ssimokawa l.tail != null/*inlined: l.nonEmpty()*/ && !instNeeded; 563120660Ssimokawa l = l.tail) { 564121466Ssimokawa if (l.head.hasTag(FORALL)) instNeeded = true; 565120660Ssimokawa } 566121466Ssimokawa 567121466Ssimokawa if (instNeeded) { 568106813Ssimokawa return infer.instantiateMethod(env, 569121466Ssimokawa tvars, 570121466Ssimokawa (MethodType)mt, 571121466Ssimokawa resultInfo, 572121466Ssimokawa (MethodSymbol)m, 573121466Ssimokawa argtypes, 574121466Ssimokawa allowBoxing, 575121466Ssimokawa useVarargs, 576121466Ssimokawa currentResolutionContext, 577106813Ssimokawa warn); 578121466Ssimokawa } 579121466Ssimokawa 580121466Ssimokawa DeferredAttr.DeferredAttrContext dc = currentResolutionContext.deferredAttrContext(m, infer.emptyContext, resultInfo, warn); 581121466Ssimokawa currentResolutionContext.methodCheck.argumentsAcceptable(env, dc, 582121466Ssimokawa argtypes, mt.getParameterTypes(), warn); 583121466Ssimokawa dc.complete(); 584121466Ssimokawa return mt; 585121466Ssimokawa } 586121466Ssimokawa 587121466Ssimokawa Type checkMethod(Env<AttrContext> env, 588121466Ssimokawa Type site, 589121466Ssimokawa Symbol m, 590121466Ssimokawa ResultInfo resultInfo, 591120660Ssimokawa List<Type> argtypes, 592106813Ssimokawa List<Type> typeargtypes, 593120660Ssimokawa Warner warn) { 594106813Ssimokawa MethodResolutionContext prevContext = currentResolutionContext; 595106813Ssimokawa try { 596106813Ssimokawa currentResolutionContext = new MethodResolutionContext(); 597106813Ssimokawa currentResolutionContext.attrMode = (resultInfo.pt == Infer.anyPoly) ? 598106813Ssimokawa AttrMode.SPECULATIVE : DeferredAttr.AttrMode.CHECK; 599106813Ssimokawa if (env.tree.hasTag(JCTree.Tag.REFERENCE)) { 600106813Ssimokawa //method/constructor references need special check class 601106813Ssimokawa //to handle inference variables in 'argtypes' (might happen 602106813Ssimokawa //during an unsticking round) 603106813Ssimokawa currentResolutionContext.methodCheck = 604106813Ssimokawa new MethodReferenceCheck(resultInfo.checkContext.inferenceContext()); 605118293Ssimokawa } 606110195Ssimokawa MethodResolutionPhase step = currentResolutionContext.step = env.info.pendingResolutionPhase; 607106813Ssimokawa return rawInstantiate(env, site, m, resultInfo, argtypes, typeargtypes, 608106813Ssimokawa step.isBoxingRequired(), step.isVarargsRequired(), warn); 609106813Ssimokawa } 610106813Ssimokawa finally { 611106813Ssimokawa currentResolutionContext = prevContext; 612106813Ssimokawa } 613106813Ssimokawa } 614106813Ssimokawa 615106813Ssimokawa /** Same but returns null instead throwing a NoInstanceException 616106813Ssimokawa */ 617110195Ssimokawa Type instantiate(Env<AttrContext> env, 618106813Ssimokawa Type site, 619106813Ssimokawa Symbol m, 620106813Ssimokawa ResultInfo resultInfo, 621106813Ssimokawa List<Type> argtypes, 622120660Ssimokawa List<Type> typeargtypes, 623120660Ssimokawa boolean allowBoxing, 624120660Ssimokawa boolean useVarargs, 625118293Ssimokawa Warner warn) { 626118293Ssimokawa try { 627113584Ssimokawa return rawInstantiate(env, site, m, resultInfo, argtypes, typeargtypes, 628106813Ssimokawa allowBoxing, useVarargs, warn); 629120660Ssimokawa } catch (InapplicableMethodException ex) { 630110269Ssimokawa return null; 631106813Ssimokawa } 632124836Ssimokawa } 633124836Ssimokawa 634106813Ssimokawa /** 635106813Ssimokawa * This interface defines an entry point that should be used to perform a 636106813Ssimokawa * method check. A method check usually consist in determining as to whether 637113584Ssimokawa * a set of types (actuals) is compatible with another set of types (formals). 638113584Ssimokawa * Since the notion of compatibility can vary depending on the circumstances, 639113584Ssimokawa * this interfaces allows to easily add new pluggable method check routines. 640113584Ssimokawa */ 641113584Ssimokawa interface MethodCheck { 642106813Ssimokawa /** 643106813Ssimokawa * Main method check routine. A method check usually consist in determining 644106813Ssimokawa * as to whether a set of types (actuals) is compatible with another set of 645109814Ssimokawa * types (formals). If an incompatibility is found, an unchecked exception 646109814Ssimokawa * is assumed to be thrown. 647109814Ssimokawa */ 648109814Ssimokawa void argumentsAcceptable(Env<AttrContext> env, 649109814Ssimokawa DeferredAttrContext deferredAttrContext, 650109814Ssimokawa List<Type> argtypes, 651109814Ssimokawa List<Type> formals, 652110193Ssimokawa Warner warn); 653109814Ssimokawa 654109814Ssimokawa /** 655109814Ssimokawa * Retrieve the method check object that will be used during a 656109814Ssimokawa * most specific check. 657109814Ssimokawa */ 658109814Ssimokawa MethodCheck mostSpecificCheck(List<Type> actuals); 659109814Ssimokawa } 660106813Ssimokawa 661106813Ssimokawa /** 662106813Ssimokawa * Helper enum defining all method check diagnostics (used by resolveMethodCheck). 663106813Ssimokawa */ 664109814Ssimokawa enum MethodCheckDiag { 665106813Ssimokawa /** 666106813Ssimokawa * Actuals and formals differs in length. 667106813Ssimokawa */ 668106813Ssimokawa ARITY_MISMATCH("arg.length.mismatch", "infer.arg.length.mismatch"), 669106813Ssimokawa /** 670106813Ssimokawa * An actual is incompatible with a formal. 671110193Ssimokawa */ 672110193Ssimokawa ARG_MISMATCH("no.conforming.assignment.exists", "infer.no.conforming.assignment.exists"), 673106813Ssimokawa /** 674106813Ssimokawa * An actual is incompatible with the varargs element type. 675117473Ssimokawa */ 676117473Ssimokawa VARARG_MISMATCH("varargs.argument.mismatch", "infer.varargs.argument.mismatch"), 677117473Ssimokawa /** 678117473Ssimokawa * The varargs element type is inaccessible. 679117473Ssimokawa */ 680117473Ssimokawa INACCESSIBLE_VARARGS("inaccessible.varargs.type", "inaccessible.varargs.type"); 681117473Ssimokawa 682117473Ssimokawa final String basicKey; 683117473Ssimokawa final String inferKey; 684117473Ssimokawa 685117473Ssimokawa MethodCheckDiag(String basicKey, String inferKey) { 686117473Ssimokawa this.basicKey = basicKey; 687117473Ssimokawa this.inferKey = inferKey; 688117473Ssimokawa } 689117473Ssimokawa 690117473Ssimokawa String regex() { 691117473Ssimokawa return String.format("([a-z]*\\.)*(%s|%s)", basicKey, inferKey); 692106813Ssimokawa } 693106813Ssimokawa } 694106813Ssimokawa 695106813Ssimokawa /** 696106813Ssimokawa * Dummy method check object. All methods are deemed applicable, regardless 697117473Ssimokawa * of their formal parameter types. 698117473Ssimokawa */ 699117473Ssimokawa MethodCheck nilMethodCheck = new MethodCheck() { 700117473Ssimokawa public void argumentsAcceptable(Env<AttrContext> env, DeferredAttrContext deferredAttrContext, List<Type> argtypes, List<Type> formals, Warner warn) { 701106813Ssimokawa //do nothing - method always applicable regardless of actuals 702106813Ssimokawa } 703106813Ssimokawa 704106813Ssimokawa public MethodCheck mostSpecificCheck(List<Type> actuals) { 705106813Ssimokawa return this; 706106813Ssimokawa } 707106813Ssimokawa }; 708106813Ssimokawa 709106813Ssimokawa /** 710106813Ssimokawa * Base class for 'real' method checks. The class defines the logic for 711118293Ssimokawa * iterating through formals and actuals and provides and entry point 712118293Ssimokawa * that can be used by subclasses in order to define the actual check logic. 713106813Ssimokawa */ 714106813Ssimokawa abstract class AbstractMethodCheck implements MethodCheck { 715106813Ssimokawa @Override 716106813Ssimokawa public void argumentsAcceptable(final Env<AttrContext> env, 717106813Ssimokawa DeferredAttrContext deferredAttrContext, 718106813Ssimokawa List<Type> argtypes, 719106813Ssimokawa List<Type> formals, 720106813Ssimokawa Warner warn) { 721118293Ssimokawa //should we expand formals? 722106813Ssimokawa boolean useVarargs = deferredAttrContext.phase.isVarargsRequired(); 723106813Ssimokawa JCTree callTree = treeForDiagnostics(env); 724106813Ssimokawa List<JCExpression> trees = TreeInfo.args(callTree); 725118293Ssimokawa 726106813Ssimokawa //inference context used during this method check 727106813Ssimokawa InferenceContext inferenceContext = deferredAttrContext.inferenceContext; 728118293Ssimokawa 729106813Ssimokawa Type varargsFormal = useVarargs ? formals.last() : null; 730106813Ssimokawa 731106813Ssimokawa if (varargsFormal == null && 732106813Ssimokawa argtypes.size() != formals.size()) { 733106813Ssimokawa reportMC(callTree, MethodCheckDiag.ARITY_MISMATCH, inferenceContext); // not enough args 734106813Ssimokawa } 735106813Ssimokawa 736106813Ssimokawa while (argtypes.nonEmpty() && formals.head != varargsFormal) { 737106813Ssimokawa DiagnosticPosition pos = trees != null ? trees.head : null; 738106813Ssimokawa checkArg(pos, false, argtypes.head, formals.head, deferredAttrContext, warn); 739106813Ssimokawa argtypes = argtypes.tail; 740113584Ssimokawa formals = formals.tail; 741111615Ssimokawa trees = trees != null ? trees.tail : trees; 742111615Ssimokawa } 743113584Ssimokawa 744111615Ssimokawa if (formals.head != varargsFormal) { 745106813Ssimokawa reportMC(callTree, MethodCheckDiag.ARITY_MISMATCH, inferenceContext); // not enough args 746118455Ssimokawa } 747106813Ssimokawa 748106813Ssimokawa if (useVarargs) { 749106813Ssimokawa //note: if applicability check is triggered by most specific test, 750113584Ssimokawa //the last argument of a varargs is _not_ an array type (see JLS 15.12.2.5) 751111615Ssimokawa final Type elt = types.elemtype(varargsFormal); 752111615Ssimokawa while (argtypes.nonEmpty()) { 753111462Smux DiagnosticPosition pos = trees != null ? trees.head : null; 754111615Ssimokawa checkArg(pos, true, argtypes.head, elt, deferredAttrContext, warn); 755106813Ssimokawa argtypes = argtypes.tail; 756118455Ssimokawa trees = trees != null ? trees.tail : trees; 757106813Ssimokawa } 758106813Ssimokawa } 759106813Ssimokawa } 760118455Ssimokawa 761120660Ssimokawa // where 762120660Ssimokawa private JCTree treeForDiagnostics(Env<AttrContext> env) { 763120660Ssimokawa return env.info.preferredTreeForDiagnostics != null ? env.info.preferredTreeForDiagnostics : env.tree; 764120660Ssimokawa } 765120660Ssimokawa 766120660Ssimokawa /** 767120660Ssimokawa * Does the actual argument conforms to the corresponding formal? 768120660Ssimokawa */ 769120660Ssimokawa abstract void checkArg(DiagnosticPosition pos, boolean varargs, Type actual, Type formal, DeferredAttrContext deferredAttrContext, Warner warn); 770120660Ssimokawa 771120660Ssimokawa protected void reportMC(DiagnosticPosition pos, MethodCheckDiag diag, InferenceContext inferenceContext, Object... args) { 772120660Ssimokawa boolean inferDiag = inferenceContext != infer.emptyContext; 773120660Ssimokawa InapplicableMethodException ex = inferDiag ? 774120660Ssimokawa infer.inferenceException : inapplicableMethodException; 775120660Ssimokawa if (inferDiag && (!diag.inferKey.equals(diag.basicKey))) { 776120660Ssimokawa Object[] args2 = new Object[args.length + 1]; 777120660Ssimokawa System.arraycopy(args, 0, args2, 1, args.length); 778118455Ssimokawa args2[0] = inferenceContext.inferenceVars(); 779118455Ssimokawa args = args2; 780118455Ssimokawa } 781118455Ssimokawa String key = inferDiag ? diag.inferKey : diag.basicKey; 782118455Ssimokawa throw ex.setMessage(diags.create(DiagnosticType.FRAGMENT, log.currentSource(), pos, key, args)); 783118455Ssimokawa } 784118455Ssimokawa 785118455Ssimokawa public MethodCheck mostSpecificCheck(List<Type> actuals) { 786118455Ssimokawa return nilMethodCheck; 787118455Ssimokawa } 788118455Ssimokawa 789118455Ssimokawa } 790118455Ssimokawa 791118455Ssimokawa /** 792118455Ssimokawa * Arity-based method check. A method is applicable if the number of actuals 793118455Ssimokawa * supplied conforms to the method signature. 794118455Ssimokawa */ 795118455Ssimokawa MethodCheck arityMethodCheck = new AbstractMethodCheck() { 796118455Ssimokawa @Override 797118455Ssimokawa void checkArg(DiagnosticPosition pos, boolean varargs, Type actual, Type formal, DeferredAttrContext deferredAttrContext, Warner warn) { 798118455Ssimokawa //do nothing - actual always compatible to formals 799118455Ssimokawa } 800118455Ssimokawa 801118455Ssimokawa @Override 802118455Ssimokawa public String toString() { 803118455Ssimokawa return "arityMethodCheck"; 804118455Ssimokawa } 805118455Ssimokawa }; 806118455Ssimokawa 807118455Ssimokawa List<Type> dummyArgs(int length) { 808118455Ssimokawa ListBuffer<Type> buf = new ListBuffer<>(); 809118455Ssimokawa for (int i = 0 ; i < length ; i++) { 810118455Ssimokawa buf.append(Type.noType); 811118455Ssimokawa } 812118455Ssimokawa return buf.toList(); 813118455Ssimokawa } 814118455Ssimokawa 815118455Ssimokawa /** 816118455Ssimokawa * Main method applicability routine. Given a list of actual types A, 817118455Ssimokawa * a list of formal types F, determines whether the types in A are 818118455Ssimokawa * compatible (by method invocation conversion) with the types in F. 819118455Ssimokawa * 820118455Ssimokawa * Since this routine is shared between overload resolution and method 821118455Ssimokawa * type-inference, a (possibly empty) inference context is used to convert 822118455Ssimokawa * formal types to the corresponding 'undet' form ahead of a compatibility 823118455Ssimokawa * check so that constraints can be propagated and collected. 824118455Ssimokawa * 825118455Ssimokawa * Moreover, if one or more types in A is a deferred type, this routine uses 826118455Ssimokawa * DeferredAttr in order to perform deferred attribution. If one or more actual 827118455Ssimokawa * deferred types are stuck, they are placed in a queue and revisited later 828118455Ssimokawa * after the remainder of the arguments have been seen. If this is not sufficient 829118455Ssimokawa * to 'unstuck' the argument, a cyclic inference error is called out. 830118455Ssimokawa * 831118455Ssimokawa * A method check handler (see above) is used in order to report errors. 832118455Ssimokawa */ 833120624Ssimokawa MethodCheck resolveMethodCheck = new AbstractMethodCheck() { 834118455Ssimokawa 835118455Ssimokawa @Override 836118455Ssimokawa void checkArg(DiagnosticPosition pos, boolean varargs, Type actual, Type formal, DeferredAttrContext deferredAttrContext, Warner warn) { 837118455Ssimokawa ResultInfo mresult = methodCheckResult(varargs, formal, deferredAttrContext, warn); 838118455Ssimokawa mresult.check(pos, actual); 839118455Ssimokawa } 840118455Ssimokawa 841118455Ssimokawa @Override 842118455Ssimokawa public void argumentsAcceptable(final Env<AttrContext> env, 843118455Ssimokawa DeferredAttrContext deferredAttrContext, 844118455Ssimokawa List<Type> argtypes, 845118455Ssimokawa List<Type> formals, 846118455Ssimokawa Warner warn) { 847118455Ssimokawa super.argumentsAcceptable(env, deferredAttrContext, argtypes, formals, warn); 848118455Ssimokawa // should we check varargs element type accessibility? 849118455Ssimokawa if (deferredAttrContext.phase.isVarargsRequired()) { 850118455Ssimokawa if (deferredAttrContext.mode == AttrMode.CHECK || !checkVarargsAccessAfterResolution) { 851118455Ssimokawa varargsAccessible(env, types.elemtype(formals.last()), deferredAttrContext.inferenceContext); 852118455Ssimokawa } 853118455Ssimokawa } 854118455Ssimokawa } 855118455Ssimokawa 856118455Ssimokawa /** 857118455Ssimokawa * Test that the runtime array element type corresponding to 't' is accessible. 't' should be the 858118455Ssimokawa * varargs element type of either the method invocation type signature (after inference completes) 859118455Ssimokawa * or the method declaration signature (before inference completes). 860118455Ssimokawa */ 861 private void varargsAccessible(final Env<AttrContext> env, final Type t, final InferenceContext inferenceContext) { 862 if (inferenceContext.free(t)) { 863 inferenceContext.addFreeTypeListener(List.of(t), new FreeTypeListener() { 864 @Override 865 public void typesInferred(InferenceContext inferenceContext) { 866 varargsAccessible(env, inferenceContext.asInstType(t), inferenceContext); 867 } 868 }); 869 } else { 870 if (!isAccessible(env, types.erasure(t))) { 871 Symbol location = env.enclClass.sym; 872 reportMC(env.tree, MethodCheckDiag.INACCESSIBLE_VARARGS, inferenceContext, t, Kinds.kindName(location), location); 873 } 874 } 875 } 876 877 private ResultInfo methodCheckResult(final boolean varargsCheck, Type to, 878 final DeferredAttr.DeferredAttrContext deferredAttrContext, Warner rsWarner) { 879 CheckContext checkContext = new MethodCheckContext(!deferredAttrContext.phase.isBoxingRequired(), deferredAttrContext, rsWarner) { 880 MethodCheckDiag methodDiag = varargsCheck ? 881 MethodCheckDiag.VARARG_MISMATCH : MethodCheckDiag.ARG_MISMATCH; 882 883 @Override 884 public void report(DiagnosticPosition pos, JCDiagnostic details) { 885 reportMC(pos, methodDiag, deferredAttrContext.inferenceContext, details); 886 } 887 }; 888 return new MethodResultInfo(to, checkContext); 889 } 890 891 @Override 892 public MethodCheck mostSpecificCheck(List<Type> actuals) { 893 return new MostSpecificCheck(actuals); 894 } 895 896 @Override 897 public String toString() { 898 return "resolveMethodCheck"; 899 } 900 }; 901 902 /** 903 * This class handles method reference applicability checks; since during 904 * these checks it's sometime possible to have inference variables on 905 * the actual argument types list, the method applicability check must be 906 * extended so that inference variables are 'opened' as needed. 907 */ 908 class MethodReferenceCheck extends AbstractMethodCheck { 909 910 InferenceContext pendingInferenceContext; 911 912 MethodReferenceCheck(InferenceContext pendingInferenceContext) { 913 this.pendingInferenceContext = pendingInferenceContext; 914 } 915 916 @Override 917 void checkArg(DiagnosticPosition pos, boolean varargs, Type actual, Type formal, DeferredAttrContext deferredAttrContext, Warner warn) { 918 ResultInfo mresult = methodCheckResult(varargs, formal, deferredAttrContext, warn); 919 mresult.check(pos, actual); 920 } 921 922 private ResultInfo methodCheckResult(final boolean varargsCheck, Type to, 923 final DeferredAttr.DeferredAttrContext deferredAttrContext, Warner rsWarner) { 924 CheckContext checkContext = new MethodCheckContext(!deferredAttrContext.phase.isBoxingRequired(), deferredAttrContext, rsWarner) { 925 MethodCheckDiag methodDiag = varargsCheck ? 926 MethodCheckDiag.VARARG_MISMATCH : MethodCheckDiag.ARG_MISMATCH; 927 928 @Override 929 public boolean compatible(Type found, Type req, Warner warn) { 930 found = pendingInferenceContext.asUndetVar(found); 931 if (found.hasTag(UNDETVAR) && req.isPrimitive()) { 932 req = types.boxedClass(req).type; 933 } 934 return super.compatible(found, req, warn); 935 } 936 937 @Override 938 public void report(DiagnosticPosition pos, JCDiagnostic details) { 939 reportMC(pos, methodDiag, deferredAttrContext.inferenceContext, details); 940 } 941 }; 942 return new MethodResultInfo(to, checkContext); 943 } 944 945 @Override 946 public MethodCheck mostSpecificCheck(List<Type> actuals) { 947 return new MostSpecificCheck(actuals); 948 } 949 950 @Override 951 public String toString() { 952 return "MethodReferenceCheck"; 953 } 954 } 955 956 /** 957 * Check context to be used during method applicability checks. A method check 958 * context might contain inference variables. 959 */ 960 abstract class MethodCheckContext implements CheckContext { 961 962 boolean strict; 963 DeferredAttrContext deferredAttrContext; 964 Warner rsWarner; 965 966 public MethodCheckContext(boolean strict, DeferredAttrContext deferredAttrContext, Warner rsWarner) { 967 this.strict = strict; 968 this.deferredAttrContext = deferredAttrContext; 969 this.rsWarner = rsWarner; 970 } 971 972 public boolean compatible(Type found, Type req, Warner warn) { 973 InferenceContext inferenceContext = deferredAttrContext.inferenceContext; 974 return strict ? 975 types.isSubtypeUnchecked(inferenceContext.asUndetVar(found), inferenceContext.asUndetVar(req), warn) : 976 types.isConvertible(inferenceContext.asUndetVar(found), inferenceContext.asUndetVar(req), warn); 977 } 978 979 public void report(DiagnosticPosition pos, JCDiagnostic details) { 980 throw inapplicableMethodException.setMessage(details); 981 } 982 983 public Warner checkWarner(DiagnosticPosition pos, Type found, Type req) { 984 return rsWarner; 985 } 986 987 public InferenceContext inferenceContext() { 988 return deferredAttrContext.inferenceContext; 989 } 990 991 public DeferredAttrContext deferredAttrContext() { 992 return deferredAttrContext; 993 } 994 995 @Override 996 public String toString() { 997 return "MethodCheckContext"; 998 } 999 } 1000 1001 /** 1002 * ResultInfo class to be used during method applicability checks. Check 1003 * for deferred types goes through special path. 1004 */ 1005 class MethodResultInfo extends ResultInfo { 1006 1007 public MethodResultInfo(Type pt, CheckContext checkContext) { 1008 attr.super(KindSelector.VAL, pt, checkContext); 1009 } 1010 1011 @Override 1012 protected Type check(DiagnosticPosition pos, Type found) { 1013 if (found.hasTag(DEFERRED)) { 1014 DeferredType dt = (DeferredType)found; 1015 return dt.check(this); 1016 } else { 1017 Type uResult = U(found); 1018 Type capturedType = pos == null || pos.getTree() == null ? 1019 types.capture(uResult) : 1020 checkContext.inferenceContext() 1021 .cachedCapture(pos.getTree(), uResult, true); 1022 return super.check(pos, chk.checkNonVoid(pos, capturedType)); 1023 } 1024 } 1025 1026 /** 1027 * javac has a long-standing 'simplification' (see 6391995): 1028 * given an actual argument type, the method check is performed 1029 * on its upper bound. This leads to inconsistencies when an 1030 * argument type is checked against itself. For example, given 1031 * a type-variable T, it is not true that {@code U(T) <: T}, 1032 * so we need to guard against that. 1033 */ 1034 private Type U(Type found) { 1035 return found == pt ? 1036 found : types.cvarUpperBound(found); 1037 } 1038 1039 @Override 1040 protected MethodResultInfo dup(Type newPt) { 1041 return new MethodResultInfo(newPt, checkContext); 1042 } 1043 1044 @Override 1045 protected ResultInfo dup(CheckContext newContext) { 1046 return new MethodResultInfo(pt, newContext); 1047 } 1048 1049 @Override 1050 protected ResultInfo dup(Type newPt, CheckContext newContext) { 1051 return new MethodResultInfo(newPt, newContext); 1052 } 1053 } 1054 1055 /** 1056 * Most specific method applicability routine. Given a list of actual types A, 1057 * a list of formal types F1, and a list of formal types F2, the routine determines 1058 * as to whether the types in F1 can be considered more specific than those in F2 w.r.t. 1059 * argument types A. 1060 */ 1061 class MostSpecificCheck implements MethodCheck { 1062 1063 List<Type> actuals; 1064 1065 MostSpecificCheck(List<Type> actuals) { 1066 this.actuals = actuals; 1067 } 1068 1069 @Override 1070 public void argumentsAcceptable(final Env<AttrContext> env, 1071 DeferredAttrContext deferredAttrContext, 1072 List<Type> formals1, 1073 List<Type> formals2, 1074 Warner warn) { 1075 formals2 = adjustArgs(formals2, deferredAttrContext.msym, formals1.length(), deferredAttrContext.phase.isVarargsRequired()); 1076 while (formals2.nonEmpty()) { 1077 ResultInfo mresult = methodCheckResult(formals2.head, deferredAttrContext, warn, actuals.head); 1078 mresult.check(null, formals1.head); 1079 formals1 = formals1.tail; 1080 formals2 = formals2.tail; 1081 actuals = actuals.isEmpty() ? actuals : actuals.tail; 1082 } 1083 } 1084 1085 /** 1086 * Create a method check context to be used during the most specific applicability check 1087 */ 1088 ResultInfo methodCheckResult(Type to, DeferredAttr.DeferredAttrContext deferredAttrContext, 1089 Warner rsWarner, Type actual) { 1090 return attr.new ResultInfo(KindSelector.VAL, to, 1091 new MostSpecificCheckContext(deferredAttrContext, rsWarner, actual)); 1092 } 1093 1094 /** 1095 * Subclass of method check context class that implements most specific 1096 * method conversion. If the actual type under analysis is a deferred type 1097 * a full blown structural analysis is carried out. 1098 */ 1099 class MostSpecificCheckContext extends MethodCheckContext { 1100 1101 Type actual; 1102 1103 public MostSpecificCheckContext(DeferredAttrContext deferredAttrContext, Warner rsWarner, Type actual) { 1104 super(true, deferredAttrContext, rsWarner); 1105 this.actual = actual; 1106 } 1107 1108 public boolean compatible(Type found, Type req, Warner warn) { 1109 if (allowFunctionalInterfaceMostSpecific && 1110 unrelatedFunctionalInterfaces(found, req) && 1111 (actual != null && actual.getTag() == DEFERRED)) { 1112 DeferredType dt = (DeferredType) actual; 1113 JCTree speculativeTree = dt.speculativeTree(deferredAttrContext); 1114 if (speculativeTree != deferredAttr.stuckTree) { 1115 return functionalInterfaceMostSpecific(found, req, speculativeTree); 1116 } 1117 } 1118 return compatibleBySubtyping(found, req); 1119 } 1120 1121 private boolean compatibleBySubtyping(Type found, Type req) { 1122 if (!strict && found.isPrimitive() != req.isPrimitive()) { 1123 found = found.isPrimitive() ? types.boxedClass(found).type : types.unboxedType(found); 1124 } 1125 return types.isSubtypeNoCapture(found, deferredAttrContext.inferenceContext.asUndetVar(req)); 1126 } 1127 1128 /** Whether {@code t} and {@code s} are unrelated functional interface types. */ 1129 private boolean unrelatedFunctionalInterfaces(Type t, Type s) { 1130 return types.isFunctionalInterface(t.tsym) && 1131 types.isFunctionalInterface(s.tsym) && 1132 types.asSuper(t, s.tsym) == null && 1133 types.asSuper(s, t.tsym) == null; 1134 } 1135 1136 /** Parameters {@code t} and {@code s} are unrelated functional interface types. */ 1137 private boolean functionalInterfaceMostSpecific(Type t, Type s, JCTree tree) { 1138 Type tDesc = types.findDescriptorType(t); 1139 Type sDesc = types.findDescriptorType(s); 1140 1141 // compare type parameters -- can't use Types.hasSameBounds because bounds may have ivars 1142 final List<Type> tTypeParams = tDesc.getTypeArguments(); 1143 final List<Type> sTypeParams = sDesc.getTypeArguments(); 1144 List<Type> tIter = tTypeParams; 1145 List<Type> sIter = sTypeParams; 1146 while (tIter.nonEmpty() && sIter.nonEmpty()) { 1147 Type tBound = tIter.head.getUpperBound(); 1148 Type sBound = types.subst(sIter.head.getUpperBound(), sTypeParams, tTypeParams); 1149 if (tBound.containsAny(tTypeParams) && inferenceContext().free(sBound)) { 1150 return false; 1151 } 1152 if (!types.isSameType(tBound, inferenceContext().asUndetVar(sBound))) { 1153 return false; 1154 } 1155 tIter = tIter.tail; 1156 sIter = sIter.tail; 1157 } 1158 if (!tIter.isEmpty() || !sIter.isEmpty()) { 1159 return false; 1160 } 1161 1162 // compare parameters 1163 List<Type> tParams = tDesc.getParameterTypes(); 1164 List<Type> sParams = sDesc.getParameterTypes(); 1165 while (tParams.nonEmpty() && sParams.nonEmpty()) { 1166 Type tParam = tParams.head; 1167 Type sParam = types.subst(sParams.head, sTypeParams, tTypeParams); 1168 if (tParam.containsAny(tTypeParams) && inferenceContext().free(sParam)) { 1169 return false; 1170 } 1171 if (!types.isSameType(tParam, inferenceContext().asUndetVar(sParam))) { 1172 return false; 1173 } 1174 tParams = tParams.tail; 1175 sParams = sParams.tail; 1176 } 1177 if (!tParams.isEmpty() || !sParams.isEmpty()) { 1178 return false; 1179 } 1180 1181 // compare returns 1182 Type tRet = tDesc.getReturnType(); 1183 Type sRet = types.subst(sDesc.getReturnType(), sTypeParams, tTypeParams); 1184 if (tRet.containsAny(tTypeParams) && inferenceContext().free(sRet)) { 1185 return false; 1186 } 1187 MostSpecificFunctionReturnChecker msc = new MostSpecificFunctionReturnChecker(tRet, sRet); 1188 msc.scan(tree); 1189 return msc.result; 1190 } 1191 1192 /** 1193 * Tests whether one functional interface type can be considered more specific 1194 * than another unrelated functional interface type for the scanned expression. 1195 */ 1196 class MostSpecificFunctionReturnChecker extends DeferredAttr.PolyScanner { 1197 1198 final Type tRet; 1199 final Type sRet; 1200 boolean result; 1201 1202 /** Parameters {@code t} and {@code s} are unrelated functional interface types. */ 1203 MostSpecificFunctionReturnChecker(Type tRet, Type sRet) { 1204 this.tRet = tRet; 1205 this.sRet = sRet; 1206 result = true; 1207 } 1208 1209 @Override 1210 void skip(JCTree tree) { 1211 result &= false; 1212 } 1213 1214 @Override 1215 public void visitConditional(JCConditional tree) { 1216 scan(asExpr(tree.truepart)); 1217 scan(asExpr(tree.falsepart)); 1218 } 1219 1220 @Override 1221 public void visitReference(JCMemberReference tree) { 1222 if (sRet.hasTag(VOID)) { 1223 result &= true; 1224 } else if (tRet.hasTag(VOID)) { 1225 result &= false; 1226 } else if (tRet.isPrimitive() != sRet.isPrimitive()) { 1227 boolean retValIsPrimitive = 1228 tree.refPolyKind == PolyKind.STANDALONE && 1229 tree.sym.type.getReturnType().isPrimitive(); 1230 result &= (retValIsPrimitive == tRet.isPrimitive()) && 1231 (retValIsPrimitive != sRet.isPrimitive()); 1232 } else { 1233 result &= compatibleBySubtyping(tRet, sRet); 1234 } 1235 } 1236 1237 @Override 1238 public void visitParens(JCParens tree) { 1239 scan(asExpr(tree.expr)); 1240 } 1241 1242 @Override 1243 public void visitLambda(JCLambda tree) { 1244 if (sRet.hasTag(VOID)) { 1245 result &= true; 1246 } else if (tRet.hasTag(VOID)) { 1247 result &= false; 1248 } else { 1249 List<JCExpression> lambdaResults = lambdaResults(tree); 1250 if (!lambdaResults.isEmpty() && unrelatedFunctionalInterfaces(tRet, sRet)) { 1251 for (JCExpression expr : lambdaResults) { 1252 result &= functionalInterfaceMostSpecific(tRet, sRet, expr); 1253 } 1254 } else if (!lambdaResults.isEmpty() && tRet.isPrimitive() != sRet.isPrimitive()) { 1255 for (JCExpression expr : lambdaResults) { 1256 boolean retValIsPrimitive = expr.isStandalone() && expr.type.isPrimitive(); 1257 result &= (retValIsPrimitive == tRet.isPrimitive()) && 1258 (retValIsPrimitive != sRet.isPrimitive()); 1259 } 1260 } else { 1261 result &= compatibleBySubtyping(tRet, sRet); 1262 } 1263 } 1264 } 1265 //where 1266 1267 private List<JCExpression> lambdaResults(JCLambda lambda) { 1268 if (lambda.getBodyKind() == JCTree.JCLambda.BodyKind.EXPRESSION) { 1269 return List.of(asExpr((JCExpression) lambda.body)); 1270 } else { 1271 final ListBuffer<JCExpression> buffer = new ListBuffer<>(); 1272 DeferredAttr.LambdaReturnScanner lambdaScanner = 1273 new DeferredAttr.LambdaReturnScanner() { 1274 @Override 1275 public void visitReturn(JCReturn tree) { 1276 if (tree.expr != null) { 1277 buffer.append(asExpr(tree.expr)); 1278 } 1279 } 1280 }; 1281 lambdaScanner.scan(lambda.body); 1282 return buffer.toList(); 1283 } 1284 } 1285 1286 private JCExpression asExpr(JCExpression expr) { 1287 if (expr.type.hasTag(DEFERRED)) { 1288 JCTree speculativeTree = ((DeferredType)expr.type).speculativeTree(deferredAttrContext); 1289 if (speculativeTree != deferredAttr.stuckTree) { 1290 expr = (JCExpression)speculativeTree; 1291 } 1292 } 1293 return expr; 1294 } 1295 } 1296 1297 } 1298 1299 public MethodCheck mostSpecificCheck(List<Type> actuals) { 1300 Assert.error("Cannot get here!"); 1301 return null; 1302 } 1303 } 1304 1305 public static class InapplicableMethodException extends RuntimeException { 1306 private static final long serialVersionUID = 0; 1307 1308 JCDiagnostic diagnostic; 1309 JCDiagnostic.Factory diags; 1310 1311 InapplicableMethodException(JCDiagnostic.Factory diags) { 1312 this.diagnostic = null; 1313 this.diags = diags; 1314 } 1315 InapplicableMethodException setMessage() { 1316 return setMessage((JCDiagnostic)null); 1317 } 1318 InapplicableMethodException setMessage(String key) { 1319 return setMessage(key != null ? diags.fragment(key) : null); 1320 } 1321 InapplicableMethodException setMessage(String key, Object... args) { 1322 return setMessage(key != null ? diags.fragment(key, args) : null); 1323 } 1324 InapplicableMethodException setMessage(JCDiagnostic diag) { 1325 this.diagnostic = diag; 1326 return this; 1327 } 1328 1329 public JCDiagnostic getDiagnostic() { 1330 return diagnostic; 1331 } 1332 } 1333 private final InapplicableMethodException inapplicableMethodException; 1334 1335/* *************************************************************************** 1336 * Symbol lookup 1337 * the following naming conventions for arguments are used 1338 * 1339 * env is the environment where the symbol was mentioned 1340 * site is the type of which the symbol is a member 1341 * name is the symbol's name 1342 * if no arguments are given 1343 * argtypes are the value arguments, if we search for a method 1344 * 1345 * If no symbol was found, a ResolveError detailing the problem is returned. 1346 ****************************************************************************/ 1347 1348 /** Find field. Synthetic fields are always skipped. 1349 * @param env The current environment. 1350 * @param site The original type from where the selection takes place. 1351 * @param name The name of the field. 1352 * @param c The class to search for the field. This is always 1353 * a superclass or implemented interface of site's class. 1354 */ 1355 Symbol findField(Env<AttrContext> env, 1356 Type site, 1357 Name name, 1358 TypeSymbol c) { 1359 while (c.type.hasTag(TYPEVAR)) 1360 c = c.type.getUpperBound().tsym; 1361 Symbol bestSoFar = varNotFound; 1362 Symbol sym; 1363 for (Symbol s : c.members().getSymbolsByName(name)) { 1364 if (s.kind == VAR && (s.flags_field & SYNTHETIC) == 0) { 1365 return isAccessible(env, site, s) 1366 ? s : new AccessError(env, site, s); 1367 } 1368 } 1369 Type st = types.supertype(c.type); 1370 if (st != null && (st.hasTag(CLASS) || st.hasTag(TYPEVAR))) { 1371 sym = findField(env, site, name, st.tsym); 1372 bestSoFar = bestOf(bestSoFar, sym); 1373 } 1374 for (List<Type> l = types.interfaces(c.type); 1375 bestSoFar.kind != AMBIGUOUS && l.nonEmpty(); 1376 l = l.tail) { 1377 sym = findField(env, site, name, l.head.tsym); 1378 if (bestSoFar.exists() && sym.exists() && 1379 sym.owner != bestSoFar.owner) 1380 bestSoFar = new AmbiguityError(bestSoFar, sym); 1381 else 1382 bestSoFar = bestOf(bestSoFar, sym); 1383 } 1384 return bestSoFar; 1385 } 1386 1387 /** Resolve a field identifier, throw a fatal error if not found. 1388 * @param pos The position to use for error reporting. 1389 * @param env The environment current at the method invocation. 1390 * @param site The type of the qualifying expression, in which 1391 * identifier is searched. 1392 * @param name The identifier's name. 1393 */ 1394 public VarSymbol resolveInternalField(DiagnosticPosition pos, Env<AttrContext> env, 1395 Type site, Name name) { 1396 Symbol sym = findField(env, site, name, site.tsym); 1397 if (sym.kind == VAR) return (VarSymbol)sym; 1398 else throw new FatalError( 1399 diags.fragment("fatal.err.cant.locate.field", 1400 name)); 1401 } 1402 1403 /** Find unqualified variable or field with given name. 1404 * Synthetic fields always skipped. 1405 * @param env The current environment. 1406 * @param name The name of the variable or field. 1407 */ 1408 Symbol findVar(Env<AttrContext> env, Name name) { 1409 Symbol bestSoFar = varNotFound; 1410 Env<AttrContext> env1 = env; 1411 boolean staticOnly = false; 1412 while (env1.outer != null) { 1413 Symbol sym = null; 1414 if (isStatic(env1)) staticOnly = true; 1415 for (Symbol s : env1.info.scope.getSymbolsByName(name)) { 1416 if (s.kind == VAR && (s.flags_field & SYNTHETIC) == 0) { 1417 sym = s; 1418 break; 1419 } 1420 } 1421 if (sym == null) { 1422 sym = findField(env1, env1.enclClass.sym.type, name, env1.enclClass.sym); 1423 } 1424 if (sym.exists()) { 1425 if (staticOnly && 1426 sym.kind == VAR && 1427 sym.owner.kind == TYP && 1428 (sym.flags() & STATIC) == 0) 1429 return new StaticError(sym); 1430 else 1431 return sym; 1432 } else { 1433 bestSoFar = bestOf(bestSoFar, sym); 1434 } 1435 1436 if ((env1.enclClass.sym.flags() & STATIC) != 0) staticOnly = true; 1437 env1 = env1.outer; 1438 } 1439 1440 Symbol sym = findField(env, syms.predefClass.type, name, syms.predefClass); 1441 if (sym.exists()) 1442 return sym; 1443 if (bestSoFar.exists()) 1444 return bestSoFar; 1445 1446 Symbol origin = null; 1447 for (Scope sc : new Scope[] { env.toplevel.namedImportScope, env.toplevel.starImportScope }) { 1448 for (Symbol currentSymbol : sc.getSymbolsByName(name)) { 1449 if (currentSymbol.kind != VAR) 1450 continue; 1451 // invariant: sym.kind == Symbol.Kind.VAR 1452 if (!bestSoFar.kind.isResolutionError() && 1453 currentSymbol.owner != bestSoFar.owner) 1454 return new AmbiguityError(bestSoFar, currentSymbol); 1455 else if (!bestSoFar.kind.betterThan(VAR)) { 1456 origin = sc.getOrigin(currentSymbol).owner; 1457 bestSoFar = isAccessible(env, origin.type, currentSymbol) 1458 ? currentSymbol : new AccessError(env, origin.type, currentSymbol); 1459 } 1460 } 1461 if (bestSoFar.exists()) break; 1462 } 1463 if (bestSoFar.kind == VAR && bestSoFar.owner.type != origin.type) 1464 return bestSoFar.clone(origin); 1465 else 1466 return bestSoFar; 1467 } 1468 1469 Warner noteWarner = new Warner(); 1470 1471 /** Select the best method for a call site among two choices. 1472 * @param env The current environment. 1473 * @param site The original type from where the 1474 * selection takes place. 1475 * @param argtypes The invocation's value arguments, 1476 * @param typeargtypes The invocation's type arguments, 1477 * @param sym Proposed new best match. 1478 * @param bestSoFar Previously found best match. 1479 * @param allowBoxing Allow boxing conversions of arguments. 1480 * @param useVarargs Box trailing arguments into an array for varargs. 1481 */ 1482 @SuppressWarnings("fallthrough") 1483 Symbol selectBest(Env<AttrContext> env, 1484 Type site, 1485 List<Type> argtypes, 1486 List<Type> typeargtypes, 1487 Symbol sym, 1488 Symbol bestSoFar, 1489 boolean allowBoxing, 1490 boolean useVarargs) { 1491 if (sym.kind == ERR || 1492 !sym.isInheritedIn(site.tsym, types)) { 1493 return bestSoFar; 1494 } else if (useVarargs && (sym.flags() & VARARGS) == 0) { 1495 return bestSoFar.kind.isResolutionError() ? 1496 new BadVarargsMethod((ResolveError)bestSoFar.baseSymbol()) : 1497 bestSoFar; 1498 } 1499 Assert.check(!sym.kind.isResolutionError()); 1500 try { 1501 types.noWarnings.clear(); 1502 Type mt = rawInstantiate(env, site, sym, null, argtypes, typeargtypes, 1503 allowBoxing, useVarargs, types.noWarnings); 1504 currentResolutionContext.addApplicableCandidate(sym, mt); 1505 } catch (InapplicableMethodException ex) { 1506 currentResolutionContext.addInapplicableCandidate(sym, ex.getDiagnostic()); 1507 switch (bestSoFar.kind) { 1508 case ABSENT_MTH: 1509 return new InapplicableSymbolError(currentResolutionContext); 1510 case WRONG_MTH: 1511 bestSoFar = new InapplicableSymbolsError(currentResolutionContext); 1512 default: 1513 return bestSoFar; 1514 } 1515 } 1516 if (!isAccessible(env, site, sym)) { 1517 return (bestSoFar.kind == ABSENT_MTH) 1518 ? new AccessError(env, site, sym) 1519 : bestSoFar; 1520 } 1521 return (bestSoFar.kind.isResolutionError() && bestSoFar.kind != AMBIGUOUS) 1522 ? sym 1523 : mostSpecific(argtypes, sym, bestSoFar, env, site, useVarargs); 1524 } 1525 1526 /* Return the most specific of the two methods for a call, 1527 * given that both are accessible and applicable. 1528 * @param m1 A new candidate for most specific. 1529 * @param m2 The previous most specific candidate. 1530 * @param env The current environment. 1531 * @param site The original type from where the selection 1532 * takes place. 1533 * @param allowBoxing Allow boxing conversions of arguments. 1534 * @param useVarargs Box trailing arguments into an array for varargs. 1535 */ 1536 Symbol mostSpecific(List<Type> argtypes, Symbol m1, 1537 Symbol m2, 1538 Env<AttrContext> env, 1539 final Type site, 1540 boolean useVarargs) { 1541 switch (m2.kind) { 1542 case MTH: 1543 if (m1 == m2) return m1; 1544 boolean m1SignatureMoreSpecific = 1545 signatureMoreSpecific(argtypes, env, site, m1, m2, useVarargs); 1546 boolean m2SignatureMoreSpecific = 1547 signatureMoreSpecific(argtypes, env, site, m2, m1, useVarargs); 1548 if (m1SignatureMoreSpecific && m2SignatureMoreSpecific) { 1549 Type mt1 = types.memberType(site, m1); 1550 Type mt2 = types.memberType(site, m2); 1551 if (!types.overrideEquivalent(mt1, mt2)) 1552 return ambiguityError(m1, m2); 1553 1554 // same signature; select (a) the non-bridge method, or 1555 // (b) the one that overrides the other, or (c) the concrete 1556 // one, or (d) merge both abstract signatures 1557 if ((m1.flags() & BRIDGE) != (m2.flags() & BRIDGE)) 1558 return ((m1.flags() & BRIDGE) != 0) ? m2 : m1; 1559 1560 // if one overrides or hides the other, use it 1561 TypeSymbol m1Owner = (TypeSymbol)m1.owner; 1562 TypeSymbol m2Owner = (TypeSymbol)m2.owner; 1563 if (types.asSuper(m1Owner.type, m2Owner) != null && 1564 ((m1.owner.flags_field & INTERFACE) == 0 || 1565 (m2.owner.flags_field & INTERFACE) != 0) && 1566 m1.overrides(m2, m1Owner, types, false)) 1567 return m1; 1568 if (types.asSuper(m2Owner.type, m1Owner) != null && 1569 ((m2.owner.flags_field & INTERFACE) == 0 || 1570 (m1.owner.flags_field & INTERFACE) != 0) && 1571 m2.overrides(m1, m2Owner, types, false)) 1572 return m2; 1573 boolean m1Abstract = (m1.flags() & ABSTRACT) != 0; 1574 boolean m2Abstract = (m2.flags() & ABSTRACT) != 0; 1575 if (m1Abstract && !m2Abstract) return m2; 1576 if (m2Abstract && !m1Abstract) return m1; 1577 // both abstract or both concrete 1578 return ambiguityError(m1, m2); 1579 } 1580 if (m1SignatureMoreSpecific) return m1; 1581 if (m2SignatureMoreSpecific) return m2; 1582 return ambiguityError(m1, m2); 1583 case AMBIGUOUS: 1584 //compare m1 to ambiguous methods in m2 1585 AmbiguityError e = (AmbiguityError)m2.baseSymbol(); 1586 boolean m1MoreSpecificThanAnyAmbiguous = true; 1587 boolean allAmbiguousMoreSpecificThanM1 = true; 1588 for (Symbol s : e.ambiguousSyms) { 1589 Symbol moreSpecific = mostSpecific(argtypes, m1, s, env, site, useVarargs); 1590 m1MoreSpecificThanAnyAmbiguous &= moreSpecific == m1; 1591 allAmbiguousMoreSpecificThanM1 &= moreSpecific == s; 1592 } 1593 if (m1MoreSpecificThanAnyAmbiguous) 1594 return m1; 1595 //if m1 is more specific than some ambiguous methods, but other ambiguous methods are 1596 //more specific than m1, add it as a new ambiguous method: 1597 if (!allAmbiguousMoreSpecificThanM1) 1598 e.addAmbiguousSymbol(m1); 1599 return e; 1600 default: 1601 throw new AssertionError(); 1602 } 1603 } 1604 //where 1605 private boolean signatureMoreSpecific(List<Type> actuals, Env<AttrContext> env, Type site, Symbol m1, Symbol m2, boolean useVarargs) { 1606 noteWarner.clear(); 1607 int maxLength = Math.max( 1608 Math.max(m1.type.getParameterTypes().length(), actuals.length()), 1609 m2.type.getParameterTypes().length()); 1610 MethodResolutionContext prevResolutionContext = currentResolutionContext; 1611 try { 1612 currentResolutionContext = new MethodResolutionContext(); 1613 currentResolutionContext.step = prevResolutionContext.step; 1614 currentResolutionContext.methodCheck = 1615 prevResolutionContext.methodCheck.mostSpecificCheck(actuals); 1616 Type mst = instantiate(env, site, m2, null, 1617 adjustArgs(types.cvarLowerBounds(types.memberType(site, m1).getParameterTypes()), m1, maxLength, useVarargs), null, 1618 false, useVarargs, noteWarner); 1619 return mst != null && 1620 !noteWarner.hasLint(Lint.LintCategory.UNCHECKED); 1621 } finally { 1622 currentResolutionContext = prevResolutionContext; 1623 } 1624 } 1625 1626 List<Type> adjustArgs(List<Type> args, Symbol msym, int length, boolean allowVarargs) { 1627 if ((msym.flags() & VARARGS) != 0 && allowVarargs) { 1628 Type varargsElem = types.elemtype(args.last()); 1629 if (varargsElem == null) { 1630 Assert.error("Bad varargs = " + args.last() + " " + msym); 1631 } 1632 List<Type> newArgs = args.reverse().tail.prepend(varargsElem).reverse(); 1633 while (newArgs.length() < length) { 1634 newArgs = newArgs.append(newArgs.last()); 1635 } 1636 return newArgs; 1637 } else { 1638 return args; 1639 } 1640 } 1641 //where 1642 Type mostSpecificReturnType(Type mt1, Type mt2) { 1643 Type rt1 = mt1.getReturnType(); 1644 Type rt2 = mt2.getReturnType(); 1645 1646 if (mt1.hasTag(FORALL) && mt2.hasTag(FORALL)) { 1647 //if both are generic methods, adjust return type ahead of subtyping check 1648 rt1 = types.subst(rt1, mt1.getTypeArguments(), mt2.getTypeArguments()); 1649 } 1650 //first use subtyping, then return type substitutability 1651 if (types.isSubtype(rt1, rt2)) { 1652 return mt1; 1653 } else if (types.isSubtype(rt2, rt1)) { 1654 return mt2; 1655 } else if (types.returnTypeSubstitutable(mt1, mt2)) { 1656 return mt1; 1657 } else if (types.returnTypeSubstitutable(mt2, mt1)) { 1658 return mt2; 1659 } else { 1660 return null; 1661 } 1662 } 1663 //where 1664 Symbol ambiguityError(Symbol m1, Symbol m2) { 1665 if (((m1.flags() | m2.flags()) & CLASH) != 0) { 1666 return (m1.flags() & CLASH) == 0 ? m1 : m2; 1667 } else { 1668 return new AmbiguityError(m1, m2); 1669 } 1670 } 1671 1672 Symbol findMethodInScope(Env<AttrContext> env, 1673 Type site, 1674 Name name, 1675 List<Type> argtypes, 1676 List<Type> typeargtypes, 1677 Scope sc, 1678 Symbol bestSoFar, 1679 boolean allowBoxing, 1680 boolean useVarargs, 1681 boolean abstractok) { 1682 for (Symbol s : sc.getSymbolsByName(name, new LookupFilter(abstractok))) { 1683 bestSoFar = selectBest(env, site, argtypes, typeargtypes, s, 1684 bestSoFar, allowBoxing, useVarargs); 1685 } 1686 return bestSoFar; 1687 } 1688 //where 1689 class LookupFilter implements Filter<Symbol> { 1690 1691 boolean abstractOk; 1692 1693 LookupFilter(boolean abstractOk) { 1694 this.abstractOk = abstractOk; 1695 } 1696 1697 public boolean accepts(Symbol s) { 1698 long flags = s.flags(); 1699 return s.kind == MTH && 1700 (flags & SYNTHETIC) == 0 && 1701 (abstractOk || 1702 (flags & DEFAULT) != 0 || 1703 (flags & ABSTRACT) == 0); 1704 } 1705 } 1706 1707 /** Find best qualified method matching given name, type and value 1708 * arguments. 1709 * @param env The current environment. 1710 * @param site The original type from where the selection 1711 * takes place. 1712 * @param name The method's name. 1713 * @param argtypes The method's value arguments. 1714 * @param typeargtypes The method's type arguments 1715 * @param allowBoxing Allow boxing conversions of arguments. 1716 * @param useVarargs Box trailing arguments into an array for varargs. 1717 */ 1718 Symbol findMethod(Env<AttrContext> env, 1719 Type site, 1720 Name name, 1721 List<Type> argtypes, 1722 List<Type> typeargtypes, 1723 boolean allowBoxing, 1724 boolean useVarargs) { 1725 Symbol bestSoFar = methodNotFound; 1726 bestSoFar = findMethod(env, 1727 site, 1728 name, 1729 argtypes, 1730 typeargtypes, 1731 site.tsym.type, 1732 bestSoFar, 1733 allowBoxing, 1734 useVarargs); 1735 return bestSoFar; 1736 } 1737 // where 1738 private Symbol findMethod(Env<AttrContext> env, 1739 Type site, 1740 Name name, 1741 List<Type> argtypes, 1742 List<Type> typeargtypes, 1743 Type intype, 1744 Symbol bestSoFar, 1745 boolean allowBoxing, 1746 boolean useVarargs) { 1747 @SuppressWarnings({"unchecked","rawtypes"}) 1748 List<Type>[] itypes = (List<Type>[])new List[] { List.<Type>nil(), List.<Type>nil() }; 1749 1750 InterfaceLookupPhase iphase = InterfaceLookupPhase.ABSTRACT_OK; 1751 for (TypeSymbol s : superclasses(intype)) { 1752 bestSoFar = findMethodInScope(env, site, name, argtypes, typeargtypes, 1753 s.members(), bestSoFar, allowBoxing, useVarargs, true); 1754 if (name == names.init) return bestSoFar; 1755 iphase = (iphase == null) ? null : iphase.update(s, this); 1756 if (iphase != null) { 1757 for (Type itype : types.interfaces(s.type)) { 1758 itypes[iphase.ordinal()] = types.union(types.closure(itype), itypes[iphase.ordinal()]); 1759 } 1760 } 1761 } 1762 1763 Symbol concrete = bestSoFar.kind.isValid() && 1764 (bestSoFar.flags() & ABSTRACT) == 0 ? 1765 bestSoFar : methodNotFound; 1766 1767 for (InterfaceLookupPhase iphase2 : InterfaceLookupPhase.values()) { 1768 //keep searching for abstract methods 1769 for (Type itype : itypes[iphase2.ordinal()]) { 1770 if (!itype.isInterface()) continue; //skip j.l.Object (included by Types.closure()) 1771 if (iphase2 == InterfaceLookupPhase.DEFAULT_OK && 1772 (itype.tsym.flags() & DEFAULT) == 0) continue; 1773 bestSoFar = findMethodInScope(env, site, name, argtypes, typeargtypes, 1774 itype.tsym.members(), bestSoFar, allowBoxing, useVarargs, true); 1775 if (concrete != bestSoFar && 1776 concrete.kind.isValid() && 1777 bestSoFar.kind.isValid() && 1778 types.isSubSignature(concrete.type, bestSoFar.type)) { 1779 //this is an hack - as javac does not do full membership checks 1780 //most specific ends up comparing abstract methods that might have 1781 //been implemented by some concrete method in a subclass and, 1782 //because of raw override, it is possible for an abstract method 1783 //to be more specific than the concrete method - so we need 1784 //to explicitly call that out (see CR 6178365) 1785 bestSoFar = concrete; 1786 } 1787 } 1788 } 1789 return bestSoFar; 1790 } 1791 1792 enum InterfaceLookupPhase { 1793 ABSTRACT_OK() { 1794 @Override 1795 InterfaceLookupPhase update(Symbol s, Resolve rs) { 1796 //We should not look for abstract methods if receiver is a concrete class 1797 //(as concrete classes are expected to implement all abstracts coming 1798 //from superinterfaces) 1799 if ((s.flags() & (ABSTRACT | INTERFACE | ENUM)) != 0) { 1800 return this; 1801 } else { 1802 return DEFAULT_OK; 1803 } 1804 } 1805 }, 1806 DEFAULT_OK() { 1807 @Override 1808 InterfaceLookupPhase update(Symbol s, Resolve rs) { 1809 return this; 1810 } 1811 }; 1812 1813 abstract InterfaceLookupPhase update(Symbol s, Resolve rs); 1814 } 1815 1816 /** 1817 * Return an Iterable object to scan the superclasses of a given type. 1818 * It's crucial that the scan is done lazily, as we don't want to accidentally 1819 * access more supertypes than strictly needed (as this could trigger completion 1820 * errors if some of the not-needed supertypes are missing/ill-formed). 1821 */ 1822 Iterable<TypeSymbol> superclasses(final Type intype) { 1823 return new Iterable<TypeSymbol>() { 1824 public Iterator<TypeSymbol> iterator() { 1825 return new Iterator<TypeSymbol>() { 1826 1827 List<TypeSymbol> seen = List.nil(); 1828 TypeSymbol currentSym = symbolFor(intype); 1829 TypeSymbol prevSym = null; 1830 1831 public boolean hasNext() { 1832 if (currentSym == syms.noSymbol) { 1833 currentSym = symbolFor(types.supertype(prevSym.type)); 1834 } 1835 return currentSym != null; 1836 } 1837 1838 public TypeSymbol next() { 1839 prevSym = currentSym; 1840 currentSym = syms.noSymbol; 1841 Assert.check(prevSym != null || prevSym != syms.noSymbol); 1842 return prevSym; 1843 } 1844 1845 public void remove() { 1846 throw new UnsupportedOperationException(); 1847 } 1848 1849 TypeSymbol symbolFor(Type t) { 1850 if (!t.hasTag(CLASS) && 1851 !t.hasTag(TYPEVAR)) { 1852 return null; 1853 } 1854 t = types.skipTypeVars(t, false); 1855 if (seen.contains(t.tsym)) { 1856 //degenerate case in which we have a circular 1857 //class hierarchy - because of ill-formed classfiles 1858 return null; 1859 } 1860 seen = seen.prepend(t.tsym); 1861 return t.tsym; 1862 } 1863 }; 1864 } 1865 }; 1866 } 1867 1868 /** Find unqualified method matching given name, type and value arguments. 1869 * @param env The current environment. 1870 * @param name The method's name. 1871 * @param argtypes The method's value arguments. 1872 * @param typeargtypes The method's type arguments. 1873 * @param allowBoxing Allow boxing conversions of arguments. 1874 * @param useVarargs Box trailing arguments into an array for varargs. 1875 */ 1876 Symbol findFun(Env<AttrContext> env, Name name, 1877 List<Type> argtypes, List<Type> typeargtypes, 1878 boolean allowBoxing, boolean useVarargs) { 1879 Symbol bestSoFar = methodNotFound; 1880 Env<AttrContext> env1 = env; 1881 boolean staticOnly = false; 1882 while (env1.outer != null) { 1883 if (isStatic(env1)) staticOnly = true; 1884 Assert.check(env1.info.preferredTreeForDiagnostics == null); 1885 env1.info.preferredTreeForDiagnostics = env.tree; 1886 try { 1887 Symbol sym = findMethod( 1888 env1, env1.enclClass.sym.type, name, argtypes, typeargtypes, 1889 allowBoxing, useVarargs); 1890 if (sym.exists()) { 1891 if (staticOnly && 1892 sym.kind == MTH && 1893 sym.owner.kind == TYP && 1894 (sym.flags() & STATIC) == 0) return new StaticError(sym); 1895 else return sym; 1896 } else { 1897 bestSoFar = bestOf(bestSoFar, sym); 1898 } 1899 } finally { 1900 env1.info.preferredTreeForDiagnostics = null; 1901 } 1902 if ((env1.enclClass.sym.flags() & STATIC) != 0) staticOnly = true; 1903 env1 = env1.outer; 1904 } 1905 1906 Symbol sym = findMethod(env, syms.predefClass.type, name, argtypes, 1907 typeargtypes, allowBoxing, useVarargs); 1908 if (sym.exists()) 1909 return sym; 1910 1911 for (Symbol currentSym : env.toplevel.namedImportScope.getSymbolsByName(name)) { 1912 Symbol origin = env.toplevel.namedImportScope.getOrigin(currentSym).owner; 1913 if (currentSym.kind == MTH) { 1914 if (currentSym.owner.type != origin.type) 1915 currentSym = currentSym.clone(origin); 1916 if (!isAccessible(env, origin.type, currentSym)) 1917 currentSym = new AccessError(env, origin.type, currentSym); 1918 bestSoFar = selectBest(env, origin.type, 1919 argtypes, typeargtypes, 1920 currentSym, bestSoFar, 1921 allowBoxing, useVarargs); 1922 } 1923 } 1924 if (bestSoFar.exists()) 1925 return bestSoFar; 1926 1927 for (Symbol currentSym : env.toplevel.starImportScope.getSymbolsByName(name)) { 1928 Symbol origin = env.toplevel.starImportScope.getOrigin(currentSym).owner; 1929 if (currentSym.kind == MTH) { 1930 if (currentSym.owner.type != origin.type) 1931 currentSym = currentSym.clone(origin); 1932 if (!isAccessible(env, origin.type, currentSym)) 1933 currentSym = new AccessError(env, origin.type, currentSym); 1934 bestSoFar = selectBest(env, origin.type, 1935 argtypes, typeargtypes, 1936 currentSym, bestSoFar, 1937 allowBoxing, useVarargs); 1938 } 1939 } 1940 return bestSoFar; 1941 } 1942 1943 /** Load toplevel or member class with given fully qualified name and 1944 * verify that it is accessible. 1945 * @param env The current environment. 1946 * @param name The fully qualified name of the class to be loaded. 1947 */ 1948 Symbol loadClass(Env<AttrContext> env, Name name) { 1949 try { 1950 ClassSymbol c = finder.loadClass(name); 1951 return isAccessible(env, c) ? c : new AccessError(c); 1952 } catch (ClassFinder.BadClassFile err) { 1953 throw err; 1954 } catch (CompletionFailure ex) { 1955 return typeNotFound; 1956 } 1957 } 1958 1959 1960 /** 1961 * Find a type declared in a scope (not inherited). Return null 1962 * if none is found. 1963 * @param env The current environment. 1964 * @param site The original type from where the selection takes 1965 * place. 1966 * @param name The type's name. 1967 * @param c The class to search for the member type. This is 1968 * always a superclass or implemented interface of 1969 * site's class. 1970 */ 1971 Symbol findImmediateMemberType(Env<AttrContext> env, 1972 Type site, 1973 Name name, 1974 TypeSymbol c) { 1975 for (Symbol sym : c.members().getSymbolsByName(name)) { 1976 if (sym.kind == TYP) { 1977 return isAccessible(env, site, sym) 1978 ? sym 1979 : new AccessError(env, site, sym); 1980 } 1981 } 1982 return typeNotFound; 1983 } 1984 1985 /** Find a member type inherited from a superclass or interface. 1986 * @param env The current environment. 1987 * @param site The original type from where the selection takes 1988 * place. 1989 * @param name The type's name. 1990 * @param c The class to search for the member type. This is 1991 * always a superclass or implemented interface of 1992 * site's class. 1993 */ 1994 Symbol findInheritedMemberType(Env<AttrContext> env, 1995 Type site, 1996 Name name, 1997 TypeSymbol c) { 1998 Symbol bestSoFar = typeNotFound; 1999 Symbol sym; 2000 Type st = types.supertype(c.type); 2001 if (st != null && st.hasTag(CLASS)) { 2002 sym = findMemberType(env, site, name, st.tsym); 2003 bestSoFar = bestOf(bestSoFar, sym); 2004 } 2005 for (List<Type> l = types.interfaces(c.type); 2006 bestSoFar.kind != AMBIGUOUS && l.nonEmpty(); 2007 l = l.tail) { 2008 sym = findMemberType(env, site, name, l.head.tsym); 2009 if (!bestSoFar.kind.isResolutionError() && 2010 !sym.kind.isResolutionError() && 2011 sym.owner != bestSoFar.owner) 2012 bestSoFar = new AmbiguityError(bestSoFar, sym); 2013 else 2014 bestSoFar = bestOf(bestSoFar, sym); 2015 } 2016 return bestSoFar; 2017 } 2018 2019 /** Find qualified member type. 2020 * @param env The current environment. 2021 * @param site The original type from where the selection takes 2022 * place. 2023 * @param name The type's name. 2024 * @param c The class to search for the member type. This is 2025 * always a superclass or implemented interface of 2026 * site's class. 2027 */ 2028 Symbol findMemberType(Env<AttrContext> env, 2029 Type site, 2030 Name name, 2031 TypeSymbol c) { 2032 Symbol sym = findImmediateMemberType(env, site, name, c); 2033 2034 if (sym != typeNotFound) 2035 return sym; 2036 2037 return findInheritedMemberType(env, site, name, c); 2038 2039 } 2040 2041 /** Find a global type in given scope and load corresponding class. 2042 * @param env The current environment. 2043 * @param scope The scope in which to look for the type. 2044 * @param name The type's name. 2045 */ 2046 Symbol findGlobalType(Env<AttrContext> env, Scope scope, Name name) { 2047 Symbol bestSoFar = typeNotFound; 2048 for (Symbol s : scope.getSymbolsByName(name)) { 2049 Symbol sym = loadClass(env, s.flatName()); 2050 if (bestSoFar.kind == TYP && sym.kind == TYP && 2051 bestSoFar != sym) 2052 return new AmbiguityError(bestSoFar, sym); 2053 else 2054 bestSoFar = bestOf(bestSoFar, sym); 2055 } 2056 return bestSoFar; 2057 } 2058 2059 Symbol findTypeVar(Env<AttrContext> env, Name name, boolean staticOnly) { 2060 for (Symbol sym : env.info.scope.getSymbolsByName(name)) { 2061 if (sym.kind == TYP) { 2062 if (staticOnly && 2063 sym.type.hasTag(TYPEVAR) && 2064 sym.owner.kind == TYP) 2065 return new StaticError(sym); 2066 return sym; 2067 } 2068 } 2069 return typeNotFound; 2070 } 2071 2072 /** Find an unqualified type symbol. 2073 * @param env The current environment. 2074 * @param name The type's name. 2075 */ 2076 Symbol findType(Env<AttrContext> env, Name name) { 2077 if (name == names.empty) 2078 return typeNotFound; // do not allow inadvertent "lookup" of anonymous types 2079 Symbol bestSoFar = typeNotFound; 2080 Symbol sym; 2081 boolean staticOnly = false; 2082 for (Env<AttrContext> env1 = env; env1.outer != null; env1 = env1.outer) { 2083 if (isStatic(env1)) staticOnly = true; 2084 // First, look for a type variable and the first member type 2085 final Symbol tyvar = findTypeVar(env1, name, staticOnly); 2086 sym = findImmediateMemberType(env1, env1.enclClass.sym.type, 2087 name, env1.enclClass.sym); 2088 2089 // Return the type variable if we have it, and have no 2090 // immediate member, OR the type variable is for a method. 2091 if (tyvar != typeNotFound) { 2092 if (env.baseClause || sym == typeNotFound || 2093 (tyvar.kind == TYP && tyvar.exists() && 2094 tyvar.owner.kind == MTH)) { 2095 return tyvar; 2096 } 2097 } 2098 2099 // If the environment is a class def, finish up, 2100 // otherwise, do the entire findMemberType 2101 if (sym == typeNotFound) 2102 sym = findInheritedMemberType(env1, env1.enclClass.sym.type, 2103 name, env1.enclClass.sym); 2104 2105 if (staticOnly && sym.kind == TYP && 2106 sym.type.hasTag(CLASS) && 2107 sym.type.getEnclosingType().hasTag(CLASS) && 2108 env1.enclClass.sym.type.isParameterized() && 2109 sym.type.getEnclosingType().isParameterized()) 2110 return new StaticError(sym); 2111 else if (sym.exists()) return sym; 2112 else bestSoFar = bestOf(bestSoFar, sym); 2113 2114 JCClassDecl encl = env1.baseClause ? (JCClassDecl)env1.tree : env1.enclClass; 2115 if ((encl.sym.flags() & STATIC) != 0) 2116 staticOnly = true; 2117 } 2118 2119 if (!env.tree.hasTag(IMPORT)) { 2120 sym = findGlobalType(env, env.toplevel.namedImportScope, name); 2121 if (sym.exists()) return sym; 2122 else bestSoFar = bestOf(bestSoFar, sym); 2123 2124 sym = findGlobalType(env, env.toplevel.packge.members(), name); 2125 if (sym.exists()) return sym; 2126 else bestSoFar = bestOf(bestSoFar, sym); 2127 2128 sym = findGlobalType(env, env.toplevel.starImportScope, name); 2129 if (sym.exists()) return sym; 2130 else bestSoFar = bestOf(bestSoFar, sym); 2131 } 2132 2133 return bestSoFar; 2134 } 2135 2136 /** Find an unqualified identifier which matches a specified kind set. 2137 * @param env The current environment. 2138 * @param name The identifier's name. 2139 * @param kind Indicates the possible symbol kinds 2140 * (a subset of VAL, TYP, PCK). 2141 */ 2142 Symbol findIdent(Env<AttrContext> env, Name name, KindSelector kind) { 2143 Symbol bestSoFar = typeNotFound; 2144 Symbol sym; 2145 2146 if (kind.contains(KindSelector.VAL)) { 2147 sym = findVar(env, name); 2148 if (sym.exists()) return sym; 2149 else bestSoFar = bestOf(bestSoFar, sym); 2150 } 2151 2152 if (kind.contains(KindSelector.TYP)) { 2153 sym = findType(env, name); 2154 2155 if (sym.exists()) return sym; 2156 else bestSoFar = bestOf(bestSoFar, sym); 2157 } 2158 2159 if (kind.contains(KindSelector.PCK)) 2160 return syms.enterPackage(name); 2161 else return bestSoFar; 2162 } 2163 2164 /** Find an identifier in a package which matches a specified kind set. 2165 * @param env The current environment. 2166 * @param name The identifier's name. 2167 * @param kind Indicates the possible symbol kinds 2168 * (a nonempty subset of TYP, PCK). 2169 */ 2170 Symbol findIdentInPackage(Env<AttrContext> env, TypeSymbol pck, 2171 Name name, KindSelector kind) { 2172 Name fullname = TypeSymbol.formFullName(name, pck); 2173 Symbol bestSoFar = typeNotFound; 2174 PackageSymbol pack = null; 2175 if (kind.contains(KindSelector.PCK)) { 2176 pack = syms.enterPackage(fullname); 2177 if (pack.exists()) return pack; 2178 } 2179 if (kind.contains(KindSelector.TYP)) { 2180 Symbol sym = loadClass(env, fullname); 2181 if (sym.exists()) { 2182 // don't allow programs to use flatnames 2183 if (name == sym.name) return sym; 2184 } 2185 else bestSoFar = bestOf(bestSoFar, sym); 2186 } 2187 return (pack != null) ? pack : bestSoFar; 2188 } 2189 2190 /** Find an identifier among the members of a given type `site'. 2191 * @param env The current environment. 2192 * @param site The type containing the symbol to be found. 2193 * @param name The identifier's name. 2194 * @param kind Indicates the possible symbol kinds 2195 * (a subset of VAL, TYP). 2196 */ 2197 Symbol findIdentInType(Env<AttrContext> env, Type site, 2198 Name name, KindSelector kind) { 2199 Symbol bestSoFar = typeNotFound; 2200 Symbol sym; 2201 if (kind.contains(KindSelector.VAL)) { 2202 sym = findField(env, site, name, site.tsym); 2203 if (sym.exists()) return sym; 2204 else bestSoFar = bestOf(bestSoFar, sym); 2205 } 2206 2207 if (kind.contains(KindSelector.TYP)) { 2208 sym = findMemberType(env, site, name, site.tsym); 2209 if (sym.exists()) return sym; 2210 else bestSoFar = bestOf(bestSoFar, sym); 2211 } 2212 return bestSoFar; 2213 } 2214 2215/* *************************************************************************** 2216 * Access checking 2217 * The following methods convert ResolveErrors to ErrorSymbols, issuing 2218 * an error message in the process 2219 ****************************************************************************/ 2220 2221 /** If `sym' is a bad symbol: report error and return errSymbol 2222 * else pass through unchanged, 2223 * additional arguments duplicate what has been used in trying to find the 2224 * symbol {@literal (--> flyweight pattern)}. This improves performance since we 2225 * expect misses to happen frequently. 2226 * 2227 * @param sym The symbol that was found, or a ResolveError. 2228 * @param pos The position to use for error reporting. 2229 * @param location The symbol the served as a context for this lookup 2230 * @param site The original type from where the selection took place. 2231 * @param name The symbol's name. 2232 * @param qualified Did we get here through a qualified expression resolution? 2233 * @param argtypes The invocation's value arguments, 2234 * if we looked for a method. 2235 * @param typeargtypes The invocation's type arguments, 2236 * if we looked for a method. 2237 * @param logResolveHelper helper class used to log resolve errors 2238 */ 2239 Symbol accessInternal(Symbol sym, 2240 DiagnosticPosition pos, 2241 Symbol location, 2242 Type site, 2243 Name name, 2244 boolean qualified, 2245 List<Type> argtypes, 2246 List<Type> typeargtypes, 2247 LogResolveHelper logResolveHelper) { 2248 if (sym.kind.isResolutionError()) { 2249 ResolveError errSym = (ResolveError)sym.baseSymbol(); 2250 sym = errSym.access(name, qualified ? site.tsym : syms.noSymbol); 2251 argtypes = logResolveHelper.getArgumentTypes(errSym, sym, name, argtypes); 2252 if (logResolveHelper.resolveDiagnosticNeeded(site, argtypes, typeargtypes)) { 2253 logResolveError(errSym, pos, location, site, name, argtypes, typeargtypes); 2254 } 2255 } 2256 return sym; 2257 } 2258 2259 /** 2260 * Variant of the generalized access routine, to be used for generating method 2261 * resolution diagnostics 2262 */ 2263 Symbol accessMethod(Symbol sym, 2264 DiagnosticPosition pos, 2265 Symbol location, 2266 Type site, 2267 Name name, 2268 boolean qualified, 2269 List<Type> argtypes, 2270 List<Type> typeargtypes) { 2271 return accessInternal(sym, pos, location, site, name, qualified, argtypes, typeargtypes, methodLogResolveHelper); 2272 } 2273 2274 /** Same as original accessMethod(), but without location. 2275 */ 2276 Symbol accessMethod(Symbol sym, 2277 DiagnosticPosition pos, 2278 Type site, 2279 Name name, 2280 boolean qualified, 2281 List<Type> argtypes, 2282 List<Type> typeargtypes) { 2283 return accessMethod(sym, pos, site.tsym, site, name, qualified, argtypes, typeargtypes); 2284 } 2285 2286 /** 2287 * Variant of the generalized access routine, to be used for generating variable, 2288 * type resolution diagnostics 2289 */ 2290 Symbol accessBase(Symbol sym, 2291 DiagnosticPosition pos, 2292 Symbol location, 2293 Type site, 2294 Name name, 2295 boolean qualified) { 2296 return accessInternal(sym, pos, location, site, name, qualified, List.<Type>nil(), null, basicLogResolveHelper); 2297 } 2298 2299 /** Same as original accessBase(), but without location. 2300 */ 2301 Symbol accessBase(Symbol sym, 2302 DiagnosticPosition pos, 2303 Type site, 2304 Name name, 2305 boolean qualified) { 2306 return accessBase(sym, pos, site.tsym, site, name, qualified); 2307 } 2308 2309 interface LogResolveHelper { 2310 boolean resolveDiagnosticNeeded(Type site, List<Type> argtypes, List<Type> typeargtypes); 2311 List<Type> getArgumentTypes(ResolveError errSym, Symbol accessedSym, Name name, List<Type> argtypes); 2312 } 2313 2314 LogResolveHelper basicLogResolveHelper = new LogResolveHelper() { 2315 public boolean resolveDiagnosticNeeded(Type site, List<Type> argtypes, List<Type> typeargtypes) { 2316 return !site.isErroneous(); 2317 } 2318 public List<Type> getArgumentTypes(ResolveError errSym, Symbol accessedSym, Name name, List<Type> argtypes) { 2319 return argtypes; 2320 } 2321 }; 2322 2323 LogResolveHelper methodLogResolveHelper = new LogResolveHelper() { 2324 public boolean resolveDiagnosticNeeded(Type site, List<Type> argtypes, List<Type> typeargtypes) { 2325 return !site.isErroneous() && 2326 !Type.isErroneous(argtypes) && 2327 (typeargtypes == null || !Type.isErroneous(typeargtypes)); 2328 } 2329 public List<Type> getArgumentTypes(ResolveError errSym, Symbol accessedSym, Name name, List<Type> argtypes) { 2330 return argtypes.map(new ResolveDeferredRecoveryMap(AttrMode.SPECULATIVE, accessedSym, currentResolutionContext.step)); 2331 } 2332 }; 2333 2334 class ResolveDeferredRecoveryMap extends DeferredAttr.RecoveryDeferredTypeMap { 2335 2336 public ResolveDeferredRecoveryMap(AttrMode mode, Symbol msym, MethodResolutionPhase step) { 2337 deferredAttr.super(mode, msym, step); 2338 } 2339 2340 @Override 2341 protected Type typeOf(DeferredType dt) { 2342 Type res = super.typeOf(dt); 2343 if (!res.isErroneous()) { 2344 switch (TreeInfo.skipParens(dt.tree).getTag()) { 2345 case LAMBDA: 2346 case REFERENCE: 2347 return dt; 2348 case CONDEXPR: 2349 return res == Type.recoveryType ? 2350 dt : res; 2351 } 2352 } 2353 return res; 2354 } 2355 } 2356 2357 /** Check that sym is not an abstract method. 2358 */ 2359 void checkNonAbstract(DiagnosticPosition pos, Symbol sym) { 2360 if ((sym.flags() & ABSTRACT) != 0 && (sym.flags() & DEFAULT) == 0) 2361 log.error(pos, "abstract.cant.be.accessed.directly", 2362 kindName(sym), sym, sym.location()); 2363 } 2364 2365/* *************************************************************************** 2366 * Name resolution 2367 * Naming conventions are as for symbol lookup 2368 * Unlike the find... methods these methods will report access errors 2369 ****************************************************************************/ 2370 2371 /** Resolve an unqualified (non-method) identifier. 2372 * @param pos The position to use for error reporting. 2373 * @param env The environment current at the identifier use. 2374 * @param name The identifier's name. 2375 * @param kind The set of admissible symbol kinds for the identifier. 2376 */ 2377 Symbol resolveIdent(DiagnosticPosition pos, Env<AttrContext> env, 2378 Name name, KindSelector kind) { 2379 return accessBase( 2380 findIdent(env, name, kind), 2381 pos, env.enclClass.sym.type, name, false); 2382 } 2383 2384 /** Resolve an unqualified method identifier. 2385 * @param pos The position to use for error reporting. 2386 * @param env The environment current at the method invocation. 2387 * @param name The identifier's name. 2388 * @param argtypes The types of the invocation's value arguments. 2389 * @param typeargtypes The types of the invocation's type arguments. 2390 */ 2391 Symbol resolveMethod(DiagnosticPosition pos, 2392 Env<AttrContext> env, 2393 Name name, 2394 List<Type> argtypes, 2395 List<Type> typeargtypes) { 2396 return lookupMethod(env, pos, env.enclClass.sym, resolveMethodCheck, 2397 new BasicLookupHelper(name, env.enclClass.sym.type, argtypes, typeargtypes) { 2398 @Override 2399 Symbol doLookup(Env<AttrContext> env, MethodResolutionPhase phase) { 2400 return findFun(env, name, argtypes, typeargtypes, 2401 phase.isBoxingRequired(), 2402 phase.isVarargsRequired()); 2403 }}); 2404 } 2405 2406 /** Resolve a qualified method identifier 2407 * @param pos The position to use for error reporting. 2408 * @param env The environment current at the method invocation. 2409 * @param site The type of the qualifying expression, in which 2410 * identifier is searched. 2411 * @param name The identifier's name. 2412 * @param argtypes The types of the invocation's value arguments. 2413 * @param typeargtypes The types of the invocation's type arguments. 2414 */ 2415 Symbol resolveQualifiedMethod(DiagnosticPosition pos, Env<AttrContext> env, 2416 Type site, Name name, List<Type> argtypes, 2417 List<Type> typeargtypes) { 2418 return resolveQualifiedMethod(pos, env, site.tsym, site, name, argtypes, typeargtypes); 2419 } 2420 Symbol resolveQualifiedMethod(DiagnosticPosition pos, Env<AttrContext> env, 2421 Symbol location, Type site, Name name, List<Type> argtypes, 2422 List<Type> typeargtypes) { 2423 return resolveQualifiedMethod(new MethodResolutionContext(), pos, env, location, site, name, argtypes, typeargtypes); 2424 } 2425 private Symbol resolveQualifiedMethod(MethodResolutionContext resolveContext, 2426 DiagnosticPosition pos, Env<AttrContext> env, 2427 Symbol location, Type site, Name name, List<Type> argtypes, 2428 List<Type> typeargtypes) { 2429 return lookupMethod(env, pos, location, resolveContext, new BasicLookupHelper(name, site, argtypes, typeargtypes) { 2430 @Override 2431 Symbol doLookup(Env<AttrContext> env, MethodResolutionPhase phase) { 2432 return findMethod(env, site, name, argtypes, typeargtypes, 2433 phase.isBoxingRequired(), 2434 phase.isVarargsRequired()); 2435 } 2436 @Override 2437 Symbol access(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, Symbol sym) { 2438 if (sym.kind.isResolutionError()) { 2439 sym = super.access(env, pos, location, sym); 2440 } else if (allowMethodHandles) { 2441 MethodSymbol msym = (MethodSymbol)sym; 2442 if ((msym.flags() & SIGNATURE_POLYMORPHIC) != 0) { 2443 return findPolymorphicSignatureInstance(env, sym, argtypes); 2444 } 2445 } 2446 return sym; 2447 } 2448 }); 2449 } 2450 2451 /** Find or create an implicit method of exactly the given type (after erasure). 2452 * Searches in a side table, not the main scope of the site. 2453 * This emulates the lookup process required by JSR 292 in JVM. 2454 * @param env Attribution environment 2455 * @param spMethod signature polymorphic method - i.e. MH.invokeExact 2456 * @param argtypes The required argument types 2457 */ 2458 Symbol findPolymorphicSignatureInstance(Env<AttrContext> env, 2459 final Symbol spMethod, 2460 List<Type> argtypes) { 2461 Type mtype = infer.instantiatePolymorphicSignatureInstance(env, 2462 (MethodSymbol)spMethod, currentResolutionContext, argtypes); 2463 for (Symbol sym : polymorphicSignatureScope.getSymbolsByName(spMethod.name)) { 2464 if (types.isSameType(mtype, sym.type)) { 2465 return sym; 2466 } 2467 } 2468 2469 // create the desired method 2470 long flags = ABSTRACT | HYPOTHETICAL | spMethod.flags() & Flags.AccessFlags; 2471 Symbol msym = new MethodSymbol(flags, spMethod.name, mtype, spMethod.owner) { 2472 @Override 2473 public Symbol baseSymbol() { 2474 return spMethod; 2475 } 2476 }; 2477 if (!mtype.isErroneous()) { // Cache only if kosher. 2478 polymorphicSignatureScope.enter(msym); 2479 } 2480 return msym; 2481 } 2482 2483 /** Resolve a qualified method identifier, throw a fatal error if not 2484 * 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 of the qualifying expression, in which 2488 * identifier is searched. 2489 * @param name The identifier's name. 2490 * @param argtypes The types of the invocation's value arguments. 2491 * @param typeargtypes The types of the invocation's type arguments. 2492 */ 2493 public MethodSymbol resolveInternalMethod(DiagnosticPosition pos, Env<AttrContext> env, 2494 Type site, Name name, 2495 List<Type> argtypes, 2496 List<Type> typeargtypes) { 2497 MethodResolutionContext resolveContext = new MethodResolutionContext(); 2498 resolveContext.internalResolution = true; 2499 Symbol sym = resolveQualifiedMethod(resolveContext, pos, env, site.tsym, 2500 site, name, argtypes, typeargtypes); 2501 if (sym.kind == MTH) return (MethodSymbol)sym; 2502 else throw new FatalError( 2503 diags.fragment("fatal.err.cant.locate.meth", 2504 name)); 2505 } 2506 2507 /** Resolve constructor. 2508 * @param pos The position to use for error reporting. 2509 * @param env The environment current at the constructor invocation. 2510 * @param site The type of class for which a constructor is searched. 2511 * @param argtypes The types of the constructor invocation's value 2512 * arguments. 2513 * @param typeargtypes The types of the constructor invocation's type 2514 * arguments. 2515 */ 2516 Symbol resolveConstructor(DiagnosticPosition pos, 2517 Env<AttrContext> env, 2518 Type site, 2519 List<Type> argtypes, 2520 List<Type> typeargtypes) { 2521 return resolveConstructor(new MethodResolutionContext(), pos, env, site, argtypes, typeargtypes); 2522 } 2523 2524 private Symbol resolveConstructor(MethodResolutionContext resolveContext, 2525 final DiagnosticPosition pos, 2526 Env<AttrContext> env, 2527 Type site, 2528 List<Type> argtypes, 2529 List<Type> typeargtypes) { 2530 return lookupMethod(env, pos, site.tsym, resolveContext, new BasicLookupHelper(names.init, site, argtypes, typeargtypes) { 2531 @Override 2532 Symbol doLookup(Env<AttrContext> env, MethodResolutionPhase phase) { 2533 return findConstructor(pos, env, site, argtypes, typeargtypes, 2534 phase.isBoxingRequired(), 2535 phase.isVarargsRequired()); 2536 } 2537 }); 2538 } 2539 2540 /** Resolve a constructor, throw a fatal error if not found. 2541 * @param pos The position to use for error reporting. 2542 * @param env The environment current at the method invocation. 2543 * @param site The type to be constructed. 2544 * @param argtypes The types of the invocation's value arguments. 2545 * @param typeargtypes The types of the invocation's type arguments. 2546 */ 2547 public MethodSymbol resolveInternalConstructor(DiagnosticPosition pos, Env<AttrContext> env, 2548 Type site, 2549 List<Type> argtypes, 2550 List<Type> typeargtypes) { 2551 MethodResolutionContext resolveContext = new MethodResolutionContext(); 2552 resolveContext.internalResolution = true; 2553 Symbol sym = resolveConstructor(resolveContext, pos, env, site, argtypes, typeargtypes); 2554 if (sym.kind == MTH) return (MethodSymbol)sym; 2555 else throw new FatalError( 2556 diags.fragment("fatal.err.cant.locate.ctor", site)); 2557 } 2558 2559 Symbol findConstructor(DiagnosticPosition pos, Env<AttrContext> env, 2560 Type site, List<Type> argtypes, 2561 List<Type> typeargtypes, 2562 boolean allowBoxing, 2563 boolean useVarargs) { 2564 Symbol sym = findMethod(env, site, 2565 names.init, argtypes, 2566 typeargtypes, allowBoxing, 2567 useVarargs); 2568 chk.checkDeprecated(pos, env.info.scope.owner, sym); 2569 return sym; 2570 } 2571 2572 /** Resolve constructor using diamond inference. 2573 * @param pos The position to use for error reporting. 2574 * @param env The environment current at the constructor invocation. 2575 * @param site The type of class for which a constructor is searched. 2576 * The scope of this class has been touched in attribution. 2577 * @param argtypes The types of the constructor invocation's value 2578 * arguments. 2579 * @param typeargtypes The types of the constructor invocation's type 2580 * arguments. 2581 */ 2582 Symbol resolveDiamond(DiagnosticPosition pos, 2583 Env<AttrContext> env, 2584 Type site, 2585 List<Type> argtypes, 2586 List<Type> typeargtypes) { 2587 return lookupMethod(env, pos, site.tsym, resolveMethodCheck, 2588 new BasicLookupHelper(names.init, site, argtypes, typeargtypes) { 2589 @Override 2590 Symbol doLookup(Env<AttrContext> env, MethodResolutionPhase phase) { 2591 return findDiamond(env, site, argtypes, typeargtypes, 2592 phase.isBoxingRequired(), 2593 phase.isVarargsRequired()); 2594 } 2595 @Override 2596 Symbol access(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, Symbol sym) { 2597 if (sym.kind.isResolutionError()) { 2598 if (sym.kind != WRONG_MTH && 2599 sym.kind != WRONG_MTHS) { 2600 sym = super.access(env, pos, location, sym); 2601 } else { 2602 final JCDiagnostic details = sym.kind == WRONG_MTH ? 2603 ((InapplicableSymbolError)sym.baseSymbol()).errCandidate().snd : 2604 null; 2605 sym = new DiamondError(sym, currentResolutionContext); 2606 sym = accessMethod(sym, pos, site, names.init, true, argtypes, typeargtypes); 2607 env.info.pendingResolutionPhase = currentResolutionContext.step; 2608 } 2609 } 2610 return sym; 2611 }}); 2612 } 2613 2614 /** This method scans all the constructor symbol in a given class scope - 2615 * assuming that the original scope contains a constructor of the kind: 2616 * {@code Foo(X x, Y y)}, where X,Y are class type-variables declared in Foo, 2617 * a method check is executed against the modified constructor type: 2618 * {@code <X,Y>Foo<X,Y>(X x, Y y)}. This is crucial in order to enable diamond 2619 * inference. The inferred return type of the synthetic constructor IS 2620 * the inferred type for the diamond operator. 2621 */ 2622 private Symbol findDiamond(Env<AttrContext> env, 2623 Type site, 2624 List<Type> argtypes, 2625 List<Type> typeargtypes, 2626 boolean allowBoxing, 2627 boolean useVarargs) { 2628 Symbol bestSoFar = methodNotFound; 2629 TypeSymbol tsym = site.tsym.isInterface() ? syms.objectType.tsym : site.tsym; 2630 for (final Symbol sym : tsym.members().getSymbolsByName(names.init)) { 2631 //- System.out.println(" e " + e.sym); 2632 if (sym.kind == MTH && 2633 (sym.flags_field & SYNTHETIC) == 0) { 2634 List<Type> oldParams = sym.type.hasTag(FORALL) ? 2635 ((ForAll)sym.type).tvars : 2636 List.<Type>nil(); 2637 Type constrType = new ForAll(site.tsym.type.getTypeArguments().appendList(oldParams), 2638 types.createMethodTypeWithReturn(sym.type.asMethodType(), site)); 2639 MethodSymbol newConstr = new MethodSymbol(sym.flags(), names.init, constrType, site.tsym) { 2640 @Override 2641 public Symbol baseSymbol() { 2642 return sym; 2643 } 2644 }; 2645 bestSoFar = selectBest(env, site, argtypes, typeargtypes, 2646 newConstr, 2647 bestSoFar, 2648 allowBoxing, 2649 useVarargs); 2650 } 2651 } 2652 return bestSoFar; 2653 } 2654 2655 Symbol getMemberReference(DiagnosticPosition pos, 2656 Env<AttrContext> env, 2657 JCMemberReference referenceTree, 2658 Type site, 2659 Name name) { 2660 2661 site = types.capture(site); 2662 2663 ReferenceLookupHelper lookupHelper = makeReferenceLookupHelper( 2664 referenceTree, site, name, List.<Type>nil(), null, VARARITY); 2665 2666 Env<AttrContext> newEnv = env.dup(env.tree, env.info.dup()); 2667 Symbol sym = lookupMethod(newEnv, env.tree.pos(), site.tsym, 2668 nilMethodCheck, lookupHelper); 2669 2670 env.info.pendingResolutionPhase = newEnv.info.pendingResolutionPhase; 2671 2672 return sym; 2673 } 2674 2675 ReferenceLookupHelper makeReferenceLookupHelper(JCMemberReference referenceTree, 2676 Type site, 2677 Name name, 2678 List<Type> argtypes, 2679 List<Type> typeargtypes, 2680 MethodResolutionPhase maxPhase) { 2681 if (!name.equals(names.init)) { 2682 //method reference 2683 return new MethodReferenceLookupHelper(referenceTree, name, site, argtypes, typeargtypes, maxPhase); 2684 } else if (site.hasTag(ARRAY)) { 2685 //array constructor reference 2686 return new ArrayConstructorReferenceLookupHelper(referenceTree, site, argtypes, typeargtypes, maxPhase); 2687 } else { 2688 //class constructor reference 2689 return new ConstructorReferenceLookupHelper(referenceTree, site, argtypes, typeargtypes, maxPhase); 2690 } 2691 } 2692 2693 /** 2694 * Resolution of member references is typically done as a single 2695 * overload resolution step, where the argument types A are inferred from 2696 * the target functional descriptor. 2697 * 2698 * If the member reference is a method reference with a type qualifier, 2699 * a two-step lookup process is performed. The first step uses the 2700 * expected argument list A, while the second step discards the first 2701 * type from A (which is treated as a receiver type). 2702 * 2703 * There are two cases in which inference is performed: (i) if the member 2704 * reference is a constructor reference and the qualifier type is raw - in 2705 * which case diamond inference is used to infer a parameterization for the 2706 * type qualifier; (ii) if the member reference is an unbound reference 2707 * where the type qualifier is raw - in that case, during the unbound lookup 2708 * the receiver argument type is used to infer an instantiation for the raw 2709 * qualifier type. 2710 * 2711 * When a multi-step resolution process is exploited, the process of picking 2712 * the resulting symbol is delegated to an helper class {@link com.sun.tools.javac.comp.Resolve.ReferenceChooser}. 2713 * 2714 * This routine returns a pair (T,S), where S is the member reference symbol, 2715 * and T is the type of the class in which S is defined. This is necessary as 2716 * the type T might be dynamically inferred (i.e. if constructor reference 2717 * has a raw qualifier). 2718 */ 2719 Pair<Symbol, ReferenceLookupHelper> resolveMemberReference(Env<AttrContext> env, 2720 JCMemberReference referenceTree, 2721 Type site, 2722 Name name, 2723 List<Type> argtypes, 2724 List<Type> typeargtypes, 2725 MethodCheck methodCheck, 2726 InferenceContext inferenceContext, 2727 ReferenceChooser referenceChooser) { 2728 2729 //step 1 - bound lookup 2730 ReferenceLookupHelper boundLookupHelper = makeReferenceLookupHelper( 2731 referenceTree, site, name, argtypes, typeargtypes, VARARITY); 2732 Env<AttrContext> boundEnv = env.dup(env.tree, env.info.dup()); 2733 MethodResolutionContext boundSearchResolveContext = new MethodResolutionContext(); 2734 boundSearchResolveContext.methodCheck = methodCheck; 2735 Symbol boundSym = lookupMethod(boundEnv, env.tree.pos(), 2736 site.tsym, boundSearchResolveContext, boundLookupHelper); 2737 ReferenceLookupResult boundRes = new ReferenceLookupResult(boundSym, boundSearchResolveContext); 2738 2739 //step 2 - unbound lookup 2740 Symbol unboundSym = methodNotFound; 2741 Env<AttrContext> unboundEnv = env.dup(env.tree, env.info.dup()); 2742 ReferenceLookupHelper unboundLookupHelper = boundLookupHelper.unboundLookup(inferenceContext); 2743 ReferenceLookupResult unboundRes = referenceNotFound; 2744 if (unboundLookupHelper != null) { 2745 MethodResolutionContext unboundSearchResolveContext = 2746 new MethodResolutionContext(); 2747 unboundSearchResolveContext.methodCheck = methodCheck; 2748 unboundSym = lookupMethod(unboundEnv, env.tree.pos(), 2749 site.tsym, unboundSearchResolveContext, unboundLookupHelper); 2750 unboundRes = new ReferenceLookupResult(unboundSym, unboundSearchResolveContext); 2751 } 2752 2753 //merge results 2754 Pair<Symbol, ReferenceLookupHelper> res; 2755 Symbol bestSym = referenceChooser.result(boundRes, unboundRes); 2756 res = new Pair<>(bestSym, 2757 bestSym == unboundSym ? unboundLookupHelper : boundLookupHelper); 2758 env.info.pendingResolutionPhase = bestSym == unboundSym ? 2759 unboundEnv.info.pendingResolutionPhase : 2760 boundEnv.info.pendingResolutionPhase; 2761 2762 return res; 2763 } 2764 2765 /** 2766 * This class is used to represent a method reference lookup result. It keeps track of two 2767 * things: (i) the symbol found during a method reference lookup and (ii) the static kind 2768 * of the lookup (see {@link com.sun.tools.javac.comp.Resolve.ReferenceLookupResult.StaticKind}). 2769 */ 2770 static class ReferenceLookupResult { 2771 2772 /** 2773 * Static kind associated with a method reference lookup. Erroneous lookups end up with 2774 * the UNDEFINED kind; successful lookups will end up with either STATIC, NON_STATIC, 2775 * depending on whether all applicable candidates are static or non-static methods, 2776 * respectively. If a successful lookup has both static and non-static applicable methods, 2777 * its kind is set to BOTH. 2778 */ 2779 enum StaticKind { 2780 STATIC, 2781 NON_STATIC, 2782 BOTH, 2783 UNDEFINED; 2784 2785 /** 2786 * Retrieve the static kind associated with a given (method) symbol. 2787 */ 2788 static StaticKind from(Symbol s) { 2789 return s.isStatic() ? 2790 STATIC : NON_STATIC; 2791 } 2792 2793 /** 2794 * Merge two static kinds together. 2795 */ 2796 static StaticKind reduce(StaticKind sk1, StaticKind sk2) { 2797 if (sk1 == UNDEFINED) { 2798 return sk2; 2799 } else if (sk2 == UNDEFINED) { 2800 return sk1; 2801 } else { 2802 return sk1 == sk2 ? sk1 : BOTH; 2803 } 2804 } 2805 } 2806 2807 /** The static kind. */ 2808 StaticKind staticKind; 2809 2810 /** The lookup result. */ 2811 Symbol sym; 2812 2813 ReferenceLookupResult(Symbol sym, MethodResolutionContext resolutionContext) { 2814 this.staticKind = staticKind(sym, resolutionContext); 2815 this.sym = sym; 2816 } 2817 2818 private StaticKind staticKind(Symbol sym, MethodResolutionContext resolutionContext) { 2819 switch (sym.kind) { 2820 case MTH: 2821 case AMBIGUOUS: 2822 return resolutionContext.candidates.stream() 2823 .filter(c -> c.isApplicable() && c.step == resolutionContext.step) 2824 .map(c -> StaticKind.from(c.sym)) 2825 .reduce(StaticKind::reduce) 2826 .orElse(StaticKind.UNDEFINED); 2827 default: 2828 return StaticKind.UNDEFINED; 2829 } 2830 } 2831 2832 /** 2833 * Does this result corresponds to a successful lookup (i.e. one where a method has been found?) 2834 */ 2835 boolean isSuccess() { 2836 return staticKind != StaticKind.UNDEFINED; 2837 } 2838 2839 /** 2840 * Does this result have given static kind? 2841 */ 2842 boolean hasKind(StaticKind sk) { 2843 return this.staticKind == sk; 2844 } 2845 2846 /** 2847 * Error recovery helper: can this lookup result be ignored (for the purpose of returning 2848 * some 'better' result) ? 2849 */ 2850 boolean canIgnore() { 2851 switch (sym.kind) { 2852 case ABSENT_MTH: 2853 return true; 2854 case WRONG_MTH: 2855 InapplicableSymbolError errSym = 2856 (InapplicableSymbolError)sym.baseSymbol(); 2857 return new Template(MethodCheckDiag.ARITY_MISMATCH.regex()) 2858 .matches(errSym.errCandidate().snd); 2859 case WRONG_MTHS: 2860 InapplicableSymbolsError errSyms = 2861 (InapplicableSymbolsError)sym.baseSymbol(); 2862 return errSyms.filterCandidates(errSyms.mapCandidates()).isEmpty(); 2863 default: 2864 return false; 2865 } 2866 } 2867 } 2868 2869 /** 2870 * This abstract class embodies the logic that converts one (bound lookup) or two (unbound lookup) 2871 * {@code ReferenceLookupResult} objects into a (@code Symbol), which is then regarded as the 2872 * result of method reference resolution. 2873 */ 2874 abstract class ReferenceChooser { 2875 /** 2876 * Generate a result from a pair of lookup result objects. This method delegates to the 2877 * appropriate result generation routine. 2878 */ 2879 Symbol result(ReferenceLookupResult boundRes, ReferenceLookupResult unboundRes) { 2880 return unboundRes != referenceNotFound ? 2881 unboundResult(boundRes, unboundRes) : 2882 boundResult(boundRes); 2883 } 2884 2885 /** 2886 * Generate a symbol from a given bound lookup result. 2887 */ 2888 abstract Symbol boundResult(ReferenceLookupResult boundRes); 2889 2890 /** 2891 * Generate a symbol from a pair of bound/unbound lookup results. 2892 */ 2893 abstract Symbol unboundResult(ReferenceLookupResult boundRes, ReferenceLookupResult unboundRes); 2894 } 2895 2896 /** 2897 * This chooser implements the selection strategy used during a full lookup; this logic 2898 * is described in JLS SE 8 (15.3.2). 2899 */ 2900 ReferenceChooser basicReferenceChooser = new ReferenceChooser() { 2901 2902 @Override 2903 Symbol boundResult(ReferenceLookupResult boundRes) { 2904 return !boundRes.isSuccess() || boundRes.hasKind(StaticKind.NON_STATIC) ? 2905 boundRes.sym : //the search produces a non-static method 2906 new BadMethodReferenceError(boundRes.sym, false); 2907 } 2908 2909 @Override 2910 Symbol unboundResult(ReferenceLookupResult boundRes, ReferenceLookupResult unboundRes) { 2911 if (boundRes.hasKind(StaticKind.STATIC) && 2912 (!unboundRes.isSuccess() || unboundRes.hasKind(StaticKind.STATIC))) { 2913 //the first search produces a static method and no non-static method is applicable 2914 //during the second search 2915 return boundRes.sym; 2916 } else if (unboundRes.hasKind(StaticKind.NON_STATIC) && 2917 (!boundRes.isSuccess() || boundRes.hasKind(StaticKind.NON_STATIC))) { 2918 //the second search produces a non-static method and no static method is applicable 2919 //during the first search 2920 return unboundRes.sym; 2921 } else if (boundRes.isSuccess() && unboundRes.isSuccess()) { 2922 //both searches produce some result; ambiguity (error recovery) 2923 return ambiguityError(boundRes.sym, unboundRes.sym); 2924 } else if (boundRes.isSuccess() || unboundRes.isSuccess()) { 2925 //Both searches failed to produce a result with correct staticness (i.e. first search 2926 //produces an non-static method). Alternatively, a given search produced a result 2927 //with the right staticness, but the other search has applicable methods with wrong 2928 //staticness (error recovery) 2929 return new BadMethodReferenceError(boundRes.isSuccess() ? boundRes.sym : unboundRes.sym, true); 2930 } else { 2931 //both searches fail to produce a result - pick 'better' error using heuristics (error recovery) 2932 return (boundRes.canIgnore() && !unboundRes.canIgnore()) ? 2933 unboundRes.sym : boundRes.sym; 2934 } 2935 } 2936 }; 2937 2938 /** 2939 * This chooser implements the selection strategy used during an arity-based lookup; this logic 2940 * is described in JLS SE 8 (15.12.2.1). 2941 */ 2942 ReferenceChooser structuralReferenceChooser = new ReferenceChooser() { 2943 2944 @Override 2945 Symbol boundResult(ReferenceLookupResult boundRes) { 2946 return (!boundRes.isSuccess() || !boundRes.hasKind(StaticKind.STATIC)) ? 2947 boundRes.sym : //the search has at least one applicable non-static method 2948 new BadMethodReferenceError(boundRes.sym, false); 2949 } 2950 2951 @Override 2952 Symbol unboundResult(ReferenceLookupResult boundRes, ReferenceLookupResult unboundRes) { 2953 if (boundRes.isSuccess() && !boundRes.hasKind(StaticKind.NON_STATIC)) { 2954 //the first serach has at least one applicable static method 2955 return boundRes.sym; 2956 } else if (unboundRes.isSuccess() && !unboundRes.hasKind(StaticKind.STATIC)) { 2957 //the second search has at least one applicable non-static method 2958 return unboundRes.sym; 2959 } else if (boundRes.isSuccess() || unboundRes.isSuccess()) { 2960 //either the first search produces a non-static method, or second search produces 2961 //a non-static method (error recovery) 2962 return new BadMethodReferenceError(boundRes.isSuccess() ? boundRes.sym : unboundRes.sym, true); 2963 } else { 2964 //both searches fail to produce a result - pick 'better' error using heuristics (error recovery) 2965 return (boundRes.canIgnore() && !unboundRes.canIgnore()) ? 2966 unboundRes.sym : boundRes.sym; 2967 } 2968 } 2969 }; 2970 2971 /** 2972 * Helper for defining custom method-like lookup logic; a lookup helper 2973 * provides hooks for (i) the actual lookup logic and (ii) accessing the 2974 * lookup result (this step might result in compiler diagnostics to be generated) 2975 */ 2976 abstract class LookupHelper { 2977 2978 /** name of the symbol to lookup */ 2979 Name name; 2980 2981 /** location in which the lookup takes place */ 2982 Type site; 2983 2984 /** actual types used during the lookup */ 2985 List<Type> argtypes; 2986 2987 /** type arguments used during the lookup */ 2988 List<Type> typeargtypes; 2989 2990 /** Max overload resolution phase handled by this helper */ 2991 MethodResolutionPhase maxPhase; 2992 2993 LookupHelper(Name name, Type site, List<Type> argtypes, List<Type> typeargtypes, MethodResolutionPhase maxPhase) { 2994 this.name = name; 2995 this.site = site; 2996 this.argtypes = argtypes; 2997 this.typeargtypes = typeargtypes; 2998 this.maxPhase = maxPhase; 2999 } 3000 3001 /** 3002 * Should lookup stop at given phase with given result 3003 */ 3004 final boolean shouldStop(Symbol sym, MethodResolutionPhase phase) { 3005 return phase.ordinal() > maxPhase.ordinal() || 3006 !sym.kind.isResolutionError() || sym.kind == AMBIGUOUS; 3007 } 3008 3009 /** 3010 * Search for a symbol under a given overload resolution phase - this method 3011 * is usually called several times, once per each overload resolution phase 3012 */ 3013 abstract Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase); 3014 3015 /** 3016 * Dump overload resolution info 3017 */ 3018 void debug(DiagnosticPosition pos, Symbol sym) { 3019 //do nothing 3020 } 3021 3022 /** 3023 * Validate the result of the lookup 3024 */ 3025 abstract Symbol access(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, Symbol sym); 3026 } 3027 3028 abstract class BasicLookupHelper extends LookupHelper { 3029 3030 BasicLookupHelper(Name name, Type site, List<Type> argtypes, List<Type> typeargtypes) { 3031 this(name, site, argtypes, typeargtypes, MethodResolutionPhase.VARARITY); 3032 } 3033 3034 BasicLookupHelper(Name name, Type site, List<Type> argtypes, List<Type> typeargtypes, MethodResolutionPhase maxPhase) { 3035 super(name, site, argtypes, typeargtypes, maxPhase); 3036 } 3037 3038 @Override 3039 final Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) { 3040 Symbol sym = doLookup(env, phase); 3041 if (sym.kind == AMBIGUOUS) { 3042 AmbiguityError a_err = (AmbiguityError)sym.baseSymbol(); 3043 sym = a_err.mergeAbstracts(site); 3044 } 3045 return sym; 3046 } 3047 3048 abstract Symbol doLookup(Env<AttrContext> env, MethodResolutionPhase phase); 3049 3050 @Override 3051 Symbol access(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, Symbol sym) { 3052 if (sym.kind.isResolutionError()) { 3053 //if nothing is found return the 'first' error 3054 sym = accessMethod(sym, pos, location, site, name, true, argtypes, typeargtypes); 3055 } 3056 return sym; 3057 } 3058 3059 @Override 3060 void debug(DiagnosticPosition pos, Symbol sym) { 3061 reportVerboseResolutionDiagnostic(pos, name, site, argtypes, typeargtypes, sym); 3062 } 3063 } 3064 3065 /** 3066 * Helper class for member reference lookup. A reference lookup helper 3067 * defines the basic logic for member reference lookup; a method gives 3068 * access to an 'unbound' helper used to perform an unbound member 3069 * reference lookup. 3070 */ 3071 abstract class ReferenceLookupHelper extends LookupHelper { 3072 3073 /** The member reference tree */ 3074 JCMemberReference referenceTree; 3075 3076 ReferenceLookupHelper(JCMemberReference referenceTree, Name name, Type site, 3077 List<Type> argtypes, List<Type> typeargtypes, MethodResolutionPhase maxPhase) { 3078 super(name, site, argtypes, typeargtypes, maxPhase); 3079 this.referenceTree = referenceTree; 3080 } 3081 3082 /** 3083 * Returns an unbound version of this lookup helper. By default, this 3084 * method returns an dummy lookup helper. 3085 */ 3086 ReferenceLookupHelper unboundLookup(InferenceContext inferenceContext) { 3087 return null; 3088 } 3089 3090 /** 3091 * Get the kind of the member reference 3092 */ 3093 abstract JCMemberReference.ReferenceKind referenceKind(Symbol sym); 3094 3095 Symbol access(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, Symbol sym) { 3096 if (sym.kind == AMBIGUOUS) { 3097 AmbiguityError a_err = (AmbiguityError)sym.baseSymbol(); 3098 sym = a_err.mergeAbstracts(site); 3099 } 3100 //skip error reporting 3101 return sym; 3102 } 3103 } 3104 3105 /** 3106 * Helper class for method reference lookup. The lookup logic is based 3107 * upon Resolve.findMethod; in certain cases, this helper class has a 3108 * corresponding unbound helper class (see UnboundMethodReferenceLookupHelper). 3109 * In such cases, non-static lookup results are thrown away. 3110 */ 3111 class MethodReferenceLookupHelper extends ReferenceLookupHelper { 3112 3113 /** The original method reference lookup site. */ 3114 Type originalSite; 3115 3116 MethodReferenceLookupHelper(JCMemberReference referenceTree, Name name, Type site, 3117 List<Type> argtypes, List<Type> typeargtypes, MethodResolutionPhase maxPhase) { 3118 super(referenceTree, name, types.skipTypeVars(site, true), argtypes, typeargtypes, maxPhase); 3119 this.originalSite = site; 3120 } 3121 3122 @Override 3123 final Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) { 3124 return findMethod(env, site, name, argtypes, typeargtypes, 3125 phase.isBoxingRequired(), phase.isVarargsRequired()); 3126 } 3127 3128 @Override 3129 ReferenceLookupHelper unboundLookup(InferenceContext inferenceContext) { 3130 if (TreeInfo.isStaticSelector(referenceTree.expr, names)) { 3131 if (argtypes.nonEmpty() && 3132 (argtypes.head.hasTag(NONE) || 3133 types.isSubtypeUnchecked(inferenceContext.asUndetVar(argtypes.head), site))) { 3134 return new UnboundMethodReferenceLookupHelper(referenceTree, name, 3135 originalSite, argtypes, typeargtypes, maxPhase); 3136 } else { 3137 return new ReferenceLookupHelper(referenceTree, name, site, argtypes, typeargtypes, maxPhase) { 3138 @Override 3139 ReferenceLookupHelper unboundLookup(InferenceContext inferenceContext) { 3140 return this; 3141 } 3142 3143 @Override 3144 Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) { 3145 return methodNotFound; 3146 } 3147 3148 @Override 3149 ReferenceKind referenceKind(Symbol sym) { 3150 Assert.error(); 3151 return null; 3152 } 3153 }; 3154 } 3155 } else { 3156 return super.unboundLookup(inferenceContext); 3157 } 3158 } 3159 3160 @Override 3161 ReferenceKind referenceKind(Symbol sym) { 3162 if (sym.isStatic()) { 3163 return ReferenceKind.STATIC; 3164 } else { 3165 Name selName = TreeInfo.name(referenceTree.getQualifierExpression()); 3166 return selName != null && selName == names._super ? 3167 ReferenceKind.SUPER : 3168 ReferenceKind.BOUND; 3169 } 3170 } 3171 } 3172 3173 /** 3174 * Helper class for unbound method reference lookup. Essentially the same 3175 * as the basic method reference lookup helper; main difference is that static 3176 * lookup results are thrown away. If qualifier type is raw, an attempt to 3177 * infer a parameterized type is made using the first actual argument (that 3178 * would otherwise be ignored during the lookup). 3179 */ 3180 class UnboundMethodReferenceLookupHelper extends MethodReferenceLookupHelper { 3181 3182 UnboundMethodReferenceLookupHelper(JCMemberReference referenceTree, Name name, Type site, 3183 List<Type> argtypes, List<Type> typeargtypes, MethodResolutionPhase maxPhase) { 3184 super(referenceTree, name, site, argtypes.tail, typeargtypes, maxPhase); 3185 if (site.isRaw() && !argtypes.head.hasTag(NONE)) { 3186 Type asSuperSite = types.asSuper(argtypes.head, site.tsym); 3187 this.site = types.skipTypeVars(asSuperSite, true); 3188 } 3189 } 3190 3191 @Override 3192 ReferenceLookupHelper unboundLookup(InferenceContext inferenceContext) { 3193 return this; 3194 } 3195 3196 @Override 3197 ReferenceKind referenceKind(Symbol sym) { 3198 return ReferenceKind.UNBOUND; 3199 } 3200 } 3201 3202 /** 3203 * Helper class for array constructor lookup; an array constructor lookup 3204 * is simulated by looking up a method that returns the array type specified 3205 * as qualifier, and that accepts a single int parameter (size of the array). 3206 */ 3207 class ArrayConstructorReferenceLookupHelper extends ReferenceLookupHelper { 3208 3209 ArrayConstructorReferenceLookupHelper(JCMemberReference referenceTree, Type site, List<Type> argtypes, 3210 List<Type> typeargtypes, MethodResolutionPhase maxPhase) { 3211 super(referenceTree, names.init, site, argtypes, typeargtypes, maxPhase); 3212 } 3213 3214 @Override 3215 protected Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) { 3216 WriteableScope sc = WriteableScope.create(syms.arrayClass); 3217 MethodSymbol arrayConstr = new MethodSymbol(PUBLIC, name, null, site.tsym); 3218 arrayConstr.type = new MethodType(List.<Type>of(syms.intType), site, List.<Type>nil(), syms.methodClass); 3219 sc.enter(arrayConstr); 3220 return findMethodInScope(env, site, name, argtypes, typeargtypes, sc, methodNotFound, phase.isBoxingRequired(), phase.isVarargsRequired(), false); 3221 } 3222 3223 @Override 3224 ReferenceKind referenceKind(Symbol sym) { 3225 return ReferenceKind.ARRAY_CTOR; 3226 } 3227 } 3228 3229 /** 3230 * Helper class for constructor reference lookup. The lookup logic is based 3231 * upon either Resolve.findMethod or Resolve.findDiamond - depending on 3232 * whether the constructor reference needs diamond inference (this is the case 3233 * if the qualifier type is raw). A special erroneous symbol is returned 3234 * if the lookup returns the constructor of an inner class and there's no 3235 * enclosing instance in scope. 3236 */ 3237 class ConstructorReferenceLookupHelper extends ReferenceLookupHelper { 3238 3239 boolean needsInference; 3240 3241 ConstructorReferenceLookupHelper(JCMemberReference referenceTree, Type site, List<Type> argtypes, 3242 List<Type> typeargtypes, MethodResolutionPhase maxPhase) { 3243 super(referenceTree, names.init, site, argtypes, typeargtypes, maxPhase); 3244 if (site.isRaw()) { 3245 this.site = new ClassType(site.getEnclosingType(), site.tsym.type.getTypeArguments(), site.tsym, site.getMetadata()); 3246 needsInference = true; 3247 } 3248 } 3249 3250 @Override 3251 protected Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) { 3252 Symbol sym = needsInference ? 3253 findDiamond(env, site, argtypes, typeargtypes, phase.isBoxingRequired(), phase.isVarargsRequired()) : 3254 findMethod(env, site, name, argtypes, typeargtypes, 3255 phase.isBoxingRequired(), phase.isVarargsRequired()); 3256 return enclosingInstanceMissing(env, site) ? new BadConstructorReferenceError(sym) : sym; 3257 } 3258 3259 @Override 3260 ReferenceKind referenceKind(Symbol sym) { 3261 return site.getEnclosingType().hasTag(NONE) ? 3262 ReferenceKind.TOPLEVEL : ReferenceKind.IMPLICIT_INNER; 3263 } 3264 } 3265 3266 /** 3267 * Main overload resolution routine. On each overload resolution step, a 3268 * lookup helper class is used to perform the method/constructor lookup; 3269 * at the end of the lookup, the helper is used to validate the results 3270 * (this last step might trigger overload resolution diagnostics). 3271 */ 3272 Symbol lookupMethod(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, MethodCheck methodCheck, LookupHelper lookupHelper) { 3273 MethodResolutionContext resolveContext = new MethodResolutionContext(); 3274 resolveContext.methodCheck = methodCheck; 3275 return lookupMethod(env, pos, location, resolveContext, lookupHelper); 3276 } 3277 3278 Symbol lookupMethod(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, 3279 MethodResolutionContext resolveContext, LookupHelper lookupHelper) { 3280 MethodResolutionContext prevResolutionContext = currentResolutionContext; 3281 try { 3282 Symbol bestSoFar = methodNotFound; 3283 currentResolutionContext = resolveContext; 3284 for (MethodResolutionPhase phase : methodResolutionSteps) { 3285 if (lookupHelper.shouldStop(bestSoFar, phase)) 3286 break; 3287 MethodResolutionPhase prevPhase = currentResolutionContext.step; 3288 Symbol prevBest = bestSoFar; 3289 currentResolutionContext.step = phase; 3290 Symbol sym = lookupHelper.lookup(env, phase); 3291 lookupHelper.debug(pos, sym); 3292 bestSoFar = phase.mergeResults(bestSoFar, sym); 3293 env.info.pendingResolutionPhase = (prevBest == bestSoFar) ? prevPhase : phase; 3294 } 3295 return lookupHelper.access(env, pos, location, bestSoFar); 3296 } finally { 3297 currentResolutionContext = prevResolutionContext; 3298 } 3299 } 3300 3301 /** 3302 * Resolve `c.name' where name == this or name == super. 3303 * @param pos The position to use for error reporting. 3304 * @param env The environment current at the expression. 3305 * @param c The qualifier. 3306 * @param name The identifier's name. 3307 */ 3308 Symbol resolveSelf(DiagnosticPosition pos, 3309 Env<AttrContext> env, 3310 TypeSymbol c, 3311 Name name) { 3312 Env<AttrContext> env1 = env; 3313 boolean staticOnly = false; 3314 while (env1.outer != null) { 3315 if (isStatic(env1)) staticOnly = true; 3316 if (env1.enclClass.sym == c) { 3317 Symbol sym = env1.info.scope.findFirst(name); 3318 if (sym != null) { 3319 if (staticOnly) sym = new StaticError(sym); 3320 return accessBase(sym, pos, env.enclClass.sym.type, 3321 name, true); 3322 } 3323 } 3324 if ((env1.enclClass.sym.flags() & STATIC) != 0) staticOnly = true; 3325 env1 = env1.outer; 3326 } 3327 if (c.isInterface() && 3328 name == names._super && !isStatic(env) && 3329 types.isDirectSuperInterface(c, env.enclClass.sym)) { 3330 //this might be a default super call if one of the superinterfaces is 'c' 3331 for (Type t : pruneInterfaces(env.enclClass.type)) { 3332 if (t.tsym == c) { 3333 env.info.defaultSuperCallSite = t; 3334 return new VarSymbol(0, names._super, 3335 types.asSuper(env.enclClass.type, c), env.enclClass.sym); 3336 } 3337 } 3338 //find a direct superinterface that is a subtype of 'c' 3339 for (Type i : types.interfaces(env.enclClass.type)) { 3340 if (i.tsym.isSubClass(c, types) && i.tsym != c) { 3341 log.error(pos, "illegal.default.super.call", c, 3342 diags.fragment("redundant.supertype", c, i)); 3343 return syms.errSymbol; 3344 } 3345 } 3346 Assert.error(); 3347 } 3348 log.error(pos, "not.encl.class", c); 3349 return syms.errSymbol; 3350 } 3351 //where 3352 private List<Type> pruneInterfaces(Type t) { 3353 ListBuffer<Type> result = new ListBuffer<>(); 3354 for (Type t1 : types.interfaces(t)) { 3355 boolean shouldAdd = true; 3356 for (Type t2 : types.interfaces(t)) { 3357 if (t1 != t2 && types.isSubtypeNoCapture(t2, t1)) { 3358 shouldAdd = false; 3359 } 3360 } 3361 if (shouldAdd) { 3362 result.append(t1); 3363 } 3364 } 3365 return result.toList(); 3366 } 3367 3368 3369 /** 3370 * Resolve `c.this' for an enclosing class c that contains the 3371 * named member. 3372 * @param pos The position to use for error reporting. 3373 * @param env The environment current at the expression. 3374 * @param member The member that must be contained in the result. 3375 */ 3376 Symbol resolveSelfContaining(DiagnosticPosition pos, 3377 Env<AttrContext> env, 3378 Symbol member, 3379 boolean isSuperCall) { 3380 Symbol sym = resolveSelfContainingInternal(env, member, isSuperCall); 3381 if (sym == null) { 3382 log.error(pos, "encl.class.required", member); 3383 return syms.errSymbol; 3384 } else { 3385 return accessBase(sym, pos, env.enclClass.sym.type, sym.name, true); 3386 } 3387 } 3388 3389 boolean enclosingInstanceMissing(Env<AttrContext> env, Type type) { 3390 if (type.hasTag(CLASS) && type.getEnclosingType().hasTag(CLASS)) { 3391 Symbol encl = resolveSelfContainingInternal(env, type.tsym, false); 3392 return encl == null || encl.kind.isResolutionError(); 3393 } 3394 return false; 3395 } 3396 3397 private Symbol resolveSelfContainingInternal(Env<AttrContext> env, 3398 Symbol member, 3399 boolean isSuperCall) { 3400 Name name = names._this; 3401 Env<AttrContext> env1 = isSuperCall ? env.outer : env; 3402 boolean staticOnly = false; 3403 if (env1 != null) { 3404 while (env1 != null && env1.outer != null) { 3405 if (isStatic(env1)) staticOnly = true; 3406 if (env1.enclClass.sym.isSubClass(member.owner.enclClass(), types)) { 3407 Symbol sym = env1.info.scope.findFirst(name); 3408 if (sym != null) { 3409 if (staticOnly) sym = new StaticError(sym); 3410 return sym; 3411 } 3412 } 3413 if ((env1.enclClass.sym.flags() & STATIC) != 0) 3414 staticOnly = true; 3415 env1 = env1.outer; 3416 } 3417 } 3418 return null; 3419 } 3420 3421 /** 3422 * Resolve an appropriate implicit this instance for t's container. 3423 * JLS 8.8.5.1 and 15.9.2 3424 */ 3425 Type resolveImplicitThis(DiagnosticPosition pos, Env<AttrContext> env, Type t) { 3426 return resolveImplicitThis(pos, env, t, false); 3427 } 3428 3429 Type resolveImplicitThis(DiagnosticPosition pos, Env<AttrContext> env, Type t, boolean isSuperCall) { 3430 Type thisType = (t.tsym.owner.kind.matches(KindSelector.VAL_MTH) 3431 ? resolveSelf(pos, env, t.getEnclosingType().tsym, names._this) 3432 : resolveSelfContaining(pos, env, t.tsym, isSuperCall)).type; 3433 if (env.info.isSelfCall && thisType.tsym == env.enclClass.sym) 3434 log.error(pos, "cant.ref.before.ctor.called", "this"); 3435 return thisType; 3436 } 3437 3438/* *************************************************************************** 3439 * ResolveError classes, indicating error situations when accessing symbols 3440 ****************************************************************************/ 3441 3442 //used by TransTypes when checking target type of synthetic cast 3443 public void logAccessErrorInternal(Env<AttrContext> env, JCTree tree, Type type) { 3444 AccessError error = new AccessError(env, env.enclClass.type, type.tsym); 3445 logResolveError(error, tree.pos(), env.enclClass.sym, env.enclClass.type, null, null, null); 3446 } 3447 //where 3448 private void logResolveError(ResolveError error, 3449 DiagnosticPosition pos, 3450 Symbol location, 3451 Type site, 3452 Name name, 3453 List<Type> argtypes, 3454 List<Type> typeargtypes) { 3455 JCDiagnostic d = error.getDiagnostic(JCDiagnostic.DiagnosticType.ERROR, 3456 pos, location, site, name, argtypes, typeargtypes); 3457 if (d != null) { 3458 d.setFlag(DiagnosticFlag.RESOLVE_ERROR); 3459 log.report(d); 3460 } 3461 } 3462 3463 private final LocalizedString noArgs = new LocalizedString("compiler.misc.no.args"); 3464 3465 public Object methodArguments(List<Type> argtypes) { 3466 if (argtypes == null || argtypes.isEmpty()) { 3467 return noArgs; 3468 } else { 3469 ListBuffer<Object> diagArgs = new ListBuffer<>(); 3470 for (Type t : argtypes) { 3471 if (t.hasTag(DEFERRED)) { 3472 diagArgs.append(((DeferredAttr.DeferredType)t).tree); 3473 } else { 3474 diagArgs.append(t); 3475 } 3476 } 3477 return diagArgs; 3478 } 3479 } 3480 3481 /** 3482 * Root class for resolution errors. Subclass of ResolveError 3483 * represent a different kinds of resolution error - as such they must 3484 * specify how they map into concrete compiler diagnostics. 3485 */ 3486 abstract class ResolveError extends Symbol { 3487 3488 /** The name of the kind of error, for debugging only. */ 3489 final String debugName; 3490 3491 ResolveError(Kind kind, String debugName) { 3492 super(kind, 0, null, null, null); 3493 this.debugName = debugName; 3494 } 3495 3496 @Override @DefinedBy(Api.LANGUAGE_MODEL) 3497 public <R, P> R accept(ElementVisitor<R, P> v, P p) { 3498 throw new AssertionError(); 3499 } 3500 3501 @Override 3502 public String toString() { 3503 return debugName; 3504 } 3505 3506 @Override 3507 public boolean exists() { 3508 return false; 3509 } 3510 3511 @Override 3512 public boolean isStatic() { 3513 return false; 3514 } 3515 3516 /** 3517 * Create an external representation for this erroneous symbol to be 3518 * used during attribution - by default this returns the symbol of a 3519 * brand new error type which stores the original type found 3520 * during resolution. 3521 * 3522 * @param name the name used during resolution 3523 * @param location the location from which the symbol is accessed 3524 */ 3525 protected Symbol access(Name name, TypeSymbol location) { 3526 return types.createErrorType(name, location, syms.errSymbol.type).tsym; 3527 } 3528 3529 /** 3530 * Create a diagnostic representing this resolution error. 3531 * 3532 * @param dkind The kind of the diagnostic to be created (e.g error). 3533 * @param pos The position to be used for error reporting. 3534 * @param site The original type from where the selection took place. 3535 * @param name The name of the symbol to be resolved. 3536 * @param argtypes The invocation's value arguments, 3537 * if we looked for a method. 3538 * @param typeargtypes The invocation's type arguments, 3539 * if we looked for a method. 3540 */ 3541 abstract JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind, 3542 DiagnosticPosition pos, 3543 Symbol location, 3544 Type site, 3545 Name name, 3546 List<Type> argtypes, 3547 List<Type> typeargtypes); 3548 } 3549 3550 /** 3551 * This class is the root class of all resolution errors caused by 3552 * an invalid symbol being found during resolution. 3553 */ 3554 abstract class InvalidSymbolError extends ResolveError { 3555 3556 /** The invalid symbol found during resolution */ 3557 Symbol sym; 3558 3559 InvalidSymbolError(Kind kind, Symbol sym, String debugName) { 3560 super(kind, debugName); 3561 this.sym = sym; 3562 } 3563 3564 @Override 3565 public boolean exists() { 3566 return true; 3567 } 3568 3569 @Override 3570 public String toString() { 3571 return super.toString() + " wrongSym=" + sym; 3572 } 3573 3574 @Override 3575 public Symbol access(Name name, TypeSymbol location) { 3576 if (!sym.kind.isResolutionError() && sym.kind.matches(KindSelector.TYP)) 3577 return types.createErrorType(name, location, sym.type).tsym; 3578 else 3579 return sym; 3580 } 3581 } 3582 3583 /** 3584 * InvalidSymbolError error class indicating that a symbol matching a 3585 * given name does not exists in a given site. 3586 */ 3587 class SymbolNotFoundError extends ResolveError { 3588 3589 SymbolNotFoundError(Kind kind) { 3590 this(kind, "symbol not found error"); 3591 } 3592 3593 SymbolNotFoundError(Kind kind, String debugName) { 3594 super(kind, debugName); 3595 } 3596 3597 @Override 3598 JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind, 3599 DiagnosticPosition pos, 3600 Symbol location, 3601 Type site, 3602 Name name, 3603 List<Type> argtypes, 3604 List<Type> typeargtypes) { 3605 argtypes = argtypes == null ? List.<Type>nil() : argtypes; 3606 typeargtypes = typeargtypes == null ? List.<Type>nil() : typeargtypes; 3607 if (name == names.error) 3608 return null; 3609 3610 boolean hasLocation = false; 3611 if (location == null) { 3612 location = site.tsym; 3613 } 3614 if (!location.name.isEmpty()) { 3615 if (location.kind == PCK && !site.tsym.exists()) { 3616 return diags.create(dkind, log.currentSource(), pos, 3617 "doesnt.exist", location); 3618 } 3619 hasLocation = !location.name.equals(names._this) && 3620 !location.name.equals(names._super); 3621 } 3622 boolean isConstructor = name == names.init; 3623 KindName kindname = isConstructor ? KindName.CONSTRUCTOR : kind.absentKind(); 3624 Name idname = isConstructor ? site.tsym.name : name; 3625 String errKey = getErrorKey(kindname, typeargtypes.nonEmpty(), hasLocation); 3626 if (hasLocation) { 3627 return diags.create(dkind, log.currentSource(), pos, 3628 errKey, kindname, idname, //symbol kindname, name 3629 typeargtypes, args(argtypes), //type parameters and arguments (if any) 3630 getLocationDiag(location, site)); //location kindname, type 3631 } 3632 else { 3633 return diags.create(dkind, log.currentSource(), pos, 3634 errKey, kindname, idname, //symbol kindname, name 3635 typeargtypes, args(argtypes)); //type parameters and arguments (if any) 3636 } 3637 } 3638 //where 3639 private Object args(List<Type> args) { 3640 return args.isEmpty() ? args : methodArguments(args); 3641 } 3642 3643 private String getErrorKey(KindName kindname, boolean hasTypeArgs, boolean hasLocation) { 3644 String key = "cant.resolve"; 3645 String suffix = hasLocation ? ".location" : ""; 3646 switch (kindname) { 3647 case METHOD: 3648 case CONSTRUCTOR: { 3649 suffix += ".args"; 3650 suffix += hasTypeArgs ? ".params" : ""; 3651 } 3652 } 3653 return key + suffix; 3654 } 3655 private JCDiagnostic getLocationDiag(Symbol location, Type site) { 3656 if (location.kind == VAR) { 3657 return diags.fragment("location.1", 3658 kindName(location), 3659 location, 3660 location.type); 3661 } else { 3662 return diags.fragment("location", 3663 typeKindName(site), 3664 site, 3665 null); 3666 } 3667 } 3668 } 3669 3670 /** 3671 * InvalidSymbolError error class indicating that a given symbol 3672 * (either a method, a constructor or an operand) is not applicable 3673 * given an actual arguments/type argument list. 3674 */ 3675 class InapplicableSymbolError extends ResolveError { 3676 3677 protected MethodResolutionContext resolveContext; 3678 3679 InapplicableSymbolError(MethodResolutionContext context) { 3680 this(WRONG_MTH, "inapplicable symbol error", context); 3681 } 3682 3683 protected InapplicableSymbolError(Kind kind, String debugName, MethodResolutionContext context) { 3684 super(kind, debugName); 3685 this.resolveContext = context; 3686 } 3687 3688 @Override 3689 public String toString() { 3690 return super.toString(); 3691 } 3692 3693 @Override 3694 public boolean exists() { 3695 return true; 3696 } 3697 3698 @Override 3699 JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind, 3700 DiagnosticPosition pos, 3701 Symbol location, 3702 Type site, 3703 Name name, 3704 List<Type> argtypes, 3705 List<Type> typeargtypes) { 3706 if (name == names.error) 3707 return null; 3708 3709 Pair<Symbol, JCDiagnostic> c = errCandidate(); 3710 if (compactMethodDiags) { 3711 JCDiagnostic simpleDiag = 3712 MethodResolutionDiagHelper.rewrite(diags, pos, log.currentSource(), dkind, c.snd); 3713 if (simpleDiag != null) { 3714 return simpleDiag; 3715 } 3716 } 3717 Symbol ws = c.fst.asMemberOf(site, types); 3718 return diags.create(dkind, log.currentSource(), pos, 3719 "cant.apply.symbol", 3720 kindName(ws), 3721 ws.name == names.init ? ws.owner.name : ws.name, 3722 methodArguments(ws.type.getParameterTypes()), 3723 methodArguments(argtypes), 3724 kindName(ws.owner), 3725 ws.owner.type, 3726 c.snd); 3727 } 3728 3729 @Override 3730 public Symbol access(Name name, TypeSymbol location) { 3731 return types.createErrorType(name, location, syms.errSymbol.type).tsym; 3732 } 3733 3734 protected Pair<Symbol, JCDiagnostic> errCandidate() { 3735 Candidate bestSoFar = null; 3736 for (Candidate c : resolveContext.candidates) { 3737 if (c.isApplicable()) continue; 3738 bestSoFar = c; 3739 } 3740 Assert.checkNonNull(bestSoFar); 3741 return new Pair<>(bestSoFar.sym, bestSoFar.details); 3742 } 3743 } 3744 3745 /** 3746 * ResolveError error class indicating that a symbol (either methods, constructors or operand) 3747 * is not applicable given an actual arguments/type argument list. 3748 */ 3749 class InapplicableSymbolsError extends InapplicableSymbolError { 3750 3751 InapplicableSymbolsError(MethodResolutionContext context) { 3752 super(WRONG_MTHS, "inapplicable symbols", context); 3753 } 3754 3755 @Override 3756 JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind, 3757 DiagnosticPosition pos, 3758 Symbol location, 3759 Type site, 3760 Name name, 3761 List<Type> argtypes, 3762 List<Type> typeargtypes) { 3763 Map<Symbol, JCDiagnostic> candidatesMap = mapCandidates(); 3764 Map<Symbol, JCDiagnostic> filteredCandidates = compactMethodDiags ? 3765 filterCandidates(candidatesMap) : 3766 mapCandidates(); 3767 if (filteredCandidates.isEmpty()) { 3768 filteredCandidates = candidatesMap; 3769 } 3770 boolean truncatedDiag = candidatesMap.size() != filteredCandidates.size(); 3771 if (filteredCandidates.size() > 1) { 3772 JCDiagnostic err = diags.create(dkind, 3773 null, 3774 truncatedDiag ? 3775 EnumSet.of(DiagnosticFlag.COMPRESSED) : 3776 EnumSet.noneOf(DiagnosticFlag.class), 3777 log.currentSource(), 3778 pos, 3779 "cant.apply.symbols", 3780 name == names.init ? KindName.CONSTRUCTOR : kind.absentKind(), 3781 name == names.init ? site.tsym.name : name, 3782 methodArguments(argtypes)); 3783 return new JCDiagnostic.MultilineDiagnostic(err, candidateDetails(filteredCandidates, site)); 3784 } else if (filteredCandidates.size() == 1) { 3785 Map.Entry<Symbol, JCDiagnostic> _e = 3786 filteredCandidates.entrySet().iterator().next(); 3787 final Pair<Symbol, JCDiagnostic> p = new Pair<>(_e.getKey(), _e.getValue()); 3788 JCDiagnostic d = new InapplicableSymbolError(resolveContext) { 3789 @Override 3790 protected Pair<Symbol, JCDiagnostic> errCandidate() { 3791 return p; 3792 } 3793 }.getDiagnostic(dkind, pos, 3794 location, site, name, argtypes, typeargtypes); 3795 if (truncatedDiag) { 3796 d.setFlag(DiagnosticFlag.COMPRESSED); 3797 } 3798 return d; 3799 } else { 3800 return new SymbolNotFoundError(ABSENT_MTH).getDiagnostic(dkind, pos, 3801 location, site, name, argtypes, typeargtypes); 3802 } 3803 } 3804 //where 3805 private Map<Symbol, JCDiagnostic> mapCandidates() { 3806 Map<Symbol, JCDiagnostic> candidates = new LinkedHashMap<>(); 3807 for (Candidate c : resolveContext.candidates) { 3808 if (c.isApplicable()) continue; 3809 candidates.put(c.sym, c.details); 3810 } 3811 return candidates; 3812 } 3813 3814 Map<Symbol, JCDiagnostic> filterCandidates(Map<Symbol, JCDiagnostic> candidatesMap) { 3815 Map<Symbol, JCDiagnostic> candidates = new LinkedHashMap<>(); 3816 for (Map.Entry<Symbol, JCDiagnostic> _entry : candidatesMap.entrySet()) { 3817 JCDiagnostic d = _entry.getValue(); 3818 if (!new Template(MethodCheckDiag.ARITY_MISMATCH.regex()).matches(d)) { 3819 candidates.put(_entry.getKey(), d); 3820 } 3821 } 3822 return candidates; 3823 } 3824 3825 private List<JCDiagnostic> candidateDetails(Map<Symbol, JCDiagnostic> candidatesMap, Type site) { 3826 List<JCDiagnostic> details = List.nil(); 3827 for (Map.Entry<Symbol, JCDiagnostic> _entry : candidatesMap.entrySet()) { 3828 Symbol sym = _entry.getKey(); 3829 JCDiagnostic detailDiag = diags.fragment("inapplicable.method", 3830 Kinds.kindName(sym), 3831 sym.location(site, types), 3832 sym.asMemberOf(site, types), 3833 _entry.getValue()); 3834 details = details.prepend(detailDiag); 3835 } 3836 //typically members are visited in reverse order (see Scope) 3837 //so we need to reverse the candidate list so that candidates 3838 //conform to source order 3839 return details; 3840 } 3841 } 3842 3843 /** 3844 * DiamondError error class indicating that a constructor symbol is not applicable 3845 * given an actual arguments/type argument list using diamond inference. 3846 */ 3847 class DiamondError extends InapplicableSymbolError { 3848 3849 Symbol sym; 3850 3851 public DiamondError(Symbol sym, MethodResolutionContext context) { 3852 super(sym.kind, "diamondError", context); 3853 this.sym = sym; 3854 } 3855 3856 JCDiagnostic getDetails() { 3857 return (sym.kind == WRONG_MTH) ? 3858 ((InapplicableSymbolError)sym.baseSymbol()).errCandidate().snd : 3859 null; 3860 } 3861 3862 @Override 3863 JCDiagnostic getDiagnostic(DiagnosticType dkind, DiagnosticPosition pos, 3864 Symbol location, Type site, Name name, List<Type> argtypes, List<Type> typeargtypes) { 3865 JCDiagnostic details = getDetails(); 3866 if (details != null && compactMethodDiags) { 3867 JCDiagnostic simpleDiag = 3868 MethodResolutionDiagHelper.rewrite(diags, pos, log.currentSource(), dkind, details); 3869 if (simpleDiag != null) { 3870 return simpleDiag; 3871 } 3872 } 3873 String key = details == null ? 3874 "cant.apply.diamond" : 3875 "cant.apply.diamond.1"; 3876 return diags.create(dkind, log.currentSource(), pos, key, 3877 diags.fragment("diamond", site.tsym), details); 3878 } 3879 } 3880 3881 /** 3882 * An InvalidSymbolError error class indicating that a symbol is not 3883 * accessible from a given site 3884 */ 3885 class AccessError extends InvalidSymbolError { 3886 3887 private Env<AttrContext> env; 3888 private Type site; 3889 3890 AccessError(Symbol sym) { 3891 this(null, null, sym); 3892 } 3893 3894 AccessError(Env<AttrContext> env, Type site, Symbol sym) { 3895 super(HIDDEN, sym, "access error"); 3896 this.env = env; 3897 this.site = site; 3898 } 3899 3900 @Override 3901 public boolean exists() { 3902 return false; 3903 } 3904 3905 @Override 3906 JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind, 3907 DiagnosticPosition pos, 3908 Symbol location, 3909 Type site, 3910 Name name, 3911 List<Type> argtypes, 3912 List<Type> typeargtypes) { 3913 if (sym.owner.type.hasTag(ERROR)) 3914 return null; 3915 3916 if (sym.name == names.init && sym.owner != site.tsym) { 3917 return new SymbolNotFoundError(ABSENT_MTH).getDiagnostic(dkind, 3918 pos, location, site, name, argtypes, typeargtypes); 3919 } 3920 else if ((sym.flags() & PUBLIC) != 0 3921 || (env != null && this.site != null 3922 && !isAccessible(env, this.site))) { 3923 return diags.create(dkind, log.currentSource(), 3924 pos, "not.def.access.class.intf.cant.access", 3925 sym, sym.location()); 3926 } 3927 else if ((sym.flags() & (PRIVATE | PROTECTED)) != 0) { 3928 return diags.create(dkind, log.currentSource(), 3929 pos, "report.access", sym, 3930 asFlagSet(sym.flags() & (PRIVATE | PROTECTED)), 3931 sym.location()); 3932 } 3933 else { 3934 return diags.create(dkind, log.currentSource(), 3935 pos, "not.def.public.cant.access", sym, sym.location()); 3936 } 3937 } 3938 } 3939 3940 /** 3941 * InvalidSymbolError error class indicating that an instance member 3942 * has erroneously been accessed from a static context. 3943 */ 3944 class StaticError extends InvalidSymbolError { 3945 3946 StaticError(Symbol sym) { 3947 super(STATICERR, sym, "static error"); 3948 } 3949 3950 @Override 3951 JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind, 3952 DiagnosticPosition pos, 3953 Symbol location, 3954 Type site, 3955 Name name, 3956 List<Type> argtypes, 3957 List<Type> typeargtypes) { 3958 Symbol errSym = ((sym.kind == TYP && sym.type.hasTag(CLASS)) 3959 ? types.erasure(sym.type).tsym 3960 : sym); 3961 return diags.create(dkind, log.currentSource(), pos, 3962 "non-static.cant.be.ref", kindName(sym), errSym); 3963 } 3964 } 3965 3966 /** 3967 * InvalidSymbolError error class indicating that a pair of symbols 3968 * (either methods, constructors or operands) are ambiguous 3969 * given an actual arguments/type argument list. 3970 */ 3971 class AmbiguityError extends ResolveError { 3972 3973 /** The other maximally specific symbol */ 3974 List<Symbol> ambiguousSyms = List.nil(); 3975 3976 @Override 3977 public boolean exists() { 3978 return true; 3979 } 3980 3981 AmbiguityError(Symbol sym1, Symbol sym2) { 3982 super(AMBIGUOUS, "ambiguity error"); 3983 ambiguousSyms = flatten(sym2).appendList(flatten(sym1)); 3984 } 3985 3986 private List<Symbol> flatten(Symbol sym) { 3987 if (sym.kind == AMBIGUOUS) { 3988 return ((AmbiguityError)sym.baseSymbol()).ambiguousSyms; 3989 } else { 3990 return List.of(sym); 3991 } 3992 } 3993 3994 AmbiguityError addAmbiguousSymbol(Symbol s) { 3995 ambiguousSyms = ambiguousSyms.prepend(s); 3996 return this; 3997 } 3998 3999 @Override 4000 JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind, 4001 DiagnosticPosition pos, 4002 Symbol location, 4003 Type site, 4004 Name name, 4005 List<Type> argtypes, 4006 List<Type> typeargtypes) { 4007 List<Symbol> diagSyms = ambiguousSyms.reverse(); 4008 Symbol s1 = diagSyms.head; 4009 Symbol s2 = diagSyms.tail.head; 4010 Name sname = s1.name; 4011 if (sname == names.init) sname = s1.owner.name; 4012 return diags.create(dkind, log.currentSource(), 4013 pos, "ref.ambiguous", sname, 4014 kindName(s1), 4015 s1, 4016 s1.location(site, types), 4017 kindName(s2), 4018 s2, 4019 s2.location(site, types)); 4020 } 4021 4022 /** 4023 * If multiple applicable methods are found during overload and none of them 4024 * is more specific than the others, attempt to merge their signatures. 4025 */ 4026 Symbol mergeAbstracts(Type site) { 4027 List<Symbol> ambiguousInOrder = ambiguousSyms.reverse(); 4028 for (Symbol s : ambiguousInOrder) { 4029 Type mt = types.memberType(site, s); 4030 boolean found = true; 4031 List<Type> allThrown = mt.getThrownTypes(); 4032 for (Symbol s2 : ambiguousInOrder) { 4033 Type mt2 = types.memberType(site, s2); 4034 if ((s2.flags() & ABSTRACT) == 0 || 4035 !types.overrideEquivalent(mt, mt2) || 4036 !types.isSameTypes(s.erasure(types).getParameterTypes(), 4037 s2.erasure(types).getParameterTypes())) { 4038 //ambiguity cannot be resolved 4039 return this; 4040 } 4041 Type mst = mostSpecificReturnType(mt, mt2); 4042 if (mst == null || mst != mt) { 4043 found = false; 4044 break; 4045 } 4046 allThrown = chk.intersect(allThrown, mt2.getThrownTypes()); 4047 } 4048 if (found) { 4049 //all ambiguous methods were abstract and one method had 4050 //most specific return type then others 4051 return (allThrown == mt.getThrownTypes()) ? 4052 s : new MethodSymbol( 4053 s.flags(), 4054 s.name, 4055 types.createMethodTypeWithThrown(s.type, allThrown), 4056 s.owner); 4057 } 4058 } 4059 return this; 4060 } 4061 4062 @Override 4063 protected Symbol access(Name name, TypeSymbol location) { 4064 Symbol firstAmbiguity = ambiguousSyms.last(); 4065 return firstAmbiguity.kind == TYP ? 4066 types.createErrorType(name, location, firstAmbiguity.type).tsym : 4067 firstAmbiguity; 4068 } 4069 } 4070 4071 class BadVarargsMethod extends ResolveError { 4072 4073 ResolveError delegatedError; 4074 4075 BadVarargsMethod(ResolveError delegatedError) { 4076 super(delegatedError.kind, "badVarargs"); 4077 this.delegatedError = delegatedError; 4078 } 4079 4080 @Override 4081 public Symbol baseSymbol() { 4082 return delegatedError.baseSymbol(); 4083 } 4084 4085 @Override 4086 protected Symbol access(Name name, TypeSymbol location) { 4087 return delegatedError.access(name, location); 4088 } 4089 4090 @Override 4091 public boolean exists() { 4092 return true; 4093 } 4094 4095 @Override 4096 JCDiagnostic getDiagnostic(DiagnosticType dkind, DiagnosticPosition pos, Symbol location, Type site, Name name, List<Type> argtypes, List<Type> typeargtypes) { 4097 return delegatedError.getDiagnostic(dkind, pos, location, site, name, argtypes, typeargtypes); 4098 } 4099 } 4100 4101 /** 4102 * BadMethodReferenceError error class indicating that a method reference symbol has been found, 4103 * but with the wrong staticness. 4104 */ 4105 class BadMethodReferenceError extends StaticError { 4106 4107 boolean unboundLookup; 4108 4109 public BadMethodReferenceError(Symbol sym, boolean unboundLookup) { 4110 super(sym); 4111 this.unboundLookup = unboundLookup; 4112 } 4113 4114 @Override 4115 JCDiagnostic getDiagnostic(DiagnosticType dkind, DiagnosticPosition pos, Symbol location, Type site, Name name, List<Type> argtypes, List<Type> typeargtypes) { 4116 final String key; 4117 if (!unboundLookup) { 4118 key = "bad.static.method.in.bound.lookup"; 4119 } else if (sym.isStatic()) { 4120 key = "bad.static.method.in.unbound.lookup"; 4121 } else { 4122 key = "bad.instance.method.in.unbound.lookup"; 4123 } 4124 return sym.kind.isResolutionError() ? 4125 ((ResolveError)sym).getDiagnostic(dkind, pos, location, site, name, argtypes, typeargtypes) : 4126 diags.create(dkind, log.currentSource(), pos, key, Kinds.kindName(sym), sym); 4127 } 4128 } 4129 4130 /** 4131 * BadConstructorReferenceError error class indicating that a constructor reference symbol has been found, 4132 * but pointing to a class for which an enclosing instance is not available. 4133 */ 4134 class BadConstructorReferenceError extends InvalidSymbolError { 4135 4136 public BadConstructorReferenceError(Symbol sym) { 4137 super(MISSING_ENCL, sym, "BadConstructorReferenceError"); 4138 } 4139 4140 @Override 4141 JCDiagnostic getDiagnostic(DiagnosticType dkind, DiagnosticPosition pos, Symbol location, Type site, Name name, List<Type> argtypes, List<Type> typeargtypes) { 4142 return diags.create(dkind, log.currentSource(), pos, 4143 "cant.access.inner.cls.constr", site.tsym.name, argtypes, site.getEnclosingType()); 4144 } 4145 } 4146 4147 /** 4148 * Helper class for method resolution diagnostic simplification. 4149 * Certain resolution diagnostic are rewritten as simpler diagnostic 4150 * where the enclosing resolution diagnostic (i.e. 'inapplicable method') 4151 * is stripped away, as it doesn't carry additional info. The logic 4152 * for matching a given diagnostic is given in terms of a template 4153 * hierarchy: a diagnostic template can be specified programmatically, 4154 * so that only certain diagnostics are matched. Each templete is then 4155 * associated with a rewriter object that carries out the task of rewtiting 4156 * the diagnostic to a simpler one. 4157 */ 4158 static class MethodResolutionDiagHelper { 4159 4160 /** 4161 * A diagnostic rewriter transforms a method resolution diagnostic 4162 * into a simpler one 4163 */ 4164 interface DiagnosticRewriter { 4165 JCDiagnostic rewriteDiagnostic(JCDiagnostic.Factory diags, 4166 DiagnosticPosition preferedPos, DiagnosticSource preferredSource, 4167 DiagnosticType preferredKind, JCDiagnostic d); 4168 } 4169 4170 /** 4171 * A diagnostic template is made up of two ingredients: (i) a regular 4172 * expression for matching a diagnostic key and (ii) a list of sub-templates 4173 * for matching diagnostic arguments. 4174 */ 4175 static class Template { 4176 4177 /** regex used to match diag key */ 4178 String regex; 4179 4180 /** templates used to match diagnostic args */ 4181 Template[] subTemplates; 4182 4183 Template(String key, Template... subTemplates) { 4184 this.regex = key; 4185 this.subTemplates = subTemplates; 4186 } 4187 4188 /** 4189 * Returns true if the regex matches the diagnostic key and if 4190 * all diagnostic arguments are matches by corresponding sub-templates. 4191 */ 4192 boolean matches(Object o) { 4193 JCDiagnostic d = (JCDiagnostic)o; 4194 Object[] args = d.getArgs(); 4195 if (!d.getCode().matches(regex) || 4196 subTemplates.length != d.getArgs().length) { 4197 return false; 4198 } 4199 for (int i = 0; i < args.length ; i++) { 4200 if (!subTemplates[i].matches(args[i])) { 4201 return false; 4202 } 4203 } 4204 return true; 4205 } 4206 } 4207 4208 /** 4209 * Common rewriter for all argument mismatch simplifications. 4210 */ 4211 static class ArgMismatchRewriter implements DiagnosticRewriter { 4212 4213 /** the index of the subdiagnostic to be used as primary. */ 4214 int causeIndex; 4215 4216 public ArgMismatchRewriter(int causeIndex) { 4217 this.causeIndex = causeIndex; 4218 } 4219 4220 @Override 4221 public JCDiagnostic rewriteDiagnostic(JCDiagnostic.Factory diags, 4222 DiagnosticPosition preferedPos, DiagnosticSource preferredSource, 4223 DiagnosticType preferredKind, JCDiagnostic d) { 4224 JCDiagnostic cause = (JCDiagnostic)d.getArgs()[causeIndex]; 4225 DiagnosticPosition pos = d.getDiagnosticPosition(); 4226 if (pos == null) { 4227 pos = preferedPos; 4228 } 4229 return diags.create(preferredKind, preferredSource, pos, 4230 "prob.found.req", cause); 4231 } 4232 } 4233 4234 /** a dummy template that match any diagnostic argument */ 4235 static final Template skip = new Template("") { 4236 @Override 4237 boolean matches(Object d) { 4238 return true; 4239 } 4240 }; 4241 4242 /** template for matching inference-free arguments mismatch failures */ 4243 static final Template argMismatchTemplate = new Template(MethodCheckDiag.ARG_MISMATCH.regex(), skip); 4244 4245 /** template for matching inference related arguments mismatch failures */ 4246 static final Template inferArgMismatchTemplate = new Template(MethodCheckDiag.ARG_MISMATCH.regex(), skip, skip) { 4247 @Override 4248 boolean matches(Object o) { 4249 if (!super.matches(o)) { 4250 return false; 4251 } 4252 JCDiagnostic d = (JCDiagnostic)o; 4253 @SuppressWarnings("unchecked") 4254 List<Type> tvars = (List<Type>)d.getArgs()[0]; 4255 return !containsAny(d, tvars); 4256 } 4257 4258 BiPredicate<Object, List<Type>> containsPredicate = (o, ts) -> { 4259 if (o instanceof Type) { 4260 return ((Type)o).containsAny(ts); 4261 } else if (o instanceof JCDiagnostic) { 4262 return containsAny((JCDiagnostic)o, ts); 4263 } else { 4264 return false; 4265 } 4266 }; 4267 4268 boolean containsAny(JCDiagnostic d, List<Type> ts) { 4269 return Stream.of(d.getArgs()) 4270 .anyMatch(o -> containsPredicate.test(o, ts)); 4271 } 4272 }; 4273 4274 /** rewriter map used for method resolution simplification */ 4275 static final Map<Template, DiagnosticRewriter> rewriters = new LinkedHashMap<>(); 4276 4277 static { 4278 rewriters.put(argMismatchTemplate, new ArgMismatchRewriter(0)); 4279 rewriters.put(inferArgMismatchTemplate, new ArgMismatchRewriter(1)); 4280 } 4281 4282 /** 4283 * Main entry point for diagnostic rewriting - given a diagnostic, see if any templates matches it, 4284 * and rewrite it accordingly. 4285 */ 4286 static JCDiagnostic rewrite(JCDiagnostic.Factory diags, DiagnosticPosition pos, DiagnosticSource source, 4287 DiagnosticType dkind, JCDiagnostic d) { 4288 for (Map.Entry<Template, DiagnosticRewriter> _entry : rewriters.entrySet()) { 4289 if (_entry.getKey().matches(d)) { 4290 JCDiagnostic simpleDiag = 4291 _entry.getValue().rewriteDiagnostic(diags, pos, source, dkind, d); 4292 simpleDiag.setFlag(DiagnosticFlag.COMPRESSED); 4293 return simpleDiag; 4294 } 4295 } 4296 return null; 4297 } 4298 } 4299 4300 enum MethodResolutionPhase { 4301 BASIC(false, false), 4302 BOX(true, false), 4303 VARARITY(true, true) { 4304 @Override 4305 public Symbol mergeResults(Symbol bestSoFar, Symbol sym) { 4306 //Check invariants (see {@code LookupHelper.shouldStop}) 4307 Assert.check(bestSoFar.kind.isResolutionError() && bestSoFar.kind != AMBIGUOUS); 4308 if (!sym.kind.isResolutionError()) { 4309 //varargs resolution successful 4310 return sym; 4311 } else { 4312 //pick best error 4313 switch (bestSoFar.kind) { 4314 case WRONG_MTH: 4315 case WRONG_MTHS: 4316 //Override previous errors if they were caused by argument mismatch. 4317 //This generally means preferring current symbols - but we need to pay 4318 //attention to the fact that the varargs lookup returns 'less' candidates 4319 //than the previous rounds, and adjust that accordingly. 4320 switch (sym.kind) { 4321 case WRONG_MTH: 4322 //if the previous round matched more than one method, return that 4323 //result instead 4324 return bestSoFar.kind == WRONG_MTHS ? 4325 bestSoFar : sym; 4326 case ABSENT_MTH: 4327 //do not override erroneous symbol if the arity lookup did not 4328 //match any method 4329 return bestSoFar; 4330 case WRONG_MTHS: 4331 default: 4332 //safe to override 4333 return sym; 4334 } 4335 default: 4336 //otherwise, return first error 4337 return bestSoFar; 4338 } 4339 } 4340 } 4341 }; 4342 4343 final boolean isBoxingRequired; 4344 final boolean isVarargsRequired; 4345 4346 MethodResolutionPhase(boolean isBoxingRequired, boolean isVarargsRequired) { 4347 this.isBoxingRequired = isBoxingRequired; 4348 this.isVarargsRequired = isVarargsRequired; 4349 } 4350 4351 public boolean isBoxingRequired() { 4352 return isBoxingRequired; 4353 } 4354 4355 public boolean isVarargsRequired() { 4356 return isVarargsRequired; 4357 } 4358 4359 public Symbol mergeResults(Symbol prev, Symbol sym) { 4360 return sym; 4361 } 4362 } 4363 4364 final List<MethodResolutionPhase> methodResolutionSteps = List.of(BASIC, BOX, VARARITY); 4365 4366 /** 4367 * A resolution context is used to keep track of intermediate results of 4368 * overload resolution, such as list of method that are not applicable 4369 * (used to generate more precise diagnostics) and so on. Resolution contexts 4370 * can be nested - this means that when each overload resolution routine should 4371 * work within the resolution context it created. 4372 */ 4373 class MethodResolutionContext { 4374 4375 private List<Candidate> candidates = List.nil(); 4376 4377 MethodResolutionPhase step = null; 4378 4379 MethodCheck methodCheck = resolveMethodCheck; 4380 4381 private boolean internalResolution = false; 4382 private DeferredAttr.AttrMode attrMode = DeferredAttr.AttrMode.SPECULATIVE; 4383 4384 void addInapplicableCandidate(Symbol sym, JCDiagnostic details) { 4385 Candidate c = new Candidate(currentResolutionContext.step, sym, details, null); 4386 candidates = candidates.append(c); 4387 } 4388 4389 void addApplicableCandidate(Symbol sym, Type mtype) { 4390 Candidate c = new Candidate(currentResolutionContext.step, sym, null, mtype); 4391 candidates = candidates.append(c); 4392 } 4393 4394 DeferredAttrContext deferredAttrContext(Symbol sym, InferenceContext inferenceContext, ResultInfo pendingResult, Warner warn) { 4395 DeferredAttrContext parent = (pendingResult == null) 4396 ? deferredAttr.emptyDeferredAttrContext 4397 : pendingResult.checkContext.deferredAttrContext(); 4398 return deferredAttr.new DeferredAttrContext(attrMode, sym, step, 4399 inferenceContext, parent, warn); 4400 } 4401 4402 /** 4403 * This class represents an overload resolution candidate. There are two 4404 * kinds of candidates: applicable methods and inapplicable methods; 4405 * applicable methods have a pointer to the instantiated method type, 4406 * while inapplicable candidates contain further details about the 4407 * reason why the method has been considered inapplicable. 4408 */ 4409 @SuppressWarnings("overrides") 4410 class Candidate { 4411 4412 final MethodResolutionPhase step; 4413 final Symbol sym; 4414 final JCDiagnostic details; 4415 final Type mtype; 4416 4417 private Candidate(MethodResolutionPhase step, Symbol sym, JCDiagnostic details, Type mtype) { 4418 this.step = step; 4419 this.sym = sym; 4420 this.details = details; 4421 this.mtype = mtype; 4422 } 4423 4424 @Override 4425 public boolean equals(Object o) { 4426 if (o instanceof Candidate) { 4427 Symbol s1 = this.sym; 4428 Symbol s2 = ((Candidate)o).sym; 4429 if ((s1 != s2 && 4430 (s1.overrides(s2, s1.owner.type.tsym, types, false) || 4431 (s2.overrides(s1, s2.owner.type.tsym, types, false)))) || 4432 ((s1.isConstructor() || s2.isConstructor()) && s1.owner != s2.owner)) 4433 return true; 4434 } 4435 return false; 4436 } 4437 4438 boolean isApplicable() { 4439 return mtype != null; 4440 } 4441 } 4442 4443 DeferredAttr.AttrMode attrMode() { 4444 return attrMode; 4445 } 4446 4447 boolean internal() { 4448 return internalResolution; 4449 } 4450 } 4451 4452 MethodResolutionContext currentResolutionContext = null; 4453} 4454