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