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