Resolve.java revision 3199:3a6560c043d2
165543Scg/* 2137573Sru * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. 365543Scg * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 465543Scg * 565543Scg * This code is free software; you can redistribute it and/or modify it 665543Scg * under the terms of the GNU General Public License version 2 only, as 765543Scg * published by the Free Software Foundation. Oracle designates this 865543Scg * particular file as subject to the "Classpath" exception as provided 965543Scg * by Oracle in the LICENSE file that accompanied this code. 1065543Scg * 1165543Scg * This code is distributed in the hope that it will be useful, but WITHOUT 1265543Scg * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1365543Scg * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1465543Scg * version 2 for more details (a copy is included in the LICENSE file that 1565543Scg * accompanied this code). 1665543Scg * 1765543Scg * You should have received a copy of the GNU General Public License version 1865543Scg * 2 along with this work; if not, write to the Free Software Foundation, 1965543Scg * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2065543Scg * 2165543Scg * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2265543Scg * or visit www.oracle.com if you need additional information or have any 2365543Scg * questions. 2465543Scg */ 2565543Scg 26137500Sjulianpackage com.sun.tools.javac.comp; 2765543Scg 2865543Scgimport com.sun.tools.javac.api.Formattable.LocalizedString; 2965543Scgimport com.sun.tools.javac.code.*; 3065543Scgimport com.sun.tools.javac.code.Scope.WriteableScope; 3165543Scgimport com.sun.tools.javac.code.Symbol.*; 3265543Scgimport com.sun.tools.javac.code.Type.*; 3365543Scgimport com.sun.tools.javac.comp.Attr.ResultInfo; 3465543Scgimport com.sun.tools.javac.comp.Check.CheckContext; 3565543Scgimport com.sun.tools.javac.comp.DeferredAttr.AttrMode; 3665543Scgimport com.sun.tools.javac.comp.DeferredAttr.DeferredAttrContext; 3765543Scgimport com.sun.tools.javac.comp.DeferredAttr.DeferredType; 38119853Scgimport com.sun.tools.javac.comp.Infer.FreeTypeListener; 3965543Scgimport com.sun.tools.javac.comp.Resolve.MethodResolutionContext.Candidate; 4065543Scgimport com.sun.tools.javac.comp.Resolve.MethodResolutionDiagHelper.Template; 4165543Scgimport com.sun.tools.javac.comp.Resolve.ReferenceLookupResult.StaticKind; 4265543Scgimport com.sun.tools.javac.jvm.*; 4365543Scgimport com.sun.tools.javac.main.Option; 4465543Scgimport com.sun.tools.javac.tree.*; 45137500Sjulianimport com.sun.tools.javac.tree.JCTree.*; 46137500Sjulianimport com.sun.tools.javac.tree.JCTree.JCMemberReference.ReferenceKind; 47137500Sjulianimport com.sun.tools.javac.tree.JCTree.JCPolyExpression.*; 4865543Scgimport com.sun.tools.javac.util.*; 4965543Scgimport com.sun.tools.javac.util.DefinedBy.Api; 50193640Sariffimport com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag; 51193640Sariffimport com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; 52193640Sariffimport com.sun.tools.javac.util.JCDiagnostic.DiagnosticType; 53193640Sariff 5465543Scgimport java.util.Arrays; 5565543Scgimport java.util.Collection; 56119287Simpimport java.util.EnumSet; 57119287Simpimport java.util.Iterator; 5865543Scgimport java.util.LinkedHashMap; 5965543Scgimport java.util.Map; 6065543Scgimport java.util.function.BiPredicate; 6182180Scgimport java.util.stream.Stream; 6282180Scg 6365543Scgimport javax.lang.model.element.ElementVisitor; 6465543Scg 6565543Scgimport static com.sun.tools.javac.code.Flags.*; 6665543Scgimport static com.sun.tools.javac.code.Flags.BLOCK; 6765543Scgimport static com.sun.tools.javac.code.Flags.STATIC; 6865543Scgimport static com.sun.tools.javac.code.Kinds.*; 6965543Scgimport static com.sun.tools.javac.code.Kinds.Kind.*; 7065543Scgimport static com.sun.tools.javac.code.TypeTag.*; 7165543Scgimport static com.sun.tools.javac.comp.Resolve.MethodResolutionPhase.*; 7265543Scgimport static com.sun.tools.javac.tree.JCTree.Tag.*; 7365543Scg 7465543Scg/** Helper class for name resolution, used mostly by the attribution phase. 7565543Scg * 7665543Scg * <p><b>This is NOT part of any supported API. 7765543Scg * If you write code that depends on this, you do so at your own risk. 78137500Sjulian * This code and its internal interfaces are subject to change or 79137500Sjulian * deletion without notice.</b> 80137500Sjulian */ 81137500Sjulianpublic class Resolve { 82137500Sjulian protected static final Context.Key<Resolve> resolveKey = new Context.Key<>(); 83137500Sjulian 8465543Scg Names names; 8565543Scg Log log; 8665543Scg Symtab syms; 8784658Scg Attr attr; 8865543Scg DeferredAttr deferredAttr; 8965543Scg Check chk; 90137500Sjulian Infer infer; 91137500Sjulian ClassFinder finder; 92137500Sjulian Types types; 93137500Sjulian JCDiagnostic.Factory diags; 94137500Sjulian public final boolean allowMethodHandles; 95137500Sjulian public final boolean allowFunctionalInterfaceMostSpecific; 96137500Sjulian public final boolean checkVarargsAccessAfterResolution; 97137500Sjulian private final boolean debugResolve; 98137500Sjulian private final boolean compactMethodDiags; 99137500Sjulian final EnumSet<VerboseResolutionMode> verboseResolutionMode; 100137500Sjulian 10165543Scg WriteableScope polymorphicSignatureScope; 10265543Scg 10365543Scg protected Resolve(Context context) { 10465543Scg context.put(resolveKey, this); 105137500Sjulian syms = Symtab.instance(context); 10665543Scg 107137500Sjulian varNotFound = new SymbolNotFoundError(ABSENT_VAR); 108137500Sjulian methodNotFound = new SymbolNotFoundError(ABSENT_MTH); 10974763Scg typeNotFound = new SymbolNotFoundError(ABSENT_TYP); 11074763Scg referenceNotFound = new ReferenceLookupResult(methodNotFound, null); 111137500Sjulian 112137500Sjulian names = Names.instance(context); 113137500Sjulian log = Log.instance(context); 114137500Sjulian attr = Attr.instance(context); 115137500Sjulian deferredAttr = DeferredAttr.instance(context); 116137500Sjulian chk = Check.instance(context); 11770291Scg infer = Infer.instance(context); 118137500Sjulian finder = ClassFinder.instance(context); 119137500Sjulian types = Types.instance(context); 120137500Sjulian diags = JCDiagnostic.Factory.instance(context); 121137500Sjulian Source source = Source.instance(context); 12265543Scg Options options = Options.instance(context); 12365543Scg debugResolve = options.isSet("debugresolve"); 124137500Sjulian compactMethodDiags = options.isSet(Option.XDIAGS, "compact") || 125137500Sjulian options.isUnset(Option.XDIAGS) && options.isUnset("rawDiagnostics"); 126137500Sjulian verboseResolutionMode = VerboseResolutionMode.getVerboseResolutionMode(options); 127137500Sjulian Target target = Target.instance(context); 128137500Sjulian allowMethodHandles = target.hasMethodHandles(); 129137500Sjulian allowFunctionalInterfaceMostSpecific = source.allowFunctionalInterfaceMostSpecific(); 130137500Sjulian checkVarargsAccessAfterResolution = 131137500Sjulian source.allowPostApplicabilityVarargsAccessCheck(); 132137500Sjulian polymorphicSignatureScope = WriteableScope.create(syms.noSymbol); 133137500Sjulian 134137500Sjulian inapplicableMethodException = new InapplicableMethodException(diags); 135137500Sjulian } 136137500Sjulian 137137500Sjulian /** error symbols, which are returned when resolution fails 138137500Sjulian */ 139137500Sjulian private final SymbolNotFoundError varNotFound; 140137500Sjulian private final SymbolNotFoundError methodNotFound; 141137500Sjulian private final SymbolNotFoundError typeNotFound; 142137500Sjulian 143137500Sjulian /** empty reference lookup result */ 144137500Sjulian private final ReferenceLookupResult referenceNotFound; 145137500Sjulian 14665543Scg public static Resolve instance(Context context) { 147137500Sjulian Resolve instance = context.get(resolveKey); 14865543Scg if (instance == null) 149137500Sjulian instance = new Resolve(context); 150137500Sjulian return instance; 15165543Scg } 15265543Scg 15365543Scg private static Symbol bestOf(Symbol s1, 15465543Scg Symbol s2) { 15565543Scg return s1.kind.betterThan(s2.kind) ? s1 : s2; 15665543Scg } 15765543Scg 15865543Scg // <editor-fold defaultstate="collapsed" desc="Verbose resolution diagnostics support"> 15965543Scg enum VerboseResolutionMode { 160137500Sjulian SUCCESS("success"), 161137500Sjulian FAILURE("failure"), 16265543Scg APPLICABLE("applicable"), 163137500Sjulian INAPPLICABLE("inapplicable"), 164137500Sjulian DEFERRED_INST("deferred-inference"), 165137500Sjulian PREDEF("predef"), 16665543Scg OBJECT_INIT("object-init"), 16765543Scg INTERNAL("internal"); 168137500Sjulian 169137500Sjulian final String opt; 170137500Sjulian 171137500Sjulian private VerboseResolutionMode(String opt) { 172137500Sjulian this.opt = opt; 173137500Sjulian } 17465543Scg 175137500Sjulian static EnumSet<VerboseResolutionMode> getVerboseResolutionMode(Options opts) { 176137500Sjulian String s = opts.get("verboseResolution"); 17765543Scg EnumSet<VerboseResolutionMode> res = EnumSet.noneOf(VerboseResolutionMode.class); 17865543Scg if (s == null) return res; 179137500Sjulian if (s.contains("all")) { 180137500Sjulian res = EnumSet.allOf(VerboseResolutionMode.class); 181137500Sjulian } 182137500Sjulian Collection<String> args = Arrays.asList(s.split(",")); 183137500Sjulian for (VerboseResolutionMode mode : values()) { 184137500Sjulian if (args.contains(mode.opt)) { 185137500Sjulian res.add(mode); 186137500Sjulian } else if (args.contains("-" + mode.opt)) { 187137500Sjulian res.remove(mode); 188137500Sjulian } 189137500Sjulian } 190137500Sjulian return res; 191159732Snetchild } 192159732Snetchild } 193159732Snetchild 194248085Smarius void reportVerboseResolutionDiagnostic(DiagnosticPosition dpos, Name name, Type site, 195137500Sjulian List<Type> argtypes, List<Type> typeargtypes, Symbol bestSoFar) { 196137500Sjulian boolean success = !bestSoFar.kind.isResolutionError(); 197137500Sjulian 198137500Sjulian if (success && !verboseResolutionMode.contains(VerboseResolutionMode.SUCCESS)) { 199137500Sjulian return; 200166279Sariff } else if (!success && !verboseResolutionMode.contains(VerboseResolutionMode.FAILURE)) { 201166279Sariff return; 202137500Sjulian } 203137500Sjulian 204137500Sjulian if (bestSoFar.name == names.init && 205137500Sjulian bestSoFar.owner == syms.objectType.tsym && 206137500Sjulian !verboseResolutionMode.contains(VerboseResolutionMode.OBJECT_INIT)) { 207137500Sjulian return; //skip diags for Object constructor resolution 208166279Sariff } else if (site == syms.predefClass.type && 209137500Sjulian !verboseResolutionMode.contains(VerboseResolutionMode.PREDEF)) { 210260298Sdim return; //skip spurious diags for predef symbols (i.e. operators) 211166279Sariff } else if (currentResolutionContext.internalResolution && 212166279Sariff !verboseResolutionMode.contains(VerboseResolutionMode.INTERNAL)) { 213166279Sariff return; 214260298Sdim } 215166279Sariff 216166279Sariff int pos = 0; 217137500Sjulian int mostSpecificPos = -1; 218166279Sariff ListBuffer<JCDiagnostic> subDiags = new ListBuffer<>(); 219137500Sjulian for (Candidate c : currentResolutionContext.candidates) { 220166279Sariff if (currentResolutionContext.step != c.step || 221166279Sariff (c.isApplicable() && !verboseResolutionMode.contains(VerboseResolutionMode.APPLICABLE)) || 222166279Sariff (!c.isApplicable() && !verboseResolutionMode.contains(VerboseResolutionMode.INAPPLICABLE))) { 223166279Sariff continue; 224166279Sariff } else { 225166279Sariff subDiags.append(c.isApplicable() ? 226166279Sariff getVerboseApplicableCandidateDiag(pos, c.sym, c.mtype) : 22765543Scg getVerboseInapplicableCandidateDiag(pos, c.sym, c.details)); 228166279Sariff if (c.sym == bestSoFar) 229166279Sariff mostSpecificPos = pos; 230166279Sariff pos++; 231166279Sariff } 232166279Sariff } 233166279Sariff String key = success ? "verbose.resolve.multi" : "verbose.resolve.multi.1"; 234166279Sariff List<Type> argtypes2 = argtypes.map(deferredAttr.new RecoveryDeferredTypeMap(AttrMode.SPECULATIVE, bestSoFar, currentResolutionContext.step)); 235166279Sariff JCDiagnostic main = diags.note(log.currentSource(), dpos, key, name, 23665543Scg site.tsym, mostSpecificPos, currentResolutionContext.step, 237166279Sariff methodArguments(argtypes2), 23865543Scg methodArguments(typeargtypes)); 239166279Sariff JCDiagnostic d = new JCDiagnostic.MultilineDiagnostic(main, subDiags.toList()); 240166279Sariff log.report(d); 241166279Sariff } 24265543Scg 243166279Sariff JCDiagnostic getVerboseApplicableCandidateDiag(int pos, Symbol sym, Type inst) { 244166279Sariff JCDiagnostic subDiag = null; 245166279Sariff if (sym.type.hasTag(FORALL)) { 246166279Sariff subDiag = diags.fragment("partial.inst.sig", inst); 247166279Sariff } 248166279Sariff 24965543Scg String key = subDiag == null ? 250166279Sariff "applicable.method.found" : 251166279Sariff "applicable.method.found.1"; 252166279Sariff 253166279Sariff return diags.fragment(key, pos, sym, subDiag); 25465543Scg } 255166279Sariff 25665543Scg JCDiagnostic getVerboseInapplicableCandidateDiag(int pos, Symbol sym, JCDiagnostic subDiag) { 257166279Sariff return diags.fragment("not.applicable.method.found", pos, sym, subDiag); 258166279Sariff } 259166279Sariff // </editor-fold> 260166279Sariff 261166279Sariff/* ************************************************************************ 262166279Sariff * Identifier resolution 263166279Sariff *************************************************************************/ 26465543Scg 265137500Sjulian /** An environment is "static" if its static level is greater than 266166279Sariff * the one of its outer environment 26765543Scg */ 268137500Sjulian protected static boolean isStatic(Env<AttrContext> env) { 26965543Scg return env.outer != null && env.info.staticLevel > env.outer.info.staticLevel; 27065543Scg } 27165543Scg 27265543Scg /** An environment is an "initializer" if it is a constructor or 273137500Sjulian * an instance initializer. 274166279Sariff */ 275166279Sariff static boolean isInitializer(Env<AttrContext> env) { 27665543Scg Symbol owner = env.info.scope.owner; 277166279Sariff return owner.isConstructor() || 278137500Sjulian owner.owner.kind == TYP && 279137500Sjulian (owner.kind == VAR || 280137500Sjulian owner.kind == MTH && (owner.flags() & BLOCK) != 0) && 281137500Sjulian (owner.flags() & STATIC) == 0; 282137500Sjulian } 283137500Sjulian 284137500Sjulian /** Is class accessible in given evironment? 285137500Sjulian * @param env The current environment. 286137500Sjulian * @param c The class whose accessibility is checked. 287137500Sjulian */ 288137500Sjulian public boolean isAccessible(Env<AttrContext> env, TypeSymbol c) { 289137500Sjulian return isAccessible(env, c, false); 290137500Sjulian } 291260298Sdim 292166279Sariff public boolean isAccessible(Env<AttrContext> env, TypeSymbol c, boolean checkInner) { 293137500Sjulian 294137500Sjulian /* 15.9.5.1: Note that it is possible for the signature of the anonymous constructor 295137500Sjulian to refer to an inaccessible type 296137500Sjulian */ 297137500Sjulian if (env.enclMethod != null && (env.enclMethod.mods.flags & ANONCONSTR) != 0) 298137500Sjulian return true; 299137500Sjulian 300137500Sjulian boolean isAccessible = false; 301137500Sjulian switch ((short)(c.flags() & AccessFlags)) { 302137500Sjulian case PRIVATE: 303137500Sjulian isAccessible = 304137500Sjulian env.enclClass.sym.outermostClass() == 305137500Sjulian c.owner.outermostClass(); 306260298Sdim break; 307137500Sjulian case 0: 308137500Sjulian isAccessible = 309137500Sjulian env.toplevel.packge == c.owner // fast special case 310137500Sjulian || 311137500Sjulian env.toplevel.packge == c.packge(); 312137500Sjulian break; 313260298Sdim default: // error recovery 314166279Sariff case PUBLIC: 315137500Sjulian isAccessible = true; 316137500Sjulian break; 317137500Sjulian case PROTECTED: 318137500Sjulian isAccessible = 319137500Sjulian env.toplevel.packge == c.owner // fast special case 320137500Sjulian || 321137500Sjulian env.toplevel.packge == c.packge() 322137500Sjulian || 323137500Sjulian isInnerSubClass(env.enclClass.sym, c.owner); 324137500Sjulian break; 325137500Sjulian } 326137500Sjulian return (checkInner == false || c.type.getEnclosingType() == Type.noType) ? 327137500Sjulian isAccessible : 328137500Sjulian isAccessible && isAccessible(env, c.type.getEnclosingType(), checkInner); 329260298Sdim } 330137500Sjulian //where 331137500Sjulian /** Is given class a subclass of given base class, or an inner class 332137500Sjulian * of a subclass? 333137500Sjulian * Return null if no such class exists. 334137500Sjulian * @param c The class which is the subclass or is contained in it. 335137500Sjulian * @param base The base class 33670134Scg */ 33770134Scg private boolean isInnerSubClass(ClassSymbol c, Symbol base) { 338137500Sjulian while (c != null && !c.isSubClass(base, types)) { 339137500Sjulian c = c.owner.enclClass(); 340166279Sariff } 341137500Sjulian return c != null; 34265543Scg } 343137500Sjulian 34470134Scg boolean isAccessible(Env<AttrContext> env, Type t) { 345137500Sjulian return isAccessible(env, t, false); 346137500Sjulian } 347137500Sjulian 348137500Sjulian boolean isAccessible(Env<AttrContext> env, Type t, boolean checkInner) { 349137500Sjulian return (t.hasTag(ARRAY)) 350137500Sjulian ? isAccessible(env, types.cvarUpperBound(types.elemtype(t))) 35170134Scg : isAccessible(env, t.tsym, checkInner); 35270134Scg } 353137500Sjulian 354166279Sariff /** Is symbol accessible as a member of given type in given environment? 355137500Sjulian * @param env The current environment. 35670134Scg * @param site The type of which the tested symbol is regarded 357137500Sjulian * as a member. 35865543Scg * @param sym The symbol. 35965543Scg */ 360137500Sjulian public boolean isAccessible(Env<AttrContext> env, Type site, Symbol sym) { 361137500Sjulian return isAccessible(env, site, sym, false); 362137500Sjulian } 363137500Sjulian public boolean isAccessible(Env<AttrContext> env, Type site, Symbol sym, boolean checkInner) { 36465543Scg if (sym.name == names.init && sym.owner != site.tsym) return false; 36565543Scg 366137500Sjulian /* 15.9.5.1: Note that it is possible for the signature of the anonymous constructor 367137500Sjulian to refer to an inaccessible type 36865543Scg */ 36965543Scg if (env.enclMethod != null && (env.enclMethod.mods.flags & ANONCONSTR) != 0) 370137500Sjulian return true; 371137500Sjulian 372137500Sjulian switch ((short)(sym.flags() & AccessFlags)) { 373137500Sjulian case PRIVATE: 374137500Sjulian return 375137500Sjulian (env.enclClass.sym == sym.owner // fast special case 37665543Scg || 37765543Scg env.enclClass.sym.outermostClass() == 378137500Sjulian sym.owner.outermostClass()) 37965543Scg && 38065543Scg sym.isInheritedIn(site.tsym, types); 381166279Sariff case 0: 382137500Sjulian return 38365543Scg (env.toplevel.packge == sym.owner.owner // fast special case 38465543Scg || 385137500Sjulian env.toplevel.packge == sym.packge()) 38665543Scg && 38765543Scg isAccessible(env, site, checkInner) 38870134Scg && 38965543Scg sym.isInheritedIn(site.tsym, types) 39065543Scg && 391137500Sjulian notOverriddenIn(site, sym); 392137500Sjulian case PROTECTED: 39370134Scg return 394137500Sjulian (env.toplevel.packge == sym.owner.owner // fast special case 395137500Sjulian || 396137500Sjulian env.toplevel.packge == sym.packge() 397137500Sjulian || 398137500Sjulian isProtectedAccessible(sym, env.enclClass.sym, site) 399137500Sjulian || 400137500Sjulian // OK to select instance method or field from 'super' or type name 40170134Scg // (but type names should be disallowed elsewhere!) 40265543Scg env.info.selectSuper && (sym.flags() & STATIC) == 0 && sym.kind != TYP) 40365543Scg && 404166279Sariff isAccessible(env, site, checkInner) 40565543Scg && 40665543Scg notOverriddenIn(site, sym); 40765543Scg default: // this case includes erroneous combinations as well 40865543Scg return isAccessible(env, site, checkInner) && notOverriddenIn(site, sym); 409137500Sjulian } 41065543Scg } 41165543Scg //where 412137500Sjulian /* `sym' is accessible only if not overridden by 41365543Scg * another symbol which is a member of `site' 41465543Scg * (because, if it is overridden, `sym' is not strictly 415137500Sjulian * speaking a member of `site'). A polymorphic signature method 416137500Sjulian * cannot be overridden (e.g. MH.invokeExact(Object[])). 41765543Scg */ 41865543Scg private boolean notOverriddenIn(Type site, Symbol sym) { 419166279Sariff if (sym.kind != MTH || sym.isConstructor() || sym.isStatic()) 42065543Scg return true; 42165543Scg else { 422137500Sjulian Symbol s2 = ((MethodSymbol)sym).implementation(site.tsym, types, true); 423137500Sjulian return (s2 == null || s2 == sym || sym.owner == s2.owner || 42465543Scg !types.isSubSignature(types.memberType(site, s2), types.memberType(site, sym))); 42565543Scg } 426166279Sariff } 42765543Scg //where 42865543Scg /** Is given protected symbol accessible if it is selected from given site 429137500Sjulian * and the selection takes place in given class? 430137500Sjulian * @param sym The symbol with protected access 43165543Scg * @param c The class where the access takes place 43265543Scg * @site The type of the qualifier 433166279Sariff */ 434137500Sjulian private 43565543Scg boolean isProtectedAccessible(Symbol sym, ClassSymbol c, Type site) { 436137500Sjulian Type newSite = site.hasTag(TYPEVAR) ? site.getUpperBound() : site; 43765543Scg while (c != null && 438137500Sjulian !(c.isSubClass(sym.owner, types) && 439137500Sjulian (c.flags() & INTERFACE) == 0 && 440137500Sjulian // In JLS 2e 6.6.2.1, the subclass restriction applies 441137500Sjulian // only to instance fields and methods -- types are excluded 442137500Sjulian // regardless of whether they are declared 'static' or not. 44365543Scg ((sym.flags() & STATIC) != 0 || sym.kind == TYP || newSite.tsym.isSubClass(c, types)))) 444137500Sjulian c = c.owner.enclClass(); 445137500Sjulian return c != null; 44665543Scg } 44765543Scg 448166279Sariff /** 449137500Sjulian * Performs a recursive scan of a type looking for accessibility problems 45065543Scg * from current attribution environment 451137500Sjulian */ 452137500Sjulian void checkAccessibleType(Env<AttrContext> env, Type t) { 453137500Sjulian accessibilityChecker.visit(t, env); 454137500Sjulian } 45565543Scg 45665543Scg /** 457166279Sariff * Accessibility type-visitor 458137500Sjulian */ 45965543Scg Types.SimpleVisitor<Void, Env<AttrContext>> accessibilityChecker = 460137500Sjulian new Types.SimpleVisitor<Void, Env<AttrContext>>() { 461137500Sjulian 462137500Sjulian void visit(List<Type> ts, Env<AttrContext> env) { 463137500Sjulian for (Type t : ts) { 464166279Sariff visit(t, env); 465166279Sariff } 466137500Sjulian } 467137500Sjulian 46865543Scg public Void visitType(Type t, Env<AttrContext> env) { 46965543Scg return null; 47065543Scg } 471137573Sru 472137500Sjulian @Override 473137500Sjulian public Void visitArrayType(ArrayType t, Env<AttrContext> env) { 47465543Scg visit(t.elemtype, env); 475137500Sjulian return null; 476137500Sjulian } 477137500Sjulian 478137500Sjulian @Override 479137500Sjulian public Void visitClassType(ClassType t, Env<AttrContext> env) { 480137500Sjulian visit(t.getTypeArguments(), env); 481137500Sjulian if (!isAccessible(env, t, true)) { 482137500Sjulian accessBase(new AccessError(t.tsym), env.tree.pos(), env.enclClass.sym, t, t.tsym.name, true); 483137500Sjulian } 484137500Sjulian return null; 485137500Sjulian } 486137500Sjulian 487137500Sjulian @Override 48865543Scg public Void visitWildcardType(WildcardType t, Env<AttrContext> env) { 489166279Sariff visit(t.type, env); 490137500Sjulian return null; 491137500Sjulian } 492137500Sjulian 49365543Scg @Override 494137500Sjulian public Void visitMethodType(MethodType t, Env<AttrContext> env) { 495137500Sjulian visit(t.getParameterTypes(), env); 496137500Sjulian visit(t.getReturnType(), env); 49765543Scg visit(t.getThrownTypes(), env); 498137500Sjulian return null; 499137500Sjulian } 50065543Scg }; 50165543Scg 50265543Scg /** Try to instantiate the type of a method so that it fits 50365543Scg * given type arguments and argument types. If successful, return 50465543Scg * the method's instantiated type, else return null. 505137500Sjulian * The instantiation will take into account an additional leading 50665543Scg * formal parameter if the method is an instance method seen as a member 50765543Scg * of an under determined site. In this case, we treat site as an additional 50865543Scg * parameter and the parameters of the class containing the method as 50965543Scg * additional type variables that get instantiated. 510166279Sariff * 51165543Scg * @param env The current environment 51265543Scg * @param site The type of which the method is a member. 513137500Sjulian * @param m The method symbol. 514137500Sjulian * @param argtypes The invocation's given value arguments. 515137500Sjulian * @param typeargtypes The invocation's given type arguments. 51665543Scg * @param allowBoxing Allow boxing conversions of arguments. 51765543Scg * @param useVarargs Box trailing arguments into an array for varargs. 51865543Scg */ 519166279Sariff Type rawInstantiate(Env<AttrContext> env, 52065543Scg Type site, 52165543Scg Symbol m, 522137500Sjulian ResultInfo resultInfo, 523137500Sjulian List<Type> argtypes, 524137500Sjulian List<Type> typeargtypes, 52565543Scg boolean allowBoxing, 52665543Scg boolean useVarargs, 52765543Scg Warner warn) throws Infer.InferenceException { 528137500Sjulian Type mt = types.memberType(site, m); 529137500Sjulian // tvars is the list of formal type variables for which type arguments 53065543Scg // need to inferred. 53165543Scg List<Type> tvars = List.nil(); 532166279Sariff if (typeargtypes == null) typeargtypes = List.nil(); 533166279Sariff if (!mt.hasTag(FORALL) && typeargtypes.nonEmpty()) { 53465543Scg // This is not a polymorphic method, but typeargs are supplied 53565543Scg // which is fine, see JLS 15.12.2.1 536137500Sjulian } else if (mt.hasTag(FORALL) && typeargtypes.nonEmpty()) { 537137500Sjulian ForAll pmt = (ForAll) mt; 53865543Scg if (typeargtypes.length() != pmt.tvars.length()) 539166279Sariff throw inapplicableMethodException.setMessage("arg.length.mismatch"); // not enough args 54065543Scg // Check type arguments are within bounds 541166279Sariff List<Type> formals = pmt.tvars; 54265543Scg List<Type> actuals = typeargtypes; 54365543Scg while (formals.nonEmpty() && actuals.nonEmpty()) { 544137500Sjulian List<Type> bounds = types.subst(types.getBounds((TypeVar)formals.head), 545137500Sjulian pmt.tvars, typeargtypes); 54665543Scg for (; bounds.nonEmpty(); bounds = bounds.tail) { 54765543Scg if (!types.isSubtypeUnchecked(actuals.head, bounds.head, warn)) 548166279Sariff throw inapplicableMethodException.setMessage("explicit.param.do.not.conform.to.bounds",actuals.head, bounds); 549166279Sariff } 55065543Scg formals = formals.tail; 55165543Scg actuals = actuals.tail; 55265543Scg } 55365543Scg mt = types.subst(pmt.qtype, pmt.tvars, typeargtypes); 554166279Sariff } else if (mt.hasTag(FORALL)) { 55565543Scg ForAll pmt = (ForAll) mt; 556166279Sariff List<Type> tvars1 = types.newInstances(pmt.tvars); 55765543Scg tvars = tvars.appendList(tvars1); 55865543Scg mt = types.subst(pmt.qtype, pmt.tvars, tvars1); 55965543Scg } 56065543Scg 56165543Scg // find out whether we need to go the slow route via infer 562137500Sjulian boolean instNeeded = tvars.tail != null; /*inlined: tvars.nonEmpty()*/ 563137500Sjulian for (List<Type> l = argtypes; 56465543Scg l.tail != null/*inlined: l.nonEmpty()*/ && !instNeeded; 565166279Sariff l = l.tail) { 566137500Sjulian if (l.head.hasTag(FORALL)) instNeeded = true; 56765543Scg } 568137500Sjulian 56965543Scg if (instNeeded) { 570137500Sjulian return infer.instantiateMethod(env, 571137500Sjulian tvars, 572137500Sjulian (MethodType)mt, 573137500Sjulian resultInfo, 574137500Sjulian (MethodSymbol)m, 575137500Sjulian argtypes, 576137500Sjulian allowBoxing, 577137500Sjulian useVarargs, 578137500Sjulian currentResolutionContext, 579137500Sjulian warn); 580137500Sjulian } 581137500Sjulian 58265543Scg DeferredAttr.DeferredAttrContext dc = currentResolutionContext.deferredAttrContext(m, infer.emptyContext, resultInfo, warn); 58365543Scg currentResolutionContext.methodCheck.argumentsAcceptable(env, dc, 58465543Scg argtypes, mt.getParameterTypes(), warn); 58565543Scg dc.complete(); 58665543Scg return mt; 58765543Scg } 58865543Scg 589166279Sariff Type checkMethod(Env<AttrContext> env, 59065543Scg Type site, 59165543Scg Symbol m, 59265543Scg ResultInfo resultInfo, 59365543Scg List<Type> argtypes, 594137500Sjulian List<Type> typeargtypes, 595137500Sjulian Warner warn) { 59665543Scg MethodResolutionContext prevContext = currentResolutionContext; 59765543Scg try { 59865543Scg currentResolutionContext = new MethodResolutionContext(); 599137500Sjulian currentResolutionContext.attrMode = (resultInfo.pt == Infer.anyPoly) ? 60065543Scg AttrMode.SPECULATIVE : DeferredAttr.AttrMode.CHECK; 601137500Sjulian if (env.tree.hasTag(JCTree.Tag.REFERENCE)) { 602137500Sjulian //method/constructor references need special check class 60365543Scg //to handle inference variables in 'argtypes' (might happen 604137500Sjulian //during an unsticking round) 605137500Sjulian currentResolutionContext.methodCheck = 60665543Scg new MethodReferenceCheck(resultInfo.checkContext.inferenceContext()); 60765543Scg } 60865543Scg MethodResolutionPhase step = currentResolutionContext.step = env.info.pendingResolutionPhase; 60965543Scg return rawInstantiate(env, site, m, resultInfo, argtypes, typeargtypes, 610137500Sjulian step.isBoxingRequired(), step.isVarargsRequired(), warn); 61165543Scg } 61265543Scg finally { 613137500Sjulian currentResolutionContext = prevContext; 614137500Sjulian } 615137500Sjulian } 616137500Sjulian 61765543Scg /** Same but returns null instead throwing a NoInstanceException 618137500Sjulian */ 61965543Scg Type instantiate(Env<AttrContext> env, 620137500Sjulian Type site, 621137500Sjulian Symbol m, 622137500Sjulian ResultInfo resultInfo, 62365543Scg List<Type> argtypes, 624137500Sjulian List<Type> typeargtypes, 625137500Sjulian boolean allowBoxing, 62665543Scg boolean useVarargs, 62765543Scg Warner warn) { 62865543Scg try { 62965543Scg return rawInstantiate(env, site, m, resultInfo, argtypes, typeargtypes, 63065543Scg allowBoxing, useVarargs, warn); 63165543Scg } catch (InapplicableMethodException ex) { 63265543Scg return null; 63365543Scg } 63465543Scg } 63565543Scg 63665543Scg /** 63765543Scg * This interface defines an entry point that should be used to perform a 63865543Scg * method check. A method check usually consist in determining as to whether 63965543Scg * a set of types (actuals) is compatible with another set of types (formals). 64065543Scg * Since the notion of compatibility can vary depending on the circumstances, 64165543Scg * this interfaces allows to easily add new pluggable method check routines. 64265543Scg */ 64365543Scg interface MethodCheck { 64465543Scg /** 64565543Scg * Main method check routine. A method check usually consist in determining 646137500Sjulian * as to whether a set of types (actuals) is compatible with another set of 64765543Scg * types (formals). If an incompatibility is found, an unchecked exception 64865543Scg * is assumed to be thrown. 64965543Scg */ 65065543Scg void argumentsAcceptable(Env<AttrContext> env, 651137500Sjulian DeferredAttrContext deferredAttrContext, 652137500Sjulian List<Type> argtypes, 653137500Sjulian List<Type> formals, 654137500Sjulian Warner warn); 655137500Sjulian 656137500Sjulian /** 657137500Sjulian * Retrieve the method check object that will be used during a 658137500Sjulian * most specific check. 659137500Sjulian */ 660137500Sjulian MethodCheck mostSpecificCheck(List<Type> actuals); 661137500Sjulian } 662137500Sjulian 663137500Sjulian /** 664137500Sjulian * Helper enum defining all method check diagnostics (used by resolveMethodCheck). 665137500Sjulian */ 666137500Sjulian enum MethodCheckDiag { 667137500Sjulian /** 668137500Sjulian * Actuals and formals differs in length. 669137500Sjulian */ 670137500Sjulian ARITY_MISMATCH("arg.length.mismatch", "infer.arg.length.mismatch"), 671137500Sjulian /** 672137500Sjulian * An actual is incompatible with a formal. 673137500Sjulian */ 674137500Sjulian ARG_MISMATCH("no.conforming.assignment.exists", "infer.no.conforming.assignment.exists"), 675137500Sjulian /** 676137500Sjulian * An actual is incompatible with the varargs element type. 677137500Sjulian */ 678137500Sjulian VARARG_MISMATCH("varargs.argument.mismatch", "infer.varargs.argument.mismatch"), 679137500Sjulian /** 68065543Scg * The varargs element type is inaccessible. 681137500Sjulian */ 682137500Sjulian INACCESSIBLE_VARARGS("inaccessible.varargs.type", "inaccessible.varargs.type"); 683137500Sjulian 684137500Sjulian final String basicKey; 685137500Sjulian final String inferKey; 686137500Sjulian 687137500Sjulian MethodCheckDiag(String basicKey, String inferKey) { 688137500Sjulian this.basicKey = basicKey; 68965543Scg this.inferKey = inferKey; 690137500Sjulian } 691137500Sjulian 692137500Sjulian String regex() { 69365543Scg return String.format("([a-z]*\\.)*(%s|%s)", basicKey, inferKey); 69465543Scg } 69565543Scg } 69665543Scg 69765543Scg /** 69865543Scg * Dummy method check object. All methods are deemed applicable, regardless 699137500Sjulian * of their formal parameter types. 70065543Scg */ 701137500Sjulian MethodCheck nilMethodCheck = new MethodCheck() { 702137500Sjulian public void argumentsAcceptable(Env<AttrContext> env, DeferredAttrContext deferredAttrContext, List<Type> argtypes, List<Type> formals, Warner warn) { 703137500Sjulian //do nothing - method always applicable regardless of actuals 70465543Scg } 705137500Sjulian 70665543Scg public MethodCheck mostSpecificCheck(List<Type> actuals) { 70765543Scg return this; 70865543Scg } 709137500Sjulian }; 710137500Sjulian 71165543Scg /** 712137500Sjulian * Base class for 'real' method checks. The class defines the logic for 713137500Sjulian * iterating through formals and actuals and provides and entry point 714137500Sjulian * that can be used by subclasses in order to define the actual check logic. 715137500Sjulian */ 716137500Sjulian abstract class AbstractMethodCheck implements MethodCheck { 717137500Sjulian @Override 71865543Scg public void argumentsAcceptable(final Env<AttrContext> env, 71965543Scg DeferredAttrContext deferredAttrContext, 72065543Scg List<Type> argtypes, 72165543Scg List<Type> formals, 72265543Scg Warner warn) { 723137500Sjulian //should we expand formals? 724137500Sjulian boolean useVarargs = deferredAttrContext.phase.isVarargsRequired(); 725137500Sjulian JCTree callTree = treeForDiagnostics(env); 726137500Sjulian List<JCExpression> trees = TreeInfo.args(callTree); 727137500Sjulian 728137500Sjulian //inference context used during this method check 72965543Scg InferenceContext inferenceContext = deferredAttrContext.inferenceContext; 730137500Sjulian 731137500Sjulian Type varargsFormal = useVarargs ? formals.last() : null; 732137500Sjulian 73365543Scg if (varargsFormal == null && 73465543Scg argtypes.size() != formals.size()) { 73565543Scg reportMC(callTree, MethodCheckDiag.ARITY_MISMATCH, inferenceContext); // not enough args 73665543Scg } 73765543Scg 73865543Scg while (argtypes.nonEmpty() && formals.head != varargsFormal) { 73965543Scg DiagnosticPosition pos = trees != null ? trees.head : null; 74065543Scg checkArg(pos, false, argtypes.head, formals.head, deferredAttrContext, warn); 74165543Scg argtypes = argtypes.tail; 74265543Scg formals = formals.tail; 74365543Scg trees = trees != null ? trees.tail : trees; 744137500Sjulian } 745137500Sjulian 746137500Sjulian if (formals.head != varargsFormal) { 747137500Sjulian reportMC(callTree, MethodCheckDiag.ARITY_MISMATCH, inferenceContext); // not enough args 74865543Scg } 74965543Scg 75065543Scg if (useVarargs) { 75165543Scg //note: if applicability check is triggered by most specific test, 752137500Sjulian //the last argument of a varargs is _not_ an array type (see JLS 15.12.2.5) 753137500Sjulian final Type elt = types.elemtype(varargsFormal); 754137500Sjulian while (argtypes.nonEmpty()) { 755137500Sjulian DiagnosticPosition pos = trees != null ? trees.head : null; 756137500Sjulian checkArg(pos, true, argtypes.head, elt, deferredAttrContext, warn); 757137500Sjulian argtypes = argtypes.tail; 758137500Sjulian trees = trees != null ? trees.tail : trees; 759137500Sjulian } 760137500Sjulian } 761137500Sjulian } 762137500Sjulian 763137500Sjulian // where 764137500Sjulian private JCTree treeForDiagnostics(Env<AttrContext> env) { 765137500Sjulian return env.info.preferredTreeForDiagnostics != null ? env.info.preferredTreeForDiagnostics : env.tree; 766137500Sjulian } 767137500Sjulian 768137500Sjulian /** 769137500Sjulian * Does the actual argument conforms to the corresponding formal? 770137500Sjulian */ 771137500Sjulian abstract void checkArg(DiagnosticPosition pos, boolean varargs, Type actual, Type formal, DeferredAttrContext deferredAttrContext, Warner warn); 772137500Sjulian 773166279Sariff protected void reportMC(DiagnosticPosition pos, MethodCheckDiag diag, InferenceContext inferenceContext, Object... args) { 774166279Sariff boolean inferDiag = inferenceContext != infer.emptyContext; 775137500Sjulian InapplicableMethodException ex = inferDiag ? 776137500Sjulian infer.inferenceException : inapplicableMethodException; 777137500Sjulian if (inferDiag && (!diag.inferKey.equals(diag.basicKey))) { 778137500Sjulian Object[] args2 = new Object[args.length + 1]; 779137500Sjulian System.arraycopy(args, 0, args2, 1, args.length); 780137500Sjulian args2[0] = inferenceContext.inferenceVars(); 781137500Sjulian args = args2; 782137500Sjulian } 783137500Sjulian String key = inferDiag ? diag.inferKey : diag.basicKey; 784137500Sjulian throw ex.setMessage(diags.create(DiagnosticType.FRAGMENT, log.currentSource(), pos, key, args)); 785137500Sjulian } 786137500Sjulian 787137500Sjulian public MethodCheck mostSpecificCheck(List<Type> actuals) { 788137500Sjulian return nilMethodCheck; 789137500Sjulian } 790137500Sjulian 791137500Sjulian } 792137500Sjulian 793137500Sjulian /** 794137500Sjulian * Arity-based method check. A method is applicable if the number of actuals 795137500Sjulian * supplied conforms to the method signature. 796137500Sjulian */ 797137500Sjulian MethodCheck arityMethodCheck = new AbstractMethodCheck() { 798137500Sjulian @Override 799137500Sjulian void checkArg(DiagnosticPosition pos, boolean varargs, Type actual, Type formal, DeferredAttrContext deferredAttrContext, Warner warn) { 800137500Sjulian //do nothing - actual always compatible to formals 801137500Sjulian } 802137500Sjulian 803137500Sjulian @Override 804137500Sjulian public String toString() { 805137500Sjulian return "arityMethodCheck"; 806137500Sjulian } 807137500Sjulian }; 808137500Sjulian 809137500Sjulian List<Type> dummyArgs(int length) { 810137500Sjulian ListBuffer<Type> buf = new ListBuffer<>(); 811137500Sjulian for (int i = 0 ; i < length ; i++) { 812137500Sjulian buf.append(Type.noType); 813137500Sjulian } 814137500Sjulian return buf.toList(); 815137500Sjulian } 816137500Sjulian 817137500Sjulian /** 818137500Sjulian * Main method applicability routine. Given a list of actual types A, 819137500Sjulian * a list of formal types F, determines whether the types in A are 820137500Sjulian * compatible (by method invocation conversion) with the types in F. 821137500Sjulian * 822137500Sjulian * Since this routine is shared between overload resolution and method 823137500Sjulian * type-inference, a (possibly empty) inference context is used to convert 824137500Sjulian * formal types to the corresponding 'undet' form ahead of a compatibility 825137500Sjulian * check so that constraints can be propagated and collected. 826137500Sjulian * 827137500Sjulian * Moreover, if one or more types in A is a deferred type, this routine uses 828137500Sjulian * DeferredAttr in order to perform deferred attribution. If one or more actual 829137500Sjulian * deferred types are stuck, they are placed in a queue and revisited later 830137500Sjulian * after the remainder of the arguments have been seen. If this is not sufficient 831137500Sjulian * to 'unstuck' the argument, a cyclic inference error is called out. 832137500Sjulian * 833137500Sjulian * A method check handler (see above) is used in order to report errors. 834137500Sjulian */ 835137500Sjulian MethodCheck resolveMethodCheck = new AbstractMethodCheck() { 836137500Sjulian 837137500Sjulian @Override 838137500Sjulian void checkArg(DiagnosticPosition pos, boolean varargs, Type actual, Type formal, DeferredAttrContext deferredAttrContext, Warner warn) { 839137500Sjulian ResultInfo mresult = methodCheckResult(varargs, formal, deferredAttrContext, warn); 840137500Sjulian mresult.check(pos, actual); 84165543Scg } 84265543Scg 84365543Scg @Override 84465543Scg public void argumentsAcceptable(final Env<AttrContext> env, 84565543Scg DeferredAttrContext deferredAttrContext, 846137500Sjulian List<Type> argtypes, 847137500Sjulian List<Type> formals, 848137500Sjulian Warner warn) { 849137500Sjulian super.argumentsAcceptable(env, deferredAttrContext, argtypes, formals, warn); 850137500Sjulian // should we check varargs element type accessibility? 85165543Scg if (deferredAttrContext.phase.isVarargsRequired()) { 852137500Sjulian if (deferredAttrContext.mode == AttrMode.CHECK || !checkVarargsAccessAfterResolution) { 853137500Sjulian varargsAccessible(env, types.elemtype(formals.last()), deferredAttrContext.inferenceContext); 854137500Sjulian } 855137500Sjulian } 856137500Sjulian } 857137500Sjulian 858137500Sjulian /** 859137500Sjulian * Test that the runtime array element type corresponding to 't' is accessible. 't' should be the 860137500Sjulian * varargs element type of either the method invocation type signature (after inference completes) 861137500Sjulian * or the method declaration signature (before inference completes). 862137500Sjulian */ 863137500Sjulian private void varargsAccessible(final Env<AttrContext> env, final Type t, final InferenceContext inferenceContext) { 864137500Sjulian if (inferenceContext.free(t)) { 865137500Sjulian inferenceContext.addFreeTypeListener(List.of(t), new FreeTypeListener() { 866137500Sjulian @Override 867137500Sjulian public void typesInferred(InferenceContext inferenceContext) { 868137500Sjulian varargsAccessible(env, inferenceContext.asInstType(t), inferenceContext); 869137500Sjulian } 870137500Sjulian }); 871137500Sjulian } else { 872137500Sjulian if (!isAccessible(env, types.erasure(t))) { 873137500Sjulian Symbol location = env.enclClass.sym; 874137500Sjulian reportMC(env.tree, MethodCheckDiag.INACCESSIBLE_VARARGS, inferenceContext, t, Kinds.kindName(location), location); 875137500Sjulian } 876137500Sjulian } 87765543Scg } 878137500Sjulian 879137500Sjulian private ResultInfo methodCheckResult(final boolean varargsCheck, Type to, 88065543Scg final DeferredAttr.DeferredAttrContext deferredAttrContext, Warner rsWarner) { 881137500Sjulian CheckContext checkContext = new MethodCheckContext(!deferredAttrContext.phase.isBoxingRequired(), deferredAttrContext, rsWarner) { 882137500Sjulian MethodCheckDiag methodDiag = varargsCheck ? 883137500Sjulian MethodCheckDiag.VARARG_MISMATCH : MethodCheckDiag.ARG_MISMATCH; 88465543Scg 88565543Scg @Override 88665543Scg public void report(DiagnosticPosition pos, JCDiagnostic details) { 887137500Sjulian reportMC(pos, methodDiag, deferredAttrContext.inferenceContext, details); 888137500Sjulian } 88965543Scg }; 890137500Sjulian return new MethodResultInfo(to, checkContext); 891137500Sjulian } 892137500Sjulian 893137500Sjulian @Override 894137500Sjulian public MethodCheck mostSpecificCheck(List<Type> actuals) { 895137500Sjulian return new MostSpecificCheck(actuals); 896137500Sjulian } 897137500Sjulian 898137500Sjulian @Override 899137500Sjulian public String toString() { 900137500Sjulian return "resolveMethodCheck"; 901137500Sjulian } 90265543Scg }; 903137500Sjulian 904137500Sjulian /** 905137500Sjulian * This class handles method reference applicability checks; since during 906137500Sjulian * these checks it's sometime possible to have inference variables on 907137500Sjulian * the actual argument types list, the method applicability check must be 90865543Scg * extended so that inference variables are 'opened' as needed. 909137500Sjulian */ 910137500Sjulian class MethodReferenceCheck extends AbstractMethodCheck { 911137500Sjulian 91265543Scg InferenceContext pendingInferenceContext; 913137500Sjulian 914137500Sjulian MethodReferenceCheck(InferenceContext pendingInferenceContext) { 915137500Sjulian this.pendingInferenceContext = pendingInferenceContext; 916137500Sjulian } 917137500Sjulian 918137500Sjulian @Override 919137500Sjulian void checkArg(DiagnosticPosition pos, boolean varargs, Type actual, Type formal, DeferredAttrContext deferredAttrContext, Warner warn) { 920137500Sjulian ResultInfo mresult = methodCheckResult(varargs, formal, deferredAttrContext, warn); 921137500Sjulian mresult.check(pos, actual); 922137500Sjulian } 923137500Sjulian 924137500Sjulian private ResultInfo methodCheckResult(final boolean varargsCheck, Type to, 925137500Sjulian final DeferredAttr.DeferredAttrContext deferredAttrContext, Warner rsWarner) { 92665543Scg CheckContext checkContext = new MethodCheckContext(!deferredAttrContext.phase.isBoxingRequired(), deferredAttrContext, rsWarner) { 92765543Scg MethodCheckDiag methodDiag = varargsCheck ? 92865543Scg MethodCheckDiag.VARARG_MISMATCH : MethodCheckDiag.ARG_MISMATCH; 92965543Scg 93065543Scg @Override 931137500Sjulian public boolean compatible(Type found, Type req, Warner warn) { 932137500Sjulian found = pendingInferenceContext.asUndetVar(found); 933137500Sjulian if (found.hasTag(UNDETVAR) && req.isPrimitive()) { 934137500Sjulian req = types.boxedClass(req).type; 935137500Sjulian } 936137500Sjulian return super.compatible(found, req, warn); 93765543Scg } 938137500Sjulian 93965543Scg @Override 940137500Sjulian public void report(DiagnosticPosition pos, JCDiagnostic details) { 941137500Sjulian reportMC(pos, methodDiag, deferredAttrContext.inferenceContext, details); 942137500Sjulian } 943137500Sjulian }; 944137500Sjulian return new MethodResultInfo(to, checkContext); 945137500Sjulian } 946137500Sjulian 947137500Sjulian @Override 948137500Sjulian public MethodCheck mostSpecificCheck(List<Type> actuals) { 94965543Scg return new MostSpecificCheck(actuals); 95065543Scg } 951137500Sjulian 952137500Sjulian @Override 953137500Sjulian public String toString() { 954137500Sjulian return "MethodReferenceCheck"; 955137500Sjulian } 956137500Sjulian } 957137500Sjulian 958137500Sjulian /** 959137500Sjulian * Check context to be used during method applicability checks. A method check 960137500Sjulian * context might contain inference variables. 961137500Sjulian */ 962137500Sjulian abstract class MethodCheckContext implements CheckContext { 963137500Sjulian 964137500Sjulian boolean strict; 965137500Sjulian DeferredAttrContext deferredAttrContext; 966137500Sjulian Warner rsWarner; 967137500Sjulian 968137500Sjulian public MethodCheckContext(boolean strict, DeferredAttrContext deferredAttrContext, Warner rsWarner) { 969137500Sjulian this.strict = strict; 970137500Sjulian this.deferredAttrContext = deferredAttrContext; 971137500Sjulian this.rsWarner = rsWarner; 972137500Sjulian } 973137500Sjulian 974137500Sjulian public boolean compatible(Type found, Type req, Warner warn) { 975137500Sjulian InferenceContext inferenceContext = deferredAttrContext.inferenceContext; 976137500Sjulian return strict ? 977137500Sjulian types.isSubtypeUnchecked(inferenceContext.asUndetVar(found), inferenceContext.asUndetVar(req), warn) : 978137500Sjulian types.isConvertible(inferenceContext.asUndetVar(found), inferenceContext.asUndetVar(req), warn); 979137500Sjulian } 980137500Sjulian 981137500Sjulian public void report(DiagnosticPosition pos, JCDiagnostic details) { 982137500Sjulian throw inapplicableMethodException.setMessage(details); 983137500Sjulian } 984137500Sjulian 985137500Sjulian public Warner checkWarner(DiagnosticPosition pos, Type found, Type req) { 986137500Sjulian return rsWarner; 987137500Sjulian } 988137500Sjulian 989137500Sjulian public InferenceContext inferenceContext() { 990137500Sjulian return deferredAttrContext.inferenceContext; 991137500Sjulian } 992137500Sjulian 993137500Sjulian public DeferredAttrContext deferredAttrContext() { 994137500Sjulian return deferredAttrContext; 995137500Sjulian } 996137500Sjulian 997137500Sjulian @Override 998137500Sjulian public String toString() { 999137500Sjulian return "MethodCheckContext"; 1000137500Sjulian } 1001137500Sjulian } 1002137500Sjulian 1003137500Sjulian /** 1004137500Sjulian * ResultInfo class to be used during method applicability checks. Check 1005137500Sjulian * for deferred types goes through special path. 1006137500Sjulian */ 1007137500Sjulian class MethodResultInfo extends ResultInfo { 1008137500Sjulian 1009137500Sjulian public MethodResultInfo(Type pt, CheckContext checkContext) { 1010137500Sjulian attr.super(KindSelector.VAL, pt, checkContext); 1011137500Sjulian } 1012137500Sjulian 1013137500Sjulian @Override 1014137500Sjulian protected Type check(DiagnosticPosition pos, Type found) { 1015137500Sjulian if (found.hasTag(DEFERRED)) { 1016137500Sjulian DeferredType dt = (DeferredType)found; 1017137500Sjulian return dt.check(this); 1018137500Sjulian } else { 1019137500Sjulian Type uResult = U(found); 1020137500Sjulian Type capturedType = pos == null || pos.getTree() == null ? 1021137500Sjulian types.capture(uResult) : 1022137500Sjulian checkContext.inferenceContext() 1023137500Sjulian .cachedCapture(pos.getTree(), uResult, true); 1024137500Sjulian return super.check(pos, chk.checkNonVoid(pos, capturedType)); 1025137500Sjulian } 1026137500Sjulian } 1027137500Sjulian 1028137500Sjulian /** 1029137500Sjulian * javac has a long-standing 'simplification' (see 6391995): 1030137500Sjulian * given an actual argument type, the method check is performed 1031137500Sjulian * on its upper bound. This leads to inconsistencies when an 1032137500Sjulian * argument type is checked against itself. For example, given 1033137500Sjulian * a type-variable T, it is not true that {@code U(T) <: T}, 1034137500Sjulian * so we need to guard against that. 1035137500Sjulian */ 1036137500Sjulian private Type U(Type found) { 1037137500Sjulian return found == pt ? 1038137500Sjulian found : types.cvarUpperBound(found); 1039137500Sjulian } 1040137500Sjulian 1041137500Sjulian @Override 1042137500Sjulian protected MethodResultInfo dup(Type newPt) { 1043137500Sjulian return new MethodResultInfo(newPt, checkContext); 1044137500Sjulian } 1045137500Sjulian 1046137500Sjulian @Override 1047137500Sjulian protected ResultInfo dup(CheckContext newContext) { 1048137500Sjulian return new MethodResultInfo(pt, newContext); 1049137500Sjulian } 1050137500Sjulian 1051137500Sjulian @Override 1052137500Sjulian protected ResultInfo dup(Type newPt, CheckContext newContext) { 1053137500Sjulian return new MethodResultInfo(newPt, newContext); 1054137500Sjulian } 1055137500Sjulian } 1056137500Sjulian 1057137500Sjulian /** 1058137500Sjulian * Most specific method applicability routine. Given a list of actual types A, 1059137500Sjulian * a list of formal types F1, and a list of formal types F2, the routine determines 1060137500Sjulian * as to whether the types in F1 can be considered more specific than those in F2 w.r.t. 1061137500Sjulian * argument types A. 106265543Scg */ 1063137500Sjulian class MostSpecificCheck implements MethodCheck { 1064137500Sjulian 1065137500Sjulian List<Type> actuals; 1066137500Sjulian 1067137500Sjulian MostSpecificCheck(List<Type> actuals) { 1068137500Sjulian this.actuals = actuals; 1069166279Sariff } 1070137500Sjulian 1071137500Sjulian @Override 1072137500Sjulian public void argumentsAcceptable(final Env<AttrContext> env, 1073137500Sjulian DeferredAttrContext deferredAttrContext, 1074137500Sjulian List<Type> formals1, 1075137500Sjulian List<Type> formals2, 1076137500Sjulian Warner warn) { 1077137500Sjulian formals2 = adjustArgs(formals2, deferredAttrContext.msym, formals1.length(), deferredAttrContext.phase.isVarargsRequired()); 1078137500Sjulian while (formals2.nonEmpty()) { 1079137500Sjulian ResultInfo mresult = methodCheckResult(formals2.head, deferredAttrContext, warn, actuals.head); 1080137500Sjulian mresult.check(null, formals1.head); 1081137500Sjulian formals1 = formals1.tail; 1082137500Sjulian formals2 = formals2.tail; 1083137500Sjulian actuals = actuals.isEmpty() ? actuals : actuals.tail; 1084137500Sjulian } 1085137500Sjulian } 1086137500Sjulian 1087137500Sjulian /** 1088137500Sjulian * Create a method check context to be used during the most specific applicability check 1089137500Sjulian */ 1090137500Sjulian ResultInfo methodCheckResult(Type to, DeferredAttr.DeferredAttrContext deferredAttrContext, 1091137500Sjulian Warner rsWarner, Type actual) { 1092137500Sjulian return attr.new ResultInfo(KindSelector.VAL, to, 1093137500Sjulian new MostSpecificCheckContext(deferredAttrContext, rsWarner, actual)); 1094137500Sjulian } 1095137500Sjulian 1096137500Sjulian /** 1097137500Sjulian * Subclass of method check context class that implements most specific 1098137500Sjulian * method conversion. If the actual type under analysis is a deferred type 1099137500Sjulian * a full blown structural analysis is carried out. 1100137500Sjulian */ 1101137500Sjulian class MostSpecificCheckContext extends MethodCheckContext { 1102137500Sjulian 1103137500Sjulian Type actual; 1104137500Sjulian 1105137500Sjulian public MostSpecificCheckContext(DeferredAttrContext deferredAttrContext, Warner rsWarner, Type actual) { 1106137500Sjulian super(true, deferredAttrContext, rsWarner); 1107137500Sjulian this.actual = actual; 1108137500Sjulian } 1109137500Sjulian 1110137500Sjulian public boolean compatible(Type found, Type req, Warner warn) { 1111166279Sariff if (allowFunctionalInterfaceMostSpecific && 1112137500Sjulian unrelatedFunctionalInterfaces(found, req) && 1113137500Sjulian (actual != null && actual.getTag() == DEFERRED)) { 1114137500Sjulian DeferredType dt = (DeferredType) actual; 1115137500Sjulian JCTree speculativeTree = dt.speculativeTree(deferredAttrContext); 1116137500Sjulian if (speculativeTree != deferredAttr.stuckTree) { 1117137500Sjulian return functionalInterfaceMostSpecific(found, req, speculativeTree); 1118137500Sjulian } 1119137500Sjulian } 1120137500Sjulian return compatibleBySubtyping(found, req); 1121137500Sjulian } 1122137500Sjulian 1123137500Sjulian private boolean compatibleBySubtyping(Type found, Type req) { 1124137500Sjulian if (!strict && found.isPrimitive() != req.isPrimitive()) { 1125137500Sjulian found = found.isPrimitive() ? types.boxedClass(found).type : types.unboxedType(found); 1126137500Sjulian } 1127137500Sjulian return types.isSubtypeNoCapture(found, deferredAttrContext.inferenceContext.asUndetVar(req)); 1128137500Sjulian } 1129137500Sjulian 1130137500Sjulian /** Whether {@code t} and {@code s} are unrelated functional interface types. */ 1131137500Sjulian private boolean unrelatedFunctionalInterfaces(Type t, Type s) { 1132137500Sjulian return types.isFunctionalInterface(t.tsym) && 1133137500Sjulian types.isFunctionalInterface(s.tsym) && 1134137500Sjulian types.asSuper(t, s.tsym) == null && 1135137500Sjulian types.asSuper(s, t.tsym) == null; 1136137500Sjulian } 1137137500Sjulian 1138137500Sjulian /** Parameters {@code t} and {@code s} are unrelated functional interface types. */ 1139166279Sariff private boolean functionalInterfaceMostSpecific(Type t, Type s, JCTree tree) { 1140137500Sjulian Type tDesc = types.findDescriptorType(t); 114165543Scg Type sDesc = types.findDescriptorType(s); 114265543Scg 114365543Scg // compare type parameters -- can't use Types.hasSameBounds because bounds may have ivars 114465543Scg final List<Type> tTypeParams = tDesc.getTypeArguments(); 1145166279Sariff final List<Type> sTypeParams = sDesc.getTypeArguments(); 114665543Scg List<Type> tIter = tTypeParams; 114765543Scg List<Type> sIter = sTypeParams; 1148137500Sjulian while (tIter.nonEmpty() && sIter.nonEmpty()) { 1149137500Sjulian Type tBound = tIter.head.getUpperBound(); 115065543Scg Type sBound = types.subst(sIter.head.getUpperBound(), sTypeParams, tTypeParams); 1151137500Sjulian if (tBound.containsAny(tTypeParams) && inferenceContext().free(sBound)) { 1152137500Sjulian return false; 1153137500Sjulian } 1154137500Sjulian if (!types.isSameType(tBound, inferenceContext().asUndetVar(sBound))) { 1155137500Sjulian return false; 1156137500Sjulian } 1157137500Sjulian tIter = tIter.tail; 1158137500Sjulian sIter = sIter.tail; 115965543Scg } 116065543Scg if (!tIter.isEmpty() || !sIter.isEmpty()) { 116165543Scg return false; 1162166279Sariff } 1163137500Sjulian 1164137500Sjulian // compare parameters 1165137500Sjulian List<Type> tParams = tDesc.getParameterTypes(); 1166137500Sjulian List<Type> sParams = sDesc.getParameterTypes(); 1167137500Sjulian while (tParams.nonEmpty() && sParams.nonEmpty()) { 1168137500Sjulian Type tParam = tParams.head; 1169137500Sjulian Type sParam = types.subst(sParams.head, sTypeParams, tTypeParams); 1170137500Sjulian if (tParam.containsAny(tTypeParams) && inferenceContext().free(sParam)) { 1171137500Sjulian return false; 1172137500Sjulian } 1173137500Sjulian if (!types.isSameType(tParam, inferenceContext().asUndetVar(sParam))) { 1174137500Sjulian return false; 1175137500Sjulian } 1176137500Sjulian tParams = tParams.tail; 1177166279Sariff sParams = sParams.tail; 1178137500Sjulian } 1179166279Sariff if (!tParams.isEmpty() || !sParams.isEmpty()) { 1180137500Sjulian return false; 118165543Scg } 1182137500Sjulian 118365543Scg // compare returns 1184137500Sjulian Type tRet = tDesc.getReturnType(); 1185137500Sjulian Type sRet = types.subst(sDesc.getReturnType(), sTypeParams, tTypeParams); 1186137500Sjulian if (tRet.containsAny(tTypeParams) && inferenceContext().free(sRet)) { 1187137500Sjulian return false; 1188137500Sjulian } 1189137500Sjulian MostSpecificFunctionReturnChecker msc = new MostSpecificFunctionReturnChecker(tRet, sRet); 1190137500Sjulian msc.scan(tree); 1191137500Sjulian return msc.result; 1192137500Sjulian } 1193137500Sjulian 1194137500Sjulian /** 119565543Scg * Tests whether one functional interface type can be considered more specific 1196166279Sariff * than another unrelated functional interface type for the scanned expression. 1197137500Sjulian */ 1198137500Sjulian class MostSpecificFunctionReturnChecker extends DeferredAttr.PolyScanner { 1199137500Sjulian 1200137500Sjulian final Type tRet; 1201137500Sjulian final Type sRet; 1202137500Sjulian boolean result; 1203137500Sjulian 1204137500Sjulian /** Parameters {@code t} and {@code s} are unrelated functional interface types. */ 1205137500Sjulian MostSpecificFunctionReturnChecker(Type tRet, Type sRet) { 1206137500Sjulian this.tRet = tRet; 1207137500Sjulian this.sRet = sRet; 1208137500Sjulian result = true; 1209137500Sjulian } 121065543Scg 121165543Scg @Override 121265543Scg void skip(JCTree tree) { 121365543Scg result &= false; 121465543Scg } 121565543Scg 1216137500Sjulian @Override 121765543Scg public void visitConditional(JCConditional tree) { 121865543Scg scan(asExpr(tree.truepart)); 121965543Scg scan(asExpr(tree.falsepart)); 1220137500Sjulian } 1221137500Sjulian 1222137500Sjulian @Override 1223137500Sjulian public void visitReference(JCMemberReference tree) { 1224137500Sjulian if (sRet.hasTag(VOID)) { 122565543Scg result &= true; 1226137500Sjulian } else if (tRet.hasTag(VOID)) { 122765543Scg result &= false; 122865543Scg } else if (tRet.isPrimitive() != sRet.isPrimitive()) { 122965543Scg boolean retValIsPrimitive = 123065543Scg tree.refPolyKind == PolyKind.STANDALONE && 123165543Scg tree.sym.type.getReturnType().isPrimitive(); 123265543Scg result &= (retValIsPrimitive == tRet.isPrimitive()) && 123365543Scg (retValIsPrimitive != sRet.isPrimitive()); 1234137500Sjulian } else { 1235137500Sjulian result &= compatibleBySubtyping(tRet, sRet); 1236137500Sjulian } 1237137500Sjulian } 1238137500Sjulian 1239137500Sjulian @Override 1240137500Sjulian public void visitParens(JCParens tree) { 1241137500Sjulian scan(asExpr(tree.expr)); 1242137500Sjulian } 1243137500Sjulian 1244137500Sjulian @Override 1245137500Sjulian public void visitLambda(JCLambda tree) { 1246137500Sjulian if (sRet.hasTag(VOID)) { 1247137500Sjulian result &= true; 1248137500Sjulian } else if (tRet.hasTag(VOID)) { 1249137500Sjulian result &= false; 1250154067Sariff } else { 1251137500Sjulian List<JCExpression> lambdaResults = lambdaResults(tree); 1252154067Sariff if (!lambdaResults.isEmpty() && unrelatedFunctionalInterfaces(tRet, sRet)) { 1253137500Sjulian for (JCExpression expr : lambdaResults) { 1254137500Sjulian result &= functionalInterfaceMostSpecific(tRet, sRet, expr); 1255137500Sjulian } 1256137500Sjulian } else if (!lambdaResults.isEmpty() && tRet.isPrimitive() != sRet.isPrimitive()) { 1257137500Sjulian for (JCExpression expr : lambdaResults) { 1258137500Sjulian boolean retValIsPrimitive = expr.isStandalone() && expr.type.isPrimitive(); 1259137500Sjulian result &= (retValIsPrimitive == tRet.isPrimitive()) && 1260137500Sjulian (retValIsPrimitive != sRet.isPrimitive()); 1261137500Sjulian } 1262154067Sariff } else { 1263137500Sjulian result &= compatibleBySubtyping(tRet, sRet); 1264154067Sariff } 1265137500Sjulian } 1266137500Sjulian } 1267137500Sjulian //where 1268137500Sjulian 1269137500Sjulian private List<JCExpression> lambdaResults(JCLambda lambda) { 1270137500Sjulian if (lambda.getBodyKind() == JCTree.JCLambda.BodyKind.EXPRESSION) { 1271137500Sjulian return List.of(asExpr((JCExpression) lambda.body)); 1272137500Sjulian } else { 1273193640Sariff final ListBuffer<JCExpression> buffer = new ListBuffer<>(); 1274137500Sjulian DeferredAttr.LambdaReturnScanner lambdaScanner = 1275137500Sjulian new DeferredAttr.LambdaReturnScanner() { 1276137500Sjulian @Override 1277137500Sjulian public void visitReturn(JCReturn tree) { 1278137500Sjulian if (tree.expr != null) { 1279137500Sjulian buffer.append(asExpr(tree.expr)); 1280137500Sjulian } 1281137500Sjulian } 128265543Scg }; 1283166279Sariff lambdaScanner.scan(lambda.body); 1284166279Sariff return buffer.toList(); 128565543Scg } 128665543Scg } 128765543Scg 128865543Scg private JCExpression asExpr(JCExpression expr) { 128970291Scg if (expr.type.hasTag(DEFERRED)) { 129065543Scg JCTree speculativeTree = ((DeferredType)expr.type).speculativeTree(deferredAttrContext); 1291137500Sjulian if (speculativeTree != deferredAttr.stuckTree) { 1292137500Sjulian expr = (JCExpression)speculativeTree; 1293137500Sjulian } 129465543Scg } 129565543Scg return expr; 129665543Scg } 129765543Scg } 129865543Scg 129965543Scg } 1300137500Sjulian 1301137500Sjulian public MethodCheck mostSpecificCheck(List<Type> actuals) { 1302137500Sjulian Assert.error("Cannot get here!"); 1303137500Sjulian return null; 1304137500Sjulian } 1305137500Sjulian } 130684658Scg 1307137500Sjulian public static class InapplicableMethodException extends RuntimeException { 1308137500Sjulian private static final long serialVersionUID = 0; 1309137500Sjulian 131065543Scg JCDiagnostic diagnostic; 1311137500Sjulian JCDiagnostic.Factory diags; 1312137500Sjulian 131365543Scg InapplicableMethodException(JCDiagnostic.Factory diags) { 1314137500Sjulian this.diagnostic = null; 1315137500Sjulian this.diags = diags; 1316137500Sjulian } 1317137500Sjulian InapplicableMethodException setMessage() { 1318137500Sjulian return setMessage((JCDiagnostic)null); 1319137500Sjulian } 132065543Scg InapplicableMethodException setMessage(String key) { 1321137500Sjulian return setMessage(key != null ? diags.fragment(key) : null); 1322137500Sjulian } 1323137500Sjulian InapplicableMethodException setMessage(String key, Object... args) { 1324137500Sjulian return setMessage(key != null ? diags.fragment(key, args) : null); 1325137500Sjulian } 1326137500Sjulian InapplicableMethodException setMessage(JCDiagnostic diag) { 1327137500Sjulian this.diagnostic = diag; 1328137500Sjulian return this; 1329137500Sjulian } 1330137500Sjulian 1331137500Sjulian public JCDiagnostic getDiagnostic() { 1332137500Sjulian return diagnostic; 1333137500Sjulian } 1334137500Sjulian } 1335137500Sjulian private final InapplicableMethodException inapplicableMethodException; 1336137500Sjulian 1337137500Sjulian/* *************************************************************************** 1338137500Sjulian * Symbol lookup 1339137500Sjulian * the following naming conventions for arguments are used 1340137500Sjulian * 1341137500Sjulian * env is the environment where the symbol was mentioned 1342137500Sjulian * site is the type of which the symbol is a member 1343137500Sjulian * name is the symbol's name 1344137500Sjulian * if no arguments are given 1345137500Sjulian * argtypes are the value arguments, if we search for a method 1346137500Sjulian * 1347137500Sjulian * If no symbol was found, a ResolveError detailing the problem is returned. 1348137500Sjulian ****************************************************************************/ 1349137500Sjulian 1350137500Sjulian /** Find field. Synthetic fields are always skipped. 1351137500Sjulian * @param env The current environment. 1352137500Sjulian * @param site The original type from where the selection takes place. 1353137500Sjulian * @param name The name of the field. 135465543Scg * @param c The class to search for the field. This is always 135565543Scg * a superclass or implemented interface of site's class. 135665543Scg */ 1357137500Sjulian Symbol findField(Env<AttrContext> env, 135865543Scg Type site, 1359137500Sjulian Name name, 1360137500Sjulian TypeSymbol c) { 1361137500Sjulian while (c.type.hasTag(TYPEVAR)) 1362137500Sjulian c = c.type.getUpperBound().tsym; 1363137500Sjulian Symbol bestSoFar = varNotFound; 1364137500Sjulian Symbol sym; 136565543Scg for (Symbol s : c.members().getSymbolsByName(name)) { 136665543Scg if (s.kind == VAR && (s.flags_field & SYNTHETIC) == 0) { 136765543Scg return isAccessible(env, site, s) 136865543Scg ? s : new AccessError(env, site, s); 136965543Scg } 1370137500Sjulian } 137165543Scg Type st = types.supertype(c.type); 137265543Scg if (st != null && (st.hasTag(CLASS) || st.hasTag(TYPEVAR))) { 137365543Scg sym = findField(env, site, name, st.tsym); 1374137500Sjulian bestSoFar = bestOf(bestSoFar, sym); 1375137500Sjulian } 1376137500Sjulian for (List<Type> l = types.interfaces(c.type); 1377193640Sariff bestSoFar.kind != AMBIGUOUS && l.nonEmpty(); 1378137500Sjulian l = l.tail) { 137965543Scg sym = findField(env, site, name, l.head.tsym); 138065543Scg if (bestSoFar.exists() && sym.exists() && 138165543Scg sym.owner != bestSoFar.owner) 1382137500Sjulian bestSoFar = new AmbiguityError(bestSoFar, sym); 1383137500Sjulian else 1384137500Sjulian bestSoFar = bestOf(bestSoFar, sym); 138589887Sscottl } 138665543Scg return bestSoFar; 138765543Scg } 1388193640Sariff 1389137500Sjulian /** Resolve a field identifier, throw a fatal error if not found. 139065543Scg * @param pos The position to use for error reporting. 1391193640Sariff * @param env The environment current at the method invocation. 1392193640Sariff * @param site The type of the qualifying expression, in which 1393193640Sariff * identifier is searched. 1394193640Sariff * @param name The identifier's name. 139565543Scg */ 139665543Scg public VarSymbol resolveInternalField(DiagnosticPosition pos, Env<AttrContext> env, 1397193640Sariff Type site, Name name) { 1398137500Sjulian Symbol sym = findField(env, site, name, site.tsym); 139965543Scg if (sym.kind == VAR) return (VarSymbol)sym; 1400137500Sjulian else throw new FatalError( 1401137500Sjulian diags.fragment("fatal.err.cant.locate.field", 1402137500Sjulian name)); 1403137500Sjulian } 1404137500Sjulian 1405137500Sjulian /** Find unqualified variable or field with given name. 1406137500Sjulian * Synthetic fields always skipped. 1407137500Sjulian * @param env The current environment. 1408137500Sjulian * @param name The name of the variable or field. 1409137500Sjulian */ 1410137500Sjulian Symbol findVar(Env<AttrContext> env, Name name) { 1411137500Sjulian Symbol bestSoFar = varNotFound; 1412137500Sjulian Env<AttrContext> env1 = env; 1413137500Sjulian boolean staticOnly = false; 1414137500Sjulian while (env1.outer != null) { 1415137500Sjulian Symbol sym = null; 1416137500Sjulian if (isStatic(env1)) staticOnly = true; 1417137500Sjulian for (Symbol s : env1.info.scope.getSymbolsByName(name)) { 1418137500Sjulian if (s.kind == VAR && (s.flags_field & SYNTHETIC) == 0) { 141965543Scg sym = s; 142065543Scg break; 142165543Scg } 1422137500Sjulian } 142365543Scg if (sym == null) { 142465543Scg sym = findField(env1, env1.enclClass.sym.type, name, env1.enclClass.sym); 142565543Scg } 142665543Scg if (sym.exists()) { 142765543Scg if (staticOnly && 1428137500Sjulian sym.kind == VAR && 142965543Scg sym.owner.kind == TYP && 1430137500Sjulian (sym.flags() & STATIC) == 0) 143165543Scg return new StaticError(sym); 143265543Scg else 143365543Scg return sym; 1434137500Sjulian } else { 143565543Scg bestSoFar = bestOf(bestSoFar, sym); 143665543Scg } 143765543Scg 143865543Scg if ((env1.enclClass.sym.flags() & STATIC) != 0) staticOnly = true; 143965543Scg env1 = env1.outer; 1440193640Sariff } 1441137500Sjulian 144265543Scg Symbol sym = findField(env, syms.predefClass.type, name, syms.predefClass); 144365543Scg if (sym.exists()) 1444193640Sariff return sym; 144565543Scg if (bestSoFar.exists()) 1446137500Sjulian return bestSoFar; 1447137500Sjulian 1448137500Sjulian Symbol origin = null; 144965543Scg for (Scope sc : new Scope[] { env.toplevel.namedImportScope, env.toplevel.starImportScope }) { 1450137500Sjulian for (Symbol currentSymbol : sc.getSymbolsByName(name)) { 1451137500Sjulian if (currentSymbol.kind != VAR) 1452137500Sjulian continue; 145365543Scg // invariant: sym.kind == Symbol.Kind.VAR 145465543Scg if (!bestSoFar.kind.isResolutionError() && 145574763Scg currentSymbol.owner != bestSoFar.owner) 1456137500Sjulian return new AmbiguityError(bestSoFar, currentSymbol); 145765543Scg else if (!bestSoFar.kind.betterThan(VAR)) { 145865543Scg origin = sc.getOrigin(currentSymbol).owner; 1459193640Sariff bestSoFar = isAccessible(env, origin.type, currentSymbol) 1460193640Sariff ? currentSymbol : new AccessError(env, origin.type, currentSymbol); 1461193640Sariff } 1462193640Sariff } 1463193640Sariff if (bestSoFar.exists()) break; 1464193640Sariff } 146565543Scg if (bestSoFar.kind == VAR && bestSoFar.owner.type != origin.type) 146665543Scg return bestSoFar.clone(origin); 1467154241Sariff else 146865543Scg return bestSoFar; 1469137500Sjulian } 1470137500Sjulian 1471137500Sjulian Warner noteWarner = new Warner(); 1472137500Sjulian 1473137500Sjulian /** Select the best method for a call site among two choices. 1474137500Sjulian * @param env The current environment. 1475137500Sjulian * @param site The original type from where the 1476137500Sjulian * selection takes place. 1477137500Sjulian * @param argtypes The invocation's value arguments, 1478137500Sjulian * @param typeargtypes The invocation's type arguments, 1479137500Sjulian * @param sym Proposed new best match. 1480137500Sjulian * @param bestSoFar Previously found best match. 1481137500Sjulian * @param allowBoxing Allow boxing conversions of arguments. 1482193640Sariff * @param useVarargs Box trailing arguments into an array for varargs. 1483137500Sjulian */ 1484137500Sjulian @SuppressWarnings("fallthrough") 1485137500Sjulian Symbol selectBest(Env<AttrContext> env, 1486137500Sjulian Type site, 1487137500Sjulian List<Type> argtypes, 1488137500Sjulian List<Type> typeargtypes, 1489137500Sjulian Symbol sym, 1490137500Sjulian Symbol bestSoFar, 1491137500Sjulian boolean allowBoxing, 1492166279Sariff boolean useVarargs) { 1493166279Sariff if (sym.kind == ERR || 1494137500Sjulian !sym.isInheritedIn(site.tsym, types)) { 1495137500Sjulian return bestSoFar; 1496137500Sjulian } else if (useVarargs && (sym.flags() & VARARGS) == 0) { 1497137500Sjulian return bestSoFar.kind.isResolutionError() ? 1498137500Sjulian new BadVarargsMethod((ResolveError)bestSoFar.baseSymbol()) : 1499137500Sjulian bestSoFar; 1500137500Sjulian } 1501137500Sjulian Assert.check(!sym.kind.isResolutionError()); 1502137500Sjulian try { 1503137500Sjulian types.noWarnings.clear(); 1504137500Sjulian Type mt = rawInstantiate(env, site, sym, null, argtypes, typeargtypes, 1505137500Sjulian allowBoxing, useVarargs, types.noWarnings); 1506137500Sjulian currentResolutionContext.addApplicableCandidate(sym, mt); 1507137500Sjulian } catch (InapplicableMethodException ex) { 1508137500Sjulian currentResolutionContext.addInapplicableCandidate(sym, ex.getDiagnostic()); 1509137500Sjulian switch (bestSoFar.kind) { 1510137500Sjulian case ABSENT_MTH: 1511137500Sjulian return new InapplicableSymbolError(currentResolutionContext); 1512137500Sjulian case WRONG_MTH: 1513137500Sjulian bestSoFar = new InapplicableSymbolsError(currentResolutionContext); 1514137500Sjulian default: 1515137500Sjulian return bestSoFar; 1516137500Sjulian } 1517137500Sjulian } 1518137500Sjulian if (!isAccessible(env, site, sym)) { 1519137500Sjulian return (bestSoFar.kind == ABSENT_MTH) 1520137500Sjulian ? new AccessError(env, site, sym) 1521137500Sjulian : bestSoFar; 1522137500Sjulian } 1523137500Sjulian return (bestSoFar.kind.isResolutionError() && bestSoFar.kind != AMBIGUOUS) 1524137500Sjulian ? sym 1525137500Sjulian : mostSpecific(argtypes, sym, bestSoFar, env, site, useVarargs); 1526137500Sjulian } 1527137500Sjulian 1528137500Sjulian /* Return the most specific of the two methods for a call, 1529193640Sariff * given that both are accessible and applicable. 1530137500Sjulian * @param m1 A new candidate for most specific. 1531137500Sjulian * @param m2 The previous most specific candidate. 1532137500Sjulian * @param env The current environment. 1533137500Sjulian * @param site The original type from where the selection 1534137500Sjulian * takes place. 1535137500Sjulian * @param allowBoxing Allow boxing conversions of arguments. 1536193640Sariff * @param useVarargs Box trailing arguments into an array for varargs. 1537137500Sjulian */ 1538137500Sjulian Symbol mostSpecific(List<Type> argtypes, Symbol m1, 1539193640Sariff Symbol m2, 1540193640Sariff Env<AttrContext> env, 1541193640Sariff final Type site, 1542193640Sariff boolean useVarargs) { 1543137500Sjulian switch (m2.kind) { 1544137500Sjulian case MTH: 1545193640Sariff if (m1 == m2) return m1; 1546137500Sjulian boolean m1SignatureMoreSpecific = 1547137500Sjulian signatureMoreSpecific(argtypes, env, site, m1, m2, useVarargs); 1548137500Sjulian boolean m2SignatureMoreSpecific = 1549137500Sjulian signatureMoreSpecific(argtypes, env, site, m2, m1, useVarargs); 1550137500Sjulian if (m1SignatureMoreSpecific && m2SignatureMoreSpecific) { 1551137500Sjulian Type mt1 = types.memberType(site, m1); 1552137500Sjulian Type mt2 = types.memberType(site, m2); 1553137500Sjulian if (!types.overrideEquivalent(mt1, mt2)) 1554137500Sjulian return ambiguityError(m1, m2); 1555137500Sjulian 1556137500Sjulian // same signature; select (a) the non-bridge method, or 1557137500Sjulian // (b) the one that overrides the other, or (c) the concrete 1558137500Sjulian // one, or (d) merge both abstract signatures 1559137500Sjulian if ((m1.flags() & BRIDGE) != (m2.flags() & BRIDGE)) 1560137500Sjulian return ((m1.flags() & BRIDGE) != 0) ? m2 : m1; 1561137500Sjulian 1562137500Sjulian // if one overrides or hides the other, use it 1563137500Sjulian TypeSymbol m1Owner = (TypeSymbol)m1.owner; 1564137500Sjulian TypeSymbol m2Owner = (TypeSymbol)m2.owner; 1565137500Sjulian if (types.asSuper(m1Owner.type, m2Owner) != null && 1566137500Sjulian ((m1.owner.flags_field & INTERFACE) == 0 || 1567137500Sjulian (m2.owner.flags_field & INTERFACE) != 0) && 1568137500Sjulian m1.overrides(m2, m1Owner, types, false)) 1569137500Sjulian return m1; 1570137500Sjulian if (types.asSuper(m2Owner.type, m1Owner) != null && 1571137500Sjulian ((m2.owner.flags_field & INTERFACE) == 0 || 1572137500Sjulian (m1.owner.flags_field & INTERFACE) != 0) && 1573137500Sjulian m2.overrides(m1, m2Owner, types, false)) 1574137500Sjulian return m2; 1575137500Sjulian boolean m1Abstract = (m1.flags() & ABSTRACT) != 0; 1576137500Sjulian boolean m2Abstract = (m2.flags() & ABSTRACT) != 0; 1577137500Sjulian if (m1Abstract && !m2Abstract) return m2; 1578137500Sjulian if (m2Abstract && !m1Abstract) return m1; 1579137500Sjulian // both abstract or both concrete 1580137500Sjulian return ambiguityError(m1, m2); 1581137500Sjulian } 1582137500Sjulian if (m1SignatureMoreSpecific) return m1; 1583137500Sjulian if (m2SignatureMoreSpecific) return m2; 1584137500Sjulian return ambiguityError(m1, m2); 1585137500Sjulian case AMBIGUOUS: 1586137500Sjulian //compare m1 to ambiguous methods in m2 1587137500Sjulian AmbiguityError e = (AmbiguityError)m2.baseSymbol(); 1588137500Sjulian boolean m1MoreSpecificThanAnyAmbiguous = true; 1589137500Sjulian boolean allAmbiguousMoreSpecificThanM1 = true; 1590137500Sjulian for (Symbol s : e.ambiguousSyms) { 1591137500Sjulian Symbol moreSpecific = mostSpecific(argtypes, m1, s, env, site, useVarargs); 1592193640Sariff m1MoreSpecificThanAnyAmbiguous &= moreSpecific == m1; 1593137500Sjulian allAmbiguousMoreSpecificThanM1 &= moreSpecific == s; 1594137500Sjulian } 1595137500Sjulian if (m1MoreSpecificThanAnyAmbiguous) 1596137500Sjulian return m1; 1597137500Sjulian //if m1 is more specific than some ambiguous methods, but other ambiguous methods are 1598137500Sjulian //more specific than m1, add it as a new ambiguous method: 1599137500Sjulian if (!allAmbiguousMoreSpecificThanM1) 1600137500Sjulian e.addAmbiguousSymbol(m1); 1601137500Sjulian return e; 1602137500Sjulian default: 160365543Scg throw new AssertionError(); 1604193640Sariff } 1605193640Sariff } 160665543Scg //where 160765543Scg private boolean signatureMoreSpecific(List<Type> actuals, Env<AttrContext> env, Type site, Symbol m1, Symbol m2, boolean useVarargs) { 1608137500Sjulian noteWarner.clear(); 160965543Scg int maxLength = Math.max( 1610137500Sjulian Math.max(m1.type.getParameterTypes().length(), actuals.length()), 161165543Scg m2.type.getParameterTypes().length()); 161265543Scg MethodResolutionContext prevResolutionContext = currentResolutionContext; 1613137500Sjulian try { 1614137500Sjulian currentResolutionContext = new MethodResolutionContext(); 1615137500Sjulian currentResolutionContext.step = prevResolutionContext.step; 1616137500Sjulian currentResolutionContext.methodCheck = 1617137500Sjulian prevResolutionContext.methodCheck.mostSpecificCheck(actuals); 1618137500Sjulian Type mst = instantiate(env, site, m2, null, 1619137500Sjulian adjustArgs(types.cvarLowerBounds(types.memberType(site, m1).getParameterTypes()), m1, maxLength, useVarargs), null, 1620137500Sjulian false, useVarargs, noteWarner); 1621137500Sjulian return mst != null && 1622193640Sariff !noteWarner.hasLint(Lint.LintCategory.UNCHECKED); 162370134Scg } finally { 1624137500Sjulian currentResolutionContext = prevResolutionContext; 162565543Scg } 1626137500Sjulian } 162765543Scg 162865543Scg List<Type> adjustArgs(List<Type> args, Symbol msym, int length, boolean allowVarargs) { 162965543Scg if ((msym.flags() & VARARGS) != 0 && allowVarargs) { 163065543Scg Type varargsElem = types.elemtype(args.last()); 163165543Scg if (varargsElem == null) { 163265543Scg Assert.error("Bad varargs = " + args.last() + " " + msym); 163365543Scg } 163465543Scg List<Type> newArgs = args.reverse().tail.prepend(varargsElem).reverse(); 1635137500Sjulian while (newArgs.length() < length) { 163665543Scg newArgs = newArgs.append(newArgs.last()); 1637137500Sjulian } 163865543Scg return newArgs; 1639137500Sjulian } else { 164065543Scg return args; 164165543Scg } 164265543Scg } 1643137500Sjulian //where 1644137500Sjulian Type mostSpecificReturnType(Type mt1, Type mt2) { 164570619Sjhb Type rt1 = mt1.getReturnType(); 1646137500Sjulian Type rt2 = mt2.getReturnType(); 1647137500Sjulian 1648137500Sjulian if (mt1.hasTag(FORALL) && mt2.hasTag(FORALL)) { 1649137500Sjulian //if both are generic methods, adjust return type ahead of subtyping check 1650137500Sjulian rt1 = types.subst(rt1, mt1.getTypeArguments(), mt2.getTypeArguments()); 1651137500Sjulian } 1652137500Sjulian //first use subtyping, then return type substitutability 1653137500Sjulian if (types.isSubtype(rt1, rt2)) { 1654137500Sjulian return mt1; 1655137500Sjulian } else if (types.isSubtype(rt2, rt1)) { 1656137500Sjulian return mt2; 1657137500Sjulian } else if (types.returnTypeSubstitutable(mt1, mt2)) { 1658137500Sjulian return mt1; 1659137500Sjulian } else if (types.returnTypeSubstitutable(mt2, mt1)) { 1660137500Sjulian return mt2; 1661137500Sjulian } else { 1662137500Sjulian return null; 1663137500Sjulian } 1664137500Sjulian } 1665137500Sjulian //where 1666137500Sjulian Symbol ambiguityError(Symbol m1, Symbol m2) { 1667137500Sjulian if (((m1.flags() | m2.flags()) & CLASH) != 0) { 1668137500Sjulian return (m1.flags() & CLASH) == 0 ? m1 : m2; 1669137500Sjulian } else { 1670137500Sjulian return new AmbiguityError(m1, m2); 1671137500Sjulian } 1672137500Sjulian } 1673137500Sjulian 1674137500Sjulian Symbol findMethodInScope(Env<AttrContext> env, 1675137500Sjulian Type site, 1676137500Sjulian Name name, 1677137500Sjulian List<Type> argtypes, 1678137500Sjulian List<Type> typeargtypes, 1679137500Sjulian Scope sc, 1680137500Sjulian Symbol bestSoFar, 168165543Scg boolean allowBoxing, 1682137500Sjulian boolean useVarargs, 168370619Sjhb boolean abstractok) { 1684137500Sjulian for (Symbol s : sc.getSymbolsByName(name, new LookupFilter(abstractok))) { 1685137500Sjulian bestSoFar = selectBest(env, site, argtypes, typeargtypes, s, 1686137500Sjulian bestSoFar, allowBoxing, useVarargs); 1687137500Sjulian } 1688137500Sjulian return bestSoFar; 168970619Sjhb } 169070619Sjhb //where 169170945Sjhb class LookupFilter implements Filter<Symbol> { 169270619Sjhb 169370619Sjhb boolean abstractOk; 169470945Sjhb 169570619Sjhb LookupFilter(boolean abstractOk) { 169670619Sjhb this.abstractOk = abstractOk; 169770619Sjhb } 169870619Sjhb 1699137500Sjulian public boolean accepts(Symbol s) { 1700137500Sjulian long flags = s.flags(); 1701137500Sjulian return s.kind == MTH && 1702137500Sjulian (flags & SYNTHETIC) == 0 && 1703137500Sjulian (abstractOk || 1704137500Sjulian (flags & DEFAULT) != 0 || 1705137500Sjulian (flags & ABSTRACT) == 0); 170665543Scg } 170765543Scg } 170865543Scg 170965543Scg /** Find best qualified method matching given name, type and value 171065543Scg * arguments. 171165543Scg * @param env The current environment. 171265543Scg * @param site The original type from where the selection 171365543Scg * takes place. 171465543Scg * @param name The method's name. 171565543Scg * @param argtypes The method's value arguments. 171665543Scg * @param typeargtypes The method's type arguments 171765543Scg * @param allowBoxing Allow boxing conversions of arguments. 171865543Scg * @param useVarargs Box trailing arguments into an array for varargs. 171965543Scg */ 172065543Scg Symbol findMethod(Env<AttrContext> env, 172165543Scg Type site, 172265543Scg Name name, 172365543Scg List<Type> argtypes, 172465543Scg List<Type> typeargtypes, 1725137500Sjulian boolean allowBoxing, 172665543Scg boolean useVarargs) { 172765543Scg Symbol bestSoFar = methodNotFound; 172865543Scg bestSoFar = findMethod(env, 172965543Scg site, 1730137500Sjulian name, 173165543Scg argtypes, 1732137500Sjulian typeargtypes, 1733137500Sjulian site.tsym.type, 1734137500Sjulian bestSoFar, 173565543Scg allowBoxing, 173665543Scg useVarargs); 173765543Scg return bestSoFar; 173865543Scg } 173965543Scg // where 174065543Scg private Symbol findMethod(Env<AttrContext> env, 1741137500Sjulian Type site, 174265543Scg Name name, 1743137500Sjulian List<Type> argtypes, 174465543Scg List<Type> typeargtypes, 174565543Scg Type intype, 174665543Scg Symbol bestSoFar, 174765543Scg boolean allowBoxing, 174865543Scg boolean useVarargs) { 174965543Scg @SuppressWarnings({"unchecked","rawtypes"}) 175065543Scg List<Type>[] itypes = (List<Type>[])new List[] { List.<Type>nil(), List.<Type>nil() }; 175165543Scg 175265543Scg InterfaceLookupPhase iphase = InterfaceLookupPhase.ABSTRACT_OK; 175365543Scg for (TypeSymbol s : superclasses(intype)) { 175465543Scg bestSoFar = findMethodInScope(env, site, name, argtypes, typeargtypes, 175565543Scg s.members(), bestSoFar, allowBoxing, useVarargs, true); 175665543Scg if (name == names.init) return bestSoFar; 175765543Scg iphase = (iphase == null) ? null : iphase.update(s, this); 175865543Scg if (iphase != null) { 175965543Scg for (Type itype : types.interfaces(s.type)) { 176065543Scg itypes[iphase.ordinal()] = types.union(types.closure(itype), itypes[iphase.ordinal()]); 176165543Scg } 176265543Scg } 176365543Scg } 176465543Scg 176565543Scg Symbol concrete = bestSoFar.kind.isValid() && 176665543Scg (bestSoFar.flags() & ABSTRACT) == 0 ? 1767142890Simp bestSoFar : methodNotFound; 176865543Scg 176965543Scg for (InterfaceLookupPhase iphase2 : InterfaceLookupPhase.values()) { 177065543Scg //keep searching for abstract methods 177165543Scg for (Type itype : itypes[iphase2.ordinal()]) { 177265543Scg if (!itype.isInterface()) continue; //skip j.l.Object (included by Types.closure()) 177365543Scg if (iphase2 == InterfaceLookupPhase.DEFAULT_OK && 177465543Scg (itype.tsym.flags() & DEFAULT) == 0) continue; 177565543Scg bestSoFar = findMethodInScope(env, site, name, argtypes, typeargtypes, 177665543Scg itype.tsym.members(), bestSoFar, allowBoxing, useVarargs, true); 1777119690Sjhb if (concrete != bestSoFar && 177865543Scg concrete.kind.isValid() && 177965543Scg bestSoFar.kind.isValid() && 178065543Scg types.isSubSignature(concrete.type, bestSoFar.type)) { 178165543Scg //this is an hack - as javac does not do full membership checks 178265543Scg //most specific ends up comparing abstract methods that might have 178365543Scg //been implemented by some concrete method in a subclass and, 1784174582Sariff //because of raw override, it is possible for an abstract method 178565543Scg //to be more specific than the concrete method - so we need 1786170873Sariff //to explicitly call that out (see CR 6178365) 178765543Scg bestSoFar = concrete; 178865543Scg } 1789167608Sariff } 1790137500Sjulian } 1791137500Sjulian return bestSoFar; 1792137500Sjulian } 1793137500Sjulian 1794137500Sjulian enum InterfaceLookupPhase { 1795137500Sjulian ABSTRACT_OK() { 1796137500Sjulian @Override 1797174582Sariff InterfaceLookupPhase update(Symbol s, Resolve rs) { 1798174582Sariff //We should not look for abstract methods if receiver is a concrete class 1799174582Sariff //(as concrete classes are expected to implement all abstracts coming 1800174582Sariff //from superinterfaces) 1801174582Sariff if ((s.flags() & (ABSTRACT | INTERFACE | ENUM)) != 0) { 1802174582Sariff return this; 1803174582Sariff } else { 1804174582Sariff return DEFAULT_OK; 1805174582Sariff } 180684658Scg } 1807166904Snetchild }, 1808137500Sjulian DEFAULT_OK() { 1809137500Sjulian @Override 1810137500Sjulian InterfaceLookupPhase update(Symbol s, Resolve rs) { 1811137500Sjulian return this; 1812137500Sjulian } 1813137500Sjulian }; 1814137500Sjulian 1815137500Sjulian abstract InterfaceLookupPhase update(Symbol s, Resolve rs); 1816137500Sjulian } 1817137500Sjulian 1818137500Sjulian /** 1819137500Sjulian * Return an Iterable object to scan the superclasses of a given type. 1820137500Sjulian * It's crucial that the scan is done lazily, as we don't want to accidentally 182184658Scg * access more supertypes than strictly needed (as this could trigger completion 1822166904Snetchild * errors if some of the not-needed supertypes are missing/ill-formed). 1823137500Sjulian */ 1824137500Sjulian Iterable<TypeSymbol> superclasses(final Type intype) { 1825137500Sjulian return new Iterable<TypeSymbol>() { 1826137500Sjulian public Iterator<TypeSymbol> iterator() { 1827137500Sjulian return new Iterator<TypeSymbol>() { 1828137500Sjulian 1829137500Sjulian List<TypeSymbol> seen = List.nil(); 1830137500Sjulian TypeSymbol currentSym = symbolFor(intype); 1831137500Sjulian TypeSymbol prevSym = null; 1832137500Sjulian 183365543Scg public boolean hasNext() { 1834137500Sjulian if (currentSym == syms.noSymbol) { 183565543Scg currentSym = symbolFor(types.supertype(prevSym.type)); 183665543Scg } 183765543Scg return currentSym != null; 1838137500Sjulian } 1839137500Sjulian 184065543Scg public TypeSymbol next() { 1841137500Sjulian prevSym = currentSym; 1842137500Sjulian currentSym = syms.noSymbol; 184365543Scg Assert.check(prevSym != null || prevSym != syms.noSymbol); 184465543Scg return prevSym; 184565543Scg } 1846137500Sjulian 1847137500Sjulian public void remove() { 184865543Scg throw new UnsupportedOperationException(); 1849137500Sjulian } 1850137500Sjulian 1851137500Sjulian TypeSymbol symbolFor(Type t) { 185265543Scg if (!t.hasTag(CLASS) && 1853254306Sscottl !t.hasTag(TYPEVAR)) { 185465543Scg return null; 1855137500Sjulian } 1856254306Sscottl t = types.skipTypeVars(t, false); 1857137500Sjulian if (seen.contains(t.tsym)) { 1858137500Sjulian //degenerate case in which we have a circular 1859137500Sjulian //class hierarchy - because of ill-formed classfiles 1860137500Sjulian return null; 1861137500Sjulian } 1862137500Sjulian seen = seen.prepend(t.tsym); 186365543Scg return t.tsym; 1864137500Sjulian } 186565543Scg }; 186665543Scg } 1867141095Simp }; 1868141095Simp } 1869137500Sjulian 1870137500Sjulian /** Find unqualified method matching given name, type and value arguments. 1871137500Sjulian * @param env The current environment. 1872137500Sjulian * @param name The method's name. 1873137500Sjulian * @param argtypes The method's value arguments. 1874137500Sjulian * @param typeargtypes The method's type arguments. 1875137500Sjulian * @param allowBoxing Allow boxing conversions of arguments. 1876137500Sjulian * @param useVarargs Box trailing arguments into an array for varargs. 187765543Scg */ 1878137500Sjulian Symbol findFun(Env<AttrContext> env, Name name, 1879137500Sjulian List<Type> argtypes, List<Type> typeargtypes, 1880137500Sjulian boolean allowBoxing, boolean useVarargs) { 1881137500Sjulian Symbol bestSoFar = methodNotFound; 1882137500Sjulian Env<AttrContext> env1 = env; 1883137500Sjulian boolean staticOnly = false; 1884137500Sjulian while (env1.outer != null) { 1885137500Sjulian if (isStatic(env1)) staticOnly = true; 1886137500Sjulian Assert.check(env1.info.preferredTreeForDiagnostics == null); 1887137500Sjulian env1.info.preferredTreeForDiagnostics = env.tree; 1888137500Sjulian try { 1889137500Sjulian Symbol sym = findMethod( 1890137500Sjulian env1, env1.enclClass.sym.type, name, argtypes, typeargtypes, 1891154067Sariff allowBoxing, useVarargs); 189265543Scg if (sym.exists()) { 1893137500Sjulian if (staticOnly && 189465543Scg sym.kind == MTH && 189565543Scg sym.owner.kind == TYP && 1896154067Sariff (sym.flags() & STATIC) == 0) return new StaticError(sym); 189770134Scg else return sym; 1898137500Sjulian } else { 1899137500Sjulian bestSoFar = bestOf(bestSoFar, sym); 1900137500Sjulian } 190165543Scg } finally { 1902137500Sjulian env1.info.preferredTreeForDiagnostics = null; 1903137500Sjulian } 1904137500Sjulian if ((env1.enclClass.sym.flags() & STATIC) != 0) staticOnly = true; 1905137500Sjulian env1 = env1.outer; 190665543Scg } 1907137500Sjulian 190865543Scg Symbol sym = findMethod(env, syms.predefClass.type, name, argtypes, 190965543Scg typeargtypes, allowBoxing, useVarargs); 1910174582Sariff if (sym.exists()) 1911137500Sjulian return sym; 191265543Scg 191365543Scg for (Symbol currentSym : env.toplevel.namedImportScope.getSymbolsByName(name)) { 191470945Sjhb Symbol origin = env.toplevel.namedImportScope.getOrigin(currentSym).owner; 1915154067Sariff if (currentSym.kind == MTH) { 1916137500Sjulian if (currentSym.owner.type != origin.type) 1917154067Sariff currentSym = currentSym.clone(origin); 1918174582Sariff if (!isAccessible(env, origin.type, currentSym)) 1919137500Sjulian currentSym = new AccessError(env, origin.type, currentSym); 192070134Scg bestSoFar = selectBest(env, origin.type, 1921137500Sjulian argtypes, typeargtypes, 1922137500Sjulian currentSym, bestSoFar, 1923137500Sjulian allowBoxing, useVarargs); 1924137500Sjulian } 1925137500Sjulian } 1926137500Sjulian if (bestSoFar.exists()) 192765543Scg return bestSoFar; 192865543Scg 192965543Scg for (Symbol currentSym : env.toplevel.starImportScope.getSymbolsByName(name)) { 193065543Scg Symbol origin = env.toplevel.starImportScope.getOrigin(currentSym).owner; 193165543Scg if (currentSym.kind == MTH) { 193265644Scg if (currentSym.owner.type != origin.type) 193365644Scg currentSym = currentSym.clone(origin); 193465543Scg if (!isAccessible(env, origin.type, currentSym)) 193565543Scg currentSym = new AccessError(env, origin.type, currentSym); 193665543Scg bestSoFar = selectBest(env, origin.type, 193765543Scg argtypes, typeargtypes, 193865543Scg currentSym, bestSoFar, 193965543Scg allowBoxing, useVarargs); 1940154627Snetchild } 1941154627Snetchild } 1942154627Snetchild return bestSoFar; 1943154627Snetchild } 1944154627Snetchild 1945154627Snetchild /** Load toplevel or member class with given fully qualified name and 1946154627Snetchild * verify that it is accessible. 1947154627Snetchild * @param env The current environment. 1948154627Snetchild * @param name The fully qualified name of the class to be loaded. 194965543Scg */ 1950154627Snetchild Symbol loadClass(Env<AttrContext> env, Name name) { 195165543Scg try { 1952137500Sjulian ClassSymbol c = finder.loadClass(name); 195365543Scg return isAccessible(env, c) ? c : new AccessError(c); 195465543Scg } catch (ClassFinder.BadClassFile err) { 195565543Scg throw err; 195665543Scg } catch (CompletionFailure ex) { 195765543Scg return typeNotFound; 195865543Scg } 195965543Scg } 1960137500Sjulian 196165543Scg 1962137500Sjulian /** 1963137500Sjulian * Find a type declared in a scope (not inherited). Return null 1964137500Sjulian * if none is found. 1965137500Sjulian * @param env The current environment. 1966137500Sjulian * @param site The original type from where the selection takes 1967137500Sjulian * place. 1968137500Sjulian * @param name The type's name. 1969137500Sjulian * @param c The class to search for the member type. This is 1970137500Sjulian * always a superclass or implemented interface of 1971137500Sjulian * site's class. 1972137500Sjulian */ 197365543Scg Symbol findImmediateMemberType(Env<AttrContext> env, 1974137500Sjulian Type site, 1975137500Sjulian Name name, 197665543Scg TypeSymbol c) { 1977137500Sjulian for (Symbol sym : c.members().getSymbolsByName(name)) { 197865543Scg if (sym.kind == TYP) { 1979137500Sjulian return isAccessible(env, site, sym) 1980137500Sjulian ? sym 1981154067Sariff : new AccessError(env, site, sym); 198265543Scg } 198365543Scg } 198465543Scg return typeNotFound; 198565543Scg } 1986137500Sjulian 1987137500Sjulian /** Find a member type inherited from a superclass or interface. 1988137500Sjulian * @param env The current environment. 1989137500Sjulian * @param site The original type from where the selection takes 199065543Scg * place. 199165543Scg * @param name The type's name. 199265543Scg * @param c The class to search for the member type. This is 199365543Scg * always a superclass or implemented interface of 199465543Scg * site's class. 199565543Scg */ 199665543Scg Symbol findInheritedMemberType(Env<AttrContext> env, 199765543Scg Type site, 199865543Scg Name name, 1999137500Sjulian TypeSymbol c) { 2000137500Sjulian Symbol bestSoFar = typeNotFound; 2001137500Sjulian Symbol sym; 2002137500Sjulian Type st = types.supertype(c.type); 200365543Scg if (st != null && st.hasTag(CLASS)) { 200465543Scg sym = findMemberType(env, site, name, st.tsym); 200565543Scg bestSoFar = bestOf(bestSoFar, sym); 200665543Scg } 200765543Scg for (List<Type> l = types.interfaces(c.type); 200865543Scg bestSoFar.kind != AMBIGUOUS && l.nonEmpty(); 200965543Scg l = l.tail) { 2010137500Sjulian sym = findMemberType(env, site, name, l.head.tsym); 201165543Scg if (!bestSoFar.kind.isResolutionError() && 201265543Scg !sym.kind.isResolutionError() && 201365543Scg sym.owner != bestSoFar.owner) 201465543Scg bestSoFar = new AmbiguityError(bestSoFar, sym); 201565543Scg else 201665543Scg bestSoFar = bestOf(bestSoFar, sym); 201765543Scg } 2018137500Sjulian return bestSoFar; 2019137500Sjulian } 2020137500Sjulian 2021137500Sjulian /** Find qualified member type. 2022137500Sjulian * @param env The current environment. 2023137500Sjulian * @param site The original type from where the selection takes 2024137500Sjulian * place. 2025137500Sjulian * @param name The type's name. 2026137500Sjulian * @param c The class to search for the member type. This is 202765543Scg * always a superclass or implemented interface of 2028137500Sjulian * site's class. 202965543Scg */ 203065543Scg Symbol findMemberType(Env<AttrContext> env, 203165543Scg Type site, 203265543Scg Name name, 203365543Scg TypeSymbol c) { 203465543Scg Symbol sym = findImmediateMemberType(env, site, name, c); 203565543Scg 203665543Scg if (sym != typeNotFound) 2037137500Sjulian return sym; 2038137500Sjulian 2039137500Sjulian return findInheritedMemberType(env, site, name, c); 204065543Scg 204165543Scg } 204265543Scg 204365543Scg /** Find a global type in given scope and load corresponding class. 204465543Scg * @param env The current environment. 204565543Scg * @param scope The scope in which to look for the type. 204665543Scg * @param name The type's name. 204765543Scg */ 204865543Scg Symbol findGlobalType(Env<AttrContext> env, Scope scope, Name name) { 204965543Scg Symbol bestSoFar = typeNotFound; 205065543Scg for (Symbol s : scope.getSymbolsByName(name)) { 205165543Scg Symbol sym = loadClass(env, s.flatName()); 205265543Scg if (bestSoFar.kind == TYP && sym.kind == TYP && 205365543Scg bestSoFar != sym) 205465543Scg return new AmbiguityError(bestSoFar, sym); 205565543Scg else 205665543Scg bestSoFar = bestOf(bestSoFar, sym); 205765543Scg } 205865543Scg return bestSoFar; 205982180Scg } 206065543Scg 206165543Scg Symbol findTypeVar(Env<AttrContext> env, Name name, boolean staticOnly) { 2062137500Sjulian for (Symbol sym : env.info.scope.getSymbolsByName(name)) { 2063137500Sjulian if (sym.kind == TYP) { 206465543Scg if (staticOnly && 2065132236Stanimura sym.type.hasTag(TYPEVAR) && 206665543Scg sym.owner.kind == TYP) 2067 return new StaticError(sym); 2068 return sym; 2069 } 2070 } 2071 return typeNotFound; 2072 } 2073 2074 /** Find an unqualified type symbol. 2075 * @param env The current environment. 2076 * @param name The type's name. 2077 */ 2078 Symbol findType(Env<AttrContext> env, Name name) { 2079 if (name == names.empty) 2080 return typeNotFound; // do not allow inadvertent "lookup" of anonymous types 2081 Symbol bestSoFar = typeNotFound; 2082 Symbol sym; 2083 boolean staticOnly = false; 2084 for (Env<AttrContext> env1 = env; env1.outer != null; env1 = env1.outer) { 2085 if (isStatic(env1)) staticOnly = true; 2086 // First, look for a type variable and the first member type 2087 final Symbol tyvar = findTypeVar(env1, name, staticOnly); 2088 sym = findImmediateMemberType(env1, env1.enclClass.sym.type, 2089 name, env1.enclClass.sym); 2090 2091 // Return the type variable if we have it, and have no 2092 // immediate member, OR the type variable is for a method. 2093 if (tyvar != typeNotFound) { 2094 if (env.baseClause || sym == typeNotFound || 2095 (tyvar.kind == TYP && tyvar.exists() && 2096 tyvar.owner.kind == MTH)) { 2097 return tyvar; 2098 } 2099 } 2100 2101 // If the environment is a class def, finish up, 2102 // otherwise, do the entire findMemberType 2103 if (sym == typeNotFound) 2104 sym = findInheritedMemberType(env1, env1.enclClass.sym.type, 2105 name, env1.enclClass.sym); 2106 2107 if (staticOnly && sym.kind == TYP && 2108 sym.type.hasTag(CLASS) && 2109 sym.type.getEnclosingType().hasTag(CLASS) && 2110 env1.enclClass.sym.type.isParameterized() && 2111 sym.type.getEnclosingType().isParameterized()) 2112 return new StaticError(sym); 2113 else if (sym.exists()) return sym; 2114 else bestSoFar = bestOf(bestSoFar, sym); 2115 2116 JCClassDecl encl = env1.baseClause ? (JCClassDecl)env1.tree : env1.enclClass; 2117 if ((encl.sym.flags() & STATIC) != 0) 2118 staticOnly = true; 2119 } 2120 2121 if (!env.tree.hasTag(IMPORT)) { 2122 sym = findGlobalType(env, env.toplevel.namedImportScope, name); 2123 if (sym.exists()) return sym; 2124 else bestSoFar = bestOf(bestSoFar, sym); 2125 2126 sym = findGlobalType(env, env.toplevel.packge.members(), name); 2127 if (sym.exists()) return sym; 2128 else bestSoFar = bestOf(bestSoFar, sym); 2129 2130 sym = findGlobalType(env, env.toplevel.starImportScope, name); 2131 if (sym.exists()) return sym; 2132 else bestSoFar = bestOf(bestSoFar, sym); 2133 } 2134 2135 return bestSoFar; 2136 } 2137 2138 /** Find an unqualified identifier which matches a specified kind set. 2139 * @param env The current environment. 2140 * @param name The identifier's name. 2141 * @param kind Indicates the possible symbol kinds 2142 * (a subset of VAL, TYP, PCK). 2143 */ 2144 Symbol findIdent(Env<AttrContext> env, Name name, KindSelector kind) { 2145 Symbol bestSoFar = typeNotFound; 2146 Symbol sym; 2147 2148 if (kind.contains(KindSelector.VAL)) { 2149 sym = findVar(env, name); 2150 if (sym.exists()) return sym; 2151 else bestSoFar = bestOf(bestSoFar, sym); 2152 } 2153 2154 if (kind.contains(KindSelector.TYP)) { 2155 sym = findType(env, name); 2156 2157 if (sym.exists()) return sym; 2158 else bestSoFar = bestOf(bestSoFar, sym); 2159 } 2160 2161 if (kind.contains(KindSelector.PCK)) 2162 return syms.enterPackage(name); 2163 else return bestSoFar; 2164 } 2165 2166 /** Find an identifier in a package which matches a specified kind set. 2167 * @param env The current environment. 2168 * @param name The identifier's name. 2169 * @param kind Indicates the possible symbol kinds 2170 * (a nonempty subset of TYP, PCK). 2171 */ 2172 Symbol findIdentInPackage(Env<AttrContext> env, TypeSymbol pck, 2173 Name name, KindSelector kind) { 2174 Name fullname = TypeSymbol.formFullName(name, pck); 2175 Symbol bestSoFar = typeNotFound; 2176 PackageSymbol pack = null; 2177 if (kind.contains(KindSelector.PCK)) { 2178 pack = syms.enterPackage(fullname); 2179 if (pack.exists()) return pack; 2180 } 2181 if (kind.contains(KindSelector.TYP)) { 2182 Symbol sym = loadClass(env, fullname); 2183 if (sym.exists()) { 2184 // don't allow programs to use flatnames 2185 if (name == sym.name) return sym; 2186 } 2187 else bestSoFar = bestOf(bestSoFar, sym); 2188 } 2189 return (pack != null) ? pack : bestSoFar; 2190 } 2191 2192 /** Find an identifier among the members of a given type `site'. 2193 * @param env The current environment. 2194 * @param site The type containing the symbol to be found. 2195 * @param name The identifier's name. 2196 * @param kind Indicates the possible symbol kinds 2197 * (a subset of VAL, TYP). 2198 */ 2199 Symbol findIdentInType(Env<AttrContext> env, Type site, 2200 Name name, KindSelector kind) { 2201 Symbol bestSoFar = typeNotFound; 2202 Symbol sym; 2203 if (kind.contains(KindSelector.VAL)) { 2204 sym = findField(env, site, name, site.tsym); 2205 if (sym.exists()) return sym; 2206 else bestSoFar = bestOf(bestSoFar, sym); 2207 } 2208 2209 if (kind.contains(KindSelector.TYP)) { 2210 sym = findMemberType(env, site, name, site.tsym); 2211 if (sym.exists()) return sym; 2212 else bestSoFar = bestOf(bestSoFar, sym); 2213 } 2214 return bestSoFar; 2215 } 2216 2217/* *************************************************************************** 2218 * Access checking 2219 * The following methods convert ResolveErrors to ErrorSymbols, issuing 2220 * an error message in the process 2221 ****************************************************************************/ 2222 2223 /** If `sym' is a bad symbol: report error and return errSymbol 2224 * else pass through unchanged, 2225 * additional arguments duplicate what has been used in trying to find the 2226 * symbol {@literal (--> flyweight pattern)}. This improves performance since we 2227 * expect misses to happen frequently. 2228 * 2229 * @param sym The symbol that was found, or a ResolveError. 2230 * @param pos The position to use for error reporting. 2231 * @param location The symbol the served as a context for this lookup 2232 * @param site The original type from where the selection took place. 2233 * @param name The symbol's name. 2234 * @param qualified Did we get here through a qualified expression resolution? 2235 * @param argtypes The invocation's value arguments, 2236 * if we looked for a method. 2237 * @param typeargtypes The invocation's type arguments, 2238 * if we looked for a method. 2239 * @param logResolveHelper helper class used to log resolve errors 2240 */ 2241 Symbol accessInternal(Symbol sym, 2242 DiagnosticPosition pos, 2243 Symbol location, 2244 Type site, 2245 Name name, 2246 boolean qualified, 2247 List<Type> argtypes, 2248 List<Type> typeargtypes, 2249 LogResolveHelper logResolveHelper) { 2250 if (sym.kind.isResolutionError()) { 2251 ResolveError errSym = (ResolveError)sym.baseSymbol(); 2252 sym = errSym.access(name, qualified ? site.tsym : syms.noSymbol); 2253 argtypes = logResolveHelper.getArgumentTypes(errSym, sym, name, argtypes); 2254 if (logResolveHelper.resolveDiagnosticNeeded(site, argtypes, typeargtypes)) { 2255 logResolveError(errSym, pos, location, site, name, argtypes, typeargtypes); 2256 } 2257 } 2258 return sym; 2259 } 2260 2261 /** 2262 * Variant of the generalized access routine, to be used for generating method 2263 * resolution diagnostics 2264 */ 2265 Symbol accessMethod(Symbol sym, 2266 DiagnosticPosition pos, 2267 Symbol location, 2268 Type site, 2269 Name name, 2270 boolean qualified, 2271 List<Type> argtypes, 2272 List<Type> typeargtypes) { 2273 return accessInternal(sym, pos, location, site, name, qualified, argtypes, typeargtypes, methodLogResolveHelper); 2274 } 2275 2276 /** Same as original accessMethod(), but without location. 2277 */ 2278 Symbol accessMethod(Symbol sym, 2279 DiagnosticPosition pos, 2280 Type site, 2281 Name name, 2282 boolean qualified, 2283 List<Type> argtypes, 2284 List<Type> typeargtypes) { 2285 return accessMethod(sym, pos, site.tsym, site, name, qualified, argtypes, typeargtypes); 2286 } 2287 2288 /** 2289 * Variant of the generalized access routine, to be used for generating variable, 2290 * type resolution diagnostics 2291 */ 2292 Symbol accessBase(Symbol sym, 2293 DiagnosticPosition pos, 2294 Symbol location, 2295 Type site, 2296 Name name, 2297 boolean qualified) { 2298 return accessInternal(sym, pos, location, site, name, qualified, List.<Type>nil(), null, basicLogResolveHelper); 2299 } 2300 2301 /** Same as original accessBase(), but without location. 2302 */ 2303 Symbol accessBase(Symbol sym, 2304 DiagnosticPosition pos, 2305 Type site, 2306 Name name, 2307 boolean qualified) { 2308 return accessBase(sym, pos, site.tsym, site, name, qualified); 2309 } 2310 2311 interface LogResolveHelper { 2312 boolean resolveDiagnosticNeeded(Type site, List<Type> argtypes, List<Type> typeargtypes); 2313 List<Type> getArgumentTypes(ResolveError errSym, Symbol accessedSym, Name name, List<Type> argtypes); 2314 } 2315 2316 LogResolveHelper basicLogResolveHelper = new LogResolveHelper() { 2317 public boolean resolveDiagnosticNeeded(Type site, List<Type> argtypes, List<Type> typeargtypes) { 2318 return !site.isErroneous(); 2319 } 2320 public List<Type> getArgumentTypes(ResolveError errSym, Symbol accessedSym, Name name, List<Type> argtypes) { 2321 return argtypes; 2322 } 2323 }; 2324 2325 LogResolveHelper methodLogResolveHelper = new LogResolveHelper() { 2326 public boolean resolveDiagnosticNeeded(Type site, List<Type> argtypes, List<Type> typeargtypes) { 2327 return !site.isErroneous() && 2328 !Type.isErroneous(argtypes) && 2329 (typeargtypes == null || !Type.isErroneous(typeargtypes)); 2330 } 2331 public List<Type> getArgumentTypes(ResolveError errSym, Symbol accessedSym, Name name, List<Type> argtypes) { 2332 return argtypes.map(new ResolveDeferredRecoveryMap(AttrMode.SPECULATIVE, accessedSym, currentResolutionContext.step)); 2333 } 2334 }; 2335 2336 class ResolveDeferredRecoveryMap extends DeferredAttr.RecoveryDeferredTypeMap { 2337 2338 public ResolveDeferredRecoveryMap(AttrMode mode, Symbol msym, MethodResolutionPhase step) { 2339 deferredAttr.super(mode, msym, step); 2340 } 2341 2342 @Override 2343 protected Type typeOf(DeferredType dt) { 2344 Type res = super.typeOf(dt); 2345 if (!res.isErroneous()) { 2346 switch (TreeInfo.skipParens(dt.tree).getTag()) { 2347 case LAMBDA: 2348 case REFERENCE: 2349 return dt; 2350 case CONDEXPR: 2351 return res == Type.recoveryType ? 2352 dt : res; 2353 } 2354 } 2355 return res; 2356 } 2357 } 2358 2359 /** Check that sym is not an abstract method. 2360 */ 2361 void checkNonAbstract(DiagnosticPosition pos, Symbol sym) { 2362 if ((sym.flags() & ABSTRACT) != 0 && (sym.flags() & DEFAULT) == 0) 2363 log.error(pos, "abstract.cant.be.accessed.directly", 2364 kindName(sym), sym, sym.location()); 2365 } 2366 2367/* *************************************************************************** 2368 * Name resolution 2369 * Naming conventions are as for symbol lookup 2370 * Unlike the find... methods these methods will report access errors 2371 ****************************************************************************/ 2372 2373 /** Resolve an unqualified (non-method) identifier. 2374 * @param pos The position to use for error reporting. 2375 * @param env The environment current at the identifier use. 2376 * @param name The identifier's name. 2377 * @param kind The set of admissible symbol kinds for the identifier. 2378 */ 2379 Symbol resolveIdent(DiagnosticPosition pos, Env<AttrContext> env, 2380 Name name, KindSelector kind) { 2381 return accessBase( 2382 findIdent(env, name, kind), 2383 pos, env.enclClass.sym.type, name, false); 2384 } 2385 2386 /** Resolve an unqualified method identifier. 2387 * @param pos The position to use for error reporting. 2388 * @param env The environment current at the method invocation. 2389 * @param name The identifier's name. 2390 * @param argtypes The types of the invocation's value arguments. 2391 * @param typeargtypes The types of the invocation's type arguments. 2392 */ 2393 Symbol resolveMethod(DiagnosticPosition pos, 2394 Env<AttrContext> env, 2395 Name name, 2396 List<Type> argtypes, 2397 List<Type> typeargtypes) { 2398 return lookupMethod(env, pos, env.enclClass.sym, resolveMethodCheck, 2399 new BasicLookupHelper(name, env.enclClass.sym.type, argtypes, typeargtypes) { 2400 @Override 2401 Symbol doLookup(Env<AttrContext> env, MethodResolutionPhase phase) { 2402 return findFun(env, name, argtypes, typeargtypes, 2403 phase.isBoxingRequired(), 2404 phase.isVarargsRequired()); 2405 }}); 2406 } 2407 2408 /** Resolve a qualified method identifier 2409 * @param pos The position to use for error reporting. 2410 * @param env The environment current at the method invocation. 2411 * @param site The type of the qualifying expression, in which 2412 * identifier is searched. 2413 * @param name The identifier's name. 2414 * @param argtypes The types of the invocation's value arguments. 2415 * @param typeargtypes The types of the invocation's type arguments. 2416 */ 2417 Symbol resolveQualifiedMethod(DiagnosticPosition pos, Env<AttrContext> env, 2418 Type site, Name name, List<Type> argtypes, 2419 List<Type> typeargtypes) { 2420 return resolveQualifiedMethod(pos, env, site.tsym, site, name, argtypes, typeargtypes); 2421 } 2422 Symbol resolveQualifiedMethod(DiagnosticPosition pos, Env<AttrContext> env, 2423 Symbol location, Type site, Name name, List<Type> argtypes, 2424 List<Type> typeargtypes) { 2425 return resolveQualifiedMethod(new MethodResolutionContext(), pos, env, location, site, name, argtypes, typeargtypes); 2426 } 2427 private Symbol resolveQualifiedMethod(MethodResolutionContext resolveContext, 2428 DiagnosticPosition pos, Env<AttrContext> env, 2429 Symbol location, Type site, Name name, List<Type> argtypes, 2430 List<Type> typeargtypes) { 2431 return lookupMethod(env, pos, location, resolveContext, new BasicLookupHelper(name, site, argtypes, typeargtypes) { 2432 @Override 2433 Symbol doLookup(Env<AttrContext> env, MethodResolutionPhase phase) { 2434 return findMethod(env, site, name, argtypes, typeargtypes, 2435 phase.isBoxingRequired(), 2436 phase.isVarargsRequired()); 2437 } 2438 @Override 2439 Symbol access(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, Symbol sym) { 2440 if (sym.kind.isResolutionError()) { 2441 sym = super.access(env, pos, location, sym); 2442 } else if (allowMethodHandles) { 2443 MethodSymbol msym = (MethodSymbol)sym; 2444 if ((msym.flags() & SIGNATURE_POLYMORPHIC) != 0) { 2445 return findPolymorphicSignatureInstance(env, sym, argtypes); 2446 } 2447 } 2448 return sym; 2449 } 2450 }); 2451 } 2452 2453 /** Find or create an implicit method of exactly the given type (after erasure). 2454 * Searches in a side table, not the main scope of the site. 2455 * This emulates the lookup process required by JSR 292 in JVM. 2456 * @param env Attribution environment 2457 * @param spMethod signature polymorphic method - i.e. MH.invokeExact 2458 * @param argtypes The required argument types 2459 */ 2460 Symbol findPolymorphicSignatureInstance(Env<AttrContext> env, 2461 final Symbol spMethod, 2462 List<Type> argtypes) { 2463 Type mtype = infer.instantiatePolymorphicSignatureInstance(env, 2464 (MethodSymbol)spMethod, currentResolutionContext, argtypes); 2465 for (Symbol sym : polymorphicSignatureScope.getSymbolsByName(spMethod.name)) { 2466 if (types.isSameType(mtype, sym.type)) { 2467 return sym; 2468 } 2469 } 2470 2471 // create the desired method 2472 long flags = ABSTRACT | HYPOTHETICAL | spMethod.flags() & Flags.AccessFlags; 2473 Symbol msym = new MethodSymbol(flags, spMethod.name, mtype, spMethod.owner) { 2474 @Override 2475 public Symbol baseSymbol() { 2476 return spMethod; 2477 } 2478 }; 2479 if (!mtype.isErroneous()) { // Cache only if kosher. 2480 polymorphicSignatureScope.enter(msym); 2481 } 2482 return msym; 2483 } 2484 2485 /** Resolve a qualified method identifier, throw a fatal error if not 2486 * found. 2487 * @param pos The position to use for error reporting. 2488 * @param env The environment current at the method invocation. 2489 * @param site The type of the qualifying expression, in which 2490 * identifier is searched. 2491 * @param name The identifier's name. 2492 * @param argtypes The types of the invocation's value arguments. 2493 * @param typeargtypes The types of the invocation's type arguments. 2494 */ 2495 public MethodSymbol resolveInternalMethod(DiagnosticPosition pos, Env<AttrContext> env, 2496 Type site, Name name, 2497 List<Type> argtypes, 2498 List<Type> typeargtypes) { 2499 MethodResolutionContext resolveContext = new MethodResolutionContext(); 2500 resolveContext.internalResolution = true; 2501 Symbol sym = resolveQualifiedMethod(resolveContext, pos, env, site.tsym, 2502 site, name, argtypes, typeargtypes); 2503 if (sym.kind == MTH) return (MethodSymbol)sym; 2504 else throw new FatalError( 2505 diags.fragment("fatal.err.cant.locate.meth", 2506 name)); 2507 } 2508 2509 /** Resolve constructor. 2510 * @param pos The position to use for error reporting. 2511 * @param env The environment current at the constructor invocation. 2512 * @param site The type of class for which a constructor is searched. 2513 * @param argtypes The types of the constructor invocation's value 2514 * arguments. 2515 * @param typeargtypes The types of the constructor invocation's type 2516 * arguments. 2517 */ 2518 Symbol resolveConstructor(DiagnosticPosition pos, 2519 Env<AttrContext> env, 2520 Type site, 2521 List<Type> argtypes, 2522 List<Type> typeargtypes) { 2523 return resolveConstructor(new MethodResolutionContext(), pos, env, site, argtypes, typeargtypes); 2524 } 2525 2526 private Symbol resolveConstructor(MethodResolutionContext resolveContext, 2527 final DiagnosticPosition pos, 2528 Env<AttrContext> env, 2529 Type site, 2530 List<Type> argtypes, 2531 List<Type> typeargtypes) { 2532 return lookupMethod(env, pos, site.tsym, resolveContext, new BasicLookupHelper(names.init, site, argtypes, typeargtypes) { 2533 @Override 2534 Symbol doLookup(Env<AttrContext> env, MethodResolutionPhase phase) { 2535 return findConstructor(pos, env, site, argtypes, typeargtypes, 2536 phase.isBoxingRequired(), 2537 phase.isVarargsRequired()); 2538 } 2539 }); 2540 } 2541 2542 /** Resolve a constructor, throw a fatal error if not found. 2543 * @param pos The position to use for error reporting. 2544 * @param env The environment current at the method invocation. 2545 * @param site The type to be constructed. 2546 * @param argtypes The types of the invocation's value arguments. 2547 * @param typeargtypes The types of the invocation's type arguments. 2548 */ 2549 public MethodSymbol resolveInternalConstructor(DiagnosticPosition pos, Env<AttrContext> env, 2550 Type site, 2551 List<Type> argtypes, 2552 List<Type> typeargtypes) { 2553 MethodResolutionContext resolveContext = new MethodResolutionContext(); 2554 resolveContext.internalResolution = true; 2555 Symbol sym = resolveConstructor(resolveContext, pos, env, site, argtypes, typeargtypes); 2556 if (sym.kind == MTH) return (MethodSymbol)sym; 2557 else throw new FatalError( 2558 diags.fragment("fatal.err.cant.locate.ctor", site)); 2559 } 2560 2561 Symbol findConstructor(DiagnosticPosition pos, Env<AttrContext> env, 2562 Type site, List<Type> argtypes, 2563 List<Type> typeargtypes, 2564 boolean allowBoxing, 2565 boolean useVarargs) { 2566 Symbol sym = findMethod(env, site, 2567 names.init, argtypes, 2568 typeargtypes, allowBoxing, 2569 useVarargs); 2570 chk.checkDeprecated(pos, env.info.scope.owner, sym); 2571 return sym; 2572 } 2573 2574 /** Resolve constructor using diamond inference. 2575 * @param pos The position to use for error reporting. 2576 * @param env The environment current at the constructor invocation. 2577 * @param site The type of class for which a constructor is searched. 2578 * The scope of this class has been touched in attribution. 2579 * @param argtypes The types of the constructor invocation's value 2580 * arguments. 2581 * @param typeargtypes The types of the constructor invocation's type 2582 * arguments. 2583 */ 2584 Symbol resolveDiamond(DiagnosticPosition pos, 2585 Env<AttrContext> env, 2586 Type site, 2587 List<Type> argtypes, 2588 List<Type> typeargtypes) { 2589 return lookupMethod(env, pos, site.tsym, resolveMethodCheck, 2590 new BasicLookupHelper(names.init, site, argtypes, typeargtypes) { 2591 @Override 2592 Symbol doLookup(Env<AttrContext> env, MethodResolutionPhase phase) { 2593 return findDiamond(env, site, argtypes, typeargtypes, 2594 phase.isBoxingRequired(), 2595 phase.isVarargsRequired()); 2596 } 2597 @Override 2598 Symbol access(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, Symbol sym) { 2599 if (sym.kind.isResolutionError()) { 2600 if (sym.kind != WRONG_MTH && 2601 sym.kind != WRONG_MTHS) { 2602 sym = super.access(env, pos, location, sym); 2603 } else { 2604 final JCDiagnostic details = sym.kind == WRONG_MTH ? 2605 ((InapplicableSymbolError)sym.baseSymbol()).errCandidate().snd : 2606 null; 2607 sym = new DiamondError(sym, currentResolutionContext); 2608 sym = accessMethod(sym, pos, site, names.init, true, argtypes, typeargtypes); 2609 env.info.pendingResolutionPhase = currentResolutionContext.step; 2610 } 2611 } 2612 return sym; 2613 }}); 2614 } 2615 2616 /** This method scans all the constructor symbol in a given class scope - 2617 * assuming that the original scope contains a constructor of the kind: 2618 * {@code Foo(X x, Y y)}, where X,Y are class type-variables declared in Foo, 2619 * a method check is executed against the modified constructor type: 2620 * {@code <X,Y>Foo<X,Y>(X x, Y y)}. This is crucial in order to enable diamond 2621 * inference. The inferred return type of the synthetic constructor IS 2622 * the inferred type for the diamond operator. 2623 */ 2624 private Symbol findDiamond(Env<AttrContext> env, 2625 Type site, 2626 List<Type> argtypes, 2627 List<Type> typeargtypes, 2628 boolean allowBoxing, 2629 boolean useVarargs) { 2630 Symbol bestSoFar = methodNotFound; 2631 TypeSymbol tsym = site.tsym.isInterface() ? syms.objectType.tsym : site.tsym; 2632 for (final Symbol sym : tsym.members().getSymbolsByName(names.init)) { 2633 //- System.out.println(" e " + e.sym); 2634 if (sym.kind == MTH && 2635 (sym.flags_field & SYNTHETIC) == 0) { 2636 List<Type> oldParams = sym.type.hasTag(FORALL) ? 2637 ((ForAll)sym.type).tvars : 2638 List.<Type>nil(); 2639 Type constrType = new ForAll(site.tsym.type.getTypeArguments().appendList(oldParams), 2640 types.createMethodTypeWithReturn(sym.type.asMethodType(), site)); 2641 MethodSymbol newConstr = new MethodSymbol(sym.flags(), names.init, constrType, site.tsym) { 2642 @Override 2643 public Symbol baseSymbol() { 2644 return sym; 2645 } 2646 }; 2647 bestSoFar = selectBest(env, site, argtypes, typeargtypes, 2648 newConstr, 2649 bestSoFar, 2650 allowBoxing, 2651 useVarargs); 2652 } 2653 } 2654 return bestSoFar; 2655 } 2656 2657 Symbol getMemberReference(DiagnosticPosition pos, 2658 Env<AttrContext> env, 2659 JCMemberReference referenceTree, 2660 Type site, 2661 Name name) { 2662 2663 site = types.capture(site); 2664 2665 ReferenceLookupHelper lookupHelper = makeReferenceLookupHelper( 2666 referenceTree, site, name, List.<Type>nil(), null, VARARITY); 2667 2668 Env<AttrContext> newEnv = env.dup(env.tree, env.info.dup()); 2669 Symbol sym = lookupMethod(newEnv, env.tree.pos(), site.tsym, 2670 nilMethodCheck, lookupHelper); 2671 2672 env.info.pendingResolutionPhase = newEnv.info.pendingResolutionPhase; 2673 2674 return sym; 2675 } 2676 2677 ReferenceLookupHelper makeReferenceLookupHelper(JCMemberReference referenceTree, 2678 Type site, 2679 Name name, 2680 List<Type> argtypes, 2681 List<Type> typeargtypes, 2682 MethodResolutionPhase maxPhase) { 2683 if (!name.equals(names.init)) { 2684 //method reference 2685 return new MethodReferenceLookupHelper(referenceTree, name, site, argtypes, typeargtypes, maxPhase); 2686 } else if (site.hasTag(ARRAY)) { 2687 //array constructor reference 2688 return new ArrayConstructorReferenceLookupHelper(referenceTree, site, argtypes, typeargtypes, maxPhase); 2689 } else { 2690 //class constructor reference 2691 return new ConstructorReferenceLookupHelper(referenceTree, site, argtypes, typeargtypes, maxPhase); 2692 } 2693 } 2694 2695 /** 2696 * Resolution of member references is typically done as a single 2697 * overload resolution step, where the argument types A are inferred from 2698 * the target functional descriptor. 2699 * 2700 * If the member reference is a method reference with a type qualifier, 2701 * a two-step lookup process is performed. The first step uses the 2702 * expected argument list A, while the second step discards the first 2703 * type from A (which is treated as a receiver type). 2704 * 2705 * There are two cases in which inference is performed: (i) if the member 2706 * reference is a constructor reference and the qualifier type is raw - in 2707 * which case diamond inference is used to infer a parameterization for the 2708 * type qualifier; (ii) if the member reference is an unbound reference 2709 * where the type qualifier is raw - in that case, during the unbound lookup 2710 * the receiver argument type is used to infer an instantiation for the raw 2711 * qualifier type. 2712 * 2713 * When a multi-step resolution process is exploited, the process of picking 2714 * the resulting symbol is delegated to an helper class {@link com.sun.tools.javac.comp.Resolve.ReferenceChooser}. 2715 * 2716 * This routine returns a pair (T,S), where S is the member reference symbol, 2717 * and T is the type of the class in which S is defined. This is necessary as 2718 * the type T might be dynamically inferred (i.e. if constructor reference 2719 * has a raw qualifier). 2720 */ 2721 Pair<Symbol, ReferenceLookupHelper> resolveMemberReference(Env<AttrContext> env, 2722 JCMemberReference referenceTree, 2723 Type site, 2724 Name name, 2725 List<Type> argtypes, 2726 List<Type> typeargtypes, 2727 MethodCheck methodCheck, 2728 InferenceContext inferenceContext, 2729 ReferenceChooser referenceChooser) { 2730 2731 //step 1 - bound lookup 2732 ReferenceLookupHelper boundLookupHelper = makeReferenceLookupHelper( 2733 referenceTree, site, name, argtypes, typeargtypes, VARARITY); 2734 Env<AttrContext> boundEnv = env.dup(env.tree, env.info.dup()); 2735 MethodResolutionContext boundSearchResolveContext = new MethodResolutionContext(); 2736 boundSearchResolveContext.methodCheck = methodCheck; 2737 Symbol boundSym = lookupMethod(boundEnv, env.tree.pos(), 2738 site.tsym, boundSearchResolveContext, boundLookupHelper); 2739 ReferenceLookupResult boundRes = new ReferenceLookupResult(boundSym, boundSearchResolveContext); 2740 2741 //step 2 - unbound lookup 2742 Symbol unboundSym = methodNotFound; 2743 Env<AttrContext> unboundEnv = env.dup(env.tree, env.info.dup()); 2744 ReferenceLookupHelper unboundLookupHelper = boundLookupHelper.unboundLookup(inferenceContext); 2745 ReferenceLookupResult unboundRes = referenceNotFound; 2746 if (unboundLookupHelper != null) { 2747 MethodResolutionContext unboundSearchResolveContext = 2748 new MethodResolutionContext(); 2749 unboundSearchResolveContext.methodCheck = methodCheck; 2750 unboundSym = lookupMethod(unboundEnv, env.tree.pos(), 2751 site.tsym, unboundSearchResolveContext, unboundLookupHelper); 2752 unboundRes = new ReferenceLookupResult(unboundSym, unboundSearchResolveContext); 2753 } 2754 2755 //merge results 2756 Pair<Symbol, ReferenceLookupHelper> res; 2757 Symbol bestSym = referenceChooser.result(boundRes, unboundRes); 2758 res = new Pair<>(bestSym, 2759 bestSym == unboundSym ? unboundLookupHelper : boundLookupHelper); 2760 env.info.pendingResolutionPhase = bestSym == unboundSym ? 2761 unboundEnv.info.pendingResolutionPhase : 2762 boundEnv.info.pendingResolutionPhase; 2763 2764 return res; 2765 } 2766 2767 /** 2768 * This class is used to represent a method reference lookup result. It keeps track of two 2769 * things: (i) the symbol found during a method reference lookup and (ii) the static kind 2770 * of the lookup (see {@link com.sun.tools.javac.comp.Resolve.ReferenceLookupResult.StaticKind}). 2771 */ 2772 static class ReferenceLookupResult { 2773 2774 /** 2775 * Static kind associated with a method reference lookup. Erroneous lookups end up with 2776 * the UNDEFINED kind; successful lookups will end up with either STATIC, NON_STATIC, 2777 * depending on whether all applicable candidates are static or non-static methods, 2778 * respectively. If a successful lookup has both static and non-static applicable methods, 2779 * its kind is set to BOTH. 2780 */ 2781 enum StaticKind { 2782 STATIC, 2783 NON_STATIC, 2784 BOTH, 2785 UNDEFINED; 2786 2787 /** 2788 * Retrieve the static kind associated with a given (method) symbol. 2789 */ 2790 static StaticKind from(Symbol s) { 2791 return s.isStatic() ? 2792 STATIC : NON_STATIC; 2793 } 2794 2795 /** 2796 * Merge two static kinds together. 2797 */ 2798 static StaticKind reduce(StaticKind sk1, StaticKind sk2) { 2799 if (sk1 == UNDEFINED) { 2800 return sk2; 2801 } else if (sk2 == UNDEFINED) { 2802 return sk1; 2803 } else { 2804 return sk1 == sk2 ? sk1 : BOTH; 2805 } 2806 } 2807 } 2808 2809 /** The static kind. */ 2810 StaticKind staticKind; 2811 2812 /** The lookup result. */ 2813 Symbol sym; 2814 2815 ReferenceLookupResult(Symbol sym, MethodResolutionContext resolutionContext) { 2816 this.staticKind = staticKind(sym, resolutionContext); 2817 this.sym = sym; 2818 } 2819 2820 private StaticKind staticKind(Symbol sym, MethodResolutionContext resolutionContext) { 2821 switch (sym.kind) { 2822 case MTH: 2823 case AMBIGUOUS: 2824 return resolutionContext.candidates.stream() 2825 .filter(c -> c.isApplicable() && c.step == resolutionContext.step) 2826 .map(c -> StaticKind.from(c.sym)) 2827 .reduce(StaticKind::reduce) 2828 .orElse(StaticKind.UNDEFINED); 2829 default: 2830 return StaticKind.UNDEFINED; 2831 } 2832 } 2833 2834 /** 2835 * Does this result corresponds to a successful lookup (i.e. one where a method has been found?) 2836 */ 2837 boolean isSuccess() { 2838 return staticKind != StaticKind.UNDEFINED; 2839 } 2840 2841 /** 2842 * Does this result have given static kind? 2843 */ 2844 boolean hasKind(StaticKind sk) { 2845 return this.staticKind == sk; 2846 } 2847 2848 /** 2849 * Error recovery helper: can this lookup result be ignored (for the purpose of returning 2850 * some 'better' result) ? 2851 */ 2852 boolean canIgnore() { 2853 switch (sym.kind) { 2854 case ABSENT_MTH: 2855 return true; 2856 case WRONG_MTH: 2857 InapplicableSymbolError errSym = 2858 (InapplicableSymbolError)sym.baseSymbol(); 2859 return new Template(MethodCheckDiag.ARITY_MISMATCH.regex()) 2860 .matches(errSym.errCandidate().snd); 2861 case WRONG_MTHS: 2862 InapplicableSymbolsError errSyms = 2863 (InapplicableSymbolsError)sym.baseSymbol(); 2864 return errSyms.filterCandidates(errSyms.mapCandidates()).isEmpty(); 2865 default: 2866 return false; 2867 } 2868 } 2869 } 2870 2871 /** 2872 * This abstract class embodies the logic that converts one (bound lookup) or two (unbound lookup) 2873 * {@code ReferenceLookupResult} objects into a (@code Symbol), which is then regarded as the 2874 * result of method reference resolution. 2875 */ 2876 abstract class ReferenceChooser { 2877 /** 2878 * Generate a result from a pair of lookup result objects. This method delegates to the 2879 * appropriate result generation routine. 2880 */ 2881 Symbol result(ReferenceLookupResult boundRes, ReferenceLookupResult unboundRes) { 2882 return unboundRes != referenceNotFound ? 2883 unboundResult(boundRes, unboundRes) : 2884 boundResult(boundRes); 2885 } 2886 2887 /** 2888 * Generate a symbol from a given bound lookup result. 2889 */ 2890 abstract Symbol boundResult(ReferenceLookupResult boundRes); 2891 2892 /** 2893 * Generate a symbol from a pair of bound/unbound lookup results. 2894 */ 2895 abstract Symbol unboundResult(ReferenceLookupResult boundRes, ReferenceLookupResult unboundRes); 2896 } 2897 2898 /** 2899 * This chooser implements the selection strategy used during a full lookup; this logic 2900 * is described in JLS SE 8 (15.3.2). 2901 */ 2902 ReferenceChooser basicReferenceChooser = new ReferenceChooser() { 2903 2904 @Override 2905 Symbol boundResult(ReferenceLookupResult boundRes) { 2906 return !boundRes.isSuccess() || boundRes.hasKind(StaticKind.NON_STATIC) ? 2907 boundRes.sym : //the search produces a non-static method 2908 new BadMethodReferenceError(boundRes.sym, false); 2909 } 2910 2911 @Override 2912 Symbol unboundResult(ReferenceLookupResult boundRes, ReferenceLookupResult unboundRes) { 2913 if (boundRes.hasKind(StaticKind.STATIC) && 2914 (!unboundRes.isSuccess() || unboundRes.hasKind(StaticKind.STATIC))) { 2915 //the first search produces a static method and no non-static method is applicable 2916 //during the second search 2917 return boundRes.sym; 2918 } else if (unboundRes.hasKind(StaticKind.NON_STATIC) && 2919 (!boundRes.isSuccess() || boundRes.hasKind(StaticKind.NON_STATIC))) { 2920 //the second search produces a non-static method and no static method is applicable 2921 //during the first search 2922 return unboundRes.sym; 2923 } else if (boundRes.isSuccess() && unboundRes.isSuccess()) { 2924 //both searches produce some result; ambiguity (error recovery) 2925 return ambiguityError(boundRes.sym, unboundRes.sym); 2926 } else if (boundRes.isSuccess() || unboundRes.isSuccess()) { 2927 //Both searches failed to produce a result with correct staticness (i.e. first search 2928 //produces an non-static method). Alternatively, a given search produced a result 2929 //with the right staticness, but the other search has applicable methods with wrong 2930 //staticness (error recovery) 2931 return new BadMethodReferenceError(boundRes.isSuccess() ? boundRes.sym : unboundRes.sym, true); 2932 } else { 2933 //both searches fail to produce a result - pick 'better' error using heuristics (error recovery) 2934 return (boundRes.canIgnore() && !unboundRes.canIgnore()) ? 2935 unboundRes.sym : boundRes.sym; 2936 } 2937 } 2938 }; 2939 2940 /** 2941 * This chooser implements the selection strategy used during an arity-based lookup; this logic 2942 * is described in JLS SE 8 (15.12.2.1). 2943 */ 2944 ReferenceChooser structuralReferenceChooser = new ReferenceChooser() { 2945 2946 @Override 2947 Symbol boundResult(ReferenceLookupResult boundRes) { 2948 return (!boundRes.isSuccess() || !boundRes.hasKind(StaticKind.STATIC)) ? 2949 boundRes.sym : //the search has at least one applicable non-static method 2950 new BadMethodReferenceError(boundRes.sym, false); 2951 } 2952 2953 @Override 2954 Symbol unboundResult(ReferenceLookupResult boundRes, ReferenceLookupResult unboundRes) { 2955 if (boundRes.isSuccess() && !boundRes.hasKind(StaticKind.NON_STATIC)) { 2956 //the first serach has at least one applicable static method 2957 return boundRes.sym; 2958 } else if (unboundRes.isSuccess() && !unboundRes.hasKind(StaticKind.STATIC)) { 2959 //the second search has at least one applicable non-static method 2960 return unboundRes.sym; 2961 } else if (boundRes.isSuccess() || unboundRes.isSuccess()) { 2962 //either the first search produces a non-static method, or second search produces 2963 //a non-static method (error recovery) 2964 return new BadMethodReferenceError(boundRes.isSuccess() ? boundRes.sym : unboundRes.sym, true); 2965 } else { 2966 //both searches fail to produce a result - pick 'better' error using heuristics (error recovery) 2967 return (boundRes.canIgnore() && !unboundRes.canIgnore()) ? 2968 unboundRes.sym : boundRes.sym; 2969 } 2970 } 2971 }; 2972 2973 /** 2974 * Helper for defining custom method-like lookup logic; a lookup helper 2975 * provides hooks for (i) the actual lookup logic and (ii) accessing the 2976 * lookup result (this step might result in compiler diagnostics to be generated) 2977 */ 2978 abstract class LookupHelper { 2979 2980 /** name of the symbol to lookup */ 2981 Name name; 2982 2983 /** location in which the lookup takes place */ 2984 Type site; 2985 2986 /** actual types used during the lookup */ 2987 List<Type> argtypes; 2988 2989 /** type arguments used during the lookup */ 2990 List<Type> typeargtypes; 2991 2992 /** Max overload resolution phase handled by this helper */ 2993 MethodResolutionPhase maxPhase; 2994 2995 LookupHelper(Name name, Type site, List<Type> argtypes, List<Type> typeargtypes, MethodResolutionPhase maxPhase) { 2996 this.name = name; 2997 this.site = site; 2998 this.argtypes = argtypes; 2999 this.typeargtypes = typeargtypes; 3000 this.maxPhase = maxPhase; 3001 } 3002 3003 /** 3004 * Should lookup stop at given phase with given result 3005 */ 3006 final boolean shouldStop(Symbol sym, MethodResolutionPhase phase) { 3007 return phase.ordinal() > maxPhase.ordinal() || 3008 !sym.kind.isResolutionError() || sym.kind == AMBIGUOUS; 3009 } 3010 3011 /** 3012 * Search for a symbol under a given overload resolution phase - this method 3013 * is usually called several times, once per each overload resolution phase 3014 */ 3015 abstract Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase); 3016 3017 /** 3018 * Dump overload resolution info 3019 */ 3020 void debug(DiagnosticPosition pos, Symbol sym) { 3021 //do nothing 3022 } 3023 3024 /** 3025 * Validate the result of the lookup 3026 */ 3027 abstract Symbol access(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, Symbol sym); 3028 } 3029 3030 abstract class BasicLookupHelper extends LookupHelper { 3031 3032 BasicLookupHelper(Name name, Type site, List<Type> argtypes, List<Type> typeargtypes) { 3033 this(name, site, argtypes, typeargtypes, MethodResolutionPhase.VARARITY); 3034 } 3035 3036 BasicLookupHelper(Name name, Type site, List<Type> argtypes, List<Type> typeargtypes, MethodResolutionPhase maxPhase) { 3037 super(name, site, argtypes, typeargtypes, maxPhase); 3038 } 3039 3040 @Override 3041 final Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) { 3042 Symbol sym = doLookup(env, phase); 3043 if (sym.kind == AMBIGUOUS) { 3044 AmbiguityError a_err = (AmbiguityError)sym.baseSymbol(); 3045 sym = a_err.mergeAbstracts(site); 3046 } 3047 return sym; 3048 } 3049 3050 abstract Symbol doLookup(Env<AttrContext> env, MethodResolutionPhase phase); 3051 3052 @Override 3053 Symbol access(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, Symbol sym) { 3054 if (sym.kind.isResolutionError()) { 3055 //if nothing is found return the 'first' error 3056 sym = accessMethod(sym, pos, location, site, name, true, argtypes, typeargtypes); 3057 } 3058 return sym; 3059 } 3060 3061 @Override 3062 void debug(DiagnosticPosition pos, Symbol sym) { 3063 reportVerboseResolutionDiagnostic(pos, name, site, argtypes, typeargtypes, sym); 3064 } 3065 } 3066 3067 /** 3068 * Helper class for member reference lookup. A reference lookup helper 3069 * defines the basic logic for member reference lookup; a method gives 3070 * access to an 'unbound' helper used to perform an unbound member 3071 * reference lookup. 3072 */ 3073 abstract class ReferenceLookupHelper extends LookupHelper { 3074 3075 /** The member reference tree */ 3076 JCMemberReference referenceTree; 3077 3078 ReferenceLookupHelper(JCMemberReference referenceTree, Name name, Type site, 3079 List<Type> argtypes, List<Type> typeargtypes, MethodResolutionPhase maxPhase) { 3080 super(name, site, argtypes, typeargtypes, maxPhase); 3081 this.referenceTree = referenceTree; 3082 } 3083 3084 /** 3085 * Returns an unbound version of this lookup helper. By default, this 3086 * method returns an dummy lookup helper. 3087 */ 3088 ReferenceLookupHelper unboundLookup(InferenceContext inferenceContext) { 3089 return null; 3090 } 3091 3092 /** 3093 * Get the kind of the member reference 3094 */ 3095 abstract JCMemberReference.ReferenceKind referenceKind(Symbol sym); 3096 3097 Symbol access(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, Symbol sym) { 3098 if (sym.kind == AMBIGUOUS) { 3099 AmbiguityError a_err = (AmbiguityError)sym.baseSymbol(); 3100 sym = a_err.mergeAbstracts(site); 3101 } 3102 //skip error reporting 3103 return sym; 3104 } 3105 } 3106 3107 /** 3108 * Helper class for method reference lookup. The lookup logic is based 3109 * upon Resolve.findMethod; in certain cases, this helper class has a 3110 * corresponding unbound helper class (see UnboundMethodReferenceLookupHelper). 3111 * In such cases, non-static lookup results are thrown away. 3112 */ 3113 class MethodReferenceLookupHelper extends ReferenceLookupHelper { 3114 3115 /** The original method reference lookup site. */ 3116 Type originalSite; 3117 3118 MethodReferenceLookupHelper(JCMemberReference referenceTree, Name name, Type site, 3119 List<Type> argtypes, List<Type> typeargtypes, MethodResolutionPhase maxPhase) { 3120 super(referenceTree, name, types.skipTypeVars(site, true), argtypes, typeargtypes, maxPhase); 3121 this.originalSite = site; 3122 } 3123 3124 @Override 3125 final Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) { 3126 return findMethod(env, site, name, argtypes, typeargtypes, 3127 phase.isBoxingRequired(), phase.isVarargsRequired()); 3128 } 3129 3130 @Override 3131 ReferenceLookupHelper unboundLookup(InferenceContext inferenceContext) { 3132 if (TreeInfo.isStaticSelector(referenceTree.expr, names)) { 3133 if (argtypes.nonEmpty() && 3134 (argtypes.head.hasTag(NONE) || 3135 types.isSubtypeUnchecked(inferenceContext.asUndetVar(argtypes.head), site))) { 3136 return new UnboundMethodReferenceLookupHelper(referenceTree, name, 3137 originalSite, argtypes, typeargtypes, maxPhase); 3138 } else { 3139 return new ReferenceLookupHelper(referenceTree, name, site, argtypes, typeargtypes, maxPhase) { 3140 @Override 3141 ReferenceLookupHelper unboundLookup(InferenceContext inferenceContext) { 3142 return this; 3143 } 3144 3145 @Override 3146 Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) { 3147 return methodNotFound; 3148 } 3149 3150 @Override 3151 ReferenceKind referenceKind(Symbol sym) { 3152 Assert.error(); 3153 return null; 3154 } 3155 }; 3156 } 3157 } else { 3158 return super.unboundLookup(inferenceContext); 3159 } 3160 } 3161 3162 @Override 3163 ReferenceKind referenceKind(Symbol sym) { 3164 if (sym.isStatic()) { 3165 return ReferenceKind.STATIC; 3166 } else { 3167 Name selName = TreeInfo.name(referenceTree.getQualifierExpression()); 3168 return selName != null && selName == names._super ? 3169 ReferenceKind.SUPER : 3170 ReferenceKind.BOUND; 3171 } 3172 } 3173 } 3174 3175 /** 3176 * Helper class for unbound method reference lookup. Essentially the same 3177 * as the basic method reference lookup helper; main difference is that static 3178 * lookup results are thrown away. If qualifier type is raw, an attempt to 3179 * infer a parameterized type is made using the first actual argument (that 3180 * would otherwise be ignored during the lookup). 3181 */ 3182 class UnboundMethodReferenceLookupHelper extends MethodReferenceLookupHelper { 3183 3184 UnboundMethodReferenceLookupHelper(JCMemberReference referenceTree, Name name, Type site, 3185 List<Type> argtypes, List<Type> typeargtypes, MethodResolutionPhase maxPhase) { 3186 super(referenceTree, name, site, argtypes.tail, typeargtypes, maxPhase); 3187 if (site.isRaw() && !argtypes.head.hasTag(NONE)) { 3188 Type asSuperSite = types.asSuper(argtypes.head, site.tsym); 3189 this.site = types.skipTypeVars(asSuperSite, true); 3190 } 3191 } 3192 3193 @Override 3194 ReferenceLookupHelper unboundLookup(InferenceContext inferenceContext) { 3195 return this; 3196 } 3197 3198 @Override 3199 ReferenceKind referenceKind(Symbol sym) { 3200 return ReferenceKind.UNBOUND; 3201 } 3202 } 3203 3204 /** 3205 * Helper class for array constructor lookup; an array constructor lookup 3206 * is simulated by looking up a method that returns the array type specified 3207 * as qualifier, and that accepts a single int parameter (size of the array). 3208 */ 3209 class ArrayConstructorReferenceLookupHelper extends ReferenceLookupHelper { 3210 3211 ArrayConstructorReferenceLookupHelper(JCMemberReference referenceTree, Type site, List<Type> argtypes, 3212 List<Type> typeargtypes, MethodResolutionPhase maxPhase) { 3213 super(referenceTree, names.init, site, argtypes, typeargtypes, maxPhase); 3214 } 3215 3216 @Override 3217 protected Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) { 3218 WriteableScope sc = WriteableScope.create(syms.arrayClass); 3219 MethodSymbol arrayConstr = new MethodSymbol(PUBLIC, name, null, site.tsym); 3220 arrayConstr.type = new MethodType(List.<Type>of(syms.intType), site, List.<Type>nil(), syms.methodClass); 3221 sc.enter(arrayConstr); 3222 return findMethodInScope(env, site, name, argtypes, typeargtypes, sc, methodNotFound, phase.isBoxingRequired(), phase.isVarargsRequired(), false); 3223 } 3224 3225 @Override 3226 ReferenceKind referenceKind(Symbol sym) { 3227 return ReferenceKind.ARRAY_CTOR; 3228 } 3229 } 3230 3231 /** 3232 * Helper class for constructor reference lookup. The lookup logic is based 3233 * upon either Resolve.findMethod or Resolve.findDiamond - depending on 3234 * whether the constructor reference needs diamond inference (this is the case 3235 * if the qualifier type is raw). A special erroneous symbol is returned 3236 * if the lookup returns the constructor of an inner class and there's no 3237 * enclosing instance in scope. 3238 */ 3239 class ConstructorReferenceLookupHelper extends ReferenceLookupHelper { 3240 3241 boolean needsInference; 3242 3243 ConstructorReferenceLookupHelper(JCMemberReference referenceTree, Type site, List<Type> argtypes, 3244 List<Type> typeargtypes, MethodResolutionPhase maxPhase) { 3245 super(referenceTree, names.init, site, argtypes, typeargtypes, maxPhase); 3246 if (site.isRaw()) { 3247 this.site = new ClassType(site.getEnclosingType(), site.tsym.type.getTypeArguments(), site.tsym, site.getMetadata()); 3248 needsInference = true; 3249 } 3250 } 3251 3252 @Override 3253 protected Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) { 3254 Symbol sym = needsInference ? 3255 findDiamond(env, site, argtypes, typeargtypes, phase.isBoxingRequired(), phase.isVarargsRequired()) : 3256 findMethod(env, site, name, argtypes, typeargtypes, 3257 phase.isBoxingRequired(), phase.isVarargsRequired()); 3258 return enclosingInstanceMissing(env, site) ? new BadConstructorReferenceError(sym) : sym; 3259 } 3260 3261 @Override 3262 ReferenceKind referenceKind(Symbol sym) { 3263 return site.getEnclosingType().hasTag(NONE) ? 3264 ReferenceKind.TOPLEVEL : ReferenceKind.IMPLICIT_INNER; 3265 } 3266 } 3267 3268 /** 3269 * Main overload resolution routine. On each overload resolution step, a 3270 * lookup helper class is used to perform the method/constructor lookup; 3271 * at the end of the lookup, the helper is used to validate the results 3272 * (this last step might trigger overload resolution diagnostics). 3273 */ 3274 Symbol lookupMethod(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, MethodCheck methodCheck, LookupHelper lookupHelper) { 3275 MethodResolutionContext resolveContext = new MethodResolutionContext(); 3276 resolveContext.methodCheck = methodCheck; 3277 return lookupMethod(env, pos, location, resolveContext, lookupHelper); 3278 } 3279 3280 Symbol lookupMethod(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, 3281 MethodResolutionContext resolveContext, LookupHelper lookupHelper) { 3282 MethodResolutionContext prevResolutionContext = currentResolutionContext; 3283 try { 3284 Symbol bestSoFar = methodNotFound; 3285 currentResolutionContext = resolveContext; 3286 for (MethodResolutionPhase phase : methodResolutionSteps) { 3287 if (lookupHelper.shouldStop(bestSoFar, phase)) 3288 break; 3289 MethodResolutionPhase prevPhase = currentResolutionContext.step; 3290 Symbol prevBest = bestSoFar; 3291 currentResolutionContext.step = phase; 3292 Symbol sym = lookupHelper.lookup(env, phase); 3293 lookupHelper.debug(pos, sym); 3294 bestSoFar = phase.mergeResults(bestSoFar, sym); 3295 env.info.pendingResolutionPhase = (prevBest == bestSoFar) ? prevPhase : phase; 3296 } 3297 return lookupHelper.access(env, pos, location, bestSoFar); 3298 } finally { 3299 currentResolutionContext = prevResolutionContext; 3300 } 3301 } 3302 3303 /** 3304 * Resolve `c.name' where name == this or name == super. 3305 * @param pos The position to use for error reporting. 3306 * @param env The environment current at the expression. 3307 * @param c The qualifier. 3308 * @param name The identifier's name. 3309 */ 3310 Symbol resolveSelf(DiagnosticPosition pos, 3311 Env<AttrContext> env, 3312 TypeSymbol c, 3313 Name name) { 3314 Env<AttrContext> env1 = env; 3315 boolean staticOnly = false; 3316 while (env1.outer != null) { 3317 if (isStatic(env1)) staticOnly = true; 3318 if (env1.enclClass.sym == c) { 3319 Symbol sym = env1.info.scope.findFirst(name); 3320 if (sym != null) { 3321 if (staticOnly) sym = new StaticError(sym); 3322 return accessBase(sym, pos, env.enclClass.sym.type, 3323 name, true); 3324 } 3325 } 3326 if ((env1.enclClass.sym.flags() & STATIC) != 0) staticOnly = true; 3327 env1 = env1.outer; 3328 } 3329 if (c.isInterface() && 3330 name == names._super && !isStatic(env) && 3331 types.isDirectSuperInterface(c, env.enclClass.sym)) { 3332 //this might be a default super call if one of the superinterfaces is 'c' 3333 for (Type t : pruneInterfaces(env.enclClass.type)) { 3334 if (t.tsym == c) { 3335 env.info.defaultSuperCallSite = t; 3336 return new VarSymbol(0, names._super, 3337 types.asSuper(env.enclClass.type, c), env.enclClass.sym); 3338 } 3339 } 3340 //find a direct superinterface that is a subtype of 'c' 3341 for (Type i : types.interfaces(env.enclClass.type)) { 3342 if (i.tsym.isSubClass(c, types) && i.tsym != c) { 3343 log.error(pos, "illegal.default.super.call", c, 3344 diags.fragment("redundant.supertype", c, i)); 3345 return syms.errSymbol; 3346 } 3347 } 3348 Assert.error(); 3349 } 3350 log.error(pos, "not.encl.class", c); 3351 return syms.errSymbol; 3352 } 3353 //where 3354 private List<Type> pruneInterfaces(Type t) { 3355 ListBuffer<Type> result = new ListBuffer<>(); 3356 for (Type t1 : types.interfaces(t)) { 3357 boolean shouldAdd = true; 3358 for (Type t2 : types.interfaces(t)) { 3359 if (t1 != t2 && types.isSubtypeNoCapture(t2, t1)) { 3360 shouldAdd = false; 3361 } 3362 } 3363 if (shouldAdd) { 3364 result.append(t1); 3365 } 3366 } 3367 return result.toList(); 3368 } 3369 3370 3371 /** 3372 * Resolve `c.this' for an enclosing class c that contains the 3373 * named member. 3374 * @param pos The position to use for error reporting. 3375 * @param env The environment current at the expression. 3376 * @param member The member that must be contained in the result. 3377 */ 3378 Symbol resolveSelfContaining(DiagnosticPosition pos, 3379 Env<AttrContext> env, 3380 Symbol member, 3381 boolean isSuperCall) { 3382 Symbol sym = resolveSelfContainingInternal(env, member, isSuperCall); 3383 if (sym == null) { 3384 log.error(pos, "encl.class.required", member); 3385 return syms.errSymbol; 3386 } else { 3387 return accessBase(sym, pos, env.enclClass.sym.type, sym.name, true); 3388 } 3389 } 3390 3391 boolean enclosingInstanceMissing(Env<AttrContext> env, Type type) { 3392 if (type.hasTag(CLASS) && type.getEnclosingType().hasTag(CLASS)) { 3393 Symbol encl = resolveSelfContainingInternal(env, type.tsym, false); 3394 return encl == null || encl.kind.isResolutionError(); 3395 } 3396 return false; 3397 } 3398 3399 private Symbol resolveSelfContainingInternal(Env<AttrContext> env, 3400 Symbol member, 3401 boolean isSuperCall) { 3402 Name name = names._this; 3403 Env<AttrContext> env1 = isSuperCall ? env.outer : env; 3404 boolean staticOnly = false; 3405 if (env1 != null) { 3406 while (env1 != null && env1.outer != null) { 3407 if (isStatic(env1)) staticOnly = true; 3408 if (env1.enclClass.sym.isSubClass(member.owner.enclClass(), types)) { 3409 Symbol sym = env1.info.scope.findFirst(name); 3410 if (sym != null) { 3411 if (staticOnly) sym = new StaticError(sym); 3412 return sym; 3413 } 3414 } 3415 if ((env1.enclClass.sym.flags() & STATIC) != 0) 3416 staticOnly = true; 3417 env1 = env1.outer; 3418 } 3419 } 3420 return null; 3421 } 3422 3423 /** 3424 * Resolve an appropriate implicit this instance for t's container. 3425 * JLS 8.8.5.1 and 15.9.2 3426 */ 3427 Type resolveImplicitThis(DiagnosticPosition pos, Env<AttrContext> env, Type t) { 3428 return resolveImplicitThis(pos, env, t, false); 3429 } 3430 3431 Type resolveImplicitThis(DiagnosticPosition pos, Env<AttrContext> env, Type t, boolean isSuperCall) { 3432 Type thisType = (t.tsym.owner.kind.matches(KindSelector.VAL_MTH) 3433 ? resolveSelf(pos, env, t.getEnclosingType().tsym, names._this) 3434 : resolveSelfContaining(pos, env, t.tsym, isSuperCall)).type; 3435 if (env.info.isSelfCall && thisType.tsym == env.enclClass.sym) 3436 log.error(pos, "cant.ref.before.ctor.called", "this"); 3437 return thisType; 3438 } 3439 3440/* *************************************************************************** 3441 * ResolveError classes, indicating error situations when accessing symbols 3442 ****************************************************************************/ 3443 3444 //used by TransTypes when checking target type of synthetic cast 3445 public void logAccessErrorInternal(Env<AttrContext> env, JCTree tree, Type type) { 3446 AccessError error = new AccessError(env, env.enclClass.type, type.tsym); 3447 logResolveError(error, tree.pos(), env.enclClass.sym, env.enclClass.type, null, null, null); 3448 } 3449 //where 3450 private void logResolveError(ResolveError error, 3451 DiagnosticPosition pos, 3452 Symbol location, 3453 Type site, 3454 Name name, 3455 List<Type> argtypes, 3456 List<Type> typeargtypes) { 3457 JCDiagnostic d = error.getDiagnostic(JCDiagnostic.DiagnosticType.ERROR, 3458 pos, location, site, name, argtypes, typeargtypes); 3459 if (d != null) { 3460 d.setFlag(DiagnosticFlag.RESOLVE_ERROR); 3461 log.report(d); 3462 } 3463 } 3464 3465 private final LocalizedString noArgs = new LocalizedString("compiler.misc.no.args"); 3466 3467 public Object methodArguments(List<Type> argtypes) { 3468 if (argtypes == null || argtypes.isEmpty()) { 3469 return noArgs; 3470 } else { 3471 ListBuffer<Object> diagArgs = new ListBuffer<>(); 3472 for (Type t : argtypes) { 3473 if (t.hasTag(DEFERRED)) { 3474 diagArgs.append(((DeferredAttr.DeferredType)t).tree); 3475 } else { 3476 diagArgs.append(t); 3477 } 3478 } 3479 return diagArgs; 3480 } 3481 } 3482 3483 /** 3484 * Root class for resolution errors. Subclass of ResolveError 3485 * represent a different kinds of resolution error - as such they must 3486 * specify how they map into concrete compiler diagnostics. 3487 */ 3488 abstract class ResolveError extends Symbol { 3489 3490 /** The name of the kind of error, for debugging only. */ 3491 final String debugName; 3492 3493 ResolveError(Kind kind, String debugName) { 3494 super(kind, 0, null, null, null); 3495 this.debugName = debugName; 3496 } 3497 3498 @Override @DefinedBy(Api.LANGUAGE_MODEL) 3499 public <R, P> R accept(ElementVisitor<R, P> v, P p) { 3500 throw new AssertionError(); 3501 } 3502 3503 @Override 3504 public String toString() { 3505 return debugName; 3506 } 3507 3508 @Override 3509 public boolean exists() { 3510 return false; 3511 } 3512 3513 @Override 3514 public boolean isStatic() { 3515 return false; 3516 } 3517 3518 /** 3519 * Create an external representation for this erroneous symbol to be 3520 * used during attribution - by default this returns the symbol of a 3521 * brand new error type which stores the original type found 3522 * during resolution. 3523 * 3524 * @param name the name used during resolution 3525 * @param location the location from which the symbol is accessed 3526 */ 3527 protected Symbol access(Name name, TypeSymbol location) { 3528 return types.createErrorType(name, location, syms.errSymbol.type).tsym; 3529 } 3530 3531 /** 3532 * Create a diagnostic representing this resolution error. 3533 * 3534 * @param dkind The kind of the diagnostic to be created (e.g error). 3535 * @param pos The position to be used for error reporting. 3536 * @param site The original type from where the selection took place. 3537 * @param name The name of the symbol to be resolved. 3538 * @param argtypes The invocation's value arguments, 3539 * if we looked for a method. 3540 * @param typeargtypes The invocation's type arguments, 3541 * if we looked for a method. 3542 */ 3543 abstract JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind, 3544 DiagnosticPosition pos, 3545 Symbol location, 3546 Type site, 3547 Name name, 3548 List<Type> argtypes, 3549 List<Type> typeargtypes); 3550 } 3551 3552 /** 3553 * This class is the root class of all resolution errors caused by 3554 * an invalid symbol being found during resolution. 3555 */ 3556 abstract class InvalidSymbolError extends ResolveError { 3557 3558 /** The invalid symbol found during resolution */ 3559 Symbol sym; 3560 3561 InvalidSymbolError(Kind kind, Symbol sym, String debugName) { 3562 super(kind, debugName); 3563 this.sym = sym; 3564 } 3565 3566 @Override 3567 public boolean exists() { 3568 return true; 3569 } 3570 3571 @Override 3572 public String toString() { 3573 return super.toString() + " wrongSym=" + sym; 3574 } 3575 3576 @Override 3577 public Symbol access(Name name, TypeSymbol location) { 3578 if (!sym.kind.isResolutionError() && sym.kind.matches(KindSelector.TYP)) 3579 return types.createErrorType(name, location, sym.type).tsym; 3580 else 3581 return sym; 3582 } 3583 } 3584 3585 /** 3586 * InvalidSymbolError error class indicating that a symbol matching a 3587 * given name does not exists in a given site. 3588 */ 3589 class SymbolNotFoundError extends ResolveError { 3590 3591 SymbolNotFoundError(Kind kind) { 3592 this(kind, "symbol not found error"); 3593 } 3594 3595 SymbolNotFoundError(Kind kind, String debugName) { 3596 super(kind, debugName); 3597 } 3598 3599 @Override 3600 JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind, 3601 DiagnosticPosition pos, 3602 Symbol location, 3603 Type site, 3604 Name name, 3605 List<Type> argtypes, 3606 List<Type> typeargtypes) { 3607 argtypes = argtypes == null ? List.<Type>nil() : argtypes; 3608 typeargtypes = typeargtypes == null ? List.<Type>nil() : typeargtypes; 3609 if (name == names.error) 3610 return null; 3611 3612 boolean hasLocation = false; 3613 if (location == null) { 3614 location = site.tsym; 3615 } 3616 if (!location.name.isEmpty()) { 3617 if (location.kind == PCK && !site.tsym.exists()) { 3618 return diags.create(dkind, log.currentSource(), pos, 3619 "doesnt.exist", location); 3620 } 3621 hasLocation = !location.name.equals(names._this) && 3622 !location.name.equals(names._super); 3623 } 3624 boolean isConstructor = name == names.init; 3625 KindName kindname = isConstructor ? KindName.CONSTRUCTOR : kind.absentKind(); 3626 Name idname = isConstructor ? site.tsym.name : name; 3627 String errKey = getErrorKey(kindname, typeargtypes.nonEmpty(), hasLocation); 3628 if (hasLocation) { 3629 return diags.create(dkind, log.currentSource(), pos, 3630 errKey, kindname, idname, //symbol kindname, name 3631 typeargtypes, args(argtypes), //type parameters and arguments (if any) 3632 getLocationDiag(location, site)); //location kindname, type 3633 } 3634 else { 3635 return diags.create(dkind, log.currentSource(), pos, 3636 errKey, kindname, idname, //symbol kindname, name 3637 typeargtypes, args(argtypes)); //type parameters and arguments (if any) 3638 } 3639 } 3640 //where 3641 private Object args(List<Type> args) { 3642 return args.isEmpty() ? args : methodArguments(args); 3643 } 3644 3645 private String getErrorKey(KindName kindname, boolean hasTypeArgs, boolean hasLocation) { 3646 String key = "cant.resolve"; 3647 String suffix = hasLocation ? ".location" : ""; 3648 switch (kindname) { 3649 case METHOD: 3650 case CONSTRUCTOR: { 3651 suffix += ".args"; 3652 suffix += hasTypeArgs ? ".params" : ""; 3653 } 3654 } 3655 return key + suffix; 3656 } 3657 private JCDiagnostic getLocationDiag(Symbol location, Type site) { 3658 if (location.kind == VAR) { 3659 return diags.fragment("location.1", 3660 kindName(location), 3661 location, 3662 location.type); 3663 } else { 3664 return diags.fragment("location", 3665 typeKindName(site), 3666 site, 3667 null); 3668 } 3669 } 3670 } 3671 3672 /** 3673 * InvalidSymbolError error class indicating that a given symbol 3674 * (either a method, a constructor or an operand) is not applicable 3675 * given an actual arguments/type argument list. 3676 */ 3677 class InapplicableSymbolError extends ResolveError { 3678 3679 protected MethodResolutionContext resolveContext; 3680 3681 InapplicableSymbolError(MethodResolutionContext context) { 3682 this(WRONG_MTH, "inapplicable symbol error", context); 3683 } 3684 3685 protected InapplicableSymbolError(Kind kind, String debugName, MethodResolutionContext context) { 3686 super(kind, debugName); 3687 this.resolveContext = context; 3688 } 3689 3690 @Override 3691 public String toString() { 3692 return super.toString(); 3693 } 3694 3695 @Override 3696 public boolean exists() { 3697 return true; 3698 } 3699 3700 @Override 3701 JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind, 3702 DiagnosticPosition pos, 3703 Symbol location, 3704 Type site, 3705 Name name, 3706 List<Type> argtypes, 3707 List<Type> typeargtypes) { 3708 if (name == names.error) 3709 return null; 3710 3711 Pair<Symbol, JCDiagnostic> c = errCandidate(); 3712 if (compactMethodDiags) { 3713 JCDiagnostic simpleDiag = 3714 MethodResolutionDiagHelper.rewrite(diags, pos, log.currentSource(), dkind, c.snd); 3715 if (simpleDiag != null) { 3716 return simpleDiag; 3717 } 3718 } 3719 Symbol ws = c.fst.asMemberOf(site, types); 3720 return diags.create(dkind, log.currentSource(), pos, 3721 "cant.apply.symbol", 3722 kindName(ws), 3723 ws.name == names.init ? ws.owner.name : ws.name, 3724 methodArguments(ws.type.getParameterTypes()), 3725 methodArguments(argtypes), 3726 kindName(ws.owner), 3727 ws.owner.type, 3728 c.snd); 3729 } 3730 3731 @Override 3732 public Symbol access(Name name, TypeSymbol location) { 3733 return types.createErrorType(name, location, syms.errSymbol.type).tsym; 3734 } 3735 3736 protected Pair<Symbol, JCDiagnostic> errCandidate() { 3737 Candidate bestSoFar = null; 3738 for (Candidate c : resolveContext.candidates) { 3739 if (c.isApplicable()) continue; 3740 bestSoFar = c; 3741 } 3742 Assert.checkNonNull(bestSoFar); 3743 return new Pair<>(bestSoFar.sym, bestSoFar.details); 3744 } 3745 } 3746 3747 /** 3748 * ResolveError error class indicating that a symbol (either methods, constructors or operand) 3749 * is not applicable given an actual arguments/type argument list. 3750 */ 3751 class InapplicableSymbolsError extends InapplicableSymbolError { 3752 3753 InapplicableSymbolsError(MethodResolutionContext context) { 3754 super(WRONG_MTHS, "inapplicable symbols", context); 3755 } 3756 3757 @Override 3758 JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind, 3759 DiagnosticPosition pos, 3760 Symbol location, 3761 Type site, 3762 Name name, 3763 List<Type> argtypes, 3764 List<Type> typeargtypes) { 3765 Map<Symbol, JCDiagnostic> candidatesMap = mapCandidates(); 3766 Map<Symbol, JCDiagnostic> filteredCandidates = compactMethodDiags ? 3767 filterCandidates(candidatesMap) : 3768 mapCandidates(); 3769 if (filteredCandidates.isEmpty()) { 3770 filteredCandidates = candidatesMap; 3771 } 3772 boolean truncatedDiag = candidatesMap.size() != filteredCandidates.size(); 3773 if (filteredCandidates.size() > 1) { 3774 JCDiagnostic err = diags.create(dkind, 3775 null, 3776 truncatedDiag ? 3777 EnumSet.of(DiagnosticFlag.COMPRESSED) : 3778 EnumSet.noneOf(DiagnosticFlag.class), 3779 log.currentSource(), 3780 pos, 3781 "cant.apply.symbols", 3782 name == names.init ? KindName.CONSTRUCTOR : kind.absentKind(), 3783 name == names.init ? site.tsym.name : name, 3784 methodArguments(argtypes)); 3785 return new JCDiagnostic.MultilineDiagnostic(err, candidateDetails(filteredCandidates, site)); 3786 } else if (filteredCandidates.size() == 1) { 3787 Map.Entry<Symbol, JCDiagnostic> _e = 3788 filteredCandidates.entrySet().iterator().next(); 3789 final Pair<Symbol, JCDiagnostic> p = new Pair<>(_e.getKey(), _e.getValue()); 3790 JCDiagnostic d = new InapplicableSymbolError(resolveContext) { 3791 @Override 3792 protected Pair<Symbol, JCDiagnostic> errCandidate() { 3793 return p; 3794 } 3795 }.getDiagnostic(dkind, pos, 3796 location, site, name, argtypes, typeargtypes); 3797 if (truncatedDiag) { 3798 d.setFlag(DiagnosticFlag.COMPRESSED); 3799 } 3800 return d; 3801 } else { 3802 return new SymbolNotFoundError(ABSENT_MTH).getDiagnostic(dkind, pos, 3803 location, site, name, argtypes, typeargtypes); 3804 } 3805 } 3806 //where 3807 private Map<Symbol, JCDiagnostic> mapCandidates() { 3808 Map<Symbol, JCDiagnostic> candidates = new LinkedHashMap<>(); 3809 for (Candidate c : resolveContext.candidates) { 3810 if (c.isApplicable()) continue; 3811 candidates.put(c.sym, c.details); 3812 } 3813 return candidates; 3814 } 3815 3816 Map<Symbol, JCDiagnostic> filterCandidates(Map<Symbol, JCDiagnostic> candidatesMap) { 3817 Map<Symbol, JCDiagnostic> candidates = new LinkedHashMap<>(); 3818 for (Map.Entry<Symbol, JCDiagnostic> _entry : candidatesMap.entrySet()) { 3819 JCDiagnostic d = _entry.getValue(); 3820 if (!new Template(MethodCheckDiag.ARITY_MISMATCH.regex()).matches(d)) { 3821 candidates.put(_entry.getKey(), d); 3822 } 3823 } 3824 return candidates; 3825 } 3826 3827 private List<JCDiagnostic> candidateDetails(Map<Symbol, JCDiagnostic> candidatesMap, Type site) { 3828 List<JCDiagnostic> details = List.nil(); 3829 for (Map.Entry<Symbol, JCDiagnostic> _entry : candidatesMap.entrySet()) { 3830 Symbol sym = _entry.getKey(); 3831 JCDiagnostic detailDiag = diags.fragment("inapplicable.method", 3832 Kinds.kindName(sym), 3833 sym.location(site, types), 3834 sym.asMemberOf(site, types), 3835 _entry.getValue()); 3836 details = details.prepend(detailDiag); 3837 } 3838 //typically members are visited in reverse order (see Scope) 3839 //so we need to reverse the candidate list so that candidates 3840 //conform to source order 3841 return details; 3842 } 3843 } 3844 3845 /** 3846 * DiamondError error class indicating that a constructor symbol is not applicable 3847 * given an actual arguments/type argument list using diamond inference. 3848 */ 3849 class DiamondError extends InapplicableSymbolError { 3850 3851 Symbol sym; 3852 3853 public DiamondError(Symbol sym, MethodResolutionContext context) { 3854 super(sym.kind, "diamondError", context); 3855 this.sym = sym; 3856 } 3857 3858 JCDiagnostic getDetails() { 3859 return (sym.kind == WRONG_MTH) ? 3860 ((InapplicableSymbolError)sym.baseSymbol()).errCandidate().snd : 3861 null; 3862 } 3863 3864 @Override 3865 JCDiagnostic getDiagnostic(DiagnosticType dkind, DiagnosticPosition pos, 3866 Symbol location, Type site, Name name, List<Type> argtypes, List<Type> typeargtypes) { 3867 JCDiagnostic details = getDetails(); 3868 if (details != null && compactMethodDiags) { 3869 JCDiagnostic simpleDiag = 3870 MethodResolutionDiagHelper.rewrite(diags, pos, log.currentSource(), dkind, details); 3871 if (simpleDiag != null) { 3872 return simpleDiag; 3873 } 3874 } 3875 String key = details == null ? 3876 "cant.apply.diamond" : 3877 "cant.apply.diamond.1"; 3878 return diags.create(dkind, log.currentSource(), pos, key, 3879 diags.fragment("diamond", site.tsym), details); 3880 } 3881 } 3882 3883 /** 3884 * An InvalidSymbolError error class indicating that a symbol is not 3885 * accessible from a given site 3886 */ 3887 class AccessError extends InvalidSymbolError { 3888 3889 private Env<AttrContext> env; 3890 private Type site; 3891 3892 AccessError(Symbol sym) { 3893 this(null, null, sym); 3894 } 3895 3896 AccessError(Env<AttrContext> env, Type site, Symbol sym) { 3897 super(HIDDEN, sym, "access error"); 3898 this.env = env; 3899 this.site = site; 3900 if (debugResolve) 3901 log.error("proc.messager", sym + " @ " + site + " is inaccessible."); 3902 } 3903 3904 @Override 3905 public boolean exists() { 3906 return false; 3907 } 3908 3909 @Override 3910 JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind, 3911 DiagnosticPosition pos, 3912 Symbol location, 3913 Type site, 3914 Name name, 3915 List<Type> argtypes, 3916 List<Type> typeargtypes) { 3917 if (sym.owner.type.hasTag(ERROR)) 3918 return null; 3919 3920 if (sym.name == names.init && sym.owner != site.tsym) { 3921 return new SymbolNotFoundError(ABSENT_MTH).getDiagnostic(dkind, 3922 pos, location, site, name, argtypes, typeargtypes); 3923 } 3924 else if ((sym.flags() & PUBLIC) != 0 3925 || (env != null && this.site != null 3926 && !isAccessible(env, this.site))) { 3927 return diags.create(dkind, log.currentSource(), 3928 pos, "not.def.access.class.intf.cant.access", 3929 sym, sym.location()); 3930 } 3931 else if ((sym.flags() & (PRIVATE | PROTECTED)) != 0) { 3932 return diags.create(dkind, log.currentSource(), 3933 pos, "report.access", sym, 3934 asFlagSet(sym.flags() & (PRIVATE | PROTECTED)), 3935 sym.location()); 3936 } 3937 else { 3938 return diags.create(dkind, log.currentSource(), 3939 pos, "not.def.public.cant.access", sym, sym.location()); 3940 } 3941 } 3942 } 3943 3944 /** 3945 * InvalidSymbolError error class indicating that an instance member 3946 * has erroneously been accessed from a static context. 3947 */ 3948 class StaticError extends InvalidSymbolError { 3949 3950 StaticError(Symbol sym) { 3951 super(STATICERR, sym, "static error"); 3952 } 3953 3954 @Override 3955 JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind, 3956 DiagnosticPosition pos, 3957 Symbol location, 3958 Type site, 3959 Name name, 3960 List<Type> argtypes, 3961 List<Type> typeargtypes) { 3962 Symbol errSym = ((sym.kind == TYP && sym.type.hasTag(CLASS)) 3963 ? types.erasure(sym.type).tsym 3964 : sym); 3965 return diags.create(dkind, log.currentSource(), pos, 3966 "non-static.cant.be.ref", kindName(sym), errSym); 3967 } 3968 } 3969 3970 /** 3971 * InvalidSymbolError error class indicating that a pair of symbols 3972 * (either methods, constructors or operands) are ambiguous 3973 * given an actual arguments/type argument list. 3974 */ 3975 class AmbiguityError extends ResolveError { 3976 3977 /** The other maximally specific symbol */ 3978 List<Symbol> ambiguousSyms = List.nil(); 3979 3980 @Override 3981 public boolean exists() { 3982 return true; 3983 } 3984 3985 AmbiguityError(Symbol sym1, Symbol sym2) { 3986 super(AMBIGUOUS, "ambiguity error"); 3987 ambiguousSyms = flatten(sym2).appendList(flatten(sym1)); 3988 } 3989 3990 private List<Symbol> flatten(Symbol sym) { 3991 if (sym.kind == AMBIGUOUS) { 3992 return ((AmbiguityError)sym.baseSymbol()).ambiguousSyms; 3993 } else { 3994 return List.of(sym); 3995 } 3996 } 3997 3998 AmbiguityError addAmbiguousSymbol(Symbol s) { 3999 ambiguousSyms = ambiguousSyms.prepend(s); 4000 return this; 4001 } 4002 4003 @Override 4004 JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind, 4005 DiagnosticPosition pos, 4006 Symbol location, 4007 Type site, 4008 Name name, 4009 List<Type> argtypes, 4010 List<Type> typeargtypes) { 4011 List<Symbol> diagSyms = ambiguousSyms.reverse(); 4012 Symbol s1 = diagSyms.head; 4013 Symbol s2 = diagSyms.tail.head; 4014 Name sname = s1.name; 4015 if (sname == names.init) sname = s1.owner.name; 4016 return diags.create(dkind, log.currentSource(), 4017 pos, "ref.ambiguous", sname, 4018 kindName(s1), 4019 s1, 4020 s1.location(site, types), 4021 kindName(s2), 4022 s2, 4023 s2.location(site, types)); 4024 } 4025 4026 /** 4027 * If multiple applicable methods are found during overload and none of them 4028 * is more specific than the others, attempt to merge their signatures. 4029 */ 4030 Symbol mergeAbstracts(Type site) { 4031 List<Symbol> ambiguousInOrder = ambiguousSyms.reverse(); 4032 for (Symbol s : ambiguousInOrder) { 4033 Type mt = types.memberType(site, s); 4034 boolean found = true; 4035 List<Type> allThrown = mt.getThrownTypes(); 4036 for (Symbol s2 : ambiguousInOrder) { 4037 Type mt2 = types.memberType(site, s2); 4038 if ((s2.flags() & ABSTRACT) == 0 || 4039 !types.overrideEquivalent(mt, mt2) || 4040 !types.isSameTypes(s.erasure(types).getParameterTypes(), 4041 s2.erasure(types).getParameterTypes())) { 4042 //ambiguity cannot be resolved 4043 return this; 4044 } 4045 Type mst = mostSpecificReturnType(mt, mt2); 4046 if (mst == null || mst != mt) { 4047 found = false; 4048 break; 4049 } 4050 allThrown = chk.intersect(allThrown, mt2.getThrownTypes()); 4051 } 4052 if (found) { 4053 //all ambiguous methods were abstract and one method had 4054 //most specific return type then others 4055 return (allThrown == mt.getThrownTypes()) ? 4056 s : new MethodSymbol( 4057 s.flags(), 4058 s.name, 4059 types.createMethodTypeWithThrown(s.type, allThrown), 4060 s.owner); 4061 } 4062 } 4063 return this; 4064 } 4065 4066 @Override 4067 protected Symbol access(Name name, TypeSymbol location) { 4068 Symbol firstAmbiguity = ambiguousSyms.last(); 4069 return firstAmbiguity.kind == TYP ? 4070 types.createErrorType(name, location, firstAmbiguity.type).tsym : 4071 firstAmbiguity; 4072 } 4073 } 4074 4075 class BadVarargsMethod extends ResolveError { 4076 4077 ResolveError delegatedError; 4078 4079 BadVarargsMethod(ResolveError delegatedError) { 4080 super(delegatedError.kind, "badVarargs"); 4081 this.delegatedError = delegatedError; 4082 } 4083 4084 @Override 4085 public Symbol baseSymbol() { 4086 return delegatedError.baseSymbol(); 4087 } 4088 4089 @Override 4090 protected Symbol access(Name name, TypeSymbol location) { 4091 return delegatedError.access(name, location); 4092 } 4093 4094 @Override 4095 public boolean exists() { 4096 return true; 4097 } 4098 4099 @Override 4100 JCDiagnostic getDiagnostic(DiagnosticType dkind, DiagnosticPosition pos, Symbol location, Type site, Name name, List<Type> argtypes, List<Type> typeargtypes) { 4101 return delegatedError.getDiagnostic(dkind, pos, location, site, name, argtypes, typeargtypes); 4102 } 4103 } 4104 4105 /** 4106 * BadMethodReferenceError error class indicating that a method reference symbol has been found, 4107 * but with the wrong staticness. 4108 */ 4109 class BadMethodReferenceError extends StaticError { 4110 4111 boolean unboundLookup; 4112 4113 public BadMethodReferenceError(Symbol sym, boolean unboundLookup) { 4114 super(sym); 4115 this.unboundLookup = unboundLookup; 4116 } 4117 4118 @Override 4119 JCDiagnostic getDiagnostic(DiagnosticType dkind, DiagnosticPosition pos, Symbol location, Type site, Name name, List<Type> argtypes, List<Type> typeargtypes) { 4120 final String key; 4121 if (!unboundLookup) { 4122 key = "bad.static.method.in.bound.lookup"; 4123 } else if (sym.isStatic()) { 4124 key = "bad.static.method.in.unbound.lookup"; 4125 } else { 4126 key = "bad.instance.method.in.unbound.lookup"; 4127 } 4128 return sym.kind.isResolutionError() ? 4129 ((ResolveError)sym).getDiagnostic(dkind, pos, location, site, name, argtypes, typeargtypes) : 4130 diags.create(dkind, log.currentSource(), pos, key, Kinds.kindName(sym), sym); 4131 } 4132 } 4133 4134 /** 4135 * BadConstructorReferenceError error class indicating that a constructor reference symbol has been found, 4136 * but pointing to a class for which an enclosing instance is not available. 4137 */ 4138 class BadConstructorReferenceError extends InvalidSymbolError { 4139 4140 public BadConstructorReferenceError(Symbol sym) { 4141 super(MISSING_ENCL, sym, "BadConstructorReferenceError"); 4142 } 4143 4144 @Override 4145 JCDiagnostic getDiagnostic(DiagnosticType dkind, DiagnosticPosition pos, Symbol location, Type site, Name name, List<Type> argtypes, List<Type> typeargtypes) { 4146 return diags.create(dkind, log.currentSource(), pos, 4147 "cant.access.inner.cls.constr", site.tsym.name, argtypes, site.getEnclosingType()); 4148 } 4149 } 4150 4151 /** 4152 * Helper class for method resolution diagnostic simplification. 4153 * Certain resolution diagnostic are rewritten as simpler diagnostic 4154 * where the enclosing resolution diagnostic (i.e. 'inapplicable method') 4155 * is stripped away, as it doesn't carry additional info. The logic 4156 * for matching a given diagnostic is given in terms of a template 4157 * hierarchy: a diagnostic template can be specified programmatically, 4158 * so that only certain diagnostics are matched. Each templete is then 4159 * associated with a rewriter object that carries out the task of rewtiting 4160 * the diagnostic to a simpler one. 4161 */ 4162 static class MethodResolutionDiagHelper { 4163 4164 /** 4165 * A diagnostic rewriter transforms a method resolution diagnostic 4166 * into a simpler one 4167 */ 4168 interface DiagnosticRewriter { 4169 JCDiagnostic rewriteDiagnostic(JCDiagnostic.Factory diags, 4170 DiagnosticPosition preferedPos, DiagnosticSource preferredSource, 4171 DiagnosticType preferredKind, JCDiagnostic d); 4172 } 4173 4174 /** 4175 * A diagnostic template is made up of two ingredients: (i) a regular 4176 * expression for matching a diagnostic key and (ii) a list of sub-templates 4177 * for matching diagnostic arguments. 4178 */ 4179 static class Template { 4180 4181 /** regex used to match diag key */ 4182 String regex; 4183 4184 /** templates used to match diagnostic args */ 4185 Template[] subTemplates; 4186 4187 Template(String key, Template... subTemplates) { 4188 this.regex = key; 4189 this.subTemplates = subTemplates; 4190 } 4191 4192 /** 4193 * Returns true if the regex matches the diagnostic key and if 4194 * all diagnostic arguments are matches by corresponding sub-templates. 4195 */ 4196 boolean matches(Object o) { 4197 JCDiagnostic d = (JCDiagnostic)o; 4198 Object[] args = d.getArgs(); 4199 if (!d.getCode().matches(regex) || 4200 subTemplates.length != d.getArgs().length) { 4201 return false; 4202 } 4203 for (int i = 0; i < args.length ; i++) { 4204 if (!subTemplates[i].matches(args[i])) { 4205 return false; 4206 } 4207 } 4208 return true; 4209 } 4210 } 4211 4212 /** 4213 * Common rewriter for all argument mismatch simplifications. 4214 */ 4215 static class ArgMismatchRewriter implements DiagnosticRewriter { 4216 4217 /** the index of the subdiagnostic to be used as primary. */ 4218 int causeIndex; 4219 4220 public ArgMismatchRewriter(int causeIndex) { 4221 this.causeIndex = causeIndex; 4222 } 4223 4224 @Override 4225 public JCDiagnostic rewriteDiagnostic(JCDiagnostic.Factory diags, 4226 DiagnosticPosition preferedPos, DiagnosticSource preferredSource, 4227 DiagnosticType preferredKind, JCDiagnostic d) { 4228 JCDiagnostic cause = (JCDiagnostic)d.getArgs()[causeIndex]; 4229 DiagnosticPosition pos = d.getDiagnosticPosition(); 4230 if (pos == null) { 4231 pos = preferedPos; 4232 } 4233 return diags.create(preferredKind, preferredSource, pos, 4234 "prob.found.req", cause); 4235 } 4236 } 4237 4238 /** a dummy template that match any diagnostic argument */ 4239 static final Template skip = new Template("") { 4240 @Override 4241 boolean matches(Object d) { 4242 return true; 4243 } 4244 }; 4245 4246 /** template for matching inference-free arguments mismatch failures */ 4247 static final Template argMismatchTemplate = new Template(MethodCheckDiag.ARG_MISMATCH.regex(), skip); 4248 4249 /** template for matching inference related arguments mismatch failures */ 4250 static final Template inferArgMismatchTemplate = new Template(MethodCheckDiag.ARG_MISMATCH.regex(), skip, skip) { 4251 @Override 4252 boolean matches(Object o) { 4253 if (!super.matches(o)) { 4254 return false; 4255 } 4256 JCDiagnostic d = (JCDiagnostic)o; 4257 @SuppressWarnings("unchecked") 4258 List<Type> tvars = (List<Type>)d.getArgs()[0]; 4259 return !containsAny(d, tvars); 4260 } 4261 4262 BiPredicate<Object, List<Type>> containsPredicate = (o, ts) -> { 4263 if (o instanceof Type) { 4264 return ((Type)o).containsAny(ts); 4265 } else if (o instanceof JCDiagnostic) { 4266 return containsAny((JCDiagnostic)o, ts); 4267 } else { 4268 return false; 4269 } 4270 }; 4271 4272 boolean containsAny(JCDiagnostic d, List<Type> ts) { 4273 return Stream.of(d.getArgs()) 4274 .anyMatch(o -> containsPredicate.test(o, ts)); 4275 } 4276 }; 4277 4278 /** rewriter map used for method resolution simplification */ 4279 static final Map<Template, DiagnosticRewriter> rewriters = new LinkedHashMap<>(); 4280 4281 static { 4282 rewriters.put(argMismatchTemplate, new ArgMismatchRewriter(0)); 4283 rewriters.put(inferArgMismatchTemplate, new ArgMismatchRewriter(1)); 4284 } 4285 4286 /** 4287 * Main entry point for diagnostic rewriting - given a diagnostic, see if any templates matches it, 4288 * and rewrite it accordingly. 4289 */ 4290 static JCDiagnostic rewrite(JCDiagnostic.Factory diags, DiagnosticPosition pos, DiagnosticSource source, 4291 DiagnosticType dkind, JCDiagnostic d) { 4292 for (Map.Entry<Template, DiagnosticRewriter> _entry : rewriters.entrySet()) { 4293 if (_entry.getKey().matches(d)) { 4294 JCDiagnostic simpleDiag = 4295 _entry.getValue().rewriteDiagnostic(diags, pos, source, dkind, d); 4296 simpleDiag.setFlag(DiagnosticFlag.COMPRESSED); 4297 return simpleDiag; 4298 } 4299 } 4300 return null; 4301 } 4302 } 4303 4304 enum MethodResolutionPhase { 4305 BASIC(false, false), 4306 BOX(true, false), 4307 VARARITY(true, true) { 4308 @Override 4309 public Symbol mergeResults(Symbol bestSoFar, Symbol sym) { 4310 //Check invariants (see {@code LookupHelper.shouldStop}) 4311 Assert.check(bestSoFar.kind.isResolutionError() && bestSoFar.kind != AMBIGUOUS); 4312 if (!sym.kind.isResolutionError()) { 4313 //varargs resolution successful 4314 return sym; 4315 } else { 4316 //pick best error 4317 switch (bestSoFar.kind) { 4318 case WRONG_MTH: 4319 case WRONG_MTHS: 4320 //Override previous errors if they were caused by argument mismatch. 4321 //This generally means preferring current symbols - but we need to pay 4322 //attention to the fact that the varargs lookup returns 'less' candidates 4323 //than the previous rounds, and adjust that accordingly. 4324 switch (sym.kind) { 4325 case WRONG_MTH: 4326 //if the previous round matched more than one method, return that 4327 //result instead 4328 return bestSoFar.kind == WRONG_MTHS ? 4329 bestSoFar : sym; 4330 case ABSENT_MTH: 4331 //do not override erroneous symbol if the arity lookup did not 4332 //match any method 4333 return bestSoFar; 4334 case WRONG_MTHS: 4335 default: 4336 //safe to override 4337 return sym; 4338 } 4339 default: 4340 //otherwise, return first error 4341 return bestSoFar; 4342 } 4343 } 4344 } 4345 }; 4346 4347 final boolean isBoxingRequired; 4348 final boolean isVarargsRequired; 4349 4350 MethodResolutionPhase(boolean isBoxingRequired, boolean isVarargsRequired) { 4351 this.isBoxingRequired = isBoxingRequired; 4352 this.isVarargsRequired = isVarargsRequired; 4353 } 4354 4355 public boolean isBoxingRequired() { 4356 return isBoxingRequired; 4357 } 4358 4359 public boolean isVarargsRequired() { 4360 return isVarargsRequired; 4361 } 4362 4363 public Symbol mergeResults(Symbol prev, Symbol sym) { 4364 return sym; 4365 } 4366 } 4367 4368 final List<MethodResolutionPhase> methodResolutionSteps = List.of(BASIC, BOX, VARARITY); 4369 4370 /** 4371 * A resolution context is used to keep track of intermediate results of 4372 * overload resolution, such as list of method that are not applicable 4373 * (used to generate more precise diagnostics) and so on. Resolution contexts 4374 * can be nested - this means that when each overload resolution routine should 4375 * work within the resolution context it created. 4376 */ 4377 class MethodResolutionContext { 4378 4379 private List<Candidate> candidates = List.nil(); 4380 4381 MethodResolutionPhase step = null; 4382 4383 MethodCheck methodCheck = resolveMethodCheck; 4384 4385 private boolean internalResolution = false; 4386 private DeferredAttr.AttrMode attrMode = DeferredAttr.AttrMode.SPECULATIVE; 4387 4388 void addInapplicableCandidate(Symbol sym, JCDiagnostic details) { 4389 Candidate c = new Candidate(currentResolutionContext.step, sym, details, null); 4390 candidates = candidates.append(c); 4391 } 4392 4393 void addApplicableCandidate(Symbol sym, Type mtype) { 4394 Candidate c = new Candidate(currentResolutionContext.step, sym, null, mtype); 4395 candidates = candidates.append(c); 4396 } 4397 4398 DeferredAttrContext deferredAttrContext(Symbol sym, InferenceContext inferenceContext, ResultInfo pendingResult, Warner warn) { 4399 DeferredAttrContext parent = (pendingResult == null) 4400 ? deferredAttr.emptyDeferredAttrContext 4401 : pendingResult.checkContext.deferredAttrContext(); 4402 return deferredAttr.new DeferredAttrContext(attrMode, sym, step, 4403 inferenceContext, parent, warn); 4404 } 4405 4406 /** 4407 * This class represents an overload resolution candidate. There are two 4408 * kinds of candidates: applicable methods and inapplicable methods; 4409 * applicable methods have a pointer to the instantiated method type, 4410 * while inapplicable candidates contain further details about the 4411 * reason why the method has been considered inapplicable. 4412 */ 4413 @SuppressWarnings("overrides") 4414 class Candidate { 4415 4416 final MethodResolutionPhase step; 4417 final Symbol sym; 4418 final JCDiagnostic details; 4419 final Type mtype; 4420 4421 private Candidate(MethodResolutionPhase step, Symbol sym, JCDiagnostic details, Type mtype) { 4422 this.step = step; 4423 this.sym = sym; 4424 this.details = details; 4425 this.mtype = mtype; 4426 } 4427 4428 @Override 4429 public boolean equals(Object o) { 4430 if (o instanceof Candidate) { 4431 Symbol s1 = this.sym; 4432 Symbol s2 = ((Candidate)o).sym; 4433 if ((s1 != s2 && 4434 (s1.overrides(s2, s1.owner.type.tsym, types, false) || 4435 (s2.overrides(s1, s2.owner.type.tsym, types, false)))) || 4436 ((s1.isConstructor() || s2.isConstructor()) && s1.owner != s2.owner)) 4437 return true; 4438 } 4439 return false; 4440 } 4441 4442 boolean isApplicable() { 4443 return mtype != null; 4444 } 4445 } 4446 4447 DeferredAttr.AttrMode attrMode() { 4448 return attrMode; 4449 } 4450 4451 boolean internal() { 4452 return internalResolution; 4453 } 4454 } 4455 4456 MethodResolutionContext currentResolutionContext = null; 4457} 4458