23 * questions. |
23 * questions. |
24 */ |
24 */ |
25 |
25 |
26 package com.sun.tools.javac.comp; |
26 package com.sun.tools.javac.comp; |
27 |
27 |
28 import com.sun.tools.javac.util.*; |
28 import com.sun.tools.javac.api.Formattable.LocalizedString; |
29 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; |
|
30 import com.sun.tools.javac.code.*; |
29 import com.sun.tools.javac.code.*; |
|
30 import com.sun.tools.javac.code.Type.*; |
|
31 import com.sun.tools.javac.code.Symbol.*; |
31 import com.sun.tools.javac.jvm.*; |
32 import com.sun.tools.javac.jvm.*; |
32 import com.sun.tools.javac.tree.*; |
33 import com.sun.tools.javac.tree.*; |
33 import com.sun.tools.javac.api.Formattable.LocalizedString; |
|
34 import static com.sun.tools.javac.comp.Resolve.MethodResolutionPhase.*; |
|
35 |
|
36 import com.sun.tools.javac.code.Type.*; |
|
37 import com.sun.tools.javac.code.Symbol.*; |
|
38 import com.sun.tools.javac.tree.JCTree.*; |
34 import com.sun.tools.javac.tree.JCTree.*; |
|
35 import com.sun.tools.javac.util.*; |
|
36 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag; |
|
37 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; |
|
38 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticType; |
|
39 |
|
40 import java.util.Arrays; |
|
41 import java.util.Collection; |
|
42 import java.util.EnumSet; |
|
43 import java.util.HashMap; |
|
44 import java.util.HashSet; |
|
45 import java.util.LinkedHashMap; |
|
46 import java.util.Map; |
|
47 import java.util.Set; |
|
48 |
|
49 import javax.lang.model.element.ElementVisitor; |
39 |
50 |
40 import static com.sun.tools.javac.code.Flags.*; |
51 import static com.sun.tools.javac.code.Flags.*; |
41 import static com.sun.tools.javac.code.Kinds.*; |
52 import static com.sun.tools.javac.code.Kinds.*; |
42 import static com.sun.tools.javac.code.TypeTags.*; |
53 import static com.sun.tools.javac.code.TypeTags.*; |
43 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag; |
54 import static com.sun.tools.javac.comp.Resolve.MethodResolutionPhase.*; |
44 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticType; |
|
45 import javax.lang.model.element.ElementVisitor; |
|
46 |
|
47 import java.util.Map; |
|
48 import java.util.Set; |
|
49 import java.util.HashMap; |
|
50 import java.util.HashSet; |
|
51 |
55 |
52 /** Helper class for name resolution, used mostly by the attribution phase. |
56 /** Helper class for name resolution, used mostly by the attribution phase. |
53 * |
57 * |
54 * <p><b>This is NOT part of any supported API. |
58 * <p><b>This is NOT part of any supported API. |
55 * If you write code that depends on this, you do so at your own risk. |
59 * If you write code that depends on this, you do so at your own risk. |
71 JCDiagnostic.Factory diags; |
75 JCDiagnostic.Factory diags; |
72 public final boolean boxingEnabled; // = source.allowBoxing(); |
76 public final boolean boxingEnabled; // = source.allowBoxing(); |
73 public final boolean varargsEnabled; // = source.allowVarargs(); |
77 public final boolean varargsEnabled; // = source.allowVarargs(); |
74 public final boolean allowMethodHandles; |
78 public final boolean allowMethodHandles; |
75 private final boolean debugResolve; |
79 private final boolean debugResolve; |
|
80 final EnumSet<VerboseResolutionMode> verboseResolutionMode; |
76 |
81 |
77 Scope polymorphicSignatureScope; |
82 Scope polymorphicSignatureScope; |
|
83 |
|
84 enum VerboseResolutionMode { |
|
85 SUCCESS("success"), |
|
86 FAILURE("failure"), |
|
87 APPLICABLE("applicable"), |
|
88 INAPPLICABLE("inapplicable"), |
|
89 DEFERRED_INST("deferred-inference"), |
|
90 PREDEF("predef"), |
|
91 OBJECT_INIT("object-init"), |
|
92 INTERNAL("internal"); |
|
93 |
|
94 String opt; |
|
95 |
|
96 private VerboseResolutionMode(String opt) { |
|
97 this.opt = opt; |
|
98 } |
|
99 |
|
100 static EnumSet<VerboseResolutionMode> getVerboseResolutionMode(Options opts) { |
|
101 String s = opts.get("verboseResolution"); |
|
102 EnumSet<VerboseResolutionMode> res = EnumSet.noneOf(VerboseResolutionMode.class); |
|
103 if (s == null) return res; |
|
104 if (s.contains("all")) { |
|
105 res = EnumSet.allOf(VerboseResolutionMode.class); |
|
106 } |
|
107 Collection<String> args = Arrays.asList(s.split(",")); |
|
108 for (VerboseResolutionMode mode : values()) { |
|
109 if (args.contains(mode.opt)) { |
|
110 res.add(mode); |
|
111 } else if (args.contains("-" + mode.opt)) { |
|
112 res.remove(mode); |
|
113 } |
|
114 } |
|
115 return res; |
|
116 } |
|
117 } |
78 |
118 |
79 public static Resolve instance(Context context) { |
119 public static Resolve instance(Context context) { |
80 Resolve instance = context.get(resolveKey); |
120 Resolve instance = context.get(resolveKey); |
81 if (instance == null) |
121 if (instance == null) |
82 instance = new Resolve(context); |
122 instance = new Resolve(context); |
109 Source source = Source.instance(context); |
149 Source source = Source.instance(context); |
110 boxingEnabled = source.allowBoxing(); |
150 boxingEnabled = source.allowBoxing(); |
111 varargsEnabled = source.allowVarargs(); |
151 varargsEnabled = source.allowVarargs(); |
112 Options options = Options.instance(context); |
152 Options options = Options.instance(context); |
113 debugResolve = options.isSet("debugresolve"); |
153 debugResolve = options.isSet("debugresolve"); |
|
154 verboseResolutionMode = VerboseResolutionMode.getVerboseResolutionMode(options); |
114 Target target = Target.instance(context); |
155 Target target = Target.instance(context); |
115 allowMethodHandles = target.hasMethodHandles(); |
156 allowMethodHandles = target.hasMethodHandles(); |
116 polymorphicSignatureScope = new Scope(syms.noSymbol); |
157 polymorphicSignatureScope = new Scope(syms.noSymbol); |
117 |
158 |
118 inapplicableMethodException = new InapplicableMethodException(diags); |
159 inapplicableMethodException = new InapplicableMethodException(diags); |
682 boolean operator) { |
723 boolean operator) { |
683 if (sym.kind == ERR) return bestSoFar; |
724 if (sym.kind == ERR) return bestSoFar; |
684 if (!sym.isInheritedIn(site.tsym, types)) return bestSoFar; |
725 if (!sym.isInheritedIn(site.tsym, types)) return bestSoFar; |
685 Assert.check(sym.kind < AMBIGUOUS); |
726 Assert.check(sym.kind < AMBIGUOUS); |
686 try { |
727 try { |
687 rawInstantiate(env, site, sym, argtypes, typeargtypes, |
728 Type mt = rawInstantiate(env, site, sym, argtypes, typeargtypes, |
688 allowBoxing, useVarargs, Warner.noWarnings); |
729 allowBoxing, useVarargs, Warner.noWarnings); |
|
730 if (!operator) addVerboseApplicableCandidateDiag(sym ,mt); |
689 } catch (InapplicableMethodException ex) { |
731 } catch (InapplicableMethodException ex) { |
|
732 if (!operator) addVerboseInapplicableCandidateDiag(sym, ex.getDiagnostic()); |
690 switch (bestSoFar.kind) { |
733 switch (bestSoFar.kind) { |
691 case ABSENT_MTH: |
734 case ABSENT_MTH: |
692 return wrongMethod.setWrongSym(sym, ex.getDiagnostic()); |
735 return wrongMethod.setWrongSym(sym, ex.getDiagnostic()); |
693 case WRONG_MTH: |
736 case WRONG_MTH: |
694 if (operator) return bestSoFar; |
737 if (operator) return bestSoFar; |
707 return (bestSoFar.kind > AMBIGUOUS) |
750 return (bestSoFar.kind > AMBIGUOUS) |
708 ? sym |
751 ? sym |
709 : mostSpecific(sym, bestSoFar, env, site, |
752 : mostSpecific(sym, bestSoFar, env, site, |
710 allowBoxing && operator, useVarargs); |
753 allowBoxing && operator, useVarargs); |
711 } |
754 } |
|
755 //where |
|
756 void addVerboseApplicableCandidateDiag(Symbol sym, Type inst) { |
|
757 if (!verboseResolutionMode.contains(VerboseResolutionMode.APPLICABLE)) |
|
758 return; |
|
759 |
|
760 JCDiagnostic subDiag = null; |
|
761 if (inst.getReturnType().tag == FORALL) { |
|
762 Type diagType = types.createMethodTypeWithReturn(inst.asMethodType(), |
|
763 ((ForAll)inst.getReturnType()).qtype); |
|
764 subDiag = diags.fragment("partial.inst.sig", diagType); |
|
765 } else if (sym.type.tag == FORALL) { |
|
766 subDiag = diags.fragment("full.inst.sig", inst.asMethodType()); |
|
767 } |
|
768 |
|
769 String key = subDiag == null ? |
|
770 "applicable.method.found" : |
|
771 "applicable.method.found.1"; |
|
772 |
|
773 verboseResolutionCandidateDiags.put(sym, |
|
774 diags.fragment(key, verboseResolutionCandidateDiags.size(), sym, subDiag)); |
|
775 } |
|
776 |
|
777 void addVerboseInapplicableCandidateDiag(Symbol sym, JCDiagnostic subDiag) { |
|
778 if (!verboseResolutionMode.contains(VerboseResolutionMode.INAPPLICABLE)) |
|
779 return; |
|
780 verboseResolutionCandidateDiags.put(sym, |
|
781 diags.fragment("not.applicable.method.found", verboseResolutionCandidateDiags.size(), sym, subDiag)); |
|
782 } |
712 |
783 |
713 /* Return the most specific of the two methods for a call, |
784 /* Return the most specific of the two methods for a call, |
714 * given that both are accessible and applicable. |
785 * given that both are accessible and applicable. |
715 * @param m1 A new candidate for most specific. |
786 * @param m1 A new candidate for most specific. |
716 * @param m2 The previous most specific candidate. |
787 * @param m2 The previous most specific candidate. |
974 bestSoFar = concrete; |
1048 bestSoFar = concrete; |
975 } |
1049 } |
976 } |
1050 } |
977 return bestSoFar; |
1051 return bestSoFar; |
978 } |
1052 } |
|
1053 //where |
|
1054 void reportVerboseResolutionDiagnostic(DiagnosticPosition dpos, Name name, Type site, List<Type> argtypes, List<Type> typeargtypes, Symbol bestSoFar) { |
|
1055 boolean success = bestSoFar.kind < ERRONEOUS; |
|
1056 |
|
1057 if (success && !verboseResolutionMode.contains(VerboseResolutionMode.SUCCESS)) { |
|
1058 return; |
|
1059 } else if (!success && !verboseResolutionMode.contains(VerboseResolutionMode.FAILURE)) { |
|
1060 return; |
|
1061 } |
|
1062 |
|
1063 if (bestSoFar.name == names.init && |
|
1064 bestSoFar.owner == syms.objectType.tsym && |
|
1065 !verboseResolutionMode.contains(VerboseResolutionMode.OBJECT_INIT)) { |
|
1066 return; //skip diags for Object constructor resolution |
|
1067 } else if (site == syms.predefClass.type && !verboseResolutionMode.contains(VerboseResolutionMode.PREDEF)) { |
|
1068 return; //skip spurious diags for predef symbols (i.e. operators) |
|
1069 } else if (internalResolution && !verboseResolutionMode.contains(VerboseResolutionMode.INTERNAL)) { |
|
1070 return; |
|
1071 } |
|
1072 |
|
1073 int pos = 0; |
|
1074 for (Symbol s : verboseResolutionCandidateDiags.keySet()) { |
|
1075 if (s == bestSoFar) break; |
|
1076 pos++; |
|
1077 } |
|
1078 String key = success ? "verbose.resolve.multi" : "verbose.resolve.multi.1"; |
|
1079 JCDiagnostic main = diags.note(log.currentSource(), dpos, key, name, site.tsym, pos, currentStep, |
|
1080 methodArguments(argtypes), methodArguments(typeargtypes)); |
|
1081 JCDiagnostic d = new JCDiagnostic.MultilineDiagnostic(main, List.from(verboseResolutionCandidateDiags.values().toArray(new JCDiagnostic[verboseResolutionCandidateDiags.size()]))); |
|
1082 log.report(d); |
|
1083 } |
979 |
1084 |
980 /** Find unqualified method matching given name, type and value arguments. |
1085 /** Find unqualified method matching given name, type and value arguments. |
981 * @param env The current environment. |
1086 * @param env The current environment. |
982 * @param name The method's name. |
1087 * @param name The method's name. |
983 * @param argtypes The method's value arguments. |
1088 * @param argtypes The method's value arguments. |
1542 */ |
1647 */ |
1543 public MethodSymbol resolveInternalMethod(DiagnosticPosition pos, Env<AttrContext> env, |
1648 public MethodSymbol resolveInternalMethod(DiagnosticPosition pos, Env<AttrContext> env, |
1544 Type site, Name name, |
1649 Type site, Name name, |
1545 List<Type> argtypes, |
1650 List<Type> argtypes, |
1546 List<Type> typeargtypes) { |
1651 List<Type> typeargtypes) { |
1547 Symbol sym = resolveQualifiedMethod( |
1652 boolean prevInternal = internalResolution; |
1548 pos, env, site.tsym, site, name, argtypes, typeargtypes); |
1653 try { |
1549 if (sym.kind == MTH) return (MethodSymbol)sym; |
1654 internalResolution = true; |
1550 else throw new FatalError( |
1655 Symbol sym = resolveQualifiedMethod( |
1551 diags.fragment("fatal.err.cant.locate.meth", |
1656 pos, env, site.tsym, site, name, argtypes, typeargtypes); |
1552 name)); |
1657 if (sym.kind == MTH) return (MethodSymbol)sym; |
|
1658 else throw new FatalError( |
|
1659 diags.fragment("fatal.err.cant.locate.meth", |
|
1660 name)); |
|
1661 } |
|
1662 finally { |
|
1663 internalResolution = prevInternal; |
|
1664 } |
1553 } |
1665 } |
1554 |
1666 |
1555 /** Resolve constructor. |
1667 /** Resolve constructor. |
1556 * @param pos The position to use for error reporting. |
1668 * @param pos The position to use for error reporting. |
1557 * @param env The environment current at the constructor invocation. |
1669 * @param env The environment current at the constructor invocation. |
1828 } |
1940 } |
1829 |
1941 |
1830 private final LocalizedString noArgs = new LocalizedString("compiler.misc.no.args"); |
1942 private final LocalizedString noArgs = new LocalizedString("compiler.misc.no.args"); |
1831 |
1943 |
1832 public Object methodArguments(List<Type> argtypes) { |
1944 public Object methodArguments(List<Type> argtypes) { |
1833 return argtypes.isEmpty() ? noArgs : argtypes; |
1945 return argtypes == null || argtypes.isEmpty() ? noArgs : argtypes; |
1834 } |
1946 } |
1835 |
1947 |
1836 /** |
1948 /** |
1837 * Root class for resolution errors. Subclass of ResolveError |
1949 * Root class for resolution errors. Subclass of ResolveError |
1838 * represent a different kinds of resolution error - as such they must |
1950 * represent a different kinds of resolution error - as such they must |
2375 } |
2487 } |
2376 |
2488 |
2377 private Map<MethodResolutionPhase, Symbol> methodResolutionCache = |
2489 private Map<MethodResolutionPhase, Symbol> methodResolutionCache = |
2378 new HashMap<MethodResolutionPhase, Symbol>(MethodResolutionPhase.values().length); |
2490 new HashMap<MethodResolutionPhase, Symbol>(MethodResolutionPhase.values().length); |
2379 |
2491 |
|
2492 private Map<Symbol, JCDiagnostic> verboseResolutionCandidateDiags = |
|
2493 new LinkedHashMap<Symbol, JCDiagnostic>(); |
|
2494 |
2380 final List<MethodResolutionPhase> methodResolutionSteps = List.of(BASIC, BOX, VARARITY); |
2495 final List<MethodResolutionPhase> methodResolutionSteps = List.of(BASIC, BOX, VARARITY); |
2381 |
2496 |
2382 private MethodResolutionPhase currentStep = null; |
2497 private MethodResolutionPhase currentStep = null; |
|
2498 |
|
2499 private boolean internalResolution = false; |
2383 |
2500 |
2384 private MethodResolutionPhase firstErroneousResolutionPhase() { |
2501 private MethodResolutionPhase firstErroneousResolutionPhase() { |
2385 MethodResolutionPhase bestSoFar = BASIC; |
2502 MethodResolutionPhase bestSoFar = BASIC; |
2386 Symbol sym = methodNotFound; |
2503 Symbol sym = methodNotFound; |
2387 List<MethodResolutionPhase> steps = methodResolutionSteps; |
2504 List<MethodResolutionPhase> steps = methodResolutionSteps; |