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; |