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