src/share/classes/com/sun/tools/javac/comp/Resolve.java

changeset 2193
d4cbb671de1c
parent 2117
70a301b35e71
child 2219
5bf0af735c61
equal deleted inserted replaced
2192:5ae66d372d57 2193:d4cbb671de1c
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.source.tree.MemberReferenceTree.ReferenceMode;
28 import com.sun.tools.javac.api.Formattable.LocalizedString; 29 import com.sun.tools.javac.api.Formattable.LocalizedString;
29 import com.sun.tools.javac.code.*; 30 import com.sun.tools.javac.code.*;
30 import com.sun.tools.javac.code.Symbol.*; 31 import com.sun.tools.javac.code.Symbol.*;
31 import com.sun.tools.javac.code.Type.*; 32 import com.sun.tools.javac.code.Type.*;
32 import com.sun.tools.javac.comp.Attr.ResultInfo; 33 import com.sun.tools.javac.comp.Attr.ResultInfo;
108 109
109 varNotFound = new 110 varNotFound = new
110 SymbolNotFoundError(ABSENT_VAR); 111 SymbolNotFoundError(ABSENT_VAR);
111 methodNotFound = new 112 methodNotFound = new
112 SymbolNotFoundError(ABSENT_MTH); 113 SymbolNotFoundError(ABSENT_MTH);
114 methodWithCorrectStaticnessNotFound = new
115 SymbolNotFoundError(WRONG_STATICNESS,
116 "method found has incorrect staticness");
113 typeNotFound = new 117 typeNotFound = new
114 SymbolNotFoundError(ABSENT_TYP); 118 SymbolNotFoundError(ABSENT_TYP);
115 119
116 names = Names.instance(context); 120 names = Names.instance(context);
117 log = Log.instance(context); 121 log = Log.instance(context);
142 146
143 /** error symbols, which are returned when resolution fails 147 /** error symbols, which are returned when resolution fails
144 */ 148 */
145 private final SymbolNotFoundError varNotFound; 149 private final SymbolNotFoundError varNotFound;
146 private final SymbolNotFoundError methodNotFound; 150 private final SymbolNotFoundError methodNotFound;
151 private final SymbolNotFoundError methodWithCorrectStaticnessNotFound;
147 private final SymbolNotFoundError typeNotFound; 152 private final SymbolNotFoundError typeNotFound;
148 153
149 public static Resolve instance(Context context) { 154 public static Resolve instance(Context context) {
150 Resolve instance = context.get(resolveKey); 155 Resolve instance = context.get(resolveKey);
151 if (instance == null) 156 if (instance == null)
866 public MethodCheck mostSpecificCheck(List<Type> actuals, boolean strict) { 871 public MethodCheck mostSpecificCheck(List<Type> actuals, boolean strict) {
867 return new MostSpecificCheck(strict, actuals); 872 return new MostSpecificCheck(strict, actuals);
868 } 873 }
869 }; 874 };
870 875
876 /**
877 * This class handles method reference applicability checks; since during
878 * these checks it's sometime possible to have inference variables on
879 * the actual argument types list, the method applicability check must be
880 * extended so that inference variables are 'opened' as needed.
881 */
871 class MethodReferenceCheck extends AbstractMethodCheck { 882 class MethodReferenceCheck extends AbstractMethodCheck {
872 883
873 InferenceContext pendingInferenceContext; 884 InferenceContext pendingInferenceContext;
874 885
875 MethodReferenceCheck(InferenceContext pendingInferenceContext) { 886 MethodReferenceCheck(InferenceContext pendingInferenceContext) {
2672 Type left, 2683 Type left,
2673 Type right) { 2684 Type right) {
2674 return resolveOperator(pos, optag, env, List.of(left, right)); 2685 return resolveOperator(pos, optag, env, List.of(left, right));
2675 } 2686 }
2676 2687
2688 Symbol getMemberReference(DiagnosticPosition pos,
2689 Env<AttrContext> env,
2690 JCMemberReference referenceTree,
2691 Type site,
2692 Name name) {
2693
2694 site = types.capture(site);
2695
2696 ReferenceLookupHelper lookupHelper = makeReferenceLookupHelper(
2697 referenceTree, site, name, List.<Type>nil(), null, VARARITY);
2698
2699 Env<AttrContext> newEnv = env.dup(env.tree, env.info.dup());
2700 Symbol sym = lookupMethod(newEnv, env.tree.pos(), site.tsym,
2701 nilMethodCheck, lookupHelper);
2702
2703 env.info.pendingResolutionPhase = newEnv.info.pendingResolutionPhase;
2704
2705 return sym;
2706 }
2707
2708 ReferenceLookupHelper makeReferenceLookupHelper(JCMemberReference referenceTree,
2709 Type site,
2710 Name name,
2711 List<Type> argtypes,
2712 List<Type> typeargtypes,
2713 MethodResolutionPhase maxPhase) {
2714 ReferenceLookupHelper result;
2715 if (!name.equals(names.init)) {
2716 //method reference
2717 result =
2718 new MethodReferenceLookupHelper(referenceTree, name, site, argtypes, typeargtypes, maxPhase);
2719 } else {
2720 if (site.hasTag(ARRAY)) {
2721 //array constructor reference
2722 result =
2723 new ArrayConstructorReferenceLookupHelper(referenceTree, site, argtypes, typeargtypes, maxPhase);
2724 } else {
2725 //class constructor reference
2726 result =
2727 new ConstructorReferenceLookupHelper(referenceTree, site, argtypes, typeargtypes, maxPhase);
2728 }
2729 }
2730 return result;
2731 }
2732
2733 Symbol resolveMemberReferenceByArity(Env<AttrContext> env,
2734 JCMemberReference referenceTree,
2735 Type site,
2736 Name name,
2737 List<Type> argtypes,
2738 InferenceContext inferenceContext) {
2739
2740 boolean isStaticSelector = TreeInfo.isStaticSelector(referenceTree.expr, names);
2741 site = types.capture(site);
2742
2743 ReferenceLookupHelper boundLookupHelper = makeReferenceLookupHelper(
2744 referenceTree, site, name, argtypes, null, VARARITY);
2745 //step 1 - bound lookup
2746 Env<AttrContext> boundEnv = env.dup(env.tree, env.info.dup());
2747 Symbol boundSym = lookupMethod(boundEnv, env.tree.pos(), site.tsym,
2748 arityMethodCheck, boundLookupHelper);
2749 if (isStaticSelector &&
2750 !name.equals(names.init) &&
2751 !boundSym.isStatic() &&
2752 boundSym.kind < ERRONEOUS) {
2753 boundSym = methodNotFound;
2754 }
2755
2756 //step 2 - unbound lookup
2757 Symbol unboundSym = methodNotFound;
2758 ReferenceLookupHelper unboundLookupHelper = null;
2759 Env<AttrContext> unboundEnv = env.dup(env.tree, env.info.dup());
2760 if (isStaticSelector) {
2761 unboundLookupHelper = boundLookupHelper.unboundLookup(inferenceContext);
2762 unboundSym = lookupMethod(unboundEnv, env.tree.pos(), site.tsym,
2763 arityMethodCheck, unboundLookupHelper);
2764 if (unboundSym.isStatic() &&
2765 unboundSym.kind < ERRONEOUS) {
2766 unboundSym = methodNotFound;
2767 }
2768 }
2769
2770 //merge results
2771 Symbol bestSym = choose(boundSym, unboundSym);
2772 env.info.pendingResolutionPhase = bestSym == unboundSym ?
2773 unboundEnv.info.pendingResolutionPhase :
2774 boundEnv.info.pendingResolutionPhase;
2775
2776 return bestSym;
2777 }
2778
2677 /** 2779 /**
2678 * Resolution of member references is typically done as a single 2780 * Resolution of member references is typically done as a single
2679 * overload resolution step, where the argument types A are inferred from 2781 * overload resolution step, where the argument types A are inferred from
2680 * the target functional descriptor. 2782 * the target functional descriptor.
2681 * 2783 *
2698 * This routine returns a pair (T,S), where S is the member reference symbol, 2800 * This routine returns a pair (T,S), where S is the member reference symbol,
2699 * and T is the type of the class in which S is defined. This is necessary as 2801 * and T is the type of the class in which S is defined. This is necessary as
2700 * the type T might be dynamically inferred (i.e. if constructor reference 2802 * the type T might be dynamically inferred (i.e. if constructor reference
2701 * has a raw qualifier). 2803 * has a raw qualifier).
2702 */ 2804 */
2703 Pair<Symbol, ReferenceLookupHelper> resolveMemberReference(DiagnosticPosition pos, 2805 Pair<Symbol, ReferenceLookupHelper> resolveMemberReference(Env<AttrContext> env,
2704 Env<AttrContext> env,
2705 JCMemberReference referenceTree, 2806 JCMemberReference referenceTree,
2706 Type site, 2807 Type site,
2707 Name name, List<Type> argtypes, 2808 Name name,
2809 List<Type> argtypes,
2708 List<Type> typeargtypes, 2810 List<Type> typeargtypes,
2709 boolean boxingAllowed,
2710 MethodCheck methodCheck, 2811 MethodCheck methodCheck,
2711 InferenceContext inferenceContext) { 2812 InferenceContext inferenceContext,
2712 MethodResolutionPhase maxPhase = boxingAllowed ? VARARITY : BASIC; 2813 AttrMode mode) {
2713 2814
2714 site = types.capture(site); 2815 site = types.capture(site);
2715 2816 ReferenceLookupHelper boundLookupHelper = makeReferenceLookupHelper(
2716 ReferenceLookupHelper boundLookupHelper; 2817 referenceTree, site, name, argtypes, typeargtypes, VARARITY);
2717 if (!name.equals(names.init)) {
2718 //method reference
2719 boundLookupHelper =
2720 new MethodReferenceLookupHelper(referenceTree, name, site, argtypes, typeargtypes, maxPhase);
2721 } else if (site.hasTag(ARRAY)) {
2722 //array constructor reference
2723 boundLookupHelper =
2724 new ArrayConstructorReferenceLookupHelper(referenceTree, site, argtypes, typeargtypes, maxPhase);
2725 } else {
2726 //class constructor reference
2727 boundLookupHelper =
2728 new ConstructorReferenceLookupHelper(referenceTree, site, argtypes, typeargtypes, maxPhase);
2729 }
2730 2818
2731 //step 1 - bound lookup 2819 //step 1 - bound lookup
2732 Env<AttrContext> boundEnv = env.dup(env.tree, env.info.dup()); 2820 Env<AttrContext> boundEnv = env.dup(env.tree, env.info.dup());
2733 Symbol boundSym = lookupMethod(boundEnv, env.tree.pos(), site.tsym, methodCheck, boundLookupHelper); 2821 Symbol origBoundSym;
2822 boolean staticErrorForBound = false;
2823 MethodResolutionContext boundSearchResolveContext = new MethodResolutionContext();
2824 boundSearchResolveContext.methodCheck = methodCheck;
2825 Symbol boundSym = origBoundSym = lookupMethod(boundEnv, env.tree.pos(),
2826 site.tsym, boundSearchResolveContext, boundLookupHelper);
2827 SearchResultKind boundSearchResultKind = SearchResultKind.NOT_APPLICABLE_MATCH;
2828 boolean isStaticSelector = TreeInfo.isStaticSelector(referenceTree.expr, names);
2829 boolean shouldCheckForStaticness = isStaticSelector &&
2830 referenceTree.getMode() == ReferenceMode.INVOKE;
2831 if (boundSym.kind != WRONG_MTHS && boundSym.kind != WRONG_MTH) {
2832 if (shouldCheckForStaticness) {
2833 if (!boundSym.isStatic()) {
2834 staticErrorForBound = true;
2835 if (hasAnotherApplicableMethod(
2836 boundSearchResolveContext, boundSym, true)) {
2837 boundSearchResultKind = SearchResultKind.BAD_MATCH_MORE_SPECIFIC;
2838 } else {
2839 boundSearchResultKind = SearchResultKind.BAD_MATCH;
2840 if (boundSym.kind < ERRONEOUS) {
2841 boundSym = methodWithCorrectStaticnessNotFound;
2842 }
2843 }
2844 } else if (boundSym.kind < ERRONEOUS) {
2845 boundSearchResultKind = SearchResultKind.GOOD_MATCH;
2846 }
2847 }
2848 }
2734 2849
2735 //step 2 - unbound lookup 2850 //step 2 - unbound lookup
2736 ReferenceLookupHelper unboundLookupHelper = boundLookupHelper.unboundLookup(inferenceContext); 2851 Symbol origUnboundSym = null;
2852 Symbol unboundSym = methodNotFound;
2853 ReferenceLookupHelper unboundLookupHelper = null;
2737 Env<AttrContext> unboundEnv = env.dup(env.tree, env.info.dup()); 2854 Env<AttrContext> unboundEnv = env.dup(env.tree, env.info.dup());
2738 Symbol unboundSym = lookupMethod(unboundEnv, env.tree.pos(), site.tsym, methodCheck, unboundLookupHelper); 2855 SearchResultKind unboundSearchResultKind = SearchResultKind.NOT_APPLICABLE_MATCH;
2856 boolean staticErrorForUnbound = false;
2857 if (isStaticSelector) {
2858 unboundLookupHelper = boundLookupHelper.unboundLookup(inferenceContext);
2859 MethodResolutionContext unboundSearchResolveContext =
2860 new MethodResolutionContext();
2861 unboundSearchResolveContext.methodCheck = methodCheck;
2862 unboundSym = origUnboundSym = lookupMethod(unboundEnv, env.tree.pos(),
2863 site.tsym, unboundSearchResolveContext, unboundLookupHelper);
2864
2865 if (unboundSym.kind != WRONG_MTH && unboundSym.kind != WRONG_MTHS) {
2866 if (shouldCheckForStaticness) {
2867 if (unboundSym.isStatic()) {
2868 staticErrorForUnbound = true;
2869 if (hasAnotherApplicableMethod(
2870 unboundSearchResolveContext, unboundSym, false)) {
2871 unboundSearchResultKind = SearchResultKind.BAD_MATCH_MORE_SPECIFIC;
2872 } else {
2873 unboundSearchResultKind = SearchResultKind.BAD_MATCH;
2874 if (unboundSym.kind < ERRONEOUS) {
2875 unboundSym = methodWithCorrectStaticnessNotFound;
2876 }
2877 }
2878 } else if (unboundSym.kind < ERRONEOUS) {
2879 unboundSearchResultKind = SearchResultKind.GOOD_MATCH;
2880 }
2881 }
2882 }
2883 }
2739 2884
2740 //merge results 2885 //merge results
2741 Pair<Symbol, ReferenceLookupHelper> res; 2886 Pair<Symbol, ReferenceLookupHelper> res;
2742 Symbol bestSym = choose(boundSym, unboundSym); 2887 Symbol bestSym = choose(boundSym, unboundSym);
2743 res = new Pair<Symbol, ReferenceLookupHelper>(bestSym, 2888 if (bestSym.kind < ERRONEOUS && (staticErrorForBound || staticErrorForUnbound)) {
2889 if (staticErrorForBound) {
2890 boundSym = methodWithCorrectStaticnessNotFound;
2891 }
2892 if (staticErrorForUnbound) {
2893 unboundSym = methodWithCorrectStaticnessNotFound;
2894 }
2895 bestSym = choose(boundSym, unboundSym);
2896 }
2897 if (bestSym == methodWithCorrectStaticnessNotFound && mode == AttrMode.CHECK) {
2898 Symbol symToPrint = origBoundSym;
2899 String errorFragmentToPrint = "non-static.cant.be.ref";
2900 if (staticErrorForBound && staticErrorForUnbound) {
2901 if (unboundSearchResultKind == SearchResultKind.BAD_MATCH_MORE_SPECIFIC) {
2902 symToPrint = origUnboundSym;
2903 errorFragmentToPrint = "static.method.in.unbound.lookup";
2904 }
2905 } else {
2906 if (!staticErrorForBound) {
2907 symToPrint = origUnboundSym;
2908 errorFragmentToPrint = "static.method.in.unbound.lookup";
2909 }
2910 }
2911 log.error(referenceTree.expr.pos(), "invalid.mref",
2912 Kinds.kindName(referenceTree.getMode()),
2913 diags.fragment(errorFragmentToPrint,
2914 Kinds.kindName(symToPrint), symToPrint));
2915 }
2916 res = new Pair<>(bestSym,
2744 bestSym == unboundSym ? unboundLookupHelper : boundLookupHelper); 2917 bestSym == unboundSym ? unboundLookupHelper : boundLookupHelper);
2745 env.info.pendingResolutionPhase = bestSym == unboundSym ? 2918 env.info.pendingResolutionPhase = bestSym == unboundSym ?
2746 unboundEnv.info.pendingResolutionPhase : 2919 unboundEnv.info.pendingResolutionPhase :
2747 boundEnv.info.pendingResolutionPhase; 2920 boundEnv.info.pendingResolutionPhase;
2748 2921
2749 return res; 2922 return res;
2750 } 2923 }
2924
2925 enum SearchResultKind {
2926 GOOD_MATCH, //type I
2927 BAD_MATCH_MORE_SPECIFIC, //type II
2928 BAD_MATCH, //type III
2929 NOT_APPLICABLE_MATCH //type IV
2930 }
2931
2932 boolean hasAnotherApplicableMethod(MethodResolutionContext resolutionContext,
2933 Symbol bestSoFar, boolean staticMth) {
2934 for (Candidate c : resolutionContext.candidates) {
2935 if (resolutionContext.step != c.step ||
2936 !c.isApplicable() ||
2937 c.sym == bestSoFar) {
2938 continue;
2939 } else {
2940 if (c.sym.isStatic() == staticMth) {
2941 return true;
2942 }
2943 }
2944 }
2945 return false;
2946 }
2947
2751 //where 2948 //where
2752 private Symbol choose(Symbol s1, Symbol s2) { 2949 private Symbol choose(Symbol boundSym, Symbol unboundSym) {
2753 if (lookupSuccess(s1) && lookupSuccess(s2)) { 2950 if (lookupSuccess(boundSym) && lookupSuccess(unboundSym)) {
2754 return ambiguityError(s1, s2); 2951 return ambiguityError(boundSym, unboundSym);
2755 } else if (lookupSuccess(s1) || 2952 } else if (lookupSuccess(boundSym) ||
2756 (canIgnore(s2) && !canIgnore(s1))) { 2953 (canIgnore(unboundSym) && !canIgnore(boundSym))) {
2757 return s1; 2954 return boundSym;
2758 } else if (lookupSuccess(s2) || 2955 } else if (lookupSuccess(unboundSym) ||
2759 (canIgnore(s1) && !canIgnore(s2))) { 2956 (canIgnore(boundSym) && !canIgnore(unboundSym))) {
2760 return s2; 2957 return unboundSym;
2761 } else { 2958 } else {
2762 return s1; 2959 return boundSym;
2763 } 2960 }
2764 } 2961 }
2765 2962
2766 private boolean lookupSuccess(Symbol s) { 2963 private boolean lookupSuccess(Symbol s) {
2767 return s.kind == MTH || s.kind == AMBIGUOUS; 2964 return s.kind == MTH || s.kind == AMBIGUOUS;
2778 .matches(errSym.errCandidate().snd); 2975 .matches(errSym.errCandidate().snd);
2779 case WRONG_MTHS: 2976 case WRONG_MTHS:
2780 InapplicableSymbolsError errSyms = 2977 InapplicableSymbolsError errSyms =
2781 (InapplicableSymbolsError)s; 2978 (InapplicableSymbolsError)s;
2782 return errSyms.filterCandidates(errSyms.mapCandidates()).isEmpty(); 2979 return errSyms.filterCandidates(errSyms.mapCandidates()).isEmpty();
2980 case WRONG_STATICNESS:
2981 return false;
2783 default: 2982 default:
2784 return false; 2983 return false;
2785 } 2984 }
2786 } 2985 }
2787 2986
2892 3091
2893 ReferenceLookupHelper(JCMemberReference referenceTree, Name name, Type site, 3092 ReferenceLookupHelper(JCMemberReference referenceTree, Name name, Type site,
2894 List<Type> argtypes, List<Type> typeargtypes, MethodResolutionPhase maxPhase) { 3093 List<Type> argtypes, List<Type> typeargtypes, MethodResolutionPhase maxPhase) {
2895 super(name, site, argtypes, typeargtypes, maxPhase); 3094 super(name, site, argtypes, typeargtypes, maxPhase);
2896 this.referenceTree = referenceTree; 3095 this.referenceTree = referenceTree;
2897
2898 } 3096 }
2899 3097
2900 /** 3098 /**
2901 * Returns an unbound version of this lookup helper. By default, this 3099 * Returns an unbound version of this lookup helper. By default, this
2902 * method returns an dummy lookup helper. 3100 * method returns an dummy lookup helper.
3319 return debugName; 3517 return debugName;
3320 } 3518 }
3321 3519
3322 @Override 3520 @Override
3323 public boolean exists() { 3521 public boolean exists() {
3522 return false;
3523 }
3524
3525 @Override
3526 public boolean isStatic() {
3324 return false; 3527 return false;
3325 } 3528 }
3326 3529
3327 /** 3530 /**
3328 * Create an external representation for this erroneous symbol to be 3531 * Create an external representation for this erroneous symbol to be
3396 * given name does not exists in a given site. 3599 * given name does not exists in a given site.
3397 */ 3600 */
3398 class SymbolNotFoundError extends ResolveError { 3601 class SymbolNotFoundError extends ResolveError {
3399 3602
3400 SymbolNotFoundError(int kind) { 3603 SymbolNotFoundError(int kind) {
3401 super(kind, "symbol not found error"); 3604 this(kind, "symbol not found error");
3605 }
3606
3607 SymbolNotFoundError(int kind, String debugName) {
3608 super(kind, debugName);
3402 } 3609 }
3403 3610
3404 @Override 3611 @Override
3405 JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind, 3612 JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind,
3406 DiagnosticPosition pos, 3613 DiagnosticPosition pos,
3434 "doesnt.exist", location); 3641 "doesnt.exist", location);
3435 } 3642 }
3436 hasLocation = !location.name.equals(names._this) && 3643 hasLocation = !location.name.equals(names._this) &&
3437 !location.name.equals(names._super); 3644 !location.name.equals(names._super);
3438 } 3645 }
3439 boolean isConstructor = kind == ABSENT_MTH && name == names.init; 3646 boolean isConstructor = (kind == ABSENT_MTH || kind == WRONG_STATICNESS) &&
3647 name == names.init;
3440 KindName kindname = isConstructor ? KindName.CONSTRUCTOR : absentKind(kind); 3648 KindName kindname = isConstructor ? KindName.CONSTRUCTOR : absentKind(kind);
3441 Name idname = isConstructor ? site.tsym.name : name; 3649 Name idname = isConstructor ? site.tsym.name : name;
3442 String errKey = getErrorKey(kindname, typeargtypes.nonEmpty(), hasLocation); 3650 String errKey = getErrorKey(kindname, typeargtypes.nonEmpty(), hasLocation);
3443 if (hasLocation) { 3651 if (hasLocation) {
3444 return diags.create(dkind, log.currentSource(), pos, 3652 return diags.create(dkind, log.currentSource(), pos,

mercurial