Tue, 08 Jan 2013 10:15:30 +0100
8005243: Restructure method check code to allow pluggable checkers
Summary: Add interface to perform a method check - to be implemented by helper classes
Reviewed-by: jjg
1 /*
2 * Copyright (c) 1999, 2012, 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 */
26 package com.sun.tools.javac.comp;
28 import com.sun.tools.javac.api.Formattable.LocalizedString;
29 import com.sun.tools.javac.code.*;
30 import com.sun.tools.javac.code.Symbol.*;
31 import com.sun.tools.javac.code.Type.*;
32 import com.sun.tools.javac.comp.Attr.ResultInfo;
33 import com.sun.tools.javac.comp.Check.CheckContext;
34 import com.sun.tools.javac.comp.DeferredAttr.AttrMode;
35 import com.sun.tools.javac.comp.DeferredAttr.DeferredAttrContext;
36 import com.sun.tools.javac.comp.DeferredAttr.DeferredType;
37 import com.sun.tools.javac.comp.Infer.InferenceContext;
38 import com.sun.tools.javac.comp.Infer.InferenceContext.FreeTypeListener;
39 import com.sun.tools.javac.comp.Resolve.MethodResolutionContext.Candidate;
40 import com.sun.tools.javac.jvm.*;
41 import com.sun.tools.javac.tree.*;
42 import com.sun.tools.javac.tree.JCTree.*;
43 import com.sun.tools.javac.tree.JCTree.JCMemberReference.ReferenceKind;
44 import com.sun.tools.javac.util.*;
45 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
46 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
47 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticType;
49 import java.util.Arrays;
50 import java.util.Collection;
51 import java.util.EnumMap;
52 import java.util.EnumSet;
53 import java.util.Iterator;
54 import java.util.LinkedHashMap;
55 import java.util.LinkedHashSet;
56 import java.util.Map;
57 import java.util.Set;
59 import javax.lang.model.element.ElementVisitor;
61 import static com.sun.tools.javac.code.Flags.*;
62 import static com.sun.tools.javac.code.Flags.BLOCK;
63 import static com.sun.tools.javac.code.Kinds.*;
64 import static com.sun.tools.javac.code.Kinds.ERRONEOUS;
65 import static com.sun.tools.javac.code.TypeTag.*;
66 import static com.sun.tools.javac.comp.Resolve.MethodResolutionPhase.*;
67 import static com.sun.tools.javac.tree.JCTree.Tag.*;
69 /** Helper class for name resolution, used mostly by the attribution phase.
70 *
71 * <p><b>This is NOT part of any supported API.
72 * If you write code that depends on this, you do so at your own risk.
73 * This code and its internal interfaces are subject to change or
74 * deletion without notice.</b>
75 */
76 public class Resolve {
77 protected static final Context.Key<Resolve> resolveKey =
78 new Context.Key<Resolve>();
80 Names names;
81 Log log;
82 Symtab syms;
83 Attr attr;
84 DeferredAttr deferredAttr;
85 Check chk;
86 Infer infer;
87 ClassReader reader;
88 TreeInfo treeinfo;
89 Types types;
90 JCDiagnostic.Factory diags;
91 public final boolean boxingEnabled; // = source.allowBoxing();
92 public final boolean varargsEnabled; // = source.allowVarargs();
93 public final boolean allowMethodHandles;
94 public final boolean allowDefaultMethods;
95 private final boolean debugResolve;
96 final EnumSet<VerboseResolutionMode> verboseResolutionMode;
98 Scope polymorphicSignatureScope;
100 protected Resolve(Context context) {
101 context.put(resolveKey, this);
102 syms = Symtab.instance(context);
104 varNotFound = new
105 SymbolNotFoundError(ABSENT_VAR);
106 methodNotFound = new
107 SymbolNotFoundError(ABSENT_MTH);
108 typeNotFound = new
109 SymbolNotFoundError(ABSENT_TYP);
111 names = Names.instance(context);
112 log = Log.instance(context);
113 attr = Attr.instance(context);
114 deferredAttr = DeferredAttr.instance(context);
115 chk = Check.instance(context);
116 infer = Infer.instance(context);
117 reader = ClassReader.instance(context);
118 treeinfo = TreeInfo.instance(context);
119 types = Types.instance(context);
120 diags = JCDiagnostic.Factory.instance(context);
121 Source source = Source.instance(context);
122 boxingEnabled = source.allowBoxing();
123 varargsEnabled = source.allowVarargs();
124 Options options = Options.instance(context);
125 debugResolve = options.isSet("debugresolve");
126 verboseResolutionMode = VerboseResolutionMode.getVerboseResolutionMode(options);
127 Target target = Target.instance(context);
128 allowMethodHandles = target.hasMethodHandles();
129 allowDefaultMethods = source.allowDefaultMethods();
130 polymorphicSignatureScope = new Scope(syms.noSymbol);
132 inapplicableMethodException = new InapplicableMethodException(diags);
133 }
135 /** error symbols, which are returned when resolution fails
136 */
137 private final SymbolNotFoundError varNotFound;
138 private final SymbolNotFoundError methodNotFound;
139 private final SymbolNotFoundError typeNotFound;
141 public static Resolve instance(Context context) {
142 Resolve instance = context.get(resolveKey);
143 if (instance == null)
144 instance = new Resolve(context);
145 return instance;
146 }
148 // <editor-fold defaultstate="collapsed" desc="Verbose resolution diagnostics support">
149 enum VerboseResolutionMode {
150 SUCCESS("success"),
151 FAILURE("failure"),
152 APPLICABLE("applicable"),
153 INAPPLICABLE("inapplicable"),
154 DEFERRED_INST("deferred-inference"),
155 PREDEF("predef"),
156 OBJECT_INIT("object-init"),
157 INTERNAL("internal");
159 final String opt;
161 private VerboseResolutionMode(String opt) {
162 this.opt = opt;
163 }
165 static EnumSet<VerboseResolutionMode> getVerboseResolutionMode(Options opts) {
166 String s = opts.get("verboseResolution");
167 EnumSet<VerboseResolutionMode> res = EnumSet.noneOf(VerboseResolutionMode.class);
168 if (s == null) return res;
169 if (s.contains("all")) {
170 res = EnumSet.allOf(VerboseResolutionMode.class);
171 }
172 Collection<String> args = Arrays.asList(s.split(","));
173 for (VerboseResolutionMode mode : values()) {
174 if (args.contains(mode.opt)) {
175 res.add(mode);
176 } else if (args.contains("-" + mode.opt)) {
177 res.remove(mode);
178 }
179 }
180 return res;
181 }
182 }
184 void reportVerboseResolutionDiagnostic(DiagnosticPosition dpos, Name name, Type site,
185 List<Type> argtypes, List<Type> typeargtypes, Symbol bestSoFar) {
186 boolean success = bestSoFar.kind < ERRONEOUS;
188 if (success && !verboseResolutionMode.contains(VerboseResolutionMode.SUCCESS)) {
189 return;
190 } else if (!success && !verboseResolutionMode.contains(VerboseResolutionMode.FAILURE)) {
191 return;
192 }
194 if (bestSoFar.name == names.init &&
195 bestSoFar.owner == syms.objectType.tsym &&
196 !verboseResolutionMode.contains(VerboseResolutionMode.OBJECT_INIT)) {
197 return; //skip diags for Object constructor resolution
198 } else if (site == syms.predefClass.type &&
199 !verboseResolutionMode.contains(VerboseResolutionMode.PREDEF)) {
200 return; //skip spurious diags for predef symbols (i.e. operators)
201 } else if (currentResolutionContext.internalResolution &&
202 !verboseResolutionMode.contains(VerboseResolutionMode.INTERNAL)) {
203 return;
204 }
206 int pos = 0;
207 int mostSpecificPos = -1;
208 ListBuffer<JCDiagnostic> subDiags = ListBuffer.lb();
209 for (Candidate c : currentResolutionContext.candidates) {
210 if (currentResolutionContext.step != c.step ||
211 (c.isApplicable() && !verboseResolutionMode.contains(VerboseResolutionMode.APPLICABLE)) ||
212 (!c.isApplicable() && !verboseResolutionMode.contains(VerboseResolutionMode.INAPPLICABLE))) {
213 continue;
214 } else {
215 subDiags.append(c.isApplicable() ?
216 getVerboseApplicableCandidateDiag(pos, c.sym, c.mtype) :
217 getVerboseInapplicableCandidateDiag(pos, c.sym, c.details));
218 if (c.sym == bestSoFar)
219 mostSpecificPos = pos;
220 pos++;
221 }
222 }
223 String key = success ? "verbose.resolve.multi" : "verbose.resolve.multi.1";
224 List<Type> argtypes2 = Type.map(argtypes,
225 deferredAttr.new RecoveryDeferredTypeMap(AttrMode.SPECULATIVE, bestSoFar, currentResolutionContext.step));
226 JCDiagnostic main = diags.note(log.currentSource(), dpos, key, name,
227 site.tsym, mostSpecificPos, currentResolutionContext.step,
228 methodArguments(argtypes2),
229 methodArguments(typeargtypes));
230 JCDiagnostic d = new JCDiagnostic.MultilineDiagnostic(main, subDiags.toList());
231 log.report(d);
232 }
234 JCDiagnostic getVerboseApplicableCandidateDiag(int pos, Symbol sym, Type inst) {
235 JCDiagnostic subDiag = null;
236 if (sym.type.hasTag(FORALL)) {
237 subDiag = diags.fragment("partial.inst.sig", inst);
238 }
240 String key = subDiag == null ?
241 "applicable.method.found" :
242 "applicable.method.found.1";
244 return diags.fragment(key, pos, sym, subDiag);
245 }
247 JCDiagnostic getVerboseInapplicableCandidateDiag(int pos, Symbol sym, JCDiagnostic subDiag) {
248 return diags.fragment("not.applicable.method.found", pos, sym, subDiag);
249 }
250 // </editor-fold>
252 /* ************************************************************************
253 * Identifier resolution
254 *************************************************************************/
256 /** An environment is "static" if its static level is greater than
257 * the one of its outer environment
258 */
259 protected static boolean isStatic(Env<AttrContext> env) {
260 return env.info.staticLevel > env.outer.info.staticLevel;
261 }
263 /** An environment is an "initializer" if it is a constructor or
264 * an instance initializer.
265 */
266 static boolean isInitializer(Env<AttrContext> env) {
267 Symbol owner = env.info.scope.owner;
268 return owner.isConstructor() ||
269 owner.owner.kind == TYP &&
270 (owner.kind == VAR ||
271 owner.kind == MTH && (owner.flags() & BLOCK) != 0) &&
272 (owner.flags() & STATIC) == 0;
273 }
275 /** Is class accessible in given evironment?
276 * @param env The current environment.
277 * @param c The class whose accessibility is checked.
278 */
279 public boolean isAccessible(Env<AttrContext> env, TypeSymbol c) {
280 return isAccessible(env, c, false);
281 }
283 public boolean isAccessible(Env<AttrContext> env, TypeSymbol c, boolean checkInner) {
284 boolean isAccessible = false;
285 switch ((short)(c.flags() & AccessFlags)) {
286 case PRIVATE:
287 isAccessible =
288 env.enclClass.sym.outermostClass() ==
289 c.owner.outermostClass();
290 break;
291 case 0:
292 isAccessible =
293 env.toplevel.packge == c.owner // fast special case
294 ||
295 env.toplevel.packge == c.packge()
296 ||
297 // Hack: this case is added since synthesized default constructors
298 // of anonymous classes should be allowed to access
299 // classes which would be inaccessible otherwise.
300 env.enclMethod != null &&
301 (env.enclMethod.mods.flags & ANONCONSTR) != 0;
302 break;
303 default: // error recovery
304 case PUBLIC:
305 isAccessible = true;
306 break;
307 case PROTECTED:
308 isAccessible =
309 env.toplevel.packge == c.owner // fast special case
310 ||
311 env.toplevel.packge == c.packge()
312 ||
313 isInnerSubClass(env.enclClass.sym, c.owner);
314 break;
315 }
316 return (checkInner == false || c.type.getEnclosingType() == Type.noType) ?
317 isAccessible :
318 isAccessible && isAccessible(env, c.type.getEnclosingType(), checkInner);
319 }
320 //where
321 /** Is given class a subclass of given base class, or an inner class
322 * of a subclass?
323 * Return null if no such class exists.
324 * @param c The class which is the subclass or is contained in it.
325 * @param base The base class
326 */
327 private boolean isInnerSubClass(ClassSymbol c, Symbol base) {
328 while (c != null && !c.isSubClass(base, types)) {
329 c = c.owner.enclClass();
330 }
331 return c != null;
332 }
334 boolean isAccessible(Env<AttrContext> env, Type t) {
335 return isAccessible(env, t, false);
336 }
338 boolean isAccessible(Env<AttrContext> env, Type t, boolean checkInner) {
339 return (t.hasTag(ARRAY))
340 ? isAccessible(env, types.elemtype(t))
341 : isAccessible(env, t.tsym, checkInner);
342 }
344 /** Is symbol accessible as a member of given type in given evironment?
345 * @param env The current environment.
346 * @param site The type of which the tested symbol is regarded
347 * as a member.
348 * @param sym The symbol.
349 */
350 public boolean isAccessible(Env<AttrContext> env, Type site, Symbol sym) {
351 return isAccessible(env, site, sym, false);
352 }
353 public boolean isAccessible(Env<AttrContext> env, Type site, Symbol sym, boolean checkInner) {
354 if (sym.name == names.init && sym.owner != site.tsym) return false;
355 switch ((short)(sym.flags() & AccessFlags)) {
356 case PRIVATE:
357 return
358 (env.enclClass.sym == sym.owner // fast special case
359 ||
360 env.enclClass.sym.outermostClass() ==
361 sym.owner.outermostClass())
362 &&
363 sym.isInheritedIn(site.tsym, types);
364 case 0:
365 return
366 (env.toplevel.packge == sym.owner.owner // fast special case
367 ||
368 env.toplevel.packge == sym.packge())
369 &&
370 isAccessible(env, site, checkInner)
371 &&
372 sym.isInheritedIn(site.tsym, types)
373 &&
374 notOverriddenIn(site, sym);
375 case PROTECTED:
376 return
377 (env.toplevel.packge == sym.owner.owner // fast special case
378 ||
379 env.toplevel.packge == sym.packge()
380 ||
381 isProtectedAccessible(sym, env.enclClass.sym, site)
382 ||
383 // OK to select instance method or field from 'super' or type name
384 // (but type names should be disallowed elsewhere!)
385 env.info.selectSuper && (sym.flags() & STATIC) == 0 && sym.kind != TYP)
386 &&
387 isAccessible(env, site, checkInner)
388 &&
389 notOverriddenIn(site, sym);
390 default: // this case includes erroneous combinations as well
391 return isAccessible(env, site, checkInner) && notOverriddenIn(site, sym);
392 }
393 }
394 //where
395 /* `sym' is accessible only if not overridden by
396 * another symbol which is a member of `site'
397 * (because, if it is overridden, `sym' is not strictly
398 * speaking a member of `site'). A polymorphic signature method
399 * cannot be overridden (e.g. MH.invokeExact(Object[])).
400 */
401 private boolean notOverriddenIn(Type site, Symbol sym) {
402 if (sym.kind != MTH || sym.isConstructor() || sym.isStatic())
403 return true;
404 else {
405 Symbol s2 = ((MethodSymbol)sym).implementation(site.tsym, types, true);
406 return (s2 == null || s2 == sym || sym.owner == s2.owner ||
407 !types.isSubSignature(types.memberType(site, s2), types.memberType(site, sym)));
408 }
409 }
410 //where
411 /** Is given protected symbol accessible if it is selected from given site
412 * and the selection takes place in given class?
413 * @param sym The symbol with protected access
414 * @param c The class where the access takes place
415 * @site The type of the qualifier
416 */
417 private
418 boolean isProtectedAccessible(Symbol sym, ClassSymbol c, Type site) {
419 while (c != null &&
420 !(c.isSubClass(sym.owner, types) &&
421 (c.flags() & INTERFACE) == 0 &&
422 // In JLS 2e 6.6.2.1, the subclass restriction applies
423 // only to instance fields and methods -- types are excluded
424 // regardless of whether they are declared 'static' or not.
425 ((sym.flags() & STATIC) != 0 || sym.kind == TYP || site.tsym.isSubClass(c, types))))
426 c = c.owner.enclClass();
427 return c != null;
428 }
430 /**
431 * Performs a recursive scan of a type looking for accessibility problems
432 * from current attribution environment
433 */
434 void checkAccessibleType(Env<AttrContext> env, Type t) {
435 accessibilityChecker.visit(t, env);
436 }
438 /**
439 * Accessibility type-visitor
440 */
441 Types.SimpleVisitor<Void, Env<AttrContext>> accessibilityChecker =
442 new Types.SimpleVisitor<Void, Env<AttrContext>>() {
444 void visit(List<Type> ts, Env<AttrContext> env) {
445 for (Type t : ts) {
446 visit(t, env);
447 }
448 }
450 public Void visitType(Type t, Env<AttrContext> env) {
451 return null;
452 }
454 @Override
455 public Void visitArrayType(ArrayType t, Env<AttrContext> env) {
456 visit(t.elemtype, env);
457 return null;
458 }
460 @Override
461 public Void visitClassType(ClassType t, Env<AttrContext> env) {
462 visit(t.getTypeArguments(), env);
463 if (!isAccessible(env, t, true)) {
464 accessBase(new AccessError(t.tsym), env.tree.pos(), env.enclClass.sym, t, t.tsym.name, true);
465 }
466 return null;
467 }
469 @Override
470 public Void visitWildcardType(WildcardType t, Env<AttrContext> env) {
471 visit(t.type, env);
472 return null;
473 }
475 @Override
476 public Void visitMethodType(MethodType t, Env<AttrContext> env) {
477 visit(t.getParameterTypes(), env);
478 visit(t.getReturnType(), env);
479 visit(t.getThrownTypes(), env);
480 return null;
481 }
482 };
484 /** Try to instantiate the type of a method so that it fits
485 * given type arguments and argument types. If succesful, return
486 * the method's instantiated type, else return null.
487 * The instantiation will take into account an additional leading
488 * formal parameter if the method is an instance method seen as a member
489 * of un underdetermined site In this case, we treat site as an additional
490 * parameter and the parameters of the class containing the method as
491 * additional type variables that get instantiated.
492 *
493 * @param env The current environment
494 * @param site The type of which the method is a member.
495 * @param m The method symbol.
496 * @param argtypes The invocation's given value arguments.
497 * @param typeargtypes The invocation's given type arguments.
498 * @param allowBoxing Allow boxing conversions of arguments.
499 * @param useVarargs Box trailing arguments into an array for varargs.
500 */
501 Type rawInstantiate(Env<AttrContext> env,
502 Type site,
503 Symbol m,
504 ResultInfo resultInfo,
505 List<Type> argtypes,
506 List<Type> typeargtypes,
507 boolean allowBoxing,
508 boolean useVarargs,
509 MethodCheck methodCheck,
510 Warner warn) throws Infer.InferenceException {
512 Type mt = types.memberType(site, m);
513 // tvars is the list of formal type variables for which type arguments
514 // need to inferred.
515 List<Type> tvars = List.nil();
516 if (typeargtypes == null) typeargtypes = List.nil();
517 if (!mt.hasTag(FORALL) && typeargtypes.nonEmpty()) {
518 // This is not a polymorphic method, but typeargs are supplied
519 // which is fine, see JLS 15.12.2.1
520 } else if (mt.hasTag(FORALL) && typeargtypes.nonEmpty()) {
521 ForAll pmt = (ForAll) mt;
522 if (typeargtypes.length() != pmt.tvars.length())
523 throw inapplicableMethodException.setMessage("arg.length.mismatch"); // not enough args
524 // Check type arguments are within bounds
525 List<Type> formals = pmt.tvars;
526 List<Type> actuals = typeargtypes;
527 while (formals.nonEmpty() && actuals.nonEmpty()) {
528 List<Type> bounds = types.subst(types.getBounds((TypeVar)formals.head),
529 pmt.tvars, typeargtypes);
530 for (; bounds.nonEmpty(); bounds = bounds.tail)
531 if (!types.isSubtypeUnchecked(actuals.head, bounds.head, warn))
532 throw inapplicableMethodException.setMessage("explicit.param.do.not.conform.to.bounds",actuals.head, bounds);
533 formals = formals.tail;
534 actuals = actuals.tail;
535 }
536 mt = types.subst(pmt.qtype, pmt.tvars, typeargtypes);
537 } else if (mt.hasTag(FORALL)) {
538 ForAll pmt = (ForAll) mt;
539 List<Type> tvars1 = types.newInstances(pmt.tvars);
540 tvars = tvars.appendList(tvars1);
541 mt = types.subst(pmt.qtype, pmt.tvars, tvars1);
542 }
544 // find out whether we need to go the slow route via infer
545 boolean instNeeded = tvars.tail != null; /*inlined: tvars.nonEmpty()*/
546 for (List<Type> l = argtypes;
547 l.tail != null/*inlined: l.nonEmpty()*/ && !instNeeded;
548 l = l.tail) {
549 if (l.head.hasTag(FORALL)) instNeeded = true;
550 }
552 if (instNeeded)
553 return infer.instantiateMethod(env,
554 tvars,
555 (MethodType)mt,
556 resultInfo,
557 m,
558 argtypes,
559 allowBoxing,
560 useVarargs,
561 currentResolutionContext,
562 methodCheck,
563 warn);
565 methodCheck.argumentsAcceptable(env, currentResolutionContext.deferredAttrContext(m, infer.emptyContext),
566 argtypes, mt.getParameterTypes(), warn);
567 return mt;
568 }
570 Type checkMethod(Env<AttrContext> env,
571 Type site,
572 Symbol m,
573 ResultInfo resultInfo,
574 List<Type> argtypes,
575 List<Type> typeargtypes,
576 Warner warn) {
577 MethodResolutionContext prevContext = currentResolutionContext;
578 try {
579 currentResolutionContext = new MethodResolutionContext();
580 currentResolutionContext.attrMode = DeferredAttr.AttrMode.CHECK;
581 MethodResolutionPhase step = currentResolutionContext.step = env.info.pendingResolutionPhase;
582 return rawInstantiate(env, site, m, resultInfo, argtypes, typeargtypes,
583 step.isBoxingRequired(), step.isVarargsRequired(), resolveMethodCheck, warn);
584 }
585 finally {
586 currentResolutionContext = prevContext;
587 }
588 }
590 /** Same but returns null instead throwing a NoInstanceException
591 */
592 Type instantiate(Env<AttrContext> env,
593 Type site,
594 Symbol m,
595 ResultInfo resultInfo,
596 List<Type> argtypes,
597 List<Type> typeargtypes,
598 boolean allowBoxing,
599 boolean useVarargs,
600 MethodCheck methodCheck,
601 Warner warn) {
602 try {
603 return rawInstantiate(env, site, m, resultInfo, argtypes, typeargtypes,
604 allowBoxing, useVarargs, methodCheck, warn);
605 } catch (InapplicableMethodException ex) {
606 return null;
607 }
608 }
610 /**
611 * This interface defines an entry point that should be used to perform a
612 * method check. A method check usually consist in determining as to whether
613 * a set of types (actuals) is compatible with another set of types (formals).
614 * Since the notion of compatibility can vary depending on the circumstances,
615 * this interfaces allows to easily add new pluggable method check routines.
616 */
617 interface MethodCheck {
618 /**
619 * Main method check routine. A method check usually consist in determining
620 * as to whether a set of types (actuals) is compatible with another set of
621 * types (formals). If an incompatibility is found, an unchecked exception
622 * is assumed to be thrown.
623 */
624 void argumentsAcceptable(Env<AttrContext> env,
625 DeferredAttrContext deferredAttrContext,
626 List<Type> argtypes,
627 List<Type> formals,
628 Warner warn);
629 }
631 /**
632 * Helper enum defining all method check diagnostics (used by resolveMethodCheck).
633 */
634 enum MethodCheckDiag {
635 /**
636 * Actuals and formals differs in length.
637 */
638 ARITY_MISMATCH("arg.length.mismatch", "infer.arg.length.mismatch"),
639 /**
640 * An actual is incompatible with a formal.
641 */
642 ARG_MISMATCH("no.conforming.assignment.exists", "infer.no.conforming.assignment.exists"),
643 /**
644 * An actual is incompatible with the varargs element type.
645 */
646 VARARG_MISMATCH("varargs.argument.mismatch", "infer.varargs.argument.mismatch"),
647 /**
648 * The varargs element type is inaccessible.
649 */
650 INACCESSIBLE_VARARGS("inaccessible.varargs.type", "inaccessible.varargs.type");
652 final String basicKey;
653 final String inferKey;
655 MethodCheckDiag(String basicKey, String inferKey) {
656 this.basicKey = basicKey;
657 this.inferKey = inferKey;
658 }
659 }
661 /**
662 * Main method applicability routine. Given a list of actual types A,
663 * a list of formal types F, determines whether the types in A are
664 * compatible (by method invocation conversion) with the types in F.
665 *
666 * Since this routine is shared between overload resolution and method
667 * type-inference, a (possibly empty) inference context is used to convert
668 * formal types to the corresponding 'undet' form ahead of a compatibility
669 * check so that constraints can be propagated and collected.
670 *
671 * Moreover, if one or more types in A is a deferred type, this routine uses
672 * DeferredAttr in order to perform deferred attribution. If one or more actual
673 * deferred types are stuck, they are placed in a queue and revisited later
674 * after the remainder of the arguments have been seen. If this is not sufficient
675 * to 'unstuck' the argument, a cyclic inference error is called out.
676 *
677 * A method check handler (see above) is used in order to report errors.
678 */
679 MethodCheck resolveMethodCheck = new MethodCheck() {
680 @Override
681 public void argumentsAcceptable(final Env<AttrContext> env,
682 DeferredAttrContext deferredAttrContext,
683 List<Type> argtypes,
684 List<Type> formals,
685 Warner warn) {
686 //should we expand formals?
687 boolean useVarargs = deferredAttrContext.phase.isVarargsRequired();
689 //inference context used during this method check
690 InferenceContext inferenceContext = deferredAttrContext.inferenceContext;
692 Type varargsFormal = useVarargs ? formals.last() : null;
694 if (varargsFormal == null &&
695 argtypes.size() != formals.size()) {
696 report(MethodCheckDiag.ARITY_MISMATCH, inferenceContext); // not enough args
697 }
699 while (argtypes.nonEmpty() && formals.head != varargsFormal) {
700 ResultInfo mresult = methodCheckResult(false, formals.head, deferredAttrContext, warn);
701 mresult.check(null, argtypes.head);
702 argtypes = argtypes.tail;
703 formals = formals.tail;
704 }
706 if (formals.head != varargsFormal) {
707 report(MethodCheckDiag.ARITY_MISMATCH, inferenceContext); // not enough args
708 }
710 if (useVarargs) {
711 //note: if applicability check is triggered by most specific test,
712 //the last argument of a varargs is _not_ an array type (see JLS 15.12.2.5)
713 final Type elt = types.elemtype(varargsFormal);
714 ResultInfo mresult = methodCheckResult(true, elt, deferredAttrContext, warn);
715 while (argtypes.nonEmpty()) {
716 mresult.check(null, argtypes.head);
717 argtypes = argtypes.tail;
718 }
719 //check varargs element type accessibility
720 varargsAccessible(env, elt, inferenceContext);
721 }
722 }
724 private void report(MethodCheckDiag diag, InferenceContext inferenceContext, Object... args) {
725 boolean inferDiag = inferenceContext != infer.emptyContext;
726 InapplicableMethodException ex = inferDiag ?
727 infer.inferenceException : inapplicableMethodException;
728 if (inferDiag && (!diag.inferKey.equals(diag.basicKey))) {
729 Object[] args2 = new Object[args.length + 1];
730 System.arraycopy(args, 0, args2, 1, args.length);
731 args2[0] = inferenceContext.inferenceVars();
732 args = args2;
733 }
734 throw ex.setMessage(inferDiag ? diag.inferKey : diag.basicKey, args);
735 }
737 private void varargsAccessible(final Env<AttrContext> env, final Type t, final InferenceContext inferenceContext) {
738 if (inferenceContext.free(t)) {
739 inferenceContext.addFreeTypeListener(List.of(t), new FreeTypeListener() {
740 @Override
741 public void typesInferred(InferenceContext inferenceContext) {
742 varargsAccessible(env, inferenceContext.asInstType(t, types), inferenceContext);
743 }
744 });
745 } else {
746 if (!isAccessible(env, t)) {
747 Symbol location = env.enclClass.sym;
748 report(MethodCheckDiag.INACCESSIBLE_VARARGS, inferenceContext, t, Kinds.kindName(location), location);
749 }
750 }
751 }
753 private ResultInfo methodCheckResult(final boolean varargsCheck, Type to,
754 final DeferredAttr.DeferredAttrContext deferredAttrContext, Warner rsWarner) {
755 CheckContext checkContext = new MethodCheckContext(!deferredAttrContext.phase.isBoxingRequired(), deferredAttrContext, rsWarner) {
756 MethodCheckDiag methodDiag = varargsCheck ?
757 MethodCheckDiag.VARARG_MISMATCH : MethodCheckDiag.ARG_MISMATCH;
759 @Override
760 public void report(DiagnosticPosition pos, JCDiagnostic details) {
761 report(methodDiag, deferredAttrContext.inferenceContext, details);
762 }
763 };
764 return new MethodResultInfo(to, checkContext);
765 }
766 };
768 /**
769 * Check context to be used during method applicability checks. A method check
770 * context might contain inference variables.
771 */
772 abstract class MethodCheckContext implements CheckContext {
774 boolean strict;
775 DeferredAttrContext deferredAttrContext;
776 Warner rsWarner;
778 public MethodCheckContext(boolean strict, DeferredAttrContext deferredAttrContext, Warner rsWarner) {
779 this.strict = strict;
780 this.deferredAttrContext = deferredAttrContext;
781 this.rsWarner = rsWarner;
782 }
784 public boolean compatible(Type found, Type req, Warner warn) {
785 return strict ?
786 types.isSubtypeUnchecked(found, deferredAttrContext.inferenceContext.asFree(req, types), warn) :
787 types.isConvertible(found, deferredAttrContext.inferenceContext.asFree(req, types), warn);
788 }
790 public void report(DiagnosticPosition pos, JCDiagnostic details) {
791 throw inapplicableMethodException.setMessage(details);
792 }
794 public Warner checkWarner(DiagnosticPosition pos, Type found, Type req) {
795 return rsWarner;
796 }
798 public InferenceContext inferenceContext() {
799 return deferredAttrContext.inferenceContext;
800 }
802 public DeferredAttrContext deferredAttrContext() {
803 return deferredAttrContext;
804 }
805 }
807 /**
808 * ResultInfo class to be used during method applicability checks. Check
809 * for deferred types goes through special path.
810 */
811 class MethodResultInfo extends ResultInfo {
813 public MethodResultInfo(Type pt, CheckContext checkContext) {
814 attr.super(VAL, pt, checkContext);
815 }
817 @Override
818 protected Type check(DiagnosticPosition pos, Type found) {
819 if (found.hasTag(DEFERRED)) {
820 DeferredType dt = (DeferredType)found;
821 return dt.check(this);
822 } else {
823 return super.check(pos, chk.checkNonVoid(pos, types.capture(types.upperBound(found.baseType()))));
824 }
825 }
827 @Override
828 protected MethodResultInfo dup(Type newPt) {
829 return new MethodResultInfo(newPt, checkContext);
830 }
832 @Override
833 protected ResultInfo dup(CheckContext newContext) {
834 return new MethodResultInfo(pt, newContext);
835 }
836 }
838 public static class InapplicableMethodException extends RuntimeException {
839 private static final long serialVersionUID = 0;
841 JCDiagnostic diagnostic;
842 JCDiagnostic.Factory diags;
844 InapplicableMethodException(JCDiagnostic.Factory diags) {
845 this.diagnostic = null;
846 this.diags = diags;
847 }
848 InapplicableMethodException setMessage() {
849 return setMessage((JCDiagnostic)null);
850 }
851 InapplicableMethodException setMessage(String key) {
852 return setMessage(key != null ? diags.fragment(key) : null);
853 }
854 InapplicableMethodException setMessage(String key, Object... args) {
855 return setMessage(key != null ? diags.fragment(key, args) : null);
856 }
857 InapplicableMethodException setMessage(JCDiagnostic diag) {
858 this.diagnostic = diag;
859 return this;
860 }
862 public JCDiagnostic getDiagnostic() {
863 return diagnostic;
864 }
865 }
866 private final InapplicableMethodException inapplicableMethodException;
868 /* ***************************************************************************
869 * Symbol lookup
870 * the following naming conventions for arguments are used
871 *
872 * env is the environment where the symbol was mentioned
873 * site is the type of which the symbol is a member
874 * name is the symbol's name
875 * if no arguments are given
876 * argtypes are the value arguments, if we search for a method
877 *
878 * If no symbol was found, a ResolveError detailing the problem is returned.
879 ****************************************************************************/
881 /** Find field. Synthetic fields are always skipped.
882 * @param env The current environment.
883 * @param site The original type from where the selection takes place.
884 * @param name The name of the field.
885 * @param c The class to search for the field. This is always
886 * a superclass or implemented interface of site's class.
887 */
888 Symbol findField(Env<AttrContext> env,
889 Type site,
890 Name name,
891 TypeSymbol c) {
892 while (c.type.hasTag(TYPEVAR))
893 c = c.type.getUpperBound().tsym;
894 Symbol bestSoFar = varNotFound;
895 Symbol sym;
896 Scope.Entry e = c.members().lookup(name);
897 while (e.scope != null) {
898 if (e.sym.kind == VAR && (e.sym.flags_field & SYNTHETIC) == 0) {
899 return isAccessible(env, site, e.sym)
900 ? e.sym : new AccessError(env, site, e.sym);
901 }
902 e = e.next();
903 }
904 Type st = types.supertype(c.type);
905 if (st != null && (st.hasTag(CLASS) || st.hasTag(TYPEVAR))) {
906 sym = findField(env, site, name, st.tsym);
907 if (sym.kind < bestSoFar.kind) bestSoFar = sym;
908 }
909 for (List<Type> l = types.interfaces(c.type);
910 bestSoFar.kind != AMBIGUOUS && l.nonEmpty();
911 l = l.tail) {
912 sym = findField(env, site, name, l.head.tsym);
913 if (bestSoFar.kind < AMBIGUOUS && sym.kind < AMBIGUOUS &&
914 sym.owner != bestSoFar.owner)
915 bestSoFar = new AmbiguityError(bestSoFar, sym);
916 else if (sym.kind < bestSoFar.kind)
917 bestSoFar = sym;
918 }
919 return bestSoFar;
920 }
922 /** Resolve a field identifier, throw a fatal error if not found.
923 * @param pos The position to use for error reporting.
924 * @param env The environment current at the method invocation.
925 * @param site The type of the qualifying expression, in which
926 * identifier is searched.
927 * @param name The identifier's name.
928 */
929 public VarSymbol resolveInternalField(DiagnosticPosition pos, Env<AttrContext> env,
930 Type site, Name name) {
931 Symbol sym = findField(env, site, name, site.tsym);
932 if (sym.kind == VAR) return (VarSymbol)sym;
933 else throw new FatalError(
934 diags.fragment("fatal.err.cant.locate.field",
935 name));
936 }
938 /** Find unqualified variable or field with given name.
939 * Synthetic fields always skipped.
940 * @param env The current environment.
941 * @param name The name of the variable or field.
942 */
943 Symbol findVar(Env<AttrContext> env, Name name) {
944 Symbol bestSoFar = varNotFound;
945 Symbol sym;
946 Env<AttrContext> env1 = env;
947 boolean staticOnly = false;
948 while (env1.outer != null) {
949 if (isStatic(env1)) staticOnly = true;
950 Scope.Entry e = env1.info.scope.lookup(name);
951 while (e.scope != null &&
952 (e.sym.kind != VAR ||
953 (e.sym.flags_field & SYNTHETIC) != 0))
954 e = e.next();
955 sym = (e.scope != null)
956 ? e.sym
957 : findField(
958 env1, env1.enclClass.sym.type, name, env1.enclClass.sym);
959 if (sym.exists()) {
960 if (staticOnly &&
961 sym.kind == VAR &&
962 sym.owner.kind == TYP &&
963 (sym.flags() & STATIC) == 0)
964 return new StaticError(sym);
965 else
966 return sym;
967 } else if (sym.kind < bestSoFar.kind) {
968 bestSoFar = sym;
969 }
971 if ((env1.enclClass.sym.flags() & STATIC) != 0) staticOnly = true;
972 env1 = env1.outer;
973 }
975 sym = findField(env, syms.predefClass.type, name, syms.predefClass);
976 if (sym.exists())
977 return sym;
978 if (bestSoFar.exists())
979 return bestSoFar;
981 Scope.Entry e = env.toplevel.namedImportScope.lookup(name);
982 for (; e.scope != null; e = e.next()) {
983 sym = e.sym;
984 Type origin = e.getOrigin().owner.type;
985 if (sym.kind == VAR) {
986 if (e.sym.owner.type != origin)
987 sym = sym.clone(e.getOrigin().owner);
988 return isAccessible(env, origin, sym)
989 ? sym : new AccessError(env, origin, sym);
990 }
991 }
993 Symbol origin = null;
994 e = env.toplevel.starImportScope.lookup(name);
995 for (; e.scope != null; e = e.next()) {
996 sym = e.sym;
997 if (sym.kind != VAR)
998 continue;
999 // invariant: sym.kind == VAR
1000 if (bestSoFar.kind < AMBIGUOUS && sym.owner != bestSoFar.owner)
1001 return new AmbiguityError(bestSoFar, sym);
1002 else if (bestSoFar.kind >= VAR) {
1003 origin = e.getOrigin().owner;
1004 bestSoFar = isAccessible(env, origin.type, sym)
1005 ? sym : new AccessError(env, origin.type, sym);
1006 }
1007 }
1008 if (bestSoFar.kind == VAR && bestSoFar.owner.type != origin.type)
1009 return bestSoFar.clone(origin);
1010 else
1011 return bestSoFar;
1012 }
1014 Warner noteWarner = new Warner();
1016 /** Select the best method for a call site among two choices.
1017 * @param env The current environment.
1018 * @param site The original type from where the
1019 * selection takes place.
1020 * @param argtypes The invocation's value arguments,
1021 * @param typeargtypes The invocation's type arguments,
1022 * @param sym Proposed new best match.
1023 * @param bestSoFar Previously found best match.
1024 * @param allowBoxing Allow boxing conversions of arguments.
1025 * @param useVarargs Box trailing arguments into an array for varargs.
1026 */
1027 @SuppressWarnings("fallthrough")
1028 Symbol selectBest(Env<AttrContext> env,
1029 Type site,
1030 List<Type> argtypes,
1031 List<Type> typeargtypes,
1032 Symbol sym,
1033 Symbol bestSoFar,
1034 boolean allowBoxing,
1035 boolean useVarargs,
1036 boolean operator) {
1037 if (sym.kind == ERR ||
1038 !sym.isInheritedIn(site.tsym, types) ||
1039 (useVarargs && (sym.flags() & VARARGS) == 0)) {
1040 return bestSoFar;
1041 }
1042 Assert.check(sym.kind < AMBIGUOUS);
1043 try {
1044 Type mt = rawInstantiate(env, site, sym, null, argtypes, typeargtypes,
1045 allowBoxing, useVarargs, resolveMethodCheck, types.noWarnings);
1046 if (!operator)
1047 currentResolutionContext.addApplicableCandidate(sym, mt);
1048 } catch (InapplicableMethodException ex) {
1049 if (!operator)
1050 currentResolutionContext.addInapplicableCandidate(sym, ex.getDiagnostic());
1051 switch (bestSoFar.kind) {
1052 case ABSENT_MTH:
1053 return new InapplicableSymbolError(currentResolutionContext);
1054 case WRONG_MTH:
1055 if (operator) return bestSoFar;
1056 bestSoFar = new InapplicableSymbolsError(currentResolutionContext);
1057 default:
1058 return bestSoFar;
1059 }
1060 }
1061 if (!isAccessible(env, site, sym)) {
1062 return (bestSoFar.kind == ABSENT_MTH)
1063 ? new AccessError(env, site, sym)
1064 : bestSoFar;
1065 }
1066 return (bestSoFar.kind > AMBIGUOUS)
1067 ? sym
1068 : mostSpecific(argtypes, sym, bestSoFar, env, site,
1069 allowBoxing && operator, useVarargs);
1070 }
1072 /* Return the most specific of the two methods for a call,
1073 * given that both are accessible and applicable.
1074 * @param m1 A new candidate for most specific.
1075 * @param m2 The previous most specific candidate.
1076 * @param env The current environment.
1077 * @param site The original type from where the selection
1078 * takes place.
1079 * @param allowBoxing Allow boxing conversions of arguments.
1080 * @param useVarargs Box trailing arguments into an array for varargs.
1081 */
1082 Symbol mostSpecific(List<Type> argtypes, Symbol m1,
1083 Symbol m2,
1084 Env<AttrContext> env,
1085 final Type site,
1086 boolean allowBoxing,
1087 boolean useVarargs) {
1088 switch (m2.kind) {
1089 case MTH:
1090 if (m1 == m2) return m1;
1091 boolean m1SignatureMoreSpecific =
1092 signatureMoreSpecific(argtypes, env, site, m1, m2, allowBoxing, useVarargs);
1093 boolean m2SignatureMoreSpecific =
1094 signatureMoreSpecific(argtypes, env, site, m2, m1, allowBoxing, useVarargs);
1095 if (m1SignatureMoreSpecific && m2SignatureMoreSpecific) {
1096 Type mt1 = types.memberType(site, m1);
1097 Type mt2 = types.memberType(site, m2);
1098 if (!types.overrideEquivalent(mt1, mt2))
1099 return ambiguityError(m1, m2);
1101 // same signature; select (a) the non-bridge method, or
1102 // (b) the one that overrides the other, or (c) the concrete
1103 // one, or (d) merge both abstract signatures
1104 if ((m1.flags() & BRIDGE) != (m2.flags() & BRIDGE))
1105 return ((m1.flags() & BRIDGE) != 0) ? m2 : m1;
1107 // if one overrides or hides the other, use it
1108 TypeSymbol m1Owner = (TypeSymbol)m1.owner;
1109 TypeSymbol m2Owner = (TypeSymbol)m2.owner;
1110 if (types.asSuper(m1Owner.type, m2Owner) != null &&
1111 ((m1.owner.flags_field & INTERFACE) == 0 ||
1112 (m2.owner.flags_field & INTERFACE) != 0) &&
1113 m1.overrides(m2, m1Owner, types, false))
1114 return m1;
1115 if (types.asSuper(m2Owner.type, m1Owner) != null &&
1116 ((m2.owner.flags_field & INTERFACE) == 0 ||
1117 (m1.owner.flags_field & INTERFACE) != 0) &&
1118 m2.overrides(m1, m2Owner, types, false))
1119 return m2;
1120 boolean m1Abstract = (m1.flags() & ABSTRACT) != 0;
1121 boolean m2Abstract = (m2.flags() & ABSTRACT) != 0;
1122 if (m1Abstract && !m2Abstract) return m2;
1123 if (m2Abstract && !m1Abstract) return m1;
1124 // both abstract or both concrete
1125 if (!m1Abstract && !m2Abstract)
1126 return ambiguityError(m1, m2);
1127 // check that both signatures have the same erasure
1128 if (!types.isSameTypes(m1.erasure(types).getParameterTypes(),
1129 m2.erasure(types).getParameterTypes()))
1130 return ambiguityError(m1, m2);
1131 // both abstract, neither overridden; merge throws clause and result type
1132 Type mst = mostSpecificReturnType(mt1, mt2);
1133 if (mst == null) {
1134 // Theoretically, this can't happen, but it is possible
1135 // due to error recovery or mixing incompatible class files
1136 return ambiguityError(m1, m2);
1137 }
1138 Symbol mostSpecific = mst == mt1 ? m1 : m2;
1139 List<Type> allThrown = chk.intersect(mt1.getThrownTypes(), mt2.getThrownTypes());
1140 Type newSig = types.createMethodTypeWithThrown(mostSpecific.type, allThrown);
1141 MethodSymbol result = new MethodSymbol(
1142 mostSpecific.flags(),
1143 mostSpecific.name,
1144 newSig,
1145 mostSpecific.owner) {
1146 @Override
1147 public MethodSymbol implementation(TypeSymbol origin, Types types, boolean checkResult) {
1148 if (origin == site.tsym)
1149 return this;
1150 else
1151 return super.implementation(origin, types, checkResult);
1152 }
1153 };
1154 return result;
1155 }
1156 if (m1SignatureMoreSpecific) return m1;
1157 if (m2SignatureMoreSpecific) return m2;
1158 return ambiguityError(m1, m2);
1159 case AMBIGUOUS:
1160 AmbiguityError e = (AmbiguityError)m2;
1161 Symbol err1 = mostSpecific(argtypes, m1, e.sym, env, site, allowBoxing, useVarargs);
1162 Symbol err2 = mostSpecific(argtypes, m1, e.sym2, env, site, allowBoxing, useVarargs);
1163 if (err1 == err2) return err1;
1164 if (err1 == e.sym && err2 == e.sym2) return m2;
1165 if (err1 instanceof AmbiguityError &&
1166 err2 instanceof AmbiguityError &&
1167 ((AmbiguityError)err1).sym == ((AmbiguityError)err2).sym)
1168 return ambiguityError(m1, m2);
1169 else
1170 return ambiguityError(err1, err2);
1171 default:
1172 throw new AssertionError();
1173 }
1174 }
1175 //where
1176 private boolean signatureMoreSpecific(List<Type> actuals, Env<AttrContext> env, Type site, Symbol m1, Symbol m2, boolean allowBoxing, boolean useVarargs) {
1177 Symbol m12 = adjustVarargs(m1, m2, useVarargs);
1178 Symbol m22 = adjustVarargs(m2, m1, useVarargs);
1179 Type mtype1 = types.memberType(site, m12);
1180 Type mtype2 = types.memberType(site, m22);
1182 //check if invocation is more specific
1183 if (invocationMoreSpecific(env, site, m22, mtype1.getParameterTypes(), allowBoxing, useVarargs)) {
1184 return true;
1185 }
1187 //perform structural check
1189 List<Type> formals1 = mtype1.getParameterTypes();
1190 Type lastFormal1 = formals1.last();
1191 List<Type> formals2 = mtype2.getParameterTypes();
1192 Type lastFormal2 = formals2.last();
1193 ListBuffer<Type> newFormals = ListBuffer.lb();
1195 boolean hasStructuralPoly = false;
1196 for (Type actual : actuals) {
1197 //perform formal argument adaptation in case actuals > formals (varargs)
1198 Type f1 = formals1.isEmpty() ?
1199 lastFormal1 : formals1.head;
1200 Type f2 = formals2.isEmpty() ?
1201 lastFormal2 : formals2.head;
1203 //is this a structural actual argument?
1204 boolean isStructuralPoly = actual.hasTag(DEFERRED) &&
1205 (((DeferredType)actual).tree.hasTag(LAMBDA) ||
1206 ((DeferredType)actual).tree.hasTag(REFERENCE));
1208 Type newFormal = f1;
1210 if (isStructuralPoly) {
1211 //for structural arguments only - check that corresponding formals
1212 //are related - if so replace formal with <null>
1213 hasStructuralPoly = true;
1214 DeferredType dt = (DeferredType)actual;
1215 Type t1 = deferredAttr.new DeferredTypeMap(AttrMode.SPECULATIVE, m1, currentResolutionContext.step).apply(dt);
1216 Type t2 = deferredAttr.new DeferredTypeMap(AttrMode.SPECULATIVE, m2, currentResolutionContext.step).apply(dt);
1217 if (t1.isErroneous() || t2.isErroneous() || !isStructuralSubtype(t1, t2)) {
1218 //not structural subtypes - simply fail
1219 return false;
1220 } else {
1221 newFormal = syms.botType;
1222 }
1223 }
1225 newFormals.append(newFormal);
1226 if (newFormals.length() > mtype2.getParameterTypes().length()) {
1227 //expand m2's type so as to fit the new formal arity (varargs)
1228 m22.type = types.createMethodTypeWithParameters(m22.type, m22.type.getParameterTypes().append(f2));
1229 }
1231 formals1 = formals1.isEmpty() ? formals1 : formals1.tail;
1232 formals2 = formals2.isEmpty() ? formals2 : formals2.tail;
1233 }
1235 if (!hasStructuralPoly) {
1236 //if no structural actual was found, we're done
1237 return false;
1238 }
1239 //perform additional adaptation if actuals < formals (varargs)
1240 for (Type t : formals1) {
1241 newFormals.append(t);
1242 }
1243 //check if invocation (with tweaked args) is more specific
1244 return invocationMoreSpecific(env, site, m22, newFormals.toList(), allowBoxing, useVarargs);
1245 }
1246 //where
1247 private boolean invocationMoreSpecific(Env<AttrContext> env, Type site, Symbol m2, List<Type> argtypes1, boolean allowBoxing, boolean useVarargs) {
1248 MethodResolutionContext prevContext = currentResolutionContext;
1249 try {
1250 currentResolutionContext = new MethodResolutionContext();
1251 currentResolutionContext.step = allowBoxing ? BOX : BASIC;
1252 noteWarner.clear();
1253 Type mst = instantiate(env, site, m2, null,
1254 types.lowerBounds(argtypes1), null,
1255 allowBoxing, false, resolveMethodCheck, noteWarner);
1256 return mst != null &&
1257 !noteWarner.hasLint(Lint.LintCategory.UNCHECKED);
1258 } finally {
1259 currentResolutionContext = prevContext;
1260 }
1261 }
1262 //where
1263 private Symbol adjustVarargs(Symbol to, Symbol from, boolean useVarargs) {
1264 List<Type> fromArgs = from.type.getParameterTypes();
1265 List<Type> toArgs = to.type.getParameterTypes();
1266 if (useVarargs &&
1267 (from.flags() & VARARGS) != 0 &&
1268 (to.flags() & VARARGS) != 0) {
1269 Type varargsTypeFrom = fromArgs.last();
1270 Type varargsTypeTo = toArgs.last();
1271 ListBuffer<Type> args = ListBuffer.lb();
1272 if (toArgs.length() < fromArgs.length()) {
1273 //if we are checking a varargs method 'from' against another varargs
1274 //method 'to' (where arity of 'to' < arity of 'from') then expand signature
1275 //of 'to' to 'fit' arity of 'from' (this means adding fake formals to 'to'
1276 //until 'to' signature has the same arity as 'from')
1277 while (fromArgs.head != varargsTypeFrom) {
1278 args.append(toArgs.head == varargsTypeTo ? types.elemtype(varargsTypeTo) : toArgs.head);
1279 fromArgs = fromArgs.tail;
1280 toArgs = toArgs.head == varargsTypeTo ?
1281 toArgs :
1282 toArgs.tail;
1283 }
1284 } else {
1285 //formal argument list is same as original list where last
1286 //argument (array type) is removed
1287 args.appendList(toArgs.reverse().tail.reverse());
1288 }
1289 //append varargs element type as last synthetic formal
1290 args.append(types.elemtype(varargsTypeTo));
1291 Type mtype = types.createMethodTypeWithParameters(to.type, args.toList());
1292 return new MethodSymbol(to.flags_field & ~VARARGS, to.name, mtype, to.owner);
1293 } else {
1294 return to;
1295 }
1296 }
1297 //where
1298 boolean isStructuralSubtype(Type s, Type t) {
1300 Type ret_s = types.findDescriptorType(s).getReturnType();
1301 Type ret_t = types.findDescriptorType(t).getReturnType();
1303 //covariant most specific check for function descriptor return type
1304 if (!types.isSubtype(ret_s, ret_t)) {
1305 return false;
1306 }
1308 List<Type> args_s = types.findDescriptorType(s).getParameterTypes();
1309 List<Type> args_t = types.findDescriptorType(t).getParameterTypes();
1311 //arity must be identical
1312 if (args_s.length() != args_t.length()) {
1313 return false;
1314 }
1316 //invariant most specific check for function descriptor parameter types
1317 if (!types.isSameTypes(args_t, args_s)) {
1318 return false;
1319 }
1321 return true;
1322 }
1323 //where
1324 Type mostSpecificReturnType(Type mt1, Type mt2) {
1325 Type rt1 = mt1.getReturnType();
1326 Type rt2 = mt2.getReturnType();
1328 if (mt1.hasTag(FORALL) && mt2.hasTag(FORALL)) {
1329 //if both are generic methods, adjust return type ahead of subtyping check
1330 rt1 = types.subst(rt1, mt1.getTypeArguments(), mt2.getTypeArguments());
1331 }
1332 //first use subtyping, then return type substitutability
1333 if (types.isSubtype(rt1, rt2)) {
1334 return mt1;
1335 } else if (types.isSubtype(rt2, rt1)) {
1336 return mt2;
1337 } else if (types.returnTypeSubstitutable(mt1, mt2)) {
1338 return mt1;
1339 } else if (types.returnTypeSubstitutable(mt2, mt1)) {
1340 return mt2;
1341 } else {
1342 return null;
1343 }
1344 }
1345 //where
1346 Symbol ambiguityError(Symbol m1, Symbol m2) {
1347 if (((m1.flags() | m2.flags()) & CLASH) != 0) {
1348 return (m1.flags() & CLASH) == 0 ? m1 : m2;
1349 } else {
1350 return new AmbiguityError(m1, m2);
1351 }
1352 }
1354 Symbol findMethodInScope(Env<AttrContext> env,
1355 Type site,
1356 Name name,
1357 List<Type> argtypes,
1358 List<Type> typeargtypes,
1359 Scope sc,
1360 Symbol bestSoFar,
1361 boolean allowBoxing,
1362 boolean useVarargs,
1363 boolean operator,
1364 boolean abstractok) {
1365 for (Symbol s : sc.getElementsByName(name, new LookupFilter(abstractok))) {
1366 bestSoFar = selectBest(env, site, argtypes, typeargtypes, s,
1367 bestSoFar, allowBoxing, useVarargs, operator);
1368 }
1369 return bestSoFar;
1370 }
1371 //where
1372 class LookupFilter implements Filter<Symbol> {
1374 boolean abstractOk;
1376 LookupFilter(boolean abstractOk) {
1377 this.abstractOk = abstractOk;
1378 }
1380 public boolean accepts(Symbol s) {
1381 long flags = s.flags();
1382 return s.kind == MTH &&
1383 (flags & SYNTHETIC) == 0 &&
1384 (abstractOk ||
1385 (flags & DEFAULT) != 0 ||
1386 (flags & ABSTRACT) == 0);
1387 }
1388 };
1390 /** Find best qualified method matching given name, type and value
1391 * arguments.
1392 * @param env The current environment.
1393 * @param site The original type from where the selection
1394 * takes place.
1395 * @param name The method's name.
1396 * @param argtypes The method's value arguments.
1397 * @param typeargtypes The method's type arguments
1398 * @param allowBoxing Allow boxing conversions of arguments.
1399 * @param useVarargs Box trailing arguments into an array for varargs.
1400 */
1401 Symbol findMethod(Env<AttrContext> env,
1402 Type site,
1403 Name name,
1404 List<Type> argtypes,
1405 List<Type> typeargtypes,
1406 boolean allowBoxing,
1407 boolean useVarargs,
1408 boolean operator) {
1409 Symbol bestSoFar = methodNotFound;
1410 bestSoFar = findMethod(env,
1411 site,
1412 name,
1413 argtypes,
1414 typeargtypes,
1415 site.tsym.type,
1416 bestSoFar,
1417 allowBoxing,
1418 useVarargs,
1419 operator);
1420 reportVerboseResolutionDiagnostic(env.tree.pos(), name, site, argtypes, typeargtypes, bestSoFar);
1421 return bestSoFar;
1422 }
1423 // where
1424 private Symbol findMethod(Env<AttrContext> env,
1425 Type site,
1426 Name name,
1427 List<Type> argtypes,
1428 List<Type> typeargtypes,
1429 Type intype,
1430 Symbol bestSoFar,
1431 boolean allowBoxing,
1432 boolean useVarargs,
1433 boolean operator) {
1434 @SuppressWarnings({"unchecked","rawtypes"})
1435 List<Type>[] itypes = (List<Type>[])new List[] { List.<Type>nil(), List.<Type>nil() };
1436 InterfaceLookupPhase iphase = InterfaceLookupPhase.ABSTRACT_OK;
1437 for (TypeSymbol s : superclasses(intype)) {
1438 bestSoFar = findMethodInScope(env, site, name, argtypes, typeargtypes,
1439 s.members(), bestSoFar, allowBoxing, useVarargs, operator, true);
1440 if (name == names.init) return bestSoFar;
1441 iphase = (iphase == null) ? null : iphase.update(s, this);
1442 if (iphase != null) {
1443 for (Type itype : types.interfaces(s.type)) {
1444 itypes[iphase.ordinal()] = types.union(types.closure(itype), itypes[iphase.ordinal()]);
1445 }
1446 }
1447 }
1449 Symbol concrete = bestSoFar.kind < ERR &&
1450 (bestSoFar.flags() & ABSTRACT) == 0 ?
1451 bestSoFar : methodNotFound;
1453 for (InterfaceLookupPhase iphase2 : InterfaceLookupPhase.values()) {
1454 if (iphase2 == InterfaceLookupPhase.DEFAULT_OK && !allowDefaultMethods) break;
1455 //keep searching for abstract methods
1456 for (Type itype : itypes[iphase2.ordinal()]) {
1457 if (!itype.isInterface()) continue; //skip j.l.Object (included by Types.closure())
1458 if (iphase2 == InterfaceLookupPhase.DEFAULT_OK &&
1459 (itype.tsym.flags() & DEFAULT) == 0) continue;
1460 bestSoFar = findMethodInScope(env, site, name, argtypes, typeargtypes,
1461 itype.tsym.members(), bestSoFar, allowBoxing, useVarargs, operator, true);
1462 if (concrete != bestSoFar &&
1463 concrete.kind < ERR && bestSoFar.kind < ERR &&
1464 types.isSubSignature(concrete.type, bestSoFar.type)) {
1465 //this is an hack - as javac does not do full membership checks
1466 //most specific ends up comparing abstract methods that might have
1467 //been implemented by some concrete method in a subclass and,
1468 //because of raw override, it is possible for an abstract method
1469 //to be more specific than the concrete method - so we need
1470 //to explicitly call that out (see CR 6178365)
1471 bestSoFar = concrete;
1472 }
1473 }
1474 }
1475 return bestSoFar;
1476 }
1478 enum InterfaceLookupPhase {
1479 ABSTRACT_OK() {
1480 @Override
1481 InterfaceLookupPhase update(Symbol s, Resolve rs) {
1482 //We should not look for abstract methods if receiver is a concrete class
1483 //(as concrete classes are expected to implement all abstracts coming
1484 //from superinterfaces)
1485 if ((s.flags() & (ABSTRACT | INTERFACE | ENUM)) != 0) {
1486 return this;
1487 } else if (rs.allowDefaultMethods) {
1488 return DEFAULT_OK;
1489 } else {
1490 return null;
1491 }
1492 }
1493 },
1494 DEFAULT_OK() {
1495 @Override
1496 InterfaceLookupPhase update(Symbol s, Resolve rs) {
1497 return this;
1498 }
1499 };
1501 abstract InterfaceLookupPhase update(Symbol s, Resolve rs);
1502 }
1504 /**
1505 * Return an Iterable object to scan the superclasses of a given type.
1506 * It's crucial that the scan is done lazily, as we don't want to accidentally
1507 * access more supertypes than strictly needed (as this could trigger completion
1508 * errors if some of the not-needed supertypes are missing/ill-formed).
1509 */
1510 Iterable<TypeSymbol> superclasses(final Type intype) {
1511 return new Iterable<TypeSymbol>() {
1512 public Iterator<TypeSymbol> iterator() {
1513 return new Iterator<TypeSymbol>() {
1515 List<TypeSymbol> seen = List.nil();
1516 TypeSymbol currentSym = symbolFor(intype);
1517 TypeSymbol prevSym = null;
1519 public boolean hasNext() {
1520 if (currentSym == syms.noSymbol) {
1521 currentSym = symbolFor(types.supertype(prevSym.type));
1522 }
1523 return currentSym != null;
1524 }
1526 public TypeSymbol next() {
1527 prevSym = currentSym;
1528 currentSym = syms.noSymbol;
1529 Assert.check(prevSym != null || prevSym != syms.noSymbol);
1530 return prevSym;
1531 }
1533 public void remove() {
1534 throw new UnsupportedOperationException();
1535 }
1537 TypeSymbol symbolFor(Type t) {
1538 if (!t.hasTag(CLASS) &&
1539 !t.hasTag(TYPEVAR)) {
1540 return null;
1541 }
1542 while (t.hasTag(TYPEVAR))
1543 t = t.getUpperBound();
1544 if (seen.contains(t.tsym)) {
1545 //degenerate case in which we have a circular
1546 //class hierarchy - because of ill-formed classfiles
1547 return null;
1548 }
1549 seen = seen.prepend(t.tsym);
1550 return t.tsym;
1551 }
1552 };
1553 }
1554 };
1555 }
1557 /** Find unqualified method matching given name, type and value arguments.
1558 * @param env The current environment.
1559 * @param name The method's name.
1560 * @param argtypes The method's value arguments.
1561 * @param typeargtypes The method's type arguments.
1562 * @param allowBoxing Allow boxing conversions of arguments.
1563 * @param useVarargs Box trailing arguments into an array for varargs.
1564 */
1565 Symbol findFun(Env<AttrContext> env, Name name,
1566 List<Type> argtypes, List<Type> typeargtypes,
1567 boolean allowBoxing, boolean useVarargs) {
1568 Symbol bestSoFar = methodNotFound;
1569 Symbol sym;
1570 Env<AttrContext> env1 = env;
1571 boolean staticOnly = false;
1572 while (env1.outer != null) {
1573 if (isStatic(env1)) staticOnly = true;
1574 sym = findMethod(
1575 env1, env1.enclClass.sym.type, name, argtypes, typeargtypes,
1576 allowBoxing, useVarargs, false);
1577 if (sym.exists()) {
1578 if (staticOnly &&
1579 sym.kind == MTH &&
1580 sym.owner.kind == TYP &&
1581 (sym.flags() & STATIC) == 0) return new StaticError(sym);
1582 else return sym;
1583 } else if (sym.kind < bestSoFar.kind) {
1584 bestSoFar = sym;
1585 }
1586 if ((env1.enclClass.sym.flags() & STATIC) != 0) staticOnly = true;
1587 env1 = env1.outer;
1588 }
1590 sym = findMethod(env, syms.predefClass.type, name, argtypes,
1591 typeargtypes, allowBoxing, useVarargs, false);
1592 if (sym.exists())
1593 return sym;
1595 Scope.Entry e = env.toplevel.namedImportScope.lookup(name);
1596 for (; e.scope != null; e = e.next()) {
1597 sym = e.sym;
1598 Type origin = e.getOrigin().owner.type;
1599 if (sym.kind == MTH) {
1600 if (e.sym.owner.type != origin)
1601 sym = sym.clone(e.getOrigin().owner);
1602 if (!isAccessible(env, origin, sym))
1603 sym = new AccessError(env, origin, sym);
1604 bestSoFar = selectBest(env, origin,
1605 argtypes, typeargtypes,
1606 sym, bestSoFar,
1607 allowBoxing, useVarargs, false);
1608 }
1609 }
1610 if (bestSoFar.exists())
1611 return bestSoFar;
1613 e = env.toplevel.starImportScope.lookup(name);
1614 for (; e.scope != null; e = e.next()) {
1615 sym = e.sym;
1616 Type origin = e.getOrigin().owner.type;
1617 if (sym.kind == MTH) {
1618 if (e.sym.owner.type != origin)
1619 sym = sym.clone(e.getOrigin().owner);
1620 if (!isAccessible(env, origin, sym))
1621 sym = new AccessError(env, origin, sym);
1622 bestSoFar = selectBest(env, origin,
1623 argtypes, typeargtypes,
1624 sym, bestSoFar,
1625 allowBoxing, useVarargs, false);
1626 }
1627 }
1628 return bestSoFar;
1629 }
1631 /** Load toplevel or member class with given fully qualified name and
1632 * verify that it is accessible.
1633 * @param env The current environment.
1634 * @param name The fully qualified name of the class to be loaded.
1635 */
1636 Symbol loadClass(Env<AttrContext> env, Name name) {
1637 try {
1638 ClassSymbol c = reader.loadClass(name);
1639 return isAccessible(env, c) ? c : new AccessError(c);
1640 } catch (ClassReader.BadClassFile err) {
1641 throw err;
1642 } catch (CompletionFailure ex) {
1643 return typeNotFound;
1644 }
1645 }
1647 /** Find qualified member type.
1648 * @param env The current environment.
1649 * @param site The original type from where the selection takes
1650 * place.
1651 * @param name The type's name.
1652 * @param c The class to search for the member type. This is
1653 * always a superclass or implemented interface of
1654 * site's class.
1655 */
1656 Symbol findMemberType(Env<AttrContext> env,
1657 Type site,
1658 Name name,
1659 TypeSymbol c) {
1660 Symbol bestSoFar = typeNotFound;
1661 Symbol sym;
1662 Scope.Entry e = c.members().lookup(name);
1663 while (e.scope != null) {
1664 if (e.sym.kind == TYP) {
1665 return isAccessible(env, site, e.sym)
1666 ? e.sym
1667 : new AccessError(env, site, e.sym);
1668 }
1669 e = e.next();
1670 }
1671 Type st = types.supertype(c.type);
1672 if (st != null && st.hasTag(CLASS)) {
1673 sym = findMemberType(env, site, name, st.tsym);
1674 if (sym.kind < bestSoFar.kind) bestSoFar = sym;
1675 }
1676 for (List<Type> l = types.interfaces(c.type);
1677 bestSoFar.kind != AMBIGUOUS && l.nonEmpty();
1678 l = l.tail) {
1679 sym = findMemberType(env, site, name, l.head.tsym);
1680 if (bestSoFar.kind < AMBIGUOUS && sym.kind < AMBIGUOUS &&
1681 sym.owner != bestSoFar.owner)
1682 bestSoFar = new AmbiguityError(bestSoFar, sym);
1683 else if (sym.kind < bestSoFar.kind)
1684 bestSoFar = sym;
1685 }
1686 return bestSoFar;
1687 }
1689 /** Find a global type in given scope and load corresponding class.
1690 * @param env The current environment.
1691 * @param scope The scope in which to look for the type.
1692 * @param name The type's name.
1693 */
1694 Symbol findGlobalType(Env<AttrContext> env, Scope scope, Name name) {
1695 Symbol bestSoFar = typeNotFound;
1696 for (Scope.Entry e = scope.lookup(name); e.scope != null; e = e.next()) {
1697 Symbol sym = loadClass(env, e.sym.flatName());
1698 if (bestSoFar.kind == TYP && sym.kind == TYP &&
1699 bestSoFar != sym)
1700 return new AmbiguityError(bestSoFar, sym);
1701 else if (sym.kind < bestSoFar.kind)
1702 bestSoFar = sym;
1703 }
1704 return bestSoFar;
1705 }
1707 /** Find an unqualified type symbol.
1708 * @param env The current environment.
1709 * @param name The type's name.
1710 */
1711 Symbol findType(Env<AttrContext> env, Name name) {
1712 Symbol bestSoFar = typeNotFound;
1713 Symbol sym;
1714 boolean staticOnly = false;
1715 for (Env<AttrContext> env1 = env; env1.outer != null; env1 = env1.outer) {
1716 if (isStatic(env1)) staticOnly = true;
1717 for (Scope.Entry e = env1.info.scope.lookup(name);
1718 e.scope != null;
1719 e = e.next()) {
1720 if (e.sym.kind == TYP) {
1721 if (staticOnly &&
1722 e.sym.type.hasTag(TYPEVAR) &&
1723 e.sym.owner.kind == TYP) return new StaticError(e.sym);
1724 return e.sym;
1725 }
1726 }
1728 sym = findMemberType(env1, env1.enclClass.sym.type, name,
1729 env1.enclClass.sym);
1730 if (staticOnly && sym.kind == TYP &&
1731 sym.type.hasTag(CLASS) &&
1732 sym.type.getEnclosingType().hasTag(CLASS) &&
1733 env1.enclClass.sym.type.isParameterized() &&
1734 sym.type.getEnclosingType().isParameterized())
1735 return new StaticError(sym);
1736 else if (sym.exists()) return sym;
1737 else if (sym.kind < bestSoFar.kind) bestSoFar = sym;
1739 JCClassDecl encl = env1.baseClause ? (JCClassDecl)env1.tree : env1.enclClass;
1740 if ((encl.sym.flags() & STATIC) != 0)
1741 staticOnly = true;
1742 }
1744 if (!env.tree.hasTag(IMPORT)) {
1745 sym = findGlobalType(env, env.toplevel.namedImportScope, name);
1746 if (sym.exists()) return sym;
1747 else if (sym.kind < bestSoFar.kind) bestSoFar = sym;
1749 sym = findGlobalType(env, env.toplevel.packge.members(), name);
1750 if (sym.exists()) return sym;
1751 else if (sym.kind < bestSoFar.kind) bestSoFar = sym;
1753 sym = findGlobalType(env, env.toplevel.starImportScope, name);
1754 if (sym.exists()) return sym;
1755 else if (sym.kind < bestSoFar.kind) bestSoFar = sym;
1756 }
1758 return bestSoFar;
1759 }
1761 /** Find an unqualified identifier which matches a specified kind set.
1762 * @param env The current environment.
1763 * @param name The identifier's name.
1764 * @param kind Indicates the possible symbol kinds
1765 * (a subset of VAL, TYP, PCK).
1766 */
1767 Symbol findIdent(Env<AttrContext> env, Name name, int kind) {
1768 Symbol bestSoFar = typeNotFound;
1769 Symbol sym;
1771 if ((kind & VAR) != 0) {
1772 sym = findVar(env, name);
1773 if (sym.exists()) return sym;
1774 else if (sym.kind < bestSoFar.kind) bestSoFar = sym;
1775 }
1777 if ((kind & TYP) != 0) {
1778 sym = findType(env, name);
1779 if (sym.kind==TYP) {
1780 reportDependence(env.enclClass.sym, sym);
1781 }
1782 if (sym.exists()) return sym;
1783 else if (sym.kind < bestSoFar.kind) bestSoFar = sym;
1784 }
1786 if ((kind & PCK) != 0) return reader.enterPackage(name);
1787 else return bestSoFar;
1788 }
1790 /** Report dependencies.
1791 * @param from The enclosing class sym
1792 * @param to The found identifier that the class depends on.
1793 */
1794 public void reportDependence(Symbol from, Symbol to) {
1795 // Override if you want to collect the reported dependencies.
1796 }
1798 /** Find an identifier in a package which matches a specified kind set.
1799 * @param env The current environment.
1800 * @param name The identifier's name.
1801 * @param kind Indicates the possible symbol kinds
1802 * (a nonempty subset of TYP, PCK).
1803 */
1804 Symbol findIdentInPackage(Env<AttrContext> env, TypeSymbol pck,
1805 Name name, int kind) {
1806 Name fullname = TypeSymbol.formFullName(name, pck);
1807 Symbol bestSoFar = typeNotFound;
1808 PackageSymbol pack = null;
1809 if ((kind & PCK) != 0) {
1810 pack = reader.enterPackage(fullname);
1811 if (pack.exists()) return pack;
1812 }
1813 if ((kind & TYP) != 0) {
1814 Symbol sym = loadClass(env, fullname);
1815 if (sym.exists()) {
1816 // don't allow programs to use flatnames
1817 if (name == sym.name) return sym;
1818 }
1819 else if (sym.kind < bestSoFar.kind) bestSoFar = sym;
1820 }
1821 return (pack != null) ? pack : bestSoFar;
1822 }
1824 /** Find an identifier among the members of a given type `site'.
1825 * @param env The current environment.
1826 * @param site The type containing the symbol to be found.
1827 * @param name The identifier's name.
1828 * @param kind Indicates the possible symbol kinds
1829 * (a subset of VAL, TYP).
1830 */
1831 Symbol findIdentInType(Env<AttrContext> env, Type site,
1832 Name name, int kind) {
1833 Symbol bestSoFar = typeNotFound;
1834 Symbol sym;
1835 if ((kind & VAR) != 0) {
1836 sym = findField(env, site, name, site.tsym);
1837 if (sym.exists()) return sym;
1838 else if (sym.kind < bestSoFar.kind) bestSoFar = sym;
1839 }
1841 if ((kind & TYP) != 0) {
1842 sym = findMemberType(env, site, name, site.tsym);
1843 if (sym.exists()) return sym;
1844 else if (sym.kind < bestSoFar.kind) bestSoFar = sym;
1845 }
1846 return bestSoFar;
1847 }
1849 /* ***************************************************************************
1850 * Access checking
1851 * The following methods convert ResolveErrors to ErrorSymbols, issuing
1852 * an error message in the process
1853 ****************************************************************************/
1855 /** If `sym' is a bad symbol: report error and return errSymbol
1856 * else pass through unchanged,
1857 * additional arguments duplicate what has been used in trying to find the
1858 * symbol {@literal (--> flyweight pattern)}. This improves performance since we
1859 * expect misses to happen frequently.
1860 *
1861 * @param sym The symbol that was found, or a ResolveError.
1862 * @param pos The position to use for error reporting.
1863 * @param location The symbol the served as a context for this lookup
1864 * @param site The original type from where the selection took place.
1865 * @param name The symbol's name.
1866 * @param qualified Did we get here through a qualified expression resolution?
1867 * @param argtypes The invocation's value arguments,
1868 * if we looked for a method.
1869 * @param typeargtypes The invocation's type arguments,
1870 * if we looked for a method.
1871 * @param logResolveHelper helper class used to log resolve errors
1872 */
1873 Symbol accessInternal(Symbol sym,
1874 DiagnosticPosition pos,
1875 Symbol location,
1876 Type site,
1877 Name name,
1878 boolean qualified,
1879 List<Type> argtypes,
1880 List<Type> typeargtypes,
1881 LogResolveHelper logResolveHelper) {
1882 if (sym.kind >= AMBIGUOUS) {
1883 ResolveError errSym = (ResolveError)sym;
1884 sym = errSym.access(name, qualified ? site.tsym : syms.noSymbol);
1885 argtypes = logResolveHelper.getArgumentTypes(errSym, sym, name, argtypes);
1886 if (logResolveHelper.resolveDiagnosticNeeded(site, argtypes, typeargtypes)) {
1887 logResolveError(errSym, pos, location, site, name, argtypes, typeargtypes);
1888 }
1889 }
1890 return sym;
1891 }
1893 /**
1894 * Variant of the generalized access routine, to be used for generating method
1895 * resolution diagnostics
1896 */
1897 Symbol accessMethod(Symbol sym,
1898 DiagnosticPosition pos,
1899 Symbol location,
1900 Type site,
1901 Name name,
1902 boolean qualified,
1903 List<Type> argtypes,
1904 List<Type> typeargtypes) {
1905 return accessInternal(sym, pos, location, site, name, qualified, argtypes, typeargtypes, methodLogResolveHelper);
1906 }
1908 /** Same as original accessMethod(), but without location.
1909 */
1910 Symbol accessMethod(Symbol sym,
1911 DiagnosticPosition pos,
1912 Type site,
1913 Name name,
1914 boolean qualified,
1915 List<Type> argtypes,
1916 List<Type> typeargtypes) {
1917 return accessMethod(sym, pos, site.tsym, site, name, qualified, argtypes, typeargtypes);
1918 }
1920 /**
1921 * Variant of the generalized access routine, to be used for generating variable,
1922 * type resolution diagnostics
1923 */
1924 Symbol accessBase(Symbol sym,
1925 DiagnosticPosition pos,
1926 Symbol location,
1927 Type site,
1928 Name name,
1929 boolean qualified) {
1930 return accessInternal(sym, pos, location, site, name, qualified, List.<Type>nil(), null, basicLogResolveHelper);
1931 }
1933 /** Same as original accessBase(), but without location.
1934 */
1935 Symbol accessBase(Symbol sym,
1936 DiagnosticPosition pos,
1937 Type site,
1938 Name name,
1939 boolean qualified) {
1940 return accessBase(sym, pos, site.tsym, site, name, qualified);
1941 }
1943 interface LogResolveHelper {
1944 boolean resolveDiagnosticNeeded(Type site, List<Type> argtypes, List<Type> typeargtypes);
1945 List<Type> getArgumentTypes(ResolveError errSym, Symbol accessedSym, Name name, List<Type> argtypes);
1946 }
1948 LogResolveHelper basicLogResolveHelper = new LogResolveHelper() {
1949 public boolean resolveDiagnosticNeeded(Type site, List<Type> argtypes, List<Type> typeargtypes) {
1950 return !site.isErroneous();
1951 }
1952 public List<Type> getArgumentTypes(ResolveError errSym, Symbol accessedSym, Name name, List<Type> argtypes) {
1953 return argtypes;
1954 }
1955 };
1957 LogResolveHelper methodLogResolveHelper = new LogResolveHelper() {
1958 public boolean resolveDiagnosticNeeded(Type site, List<Type> argtypes, List<Type> typeargtypes) {
1959 return !site.isErroneous() &&
1960 !Type.isErroneous(argtypes) &&
1961 (typeargtypes == null || !Type.isErroneous(typeargtypes));
1962 }
1963 public List<Type> getArgumentTypes(ResolveError errSym, Symbol accessedSym, Name name, List<Type> argtypes) {
1964 return (syms.operatorNames.contains(name)) ?
1965 argtypes :
1966 Type.map(argtypes, new ResolveDeferredRecoveryMap(accessedSym));
1967 }
1969 class ResolveDeferredRecoveryMap extends DeferredAttr.RecoveryDeferredTypeMap {
1971 public ResolveDeferredRecoveryMap(Symbol msym) {
1972 deferredAttr.super(AttrMode.SPECULATIVE, msym, currentResolutionContext.step);
1973 }
1975 @Override
1976 protected Type typeOf(DeferredType dt) {
1977 Type res = super.typeOf(dt);
1978 if (!res.isErroneous()) {
1979 switch (TreeInfo.skipParens(dt.tree).getTag()) {
1980 case LAMBDA:
1981 case REFERENCE:
1982 return dt;
1983 case CONDEXPR:
1984 return res == Type.recoveryType ?
1985 dt : res;
1986 }
1987 }
1988 return res;
1989 }
1990 }
1991 };
1993 /** Check that sym is not an abstract method.
1994 */
1995 void checkNonAbstract(DiagnosticPosition pos, Symbol sym) {
1996 if ((sym.flags() & ABSTRACT) != 0 && (sym.flags() & DEFAULT) == 0)
1997 log.error(pos, "abstract.cant.be.accessed.directly",
1998 kindName(sym), sym, sym.location());
1999 }
2001 /* ***************************************************************************
2002 * Debugging
2003 ****************************************************************************/
2005 /** print all scopes starting with scope s and proceeding outwards.
2006 * used for debugging.
2007 */
2008 public void printscopes(Scope s) {
2009 while (s != null) {
2010 if (s.owner != null)
2011 System.err.print(s.owner + ": ");
2012 for (Scope.Entry e = s.elems; e != null; e = e.sibling) {
2013 if ((e.sym.flags() & ABSTRACT) != 0)
2014 System.err.print("abstract ");
2015 System.err.print(e.sym + " ");
2016 }
2017 System.err.println();
2018 s = s.next;
2019 }
2020 }
2022 void printscopes(Env<AttrContext> env) {
2023 while (env.outer != null) {
2024 System.err.println("------------------------------");
2025 printscopes(env.info.scope);
2026 env = env.outer;
2027 }
2028 }
2030 public void printscopes(Type t) {
2031 while (t.hasTag(CLASS)) {
2032 printscopes(t.tsym.members());
2033 t = types.supertype(t);
2034 }
2035 }
2037 /* ***************************************************************************
2038 * Name resolution
2039 * Naming conventions are as for symbol lookup
2040 * Unlike the find... methods these methods will report access errors
2041 ****************************************************************************/
2043 /** Resolve an unqualified (non-method) identifier.
2044 * @param pos The position to use for error reporting.
2045 * @param env The environment current at the identifier use.
2046 * @param name The identifier's name.
2047 * @param kind The set of admissible symbol kinds for the identifier.
2048 */
2049 Symbol resolveIdent(DiagnosticPosition pos, Env<AttrContext> env,
2050 Name name, int kind) {
2051 return accessBase(
2052 findIdent(env, name, kind),
2053 pos, env.enclClass.sym.type, name, false);
2054 }
2056 /** Resolve an unqualified method identifier.
2057 * @param pos The position to use for error reporting.
2058 * @param env The environment current at the method invocation.
2059 * @param name The identifier's name.
2060 * @param argtypes The types of the invocation's value arguments.
2061 * @param typeargtypes The types of the invocation's type arguments.
2062 */
2063 Symbol resolveMethod(DiagnosticPosition pos,
2064 Env<AttrContext> env,
2065 Name name,
2066 List<Type> argtypes,
2067 List<Type> typeargtypes) {
2068 return lookupMethod(env, pos, env.enclClass.sym, new BasicLookupHelper(name, env.enclClass.sym.type, argtypes, typeargtypes) {
2069 @Override
2070 Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) {
2071 return findFun(env, name, argtypes, typeargtypes,
2072 phase.isBoxingRequired(),
2073 phase.isVarargsRequired());
2074 }
2075 });
2076 }
2078 /** Resolve a qualified method identifier
2079 * @param pos The position to use for error reporting.
2080 * @param env The environment current at the method invocation.
2081 * @param site The type of the qualifying expression, in which
2082 * identifier is searched.
2083 * @param name The identifier's name.
2084 * @param argtypes The types of the invocation's value arguments.
2085 * @param typeargtypes The types of the invocation's type arguments.
2086 */
2087 Symbol resolveQualifiedMethod(DiagnosticPosition pos, Env<AttrContext> env,
2088 Type site, Name name, List<Type> argtypes,
2089 List<Type> typeargtypes) {
2090 return resolveQualifiedMethod(pos, env, site.tsym, site, name, argtypes, typeargtypes);
2091 }
2092 Symbol resolveQualifiedMethod(DiagnosticPosition pos, Env<AttrContext> env,
2093 Symbol location, Type site, Name name, List<Type> argtypes,
2094 List<Type> typeargtypes) {
2095 return resolveQualifiedMethod(new MethodResolutionContext(), pos, env, location, site, name, argtypes, typeargtypes);
2096 }
2097 private Symbol resolveQualifiedMethod(MethodResolutionContext resolveContext,
2098 DiagnosticPosition pos, Env<AttrContext> env,
2099 Symbol location, Type site, Name name, List<Type> argtypes,
2100 List<Type> typeargtypes) {
2101 return lookupMethod(env, pos, location, resolveContext, new BasicLookupHelper(name, site, argtypes, typeargtypes) {
2102 @Override
2103 Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) {
2104 return findMethod(env, site, name, argtypes, typeargtypes,
2105 phase.isBoxingRequired(),
2106 phase.isVarargsRequired(), false);
2107 }
2108 @Override
2109 Symbol access(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, Symbol sym) {
2110 if (sym.kind >= AMBIGUOUS) {
2111 sym = super.access(env, pos, location, sym);
2112 } else if (allowMethodHandles) {
2113 MethodSymbol msym = (MethodSymbol)sym;
2114 if (msym.isSignaturePolymorphic(types)) {
2115 return findPolymorphicSignatureInstance(env, sym, argtypes);
2116 }
2117 }
2118 return sym;
2119 }
2120 });
2121 }
2123 /** Find or create an implicit method of exactly the given type (after erasure).
2124 * Searches in a side table, not the main scope of the site.
2125 * This emulates the lookup process required by JSR 292 in JVM.
2126 * @param env Attribution environment
2127 * @param spMethod signature polymorphic method - i.e. MH.invokeExact
2128 * @param argtypes The required argument types
2129 */
2130 Symbol findPolymorphicSignatureInstance(Env<AttrContext> env,
2131 final Symbol spMethod,
2132 List<Type> argtypes) {
2133 Type mtype = infer.instantiatePolymorphicSignatureInstance(env,
2134 (MethodSymbol)spMethod, currentResolutionContext, argtypes);
2135 for (Symbol sym : polymorphicSignatureScope.getElementsByName(spMethod.name)) {
2136 if (types.isSameType(mtype, sym.type)) {
2137 return sym;
2138 }
2139 }
2141 // create the desired method
2142 long flags = ABSTRACT | HYPOTHETICAL | spMethod.flags() & Flags.AccessFlags;
2143 Symbol msym = new MethodSymbol(flags, spMethod.name, mtype, spMethod.owner) {
2144 @Override
2145 public Symbol baseSymbol() {
2146 return spMethod;
2147 }
2148 };
2149 polymorphicSignatureScope.enter(msym);
2150 return msym;
2151 }
2153 /** Resolve a qualified method identifier, throw a fatal error if not
2154 * found.
2155 * @param pos The position to use for error reporting.
2156 * @param env The environment current at the method invocation.
2157 * @param site The type of the qualifying expression, in which
2158 * identifier is searched.
2159 * @param name The identifier's name.
2160 * @param argtypes The types of the invocation's value arguments.
2161 * @param typeargtypes The types of the invocation's type arguments.
2162 */
2163 public MethodSymbol resolveInternalMethod(DiagnosticPosition pos, Env<AttrContext> env,
2164 Type site, Name name,
2165 List<Type> argtypes,
2166 List<Type> typeargtypes) {
2167 MethodResolutionContext resolveContext = new MethodResolutionContext();
2168 resolveContext.internalResolution = true;
2169 Symbol sym = resolveQualifiedMethod(resolveContext, pos, env, site.tsym,
2170 site, name, argtypes, typeargtypes);
2171 if (sym.kind == MTH) return (MethodSymbol)sym;
2172 else throw new FatalError(
2173 diags.fragment("fatal.err.cant.locate.meth",
2174 name));
2175 }
2177 /** Resolve constructor.
2178 * @param pos The position to use for error reporting.
2179 * @param env The environment current at the constructor invocation.
2180 * @param site The type of class for which a constructor is searched.
2181 * @param argtypes The types of the constructor invocation's value
2182 * arguments.
2183 * @param typeargtypes The types of the constructor invocation's type
2184 * arguments.
2185 */
2186 Symbol resolveConstructor(DiagnosticPosition pos,
2187 Env<AttrContext> env,
2188 Type site,
2189 List<Type> argtypes,
2190 List<Type> typeargtypes) {
2191 return resolveConstructor(new MethodResolutionContext(), pos, env, site, argtypes, typeargtypes);
2192 }
2194 private Symbol resolveConstructor(MethodResolutionContext resolveContext,
2195 final DiagnosticPosition pos,
2196 Env<AttrContext> env,
2197 Type site,
2198 List<Type> argtypes,
2199 List<Type> typeargtypes) {
2200 return lookupMethod(env, pos, site.tsym, resolveContext, new BasicLookupHelper(names.init, site, argtypes, typeargtypes) {
2201 @Override
2202 Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) {
2203 return findConstructor(pos, env, site, argtypes, typeargtypes,
2204 phase.isBoxingRequired(),
2205 phase.isVarargsRequired());
2206 }
2207 });
2208 }
2210 /** Resolve a constructor, throw a fatal error if not found.
2211 * @param pos The position to use for error reporting.
2212 * @param env The environment current at the method invocation.
2213 * @param site The type to be constructed.
2214 * @param argtypes The types of the invocation's value arguments.
2215 * @param typeargtypes The types of the invocation's type arguments.
2216 */
2217 public MethodSymbol resolveInternalConstructor(DiagnosticPosition pos, Env<AttrContext> env,
2218 Type site,
2219 List<Type> argtypes,
2220 List<Type> typeargtypes) {
2221 MethodResolutionContext resolveContext = new MethodResolutionContext();
2222 resolveContext.internalResolution = true;
2223 Symbol sym = resolveConstructor(resolveContext, pos, env, site, argtypes, typeargtypes);
2224 if (sym.kind == MTH) return (MethodSymbol)sym;
2225 else throw new FatalError(
2226 diags.fragment("fatal.err.cant.locate.ctor", site));
2227 }
2229 Symbol findConstructor(DiagnosticPosition pos, Env<AttrContext> env,
2230 Type site, List<Type> argtypes,
2231 List<Type> typeargtypes,
2232 boolean allowBoxing,
2233 boolean useVarargs) {
2234 Symbol sym = findMethod(env, site,
2235 names.init, argtypes,
2236 typeargtypes, allowBoxing,
2237 useVarargs, false);
2238 chk.checkDeprecated(pos, env.info.scope.owner, sym);
2239 return sym;
2240 }
2242 /** Resolve constructor using diamond inference.
2243 * @param pos The position to use for error reporting.
2244 * @param env The environment current at the constructor invocation.
2245 * @param site The type of class for which a constructor is searched.
2246 * The scope of this class has been touched in attribution.
2247 * @param argtypes The types of the constructor invocation's value
2248 * arguments.
2249 * @param typeargtypes The types of the constructor invocation's type
2250 * arguments.
2251 */
2252 Symbol resolveDiamond(DiagnosticPosition pos,
2253 Env<AttrContext> env,
2254 Type site,
2255 List<Type> argtypes,
2256 List<Type> typeargtypes) {
2257 return lookupMethod(env, pos, site.tsym, new BasicLookupHelper(names.init, site, argtypes, typeargtypes) {
2258 @Override
2259 Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) {
2260 return findDiamond(env, site, argtypes, typeargtypes,
2261 phase.isBoxingRequired(),
2262 phase.isVarargsRequired());
2263 }
2264 @Override
2265 Symbol access(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, Symbol sym) {
2266 if (sym.kind >= AMBIGUOUS) {
2267 final JCDiagnostic details = sym.kind == WRONG_MTH ?
2268 ((InapplicableSymbolError)sym).errCandidate().details :
2269 null;
2270 sym = new InapplicableSymbolError(sym.kind, "diamondError", currentResolutionContext) {
2271 @Override
2272 JCDiagnostic getDiagnostic(DiagnosticType dkind, DiagnosticPosition pos,
2273 Symbol location, Type site, Name name, List<Type> argtypes, List<Type> typeargtypes) {
2274 String key = details == null ?
2275 "cant.apply.diamond" :
2276 "cant.apply.diamond.1";
2277 return diags.create(dkind, log.currentSource(), pos, key,
2278 diags.fragment("diamond", site.tsym), details);
2279 }
2280 };
2281 sym = accessMethod(sym, pos, site, names.init, true, argtypes, typeargtypes);
2282 env.info.pendingResolutionPhase = currentResolutionContext.step;
2283 }
2284 return sym;
2285 }
2286 });
2287 }
2289 /** This method scans all the constructor symbol in a given class scope -
2290 * assuming that the original scope contains a constructor of the kind:
2291 * {@code Foo(X x, Y y)}, where X,Y are class type-variables declared in Foo,
2292 * a method check is executed against the modified constructor type:
2293 * {@code <X,Y>Foo<X,Y>(X x, Y y)}. This is crucial in order to enable diamond
2294 * inference. The inferred return type of the synthetic constructor IS
2295 * the inferred type for the diamond operator.
2296 */
2297 private Symbol findDiamond(Env<AttrContext> env,
2298 Type site,
2299 List<Type> argtypes,
2300 List<Type> typeargtypes,
2301 boolean allowBoxing,
2302 boolean useVarargs) {
2303 Symbol bestSoFar = methodNotFound;
2304 for (Scope.Entry e = site.tsym.members().lookup(names.init);
2305 e.scope != null;
2306 e = e.next()) {
2307 final Symbol sym = e.sym;
2308 //- System.out.println(" e " + e.sym);
2309 if (sym.kind == MTH &&
2310 (sym.flags_field & SYNTHETIC) == 0) {
2311 List<Type> oldParams = e.sym.type.hasTag(FORALL) ?
2312 ((ForAll)sym.type).tvars :
2313 List.<Type>nil();
2314 Type constrType = new ForAll(site.tsym.type.getTypeArguments().appendList(oldParams),
2315 types.createMethodTypeWithReturn(sym.type.asMethodType(), site));
2316 MethodSymbol newConstr = new MethodSymbol(sym.flags(), names.init, constrType, site.tsym) {
2317 @Override
2318 public Symbol baseSymbol() {
2319 return sym;
2320 }
2321 };
2322 bestSoFar = selectBest(env, site, argtypes, typeargtypes,
2323 newConstr,
2324 bestSoFar,
2325 allowBoxing,
2326 useVarargs,
2327 false);
2328 }
2329 }
2330 return bestSoFar;
2331 }
2335 /** Resolve operator.
2336 * @param pos The position to use for error reporting.
2337 * @param optag The tag of the operation tree.
2338 * @param env The environment current at the operation.
2339 * @param argtypes The types of the operands.
2340 */
2341 Symbol resolveOperator(DiagnosticPosition pos, JCTree.Tag optag,
2342 Env<AttrContext> env, List<Type> argtypes) {
2343 MethodResolutionContext prevResolutionContext = currentResolutionContext;
2344 try {
2345 currentResolutionContext = new MethodResolutionContext();
2346 Name name = treeinfo.operatorName(optag);
2347 env.info.pendingResolutionPhase = currentResolutionContext.step = BASIC;
2348 Symbol sym = findMethod(env, syms.predefClass.type, name, argtypes,
2349 null, false, false, true);
2350 if (boxingEnabled && sym.kind >= WRONG_MTHS)
2351 env.info.pendingResolutionPhase = currentResolutionContext.step = BOX;
2352 sym = findMethod(env, syms.predefClass.type, name, argtypes,
2353 null, true, false, true);
2354 return accessMethod(sym, pos, env.enclClass.sym.type, name,
2355 false, argtypes, null);
2356 }
2357 finally {
2358 currentResolutionContext = prevResolutionContext;
2359 }
2360 }
2362 /** Resolve operator.
2363 * @param pos The position to use for error reporting.
2364 * @param optag The tag of the operation tree.
2365 * @param env The environment current at the operation.
2366 * @param arg The type of the operand.
2367 */
2368 Symbol resolveUnaryOperator(DiagnosticPosition pos, JCTree.Tag optag, Env<AttrContext> env, Type arg) {
2369 return resolveOperator(pos, optag, env, List.of(arg));
2370 }
2372 /** Resolve binary operator.
2373 * @param pos The position to use for error reporting.
2374 * @param optag The tag of the operation tree.
2375 * @param env The environment current at the operation.
2376 * @param left The types of the left operand.
2377 * @param right The types of the right operand.
2378 */
2379 Symbol resolveBinaryOperator(DiagnosticPosition pos,
2380 JCTree.Tag optag,
2381 Env<AttrContext> env,
2382 Type left,
2383 Type right) {
2384 return resolveOperator(pos, optag, env, List.of(left, right));
2385 }
2387 /**
2388 * Resolution of member references is typically done as a single
2389 * overload resolution step, where the argument types A are inferred from
2390 * the target functional descriptor.
2391 *
2392 * If the member reference is a method reference with a type qualifier,
2393 * a two-step lookup process is performed. The first step uses the
2394 * expected argument list A, while the second step discards the first
2395 * type from A (which is treated as a receiver type).
2396 *
2397 * There are two cases in which inference is performed: (i) if the member
2398 * reference is a constructor reference and the qualifier type is raw - in
2399 * which case diamond inference is used to infer a parameterization for the
2400 * type qualifier; (ii) if the member reference is an unbound reference
2401 * where the type qualifier is raw - in that case, during the unbound lookup
2402 * the receiver argument type is used to infer an instantiation for the raw
2403 * qualifier type.
2404 *
2405 * When a multi-step resolution process is exploited, it is an error
2406 * if two candidates are found (ambiguity).
2407 *
2408 * This routine returns a pair (T,S), where S is the member reference symbol,
2409 * and T is the type of the class in which S is defined. This is necessary as
2410 * the type T might be dynamically inferred (i.e. if constructor reference
2411 * has a raw qualifier).
2412 */
2413 Pair<Symbol, ReferenceLookupHelper> resolveMemberReference(DiagnosticPosition pos,
2414 Env<AttrContext> env,
2415 JCMemberReference referenceTree,
2416 Type site,
2417 Name name, List<Type> argtypes,
2418 List<Type> typeargtypes,
2419 boolean boxingAllowed) {
2420 MethodResolutionPhase maxPhase = boxingAllowed ? VARARITY : BASIC;
2421 //step 1 - bound lookup
2422 ReferenceLookupHelper boundLookupHelper = name.equals(names.init) ?
2423 new ConstructorReferenceLookupHelper(referenceTree, site, argtypes, typeargtypes, maxPhase) :
2424 new MethodReferenceLookupHelper(referenceTree, name, site, argtypes, typeargtypes, maxPhase);
2425 Env<AttrContext> boundEnv = env.dup(env.tree, env.info.dup());
2426 Symbol boundSym = lookupMethod(boundEnv, env.tree.pos(), site.tsym, boundLookupHelper);
2428 //step 2 - unbound lookup
2429 ReferenceLookupHelper unboundLookupHelper = boundLookupHelper.unboundLookup();
2430 Env<AttrContext> unboundEnv = env.dup(env.tree, env.info.dup());
2431 Symbol unboundSym = lookupMethod(unboundEnv, env.tree.pos(), site.tsym, unboundLookupHelper);
2433 //merge results
2434 Pair<Symbol, ReferenceLookupHelper> res;
2435 if (unboundSym.kind != MTH) {
2436 res = new Pair<Symbol, ReferenceLookupHelper>(boundSym, boundLookupHelper);
2437 env.info.pendingResolutionPhase = boundEnv.info.pendingResolutionPhase;
2438 } else if (boundSym.kind == MTH) {
2439 res = new Pair<Symbol, ReferenceLookupHelper>(ambiguityError(boundSym, unboundSym), boundLookupHelper);
2440 env.info.pendingResolutionPhase = boundEnv.info.pendingResolutionPhase;
2441 } else {
2442 res = new Pair<Symbol, ReferenceLookupHelper>(unboundSym, unboundLookupHelper);
2443 env.info.pendingResolutionPhase = unboundEnv.info.pendingResolutionPhase;
2444 }
2446 return res;
2447 }
2449 /**
2450 * Helper for defining custom method-like lookup logic; a lookup helper
2451 * provides hooks for (i) the actual lookup logic and (ii) accessing the
2452 * lookup result (this step might result in compiler diagnostics to be generated)
2453 */
2454 abstract class LookupHelper {
2456 /** name of the symbol to lookup */
2457 Name name;
2459 /** location in which the lookup takes place */
2460 Type site;
2462 /** actual types used during the lookup */
2463 List<Type> argtypes;
2465 /** type arguments used during the lookup */
2466 List<Type> typeargtypes;
2468 /** Max overload resolution phase handled by this helper */
2469 MethodResolutionPhase maxPhase;
2471 LookupHelper(Name name, Type site, List<Type> argtypes, List<Type> typeargtypes, MethodResolutionPhase maxPhase) {
2472 this.name = name;
2473 this.site = site;
2474 this.argtypes = argtypes;
2475 this.typeargtypes = typeargtypes;
2476 this.maxPhase = maxPhase;
2477 }
2479 /**
2480 * Should lookup stop at given phase with given result
2481 */
2482 protected boolean shouldStop(Symbol sym, MethodResolutionPhase phase) {
2483 return phase.ordinal() > maxPhase.ordinal() ||
2484 sym.kind < ERRONEOUS || sym.kind == AMBIGUOUS;
2485 }
2487 /**
2488 * Search for a symbol under a given overload resolution phase - this method
2489 * is usually called several times, once per each overload resolution phase
2490 */
2491 abstract Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase);
2493 /**
2494 * Validate the result of the lookup
2495 */
2496 abstract Symbol access(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, Symbol sym);
2497 }
2499 abstract class BasicLookupHelper extends LookupHelper {
2501 BasicLookupHelper(Name name, Type site, List<Type> argtypes, List<Type> typeargtypes) {
2502 super(name, site, argtypes, typeargtypes, MethodResolutionPhase.VARARITY);
2503 }
2505 @Override
2506 Symbol access(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, Symbol sym) {
2507 if (sym.kind >= AMBIGUOUS) {
2508 //if nothing is found return the 'first' error
2509 sym = accessMethod(sym, pos, location, site, name, true, argtypes, typeargtypes);
2510 }
2511 return sym;
2512 }
2513 }
2515 /**
2516 * Helper class for member reference lookup. A reference lookup helper
2517 * defines the basic logic for member reference lookup; a method gives
2518 * access to an 'unbound' helper used to perform an unbound member
2519 * reference lookup.
2520 */
2521 abstract class ReferenceLookupHelper extends LookupHelper {
2523 /** The member reference tree */
2524 JCMemberReference referenceTree;
2526 ReferenceLookupHelper(JCMemberReference referenceTree, Name name, Type site,
2527 List<Type> argtypes, List<Type> typeargtypes, MethodResolutionPhase maxPhase) {
2528 super(name, site, argtypes, typeargtypes, maxPhase);
2529 this.referenceTree = referenceTree;
2531 }
2533 /**
2534 * Returns an unbound version of this lookup helper. By default, this
2535 * method returns an dummy lookup helper.
2536 */
2537 ReferenceLookupHelper unboundLookup() {
2538 //dummy loopkup helper that always return 'methodNotFound'
2539 return new ReferenceLookupHelper(referenceTree, name, site, argtypes, typeargtypes, maxPhase) {
2540 @Override
2541 ReferenceLookupHelper unboundLookup() {
2542 return this;
2543 }
2544 @Override
2545 Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) {
2546 return methodNotFound;
2547 }
2548 @Override
2549 ReferenceKind referenceKind(Symbol sym) {
2550 Assert.error();
2551 return null;
2552 }
2553 };
2554 }
2556 /**
2557 * Get the kind of the member reference
2558 */
2559 abstract JCMemberReference.ReferenceKind referenceKind(Symbol sym);
2561 Symbol access(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, Symbol sym) {
2562 //skip error reporting
2563 return sym;
2564 }
2565 }
2567 /**
2568 * Helper class for method reference lookup. The lookup logic is based
2569 * upon Resolve.findMethod; in certain cases, this helper class has a
2570 * corresponding unbound helper class (see UnboundMethodReferenceLookupHelper).
2571 * In such cases, non-static lookup results are thrown away.
2572 */
2573 class MethodReferenceLookupHelper extends ReferenceLookupHelper {
2575 MethodReferenceLookupHelper(JCMemberReference referenceTree, Name name, Type site,
2576 List<Type> argtypes, List<Type> typeargtypes, MethodResolutionPhase maxPhase) {
2577 super(referenceTree, name, site, argtypes, typeargtypes, maxPhase);
2578 }
2580 protected Symbol lookupReferenceInternal(Env<AttrContext> env, MethodResolutionPhase phase) {
2581 return findMethod(env, site, name, argtypes, typeargtypes,
2582 phase.isBoxingRequired(), phase.isVarargsRequired(), syms.operatorNames.contains(name));
2583 }
2585 protected Symbol adjustLookupResult(Env<AttrContext> env, Symbol sym) {
2586 return !TreeInfo.isStaticSelector(referenceTree.expr, names) ||
2587 sym.kind != MTH ||
2588 sym.isStatic() ? sym : new StaticError(sym);
2589 }
2591 @Override
2592 final Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) {
2593 return adjustLookupResult(env, lookupReferenceInternal(env, phase));
2594 }
2596 @Override
2597 ReferenceLookupHelper unboundLookup() {
2598 if (TreeInfo.isStaticSelector(referenceTree.expr, names) &&
2599 argtypes.nonEmpty() &&
2600 types.isSubtypeUnchecked(argtypes.head, site)) {
2601 return new UnboundMethodReferenceLookupHelper(referenceTree, name,
2602 site, argtypes, typeargtypes, maxPhase);
2603 } else {
2604 return super.unboundLookup();
2605 }
2606 }
2608 @Override
2609 ReferenceKind referenceKind(Symbol sym) {
2610 if (sym.isStatic()) {
2611 return ReferenceKind.STATIC;
2612 } else {
2613 Name selName = TreeInfo.name(referenceTree.getQualifierExpression());
2614 return selName != null && selName == names._super ?
2615 ReferenceKind.SUPER :
2616 ReferenceKind.BOUND;
2617 }
2618 }
2619 }
2621 /**
2622 * Helper class for unbound method reference lookup. Essentially the same
2623 * as the basic method reference lookup helper; main difference is that static
2624 * lookup results are thrown away. If qualifier type is raw, an attempt to
2625 * infer a parameterized type is made using the first actual argument (that
2626 * would otherwise be ignored during the lookup).
2627 */
2628 class UnboundMethodReferenceLookupHelper extends MethodReferenceLookupHelper {
2630 UnboundMethodReferenceLookupHelper(JCMemberReference referenceTree, Name name, Type site,
2631 List<Type> argtypes, List<Type> typeargtypes, MethodResolutionPhase maxPhase) {
2632 super(referenceTree, name,
2633 site.isRaw() ? types.asSuper(argtypes.head, site.tsym) : site,
2634 argtypes.tail, typeargtypes, maxPhase);
2635 }
2637 @Override
2638 protected Symbol adjustLookupResult(Env<AttrContext> env, Symbol sym) {
2639 return sym.kind != MTH || !sym.isStatic() ? sym : new StaticError(sym);
2640 }
2642 @Override
2643 ReferenceLookupHelper unboundLookup() {
2644 return this;
2645 }
2647 @Override
2648 ReferenceKind referenceKind(Symbol sym) {
2649 return ReferenceKind.UNBOUND;
2650 }
2651 }
2653 /**
2654 * Helper class for constructor reference lookup. The lookup logic is based
2655 * upon either Resolve.findMethod or Resolve.findDiamond - depending on
2656 * whether the constructor reference needs diamond inference (this is the case
2657 * if the qualifier type is raw). A special erroneous symbol is returned
2658 * if the lookup returns the constructor of an inner class and there's no
2659 * enclosing instance in scope.
2660 */
2661 class ConstructorReferenceLookupHelper extends ReferenceLookupHelper {
2663 boolean needsInference;
2665 ConstructorReferenceLookupHelper(JCMemberReference referenceTree, Type site, List<Type> argtypes,
2666 List<Type> typeargtypes, MethodResolutionPhase maxPhase) {
2667 super(referenceTree, names.init, site, argtypes, typeargtypes, maxPhase);
2668 if (site.isRaw()) {
2669 this.site = new ClassType(site.getEnclosingType(), site.tsym.type.getTypeArguments(), site.tsym);
2670 needsInference = true;
2671 }
2672 }
2674 @Override
2675 protected Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) {
2676 Symbol sym = needsInference ?
2677 findDiamond(env, site, argtypes, typeargtypes, phase.isBoxingRequired(), phase.isVarargsRequired()) :
2678 findMethod(env, site, name, argtypes, typeargtypes,
2679 phase.isBoxingRequired(), phase.isVarargsRequired(), syms.operatorNames.contains(name));
2680 return sym.kind != MTH ||
2681 site.getEnclosingType().hasTag(NONE) ||
2682 hasEnclosingInstance(env, site) ?
2683 sym : new InvalidSymbolError(Kinds.MISSING_ENCL, sym, null) {
2684 @Override
2685 JCDiagnostic getDiagnostic(DiagnosticType dkind, DiagnosticPosition pos, Symbol location, Type site, Name name, List<Type> argtypes, List<Type> typeargtypes) {
2686 return diags.create(dkind, log.currentSource(), pos,
2687 "cant.access.inner.cls.constr", site.tsym.name, argtypes, site.getEnclosingType());
2688 }
2689 };
2690 }
2692 @Override
2693 ReferenceKind referenceKind(Symbol sym) {
2694 return site.getEnclosingType().hasTag(NONE) ?
2695 ReferenceKind.TOPLEVEL : ReferenceKind.IMPLICIT_INNER;
2696 }
2697 }
2699 /**
2700 * Main overload resolution routine. On each overload resolution step, a
2701 * lookup helper class is used to perform the method/constructor lookup;
2702 * at the end of the lookup, the helper is used to validate the results
2703 * (this last step might trigger overload resolution diagnostics).
2704 */
2705 Symbol lookupMethod(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, LookupHelper lookupHelper) {
2706 return lookupMethod(env, pos, location, new MethodResolutionContext(), lookupHelper);
2707 }
2709 Symbol lookupMethod(Env<AttrContext> env, DiagnosticPosition pos, Symbol location,
2710 MethodResolutionContext resolveContext, LookupHelper lookupHelper) {
2711 MethodResolutionContext prevResolutionContext = currentResolutionContext;
2712 try {
2713 Symbol bestSoFar = methodNotFound;
2714 currentResolutionContext = resolveContext;
2715 for (MethodResolutionPhase phase : methodResolutionSteps) {
2716 if (!phase.isApplicable(boxingEnabled, varargsEnabled) ||
2717 lookupHelper.shouldStop(bestSoFar, phase)) break;
2718 MethodResolutionPhase prevPhase = currentResolutionContext.step;
2719 Symbol prevBest = bestSoFar;
2720 currentResolutionContext.step = phase;
2721 bestSoFar = phase.mergeResults(bestSoFar, lookupHelper.lookup(env, phase));
2722 env.info.pendingResolutionPhase = (prevBest == bestSoFar) ? prevPhase : phase;
2723 }
2724 return lookupHelper.access(env, pos, location, bestSoFar);
2725 } finally {
2726 currentResolutionContext = prevResolutionContext;
2727 }
2728 }
2730 /**
2731 * Resolve `c.name' where name == this or name == super.
2732 * @param pos The position to use for error reporting.
2733 * @param env The environment current at the expression.
2734 * @param c The qualifier.
2735 * @param name The identifier's name.
2736 */
2737 Symbol resolveSelf(DiagnosticPosition pos,
2738 Env<AttrContext> env,
2739 TypeSymbol c,
2740 Name name) {
2741 Env<AttrContext> env1 = env;
2742 boolean staticOnly = false;
2743 while (env1.outer != null) {
2744 if (isStatic(env1)) staticOnly = true;
2745 if (env1.enclClass.sym == c) {
2746 Symbol sym = env1.info.scope.lookup(name).sym;
2747 if (sym != null) {
2748 if (staticOnly) sym = new StaticError(sym);
2749 return accessBase(sym, pos, env.enclClass.sym.type,
2750 name, true);
2751 }
2752 }
2753 if ((env1.enclClass.sym.flags() & STATIC) != 0) staticOnly = true;
2754 env1 = env1.outer;
2755 }
2756 if (allowDefaultMethods && c.isInterface() &&
2757 name == names._super && !isStatic(env) &&
2758 types.isDirectSuperInterface(c, env.enclClass.sym)) {
2759 //this might be a default super call if one of the superinterfaces is 'c'
2760 for (Type t : pruneInterfaces(env.enclClass.type)) {
2761 if (t.tsym == c) {
2762 env.info.defaultSuperCallSite = t;
2763 return new VarSymbol(0, names._super,
2764 types.asSuper(env.enclClass.type, c), env.enclClass.sym);
2765 }
2766 }
2767 //find a direct superinterface that is a subtype of 'c'
2768 for (Type i : types.interfaces(env.enclClass.type)) {
2769 if (i.tsym.isSubClass(c, types) && i.tsym != c) {
2770 log.error(pos, "illegal.default.super.call", c,
2771 diags.fragment("redundant.supertype", c, i));
2772 return syms.errSymbol;
2773 }
2774 }
2775 Assert.error();
2776 }
2777 log.error(pos, "not.encl.class", c);
2778 return syms.errSymbol;
2779 }
2780 //where
2781 private List<Type> pruneInterfaces(Type t) {
2782 ListBuffer<Type> result = ListBuffer.lb();
2783 for (Type t1 : types.interfaces(t)) {
2784 boolean shouldAdd = true;
2785 for (Type t2 : types.interfaces(t)) {
2786 if (t1 != t2 && types.isSubtypeNoCapture(t2, t1)) {
2787 shouldAdd = false;
2788 }
2789 }
2790 if (shouldAdd) {
2791 result.append(t1);
2792 }
2793 }
2794 return result.toList();
2795 }
2798 /**
2799 * Resolve `c.this' for an enclosing class c that contains the
2800 * named member.
2801 * @param pos The position to use for error reporting.
2802 * @param env The environment current at the expression.
2803 * @param member The member that must be contained in the result.
2804 */
2805 Symbol resolveSelfContaining(DiagnosticPosition pos,
2806 Env<AttrContext> env,
2807 Symbol member,
2808 boolean isSuperCall) {
2809 Symbol sym = resolveSelfContainingInternal(env, member, isSuperCall);
2810 if (sym == null) {
2811 log.error(pos, "encl.class.required", member);
2812 return syms.errSymbol;
2813 } else {
2814 return accessBase(sym, pos, env.enclClass.sym.type, sym.name, true);
2815 }
2816 }
2818 boolean hasEnclosingInstance(Env<AttrContext> env, Type type) {
2819 Symbol encl = resolveSelfContainingInternal(env, type.tsym, false);
2820 return encl != null && encl.kind < ERRONEOUS;
2821 }
2823 private Symbol resolveSelfContainingInternal(Env<AttrContext> env,
2824 Symbol member,
2825 boolean isSuperCall) {
2826 Name name = names._this;
2827 Env<AttrContext> env1 = isSuperCall ? env.outer : env;
2828 boolean staticOnly = false;
2829 if (env1 != null) {
2830 while (env1 != null && env1.outer != null) {
2831 if (isStatic(env1)) staticOnly = true;
2832 if (env1.enclClass.sym.isSubClass(member.owner, types)) {
2833 Symbol sym = env1.info.scope.lookup(name).sym;
2834 if (sym != null) {
2835 if (staticOnly) sym = new StaticError(sym);
2836 return sym;
2837 }
2838 }
2839 if ((env1.enclClass.sym.flags() & STATIC) != 0)
2840 staticOnly = true;
2841 env1 = env1.outer;
2842 }
2843 }
2844 return null;
2845 }
2847 /**
2848 * Resolve an appropriate implicit this instance for t's container.
2849 * JLS 8.8.5.1 and 15.9.2
2850 */
2851 Type resolveImplicitThis(DiagnosticPosition pos, Env<AttrContext> env, Type t) {
2852 return resolveImplicitThis(pos, env, t, false);
2853 }
2855 Type resolveImplicitThis(DiagnosticPosition pos, Env<AttrContext> env, Type t, boolean isSuperCall) {
2856 Type thisType = (((t.tsym.owner.kind & (MTH|VAR)) != 0)
2857 ? resolveSelf(pos, env, t.getEnclosingType().tsym, names._this)
2858 : resolveSelfContaining(pos, env, t.tsym, isSuperCall)).type;
2859 if (env.info.isSelfCall && thisType.tsym == env.enclClass.sym)
2860 log.error(pos, "cant.ref.before.ctor.called", "this");
2861 return thisType;
2862 }
2864 /* ***************************************************************************
2865 * ResolveError classes, indicating error situations when accessing symbols
2866 ****************************************************************************/
2868 //used by TransTypes when checking target type of synthetic cast
2869 public void logAccessErrorInternal(Env<AttrContext> env, JCTree tree, Type type) {
2870 AccessError error = new AccessError(env, env.enclClass.type, type.tsym);
2871 logResolveError(error, tree.pos(), env.enclClass.sym, env.enclClass.type, null, null, null);
2872 }
2873 //where
2874 private void logResolveError(ResolveError error,
2875 DiagnosticPosition pos,
2876 Symbol location,
2877 Type site,
2878 Name name,
2879 List<Type> argtypes,
2880 List<Type> typeargtypes) {
2881 JCDiagnostic d = error.getDiagnostic(JCDiagnostic.DiagnosticType.ERROR,
2882 pos, location, site, name, argtypes, typeargtypes);
2883 if (d != null) {
2884 d.setFlag(DiagnosticFlag.RESOLVE_ERROR);
2885 log.report(d);
2886 }
2887 }
2889 private final LocalizedString noArgs = new LocalizedString("compiler.misc.no.args");
2891 public Object methodArguments(List<Type> argtypes) {
2892 if (argtypes == null || argtypes.isEmpty()) {
2893 return noArgs;
2894 } else {
2895 ListBuffer<Object> diagArgs = ListBuffer.lb();
2896 for (Type t : argtypes) {
2897 if (t.hasTag(DEFERRED)) {
2898 diagArgs.append(((DeferredAttr.DeferredType)t).tree);
2899 } else {
2900 diagArgs.append(t);
2901 }
2902 }
2903 return diagArgs;
2904 }
2905 }
2907 /**
2908 * Root class for resolution errors. Subclass of ResolveError
2909 * represent a different kinds of resolution error - as such they must
2910 * specify how they map into concrete compiler diagnostics.
2911 */
2912 abstract class ResolveError extends Symbol {
2914 /** The name of the kind of error, for debugging only. */
2915 final String debugName;
2917 ResolveError(int kind, String debugName) {
2918 super(kind, 0, null, null, null);
2919 this.debugName = debugName;
2920 }
2922 @Override
2923 public <R, P> R accept(ElementVisitor<R, P> v, P p) {
2924 throw new AssertionError();
2925 }
2927 @Override
2928 public String toString() {
2929 return debugName;
2930 }
2932 @Override
2933 public boolean exists() {
2934 return false;
2935 }
2937 /**
2938 * Create an external representation for this erroneous symbol to be
2939 * used during attribution - by default this returns the symbol of a
2940 * brand new error type which stores the original type found
2941 * during resolution.
2942 *
2943 * @param name the name used during resolution
2944 * @param location the location from which the symbol is accessed
2945 */
2946 protected Symbol access(Name name, TypeSymbol location) {
2947 return types.createErrorType(name, location, syms.errSymbol.type).tsym;
2948 }
2950 /**
2951 * Create a diagnostic representing this resolution error.
2952 *
2953 * @param dkind The kind of the diagnostic to be created (e.g error).
2954 * @param pos The position to be used for error reporting.
2955 * @param site The original type from where the selection took place.
2956 * @param name The name of the symbol to be resolved.
2957 * @param argtypes The invocation's value arguments,
2958 * if we looked for a method.
2959 * @param typeargtypes The invocation's type arguments,
2960 * if we looked for a method.
2961 */
2962 abstract JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind,
2963 DiagnosticPosition pos,
2964 Symbol location,
2965 Type site,
2966 Name name,
2967 List<Type> argtypes,
2968 List<Type> typeargtypes);
2969 }
2971 /**
2972 * This class is the root class of all resolution errors caused by
2973 * an invalid symbol being found during resolution.
2974 */
2975 abstract class InvalidSymbolError extends ResolveError {
2977 /** The invalid symbol found during resolution */
2978 Symbol sym;
2980 InvalidSymbolError(int kind, Symbol sym, String debugName) {
2981 super(kind, debugName);
2982 this.sym = sym;
2983 }
2985 @Override
2986 public boolean exists() {
2987 return true;
2988 }
2990 @Override
2991 public String toString() {
2992 return super.toString() + " wrongSym=" + sym;
2993 }
2995 @Override
2996 public Symbol access(Name name, TypeSymbol location) {
2997 if (sym.kind >= AMBIGUOUS)
2998 return ((ResolveError)sym).access(name, location);
2999 else if ((sym.kind & ERRONEOUS) == 0 && (sym.kind & TYP) != 0)
3000 return types.createErrorType(name, location, sym.type).tsym;
3001 else
3002 return sym;
3003 }
3004 }
3006 /**
3007 * InvalidSymbolError error class indicating that a symbol matching a
3008 * given name does not exists in a given site.
3009 */
3010 class SymbolNotFoundError extends ResolveError {
3012 SymbolNotFoundError(int kind) {
3013 super(kind, "symbol not found error");
3014 }
3016 @Override
3017 JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind,
3018 DiagnosticPosition pos,
3019 Symbol location,
3020 Type site,
3021 Name name,
3022 List<Type> argtypes,
3023 List<Type> typeargtypes) {
3024 argtypes = argtypes == null ? List.<Type>nil() : argtypes;
3025 typeargtypes = typeargtypes == null ? List.<Type>nil() : typeargtypes;
3026 if (name == names.error)
3027 return null;
3029 if (syms.operatorNames.contains(name)) {
3030 boolean isUnaryOp = argtypes.size() == 1;
3031 String key = argtypes.size() == 1 ?
3032 "operator.cant.be.applied" :
3033 "operator.cant.be.applied.1";
3034 Type first = argtypes.head;
3035 Type second = !isUnaryOp ? argtypes.tail.head : null;
3036 return diags.create(dkind, log.currentSource(), pos,
3037 key, name, first, second);
3038 }
3039 boolean hasLocation = false;
3040 if (location == null) {
3041 location = site.tsym;
3042 }
3043 if (!location.name.isEmpty()) {
3044 if (location.kind == PCK && !site.tsym.exists()) {
3045 return diags.create(dkind, log.currentSource(), pos,
3046 "doesnt.exist", location);
3047 }
3048 hasLocation = !location.name.equals(names._this) &&
3049 !location.name.equals(names._super);
3050 }
3051 boolean isConstructor = kind == ABSENT_MTH && name == names.init;
3052 KindName kindname = isConstructor ? KindName.CONSTRUCTOR : absentKind(kind);
3053 Name idname = isConstructor ? site.tsym.name : name;
3054 String errKey = getErrorKey(kindname, typeargtypes.nonEmpty(), hasLocation);
3055 if (hasLocation) {
3056 return diags.create(dkind, log.currentSource(), pos,
3057 errKey, kindname, idname, //symbol kindname, name
3058 typeargtypes, args(argtypes), //type parameters and arguments (if any)
3059 getLocationDiag(location, site)); //location kindname, type
3060 }
3061 else {
3062 return diags.create(dkind, log.currentSource(), pos,
3063 errKey, kindname, idname, //symbol kindname, name
3064 typeargtypes, args(argtypes)); //type parameters and arguments (if any)
3065 }
3066 }
3067 //where
3068 private Object args(List<Type> args) {
3069 return args.isEmpty() ? args : methodArguments(args);
3070 }
3072 private String getErrorKey(KindName kindname, boolean hasTypeArgs, boolean hasLocation) {
3073 String key = "cant.resolve";
3074 String suffix = hasLocation ? ".location" : "";
3075 switch (kindname) {
3076 case METHOD:
3077 case CONSTRUCTOR: {
3078 suffix += ".args";
3079 suffix += hasTypeArgs ? ".params" : "";
3080 }
3081 }
3082 return key + suffix;
3083 }
3084 private JCDiagnostic getLocationDiag(Symbol location, Type site) {
3085 if (location.kind == VAR) {
3086 return diags.fragment("location.1",
3087 kindName(location),
3088 location,
3089 location.type);
3090 } else {
3091 return diags.fragment("location",
3092 typeKindName(site),
3093 site,
3094 null);
3095 }
3096 }
3097 }
3099 /**
3100 * InvalidSymbolError error class indicating that a given symbol
3101 * (either a method, a constructor or an operand) is not applicable
3102 * given an actual arguments/type argument list.
3103 */
3104 class InapplicableSymbolError extends ResolveError {
3106 protected MethodResolutionContext resolveContext;
3108 InapplicableSymbolError(MethodResolutionContext context) {
3109 this(WRONG_MTH, "inapplicable symbol error", context);
3110 }
3112 protected InapplicableSymbolError(int kind, String debugName, MethodResolutionContext context) {
3113 super(kind, debugName);
3114 this.resolveContext = context;
3115 }
3117 @Override
3118 public String toString() {
3119 return super.toString();
3120 }
3122 @Override
3123 public boolean exists() {
3124 return true;
3125 }
3127 @Override
3128 JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind,
3129 DiagnosticPosition pos,
3130 Symbol location,
3131 Type site,
3132 Name name,
3133 List<Type> argtypes,
3134 List<Type> typeargtypes) {
3135 if (name == names.error)
3136 return null;
3138 if (syms.operatorNames.contains(name)) {
3139 boolean isUnaryOp = argtypes.size() == 1;
3140 String key = argtypes.size() == 1 ?
3141 "operator.cant.be.applied" :
3142 "operator.cant.be.applied.1";
3143 Type first = argtypes.head;
3144 Type second = !isUnaryOp ? argtypes.tail.head : null;
3145 return diags.create(dkind, log.currentSource(), pos,
3146 key, name, first, second);
3147 }
3148 else {
3149 Candidate c = errCandidate();
3150 Symbol ws = c.sym.asMemberOf(site, types);
3151 return diags.create(dkind, log.currentSource(), pos,
3152 "cant.apply.symbol",
3153 kindName(ws),
3154 ws.name == names.init ? ws.owner.name : ws.name,
3155 methodArguments(ws.type.getParameterTypes()),
3156 methodArguments(argtypes),
3157 kindName(ws.owner),
3158 ws.owner.type,
3159 c.details);
3160 }
3161 }
3163 @Override
3164 public Symbol access(Name name, TypeSymbol location) {
3165 return types.createErrorType(name, location, syms.errSymbol.type).tsym;
3166 }
3168 private Candidate errCandidate() {
3169 Candidate bestSoFar = null;
3170 for (Candidate c : resolveContext.candidates) {
3171 if (c.isApplicable()) continue;
3172 bestSoFar = c;
3173 }
3174 Assert.checkNonNull(bestSoFar);
3175 return bestSoFar;
3176 }
3177 }
3179 /**
3180 * ResolveError error class indicating that a set of symbols
3181 * (either methods, constructors or operands) is not applicable
3182 * given an actual arguments/type argument list.
3183 */
3184 class InapplicableSymbolsError extends InapplicableSymbolError {
3186 InapplicableSymbolsError(MethodResolutionContext context) {
3187 super(WRONG_MTHS, "inapplicable symbols", context);
3188 }
3190 @Override
3191 JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind,
3192 DiagnosticPosition pos,
3193 Symbol location,
3194 Type site,
3195 Name name,
3196 List<Type> argtypes,
3197 List<Type> typeargtypes) {
3198 if (!resolveContext.candidates.isEmpty()) {
3199 JCDiagnostic err = diags.create(dkind,
3200 log.currentSource(),
3201 pos,
3202 "cant.apply.symbols",
3203 name == names.init ? KindName.CONSTRUCTOR : absentKind(kind),
3204 name == names.init ? site.tsym.name : name,
3205 methodArguments(argtypes));
3206 return new JCDiagnostic.MultilineDiagnostic(err, candidateDetails(site));
3207 } else {
3208 return new SymbolNotFoundError(ABSENT_MTH).getDiagnostic(dkind, pos,
3209 location, site, name, argtypes, typeargtypes);
3210 }
3211 }
3213 //where
3214 List<JCDiagnostic> candidateDetails(Type site) {
3215 Map<Symbol, JCDiagnostic> details = new LinkedHashMap<Symbol, JCDiagnostic>();
3216 for (Candidate c : resolveContext.candidates) {
3217 if (c.isApplicable()) continue;
3218 JCDiagnostic detailDiag = diags.fragment("inapplicable.method",
3219 Kinds.kindName(c.sym),
3220 c.sym.location(site, types),
3221 c.sym.asMemberOf(site, types),
3222 c.details);
3223 details.put(c.sym, detailDiag);
3224 }
3225 return List.from(details.values());
3226 }
3227 }
3229 /**
3230 * An InvalidSymbolError error class indicating that a symbol is not
3231 * accessible from a given site
3232 */
3233 class AccessError extends InvalidSymbolError {
3235 private Env<AttrContext> env;
3236 private Type site;
3238 AccessError(Symbol sym) {
3239 this(null, null, sym);
3240 }
3242 AccessError(Env<AttrContext> env, Type site, Symbol sym) {
3243 super(HIDDEN, sym, "access error");
3244 this.env = env;
3245 this.site = site;
3246 if (debugResolve)
3247 log.error("proc.messager", sym + " @ " + site + " is inaccessible.");
3248 }
3250 @Override
3251 public boolean exists() {
3252 return false;
3253 }
3255 @Override
3256 JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind,
3257 DiagnosticPosition pos,
3258 Symbol location,
3259 Type site,
3260 Name name,
3261 List<Type> argtypes,
3262 List<Type> typeargtypes) {
3263 if (sym.owner.type.hasTag(ERROR))
3264 return null;
3266 if (sym.name == names.init && sym.owner != site.tsym) {
3267 return new SymbolNotFoundError(ABSENT_MTH).getDiagnostic(dkind,
3268 pos, location, site, name, argtypes, typeargtypes);
3269 }
3270 else if ((sym.flags() & PUBLIC) != 0
3271 || (env != null && this.site != null
3272 && !isAccessible(env, this.site))) {
3273 return diags.create(dkind, log.currentSource(),
3274 pos, "not.def.access.class.intf.cant.access",
3275 sym, sym.location());
3276 }
3277 else if ((sym.flags() & (PRIVATE | PROTECTED)) != 0) {
3278 return diags.create(dkind, log.currentSource(),
3279 pos, "report.access", sym,
3280 asFlagSet(sym.flags() & (PRIVATE | PROTECTED)),
3281 sym.location());
3282 }
3283 else {
3284 return diags.create(dkind, log.currentSource(),
3285 pos, "not.def.public.cant.access", sym, sym.location());
3286 }
3287 }
3288 }
3290 /**
3291 * InvalidSymbolError error class indicating that an instance member
3292 * has erroneously been accessed from a static context.
3293 */
3294 class StaticError extends InvalidSymbolError {
3296 StaticError(Symbol sym) {
3297 super(STATICERR, sym, "static error");
3298 }
3300 @Override
3301 JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind,
3302 DiagnosticPosition pos,
3303 Symbol location,
3304 Type site,
3305 Name name,
3306 List<Type> argtypes,
3307 List<Type> typeargtypes) {
3308 Symbol errSym = ((sym.kind == TYP && sym.type.hasTag(CLASS))
3309 ? types.erasure(sym.type).tsym
3310 : sym);
3311 return diags.create(dkind, log.currentSource(), pos,
3312 "non-static.cant.be.ref", kindName(sym), errSym);
3313 }
3314 }
3316 /**
3317 * InvalidSymbolError error class indicating that a pair of symbols
3318 * (either methods, constructors or operands) are ambiguous
3319 * given an actual arguments/type argument list.
3320 */
3321 class AmbiguityError extends InvalidSymbolError {
3323 /** The other maximally specific symbol */
3324 Symbol sym2;
3326 AmbiguityError(Symbol sym1, Symbol sym2) {
3327 super(AMBIGUOUS, sym1, "ambiguity error");
3328 this.sym2 = sym2;
3329 }
3331 @Override
3332 JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind,
3333 DiagnosticPosition pos,
3334 Symbol location,
3335 Type site,
3336 Name name,
3337 List<Type> argtypes,
3338 List<Type> typeargtypes) {
3339 AmbiguityError pair = this;
3340 while (true) {
3341 if (pair.sym.kind == AMBIGUOUS)
3342 pair = (AmbiguityError)pair.sym;
3343 else if (pair.sym2.kind == AMBIGUOUS)
3344 pair = (AmbiguityError)pair.sym2;
3345 else break;
3346 }
3347 Name sname = pair.sym.name;
3348 if (sname == names.init) sname = pair.sym.owner.name;
3349 return diags.create(dkind, log.currentSource(),
3350 pos, "ref.ambiguous", sname,
3351 kindName(pair.sym),
3352 pair.sym,
3353 pair.sym.location(site, types),
3354 kindName(pair.sym2),
3355 pair.sym2,
3356 pair.sym2.location(site, types));
3357 }
3358 }
3360 enum MethodResolutionPhase {
3361 BASIC(false, false),
3362 BOX(true, false),
3363 VARARITY(true, true) {
3364 @Override
3365 public Symbol mergeResults(Symbol bestSoFar, Symbol sym) {
3366 switch (sym.kind) {
3367 case WRONG_MTH:
3368 return (bestSoFar.kind == WRONG_MTH || bestSoFar.kind == WRONG_MTHS) ?
3369 bestSoFar :
3370 sym;
3371 case ABSENT_MTH:
3372 return bestSoFar;
3373 default:
3374 return sym;
3375 }
3376 }
3377 };
3379 final boolean isBoxingRequired;
3380 final boolean isVarargsRequired;
3382 MethodResolutionPhase(boolean isBoxingRequired, boolean isVarargsRequired) {
3383 this.isBoxingRequired = isBoxingRequired;
3384 this.isVarargsRequired = isVarargsRequired;
3385 }
3387 public boolean isBoxingRequired() {
3388 return isBoxingRequired;
3389 }
3391 public boolean isVarargsRequired() {
3392 return isVarargsRequired;
3393 }
3395 public boolean isApplicable(boolean boxingEnabled, boolean varargsEnabled) {
3396 return (varargsEnabled || !isVarargsRequired) &&
3397 (boxingEnabled || !isBoxingRequired);
3398 }
3400 public Symbol mergeResults(Symbol prev, Symbol sym) {
3401 return sym;
3402 }
3403 }
3405 final List<MethodResolutionPhase> methodResolutionSteps = List.of(BASIC, BOX, VARARITY);
3407 /**
3408 * A resolution context is used to keep track of intermediate results of
3409 * overload resolution, such as list of method that are not applicable
3410 * (used to generate more precise diagnostics) and so on. Resolution contexts
3411 * can be nested - this means that when each overload resolution routine should
3412 * work within the resolution context it created.
3413 */
3414 class MethodResolutionContext {
3416 private List<Candidate> candidates = List.nil();
3418 MethodResolutionPhase step = null;
3420 private boolean internalResolution = false;
3421 private DeferredAttr.AttrMode attrMode = DeferredAttr.AttrMode.SPECULATIVE;
3423 void addInapplicableCandidate(Symbol sym, JCDiagnostic details) {
3424 Candidate c = new Candidate(currentResolutionContext.step, sym, details, null);
3425 candidates = candidates.append(c);
3426 }
3428 void addApplicableCandidate(Symbol sym, Type mtype) {
3429 Candidate c = new Candidate(currentResolutionContext.step, sym, null, mtype);
3430 candidates = candidates.append(c);
3431 }
3433 DeferredAttrContext deferredAttrContext(Symbol sym, InferenceContext inferenceContext) {
3434 return deferredAttr.new DeferredAttrContext(attrMode, sym, step, inferenceContext);
3435 }
3437 /**
3438 * This class represents an overload resolution candidate. There are two
3439 * kinds of candidates: applicable methods and inapplicable methods;
3440 * applicable methods have a pointer to the instantiated method type,
3441 * while inapplicable candidates contain further details about the
3442 * reason why the method has been considered inapplicable.
3443 */
3444 class Candidate {
3446 final MethodResolutionPhase step;
3447 final Symbol sym;
3448 final JCDiagnostic details;
3449 final Type mtype;
3451 private Candidate(MethodResolutionPhase step, Symbol sym, JCDiagnostic details, Type mtype) {
3452 this.step = step;
3453 this.sym = sym;
3454 this.details = details;
3455 this.mtype = mtype;
3456 }
3458 @Override
3459 public boolean equals(Object o) {
3460 if (o instanceof Candidate) {
3461 Symbol s1 = this.sym;
3462 Symbol s2 = ((Candidate)o).sym;
3463 if ((s1 != s2 &&
3464 (s1.overrides(s2, s1.owner.type.tsym, types, false) ||
3465 (s2.overrides(s1, s2.owner.type.tsym, types, false)))) ||
3466 ((s1.isConstructor() || s2.isConstructor()) && s1.owner != s2.owner))
3467 return true;
3468 }
3469 return false;
3470 }
3472 boolean isApplicable() {
3473 return mtype != null;
3474 }
3475 }
3477 DeferredAttr.AttrMode attrMode() {
3478 return attrMode;
3479 }
3481 boolean internal() {
3482 return internalResolution;
3483 }
3484 }
3486 MethodResolutionContext currentResolutionContext = null;
3487 }